use vapory_types::{Address, U256, H256};
use bytes::Bytes;
use vapjson;
use crate::BlockNumber;
use crate::engines::DEFAULT_BLOCKHASH_CONTRACT;
const MAX_TRANSACTION_SIZE: usize = 300 * 1024;
#[derive(Debug, PartialEq, Default)]
#[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))]
pub struct CommonParams {
pub account_start_nonce: U256,
pub maximum_extra_data_size: usize,
pub network_id: u64,
pub chain_id: u64,
pub subprotocol_name: String,
pub min_gas_limit: U256,
pub fork_block: Option<(BlockNumber, H256)>,
pub eip150_transition: BlockNumber,
pub eip160_transition: BlockNumber,
pub eip161abc_transition: BlockNumber,
pub eip161d_transition: BlockNumber,
pub eip98_transition: BlockNumber,
pub eip658_transition: BlockNumber,
pub eip155_transition: BlockNumber,
pub validate_receipts_transition: BlockNumber,
pub validate_chain_id_transition: BlockNumber,
pub eip140_transition: BlockNumber,
pub eip210_transition: BlockNumber,
pub eip210_contract_address: Address,
pub eip210_contract_code: Bytes,
pub eip210_contract_gas: U256,
pub eip211_transition: BlockNumber,
pub eip214_transition: BlockNumber,
pub eip145_transition: BlockNumber,
pub eip1052_transition: BlockNumber,
pub eip1283_transition: BlockNumber,
pub eip1283_disable_transition: BlockNumber,
pub eip1283_reenable_transition: BlockNumber,
pub eip1014_transition: BlockNumber,
pub eip1706_transition: BlockNumber,
pub eip1344_transition: BlockNumber,
pub eip1884_transition: BlockNumber,
pub eip2028_transition: BlockNumber,
pub eip2200_advance_transition: BlockNumber,
pub dust_protection_transition: BlockNumber,
pub nonce_cap_increment: u64,
pub remove_dust_contracts: bool,
pub wasm_activation_transition: BlockNumber,
pub wasm_version: Option<U256>,
pub kip4_transition: BlockNumber,
pub kip6_transition: BlockNumber,
pub gas_limit_bound_divisor: U256,
pub registrar: Option<Address>,
pub node_permission_contract: Option<Address>,
pub max_code_size: u64,
pub max_code_size_transition: BlockNumber,
pub transaction_permission_contract: Option<Address>,
pub transaction_permission_contract_transition: BlockNumber,
pub max_transaction_size: usize,
}
impl CommonParams {
pub fn schedule(&self, block_number: u64) -> tetsy_vm::Schedule {
if block_number < self.eip150_transition {
tetsy_vm::Schedule::new_homestead()
} else {
let max_code_size = self.max_code_size(block_number);
let mut schedule = tetsy_vm::Schedule::new_post_eip150(
max_code_size as _,
block_number >= self.eip160_transition,
block_number >= self.eip161abc_transition,
block_number >= self.eip161d_transition
);
self.update_schedule(block_number, &mut schedule);
schedule
}
}
pub fn max_code_size(&self, block_number: u64) -> u64 {
if block_number >= self.max_code_size_transition {
self.max_code_size
} else {
u64::max_value()
}
}
pub fn update_schedule(&self, block_number: u64, schedule: &mut tetsy_vm::Schedule) {
schedule.have_create2 = block_number >= self.eip1014_transition;
schedule.have_revert = block_number >= self.eip140_transition;
schedule.have_static_call = block_number >= self.eip214_transition;
schedule.have_return_data = block_number >= self.eip211_transition;
schedule.have_bitwise_shifting = block_number >= self.eip145_transition;
schedule.have_extcodehash = block_number >= self.eip1052_transition;
schedule.have_chain_id = block_number >= self.eip1344_transition;
schedule.eip1283 =
(block_number >= self.eip1283_transition &&
!(block_number >= self.eip1283_disable_transition)) ||
block_number >= self.eip1283_reenable_transition;
schedule.eip1706 = block_number >= self.eip1706_transition;
if block_number >= self.eip1884_transition {
schedule.have_selfbalance = true;
schedule.sload_gas = 800;
schedule.balance_gas = 700;
schedule.extcodehash_gas = 700;
}
if block_number >= self.eip2028_transition {
schedule.tx_data_non_zero_gas = 16;
}
if block_number >= self.eip2200_advance_transition {
schedule.sstore_dirty_gas = Some(800);
}
if block_number >= self.eip210_transition {
schedule.blockhash_gas = 800;
}
if block_number >= self.dust_protection_transition {
schedule.kill_dust = match self.remove_dust_contracts {
true => tetsy_vm::CleanDustMode::WithCodeAndStorage,
false => tetsy_vm::CleanDustMode::BasicOnly,
};
}
if block_number >= self.wasm_activation_transition {
let mut wasm = tetsy_vm::WasmCosts::default();
if block_number >= self.kip4_transition {
wasm.have_create2 = true;
}
if block_number >= self.kip6_transition {
wasm.have_gasleft = true;
}
schedule.wasm = Some(wasm);
if let Some(version) = self.wasm_version {
schedule.versions.insert(version, tetsy_vm::VersionedSchedule::TWasm);
}
}
}
pub fn nonzero_bugfix_hard_fork(&self) -> Option<&str> {
if self.eip155_transition != 0 {
return Some("eip155Transition");
}
if self.validate_receipts_transition != 0 {
return Some("validateReceiptsTransition");
}
if self.validate_chain_id_transition != 0 {
return Some("validateChainIdTransition");
}
None
}
}
impl From<vapjson::spec::Params> for CommonParams {
fn from(p: vapjson::spec::Params) -> Self {
CommonParams {
account_start_nonce: p.account_start_nonce.map_or_else(U256::zero, Into::into),
maximum_extra_data_size: p.maximum_extra_data_size.into(),
network_id: p.network_id.into(),
chain_id: if let Some(n) = p.chain_id {
n.into()
} else {
p.network_id.into()
},
subprotocol_name: p.subprotocol_name.unwrap_or_else(|| "vap".to_owned()),
min_gas_limit: p.min_gas_limit.into(),
fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) {
Some((n.into(), h.into()))
} else {
None
},
eip150_transition: p.eip150_transition.map_or(0, Into::into),
eip160_transition: p.eip160_transition.map_or(0, Into::into),
eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into),
eip161d_transition: p.eip161d_transition.map_or(0, Into::into),
eip98_transition: p.eip98_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip155_transition: p.eip155_transition.map_or(0, Into::into),
validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
validate_chain_id_transition: p.validate_chain_id_transition.map_or(0, Into::into),
eip140_transition: p.eip140_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip210_transition: p.eip210_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip210_contract_address: p.eip210_contract_address.map_or(Address::from_low_u64_be(0xf0), Into::into),
eip210_contract_code: p.eip210_contract_code.map_or_else(
|| DEFAULT_BLOCKHASH_CONTRACT.to_vec(),
Into::into,
),
eip210_contract_gas: p.eip210_contract_gas.map_or(1000000.into(), Into::into),
eip211_transition: p.eip211_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip145_transition: p.eip145_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip214_transition: p.eip214_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip658_transition: p.eip658_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1052_transition: p.eip1052_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1283_transition: p.eip1283_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1283_disable_transition: p.eip1283_disable_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1283_reenable_transition: p.eip1283_reenable_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1706_transition: p.eip1706_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1014_transition: p.eip1014_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1344_transition: p.eip1344_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip1884_transition: p.eip1884_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip2028_transition: p.eip2028_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
eip2200_advance_transition: p.eip2200_advance_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
dust_protection_transition: p.dust_protection_transition.map_or_else(
BlockNumber::max_value,
Into::into,
),
nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into),
remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false),
gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(),
registrar: p.tetsy_registrar.map(Into::into),
node_permission_contract: p.node_permission_contract.map(Into::into),
max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into),
max_transaction_size: p.max_transaction_size.map_or(MAX_TRANSACTION_SIZE, Into::into),
max_code_size_transition: p.max_code_size_transition.map_or(0, Into::into),
transaction_permission_contract: p.transaction_permission_contract.map(Into::into),
transaction_permission_contract_transition:
p.transaction_permission_contract_transition.map_or(0, Into::into),
wasm_activation_transition: p.wasm_activation_transition.map_or_else(
BlockNumber::max_value,
Into::into
),
wasm_version: p.wasm_version.map(Into::into),
kip4_transition: p.kip4_transition.map_or_else(
BlockNumber::max_value,
Into::into
),
kip6_transition: p.kip6_transition.map_or_else(
BlockNumber::max_value,
Into::into
),
}
}
}