use fuel_types::{
bytes::WORD_SIZE,
Address,
AssetId,
Bytes32,
ChainId,
};
pub mod gas;
pub use gas::{
DependentCost,
GasCostNotDefined,
GasCosts,
GasCostsValues,
};
use crate::consts::BALANCE_ENTRY_SIZE;
#[cfg(feature = "test-helpers")]
const MAX_GAS: u64 = 100_000_000;
#[cfg(feature = "test-helpers")]
const MAX_SIZE: u64 = 110 * 1024;
#[derive(Debug, derive_more::Display)]
#[display(fmt = "setting block transaction size limit is not supported")]
pub struct SettingBlockTransactionSizeLimitNotSupported;
#[cfg(feature = "std")]
impl std::error::Error for SettingBlockTransactionSizeLimitNotSupported {}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub enum ConsensusParameters {
V1(ConsensusParametersV1),
V2(ConsensusParametersV2),
}
#[cfg(feature = "test-helpers")]
impl Default for ConsensusParameters {
fn default() -> Self {
Self::standard()
}
}
impl ConsensusParameters {
#[cfg(feature = "test-helpers")]
pub fn standard() -> Self {
ConsensusParametersV2::standard().into()
}
#[cfg(feature = "test-helpers")]
pub fn standard_with_id(chain_id: ChainId) -> Self {
ConsensusParametersV2::standard_with_id(chain_id).into()
}
pub const fn new(
tx_params: TxParameters,
predicate_params: PredicateParameters,
script_params: ScriptParameters,
contract_params: ContractParameters,
fee_params: FeeParameters,
chain_id: ChainId,
gas_costs: GasCosts,
base_asset_id: AssetId,
block_gas_limit: u64,
block_transaction_size_limit: u64,
privileged_address: Address,
) -> Self {
Self::V2(ConsensusParametersV2 {
tx_params,
predicate_params,
script_params,
contract_params,
fee_params,
chain_id,
gas_costs,
base_asset_id,
block_gas_limit,
block_transaction_size_limit,
privileged_address,
})
}
pub const fn tx_params(&self) -> &TxParameters {
match self {
Self::V1(params) => ¶ms.tx_params,
Self::V2(params) => ¶ms.tx_params,
}
}
pub const fn predicate_params(&self) -> &PredicateParameters {
match self {
Self::V1(params) => ¶ms.predicate_params,
Self::V2(params) => ¶ms.predicate_params,
}
}
pub const fn script_params(&self) -> &ScriptParameters {
match self {
Self::V1(params) => ¶ms.script_params,
Self::V2(params) => ¶ms.script_params,
}
}
pub const fn contract_params(&self) -> &ContractParameters {
match self {
Self::V1(params) => ¶ms.contract_params,
Self::V2(params) => ¶ms.contract_params,
}
}
pub const fn fee_params(&self) -> &FeeParameters {
match self {
Self::V1(params) => ¶ms.fee_params,
Self::V2(params) => ¶ms.fee_params,
}
}
pub const fn chain_id(&self) -> ChainId {
match self {
Self::V1(params) => params.chain_id,
Self::V2(params) => params.chain_id,
}
}
pub const fn gas_costs(&self) -> &GasCosts {
match self {
Self::V1(params) => ¶ms.gas_costs,
Self::V2(params) => ¶ms.gas_costs,
}
}
pub const fn base_asset_id(&self) -> &AssetId {
match self {
Self::V1(params) => ¶ms.base_asset_id,
Self::V2(params) => ¶ms.base_asset_id,
}
}
pub const fn block_gas_limit(&self) -> u64 {
match self {
Self::V1(params) => params.block_gas_limit,
Self::V2(params) => params.block_gas_limit,
}
}
pub fn block_transaction_size_limit(&self) -> u64 {
match self {
Self::V1(_) => {
u64::MAX
}
Self::V2(params) => params.block_transaction_size_limit,
}
}
pub const fn privileged_address(&self) -> &Address {
match self {
Self::V1(params) => ¶ms.privileged_address,
Self::V2(params) => ¶ms.privileged_address,
}
}
}
impl ConsensusParameters {
pub fn set_tx_params(&mut self, tx_params: TxParameters) {
match self {
Self::V1(params) => params.tx_params = tx_params,
Self::V2(params) => params.tx_params = tx_params,
}
}
pub fn set_predicate_params(&mut self, predicate_params: PredicateParameters) {
match self {
Self::V1(params) => params.predicate_params = predicate_params,
Self::V2(params) => params.predicate_params = predicate_params,
}
}
pub fn set_script_params(&mut self, script_params: ScriptParameters) {
match self {
Self::V1(params) => params.script_params = script_params,
Self::V2(params) => params.script_params = script_params,
}
}
pub fn set_contract_params(&mut self, contract_params: ContractParameters) {
match self {
Self::V1(params) => params.contract_params = contract_params,
Self::V2(params) => params.contract_params = contract_params,
}
}
pub fn set_fee_params(&mut self, fee_params: FeeParameters) {
match self {
Self::V1(params) => params.fee_params = fee_params,
Self::V2(params) => params.fee_params = fee_params,
}
}
pub fn set_chain_id(&mut self, chain_id: ChainId) {
match self {
Self::V1(params) => params.chain_id = chain_id,
Self::V2(params) => params.chain_id = chain_id,
}
}
pub fn set_gas_costs(&mut self, gas_costs: GasCosts) {
match self {
Self::V1(params) => params.gas_costs = gas_costs,
Self::V2(params) => params.gas_costs = gas_costs,
}
}
pub fn set_base_asset_id(&mut self, base_asset_id: AssetId) {
match self {
Self::V1(params) => params.base_asset_id = base_asset_id,
Self::V2(params) => params.base_asset_id = base_asset_id,
}
}
pub fn set_block_gas_limit(&mut self, block_gas_limit: u64) {
match self {
Self::V1(params) => params.block_gas_limit = block_gas_limit,
Self::V2(params) => params.block_gas_limit = block_gas_limit,
}
}
pub fn set_block_transaction_size_limit(
&mut self,
block_transaction_size_limit: u64,
) -> Result<(), SettingBlockTransactionSizeLimitNotSupported> {
match self {
Self::V1(_) => Err(SettingBlockTransactionSizeLimitNotSupported),
Self::V2(params) => {
params.block_transaction_size_limit = block_transaction_size_limit;
Ok(())
}
}
}
pub fn set_privileged_address(&mut self, privileged_address: Address) {
match self {
Self::V1(params) => params.privileged_address = privileged_address,
Self::V2(params) => params.privileged_address = privileged_address,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct ConsensusParametersV1 {
pub tx_params: TxParameters,
pub predicate_params: PredicateParameters,
pub script_params: ScriptParameters,
pub contract_params: ContractParameters,
pub fee_params: FeeParameters,
pub chain_id: ChainId,
pub gas_costs: GasCosts,
pub base_asset_id: AssetId,
pub block_gas_limit: u64,
pub privileged_address: Address,
}
#[cfg(feature = "test-helpers")]
impl ConsensusParametersV1 {
pub fn standard() -> Self {
Self::standard_with_id(ChainId::default())
}
pub fn standard_with_id(chain_id: ChainId) -> Self {
Self {
tx_params: TxParameters::DEFAULT,
predicate_params: PredicateParameters::DEFAULT,
script_params: ScriptParameters::DEFAULT,
contract_params: ContractParameters::DEFAULT,
fee_params: FeeParameters::DEFAULT,
chain_id,
gas_costs: GasCosts::default(),
base_asset_id: Default::default(),
block_gas_limit: TxParameters::DEFAULT.max_gas_per_tx(),
privileged_address: Default::default(),
}
}
}
#[cfg(feature = "test-helpers")]
impl Default for ConsensusParametersV1 {
fn default() -> Self {
Self::standard()
}
}
impl From<ConsensusParametersV1> for ConsensusParameters {
fn from(params: ConsensusParametersV1) -> Self {
Self::V1(params)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct ConsensusParametersV2 {
pub tx_params: TxParameters,
pub predicate_params: PredicateParameters,
pub script_params: ScriptParameters,
pub contract_params: ContractParameters,
pub fee_params: FeeParameters,
pub chain_id: ChainId,
pub gas_costs: GasCosts,
pub base_asset_id: AssetId,
pub block_gas_limit: u64,
pub block_transaction_size_limit: u64,
pub privileged_address: Address,
}
#[cfg(feature = "test-helpers")]
impl ConsensusParametersV2 {
const DEFAULT_BLOCK_TRANSACTION_SIZE_LIMIT: u64 = 126 * 1024;
pub fn standard() -> Self {
Self::standard_with_id(ChainId::default())
}
pub fn standard_with_id(chain_id: ChainId) -> Self {
Self {
tx_params: TxParameters::DEFAULT,
predicate_params: PredicateParameters::DEFAULT,
script_params: ScriptParameters::DEFAULT,
contract_params: ContractParameters::DEFAULT,
fee_params: FeeParameters::DEFAULT,
chain_id,
gas_costs: GasCosts::default(),
base_asset_id: Default::default(),
block_gas_limit: TxParameters::DEFAULT.max_gas_per_tx(),
block_transaction_size_limit: Self::DEFAULT_BLOCK_TRANSACTION_SIZE_LIMIT,
privileged_address: Default::default(),
}
}
}
#[cfg(feature = "test-helpers")]
impl Default for ConsensusParametersV2 {
fn default() -> Self {
Self::standard()
}
}
impl From<ConsensusParametersV2> for ConsensusParameters {
fn from(params: ConsensusParametersV2) -> Self {
Self::V2(params)
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub enum FeeParameters {
V1(FeeParametersV1),
}
impl FeeParameters {
#[cfg(feature = "test-helpers")]
pub const DEFAULT: Self = Self::V1(FeeParametersV1::DEFAULT);
pub const fn with_gas_price_factor(self, gas_price_factor: u64) -> Self {
match self {
Self::V1(mut params) => {
params.gas_price_factor = gas_price_factor;
Self::V1(params)
}
}
}
pub const fn with_gas_per_byte(self, gas_per_byte: u64) -> Self {
match self {
Self::V1(mut params) => {
params.gas_per_byte = gas_per_byte;
Self::V1(params)
}
}
}
}
impl FeeParameters {
pub const fn gas_price_factor(&self) -> u64 {
match self {
Self::V1(params) => params.gas_price_factor,
}
}
pub const fn gas_per_byte(&self) -> u64 {
match self {
Self::V1(params) => params.gas_per_byte,
}
}
}
#[cfg(feature = "test-helpers")]
impl Default for FeeParameters {
fn default() -> Self {
Self::DEFAULT
}
}
impl From<FeeParametersV1> for FeeParameters {
fn from(params: FeeParametersV1) -> Self {
Self::V1(params)
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct FeeParametersV1 {
pub gas_price_factor: u64,
pub gas_per_byte: u64,
}
#[cfg(feature = "test-helpers")]
impl FeeParametersV1 {
pub const DEFAULT: Self = FeeParametersV1 {
gas_price_factor: 1_000_000_000,
gas_per_byte: 4,
};
}
#[cfg(feature = "test-helpers")]
impl Default for FeeParametersV1 {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub enum PredicateParameters {
V1(PredicateParametersV1),
}
impl PredicateParameters {
#[cfg(feature = "test-helpers")]
pub const DEFAULT: Self = Self::V1(PredicateParametersV1::DEFAULT);
pub const fn with_max_predicate_length(self, max_predicate_length: u64) -> Self {
match self {
Self::V1(mut params) => {
params.max_predicate_length = max_predicate_length;
Self::V1(params)
}
}
}
pub const fn with_max_predicate_data_length(
self,
max_predicate_data_length: u64,
) -> Self {
match self {
Self::V1(mut params) => {
params.max_predicate_data_length = max_predicate_data_length;
Self::V1(params)
}
}
}
pub const fn with_max_message_data_length(
self,
max_message_data_length: u64,
) -> Self {
match self {
Self::V1(mut params) => {
params.max_message_data_length = max_message_data_length;
Self::V1(params)
}
}
}
pub const fn with_max_gas_per_predicate(self, max_gas_per_predicate: u64) -> Self {
match self {
Self::V1(mut params) => {
params.max_gas_per_predicate = max_gas_per_predicate;
Self::V1(params)
}
}
}
}
impl PredicateParameters {
pub const fn max_predicate_length(&self) -> u64 {
match self {
Self::V1(params) => params.max_predicate_length,
}
}
pub const fn max_predicate_data_length(&self) -> u64 {
match self {
Self::V1(params) => params.max_predicate_data_length,
}
}
pub const fn max_message_data_length(&self) -> u64 {
match self {
Self::V1(params) => params.max_message_data_length,
}
}
pub const fn max_gas_per_predicate(&self) -> u64 {
match self {
Self::V1(params) => params.max_gas_per_predicate,
}
}
}
impl From<PredicateParametersV1> for PredicateParameters {
fn from(params: PredicateParametersV1) -> Self {
Self::V1(params)
}
}
#[cfg(feature = "test-helpers")]
impl Default for PredicateParameters {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct PredicateParametersV1 {
pub max_predicate_length: u64,
pub max_predicate_data_length: u64,
pub max_message_data_length: u64,
pub max_gas_per_predicate: u64,
}
#[cfg(feature = "test-helpers")]
impl PredicateParametersV1 {
pub const DEFAULT: Self = Self {
max_predicate_length: 1024 * 1024,
max_predicate_data_length: 1024 * 1024,
max_message_data_length: 1024 * 1024,
max_gas_per_predicate: MAX_GAS,
};
}
#[cfg(feature = "test-helpers")]
impl Default for PredicateParametersV1 {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub enum TxParameters {
V1(TxParametersV1),
}
impl TxParameters {
#[cfg(feature = "test-helpers")]
pub const DEFAULT: Self = Self::V1(TxParametersV1::DEFAULT);
pub const fn tx_offset(&self) -> usize {
let Some(balances_size) =
(self.max_inputs() as usize).checked_mul(BALANCE_ENTRY_SIZE)
else {
panic!(
"Consensus parameters shouldn't allow max_inputs to cause overflow here"
);
};
balances_size.saturating_add(
Bytes32::LEN + WORD_SIZE + AssetId::LEN, )
}
pub const fn with_max_inputs(self, max_inputs: u16) -> Self {
match self {
Self::V1(mut params) => {
params.max_inputs = max_inputs;
Self::V1(params)
}
}
}
pub const fn with_max_outputs(self, max_outputs: u16) -> Self {
match self {
Self::V1(mut params) => {
params.max_outputs = max_outputs;
Self::V1(params)
}
}
}
pub const fn with_max_witnesses(self, max_witnesses: u32) -> Self {
match self {
Self::V1(mut params) => {
params.max_witnesses = max_witnesses;
Self::V1(params)
}
}
}
pub const fn with_max_gas_per_tx(self, max_gas_per_tx: u64) -> Self {
match self {
Self::V1(mut params) => {
params.max_gas_per_tx = max_gas_per_tx;
Self::V1(params)
}
}
}
pub const fn with_max_size(self, max_size: u64) -> Self {
match self {
Self::V1(mut params) => {
params.max_size = max_size;
Self::V1(params)
}
}
}
pub const fn with_max_bytecode_subsections(
self,
max_bytecode_subsections: u16,
) -> Self {
match self {
Self::V1(mut params) => {
params.max_bytecode_subsections = max_bytecode_subsections;
Self::V1(params)
}
}
}
}
impl TxParameters {
pub const fn max_inputs(&self) -> u16 {
match self {
Self::V1(params) => params.max_inputs,
}
}
pub const fn max_outputs(&self) -> u16 {
match self {
Self::V1(params) => params.max_outputs,
}
}
pub const fn max_witnesses(&self) -> u32 {
match self {
Self::V1(params) => params.max_witnesses,
}
}
pub const fn max_gas_per_tx(&self) -> u64 {
match self {
Self::V1(params) => params.max_gas_per_tx,
}
}
pub const fn max_size(&self) -> u64 {
match self {
Self::V1(params) => params.max_size,
}
}
pub const fn max_bytecode_subsections(&self) -> u16 {
match self {
Self::V1(params) => params.max_bytecode_subsections,
}
}
}
#[cfg(feature = "test-helpers")]
impl Default for TxParameters {
fn default() -> Self {
Self::DEFAULT
}
}
#[cfg(feature = "test-helpers")]
impl TxParameters {
pub fn set_max_size(&mut self, max_size: u64) {
match self {
Self::V1(params) => params.max_size = max_size,
}
}
}
impl From<TxParametersV1> for TxParameters {
fn from(params: TxParametersV1) -> Self {
Self::V1(params)
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct TxParametersV1 {
pub max_inputs: u16,
pub max_outputs: u16,
pub max_witnesses: u32,
pub max_gas_per_tx: u64,
pub max_size: u64,
pub max_bytecode_subsections: u16,
}
#[cfg(feature = "test-helpers")]
impl TxParametersV1 {
pub const DEFAULT: Self = Self {
max_inputs: 255,
max_outputs: 255,
max_witnesses: 255,
max_gas_per_tx: MAX_GAS,
max_size: MAX_SIZE,
max_bytecode_subsections: 255,
};
}
#[cfg(feature = "test-helpers")]
impl Default for TxParametersV1 {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub enum ScriptParameters {
V1(ScriptParametersV1),
}
impl ScriptParameters {
#[cfg(feature = "test-helpers")]
pub const DEFAULT: Self = Self::V1(ScriptParametersV1::DEFAULT);
pub const fn with_max_script_length(self, max_script_length: u64) -> Self {
match self {
Self::V1(mut params) => {
params.max_script_length = max_script_length;
Self::V1(params)
}
}
}
pub const fn with_max_script_data_length(self, max_script_data_length: u64) -> Self {
match self {
Self::V1(mut params) => {
params.max_script_data_length = max_script_data_length;
Self::V1(params)
}
}
}
}
impl ScriptParameters {
pub const fn max_script_length(&self) -> u64 {
match self {
Self::V1(params) => params.max_script_length,
}
}
pub const fn max_script_data_length(&self) -> u64 {
match self {
Self::V1(params) => params.max_script_data_length,
}
}
}
impl From<ScriptParametersV1> for ScriptParameters {
fn from(params: ScriptParametersV1) -> Self {
Self::V1(params)
}
}
#[cfg(feature = "test-helpers")]
impl Default for ScriptParameters {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct ScriptParametersV1 {
pub max_script_length: u64,
pub max_script_data_length: u64,
}
#[cfg(feature = "test-helpers")]
impl ScriptParametersV1 {
pub const DEFAULT: Self = Self {
max_script_length: 1024 * 1024,
max_script_data_length: 1024 * 1024,
};
}
#[cfg(feature = "test-helpers")]
impl Default for ScriptParametersV1 {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub enum ContractParameters {
V1(ContractParametersV1),
}
impl ContractParameters {
#[cfg(feature = "test-helpers")]
pub const DEFAULT: Self = Self::V1(ContractParametersV1::DEFAULT);
pub const fn with_contract_max_size(self, contract_max_size: u64) -> Self {
match self {
Self::V1(mut params) => {
params.contract_max_size = contract_max_size;
Self::V1(params)
}
}
}
pub const fn with_max_storage_slots(self, max_storage_slots: u64) -> Self {
match self {
Self::V1(mut params) => {
params.max_storage_slots = max_storage_slots;
Self::V1(params)
}
}
}
}
impl ContractParameters {
pub const fn contract_max_size(&self) -> u64 {
match self {
Self::V1(params) => params.contract_max_size,
}
}
pub const fn max_storage_slots(&self) -> u64 {
match self {
Self::V1(params) => params.max_storage_slots,
}
}
}
impl From<ContractParametersV1> for ContractParameters {
fn from(params: ContractParametersV1) -> Self {
Self::V1(params)
}
}
#[cfg(feature = "test-helpers")]
impl Default for ContractParameters {
fn default() -> Self {
Self::DEFAULT
}
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct ContractParametersV1 {
pub contract_max_size: u64,
pub max_storage_slots: u64,
}
#[cfg(feature = "test-helpers")]
impl ContractParametersV1 {
pub const DEFAULT: Self = Self {
contract_max_size: 100 * 1024,
max_storage_slots: 255,
};
}
#[cfg(feature = "test-helpers")]
impl Default for ContractParametersV1 {
fn default() -> Self {
Self::DEFAULT
}
}
#[cfg(feature = "typescript")]
pub mod typescript {
use wasm_bindgen::prelude::*;
use super::{
PredicateParameters as PredicateParametersRust,
PredicateParametersV1,
};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "typescript", wasm_bindgen::prelude::wasm_bindgen)]
pub struct PredicateParameters(alloc::boxed::Box<PredicateParametersRust>);
impl AsRef<PredicateParametersRust> for PredicateParameters {
fn as_ref(&self) -> &PredicateParametersRust {
&self.0
}
}
#[wasm_bindgen]
impl PredicateParameters {
#[wasm_bindgen(constructor)]
pub fn typescript_new(
max_predicate_length: u64,
max_predicate_data_length: u64,
max_message_data_length: u64,
max_gas_per_predicate: u64,
) -> Self {
let params: PredicateParametersRust = PredicateParametersV1 {
max_predicate_length,
max_predicate_data_length,
max_message_data_length,
max_gas_per_predicate,
}
.into();
PredicateParameters(params.into())
}
}
}
#[cfg(test)]
mod tests {
use crate::consensus_parameters::{
ConsensusParametersV2,
SettingBlockTransactionSizeLimitNotSupported,
};
use super::{
ConsensusParameters,
ConsensusParametersV1,
};
#[test]
fn error_when_setting_block_size_limit_in_consensus_parameters_v1() {
let mut consensus_params: ConsensusParameters =
ConsensusParametersV1::default().into();
let result = consensus_params.set_block_transaction_size_limit(0);
assert!(matches!(
result,
Err(SettingBlockTransactionSizeLimitNotSupported)
))
}
#[test]
fn ok_when_setting_block_size_limit_in_consensus_parameters_v2() {
let mut consensus_params: ConsensusParameters =
ConsensusParametersV2::default().into();
let result = consensus_params.set_block_transaction_size_limit(0);
assert!(matches!(result, Ok(())))
}
}