casper_types/chainspec/
transaction_config.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
mod deploy_config;
mod runtime_config;
mod transaction_v1_config;

#[cfg(feature = "datasize")]
use datasize::DataSize;
#[cfg(any(feature = "testing", test))]
use rand::Rng;
use runtime_config::RuntimeConfig;
use serde::{Deserialize, Serialize};

#[cfg(any(feature = "testing", test))]
use crate::testing::TestRng;
use crate::{
    bytesrepr::{self, FromBytes, ToBytes},
    TimeDiff,
};

pub use deploy_config::DeployConfig;
#[cfg(any(feature = "testing", test))]
pub use deploy_config::DEFAULT_MAX_PAYMENT_MOTES;
#[cfg(any(feature = "testing", test))]
pub use transaction_v1_config::DEFAULT_LARGE_TRANSACTION_GAS_LIMIT;
pub use transaction_v1_config::{TransactionLimitsDefinition, TransactionV1Config};

/// The default minimum number of motes that can be transferred.
pub const DEFAULT_MIN_TRANSFER_MOTES: u64 = 2_500_000_000;

/// Configuration values associated with Transactions.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
#[cfg_attr(feature = "datasize", derive(DataSize))]
// Disallow unknown fields to ensure config files and command-line overrides contain valid keys.
#[serde(deny_unknown_fields)]
pub struct TransactionConfig {
    /// Maximum time to live any transaction can specify.
    pub max_ttl: TimeDiff,
    /// Maximum number of approvals (signatures) allowed in a block across all transactions.
    pub block_max_approval_count: u32,
    /// Maximum possible size in bytes of a block.
    pub max_block_size: u32,
    /// Maximum sum of payment across all transactions included in a block.
    pub block_gas_limit: u64,
    /// Minimum token amount for a native transfer deploy or transaction (a transfer deploy or
    /// transaction received with an transfer amount less than this will be rejected upon receipt).
    pub native_transfer_minimum_motes: u64,
    /// Maximum value to which `transaction_acceptor.timestamp_leeway` can be set in the
    /// config.toml file.
    pub max_timestamp_leeway: TimeDiff,
    /// Configuration values specific to Deploy transactions.
    #[serde(rename = "deploy")]
    pub deploy_config: DeployConfig,
    /// Configuration of the transaction runtime.
    /// Configuration values specific to V1 transactions.
    #[serde(rename = "v1")]
    pub transaction_v1_config: TransactionV1Config,
    /// Configuration values specific to the runtime.
    ///
    /// This is where we specify which runtimes are available.
    #[serde(rename = "enabled_runtime")]
    pub runtime_config: RuntimeConfig,
}

#[cfg(any(all(feature = "std", feature = "testing"), test))]
impl TransactionConfig {
    /// Generates a random instance using a `TestRng`.
    pub fn random(rng: &mut TestRng) -> Self {
        let max_ttl = TimeDiff::from_seconds(rng.gen_range(60..3_600));
        let block_max_approval_count = rng.gen();
        let max_block_size = rng.gen_range(1_000_000..1_000_000_000);
        let block_gas_limit = rng.gen_range(100_000_000_000..1_000_000_000_000_000);
        let native_transfer_minimum_motes =
            rng.gen_range(DEFAULT_MIN_TRANSFER_MOTES..1_000_000_000_000_000);
        let max_timestamp_leeway = TimeDiff::from_seconds(rng.gen_range(0..6));
        let deploy_config = DeployConfig::random(rng);
        let transaction_v1_config: TransactionV1Config = TransactionV1Config::random(rng);
        let runtime_config = RuntimeConfig::random(rng);

        TransactionConfig {
            max_ttl,
            block_max_approval_count,
            max_block_size,
            block_gas_limit,
            native_transfer_minimum_motes,
            max_timestamp_leeway,
            deploy_config,
            transaction_v1_config,
            runtime_config,
        }
    }
}

impl Default for TransactionConfig {
    fn default() -> Self {
        let eighteen_hours = TimeDiff::from_seconds(18 * 60 * 60);
        TransactionConfig {
            max_ttl: eighteen_hours,
            block_max_approval_count: 2600,
            max_block_size: 10_485_760,
            block_gas_limit: 10_000_000_000_000,
            native_transfer_minimum_motes: DEFAULT_MIN_TRANSFER_MOTES,
            max_timestamp_leeway: TimeDiff::from_seconds(5),
            deploy_config: DeployConfig::default(),
            runtime_config: RuntimeConfig {
                vm_casper_v1: true,
                vm_casper_v2: false,
            },
            transaction_v1_config: TransactionV1Config::default(),
        }
    }
}

impl ToBytes for TransactionConfig {
    fn write_bytes(&self, writer: &mut Vec<u8>) -> Result<(), bytesrepr::Error> {
        self.max_ttl.write_bytes(writer)?;
        self.block_max_approval_count.write_bytes(writer)?;
        self.max_block_size.write_bytes(writer)?;
        self.block_gas_limit.write_bytes(writer)?;
        self.native_transfer_minimum_motes.write_bytes(writer)?;
        self.max_timestamp_leeway.write_bytes(writer)?;
        self.deploy_config.write_bytes(writer)?;
        self.runtime_config.write_bytes(writer)?;
        self.transaction_v1_config.write_bytes(writer)
    }

    fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
        let mut buffer = bytesrepr::allocate_buffer(self)?;
        self.write_bytes(&mut buffer)?;
        Ok(buffer)
    }

    fn serialized_length(&self) -> usize {
        self.max_ttl.serialized_length()
            + self.block_max_approval_count.serialized_length()
            + self.max_block_size.serialized_length()
            + self.block_gas_limit.serialized_length()
            + self.native_transfer_minimum_motes.serialized_length()
            + self.max_timestamp_leeway.serialized_length()
            + self.deploy_config.serialized_length()
            + self.runtime_config.serialized_length()
            + self.transaction_v1_config.serialized_length()
    }
}

impl FromBytes for TransactionConfig {
    fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
        let (max_ttl, remainder) = TimeDiff::from_bytes(bytes)?;
        let (block_max_approval_count, remainder) = u32::from_bytes(remainder)?;
        let (max_block_size, remainder) = u32::from_bytes(remainder)?;
        let (block_gas_limit, remainder) = u64::from_bytes(remainder)?;
        let (native_transfer_minimum_motes, remainder) = u64::from_bytes(remainder)?;
        let (max_timestamp_leeway, remainder) = TimeDiff::from_bytes(remainder)?;
        let (deploy_config, remainder) = DeployConfig::from_bytes(remainder)?;
        let (runtime_config, remainder) = RuntimeConfig::from_bytes(remainder)?;
        let (transaction_v1_config, remainder) = TransactionV1Config::from_bytes(remainder)?;

        let config = TransactionConfig {
            max_ttl,
            block_max_approval_count,
            max_block_size,
            block_gas_limit,
            native_transfer_minimum_motes,
            max_timestamp_leeway,
            deploy_config,
            runtime_config,
            transaction_v1_config,
        };
        Ok((config, remainder))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn bytesrepr_roundtrip() {
        let mut rng = TestRng::new();
        let config = TransactionConfig::random(&mut rng);
        bytesrepr::test_serialization_roundtrip(&config);
    }
}