diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f80245bb0..625b53675 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -24,6 +24,7 @@ cache: - stable - beta - tags + - schedules .collect_artifacts: &collect_artifacts artifacts: diff --git a/Cargo.toml b/Cargo.toml index 6f2559cd6..3fdfd56d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,6 +89,7 @@ daemonize = { git = "https://github.com/paritytech/daemonize" } [features] miner-debug = ["ethcore/miner-debug"] json-tests = ["ethcore/json-tests"] +ci-skip-issue = ["ethcore/ci-skip-issue"] test-heavy = ["ethcore/test-heavy"] evm-debug = ["ethcore/evm-debug"] evm-debug-tests = ["ethcore/evm-debug-tests"] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 82dd2230d..80f7e4326 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -102,6 +102,8 @@ evm-debug-tests = ["evm-debug", "evm/evm-debug-tests"] slow-blocks = [] # Run JSON consensus tests. json-tests = ["ethcore-transaction/json-tests", "test-helpers", "tempdir"] +# Skip JSON consensus tests with pending issues. +ci-skip-issue = [] # Run memory/cpu heavy tests. test-heavy = [] # Compile benches diff --git a/ethcore/evm/src/evm.rs b/ethcore/evm/src/evm.rs index 4c85b3702..d44d120e7 100644 --- a/ethcore/evm/src/evm.rs +++ b/ethcore/evm/src/evm.rs @@ -57,7 +57,7 @@ impl Finalize for Result { /// Cost calculation type. For low-gas usage we calculate costs using usize instead of U256 pub trait CostType: Sized + From + Copy - + ops::Mul + ops::Div + ops::Add +ops::Sub + + ops::Mul + ops::Div + ops::Add + ops::Sub + ops::Shr + ops::Shl + cmp::Ord + fmt::Debug { /// Converts this cost into `U256` diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 7a41ed33c..e1d31b13a 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -134,6 +134,8 @@ enum_with_from_u8! { RETURNDATASIZE = 0x3d, #[doc = "copy return data buffer to memory"] RETURNDATACOPY = 0x3e, + #[doc = "return the keccak256 hash of contract code"] + EXTCODEHASH = 0x3f, #[doc = "get hash of most recent complete block"] BLOCKHASH = 0x40, @@ -326,7 +328,7 @@ enum_with_from_u8! { #[doc = "like CALLCODE but keeps caller's value and sender"] DELEGATECALL = 0xf4, #[doc = "create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160"] - CREATE2 = 0xfb, + CREATE2 = 0xf5, #[doc = "stop execution and revert state changes. Return output data."] REVERT = 0xfd, #[doc = "like CALL but it does not take value, nor modify the state"] @@ -492,6 +494,7 @@ lazy_static! { arr[CALLDATALOAD as usize] = Some(InstructionInfo::new("CALLDATALOAD", 1, 1, GasPriceTier::VeryLow)); arr[CALLDATASIZE as usize] = Some(InstructionInfo::new("CALLDATASIZE", 0, 1, GasPriceTier::Base)); arr[CALLDATACOPY as usize] = Some(InstructionInfo::new("CALLDATACOPY", 3, 0, GasPriceTier::VeryLow)); + arr[EXTCODEHASH as usize] = Some(InstructionInfo::new("EXTCODEHASH", 1, 1, GasPriceTier::Special)); arr[CODESIZE as usize] = Some(InstructionInfo::new("CODESIZE", 0, 1, GasPriceTier::Base)); arr[CODECOPY as usize] = Some(InstructionInfo::new("CODECOPY", 3, 0, GasPriceTier::VeryLow)); arr[GASPRICE as usize] = Some(InstructionInfo::new("GASPRICE", 0, 1, GasPriceTier::Base)); @@ -591,7 +594,7 @@ lazy_static! { arr[DELEGATECALL as usize] = Some(InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special)); arr[STATICCALL as usize] = Some(InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special)); arr[SUICIDE as usize] = Some(InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special)); - arr[CREATE2 as usize] = Some(InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special)); + arr[CREATE2 as usize] = Some(InstructionInfo::new("CREATE2", 4, 1, GasPriceTier::Special)); arr[REVERT as usize] = Some(InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero)); arr }; diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index dbb333837..524791fe9 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -125,12 +125,17 @@ impl Gasometer { let newval = stack.peek(1); let val = U256::from(&*ext.storage_at(&address)?); - let gas = if val.is_zero() && !newval.is_zero() { - schedule.sstore_set_gas + let gas = if schedule.eip1283 { + let orig = U256::from(&*ext.initial_storage_at(&address)?); + calculate_eip1283_sstore_gas(schedule, &orig, &val, &newval) } else { - // Refund for below case is added when actually executing sstore - // !is_zero(&val) && is_zero(newval) - schedule.sstore_reset_gas + if val.is_zero() && !newval.is_zero() { + schedule.sstore_set_gas + } else { + // Refund for below case is added when actually executing sstore + // !is_zero(&val) && is_zero(newval) + schedule.sstore_reset_gas + } }; Request::Gas(Gas::from(gas)) }, @@ -143,6 +148,9 @@ impl Gasometer { instructions::EXTCODESIZE => { Request::Gas(Gas::from(schedule.extcodesize_gas)) }, + instructions::EXTCODEHASH => { + Request::Gas(Gas::from(schedule.extcodehash_gas)) + }, instructions::SUICIDE => { let mut gas = Gas::from(schedule.suicide_gas); @@ -168,9 +176,8 @@ impl Gasometer { Request::GasMem(default_gas, mem_needed(stack.peek(0), stack.peek(1))?) }, instructions::SHA3 => { - let w = overflowing!(add_gas_usize(Gas::from_u256(*stack.peek(1))?, 31)); - let words = w >> 5; - let gas = Gas::from(schedule.sha3_gas) + (Gas::from(schedule.sha3_word_gas) * words); + let words = overflowing!(to_word_size(Gas::from_u256(*stack.peek(1))?)); + let gas = overflowing!(Gas::from(schedule.sha3_gas).overflow_add(overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(words)))); Request::GasMem(gas, mem_needed(stack.peek(0), stack.peek(1))?) }, instructions::CALLDATACOPY | instructions::CODECOPY | instructions::RETURNDATACOPY => { @@ -223,9 +230,24 @@ impl Gasometer { Request::GasMemProvide(gas, mem, Some(requested)) }, - instructions::CREATE | instructions::CREATE2 => { + instructions::CREATE => { + let start = stack.peek(1); + let len = stack.peek(2); + let gas = Gas::from(schedule.create_gas); - let mem = mem_needed(stack.peek(1), stack.peek(2))?; + let mem = mem_needed(start, len)?; + + Request::GasMemProvide(gas, mem, None) + }, + instructions::CREATE2 => { + let start = stack.peek(1); + let len = stack.peek(2); + + let base = Gas::from(schedule.create_gas); + let word = overflowing!(to_word_size(Gas::from_u256(*len)?)); + let word_gas = overflowing!(Gas::from(schedule.sha3_word_gas).overflow_mul(word)); + let gas = overflowing!(base.overflow_add(word_gas)); + let mem = mem_needed(start, len)?; Request::GasMemProvide(gas, mem, None) }, @@ -275,8 +297,8 @@ impl Gasometer { }, Request::GasMemCopy(gas, mem_size, copy) => { let (mem_gas_cost, new_mem_gas, new_mem_size) = self.mem_gas_cost(schedule, current_mem_size, &mem_size)?; - let copy = overflowing!(add_gas_usize(copy, 31)) >> 5; - let copy_gas = Gas::from(schedule.copy_gas) * copy; + let copy = overflowing!(to_word_size(copy)); + let copy_gas = overflowing!(Gas::from(schedule.copy_gas).overflow_mul(copy)); let gas = overflowing!(gas.overflow_add(copy_gas)); let gas = overflowing!(gas.overflow_add(mem_gas_cost)); @@ -303,7 +325,7 @@ impl Gasometer { }; let current_mem_size = Gas::from(current_mem_size); - let req_mem_size_rounded = (overflowing!(mem_size.overflow_add(Gas::from(31 as usize))) >> 5) << 5; + let req_mem_size_rounded = overflowing!(to_word_size(*mem_size)) << 5; let (mem_gas_cost, new_mem_gas) = if req_mem_size_rounded > current_mem_size { let new_mem_gas = gas_for_mem(req_mem_size_rounded)?; @@ -335,6 +357,99 @@ fn add_gas_usize(value: Gas, num: usize) -> (Gas, bool) { value.overflow_add(Gas::from(num)) } +#[inline] +fn to_word_size(value: Gas) -> (Gas, bool) { + let (gas, overflow) = add_gas_usize(value, 31); + if overflow { + return (gas, overflow); + } + + (gas >> 5, false) +} + +#[inline] +fn calculate_eip1283_sstore_gas(schedule: &Schedule, original: &U256, current: &U256, new: &U256) -> Gas { + Gas::from( + if current == new { + // 1. If current value equals new value (this is a no-op), 200 gas is deducted. + schedule.sload_gas + } else { + // 2. If current value does not equal new value + if original == current { + // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context) + if original.is_zero() { + // 2.1.1. If original value is 0, 20000 gas is deducted. + schedule.sstore_set_gas + } else { + // 2.1.2. Otherwise, 5000 gas is deducted. + schedule.sstore_reset_gas + + // 2.1.2.1. If new value is 0, add 15000 gas to refund counter. + } + } else { + // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. + schedule.sload_gas + + // 2.2.1. If original value is not 0 + // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0. + // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter. + + // 2.2.2. If original value equals new value (this storage slot is reset) + // 2.2.2.1. If original value is 0, add 19800 gas to refund counter. + // 2.2.2.2. Otherwise, add 4800 gas to refund counter. + } + } + ) +} + +pub fn handle_eip1283_sstore_clears_refund(ext: &mut vm::Ext, original: &U256, current: &U256, new: &U256) { + let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas); + + if current == new { + // 1. If current value equals new value (this is a no-op), 200 gas is deducted. + } else { + // 2. If current value does not equal new value + if original == current { + // 2.1. If original value equals current value (this storage slot has not been changed by the current execution context) + if original.is_zero() { + // 2.1.1. If original value is 0, 20000 gas is deducted. + } else { + // 2.1.2. Otherwise, 5000 gas is deducted. + if new.is_zero() { + // 2.1.2.1. If new value is 0, add 15000 gas to refund counter. + ext.add_sstore_refund(sstore_clears_schedule); + } + } + } else { + // 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses. + + if !original.is_zero() { + // 2.2.1. If original value is not 0 + if current.is_zero() { + // 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0. + ext.sub_sstore_refund(sstore_clears_schedule); + } else if new.is_zero() { + // 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter. + ext.add_sstore_refund(sstore_clears_schedule); + } + } + + if original == new { + // 2.2.2. If original value equals new value (this storage slot is reset) + if original.is_zero() { + // 2.2.2.1. If original value is 0, add 19800 gas to refund counter. + let refund = U256::from(ext.schedule().sstore_set_gas - ext.schedule().sload_gas); + ext.add_sstore_refund(refund); + } else { + // 2.2.2.2. Otherwise, add 4800 gas to refund counter. + let refund = U256::from(ext.schedule().sstore_reset_gas - ext.schedule().sload_gas); + ext.add_sstore_refund(refund); + } + } + } + } +} + #[test] fn test_mem_gas_cost() { // given diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 111986913..8e32c83fd 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -186,8 +186,7 @@ impl vm::Vm for Interpreter { match result { InstructionResult::JumpToPosition(position) => { if valid_jump_destinations.is_none() { - let code_hash = params.code_hash.clone().unwrap_or_else(|| keccak(code.as_ref())); - valid_jump_destinations = Some(self.cache.jump_destinations(&code_hash, code)); + valid_jump_destinations = Some(self.cache.jump_destinations(¶ms.code_hash, code)); } let jump_destinations = valid_jump_destinations.as_ref().expect("jump_destinations are initialized on first jump; qed"); let pos = self.verify_jump(position, jump_destinations)?; @@ -230,8 +229,9 @@ impl Interpreter { (instruction == instructions::STATICCALL && !schedule.have_static_call) || ((instruction == instructions::RETURNDATACOPY || instruction == instructions::RETURNDATASIZE) && !schedule.have_return_data) || (instruction == instructions::REVERT && !schedule.have_revert) || - ((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) { - + ((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) || + (instruction == instructions::EXTCODEHASH && !schedule.have_extcodehash) + { return Err(vm::Error::BadInstruction { instruction: instruction as u8 }); @@ -318,6 +318,11 @@ impl Interpreter { let endowment = stack.pop_back(); let init_off = stack.pop_back(); let init_size = stack.pop_back(); + let address_scheme = match instruction { + instructions::CREATE => CreateContractAddress::FromSenderAndNonce, + instructions::CREATE2 => CreateContractAddress::FromSenderSaltAndCodeHash(stack.pop_back().into()), + _ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"), + }; let create_gas = provided.expect("`provided` comes through Self::exec from `Gasometer::get_gas_cost_mem`; `gas_gas_mem_cost` guarantees `Some` when instruction is `CALL`/`CALLCODE`/`DELEGATECALL`/`CREATE`; this is `CREATE`; qed"); @@ -335,7 +340,6 @@ impl Interpreter { } let contract_code = self.mem.read_slice(init_off, init_size); - let address_scheme = if instruction == instructions::CREATE { CreateContractAddress::FromSenderAndNonce } else { CreateContractAddress::FromSenderAndCodeHash }; let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme); return match create_result { @@ -510,8 +514,14 @@ impl Interpreter { let current_val = U256::from(&*ext.storage_at(&address)?); // Increase refund for clear - if !self.is_zero(¤t_val) && self.is_zero(&val) { - ext.inc_sstore_clears(); + if ext.schedule().eip1283 { + let original_val = U256::from(&*ext.initial_storage_at(&address)?); + gasometer::handle_eip1283_sstore_clears_refund(ext, &original_val, ¤t_val, &val); + } else { + if !current_val.is_zero() && val.is_zero() { + let sstore_clears_schedule = U256::from(ext.schedule().sstore_refund_gas); + ext.add_sstore_refund(sstore_clears_schedule); + } } ext.set_storage(address, H256::from(&val))?; }, @@ -568,9 +578,14 @@ impl Interpreter { }, instructions::EXTCODESIZE => { let address = u256_to_address(&stack.pop_back()); - let len = ext.extcodesize(&address)?; + let len = ext.extcodesize(&address)?.unwrap_or(0); stack.push(U256::from(len)); }, + instructions::EXTCODEHASH => { + let address = u256_to_address(&stack.pop_back()); + let hash = ext.extcodehash(&address)?.unwrap_or_else(H256::zero); + stack.push(U256::from(hash)); + }, instructions::CALLDATACOPY => { Self::copy_data_to_memory(&mut self.mem, stack, params.data.as_ref().map_or_else(|| &[] as &[u8], |d| &*d as &[u8])); }, @@ -591,7 +606,11 @@ impl Interpreter { instructions::EXTCODECOPY => { let address = u256_to_address(&stack.pop_back()); let code = ext.extcode(&address)?; - Self::copy_data_to_memory(&mut self.mem, stack, &code); + Self::copy_data_to_memory( + &mut self.mem, + stack, + code.as_ref().map(|c| &(*c)[..]).unwrap_or(&[]) + ); }, instructions::GASPRICE => { stack.push(params.gas_price.clone()); diff --git a/ethcore/evm/src/interpreter/shared_cache.rs b/ethcore/evm/src/interpreter/shared_cache.rs index f4a7f47f9..63c4f507d 100644 --- a/ethcore/evm/src/interpreter/shared_cache.rs +++ b/ethcore/evm/src/interpreter/shared_cache.rs @@ -50,17 +50,22 @@ impl SharedCache { } /// Get jump destinations bitmap for a contract. - pub fn jump_destinations(&self, code_hash: &H256, code: &[u8]) -> Arc { - if code_hash == &KECCAK_EMPTY { - return Self::find_jump_destinations(code); - } + pub fn jump_destinations(&self, code_hash: &Option, code: &[u8]) -> Arc { + if let Some(ref code_hash) = code_hash { + if code_hash == &KECCAK_EMPTY { + return Self::find_jump_destinations(code); + } - if let Some(d) = self.jump_destinations.lock().get_mut(code_hash) { - return d.0.clone(); + if let Some(d) = self.jump_destinations.lock().get_mut(code_hash) { + return d.0.clone(); + } } let d = Self::find_jump_destinations(code); - self.jump_destinations.lock().insert(code_hash.clone(), Bits(d.clone())); + + if let Some(ref code_hash) = code_hash { + self.jump_destinations.lock().insert(*code_hash, Bits(d.clone())); + } d } diff --git a/ethcore/evm/src/tests.rs b/ethcore/evm/src/tests.rs index b62faf87d..6b4d5cc6f 100644 --- a/ethcore/evm/src/tests.rs +++ b/ethcore/evm/src/tests.rs @@ -716,7 +716,7 @@ fn test_jumps(factory: super::Factory) { test_finalize(vm.exec(params, &mut ext)).unwrap() }; - assert_eq!(ext.sstore_clears, 1); + assert_eq!(ext.sstore_clears, U256::from(ext.schedule.sstore_refund_gas)); assert_store(&ext, 0, "0000000000000000000000000000000000000000000000000000000000000000"); // 5! assert_store(&ext, 1, "0000000000000000000000000000000000000000000000000000000000000078"); // 5! assert_eq!(gas_left, U256::from(54_117)); @@ -746,6 +746,7 @@ fn test_calls(factory: super::Factory) { assert_set_contains(&ext.calls, &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(2556), sender_address: Some(address.clone()), receive_address: Some(code_address.clone()), @@ -755,6 +756,7 @@ fn test_calls(factory: super::Factory) { }); assert_set_contains(&ext.calls, &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(2556), sender_address: Some(address.clone()), receive_address: Some(address.clone()), diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index a1625b0e8..af557c024 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -127,9 +127,6 @@ pub trait LightChainClient: Send + Sync { /// Get the `i`th CHT root. fn cht_root(&self, i: usize) -> Option; - /// Get the EIP-86 transition block number. - fn eip86_transition(&self) -> BlockNumber; - /// Get a report of import activity since the last call. fn report(&self) -> ClientReport; } @@ -585,10 +582,6 @@ impl LightChainClient for Client { Client::cht_root(self, i) } - fn eip86_transition(&self) -> BlockNumber { - self.engine().params().eip86_transition - } - fn report(&self) -> ClientReport { Client::report(self) } diff --git a/ethcore/res/ethereum/byzantium_test.json b/ethcore/res/ethereum/byzantium_test.json index 90c92bbff..e3d8645d6 100644 --- a/ethcore/res/ethereum/byzantium_test.json +++ b/ethcore/res/ethereum/byzantium_test.json @@ -6,10 +6,10 @@ "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "blockReward": "0x4563918244F40000", + "blockReward": "0x29A2241AF62C0000", "homesteadTransition": "0x0", - "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": "0x0", + "eip649Reward": "0x29A2241AF62C0000", "eip649Transition": "0x0" } } diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index 602c05cd3..a2bcb717a 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -31,8 +31,7 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": 3000000, - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/constantinople_test.json b/ethcore/res/ethereum/constantinople_test.json index 155b06507..fd7474dc2 100644 --- a/ethcore/res/ethereum/constantinople_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -1,16 +1,18 @@ { - "name": "Byzantium (Test)", + "name": "Constantinople (test)", "engine": { "Ethash": { "params": { "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "blockReward": "0x4563918244F40000", + "blockReward": "0x29A2241AF62C0000", "homesteadTransition": "0x0", - "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": "0x0", - "eip649Transition": "0x0" + "eip649Transition": "0x5", + "eip649Reward": "0x1BC16D674EC80000", + "eip1234Transition": "0x5", + "eip1234Reward": "0x1BC16D674EC80000" } } }, @@ -29,11 +31,14 @@ "eip161abcTransition": "0x0", "eip161dTransition": "0x0", "eip140Transition": "0x0", - "eip210Transition": "0x0", "eip211Transition": "0x0", "eip214Transition": "0x0", "eip155Transition": "0x0", - "eip658Transition": "0x0" + "eip658Transition": "0x0", + "eip145Transition": "0x0", + "eip1014Transition": "0x0", + "eip1052Transition": "0x0", + "eip1283Transition": "0x0" }, "genesis": { "seal": { @@ -54,9 +59,9 @@ "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } } } diff --git a/ethcore/res/ethereum/easthub.json b/ethcore/res/ethereum/easthub.json index e7e1a6e70..bcc34a782 100644 --- a/ethcore/res/ethereum/easthub.json +++ b/ethcore/res/ethereum/easthub.json @@ -27,8 +27,7 @@ "eip155Transition": "0x0", "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/eip150_test.json b/ethcore/res/ethereum/eip150_test.json index baf9c1b7b..32f6401ff 100644 --- a/ethcore/res/ethereum/eip150_test.json +++ b/ethcore/res/ethereum/eip150_test.json @@ -23,7 +23,6 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffffff", - "eip86Transition": "0x7fffffffffffffff", "eip155Transition": "0x7fffffffffffffff", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x7fffffffffffffff" diff --git a/ethcore/res/ethereum/eip161_test.json b/ethcore/res/ethereum/eip161_test.json index 079ce7d55..b64b6b047 100644 --- a/ethcore/res/ethereum/eip161_test.json +++ b/ethcore/res/ethereum/eip161_test.json @@ -23,8 +23,7 @@ "eip161abcTransition": "0x0", "eip161dTransition": "0x0", "eip98Transition": "0x7fffffffffffffff", - "eip86Transition": "0x7fffffffffffffff", - "eip155Transition": "0x7fffffffffffffff", + "eip155Transition": "0x0", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0" }, diff --git a/ethcore/res/ethereum/eip210_test.json b/ethcore/res/ethereum/eip210_test.json new file mode 100644 index 000000000..9733e5d87 --- /dev/null +++ b/ethcore/res/ethereum/eip210_test.json @@ -0,0 +1,54 @@ +{ + "name": "EIP210 (test)", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "blockReward": "0x4563918244F40000", + "homesteadTransition": "0x0" + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1", + "maxCodeSize": 24576, + "maxCodeSizeTransition": "0x0", + "eip98Transition": "0xffffffffffffffff", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "eip210Transition": "0x0" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + } +} diff --git a/ethcore/res/ethereum/ellaism.json b/ethcore/res/ethereum/ellaism.json index c3107bbe4..de56ae947 100644 --- a/ethcore/res/ethereum/ellaism.json +++ b/ethcore/res/ethereum/ellaism.json @@ -29,7 +29,6 @@ "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": "0x0", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "wasmActivationTransition": 2000000, "eip140Transition": 2000000, "eip211Transition": 2000000, diff --git a/ethcore/res/ethereum/expanse.json b/ethcore/res/ethereum/expanse.json index 2061231c6..5e54f6833 100644 --- a/ethcore/res/ethereum/expanse.json +++ b/ethcore/res/ethereum/expanse.json @@ -38,7 +38,6 @@ "eip161abcTransition": "0x927C0", "eip161dTransition": "0x927C0", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x927C0", "eip140Transition": "0xC3500", "eip211Transition": "0xC3500", diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index 3332ad6f9..850e31f12 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -150,7 +150,6 @@ "eip161dTransition": 2675000, "eip155Transition": 2675000, "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "maxCodeSize": 24576, "maxCodeSizeTransition": 2675000, "eip140Transition": 4370000, @@ -174,8 +173,8 @@ "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" }, "hardcodedSync": { - "header": "f9020ba0c7139a7f4b14c2e12dbe34aeb92711b37747bf8698ecdd6f2c3b1f5f3840e288a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479452e44f279f4203dcf680395379e5f9990a69f13ca06e817f8a9b206f93a393da76a3ece2a74b98eaecc4dae0cfa8f409455e88ccb4a0d739197170d2bc6bbb24fac0ce695982090702082fe1541bb7634f018dfe87b3a038503b7299fb1c113a78b4a3a5dfd997ef32e7fbf722fc178dfcb21e1af1f7f5b9010000020000000000000008000000000010000000000000000000000000000200000002000000000008000000000000000000000000000000000000000000000000000000000000000001004008000000000000000000000000000080000000000008000000080000000000008000000000000000000000000000040210004000000010000000400000000001040000000200000000000000440008000000040000000000000000000000000010000000000000000000000000000000800000000000100002000000000000000000002000000000000000000000000000000000000080000000100000000000000000040400000000000000004000000000000000870c90e059b181c6835ee8018379fb9583065150845b833d198a7777772e62772e636f6da0171fc2d066507ea10c8c2d7bedd5ccc3f0dfb4d590a3998a614013326c0b213a88b4fd884826187393", - "totalDifficulty": "6255555800944520547241", + "header": "f90206a0391c42ff4f047145a6b9a14179c3cc404b31d92f30693e28cf2bba41f47f6329a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b2930b35844a230f00e51431acae96fe543a0347a0fb280d4457e60a0b96577e1dde9e00905102cfd36def5c5b31dcc2284636136ea077f739c324e35c7448b14aa02186973d3c74cc1ab081498cd0c487a604873723a0e462d76b5204d14b13d1f1b39ea048a3b637f91d42c729c367d5bbdbd0a72d70b90100008003410402005000200009400030c40490500208480008414000a40048806408000080802008204400010001800c0020080c0a00400105a9080820400900240000084012030a1504030508000200005c4404a0c3490820000010400811040004708a1006910211444040c28001a800e920d00000940c200119111a10401001008044214002002080c21081801e008a320848a204400042400898004004010028840181106210080254a081112480031000410202440092c880be3894000120050500860880000108000c0080009e0000204007212840808cb80200601024020000210280100c018540b28a1041a62400000108204084000008808040000004870bc009a1914d7f8362f801837a121d8379ee5a845bbd53ca8573696e6731a0abce0f90ce69f740080eeb94d1cb13981fafe3bc6d020a44815acd86cbd3fc0a889501b04c0614e053", + "totalDifficulty": "7128515864594819065361", "CHTs": [ "0x0eb474b7721727204978e92e27d31cddff56471911e424a4c8271c35f9c982cc", "0xe10e94515fb5ffb7ffa9bf50db4a959b3f50c2ff75e0b8bd5f5e038749e52a11", @@ -3213,7 +3212,137 @@ "0xf344c0cf6516f0fa6617e48076726aefbdaaf5a31f67ad8199bc3f6e426bf904", "0x3f3d2d33f36ba9009e9a72f3f5bbcb5df5392a19fc7afc8d37823aaf52b03477", "0x346a89411f090d559ff90e670bf0a385b1b09f117fc9ffa18b09d3b6d5d8e45c", - "0x5bc5689e2b4572b8ceea472cc7827e22cbfd018920beebf5c5b25f65f5cd5357" + "0x5bc5689e2b4572b8ceea472cc7827e22cbfd018920beebf5c5b25f65f5cd5357", + "0xda418efcaa0076f77e4d2f0c57fc32fa67179a5631d9df52d56497113d0e87af", + "0x5a8050832e835202695129f6f384652827e61ea5f1be7ff300183201d8bd6b4d", + "0xd9f444c382da42c310bd2f05955187163ae7b224e5efd44ab95af332e197d374", + "0x9ef2c5bad361117eedbc2adcb72a2ef5eba4caf3a99a0cbb2a65a94d185e48ae", + "0x7e3e089bc46b00a4174d90003379c382ab5bd84d092b9c4db3189d2bdc24f00b", + "0x94f50fb12eed909d251fe69adb1a1f214776cb029d487360b55c3a2abb663d7e", + "0xd3e1f4244dea40d0741255db2dae72103e263390e0ccfdefcbb2da59ecc5ec9f", + "0x6808bf0cb7d4b677527de762b6db8ddf74a1b272349f34f44505912bd95d62f3", + "0xbf7672ac474b5b849bc086ff8455216f015c8fc7660436dee153522ef6991c04", + "0xe79d27a369cdd5455ddbc6bd9158cd1870aa895b3c3971d07f1555b95ed02ac3", + "0xfa9e20a36c11b0dfbf7e9c62872a6423f5460dfd18e447481461a41176678262", + "0xaafb6c407910341bedc82c0f260cdef75ce5653f644b93a465cb990247a32986", + "0x5058e655e0c179e6c20f48fbd08c2f34f9341f6c07972ff40f55bfabbc783b12", + "0x28d2e7c852de8602a764ff693b6881af18ddadd67fc7eff481f48ac20ebf32f6", + "0xf82e09e7916f61b5cfdc3dcf193bf9d535f2b33f93a06c90fbdc78b3aac6b7ef", + "0x626f3cca9e1a9e5e123e34485c8697c758ffc32213a727665065dd6abd2babe5", + "0xb7f1c07f673d903daa61dec649eb12286a7a0568ee36ecfb1023ec41427c8dd0", + "0x8d1d42bfe88dbe4c621cf68d380dc57e7768121a815546bb4aab29b7486da9ee", + "0x79835acd7266bce85978f481aa3c58f3bab9106d72892df8579e472dc95c6899", + "0x0911c9c804bbe9be0aebab6c92f5b71a893f72a9d0cd35a51b0e8cd19ab0c02a", + "0x7fd2eff10936d8d12fd9a1c6d27e77cbec4e48253465eb7e65876134ff60c8ec", + "0xc739ad4255415e2831c6996673f3d02dc79f6e6d6822f7dee23bff5b94833c3a", + "0x2559faafbae0852fe5a1c924f0e4f6ccdf4fd22f483148b3672a3e7b3692b669", + "0xca37f0aa3d375dbddc0b426c9564fe68f10b0a4cbbf1ab87f97b27b44878f2fb", + "0x00ba40205d1bd46ad5b5e73cd5b1f3418bd892586d5a4647ac9a6d158f15bd93", + "0xfa6d25c829299535e6b80af81a2416d10ed6903117e73c656b979a5f5abe3ee0", + "0xfd82d8944315cfb228a8fa416c18ff82cbd8869c3babbd3389dca6dd66797785", + "0xd8834cc29788cb40ec901725419df8c031a13e190756a6352696de870eaf4671", + "0xdf6843a52bf55e0f4404e7bdf144bb17d5c47a72ef9482e712090ac9730a7f52", + "0x4c2c562f835966c72985f7cca89a3b1a7b0d4cb04623dc96e337daa35a2f5925", + "0x49d2afd87e83a04059dbf3ef4e2598b8d0c495ab1cf91ed3004e16a608e910c2", + "0x5be64774739c001c239efae1ce9f2a5706cc6e3054ddf24b03c09358f2f4852f", + "0x678f789dc8c409653b36f4d2015338165d3bc6a73f2a77ebfe438676b8412d7a", + "0xf87c8fbf02d8e84cf72680e6b9a8b8be39fbae9f1eb1047c536d77535494a301", + "0xe2428b952d2c6d60d4925f56b3d8227cd6bc608da2c1b20264befd8b1ad89454", + "0x561a95eb50c663462bb8af3aab336bd745b0571746b10fefa791bc11be777763", + "0x6945f40e3499d2769ceecf499c701015d93fddb607720b18dbbd5a6a2aa46639", + "0x9c35b0367a2b82270d64f11c5299336b21b9f454077dcf7af3b2e434677a31b6", + "0x454dc6bb2443509381e478f1836cb36808e2ecd1a9944072056c292b710072f4", + "0x0c80566f34a46477592560a883a9c01fa393f7a2c9dbb28a54e46a5c017e8596", + "0xeff6a1255090509eccfdea2e591516886c91191f1f02eaae4808ac95009086fc", + "0x37cf60888e5ec75841e7f0533feef7200185a1c9f3253073216d83923c864829", + "0xb169ebb9e418809a96529835bc293782e4fc6310dba450afe3e95a7abdf7cc01", + "0xa3c8d5c71ce0477a247f56bfe95272ea07f0b7f10a8526b6e3ff9a8de8faa9ab", + "0x2bf18db4ee84bafbbabaf05d1d4d383c0d5fc91be6ae902334496996eb3a8e48", + "0x6c116f0d5809a2c28351a737ef3dbd1808685e1fd656e37df6b6e524aa82c918", + "0x21e2c8e019c687fdb360c9bdd4e3a5133488cd2e0365aee3b823120734aa6f27", + "0x20c9a1db9de894ab4f576265da25f391b32c0805c3da76fbfdd0aaf300f88a39", + "0x23ef1f43af87be7396449fc1f89d9766c59e8adf2660812293c65a27482ddb8e", + "0x04a82d3a4a5e7f2507688ecdcdc300d7fb97aa8be92a671d7d42c0b60fa4532b", + "0x99e204c42afd6d4040faad384517d99bd0e077b03310d32223234d2251d6a07c", + "0xe342c0c4295665b9e25773fc9998e18c460e723d0a14efdb59c19b27b9c7011b", + "0xb654b1b8ede0d54a605cda54b4635d2b3c2bb8efd01ebd416e52cc87b590d4f3", + "0x5daabc41eeb6de98336411a03ec0323995e81549941cf32b7e15c765d1b7b39e", + "0x5103fc7f0fc6df43fb081b580bb01476f2b1cbde73e4d0f9d1fa6d8427fae789", + "0xe2ecf5daba51d2f7b22106033fc43f956bd1db0c5ad02bd941bd3d2b96ca21c5", + "0xf152bce5c6d1efb7e22cde72d6b8ca37f556ffb686a13770c5fab46e04837c92", + "0x306007d8091caa5baaa78643307f5abf9a5f03996fc072a9016ba6b487b2017c", + "0xf57308d0c02c6b8e2416c070554c7e29911fa84ef4cf2d934e2322ca262e987c", + "0xb234fe7433d7fd71fe0c6dfc834e4bcbf84a261b95760a6c4eb67d222b9ff392", + "0x753059f3405f60da3aa7cd1aa0cbcfa4d5ef4f2a6ed34b853b2c5ab2181fd383", + "0x096c6630e821816d9f4bd83fbe0ccfd223282f34aae5a49f969ba30b98c324c3", + "0xd3eec9dedb057fbc839c474fc99cb54d89f3f47d896e06e758c98f1cd194b61f", + "0x0d44cb2a83b9a3fa18daac280cf08b46cc637d705488fd9400cd7300475d0a1c", + "0x2e37a3036db99c4cb1c135f5ca6b527fa13b2e80ee421805b7be5d8b16983602", + "0x381e0ca505308b7d3a083e60b0f9cb44c89f84942430ec9e4c5571796ab6a8eb", + "0x90b04d35906c6f5a59c266c3bce7c2b63cea1486f714e272592ef9ecab25b0ee", + "0x9cbea70e760f2ee97537d058d57f395886a2c3a6e769ccd3433b797b8716517b", + "0x4e2167846e8d6f0f6495b5f1443f59bea143b63f242e40186fc6429434d1136e", + "0xcaa0512739d000bb9783fceb46d0427098886e2b7f2e1140855f1a91f843d5b3", + "0xc14df4e379e84591f618e60b5953aa6764146c7822aa1f0e3c2287e20753985a", + "0xf4443154c04fd378b2c3812fee84b774b37d6e12778674403fb5c995379df866", + "0x1a501c2733cc138fb6ff3716899e08dbcd4d75edc18af8972e8a749e45eaf67a", + "0xfc8cb80bb0d0fb490f29aae3067641eef72e9225c558e7e299e0796a2086969d", + "0x2b7895550febf03070485c02d521e7ddd80b94b7fe33a60b7d7ea3545b13e7dd", + "0xfc4137c3cccd45050b5770a40b2f38c43c62b70b07d17bb6d762b405f3d753dc", + "0x86ed22bbbb9fc6600112b91601af4fff56d0ecbe9b3099f91d4477cab8e300f5", + "0x2273a60405ffb04bd024d880c79010f18d58e3c8ca0dc82795a0125364679fa6", + "0x00dfbfe7be3bb2116d9a603a01ac428c0088a2c1477810cd5d3be0d1bd86beab", + "0x7acfb03315585c79e2a47dbe847d24cab0785791f6af7f179fea4f9d6ecb0e0f", + "0xbf6a2e20ee1da5eec12b792bbaec2531e20766ba54bac423011c1057215851db", + "0xb5e94d1e3ba7363d1d79fb62dedd0b6c26b0485052dd64a7093d41ad2d41b890", + "0x9b0cc26f08708814960de8f280ac26d8ed5089a19bcbd2d765059306da22c196", + "0x22d8af121d3e395d3cb4f6ee43c06e6292f1b5ffda672d2e40dba69a2885f5ac", + "0x04bc174272a57189d76aa17de0f76806e8481f4903575ed8c4df12b042637e0e", + "0x06ebd2b6ec4b80280969a92726df5f9cb12d4288b60af617b7040876116656d3", + "0x0e9430513e63b5173271c89b1c91af0b4818d5d14a3034e1228c56c94186a109", + "0x8dc5422ba98d9e58112b052a00d4b82b1db32e22dd7ff2d845619899bd47f277", + "0xde513d40bdbb1e4956b468cece598d77134626a900066b92fb2ecd6fcb5f81c2", + "0x90746299ec75af1eb444ad14ac666ee444aa020fac3fb57796516d8772ec8f45", + "0xaa91c30c62b24f943ee1eec7586b682289541c0355c2726e44424da8686ca24d", + "0x76eb68baae9fb7ed126097f93842dcadfe6e7188d61549d9c0922a9b3ef8e80a", + "0x5aa5b4045e7fe71559a6e93f4a89b135eaef38b9a7f3a84e383ab1ff902ceca9", + "0x504b78f8fc3646e9722e96a5e97d99f2560d4fa3337fa5faf1cc8c8a05f3520d", + "0xffd7a5d7c3b21e8144f7678a9ddc039cf85eb32b09000a600c9f12aa7d6083ed", + "0xcbb4010000e96ff0b50b9627dae032bd50782ccbd51af8af7cfcd6cd184675f7", + "0xb96fabbdd02371bf4a6a0dc00e3874cf43d47246e27163c910c141b6759a4249", + "0x7358419f4e994ff296a37f2e88b238b3de6ba73062073c9467dec52a2df64422", + "0xca90be9f190a1fd0548becfa719a6e4763e92de0e4da4283a33b5f7d2886b425", + "0xa629364f7d6329b008d9c6a0262327bcc12953aa515cdb7b8817e7fe1d746d46", + "0xc5167bd8cac1ea6d14f305c9d4fe075e1875d96353e5236473b6daca5ae9b4fe", + "0xaf4ce2490e9504172a4393cf14e691e947c86a0ec7b53416384a5832b213d6c5", + "0xbfa4853ef2eecc5d99a90e1abfef37ca10c1f823c1d0ad59a1bb19339861241f", + "0xbb5a6584cdc7e4d06ec5fc1514233cc42970f6c332c3a9590978dc9908e58c0a", + "0xe69d7a0766db411e504f09a8f39f0583b2869016bbe95f21dba432bbe8b88442", + "0x89cf4caaaf200881779f5fa6da8ae91ff1c962045dd0622b5ca65c830d3a9d4f", + "0x82d66c631f4c4167e5301d896dbdfe24d8245b1de041fc85eaeb6e35117ed9a0", + "0x957907bc93879681d8682a188622f9bf2c7d2595dbe3e2e34bb01711cc4124d1", + "0xccb3a3380550586696abd3ac267e85c7516b2b682b3c48f66aca94d57500f3b3", + "0xaf56d4650406e70748dc860a7879d8d522599081f8e7011056c976b860703e43", + "0x5d96ac1d2dff8a054d880a44f5d45a1bd18aba29085fcd633b0608351ff1876c", + "0xe051736dad8b9f93a8f1c13031c2b63249925e152685a2e7ec188ee089861b20", + "0x0db8987339e1fae41af5f08e6fa15da5fd80de3431b54e82cf8edbdc792f870e", + "0xcc99097678110af2be8dc07da8d642dce928b7d9e2728fe6fef1fe2eaa81a72a", + "0x2428c1f94ca57c7913b011a68281eee9ee4855e4ed2c97e34a370e649b21acb1", + "0x501ee9580c89b1f67c5b3b69ae5fd1f83852a2f9330f53565bcd04d8a7c0b776", + "0x16ae47cfa19e8046f93a579fa2557b17aeca7892fc7a82b6d539930c8b7c95c9", + "0xda62590043ca70c1cdfc7969cdfa853bddbcef0ef62aabb9f372805322511014", + "0x481b4aeaaa60504c94dcfea966840b381db85183c34cd25b4857300b5c189003", + "0x035dcc47f8670a9f648bcb0232e42fd4876243a7a3bf737b88d723ba187929a7", + "0xebe9bf09e3577865aeb341a06f67bb6e607f10b04ed9f9d733492a9d0e9ceb1a", + "0xad5d85b58af6aef7f81bd6b2407c6e4884ec82b2ae2aeaa24e379a3d35902375", + "0x0f0dd63d7c6c284659283825624140b31a3adaf7cdbb2255faca443e52ebfe84", + "0x40079be1c9394e95b4823895ed380d79333ca2085aed2abd0d766f84d21b7b42", + "0x7cc40ed01b436ce225a3f9c5c2bc7f6f81aee40bb83a54bca2fe899b15f3e2b6", + "0x1b6356e1a83ca5b0eefda1fd62fa959b118d2a19a6a90f182a53414b3fc7f9f0", + "0xae4a71712cc96a5b30b45e3b92c339c2e975e4ed683f4d1fcadcdc121ff7c6bf", + "0x226f6d8c71ec32c5eaab6b01c0fc1d00ae95e60b383d09560e90549b79eb1447", + "0xf3dec779841c9384df93bcefbba8700a292b570b29d286a7c9c5a442b4788a20", + "0x63ef48e80efa45383857adcb0f31076393260cbad058d1938345ad13faae50b4" ] }, "nodes": [ diff --git a/ethcore/res/ethereum/frontier_like_test.json b/ethcore/res/ethereum/frontier_like_test.json index 7eac5acbd..3596217cb 100644 --- a/ethcore/res/ethereum/frontier_like_test.json +++ b/ethcore/res/ethereum/frontier_like_test.json @@ -143,7 +143,6 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" }, "genesis": { diff --git a/ethcore/res/ethereum/frontier_test.json b/ethcore/res/ethereum/frontier_test.json index 7e52f6ecf..b01ae9ef0 100644 --- a/ethcore/res/ethereum/frontier_test.json +++ b/ethcore/res/ethereum/frontier_test.json @@ -23,7 +23,6 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" }, "genesis": { diff --git a/ethcore/res/ethereum/homestead_test.json b/ethcore/res/ethereum/homestead_test.json index 817bf5ff5..2dc521b9a 100644 --- a/ethcore/res/ethereum/homestead_test.json +++ b/ethcore/res/ethereum/homestead_test.json @@ -19,7 +19,6 @@ "minGasLimit": "0x1388", "networkID" : "0x1", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff", "eip150Transition": "0x7fffffffffffffff", "eip160Transition": "0x7fffffffffffffff", diff --git a/ethcore/res/ethereum/kovan.json b/ethcore/res/ethereum/kovan.json index 281267135..336d32bae 100644 --- a/ethcore/res/ethereum/kovan.json +++ b/ethcore/res/ethereum/kovan.json @@ -43,7 +43,13 @@ "eip211Transition": 5067000, "eip214Transition": 5067000, "eip658Transition": 5067000, - "wasmActivationTransition": 6600000 + "wasmActivationTransition": 6600000, + "eip145Transition": 9200000, + "eip1014Transition": 9200000, + "eip1052Transition": 9200000, + "eip1283Transition": 9200000, + "kip4Transition": 9200000, + "kip6Transition": 9200000 }, "genesis": { "seal": { @@ -56,8 +62,8 @@ "gasLimit": "0x5B8D80" }, "hardcodedSync": { - "header": "f9023ea00861b3771ffb84fce48b8ba3c54a09f81e91ccb38c401261f06d370098889a43a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a071cc81d58cdd21d1e17f7389e55c530cd9f94cc15bb32af6477320682327dcffa06090021a7c09ae5e75e443410ebdb76de04f1eafb0ab910daae96ee6eec560eaa032510bf257dd03b11f3b4761b94b495a5b5a18cd6eb17c77785e0f46e2ffc882b901000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000400000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8381e001837a12008306697a845b83bd6096d583010b068650617269747986312e32372e30826c698416e0ef58b841117e2088e2835bf2afcd5d48f42b3bf2a1f33435f21f089ead2a6bae7d01c1486e645b460bb3c726a827ff1eb50e0579f3410563bae090fc256cf1d8d594b82100", - "totalDifficulty": "2845866505151538604560067685603735513869853136", + "header": "f90247a01865856fb6e4118598117560df31734c74cf725c8edae4db941055ac0afeb207a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479400e6d2b931f55a3f1701c7389d592a7778897879a054563efd593e9682943065880710af9187131127148575efc8bb51d80dfed41aa0a568a1653a6c7d559711be0b91a8e75db76c678dbdd286c75b88e4f0c0d31171a0dab32c5cbe9b9244a7af00afa7f6042a4ac923573e8f2f025b107abe1e3da999b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000004000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000090fffffffffffffffffffffffffffffffd8389b001837a120083046540845bbd803c9fde830200048f5061726974792d457468657265756d86312e32382e30826c698416ef600fb841387b51dae8bc8daa6cde190d3f44797690b4da1ce5fcfcd54bdbb2a6ee6d8c1f7649081ca28b5cd70067ee9f61e27d8184db83705102d5e1a269f2b631b4d5db01", + "totalDifficulty": "3020091077015059097853315484608800838133866777", "CHTs": [ "0xdb9557458495268ddd69409fc1f66631ed5ff9bf6c479be6eabe5d83a460acac", "0xd413800c22172be6e0b7a36348c90098955991f119ddad32c5b928e8db4deb02", @@ -4214,7 +4220,257 @@ "0x3ef50c81169af169c100f58f3afcb8e2f926d957b2adbaca8787be5d4e8d7233", "0x8783eaeb56ca2d7fec84e0e272b77271fdfd6c14452a2e1dd83de770c5d99a1a", "0x861024460895378ba100c5d0c05e62bb6cac8b21ae529ab5cab39eb6c6cabd90", - "0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b" + "0x1c741ed9eda60e5ac585e2f48f06fb988367c2c40a0d8111bb04b260fe44ec6b", + "0x6051d77e0596a911bce132c4bc12be2ae5cf29d113dd52a41b3bc166861149ce", + "0x92c049df5ddb238644015d4e039e169614ed1d926de070952f2407912906cb4b", + "0xa897567fc1ee9437f2876deb3de2b11b8fc00aa07340564031573f0351ec556d", + "0x3e54a8e15218db168960d28369003cdb1a76f8db19384e9e2696ae66a6693d6e", + "0xc5db7ade97cf28f8b61f2c63a0773201ba64f37dadc19c03943b6772aa7a1a50", + "0xda784d1bf64b7efd06558b90cd2436f3e61dc0f7a8370ff92516ed062f461091", + "0xa1d10b0a36ec5169d2df740878d051bf4d38ebc5dc04ae5558daaabc2bfa1471", + "0xcc89a8be2ff74a7bb9e967cfea3cac067aa84cc455a2fdd5449577b52a2b4ff3", + "0xbd23a3e6d3198d81d798c2851c36b954fa6f359bc8fc6e04a0b757e3d0ba053a", + "0x74640f825b9d9f95be69763845aaa0269d3a6ed5aaec88bfd9b5c4139ba7ef41", + "0xc01a29e41af3cc0d0a13ea83f131f3e4828ec3e83dd2fdf9739c139938dfc2b3", + "0x832509e705972acc7efe91475e8d76ac00a12750e194847093825e6c4db9e83b", + "0x63139d1224766ada1318613b9ec5894308efa2473e809d9e37c8305c6965f2cc", + "0x76547e54dc59473093c3fcca1166307cc7d0f4f0e8a35d850507bec216b76476", + "0x3a6a14785272391982cfa690762f5b2aeccc1dc0bb13eab6b9fcfd056f40703a", + "0x603e32b52795c04416d800b6a936343aaaa09898fa97cadc2b157eeaaf3bd6f7", + "0xf241102a3d3f3a9fdc5a1a586b16fdce4280c6c6da04290541eb3cb9c28c7325", + "0x6db6de041bcc7c00104a21bbd487a1e1ddd5e4953f7a503aa992d68a8a7bbc43", + "0x8377d795c55eac07c0acca674e775ed7d8eea35867990c8a776f40965c9ddc68", + "0x48d62d562279641043e405f4d7fbd76050d773103871c5de2c8acc25992db502", + "0xa9ef42d314e15c419537e022753ab46d41318f1fa8784e4363494f395eb6d236", + "0x99572f567eb602a1d9839bd23b41562bb3782eccf9a8893e54b002e685ab378c", + "0xd8cf2fa2291efed46c1a36e1b8837be62e86caacc380aa6397792ae8baf8f3a1", + "0xed2e800df1acb7bba5ee6251592c397a604debd7b0bfc28c8b0002dc40faa8bf", + "0x9ccece195d9e67e318f6d2952bca9486d09f4207c6d8be266cc0eebe41290920", + "0xb20580a5c96c25bb59e1bae6ced3ea5cb69d903f64e648bcb38b799141b3cd5b", + "0x1488647e697452306d2744ca6c709007cf75e2e37da3c7c05006211ba0720824", + "0x009c3dfc5494962c77900fb8da67d7bf2a2f4b855c521b9d50c4aafb1e0735bb", + "0x482428835dfff3ee1da335b36ba3aa1969fa35e89150e5b3c1991f28272d14f5", + "0x6a972044f2076e98833b243c9ed18162d96b46823170ef7c20b1a02d8bbd48c5", + "0x676242effe0fae84110c4933beecfe5ff549b439e54ff5a588add229329e5365", + "0x2441bce77589ebf8019fa8ae870a8529479c6eaa0fed7e0fbd3cc7439dbd4a09", + "0x0b20c25d2c6897c1a8dc9ea1364d3c72d33c97b4d70b9176c3f0a1e3b6ce08a7", + "0x685aa4e279118f8326a90c78e9896e40d9baa62144e2425887dcc704106979c3", + "0xabcab60973f6bc9ec3b596452e7434c4dc89c55c8eea925fc0092d1103c6f86b", + "0xcbf44f106f3f2c0050906b5e344ad22f0e0034067d35402d447311d254516dd0", + "0xcaa67796a8ac69283d7b6304181a988992130ad8441d47b4fdaf236686dc1caa", + "0xad06e6db230bd0bfaa0df59d1ae517ced29d5f11b34f76ef9bb6a73407128b59", + "0x93ef56a4951e4e5c19230918b1219c1f07e9356363503c1410e71486ed338f87", + "0xc6fef02b5bdd4909906c40cf5b999fe9e08e4c0d8bfe59d3c9aa99011136f780", + "0xfed633749700ffdeb0921a537a215ae31c25b85e4f80727376e50c247b4c5a38", + "0xc39d8cc15f4331fb7db2c24ee1163bd164e81ad2ebc43271f841fb25d03835c6", + "0xb13962dcb364ee49e2d0a34dd1a555fa8df363041504ef1e987ce78646d64146", + "0x97e0d3047e2151d53cbd1358da627453558362c6a830910b33f241848b20cffc", + "0x587ea98cbd1da50c0af1986f6ee5e676658c06442e893304708db831fec8e804", + "0x0a1d21212d9bd85a1a39e046c897d1dafb496bfd80762beda2fd3eb1cdc72eb9", + "0x46aad83612f04e7a51fd642de742f713601992e58de4daf24148a3e6f3318aa2", + "0xa65a8a9ed4fb28fcab6ee3af5df4647083c2e735fc652568759fe0426e9a294e", + "0xacd7ed5525cad187f053ba98487cc4abf24f76c8c0e97e71a696d553a3a41b7f", + "0xdcbdcfbaee764bb404bfa5261b5037b9c7ce567a3c1aa9f7280071990320da18", + "0xf195aae79a232b2170a98602efaa2efbdebb3c40d2438e63bf0954e4dc779cb0", + "0xfbb2675a62e2e67baf85e56fcd4cdf2bf89ff7905952155d3cfd4e625fb674d9", + "0x5b955473a35f6b0d24fa8be8009734ecee62f6c4bcf0cafc2335f07c51752fb1", + "0x66f37b268338f4ba1e21eef6884aef245bc36935be1f5eb14ee1d23618f00f5b", + "0xaab809ee86773263043201b83bd445d98a634d8a6da4c389b2336f68381dd481", + "0x509fc38118491458e45c7e8ab1d60c687f50d85fc1c0bf104b531a3b352198ea", + "0x20d1e4f38e83b27b77d55281af40e9f96be098fdbb90730170638c88ab7e435a", + "0xb33711864d62709a98f81d9c5f0a301bd5808d0e8ecef1063c97347af754c8c2", + "0xd69fd6c0fea478bb380b948f5b054f91831cf26d304991d40ebdf0b00a97503c", + "0x87157d452bf57e617ac1dd2372438b0777b83f6087d8223008d823652c634882", + "0x9c54b0172ae0223e6b23f7e000cb6887144e615efb02c74596002dc26d43eb5c", + "0x5b0f87baa8e40f0a2bbc1a76afbe0b21b5e8aae1443f0d38c3ac55c5f942db42", + "0xeb68d93e19860fb9fb76847080edc345972e29ab1ffd417ae5727d3cec79c0eb", + "0xd27026033bba2557c79c4babaf669a399fbc72a2a5cc06c707e24eaacee83bce", + "0x420d887bd82cccac29711c52f4d362b6a7d854e694f8d597d208d0a094fbad8e", + "0x02ff085c6c3c47879a91f511ea4c54a214af8160e07dce8e82a6be9e8299e237", + "0x1f0384e0afaf47ba59aff9f224905950768674c48de0fb0312749b16edb0a347", + "0x55cefaac814e132ff335882a366ea6173bc21fa713e93d8ad92260c84cfd2d85", + "0x58a8dd6e036a05a937a7053be916c0e7f719f2a1905186e7586a9d2dafd5a1a4", + "0x8714d03549461e32a467cefdad60a96788c97172db05c18eb9debf6e6a4d39e8", + "0xd141656c1f57c12feed31dbff3817e1d2af4e1b5cf6aa75d1bb29ea2c0a3ae69", + "0x5ec365177e19fca3c1063e65a9342008aff04ba9d03d53837b598b143504b97a", + "0xc620e23ae73d423bf2628a3de70b1a1f915d80173e0c8d1443a44b91400c5a8a", + "0xc72c2356ed53eae5a4a56bc248d9d2f4e9154f1404780b84781f357cbc7ad2d2", + "0xe60bfe30e5a1a9457ccca65810675e129948b474f391ce64d270200be7ea6beb", + "0xf679887baad8f8e497d60b015156f194b94fc30c6cb1f83fbc4575e99b95a8d5", + "0x654463146799fcfa18a74ffe4f2423fa04c8747c16b789dd24da26d0338d381c", + "0xe8b5406278d9e4622d088976af8b5e6b14cc146a9530c862a42fa5566a247355", + "0x8ecb4735132f769663781f96fb531115190e68390c54e33b250db874e90aebaa", + "0xef13bf38c2ba993c9dea5777e5db348339273d0e6dd1f41867d3b258f24ac4d4", + "0xbbbbeedf7276a857c513f4ebce88e3b531c99cf206eacd1c6c29d3cabab45df4", + "0x89cd50cde2de3ef40de7502241b78e664de53dd4a5e2ed85db62c55be0a4d8a4", + "0x0da2cae061e7dff539c7e39b0b9f63af3217f1a51bc597db957b6a3972cf7186", + "0x57aa87a6daab3c65519de7c1c1360ab33b830d46f169d4e0d3c38e7dadef289b", + "0x85fb1241c4110b4f3a6c197450af8ac47bb24d531219f6cefcc079717b208c84", + "0x52194cfba6bd7d5eb8b438054fbaf5fef387cdb8b1a7ebafe44cdcf4da47b1dd", + "0x7d24eb47a1310f7f4244e825847f634fd4a4224f695a3609c5250dc6052de6d4", + "0x38edeacb93b10653624f77dc05063499daa770b74d6b63ebe656be5a3630b7b8", + "0x4e050f7b9d73c1aea3ce60c8eae8e46b55b6d4c1cd1eae22faf982895871dcd1", + "0xf22b284ed4d97b7d3553600388748721a328052daaf92a58ed5403fd4020a496", + "0xc5fcf858d9a9748045fa0ca1271ba5af780a788c51d693815e0490671be3885b", + "0x2342efdb88226e68173ef84060a0d4dc6c8aa9c9431883beef4a5588f3157fae", + "0xe1599bf452eaacb8dcd51ff835a9ef5761dbce83cfc719813d6a10772ca5fdb3", + "0xb754797393b3216778ea6389361ca5951f365ae4e7ed99ed4cd4c9c76ff442d3", + "0x3fb5f9f3754764155296c6ff4c469109512264c603ece7c78c1231942bb8ac35", + "0xbb347d23c7d703cd2801e2763f1a6c375b5cb2a666ba137c4d6442c3f94688dc", + "0xed3806645b55fd7027dfb7f5f796933049ae558d26ca695a01e1b11333f5e453", + "0xeadb7740432ede4f90c0bc490c15fb377b68de0fc1ee3a56e87e21e7771211fe", + "0xa8c0e907e0b544e7fc3116d47e4cdfc8e8688f5cc4a67cdf600f74be6b79775a", + "0xc6f6b94f2fb4c56066e3c722123b8e85f80ce8baa0427b62c5a2ff937702c481", + "0xfff0b94553a7daaee58a7e15daf9845d1a3ad4917d81d4f23dad27d0262b48ec", + "0xb9084676613e1a063c2b491bef1b984acfbd2dce60a8ed970688239524e31962", + "0x196af717eab2cf09b47db13605ca4864cb0c4189d40c9b618d8a7d3f92831d78", + "0x4fac369653dcfe74d86b7422354d68f7580b1ae0ab359a8b8f8be8582590ea7a", + "0x035ff04f84478354706945480266321d31790f5445028f3e964801fd9a16c78c", + "0x63df70a24370a408bffabbe1c7a4c9b9e40be1cb326ab10d63fe54bb9de50d34", + "0x37b5c558d31128595425ca68deddf5ae7539abc6da838837eb1e0457e092d9ea", + "0x41a9ce82ab27afbc84669368c2e75a15e6386b77034ec316795a896ef9de577d", + "0x08bc6cc18842df4130280823f7676f418f4797d3ddfc544e54267e6456cfac68", + "0xeabc09ffceeb35cc4ec18518d4920bea2f43bf746f23b5524fa405bd874e9d34", + "0x40336744dcfe6f312e17eea83f53538f9999864c41bec43576cfcbef68d12e7d", + "0x3e780dc9c8f2b708527f1eebca75d18507e00e226a00e1b1ddd0b715aa8dd561", + "0xfd6a3c50c4a4d6e1a6fe27fa96f6aa2654573cbb9b839ce8e09a75993e2bf8e5", + "0x166c03d381d6ab94666099024adc95de0ecc9818e5ceb49965767682ca0c73fe", + "0x9805810b802a51a3ae18ce44f6b2c68abfccef2119df2430e4693e291059e222", + "0x353ecd1a0922e819ffdcd634385ebbdb674d247c4fe75e2d5437b659c98424a4", + "0xe75fb8682b706ed6596699d6151db4dcb19f6e71a3b6e34aabc3508c919f5c17", + "0x6e9bab64b10a2341f49e81d862ef3322d3117842e3f1aabc8b774c68484a2a31", + "0x82b5e79ee8d72c3613458c975530bcbba359734a4e9f07015686dfc521230329", + "0x86d48d57ccbe1f1986a4043748b1a0d8d76fd56bc74e7c48c6fd742affa0ee11", + "0x46ee65b9c2fa3e69aa1cd6ba5aaafa7f7aef59224098b60e22994996c927c9c4", + "0xb6983761b177e21899799410dc018f1acd3d417fe35943fbe57207f9f799a100", + "0x594057a8386db6e159d43d136c464c5e3980eae75a73900f7a84ba94803fc6c4", + "0x53c78073c4a4c44d17db85be06f38ab47ecbb7f36ffa87b9db707fd2bc87f391", + "0x4a976673044732e3e8a0987fc8f3c36375e3c4fb3722fcde5259af492ec458c7", + "0x1e2fc8db341a4d9e123ae4ff4f4d8096d8afef47c5d2915c665922bd1de3b00c", + "0x565cd8eb410c6e0b4d67b54d37ff42f6189095965896b0f81566ca502bea34e3", + "0x32d030e4ff6b2f5a560cb7525b5e66ab1f34a1e06531f9b81c48b8a257bd5637", + "0x25a91d756023bb9ae538034bd39b6e698d05fb1393d1328c4fc7e5c14209cce1", + "0x8036f74c4cbaff3bd98820ddd84bc093c95e88d357b341154a3189715225d068", + "0x8bc6bc61f7a57a145b8d728f583e027c8630f0c07e003b189f390ffd11d6f150", + "0xfbeb53fa167d067c9b0a2c0710f7f5931484f7dd90b9456c52c578a15f402d9b", + "0x8d355b208a16b8aa3f7bc5d8864dc7d6a1c4917a97c523274b86e82998d60b63", + "0xc94e45da800d7b56456d55a9aa36ddf9df45e9cfeeacb1116b8c51a0cea34ebd", + "0x81761ec04a8d219aedb2f58aee529e876043b0a476e771957bc03fef9f0780de", + "0x29264094c720151f7448cae053a403aa86fc20649bcf383517e214d1677e893e", + "0x9ac97c7eef9b69dcd73ec7144a0cddfbf0973791beed405202fb4c2d932ec59e", + "0x89611f8e2f9e2e1629f83ec14aaec1656876718c05088e5087887c87b8414c39", + "0x67244fcdba97905472631378fa3a228b649880c2efdd57e5a6c95e9b70ad8456", + "0x0d554cfc4df02560c3e76159d1964c69c39f5df9489bba5516f28a32a4be202e", + "0xce9274a36a0f25a13edef679a5b286bf91a9dc5274354bb6f1ce0ac52557e650", + "0x6017e68689d9f6dca78f42b93a224b445c18b70288a6e4c0d6cc295627dbb1b9", + "0x76791c90f887355878d0a4d8c84ec3990a3159933ecc8d868d196b363153bd5f", + "0xacb6a6c9ec937b3d5cedba26ab6d581fc41cf9a58b0867232e2c8c73d9978cc3", + "0x89f17989ef556a0562c2aa5a2a1d71e5132b89d656bead1ef88ad31073b80cd1", + "0x06efcf8dbadaf28ee719a5b9c017a093fde84a7f4b9966fe3052c0b2fe410ea6", + "0xce16909616f1d97e5853818938b4798030259ddd41e3468f35b940ca901d6817", + "0xd3ff9e9ad14a605a94bdf05dd2639b6fbda28ccf7b2b228f064b0de52410df5b", + "0xb3e8ca9ee88d4c3ce347d82e8f22793ba22b7adc350fd694b1b00b0764c584f9", + "0xe690268a4ec089aced00f9654aa95acb7a8d7270d9428205b103c30a08d142eb", + "0xd685e1460799c51f14273361e31b9739e5212fa538fb8dfbb8e81e8b1d329bbe", + "0x664c293680fb7c5a89ff3c31e81ec8d0c30a6274ef44e4e76bdb9bba83f3c0b3", + "0x44027fd23526685d920d37b032f912159e308286eaac018244006690b4191d4e", + "0x7ea934c3d75a9ecb6a2055dcd5feaf2d4c851eaf360a648d5d87ef40fba2fbd0", + "0xfd97fc801315e5be630ccb3dc983c409a58fc1fc307adc1e4a48fc60c89ea40f", + "0x15aa0c3c732a2c6684d521729dfeb93f62e22e155d85d20e5488e2c86b043142", + "0xba235420ac54100da28cd6f30ff64b8594e73c42f45ca8494fb3d3c4d66651a9", + "0x9948e8489cd94bed4b8e90a8bd35e01ffe38e7c077f587c6c1949caa99cc98e0", + "0xcf66ccdfa85655d7d4c94cffd41f499afdfa2bbddcdaac547223e6ac4d1f9cf1", + "0x7e5382881f710530720b420a3f3ac08211565ecc8fead8ec649cea11f9385c3d", + "0x104576fbb1760c16ce85c3e5757832d53bda83d618500ef677a6a192ff14a5fb", + "0x9e4689bb1ee34635e1106e38ca41833d2dbc1cfacb7635ede5761048a8637c7c", + "0xc8c7f7ac271015da443320f4af650fc71ea0914f4c41252a5b7ec76f329d5268", + "0x46a93ae992001a54119c8d27788e3ef8927dee0a9949b22ece0196a90932c1da", + "0xa69467f9944f1a5e3a46718a99d3cb14930cab6d971baa37bb774cc757e55c2b", + "0x33f7272fdbfb91428a1344df5867300e256fc3cc2e439c777c3feae1cb27b781", + "0x0aaa367f4c7f399edc64ac1754f47aa5c28b0fa208238276de6bd9e424021ce3", + "0xf5f363c3bfa4a23bf221951f4b53a77b27613938babe40f0832d05fdfd252233", + "0xec315af99bdfdcb3cab1f1dcaa5b42ef53f4e3fcf4d921578892a5896fa20e9c", + "0xb580a8e51e875446d7096a20801dded1f7e5b5fac9f47e9361dfc9dd80214013", + "0xb877df38d8f4cebdfb89f26868bdb97ef945da187b44e1cbeafc1d4b7059d713", + "0x78613b9d2d6b639a54ecf1d50a56af80560b436fa632ae636cf354d4a6dd4af8", + "0x80a9d0a5e43558f1d24256baa6940c0074fa84d4b8e7e236054943f9ad5fbe2b", + "0x60f79f699ba1a740c9784f2a8f1b652d4e695ad2d230b110472b95914fd35c8d", + "0xae20de288eb7362a36a1ff236faaed6ddaacf58783d098118bc9fe66b8780651", + "0xcd08003531d6094cabdbe4d971a01b41552784c246bd2a2f749ee9947d1394d6", + "0x676720accf739c380f64748390c1acd2f88d454539866f7326a517c9b629b545", + "0x086b71ac681c0ea369c16b22ca49753b2083ec25b46ba659206433eb060d98c3", + "0x78910ab7d67e67da722ad53b669d8c3a312de3cf362c6254c09581088e920acb", + "0x5bc6e98a830c114cb432091679ac5b3efd25c362d6f99585ce3a027dff95e524", + "0x8d0daff5a97327b615d1535fea44fa33610fd645d93035e1e5e2bb49d4dcef24", + "0xbb46662b884bc6676d98ebf3f2a35ff9190339b72d68520fe40100b4eafaa2a2", + "0x9aa8faaf935c95a60ffae0487844860084a963792ae0bb90a831f825339810ac", + "0xfd77b5d6b6b87bfb0ddcad7b0ed3992e5fe897b16db06b118230b2d292e317e9", + "0xc465a3384c694bc50cbe97ce9f3bc364884651a97a491f7f64e65dc319d1c9f0", + "0xc4634431867d7a302be79e83fb50d01df7f3b950aeede21fcb59b883399b06e4", + "0xfd524c29525cb97a89026ff68048ca6e2a9f522791eadd74447a6c278151d7df", + "0xc7df516c295a58cf4cd5614eee3d2f773a412dcd4926eadad7e935ecae6d8907", + "0xfb915abde0108d6e84354e21a513fa564f5201277e060bb916a9153537fba1f7", + "0x1d3c6a780f1b259e096f4a141ab83cb6bd035407421e2468e743daec211e536f", + "0xb2f47534f060c70f61a7c16f920d0e11b957bb3ef912ed9292f35b8ceda2acea", + "0x03e0ebe6e9992f6921362d463b68f91518d91079c001c6bea7b3452879fdc29c", + "0xd9a7de173a1617ad813a554a56d7c7d2f010ac78d7782e524b35b5c676cb72dc", + "0x90d05d99167e53d34a02c5b66ed6920190370656905465f20efe56499aa0ba6b", + "0x17702606dc895aae35aef034fddf8f7235efcc66e5c9d252347063209c2177b0", + "0x3c416492193d81fc03b5c1964989a314e5ee6d689c638c996f6761b4d7acd6be", + "0x3c6c1162ea9b277f831989ea26e14bb23ce4d72bb9c865e354992559266ceb16", + "0x96de93f849613bb2ffc117bf111d4798b9252649f94f21187da324a3fe363833", + "0x91e50fc6e564cb9d6b7aab3a6e93f6b32944d5a781196a9a8b12ac7f6f527565", + "0xdbefa2bb2ee620d75295d0f3103e06b428f955dba1a792421e435051c46f7933", + "0x78f29df98ef7dce9fe7b4414da90fb4df5d99231ab0a3b7a3e70659986580fe4", + "0x56cf56899c2388d55eb1496ccbe62041d14cf655c9dbc53984d86c22ed281acd", + "0x099f52c675171088550a9e93e1ab17f003190fa3388d956724d422e5925c4813", + "0x9913e4ad8405b8a60fa512fb616c544c6cdc415cb1023aad0669d58cc3810161", + "0xbf5d51369b2510bb57f8fc8e9342890e8bb37049079dc79ab97afc0bcbf3cbf2", + "0x3a012d45d250c818b641fb18b71b622f5bdf0b7a541e0d8de54f61e516ee3ce7", + "0x0233833414d2cff3da0326f7baccf1bd522db5fee290ab4fc0a976934a20358e", + "0x38a0978c955f20cdc32e2013a5373efbfc50924e45e9c4c756291a903f4162b4", + "0x4107f33a14052662a0469ddd646ab6659006df131c4b0f6b0e6cfd331b46fea2", + "0x8074fb5054c755c912bc68b1dc22ae40ba13c06912c8af1c12652eb4d84c6503", + "0xf6d151b8f9c26c3a31366d967dd7338e80e8107b9b81da0a98faf16df9cbc91a", + "0xcebb0256d0a8a4b22d2341ec7c48292c3226caf4aeaa2003ee36dde25cff833b", + "0x5fa9ac499a2642b0cb7ca365062c02588f9c555bcdf584f533ee8e8544b9928d", + "0x800c7f04db30247318b8d4c11d575dca66bf615674fbeb9e8c20f387d907c8e2", + "0xb0a43de06c9d48afefd5411d759e3c6293cbea4a7c6d862b119182ea02af81b7", + "0xb6e7ca0075d28959cf87d716fea885e9e3a0062fc7da1b6e06089c808a632b8a", + "0x734c1b19f0b5972b5215f675cf60c68c12cf6d6bda7b5a95ee9a781482e68365", + "0x1995b08fffb20dedbef592ac23a81d87129ceb396e065265dd4a6cb876beaf09", + "0x051082047a6b579684b5444ce5b75bc630277ec06b0087779387b9d7fcd18fec", + "0x4aabfe145c368e6878e2ccbdfbecf2f1db5c9078650696bb3a584c14fe17177f", + "0x42811ab68b304ce30fe896c52b53d861abc3c8b5e4e740fa97b1695db9a6691f", + "0xd90cdb12ad64f86b2aa7afb781c00301f50206b05f1543b111c2b971ed209c94", + "0x385435507c2ef42b5f1760b97497e8a02a4b5ec4926c3cce8569fc0f4be59ce8", + "0x2d7a4908350c9cf022920cc51e0cad9c3c05d1d14a92d72310b52f984c857101", + "0xceea9c58106f4f806a256f64dc04e1c4b53e6cc5eb048f3df7a14f8de3506e96", + "0x7032f864eb3eae8d198c3f8edd9cc2dfe88b9971cd01b33318dcba004f9b044b", + "0x71bfeb4c183b20fba60e225524c809b0864fa14f5c0137accc36649ed0712e5c", + "0xef0ec5a2761c46827110c20e14fc4aecadc2407541ea046de09a58cda3b2e839", + "0x5e6debf328055c9413fc3eeca28583f917b361a5b5bda9af4306929931a4116a", + "0x1aab81df07eab969189333e5b2930fcc1b88a525ec5bc6af6626fdcb202b8f34", + "0xbdbf97e1558711d4872821b9400e03a811c61096bb838d3126b1c2154f8fb776", + "0x7d8aaee482933ffaa97777af3e4bf69ce7d99afb24e546d2e365d445d3d0190d", + "0x9da421621b14164582b2b877090c9a956f3a7c917031bf743a9ce457b6292369", + "0x050d717f0433a72b17a0e9a1340f26aed5bf17f90c08a5b73e675860ac9c24de", + "0x80551d3ff835aaf987b9ec056a73a3890985ef551431daa9d4aca10c81cac7fd", + "0x625a5b5aed2660d32d2fd8c4d1bfc248365a5cddaf9b5695e3f131629739ec60", + "0x7d86bc2dc5914d16b3d0d882a5db0230b4b688cbd8c81098d2efc5080e589646", + "0xfe42cd832cdffe56426031ba7d837c56d86be72b89ca9f5474bd08db80cfe903", + "0x0ca30e1fd3bf3e16a0e295ecbb442757248b2ad47baf88fc37d6c55901e709f6", + "0x2a83ed111b99844e17fb7aa69854525958255ffea04e0bfdc365264e72b349db", + "0x709779de19590b69864f5b9228b3a1c334724e20be006ef5ae38f8c05eb6f37e", + "0xf09c664d0e2e88ad5418d14481fefdc9e9c46158bc5439ffe0bf6d6d5ecb2eda", + "0xf350785dd3617ef73b0a5bf439ce5c49adca0c041b6b5047a664e5e33967ddf7", + "0x8fcf87571154dc4eb0a73c6ee31cc0db5f4e064cf23a255a408b2f2c7cc9c0e9", + "0x75801fc8867ce7c75b3148c6c022d7702143b93d93c1fc2349e3e969d0179cae", + "0xf14c18bf68ae881d3fb07f631340b00557a83860d0ba0efbfe55fe199176aff6", + "0xbe48c727fb6a32242229eaa09146c76522dcf6bed6d1c6fc1bebf86b5e4ccdb4", + "0x8487b971e383272df82cd812a0bf3a2026b85bc3897b4ce9ce48afa00849fe00", + "0x60d18b465172f59c0d71594b5273a90cb41db24a5d4c9fc37020f9d8c467a4a2", + "0xab4e36d9f17c748c87d89c23b667e3f4e3265e77b62dbd9c92659026f8a53d12" ] }, "accounts": { diff --git a/ethcore/res/ethereum/mcip3_test.json b/ethcore/res/ethereum/mcip3_test.json index 391a62573..d24164dcf 100644 --- a/ethcore/res/ethereum/mcip3_test.json +++ b/ethcore/res/ethereum/mcip3_test.json @@ -33,7 +33,6 @@ "eip160Transition":"0x7fffffffffffff", "eip161abcTransition":"0x7fffffffffffff", "eip161dTransition":"0x7fffffffffffff", - "eip86Transition":"0x7fffffffffffff", "eip98Transition":"0x7fffffffffffff", "eip140Transition":"0x7fffffffffffff", "eip155Transition":"0x7fffffffffffff", diff --git a/ethcore/res/ethereum/mcip6_byz.json b/ethcore/res/ethereum/mcip6_byz.json index a12df7c71..45aef8b4b 100644 --- a/ethcore/res/ethereum/mcip6_byz.json +++ b/ethcore/res/ethereum/mcip6_byz.json @@ -33,7 +33,6 @@ "eip160Transition":"0x7fffffffffffff", "eip161abcTransition":"0x7fffffffffffff", "eip161dTransition":"0x7fffffffffffff", - "eip86Transition":"0x7fffffffffffff", "eip98Transition":"0x7fffffffffffff", "eip140Transition":"0x2a", "eip155Transition":"0x2a", diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index b61799c0c..5cff465f8 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -31,8 +31,7 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": 1915000, - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/musicoin.json b/ethcore/res/ethereum/musicoin.json index 724f11478..91c176cf4 100644 --- a/ethcore/res/ethereum/musicoin.json +++ b/ethcore/res/ethereum/musicoin.json @@ -33,7 +33,6 @@ "eip160Transition":"0x21e88e", "eip161abcTransition":"0x21e88e", "eip161dTransition":"0x21e88e", - "eip86Transition":"0x7fffffffffffff", "eip98Transition":"0x7fffffffffffff", "eip140Transition":"0x21e88e", "eip155Transition":"0x21e88e", diff --git a/ethcore/res/ethereum/olympic.json b/ethcore/res/ethereum/olympic.json index 3ae9baddf..274e8c23a 100644 --- a/ethcore/res/ethereum/olympic.json +++ b/ethcore/res/ethereum/olympic.json @@ -23,7 +23,6 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip155Transition": "0x7fffffffffffffff" }, "genesis": { diff --git a/ethcore/res/ethereum/poacore.json b/ethcore/res/ethereum/poacore.json index b80b3a113..115108f27 100644 --- a/ethcore/res/ethereum/poacore.json +++ b/ethcore/res/ethereum/poacore.json @@ -15,9 +15,14 @@ }, "772000": { "safeContract": "0x83451c8bc04d4ee9745ccc58edfab88037bc48cc" + }, + "5329160": { + "safeContract": "0xa105Db0e6671C7B5f4f350ff1Af6460E6C696e71" } } - } + }, + "blockRewardContractAddress": "0x4d0153D434384128D17243409e02fca1B3EE21D6", + "blockRewardContractTransition": 5761140 } } }, diff --git a/ethcore/res/ethereum/ropsten.json b/ethcore/res/ethereum/ropsten.json index bdf44fe83..cf418af19 100644 --- a/ethcore/res/ethereum/ropsten.json +++ b/ethcore/res/ethereum/ropsten.json @@ -9,9 +9,11 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "homesteadTransition": 0, - "eip649Reward": "0x29A2241AF62C0000", "eip100bTransition": 1700000, - "eip649Transition": 1700000 + "eip649Transition": 1700000, + "eip649Reward": "0x29A2241AF62C0000", + "eip1234Transition": 4230000, + "eip1234Reward": "0x1BC16D674EC80000" } } }, @@ -32,11 +34,14 @@ "eip161dTransition": 10, "eip155Transition": 10, "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "eip140Transition": 1700000, "eip211Transition": 1700000, "eip214Transition": 1700000, - "eip658Transition": 1700000 + "eip658Transition": 1700000, + "eip145Transition": 4230000, + "eip1014Transition": 4230000, + "eip1052Transition": 4230000, + "eip1283Transition": 4230000 }, "genesis": { "seal": { @@ -53,8 +58,8 @@ "gasLimit": "0x1000000" }, "hardcodedSync":{ - "header": "f9020fa0a415a8dcd55fe9c93372da415ff6897036e48cd3c1a5ff8ffe119eea1096ecd6a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479443d58f2096e015db88e44346e73d8c59cb1753bda0100f05d66d36782b7c061c724d8d07619cc61053eda41badc8d2cb9292898ebaa00a60317b490365f40f0528e1f559b0f49facb6638c82a9490d368e963647c704a0118b536c3bdabf90273d527dfc26914c7878176fff16cee8fbb150e00ffcdd29b9010000000000000000040000002040000000000000000000000000000000000000000040020000000000010800000000000010000000000200000800000000600400000000080100c000004002080000000045000000008000080000000020000200404010010200010004000000000008020000008000000000000000108010440000800080000400010000080010820008000410800000100000000000000000000240244000000010000000000010010000000000002000000000000000000004000000020000001000002000000000000000013000000100000800008000200000104000000000000080000080200402010000000000000000001020000008008501602a8414833bc8018347b7a983476d40845b838083904d696e656420627920416e74506f6f6ca0f540bc9cfa258b97576bfb9a79518b2c07ed73a98bc6baa61cf7af4b40ad5b6988965658a406315a8a", - "totalDifficulty": "9811143388018700", + "header": "f90217a00f0e017311206b97b47403eba05a16ada760a691a36f844ab8bc9082a4efedc9a067baeee20ae4f4216ab4b0c41198efd376aca23e44b1d6575c5949955547b72a946a9ecfa04e99726ec105517ac7ae1aba550bea6ca0e64d4fe9bee34d98e127f7f94f17535582d5bc6eeb6219f323b046b9a98c72b5a02d33ce5daab0436707c6d958dcf0bcd311ec7a72d7b33c20784178d5d95bc6e9a0a5b9cd4802fafaa9381ec0aa745cdb7ac953675e9df89474e5fe14fee134cf87b90100000008018000100000000000800000010000000050004000800000800014200010000001000000000001009001000000000000000000000000000000006004020600000000200001000108088002260441000020204000000000000000000280000000000200010001000000041008002000000004004c000000001000000000008000000000000800000400000201000000044001145000000000000001000a0200c04000a00010080100000020000000400002040000000000040000000040200001020000401000000800080080000400010000000200000008020020200000101000000000100400000000004400010020000200000000000001000000008453461c8683402001837a1200832c5216845bbd359199d88301080f846765746888676f312e31302e31856c696e7578a0c1da176f6642888b4369e14349ca7dc125ef7d4f5f7abad61bd7f6b95bfd46bf887d1a171a9f55dd67", + "totalDifficulty": "12027449412394243", "CHTs": [ "0x614648fc0a459451850bdfe353a932b5ff824e1b568478394f78b3ed5427e37a", "0x1eae561c582dbb7f4e041998e084e165d0332c915d3a6da367638a8d24f3fafc", @@ -1968,7 +1973,146 @@ "0xb652952de1bf9e1174e5f6a37b069b437792672a37a9e0159c4f36b6e64306b4", "0xb72dd6cb5df1b00dbbd84e097e2da79af2ce60559697ab4c93b0a8b85b2ee406", "0xb96fd4a94ac30c10f757691f7f06f25a4900fe424f4eb7ccf322e2f95249b914", - "0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8" + "0x99fd442599036f161ccef1ae8088c5ef694c1819f5b76d9d2fa8f979935f69f8", + "0x3e53574f6ae31a45ef928f9c37bea6c61e6d728a5ade9851567d3167f5ca3314", + "0xd7e3d08c5b71a7ad8338e8b51ec54cb11ad4d643d129a371af07376f8c47c1d4", + "0x1033c8aed4ec46377f75cc9a6b3297e1da0a7d1e74df20bae9fdf6d037afdc28", + "0x924d621544f3301f9e212fbb95872fce9eb4a4172a11693674de733bfc2b0018", + "0x7f61884149ea4def1444a70c022da1c23f31ecc51bb175905b492236a57c7fde", + "0x40c50785bc0665ab4eb3cec95405e17510c571570a5859ead804530dbcbd1387", + "0xf806491cf778f4796c0f73428e6eaf237da8488af99e9b61d72c56fa03e7051c", + "0x7a9670842dcb12c66f11e357a84849cee227ea5a7351e7c6c9370e9ef2560129", + "0x1c974da4e1073157c10deac8b256c8ced77a030e0500b2b8a90b6ca1d32ab4fa", + "0x97ebcc81ba9c1e04865ee4617daa967dec39f65501be21fbbe929db869d57dd8", + "0xa36e4506065d8b9c662697b18ffe50ed2f6ccfe6d07a065bdad048778cc53668", + "0xb9d5566eb0d40bbb03114d333d1d1dc85b0e780ec63229f3b93b2c84af5f9509", + "0xcd16693573724880c3c83834d516be65c35a861b76b43878e28aa7fcbc961361", + "0x4f60ecd7811acc087fc4557fdfaa1a0b522fe30da1cbae5e7740eec3cff04c00", + "0x9e58573b152bf5008e0ea3fc0d64573211916521a62fb08ba0f1b44c5da12e7d", + "0x2c6693cfd7e5bf9a3d8cef9e186b3da25d07af983564ced6238f9191b020f105", + "0x8cc6149caeafef85ec7b2456f33530459c52b30a5365a2a0022b1c308357f7b4", + "0x6f66863bd9909f687523128569cd0894c4cf41e2eddd5cd9c20d30c446b1711b", + "0x402317752053e7b6d7e2d5512d6397112d80ace0873f5f9d32c023a402ec03b3", + "0x2fcd50a79495057908bd34875e3531e6298488f0d06d043fb6fb0b140895d379", + "0x533ba9669dcee2c6e35713c7eca3bca168a326a36b0e39fcde76cbd35ab3d99d", + "0xdc2e86503e8066bc5fac91fe63544e33568a3c744967b9360458101c3d9df096", + "0xf994b38ba312d8bfb00d428b13a088738d93965b525eae81b45b9be344f99fd2", + "0x0721f3f772958d6a58dba638453b8d004e0c76dc8b4cf6d595b712edddcf002f", + "0x3c650c2c7ebbe7879a15882c3157552e8ae1adebea8f0c65a2dda272cc4ed838", + "0x649fe38e87546703245a7adf5925e8c7a07942750e14d39553a56ca3fcbd8c65", + "0xad204bf42d2a444faa864df8e9d023483a6b6daaa8001e00bb5373a45ed064a3", + "0x2c5cdc73d8ddef2e5c0d47358ac180043e7e246e590a7e8ad2b0a3f9b4e9375d", + "0xf38f6c364bbbbe626e849ca9bb9324c54cf0ba8dfc0b2741a3ff87ce7734adbc", + "0x317efc1cea774849d6219d31c8464a15956da4f3810bf15d4353443f79d98e75", + "0xb6796dccdf4d3cab16b5ec9567237cb988ee94131f3262c2a581180b775e76de", + "0x1fde3fdf2303d080d400c43345a424f50f6551a6a06ad50c6e277d49e8034df3", + "0x4d7bc44a3b56f5e69fd3e5e8c0cd8f5f839a775c4ee381b4b1d0a36656cf91cc", + "0x6051b60fdced0c51aa6a1cab2418c8f21c5d174109d514a4c6de758b2056611b", + "0x3c2f7be830078af3c2c6d1557b3da74d1d5bbfd8094f98886a959aa71ce70b15", + "0x8f296b90a0ece0a3dbec19a801072497c5840f9c0491062cd402db00c2b69f2a", + "0x6c14c4697f8291dbdfdbfea5522798e3f8b17204f80d8370e6d379e6ee659e77", + "0x4e98f63afaa50f8a30b0d352eb5fcb5403c635cf54b41545aa8b48465d23fb1d", + "0xad3059433e981ff12cd0d7dbc11a8d92a65cb39c6e936e9c7db5934d45806492", + "0x1cbb21f28ad2d191d6850c97487e5a733306f2f6ba370723fd5ed37cf6c880a0", + "0x82a0010a1b20d383bff0e5d7ba3751bc0d9161a4817554432558c5c2825babb3", + "0x33e54e93443e87c003d582dc51d0b9981ddcaeac4df0993877739651cbf52a58", + "0x1de8bc150f4142cd45b5d0784e5952abd8de7cba9654af959498c0fd0bcac404", + "0x3ee852f48a1a930d671e53c9c8d8c3c38353ee1737c093960c3f841e6c682e94", + "0xa9c6e05ec91e2a2f2f003419063fe033e37e5353c6e233706e29c08693e35eb8", + "0x649f7328064c55c03249d527dadaedcdbb4cb0e939d94c866844192d99469e05", + "0x3a407d00efcd5fe7bb765347b1a3f231b744349269b3aeb44099f4bdd068eb9e", + "0xa1a20af2f7e61082810ce7e7afe6118bc0ad95e9641e6129027f46af28048107", + "0x0d68fc5e58cacb2d16d99a0e9e612d674754ea51cbee2c68a21f4b0aa926688c", + "0x9b3e58144c014343271c9dc90daa8d2f642954b3eda223d64bbb0ac41380e512", + "0xd3de08b676d4f06bbf4322ed4340caab76e6ab7144c97af91c2bc9c749e65b38", + "0x21d626c9c38087aac6262b64f09398be6e4cbf246100d8c2416cab57e9ac1b68", + "0x563a450e35f40279f5946641a823f596ef3ad22a45b8ec280128546aeb0faf14", + "0xadd9c7128e14e670c7d21d6dfa5c09a11dfd237e90709b087e3329d3cd89b5fd", + "0x258cc0f845d8e7438a707f590f55203c6c51302cef4cfbf788b1c7054688da14", + "0x4309676aa14fa8244e0a089c7013b89c9adf57fa952295b8ddb23fc6545c9870", + "0x5db769765dfb41aefc0f40f06f3d005b30ce1f14f04f653e0c5500f651cd61cb", + "0xbef131c9f19572b05d295d7122fd1a09fe4a8afd4e20c5a0f3cd2785b7eb9882", + "0x3f235228ea537332a041ec75cc6cb5663edaa1c2ed1c1700273af73a5d49bf1c", + "0xc081811bb077c6ebe224b560eb6b81f3f813b26789cb06d96110071ffc25fcb4", + "0x912444c19a5e458b79c89969ed5336f2873267baf2fe729b6f218b74d269b797", + "0x5846fc726eb9627e9d070041b92d76191c4b32e315d33ad18121b8acd01634fd", + "0xc899f45494660034d343670856c13a32b230d047434a4d54a772132ddfe3e182", + "0x11a699c18b04e8cdcd96a43b7465f7bd81f8f64d7ebe79dcaf9201cc897f2746", + "0x8e09b134dc8a1735c060175e9688fd001974bf2e3baa5a8e88dc4c87365e0e07", + "0xa086797ebca0a1d446a9289b7eda920b926e1b595c288a9dea31ad225e6de86f", + "0x0cc04369b6036dff78a9856a5173bb2dde380359a8dbe0126e06d6e763a01c36", + "0x4b5efcac86e03d1f67774769b8bcc5d131c181cd4fa297eaa6cea5ec0cdfaa6f", + "0x47272a21a07ad5e14e3f97b237dab7e33344da4db5b2d31bc7cd0cc2d2c9f1db", + "0x9540755fd321d125b73cb6f1884c2f0b2a821d29362194f5029a5e7ba2d3ed44", + "0x229b88922fe52a78090673775f264cd665fe222002d6add2ed29b7ffd98de717", + "0x8fa2d755d5cc0efb01d9fd6f5ae1f7864404ae111d8ba17e23686ea9b6566336", + "0x33a8f2e0775fd19b1302b985bd6c29d4ab5fc63060bcf3df2c3685ab1b19ce67", + "0xf6d6bebb541ef9b84d779c62adb76774bb38a8eba3823e74e0790dc7401bebbc", + "0xa1f421108d49ed23996e55012613fc05e0f86e00f17251b1ff1e0824d35befc7", + "0x2cc572ed83dc6c604bb455ab050c550184a923f4b13815f06d10ef19dffb3c7a", + "0x28220e7d1a9583d68656f03ef4d6fa3e249c71d1b42698f87ba1fc582493e194", + "0xe8aa37b3214abb1bc167fdb6f10119a4019541f31c76b3b3f8c363bb138bd09e", + "0x825189c2c836dda454b457a03ff83d422bf78df1f368434768690fa7f51c57e0", + "0x5dad65d275e69478c81ecaec5b872660205735d9649ac020f65f5ea6ae972dda", + "0x84a1184d8f94fab280e0593479179348f9184d6fe5a2b2ea9697894c42574473", + "0xbef5a05bc7e1fb94465570144499672d95f31fa241b4c510011f6677e2bf72fb", + "0xd08235ebe6d79a8549bcd3d2414cd8afd2a3e2ca22ced226c60aacad1361ff89", + "0xbab5204ad45ec52860023e7474579e7c95397f3c4ac01db7e446e92c19dceef0", + "0x6c81acf2ff161d423a904c457166ff454ef41571d01e73d56bf9ab892790248d", + "0xaf4a603b808e3ddece42e3e123ea02defb9f8ef2546a95c5a617b6ecdb89c306", + "0xeecdbda25b04eb764e322d9a1e5eefad399c9ced8c77b1e4ecfbefcc90bb403d", + "0x9463f4677a2039ca372b61b16d5bcb7c043b26af04aea4d3f0dcdec7bd222070", + "0x27bfd92799b4cf9699d2bfcb158f6727bb986fc0dee780fc1052366ebc4e6364", + "0x63c3faa1a8fc0d531261cd241b1299d4fc13629abb4cd357eeb130505fbddf94", + "0x9a4535b07ff68862f3396b14b88fa07cff7abdd5744775aeeec6868606eb4712", + "0xae59e7c3e0a1df32f6e027da2983d3c55b4ba4d99e85329361561bd7f13ac629", + "0xcc5dc26b9be8fd8432537d967afe12fc668949e4fcf72d97a40f9214975fa57a", + "0x8f11634c83c7a43be8b98335ba617a64c6379f5f92664055c5e1620791134ddb", + "0x14ce2a69d844e6a46aa244c5aca9fb74c127f2151c7c16f4611ca030df365d8b", + "0xb06f220566a5e62570b9e9e49a8b9d5663501ba145b12260fbf9d4a18a4b19e3", + "0x6274f3cf553c45e6ba7ef644d75bf208e08a8c6325e336aefd35dda9cca3c4d2", + "0xd0d685497c2f2b923d0b9f1590a748da8c684a915a470db58c3105c83d8304e7", + "0xf37fab515f96e655f182f0b6e6aa3602f2cd74773329094772151e8c33d1f9a4", + "0xf6efd731481e8553f1d18b5735166499e787009b484b0dfbe4d35e7930f0d837", + "0xc96132b510863e553e08c54e98b5e9c0067f26e421980a6a3bfd4f07480c4396", + "0xdca9d8182c573871b6d6a184cb9819256398080bcb7fd765e6c69cd972a28d8d", + "0xd632ca6f5d45646726ecd2977ffea5c71a867890633f571b359657c0d096f840", + "0xfe3884dbca6bd3b0087466b04e6a5857ad59d7a25021e1d994d059d20005185b", + "0x7f40eb6fb94b05bb43873a98e9d4eb5f7ac90fb8913240bc0909c6be42922b30", + "0x5113a0808666815cfc52b8ed63c649d96f35c365def36ae623f536241b163c3f", + "0x8e6dbacfb5c593d7d7c2650d3d0115c3702cbb55f73011823a202e69ca33cc70", + "0x8f069ac7caa48bce09fe93f4aaef6784d8a6f7a3a09edb82c7512ec18acc3ab9", + "0xa5525e51fd789c59d3b208efffe09abca47cfd6981d36ab44084b86706c69888", + "0xcb4a7e60d5e8b9d22887ef1e8ce339cfcea0ae1fcbfa9adb766ad05d84182de7", + "0x0a14f23f9066ebdb67df31e66f6b8ab1c089025c0ba56ea56d15f73749f47cb7", + "0x0963e3eba12e41d21af7625b8dc487b637b1789a6ac05fb23062e0166942df68", + "0xcb7ec271b2f42cae0027d22b688b19b9288f2b5d9c43bc5b1ea23b35f5542828", + "0x9b97e6f4b2eeee29ecccf9584dc020c8caa3cae51c82f5b58d279eaf0c6ab4e3", + "0xad7f1963ce9993e6172c2ae90c6e1d4d3d3c52e14284fcc1b1e9a56776afb97e", + "0x52ef2ad7bc2921742dcbac9772f13d5c31be938eb1ad6aceb2fa8a163389cefa", + "0x369ead6d900e64ae0b5028df8574e59b67c61dca418c87ce6461eb4c8535fd30", + "0x7e1a18f6199f05f21f9eb5463e9ffd87637d2fd24a23047fe095895c533cb6a5", + "0xe1b8813a95e511aaec9b358d515e624fbc20e551c56328f843ae90b3c895d3a2", + "0xc2ea59f3d1e7bbe115390a4c210142fe9f9dcb1959764450f5b5292ad90e0fcf", + "0x97d235c3f18e6819c08dab4efe66d0f11f0d06f8ffc9686e3f28400e057e6f4a", + "0xea64f817770252b77b08ca2f579b440ec02e833fc88af7c9c96a8e1e07b2cb2c", + "0x185f5fd1f7001b533dc01783c83b7ab0828a4e2f188cc4e26768c515b4c421f6", + "0x0c9de9844e856a1e4340bf54dcaf9dc66b489304765b5c3c6ca20284f5a0dca6", + "0x4dd1d52da1d260d1f0f63bafc4c816b30cea8ec3434e7d4b63a0eff86997254c", + "0x0b3eb94aa246f7c8c871535ae2d3abe5c1b951e76b77510140ef52d5ea2457ee", + "0x27102708eea5d715799642f213049d8ac9abc3b12c76d147ce443dab28af96d8", + "0x81fb3c4e8dc6c658af2901b7aebf7467b9ae045dd0f58fe8d77f8770ac517fb6", + "0xf68dba4eee635d7494bae6fb9f0c44e739b3121d4bc6f6f21b495a716af3cf52", + "0xcf87b723dc473d313bf9ddfa233056036c5658777e831796f1f56647cd040c8d", + "0x49927c2100039ac496d9c16dd12f0a05c9441b8616c69c726fd2e79ae65e130c", + "0x088195c7251f6b9fa2105e77df5620211b8ca783a77f1a98de6752fc442c26c7", + "0x604de480bcb88e908b90451c4142b99b9cbb479167473befca7bea9b4ca427a3", + "0x642fdaf6bc1abbf261a9480fcf9bb48cf03fb80bdd434c6ab63401856c74fa39", + "0xe6b596393fce7a3023a316ac34a1fac18e18779ca5983791866f857f257592e1", + "0x40384a52564fae5df8c3e41827cdf584e38f3f555a54ca749b7b516619071d85", + "0xe52f7c17a4106594563ae7b724e5613e87d8442177f39a36b946b0e335be0e5b", + "0x7726202a7c255a9d7be47af6f3b44c1e379cda61237866554396fb6ec043482c", + "0x665da353f296cde80e3cbcb9c7f93b107d5676e5cd694b0bd33334d74789beb9" ] }, "nodes": [ diff --git a/ethcore/res/ethereum/social.json b/ethcore/res/ethereum/social.json index 2ad8fec8b..bbc77359b 100644 --- a/ethcore/res/ethereum/social.json +++ b/ethcore/res/ethereum/social.json @@ -27,8 +27,7 @@ "eip161abcTransition": "0x7fffffffffffffff", "eip161dTransition": "0x7fffffffffffffff", "eip155Transition": "0x0", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff" + "eip98Transition": "0x7fffffffffffff" }, "genesis": { "seal": { diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index b6011c3fb..3f5febc90 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit b6011c3fb567d7178915574de0a8d4b5331fe725 +Subproject commit 3f5febc901913ef698f1b09dda8705babd729e4a diff --git a/ethcore/res/ethereum/tests-issues/currents.json b/ethcore/res/ethereum/tests-issues/currents.json new file mode 100644 index 000000000..b6be610eb --- /dev/null +++ b/ethcore/res/ethereum/tests-issues/currents.json @@ -0,0 +1,468 @@ +{ "block": + [ + { + "reference": "9590", + "failing": "stCreateTest", + "subtests": [ + "CreateOOGafterInitCodeReturndata2_d0g1v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stCreate2", + "subtests": [ + "RevertDepthCreateAddressCollision_d0g1v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g1v1_Constantinople", + "CREATE2_Suicide_d5g0v0_Constantinople", + "CREATE2_Suicide_d7g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d2g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d2g0v0_Constantinople", + "create2collisionNonce_d1g0v0_Byzantium", + "create2collisionNonce_d1g0v0_Constantinople", + "CreateMessageRevertedOOGInInit_d0g1v0_Constantinople", + "create2callPrecompiles_d3g0v0_Constantinople", + "create2collisionCode_d1g0v0_Byzantium", + "create2collisionCode_d1g0v0_Constantinople", + "create2collisionStorage_d0g0v0_Byzantium", + "create2collisionStorage_d0g0v0_Constantinople", + "create2callPrecompiles_d4g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d0g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d0g0v0_Constantinople", + "CreateMessageReverted_d0g1v0_Constantinople", + "RevertOpcodeCreate_d0g1v0_Constantinople", + "CREATE2_Suicide_d11g0v0_Constantinople", + "create2checkFieldsInInitcode_d5g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d1g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d1g0v0_Constantinople", + "returndatacopy_following_create_d1g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g1v1_Constantinople", + "create2collisionSelfdestructed_d2g0v0_Byzantium", + "create2collisionSelfdestructed_d2g0v0_Constantinople", + "create2callPrecompiles_d2g0v0_Constantinople", + "create2InitCodes_d2g0v0_Constantinople", + "create2collisionNonce_d2g0v0_Byzantium", + "create2collisionNonce_d2g0v0_Constantinople", + "create2collisionCode_d0g0v0_Byzantium", + "create2collisionCode_d0g0v0_Constantinople", + "CREATE2_Bounds_d0g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g0v0_Constantinople", + "CREATE2_Suicide_d1g0v0_Constantinople", + "CREATE2_Bounds3_d0g1v0_Constantinople", + "create2collisionStorage_d2g0v0_Byzantium", + "create2collisionStorage_d2g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g0v1_Constantinople", + "create2callPrecompiles_d5g0v0_Constantinople", + "create2collisionCode2_d0g0v0_Byzantium", + "create2collisionCode2_d0g0v0_Constantinople", + "create2noCash_d0g0v0_Byzantium", + "create2noCash_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d7g0v0_Constantinople", + "create2SmartInitCode_d1g0v0_Constantinople", + "create2InitCodes_d6g0v0_Constantinople", + "create2noCash_d1g0v0_Byzantium", + "create2noCash_d1g0v0_Constantinople", + "CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn_d0g0v0_Constantinople", + "RevertOpcodeInCreateReturns_d0g0v0_Constantinople", + "create2collisionStorage_d1g0v0_Byzantium", + "create2collisionStorage_d1g0v0_Constantinople", + "create2checkFieldsInInitcode_d3g0v0_Constantinople", + "create2collisionBalance_d0g0v0_Byzantium", + "create2collisionBalance_d0g0v0_Constantinople", + "create2collisionSelfdestructed2_d0g0v0_Constantinople", + "create2InitCodes_d3g0v0_Constantinople", + "create2collisionCode2_d1g0v0_Byzantium", + "create2collisionCode2_d1g0v0_Constantinople", + "create2checkFieldsInInitcode_d1g0v0_Constantinople", + "create2collisionBalance_d1g0v0_Byzantium", + "create2collisionBalance_d1g0v0_Constantinople", + "CREATE2_Bounds3_d0g2v0_Constantinople", + "create2callPrecompiles_d6g0v0_Constantinople", + "Create2Recursive_d0g0v0_Constantinople", + "create2collisionSelfdestructedOOG_d0g0v0_Byzantium", + "create2collisionSelfdestructedOOG_d0g0v0_Constantinople", + "CREATE2_Suicide_d3g0v0_Constantinople", + "returndatacopy_following_create_d0g0v0_Constantinople", + "create2InitCodes_d8g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g0v1_Constantinople", + "create2checkFieldsInInitcode_d2g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g0v1_Constantinople", + "Create2OnDepth1024_d0g0v0_Constantinople", + "create2collisionSelfdestructed2_d1g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d2g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d2g0v0_Constantinople", + "create2callPrecompiles_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g1v1_Constantinople", + "create2collisionSelfdestructed_d1g0v0_Byzantium", + "create2collisionSelfdestructed_d1g0v0_Constantinople", + "call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Byzantium", + "call_outsize_then_create2_successful_then_returndatasize_d0g0v0_Constantinople", + "Create2OOGafterInitCodeRevert_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata3_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndataSize_d0g0v0_Constantinople", + "create2InitCodes_d7g0v0_Constantinople", + "CREATE2_Suicide_d10g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g1v0_Constantinople", + "create2InitCodes_d5g0v0_Constantinople", + "create2collisionSelfdestructedRevert_d1g0v0_Byzantium", + "create2collisionSelfdestructedRevert_d1g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g1v0_Constantinople", + "create2collisionSelfdestructed_d0g0v0_Byzantium", + "create2collisionSelfdestructed_d0g0v0_Constantinople", + "create2noCash_d2g0v0_Byzantium", + "create2noCash_d2g0v0_Constantinople", + "CREATE2_Bounds3_d0g0v0_Constantinople", + "create2collisionNonce_d0g0v0_Byzantium", + "create2collisionNonce_d0g0v0_Constantinople", + "CREATE2_Suicide_d2g0v0_Constantinople", + "Create2OOGafterInitCode_d0g0v0_Constantinople", + "call_then_create2_successful_then_returndatasize_d0g0v0_Byzantium", + "call_then_create2_successful_then_returndatasize_d0g0v0_Constantinople", + "create2collisionBalance_d2g0v0_Byzantium", + "create2collisionBalance_d2g0v0_Constantinople", + "create2checkFieldsInInitcode_d6g0v0_Constantinople", + "RevertDepthCreate2OOG_d0g1v1_Constantinople", + "returndatacopy_afterFailing_create_d0g0v0_Constantinople", + "returndatacopy_following_revert_in_create_d0g0v0_Constantinople", + "CREATE2_Suicide_d9g0v0_Constantinople", + "create2callPrecompiles_d7g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g0v1_Constantinople", + "create2InitCodes_d1g0v0_Constantinople", + "CREATE2_Bounds_d0g1v0_Constantinople", + "Create2OOGafterInitCodeReturndata_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d4g0v0_Constantinople", + "CreateMessageRevertedOOGInInit_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g1v0_Constantinople", + "returndatacopy_following_successful_create_d0g0v0_Constantinople", + "create2checkFieldsInInitcode_d0g0v0_Constantinople", + "CreateMessageReverted_d0g0v0_Constantinople", + "create2SmartInitCode_d0g0v0_Constantinople", + "CREATE2_Bounds2_d0g0v0_Constantinople", + "returndatasize_following_successful_create_d0g0v0_Constantinople", + "CREATE2_Bounds2_d0g1v0_Constantinople", + "returndatacopy_0_0_following_successful_create_d0g0v0_Constantinople", + "RevertDepthCreateAddressCollision_d0g0v0_Constantinople", + "CREATE2_Suicide_d0g0v0_Constantinople", + "create2InitCodes_d0g0v0_Constantinople", + "Create2OnDepth1023_d0g0v0_Constantinople", + "create2InitCodes_d4g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata2_d0g0v0_Constantinople", + "create2collisionBalance_d3g0v0_Byzantium", + "create2collisionBalance_d3g0v0_Constantinople", + "CREATE2_Suicide_d4g0v0_Constantinople", + "Create2OOGafterInitCode_d0g1v0_Constantinople", + "RevertDepthCreateAddressCollision_d1g0v0_Constantinople", + "Create2OOGafterInitCodeRevert2_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata_d0g1v0_Constantinople", + "Create2Recursive_d0g1v0_Constantinople", + "create2collisionCode_d2g0v0_Byzantium", + "create2collisionCode_d2g0v0_Constantinople", + "CREATE2_Suicide_d6g0v0_Constantinople", + "CREATE2_Suicide_d8g0v0_Constantinople", + "RevertOpcodeCreate_d0g0v0_Constantinople", + "Create2OOGafterInitCodeReturndata2_d0g1v0_Constantinople", + "create2callPrecompiles_d1g0v0_Constantinople", + "RevertInCreateInInit_d0g0v0_Constantinople", + "RevertDepthCreate2OOG_d1g0v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "bcStateTest", + "subtests": [ + "suicideStorageCheck_Byzantium", + "suicideStorageCheck_Constantinople", + "suicideStorageCheckVCreate2_Byzantium", + "suicideStorageCheckVCreate2_Constantinople", + "create2collisionwithSelfdestructSameBlock_Constantinople", + "blockhashNonConstArg_Constantinople", + "suicideThenCheckBalance_Constantinople", + "suicideThenCheckBalance_Homestead", + "suicideStorageCheckVCreate_Byzantium", + "suicideStorageCheckVCreate_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stEIP158Specific", + "subtests": [ + "callToEmptyThenCallError_d0g0v0_Byzantium", + "callToEmptyThenCallError_d0g0v0_Constantinople", + "callToEmptyThenCallError_d0g0v0_EIP158" + ] + }, + { + "reference": "9590", + "failing": "stPreCompiledContracts", + "subtests": [ + "identity_to_smaller_d0g0v0_Constantinople", + "identity_to_bigger_d0g0v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stReturnDataTest", + "subtests": [ + "modexp_modsize0_returndatasize_d0g1v0_Constantinople", + "modexp_modsize0_returndatasize_d0g2v0_Constantinople", + "modexp_modsize0_returndatasize_d0g3v0_Constantinople" + ] + }, + { + "reference": "9590", + "failing": "stSpecialTest", + "subtests": [ + "push32withoutByte_d0g0v0_Constantinople" + ] + } + + ], + "state": + [ + { + "reference": "9590", + "failing": "stCreateTest", + "subtests": { + "CreateOOGafterInitCodeReturndata2": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stCreate2Test", + "subtests": { + "RevertInCreateInInit": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stEIP150Specific", + "subtests": { + "NewGasPriceForCodes": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stInitCodeTest", + "subtests": { + "OutOfGasContractCreation": { + "subnumbers": ["4"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stPreCompiledContracts", + "subtests": { + "modexp": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stRevertTest", + "subtests": { + "LoopCallsDepthThenRevert3": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeCreate": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertSubCallStorageOOG2": { + "subnumbers": ["1","3"], + "chain": "Constantinople (test)" + }, + "RevertDepthCreateOOG": { + "subnumbers": ["3","4"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeMultipleSubCalls": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeDirectCall": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "LoopCallsDepthThenRevert2": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertDepth2": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "RevertRemoteSubCallStorageOOG2": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "RevertDepthCreateAddressCollision": { + "subnumbers": ["3","4"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stStaticCall", + "subtests": { + "static_RevertDepth2": { + "subnumbers": ["1","3"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes4": { + "subnumbers": ["3"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes3": { + "subnumbers": ["5","6","7","8"], + "chain": "Constantinople (test)" + }, + "static_callBasic": { + "subnumbers": ["1","2"], + "chain": "Constantinople (test)" + }, + "static_CheckOpcodes2": { + "subnumbers": ["5","6","7","8"], + "chain": "Constantinople (test)" + }, + "static_callCreate": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "https://github.com/ethereum/tests/issues/512", + "failing": "stZeroKnowledge", + "subtests": { + "pointAddTrunc": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointAdd": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointMulAdd": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "pointMulAdd2": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + } + } + }, + { + "reference": "9590", + "failing": "stCreate2Test", + "subtests": { + "call_then_create2_successful_then_returndatasize": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "returndatacopy_afterFailing_create": { + "subnumbers": ["1"], + "chain": "Constantinople (test)" + }, + "create2checkFieldsInInitcode": { + "subnumbers": ["1","2","3","5","6","7"], + "chain": "Constantinople (test)" + }, + "Create2Recursive": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "create2collisionBalance": { + "subnumbers": ["2","3"], + "chain": "Constantinople (test)" + }, + "create2InitCodes": { + "subnumbers": ["1","5","6","7","8","9"], + "chain": "Constantinople (test)" + }, + "Create2OOGafterInitCode": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "CreateMessageRevertedOOGInInit": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "returndatacopy_following_revert_in_create": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "create2collisionSelfdestructed": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "returndatacopy_0_0_following_successful_create": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "Create2OnDepth1023": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "Create2OOGafterInitCodeReturndata2": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "RevertOpcodeInCreateReturns": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "CREATE2_ContractSuicideDuringInit_ThenStoreThenReturn": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "returndatasize_following_successful_create": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "call_outsize_then_create2_successful_then_returndatasize": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "CreateMessageReverted": { + "subnumbers": ["2"], + "chain": "Constantinople (test)" + }, + "CREATE2_Suicide": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "Create2OOGafterInitCodeRevert": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "Create2OnDepth1024": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + }, + "create2collisionStorage": { + "subnumbers": ["2","3"], + "chain": "Constantinople (test)" + }, + "create2callPrecompiles": { + "subnumbers": ["*"], + "chain": "Constantinople (test)" + } + } + } + ] +} diff --git a/ethcore/res/instant_seal.json b/ethcore/res/instant_seal.json index 36832e698..005342437 100644 --- a/ethcore/res/instant_seal.json +++ b/ethcore/res/instant_seal.json @@ -16,7 +16,6 @@ "eip161dTransition": "0x0", "eip155Transition": "0x0", "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", "maxCodeSize": 24576, "maxCodeSizeTransition": "0x0", "eip140Transition": "0x0", diff --git a/ethcore/res/null.json b/ethcore/res/null.json index 345bb02b2..7fa41a8de 100644 --- a/ethcore/res/null.json +++ b/ethcore/res/null.json @@ -11,7 +11,6 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", - "eip86Transition": "0x7fffffffffffff", "eip140Transition": "0x0", "eip211Transition": "0x0", "eip214Transition": "0x0", diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index 474110de5..0edbf860f 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit 474110de59a0f632b20615256c913b144c49354c +Subproject commit 0edbf860ff7ed4b6b6336097ba44836e8c6482dd diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index aa5a3019c..2fb6d3f2a 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1349,7 +1349,7 @@ impl BlockInfo for Client { } fn code_hash(&self, address: &Address, id: BlockId) -> Option { - self.state_at(id).and_then(|s| s.code_hash(address).ok()) + self.state_at(id).and_then(|s| s.code_hash(address).unwrap_or(None)) } } @@ -2020,10 +2020,6 @@ impl BlockChainClient for Client { fn registrar_address(&self) -> Option
{ self.registrar_address.clone() } - - fn eip86_transition(&self) -> u64 { - self.engine().params().eip86_transition - } } impl IoClient for Client { diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index f11cae3b0..f9699af46 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -60,7 +60,7 @@ impl fmt::Display for EvmTestError { } use ethereum; -use ethjson::state::test::ForkSpec; +use ethjson::spec::ForkSpec; /// Simplified, single-block EVM test client. pub struct EvmTestClient<'a> { @@ -69,12 +69,12 @@ pub struct EvmTestClient<'a> { } impl<'a> fmt::Debug for EvmTestClient<'a> { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("EvmTestClient") - .field("state", &self.state) - .field("spec", &self.spec.name) - .finish() - } + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("EvmTestClient") + .field("state", &self.state) + .field("spec", &self.spec.name) + .finish() + } } impl<'a> EvmTestClient<'a> { @@ -86,9 +86,9 @@ impl<'a> EvmTestClient<'a> { ForkSpec::EIP150 => Some(ethereum::new_eip150_test()), ForkSpec::EIP158 => Some(ethereum::new_eip161_test()), ForkSpec::Byzantium => Some(ethereum::new_byzantium_test()), + ForkSpec::Constantinople => Some(ethereum::new_constantinople_test()), ForkSpec::EIP158ToByzantiumAt5 => Some(ethereum::new_transition_test()), ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None, - _ => None, } } @@ -205,7 +205,7 @@ impl<'a> EvmTestClient<'a> { ) -> TransactResult { let initial_gas = transaction.gas; // Verify transaction - let is_ok = transaction.verify_basic(true, None, env_info.number >= self.spec.engine.params().eip86_transition); + let is_ok = transaction.verify_basic(true, None, false); if let Err(error) = is_ok { return TransactResult::Err { state_root: *self.state.root(), @@ -217,9 +217,27 @@ impl<'a> EvmTestClient<'a> { let result = self.state.apply_with_tracing(&env_info, self.spec.engine.machine(), &transaction, tracer, vm_tracer); let scheme = self.spec.engine.machine().create_address_scheme(env_info.number); + // Touch the coinbase at the end of the test to simulate + // miner reward. + // Details: https://github.com/paritytech/parity-ethereum/issues/9431 + let schedule = self.spec.engine.machine().schedule(env_info.number); + self.state.add_balance(&env_info.author, &0.into(), if schedule.no_empty { + state::CleanupMode::NoEmpty + } else { + state::CleanupMode::ForceCreate + }).ok(); + // Touching also means that we should remove the account if it's within eip161 + // conditions. + self.state.kill_garbage( + &vec![env_info.author].into_iter().collect(), + schedule.kill_empty, + &None, + false + ).ok(); + self.state.commit().ok(); + match result { Ok(result) => { - self.state.commit().ok(); TransactResult::Ok { state_root: *self.state.root(), gas_left: initial_gas - result.receipt.gas_used, diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 71bf70b60..4051d004c 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -845,8 +845,6 @@ impl BlockChainClient for TestBlockChainClient { } fn registrar_address(&self) -> Option
{ None } - - fn eip86_transition(&self) -> u64 { u64::max_value() } } impl IoClient for TestBlockChainClient { diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 2e6d8d35e..0dc16c909 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -377,9 +377,6 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra /// Get the address of the registry itself. fn registrar_address(&self) -> Option
; - - /// Get the EIP-86 transition block number. - fn eip86_transition(&self) -> u64; } /// Provides `reopen_block` method diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 26151df44..0c045d236 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -36,8 +36,9 @@ use machine::EthereumMachine; const SNAPSHOT_BLOCKS: u64 = 5000; /// Maximum number of blocks allowed in an ethash snapshot. const MAX_SNAPSHOT_BLOCKS: u64 = 30000; - +/// Default number of blocks the difficulty bomb is delayed in EIP-{649,1234} const DEFAULT_EIP649_DELAY: u64 = 3_000_000; +const DEFAULT_EIP1234_DELAY: u64 = 2_000_000; /// Ethash specific seal #[derive(Debug, PartialEq)] @@ -120,6 +121,12 @@ pub struct EthashParams { pub eip649_delay: u64, /// EIP-649 base reward. pub eip649_reward: Option, + /// EIP-1234 transition block. + pub eip1234_transition: u64, + /// EIP-1234 bomb delay. + pub eip1234_delay: u64, + /// EIP-1234 base reward. + pub eip1234_reward: Option, /// EXPIP-2 block height pub expip2_transition: u64, /// EXPIP-2 duration limit @@ -152,6 +159,9 @@ impl From for EthashParams { eip649_transition: p.eip649_transition.map_or(u64::max_value(), Into::into), eip649_delay: p.eip649_delay.map_or(DEFAULT_EIP649_DELAY, Into::into), eip649_reward: p.eip649_reward.map(Into::into), + eip1234_transition: p.eip1234_transition.map_or(u64::max_value(), Into::into), + eip1234_delay: p.eip1234_delay.map_or(DEFAULT_EIP1234_DELAY, Into::into), + eip1234_reward: p.eip1234_reward.map(Into::into), expip2_transition: p.expip2_transition.map_or(u64::max_value(), Into::into), expip2_duration_limit: p.expip2_duration_limit.map_or(30, Into::into), } @@ -233,8 +243,10 @@ impl Engine for Arc { let mut rewards = Vec::new(); - // Applies EIP-649 reward. - let reward = if number >= self.ethash_params.eip649_transition { + // Applies EIP-{649,1234} reward, defaults to block_reward. + let reward = if number >= self.ethash_params.eip1234_transition { + self.ethash_params.eip1234_reward.unwrap_or(self.ethash_params.block_reward) + } else if number >= self.ethash_params.eip649_transition { self.ethash_params.eip649_reward.unwrap_or(self.ethash_params.block_reward) } else { self.ethash_params.block_reward @@ -427,6 +439,9 @@ impl Ethash { if header.number() < self.ethash_params.bomb_defuse_transition { if header.number() < self.ethash_params.ecip1010_pause_transition { let mut number = header.number(); + if number >= self.ethash_params.eip1234_transition { + number = number.saturating_sub(self.ethash_params.eip1234_delay); + } if number >= self.ethash_params.eip649_transition { number = number.saturating_sub(self.ethash_params.eip649_delay); } @@ -510,6 +525,9 @@ mod tests { eip649_transition: u64::max_value(), eip649_delay: 3_000_000, eip649_reward: None, + eip1234_transition: u64::max_value(), + eip1234_delay: 2_000_000, + eip1234_reward: None, expip2_transition: u64::max_value(), expip2_duration_limit: 30, } diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 106997044..b7fa4f486 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -151,6 +151,9 @@ pub fn new_frontier_test_machine() -> EthereumMachine { load_machine(include_byt /// Create a new Foundation Homestead-era chain spec as though it never changed from Frontier. pub fn new_homestead_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/homestead_test.json")) } +/// Create a new Foundation Homestead-EIP210-era chain spec as though it never changed from Homestead/Frontier. +pub fn new_eip210_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/eip210_test.json")) } + /// Create a new Foundation Byzantium era spec. pub fn new_byzantium_test_machine() -> EthereumMachine { load_machine(include_bytes!("../../res/ethereum/byzantium_test.json")) } diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 37dc03dee..bf5df2f9a 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -61,10 +61,13 @@ pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, stream.append(nonce); (From::from(keccak(stream.as_raw())), None) }, - CreateContractAddress::FromCodeHash => { + CreateContractAddress::FromSenderSaltAndCodeHash(salt) => { let code_hash = keccak(code); - let mut buffer = [0xffu8; 20 + 32]; - &mut buffer[20..].copy_from_slice(&code_hash[..]); + let mut buffer = [0u8; 1 + 20 + 32 + 32]; + buffer[0] = 0xff; + &mut buffer[1..(1+20)].copy_from_slice(&sender[..]); + &mut buffer[(1+20)..(1+20+32)].copy_from_slice(&salt[..]); + &mut buffer[(1+20+32)..].copy_from_slice(&code_hash[..]); (From::from(keccak(&buffer[..])), Some(code_hash)) }, CreateContractAddress::FromSenderAndCodeHash => { @@ -285,7 +288,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let mut substate = Substate::new(); // NOTE: there can be no invalid transactions from this point. - if !schedule.eip86 || !t.is_unsigned() { + if !schedule.keep_unsigned_nonce || !t.is_unsigned() { self.state.inc_nonce(&sender)?; } self.state.sub_balance(&sender, &U256::from(gas_cost), &mut substate.to_cleanup_mode(&schedule))?; @@ -320,7 +323,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { gas_price: t.gas_price, value: ActionValue::Transfer(t.value), code: self.state.code(address)?, - code_hash: Some(self.state.code_hash(address)?), + code_hash: self.state.code_hash(address)?, data: Some(t.data.clone()), call_type: CallType::Call, params_type: vm::ParamsType::Separate, @@ -557,9 +560,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let prev_bal = self.state.balance(¶ms.address)?; if let ActionValue::Transfer(val) = params.value { self.state.sub_balance(¶ms.sender, &val, &mut substate.to_cleanup_mode(&schedule))?; - self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset); + self.state.new_contract(¶ms.address, val + prev_bal, nonce_offset)?; } else { - self.state.new_contract(¶ms.address, prev_bal, nonce_offset); + self.state.new_contract(¶ms.address, prev_bal, nonce_offset)?; } let trace_info = tracer.prepare_trace_create(¶ms); @@ -610,7 +613,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let schedule = self.machine.schedule(self.info.number); // refunds from SSTORE nonzero -> zero - let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count; + let sstore_refunds = substate.sstore_clears_refund; // refunds from contract suicides let suicide_refunds = U256::from(schedule.suicide_refund_gas) * U256::from(substate.suicides.len()); let refunds_bound = sstore_refunds + suicide_refunds; @@ -1584,6 +1587,65 @@ mod tests { assert_eq!(state.storage_at(&contract_address, &H256::from(&U256::zero())).unwrap(), H256::from(&U256::from(0))); } + evm_test!{test_eip1283: test_eip1283_int} + fn test_eip1283(factory: Factory) { + let x1 = Address::from(0x1000); + let x2 = Address::from(0x1001); + let y1 = Address::from(0x2001); + let y2 = Address::from(0x2002); + let operating_address = Address::from(0); + let k = H256::new(); + + let mut state = get_temp_state_with_factory(factory.clone()); + state.new_contract(&x1, U256::zero(), U256::from(1)).unwrap(); + state.init_code(&x1, "600160005560006000556001600055".from_hex().unwrap()).unwrap(); + state.new_contract(&x2, U256::zero(), U256::from(1)).unwrap(); + state.init_code(&x2, "600060005560016000556000600055".from_hex().unwrap()).unwrap(); + state.new_contract(&y1, U256::zero(), U256::from(1)).unwrap(); + state.init_code(&y1, "600060006000600061100062fffffff4".from_hex().unwrap()).unwrap(); + state.new_contract(&y2, U256::zero(), U256::from(1)).unwrap(); + state.init_code(&y2, "600060006000600061100162fffffff4".from_hex().unwrap()).unwrap(); + + let info = EnvInfo::default(); + let machine = ::ethereum::new_constantinople_test_machine(); + + assert_eq!(state.storage_at(&operating_address, &k).unwrap(), H256::from(U256::from(0))); + // Test a call via top-level -> y1 -> x1 + let (FinalizationResult { gas_left, .. }, refund, gas) = { + let gas = U256::from(0xffffffffffu64); + let mut params = ActionParams::default(); + params.code = Some(Arc::new("6001600055600060006000600061200163fffffffff4".from_hex().unwrap())); + params.gas = gas; + let mut substate = Substate::new(); + let mut ex = Executive::new(&mut state, &info, &machine); + let res = ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap(); + + (res, substate.sstore_clears_refund, gas) + }; + let gas_used = gas - gas_left; + // sstore: 0 -> (1) -> () -> (1 -> 0 -> 1) + assert_eq!(gas_used, U256::from(41860)); + assert_eq!(refund, U256::from(19800)); + + assert_eq!(state.storage_at(&operating_address, &k).unwrap(), H256::from(U256::from(1))); + // Test a call via top-level -> y2 -> x2 + let (FinalizationResult { gas_left, .. }, refund, gas) = { + let gas = U256::from(0xffffffffffu64); + let mut params = ActionParams::default(); + params.code = Some(Arc::new("6001600055600060006000600061200263fffffffff4".from_hex().unwrap())); + params.gas = gas; + let mut substate = Substate::new(); + let mut ex = Executive::new(&mut state, &info, &machine); + let res = ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap(); + + (res, substate.sstore_clears_refund, gas) + }; + let gas_used = gas - gas_left; + // sstore: 1 -> (1) -> () -> (0 -> 1 -> 0) + assert_eq!(gas_used, U256::from(11860)); + assert_eq!(refund, U256::from(19800)); + } + fn wasm_sample_code() -> Arc> { Arc::new( "0061736d01000000010d0360027f7f0060017f0060000002270303656e7603726574000003656e760673656e646572000103656e76066d656d6f727902010110030201020404017000000501000708010463616c6c00020901000ac10101be0102057f017e4100410028020441c0006b22043602042004412c6a41106a220041003602002004412c6a41086a22014200370200200441186a41106a22024100360200200441186a41086a220342003703002004420037022c2004410036021c20044100360218200441186a1001200020022802002202360200200120032903002205370200200441106a2002360200200441086a200537030020042004290318220537022c200420053703002004411410004100200441c0006a3602040b0b0a010041040b0410c00000" diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index d315122d5..239026802 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -111,6 +111,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B> impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> where T: Tracer, V: VMTracer, B: StateBackend { + fn initial_storage_at(&self, key: &H256) -> vm::Result { + self.state.checkpoint_storage_at(0, &self.origin_info.address, key).map(|v| v.unwrap_or(H256::zero())).map_err(Into::into) + } + fn storage_at(&self, key: &H256) -> vm::Result { self.state.storage_at(&self.origin_info.address, key).map_err(Into::into) } @@ -163,7 +167,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> gas: self.machine.params().eip210_contract_gas, gas_price: 0.into(), code: code, - code_hash: Some(code_hash), + code_hash: code_hash, data: Some(H256::from(number).to_vec()), call_type: CallType::Call, params_type: vm::ParamsType::Separate, @@ -219,7 +223,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> }; if !self.static_flag { - if !self.schedule.eip86 || params.sender != UNSIGNED_SENDER { + if !self.schedule.keep_unsigned_nonce || params.sender != UNSIGNED_SENDER { if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { debug!(target: "ext", "Database corruption encountered: {:?}", e); return ContractCreateResult::Failed @@ -270,7 +274,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> gas: *gas, gas_price: self.origin_info.gas_price, code: code, - code_hash: Some(code_hash), + code_hash: code_hash, data: Some(data.to_vec()), call_type: call_type, params_type: vm::ParamsType::Separate, @@ -289,12 +293,16 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> } } - fn extcode(&self, address: &Address) -> vm::Result> { - Ok(self.state.code(address)?.unwrap_or_else(|| Arc::new(vec![]))) + fn extcode(&self, address: &Address) -> vm::Result>> { + Ok(self.state.code(address)?) } - fn extcodesize(&self, address: &Address) -> vm::Result { - Ok(self.state.code_size(address)?.unwrap_or(0)) + fn extcodehash(&self, address: &Address) -> vm::Result> { + Ok(self.state.code_hash(address)?) + } + + fn extcodesize(&self, address: &Address) -> vm::Result> { + Ok(self.state.code_size(address)?) } fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result @@ -390,8 +398,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> self.depth } - fn inc_sstore_clears(&mut self) { - self.substate.sstore_clears_count = self.substate.sstore_clears_count + U256::one(); + fn add_sstore_refund(&mut self, value: U256) { + self.substate.sstore_clears_refund = self.substate.sstore_clears_refund.saturating_add(value); + } + + fn sub_sstore_refund(&mut self, value: U256) { + self.substate.sstore_clears_refund = self.substate.sstore_clears_refund.saturating_sub(value); } fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool { @@ -570,4 +582,44 @@ mod tests { assert_eq!(setup.sub_state.suicides.len(), 1); } + + #[test] + fn can_create() { + use std::str::FromStr; + + let mut setup = TestSetup::new(); + let state = &mut setup.state; + let mut tracer = NoopTracer; + let mut vm_tracer = NoopVMTracer; + + let address = { + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderAndNonce) { + ContractCreateResult::Created(address, _) => address, + _ => panic!("Test create failed; expected Created, got Failed/Reverted."), + } + }; + + assert_eq!(address, Address::from_str("bd770416a3345f91e4b34576cb804a576fa48eb1").unwrap()); + } + + #[test] + fn can_create2() { + use std::str::FromStr; + + let mut setup = TestSetup::new(); + let state = &mut setup.state; + let mut tracer = NoopTracer; + let mut vm_tracer = NoopVMTracer; + + let address = { + let mut ext = Externalities::new(state, &setup.env_info, &setup.machine, 0, get_test_origin(), &mut setup.sub_state, OutputPolicy::InitContract(None), &mut tracer, &mut vm_tracer, false); + match ext.create(&U256::max_value(), &U256::zero(), &[], CreateContractAddress::FromSenderSaltAndCodeHash(H256::default())) { + ContractCreateResult::Created(address, _) => address, + _ => panic!("Test create failed; expected Created, got Failed/Reverted."), + } + }; + + assert_eq!(address, Address::from_str("e33c0c7f7df4809055c3eba6c09cfe4baf1bd9e0").unwrap()); + } } diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 2d643e75f..ae78d4d58 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -23,6 +23,7 @@ use ethjson; use miner::Miner; use io::IoChannel; use test_helpers; +use super::SKIP_TEST_STATE; use super::HookType; @@ -36,12 +37,20 @@ pub fn run_test_file(p: &Path, h: &mut H) { ::json_tests::test_common::run_test_file(p, json_chain_test, h) } +fn skip_test(name: &String) -> bool { + SKIP_TEST_STATE.block.iter().any(|block_test|block_test.subtests.contains(name)) +} + pub fn json_chain_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { ::ethcore_logger::init_log(); let tests = ethjson::blockchain::Test::load(json_data).unwrap(); let mut failed = Vec::new(); for (name, blockchain) in tests.into_iter() { + if skip_test(&name) { + println!(" - {} | {:?} Ignoring tests because in skip list", name, blockchain.network); + continue; + } start_stop_hook(&name, HookType::OnStart); let mut fail = false; @@ -122,19 +131,24 @@ mod block_tests { declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} declare_test!{BlockchainTests_bcRandomBlockhashTest, "BlockchainTests/bcRandomBlockhashTest"} + declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTests"} declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} declare_test!{BlockchainTests_bcUncleHeaderValidity, "BlockchainTests/bcUncleHeaderValidity"} declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} + declare_test!{BlockchainTests_GeneralStateTest_stArgsZeroOneBalance, "BlockchainTests/GeneralStateTests/stArgsZeroOneBalance/"} declare_test!{BlockchainTests_GeneralStateTest_stAttackTest, "BlockchainTests/GeneralStateTests/stAttackTest/"} declare_test!{BlockchainTests_GeneralStateTest_stBadOpcodeTest, "BlockchainTests/GeneralStateTests/stBadOpcode/"} + declare_test!{BlockchainTests_GeneralStateTest_stBugsTest, "BlockchainTests/GeneralStateTests/stBugs/"} declare_test!{BlockchainTests_GeneralStateTest_stCallCodes, "BlockchainTests/GeneralStateTests/stCallCodes/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallCreateCallCodeTest, "BlockchainTests/GeneralStateTests/stCallCreateCallCodeTest/"} declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stChangedEIP150, "BlockchainTests/GeneralStateTests/stChangedEIP150/"} declare_test!{BlockchainTests_GeneralStateTest_stCodeSizeLimit, "BlockchainTests/GeneralStateTests/stCodeSizeLimit/"} + declare_test!{BlockchainTests_GeneralStateTest_stCreate2, "BlockchainTests/GeneralStateTests/stCreate2/"} declare_test!{BlockchainTests_GeneralStateTest_stCreateTest, "BlockchainTests/GeneralStateTests/stCreateTest/"} declare_test!{BlockchainTests_GeneralStateTest_stDelegatecallTestHomestead, "BlockchainTests/GeneralStateTests/stDelegatecallTestHomestead/"} declare_test!{BlockchainTests_GeneralStateTest_stEIP150singleCodeGasPrices, "BlockchainTests/GeneralStateTests/stEIP150singleCodeGasPrices/"} @@ -149,12 +163,15 @@ mod block_tests { declare_test!{BlockchainTests_GeneralStateTest_stMemoryTest, "BlockchainTests/GeneralStateTests/stMemoryTest/"} declare_test!{BlockchainTests_GeneralStateTest_stNonZeroCallsTest, "BlockchainTests/GeneralStateTests/stNonZeroCallsTest/"} declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts, "BlockchainTests/GeneralStateTests/stPreCompiledContracts/"} + declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts2, "BlockchainTests/GeneralStateTests/stPreCompiledContracts2/"} declare_test!{heavy => BlockchainTests_GeneralStateTest_stQuadraticComplexityTest, "BlockchainTests/GeneralStateTests/stQuadraticComplexityTest/"} declare_test!{BlockchainTests_GeneralStateTest_stRandom, "BlockchainTests/GeneralStateTests/stRandom/"} + declare_test!{BlockchainTests_GeneralStateTest_stRandom2, "BlockchainTests/GeneralStateTests/stRandom2/"} declare_test!{BlockchainTests_GeneralStateTest_stRecursiveCreate, "BlockchainTests/GeneralStateTests/stRecursiveCreate/"} declare_test!{BlockchainTests_GeneralStateTest_stRefundTest, "BlockchainTests/GeneralStateTests/stRefundTest/"} declare_test!{BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"} declare_test!{BlockchainTests_GeneralStateTest_stRevertTest, "BlockchainTests/GeneralStateTests/stRevertTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stShift, "BlockchainTests/GeneralStateTests/stShift/"} declare_test!{BlockchainTests_GeneralStateTest_stSolidityTest, "BlockchainTests/GeneralStateTests/stSolidityTest/"} declare_test!{BlockchainTests_GeneralStateTest_stSpecialTest, "BlockchainTests/GeneralStateTests/stSpecialTest/"} declare_test!{BlockchainTests_GeneralStateTest_stStackTests, "BlockchainTests/GeneralStateTests/stStackTests/"} @@ -166,6 +183,7 @@ mod block_tests { declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsRevert, "BlockchainTests/GeneralStateTests/stZeroCallsRevert/"} declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsTest, "BlockchainTests/GeneralStateTests/stZeroCallsTest/"} declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge, "BlockchainTests/GeneralStateTests/stZeroKnowledge/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge2, "BlockchainTests/GeneralStateTests/stZeroKnowledge2/"} declare_test!{BlockchainTests_TransitionTests_bcEIP158ToByzantium, "BlockchainTests/TransitionTests/bcEIP158ToByzantium/"} declare_test!{BlockchainTests_TransitionTests_bcFrontierToHomestead, "BlockchainTests/TransitionTests/bcFrontierToHomestead/"} diff --git a/ethcore/src/json_tests/difficulty.rs b/ethcore/src/json_tests/difficulty.rs index 2647e1659..23a855945 100644 --- a/ethcore/src/json_tests/difficulty.rs +++ b/ethcore/src/json_tests/difficulty.rs @@ -52,26 +52,62 @@ pub fn json_difficulty_test(json_data: &[u8], spec: Sp vec![] } -mod difficulty_test_byzantium { - use super::json_difficulty_test; - use json_tests::HookType; +macro_rules! difficulty_json_test { + ( $spec:ident ) => { - fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { - json_difficulty_test(json_data, ::ethereum::new_byzantium_test(), h) - } - - declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"} -} - -mod difficulty_test_foundation { use super::json_difficulty_test; use tempdir::TempDir; use json_tests::HookType; fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { let tempdir = TempDir::new("").unwrap(); - json_difficulty_test(json_data, ::ethereum::new_foundation(&tempdir.path()), h) + json_difficulty_test(json_data, ::ethereum::$spec(&tempdir.path()), h) } + } +} + +macro_rules! difficulty_json_test_nopath { + ( $spec:ident ) => { + + use super::json_difficulty_test; + use json_tests::HookType; + + fn do_json_test(json_data: &[u8], h: &mut H) -> Vec { + json_difficulty_test(json_data, ::ethereum::$spec(), h) + } + + } +} + +mod difficulty_test { + difficulty_json_test!(new_foundation); + declare_test!{DifficultyTests_difficulty, "BasicTests/difficulty.json"} +} + +mod difficulty_test_byzantium { + difficulty_json_test_nopath!(new_byzantium_test); + declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"} +} + +mod difficulty_test_foundation { + difficulty_json_test!(new_foundation); declare_test!{DifficultyTests_difficultyMainNetwork, "BasicTests/difficultyMainNetwork.json"} } + +// Disabling Ropsten diff tests; waiting for upstream ethereum/tests Constantinople update +//mod difficulty_test_ropsten { +// difficulty_json_test_nopath!(new_ropsten_test); +// declare_test!{DifficultyTests_difficultyRopsten, "BasicTests/difficultyRopsten.json"} +//} + +mod difficulty_test_frontier { + difficulty_json_test_nopath!(new_frontier_test); + declare_test!{DifficultyTests_difficultyFrontier, "BasicTests/difficultyFrontier.json"} +} + +mod difficulty_test_homestead { + difficulty_json_test_nopath!(new_homestead_test); + declare_test!{DifficultyTests_difficultyHomestead, "BasicTests/difficultyHomestead.json"} +} + diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index daeed18eb..f01de2fb5 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -111,6 +111,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> self.ext.storage_at(key) } + fn initial_storage_at(&self, key: &H256) -> vm::Result { + self.ext.initial_storage_at(key) + } + fn set_storage(&mut self, key: H256, value: H256) -> vm::Result<()> { self.ext.set_storage(key, value) } @@ -165,14 +169,18 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> MessageCallResult::Success(*gas, ReturnData::empty()) } - fn extcode(&self, address: &Address) -> vm::Result> { + fn extcode(&self, address: &Address) -> vm::Result>> { self.ext.extcode(address) } - fn extcodesize(&self, address: &Address) -> vm::Result { + fn extcodesize(&self, address: &Address) -> vm::Result> { self.ext.extcodesize(address) } + fn extcodehash(&self, address: &Address) -> vm::Result> { + self.ext.extcodehash(address) + } + fn log(&mut self, topics: Vec, data: &[u8]) -> vm::Result<()> { self.ext.log(topics, data) } @@ -201,8 +209,12 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B> false } - fn inc_sstore_clears(&mut self) { - self.ext.inc_sstore_clears() + fn add_sstore_refund(&mut self, value: U256) { + self.ext.add_sstore_refund(value) + } + + fn sub_sstore_refund(&mut self, value: U256) { + self.ext.sub_sstore_refund(value) } } diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index fa1c822ce..35d503480 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -24,10 +24,12 @@ mod executive; mod state; mod chain; mod trie; +mod skip; #[cfg(test)] mod difficulty; + pub use self::test_common::HookType; pub use self::transaction::run_test_path as run_transaction_test_path; @@ -42,3 +44,4 @@ pub use self::trie::run_generic_test_path as run_generic_trie_test_path; pub use self::trie::run_generic_test_file as run_generic_trie_test_file; pub use self::trie::run_secure_test_path as run_secure_trie_test_path; pub use self::trie::run_secure_test_file as run_secure_trie_test_file; +use self::skip::SKIP_TEST_STATE; diff --git a/ethcore/src/json_tests/skip.rs b/ethcore/src/json_tests/skip.rs new file mode 100644 index 000000000..784e2975d --- /dev/null +++ b/ethcore/src/json_tests/skip.rs @@ -0,0 +1,37 @@ +// Copyright 2015-2018 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! State tests to skip. + +use ethjson; + +#[cfg(all(not(test), feature = "ci-skip-tests"))] +compile_error!("ci-skip-tests can only be enabled for testing builds."); + +#[cfg(feature="ci-skip-issue")] +lazy_static!{ + pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { + let skip_data = include_bytes!("../../res/ethereum/tests-issues/currents.json"); + ethjson::test::SkipStates::load(&skip_data[..]).expect("No invalid json allowed") + }; +} + +#[cfg(not(feature="ci-skip-issue"))] +lazy_static!{ + pub static ref SKIP_TEST_STATE: ethjson::test::SkipStates = { + ethjson::test::SkipStates::empty() + }; +} diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index da1716972..04ca947bf 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -22,7 +22,7 @@ use client::{EvmTestClient, EvmTestError, TransactResult}; use ethjson; use transaction::SignedTransaction; use vm::EnvInfo; - +use super::SKIP_TEST_STATE; use super::HookType; /// Run state jsontests on a given folder. @@ -35,6 +35,18 @@ pub fn run_test_file(p: &Path, h: &mut H) { ::json_tests::test_common::run_test_file(p, json_chain_test, h) } +fn skip_test(subname: &str, chain: &String, number: usize) -> bool { + SKIP_TEST_STATE.state.iter().any(|state_test|{ + if let Some(subtest) = state_test.subtests.get(subname) { + chain == &subtest.chain && + (subtest.subnumbers[0] == "*" + || subtest.subnumbers.contains(&number.to_string())) + } else { + false + } + }) +} + pub fn json_chain_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { ::ethcore_logger::init_log(); let tests = ethjson::state::test::Test::load(json_data).unwrap(); @@ -60,6 +72,10 @@ pub fn json_chain_test(json_data: &[u8], start_stop_ho for (i, state) in states.into_iter().enumerate() { let info = format!(" - {} | {:?} ({}/{}) ...", name, spec_name, i + 1, total); + if skip_test(&name, &spec.name, i + 1) { + println!("{} in skip list : SKIPPED", info); + continue; + } let post_root: H256 = state.hash.into(); let transaction: SignedTransaction = multitransaction.select(&state.indexes).into(); @@ -114,18 +130,24 @@ mod state_tests { json_chain_test(json_data, h) } + declare_test!{GeneralStateTest_stArgsZeroOneBalance, "GeneralStateTests/stArgsZeroOneBalance/"} declare_test!{GeneralStateTest_stAttackTest, "GeneralStateTests/stAttackTest/"} declare_test!{GeneralStateTest_stBadOpcodeTest, "GeneralStateTests/stBadOpcode/"} + declare_test!{GeneralStateTest_stBugs, "GeneralStateTests/stBugs/"} declare_test!{GeneralStateTest_stCallCodes, "GeneralStateTests/stCallCodes/"} + declare_test!{GeneralStateTest_stCallCreateCallCodeTest, "GeneralStateTests/stCallCreateCallCodeTest/"} declare_test!{GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} declare_test!{GeneralStateTest_stCallDelegateCodesHomestead, "GeneralStateTests/stCallDelegateCodesHomestead/"} declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"} + declare_test!{GeneralStateTest_stCodeCopyTest, "GeneralStateTests/stCodeCopyTest/"} declare_test!{GeneralStateTest_stCodeSizeLimit, "GeneralStateTests/stCodeSizeLimit/"} + declare_test!{GeneralStateTest_stCreate2Test, "GeneralStateTests/stCreate2/"} declare_test!{GeneralStateTest_stCreateTest, "GeneralStateTests/stCreateTest/"} declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"} declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"} declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"} declare_test!{GeneralStateTest_stEIP158Specific, "GeneralStateTests/stEIP158Specific/"} + declare_test!{GeneralStateTest_stEWASMTests, "GeneralStateTests/stEWASMTests/"} declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"} declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"} declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"} @@ -135,12 +157,15 @@ mod state_tests { declare_test!{GeneralStateTest_stMemoryTest, "GeneralStateTests/stMemoryTest/"} declare_test!{GeneralStateTest_stNonZeroCallsTest, "GeneralStateTests/stNonZeroCallsTest/"} declare_test!{GeneralStateTest_stPreCompiledContracts, "GeneralStateTests/stPreCompiledContracts/"} + declare_test!{GeneralStateTest_stPreCompiledContracts2, "GeneralStateTests/stPreCompiledContracts2/"} declare_test!{heavy => GeneralStateTest_stQuadraticComplexityTest, "GeneralStateTests/stQuadraticComplexityTest/"} declare_test!{GeneralStateTest_stRandom, "GeneralStateTests/stRandom/"} + declare_test!{GeneralStateTest_stRandom2, "GeneralStateTests/stRandom2/"} declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"} declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"} declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"} declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} + declare_test!{GeneralStateTest_stShift, "GeneralStateTests/stShift/"} declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"} declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"} declare_test!{GeneralStateTest_stStackTests, "GeneralStateTests/stStackTests/"} @@ -152,4 +177,11 @@ mod state_tests { declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"} declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"} declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"} + + // Attempts to send a transaction that requires more than current balance: + // Tx: + // https://github.com/ethereum/tests/blob/726b161ba8a739691006cc1ba080672bb50a9d49/GeneralStateTests/stZeroKnowledge2/ecmul_0-3_5616_28000_96.json#L170 + // Balance: + // https://github.com/ethereum/tests/blob/726b161ba8a739691006cc1ba080672bb50a9d49/GeneralStateTests/stZeroKnowledge2/ecmul_0-3_5616_28000_96.json#L126 + declare_test!{GeneralStateTest_stZeroKnowledge2, "GeneralStateTests/stZeroKnowledge2/"} } diff --git a/ethcore/src/json_tests/test_common.rs b/ethcore/src/json_tests/test_common.rs index 39b7447c7..ce16395d2 100644 --- a/ethcore/src/json_tests/test_common.rs +++ b/ethcore/src/json_tests/test_common.rs @@ -34,6 +34,18 @@ pub fn run_test_path( p: &Path, skip: &[&'static str], runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, start_stop_hook: &mut H +) { + let mut errors = Vec::new(); + run_test_path_inner(p, skip, runner, start_stop_hook, &mut errors); + let empty: [String; 0] = []; + assert_eq!(errors, empty); +} + +fn run_test_path_inner( + p: &Path, skip: &[&'static str], + runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + start_stop_hook: &mut H, + errors: &mut Vec ) { let path = Path::new(p); let s: HashSet = skip.iter().map(|s| { @@ -41,6 +53,7 @@ pub fn run_test_path( os.push(".json"); os }).collect(); + let extension = path.extension().and_then(|s| s.to_str()); if path.is_dir() { for p in read_dir(path).unwrap().filter_map(|e| { let e = e.unwrap(); @@ -49,22 +62,42 @@ pub fn run_test_path( } else { Some(e.path()) }}) { - run_test_path(&p, skip, runner, start_stop_hook) + run_test_path_inner(&p, skip, runner, start_stop_hook, errors); } + } else if extension == Some("swp") || extension == None { + // Ignore junk } else { let mut path = p.to_path_buf(); path.set_extension("json"); - run_test_file(&path, runner, start_stop_hook) + run_test_file_append(&path, runner, start_stop_hook, errors) } } +fn run_test_file_append( + path: &Path, + runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, + start_stop_hook: &mut H, + errors: &mut Vec +) { + let mut data = Vec::new(); + let mut file = match File::open(&path) { + Ok(file) => file, + Err(_) => panic!("Error opening test file at: {:?}", path), + }; + file.read_to_end(&mut data).expect("Error reading test file"); + errors.append(&mut runner(&data, start_stop_hook)); +} + pub fn run_test_file( path: &Path, runner: fn(json_data: &[u8], start_stop_hook: &mut H) -> Vec, start_stop_hook: &mut H ) { let mut data = Vec::new(); - let mut file = File::open(&path).expect("Error opening test file"); + let mut file = match File::open(&path) { + Ok(file) => file, + Err(_) => panic!("Error opening test file at: {:?}", path), + }; file.read_to_end(&mut data).expect("Error reading test file"); let results = runner(&data, start_stop_hook); let empty: [String; 0] = []; diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs index af16481f4..70021c9e9 100644 --- a/ethcore/src/json_tests/transaction.rs +++ b/ethcore/src/json_tests/transaction.rs @@ -16,10 +16,11 @@ use std::path::Path; use super::test_common::*; -use evm; +use client::EvmTestClient; +use header::Header; use ethjson; use rlp::Rlp; -use transaction::{Action, UnverifiedTransaction, SignedTransaction}; +use transaction::UnverifiedTransaction; /// Run transaction jsontests on a given folder. pub fn run_test_path(p: &Path, skip: &[&'static str], h: &mut H) { @@ -31,55 +32,61 @@ pub fn run_test_file(p: &Path, h: &mut H) { ::json_tests::test_common::run_test_file(p, do_json_test, h) } +// Block number used to run the tests. +// Make sure that all the specified features are activated. +const BLOCK_NUMBER: u64 = 0x6ffffffffffffe; + fn do_json_test(json_data: &[u8], start_stop_hook: &mut H) -> Vec { let tests = ethjson::transaction::Test::load(json_data).unwrap(); let mut failed = Vec::new(); - let frontier_schedule = evm::Schedule::new_frontier(); - let homestead_schedule = evm::Schedule::new_homestead(); - let byzantium_schedule = evm::Schedule::new_byzantium(); for (name, test) in tests.into_iter() { start_stop_hook(&name, HookType::OnStart); - let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); }; - - let number: Option = test.block_number.map(Into::into); - let schedule = match number { - None => &frontier_schedule, - Some(x) if x < 1_150_000 => &frontier_schedule, - Some(x) if x < 3_000_000 => &homestead_schedule, - Some(_) => &byzantium_schedule - }; - let allow_chain_id_of_one = number.map_or(false, |n| n >= 2_675_000); - let allow_unsigned = number.map_or(false, |n| n >= 3_000_000); - - let rlp: Vec = test.rlp.into(); - let res = Rlp::new(&rlp) - .as_val() - .map_err(::error::Error::from) - .and_then(|t: UnverifiedTransaction| { - t.validate(schedule, schedule.have_delegate_call, allow_chain_id_of_one, allow_unsigned).map_err(Into::into) - }); - - fail_unless(test.transaction.is_none() == res.is_err(), "Validity different"); - if let (Some(tx), Some(sender)) = (test.transaction, test.sender) { - let t = res.unwrap(); - fail_unless(SignedTransaction::new(t.clone()).unwrap().sender() == sender.into(), "sender mismatch"); - let is_acceptable_chain_id = match t.chain_id() { - None => true, - Some(1) if allow_chain_id_of_one => true, - _ => false, + for (spec_name, result) in test.post_state { + let spec = match EvmTestClient::spec_from_json(&spec_name) { + Some(spec) => spec, + None => { + println!(" - {} | {:?} Ignoring tests because of missing spec", name, spec_name); + continue; + } }; - fail_unless(is_acceptable_chain_id, "Network ID unacceptable"); - let data: Vec = tx.data.into(); - fail_unless(t.data == data, "data mismatch"); - fail_unless(t.gas_price == tx.gas_price.into(), "gas_price mismatch"); - fail_unless(t.nonce == tx.nonce.into(), "nonce mismatch"); - fail_unless(t.value == tx.value.into(), "value mismatch"); - let to: Option = tx.to.into(); - let to: Option
= to.map(Into::into); - match t.action { - Action::Call(dest) => fail_unless(Some(dest) == to, "call/destination mismatch"), - Action::Create => fail_unless(None == to, "create mismatch"), + + let mut fail_unless = |cond: bool, title: &str| if !cond { + failed.push(format!("{}-{:?}", name, spec_name)); + println!("Transaction failed: {:?}-{:?}: {:?}", name, spec_name, title); + }; + + let rlp: Vec = test.rlp.clone().into(); + let res = Rlp::new(&rlp) + .as_val() + .map_err(::error::Error::from) + .and_then(|t: UnverifiedTransaction| { + let mut header: Header = Default::default(); + // Use high enough number to activate all required features. + header.set_number(BLOCK_NUMBER); + + let minimal = t.gas_required(&spec.engine.schedule(header.number())).into(); + if t.gas < minimal { + return Err(::transaction::Error::InsufficientGas { + minimal, got: t.gas, + }.into()); + } + spec.engine.verify_transaction_basic(&t, &header)?; + Ok(spec.engine.verify_transaction_unordered(t, &header)?) + }); + + match (res, result.hash, result.sender) { + (Ok(t), Some(hash), Some(sender)) => { + fail_unless(t.sender() == sender.into(), "sender mismatch"); + fail_unless(t.hash() == hash.into(), "hash mismatch"); + }, + (Err(_), None, None) => {}, + data => { + fail_unless( + false, + &format!("Validity different: {:?}", data) + ); + } } } @@ -92,13 +99,14 @@ fn do_json_test(json_data: &[u8], start_stop_hook: &mu failed } -declare_test!{TransactionTests_ttEip155VitaliksHomesead, "TransactionTests/ttEip155VitaliksHomesead"} -declare_test!{TransactionTests_ttEip155VitaliksEip158, "TransactionTests/ttEip155VitaliksEip158"} -declare_test!{TransactionTests_ttEip158, "TransactionTests/ttEip158"} -declare_test!{TransactionTests_ttFrontier, "TransactionTests/ttFrontier"} -declare_test!{TransactionTests_ttHomestead, "TransactionTests/ttHomestead"} -declare_test!{TransactionTests_ttVRuleEip158, "TransactionTests/ttVRuleEip158"} -declare_test!{TransactionTests_ttWrongRLPFrontier, "TransactionTests/ttWrongRLPFrontier"} -declare_test!{TransactionTests_ttWrongRLPHomestead, "TransactionTests/ttWrongRLPHomestead"} -declare_test!{TransactionTests_ttConstantinople, "TransactionTests/ttConstantinople"} -declare_test!{TransactionTests_ttSpecConstantinople, "TransactionTests/ttSpecConstantinople"} +declare_test!{TransactionTests_ttAddress, "TransactionTests/ttAddress"} +declare_test!{TransactionTests_ttData, "TransactionTests/ttData"} +declare_test!{TransactionTests_ttGasLimit, "TransactionTests/ttGasLimit"} +declare_test!{TransactionTests_ttGasPrice, "TransactionTests/ttGasPrice"} +declare_test!{TransactionTests_ttNonce, "TransactionTests/ttNonce"} +declare_test!{TransactionTests_ttRSValue, "TransactionTests/ttRSValue"} +declare_test!{TransactionTests_ttSignature, "TransactionTests/ttSignature"} +declare_test!{TransactionTests_ttValue, "TransactionTests/ttValue"} +declare_test!{TransactionTests_ttVValue, "TransactionTests/ttVValue"} +declare_test!{TransactionTests_ttWrongRLP, "TransactionTests/ttWrongRLP"} + diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index dbf66aa12..949df9af4 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -140,7 +140,7 @@ impl EthereumMachine { gas_price: 0.into(), value: ActionValue::Transfer(0.into()), code: state.code(&contract_address)?, - code_hash: Some(state.code_hash(&contract_address)?), + code_hash: state.code_hash(&contract_address)?, data: data, call_type: CallType::Call, params_type: ParamsType::Separate, @@ -309,12 +309,8 @@ impl EthereumMachine { } /// Returns new contract address generation scheme at given block number. - pub fn create_address_scheme(&self, number: BlockNumber) -> CreateContractAddress { - if number >= self.params().eip86_transition { - CreateContractAddress::FromCodeHash - } else { - CreateContractAddress::FromSenderAndNonce - } + pub fn create_address_scheme(&self, _number: BlockNumber) -> CreateContractAddress { + CreateContractAddress::FromSenderAndNonce } /// Verify a particular transaction is valid, regardless of order. diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index f0243be73..0df5d0a37 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -96,8 +96,6 @@ pub struct CommonParams { pub validate_receipts_transition: BlockNumber, /// Validate transaction chain id. pub validate_chain_id_transition: BlockNumber, - /// Number of first block where EIP-86 (Metropolis) rules begin. - pub eip86_transition: BlockNumber, /// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin. pub eip140_transition: BlockNumber, /// Number of first block where EIP-210 (Metropolis: BLOCKHASH changes) rules begin. @@ -115,6 +113,12 @@ pub struct CommonParams { pub eip214_transition: BlockNumber, /// Number of first block where EIP-145 rules begin. pub eip145_transition: BlockNumber, + /// Number of first block where EIP-1052 rules begin. + pub eip1052_transition: BlockNumber, + /// Number of first block where EIP-1283 rules begin. + pub eip1283_transition: BlockNumber, + /// Number of first block where EIP-1014 rules begin. + pub eip1014_transition: BlockNumber, /// Number of first block where dust cleanup rules (EIP-168 and EIP169) begin. pub dust_protection_transition: BlockNumber, /// Nonce cap increase per block. Nonce cap is only checked if dust protection is enabled. @@ -123,6 +127,10 @@ pub struct CommonParams { pub remove_dust_contracts: bool, /// Wasm activation blocknumber, if any disabled initially. pub wasm_activation_transition: BlockNumber, + /// Number of first block where KIP-4 rules begin. Only has effect if Wasm is activated. + pub kip4_transition: BlockNumber, + /// Number of first block where KIP-6 rules begin. Only has effect if Wasm is activated. + pub kip6_transition: BlockNumber, /// Gas limit bound divisor (how much gas limit can change per block) pub gas_limit_bound_divisor: U256, /// Registrar contract address. @@ -169,11 +177,13 @@ impl CommonParams { /// Apply common spec config parameters to the schedule. pub fn update_schedule(&self, block_number: u64, schedule: &mut ::vm::Schedule) { - schedule.have_create2 = block_number >= self.eip86_transition; + 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.eip1283 = block_number >= self.eip1283_transition; if block_number >= self.eip210_transition { schedule.blockhash_gas = 800; } @@ -184,7 +194,14 @@ impl CommonParams { }; } if block_number >= self.wasm_activation_transition { - schedule.wasm = Some(Default::default()); + let mut wasm = ::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); } } @@ -232,10 +249,6 @@ impl From for CommonParams { 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), - eip86_transition: p.eip86_transition.map_or_else( - BlockNumber::max_value, - Into::into, - ), eip140_transition: p.eip140_transition.map_or_else( BlockNumber::max_value, Into::into, @@ -270,6 +283,18 @@ impl From for CommonParams { 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, + ), + eip1014_transition: p.eip1014_transition.map_or_else( + BlockNumber::max_value, + Into::into, + ), dust_protection_transition: p.dust_protection_transition.map_or_else( BlockNumber::max_value, Into::into, @@ -287,6 +312,14 @@ impl From for CommonParams { BlockNumber::max_value, 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 + ), } } } diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs index 359b84b1e..9741a8505 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -59,6 +59,10 @@ pub struct Account { // LRU Cache of the trie-backed storage. // This is limited to `STORAGE_CACHE_ITEMS` recent queries storage_cache: RefCell>, + // LRU Cache of the trie-backed storage for original value. + // This is only used when the initial storage root is different compared to + // what is in the database. That is, it is only used for new contracts. + original_storage_cache: Option<(H256, RefCell>)>, // Modified storage. Accumulates changes to storage made in `set_storage` // Takes precedence over `storage_cache`. storage_changes: HashMap, @@ -81,6 +85,7 @@ impl From for Account { nonce: basic.nonce, storage_root: basic.storage_root, storage_cache: Self::empty_storage_cache(), + original_storage_cache: None, storage_changes: HashMap::new(), code_hash: basic.code_hash, code_size: None, @@ -100,6 +105,7 @@ impl Account { nonce: nonce, storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), + original_storage_cache: None, storage_changes: storage, code_hash: keccak(&code), code_size: Some(code.len()), @@ -120,6 +126,7 @@ impl Account { nonce: pod.nonce, storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), + original_storage_cache: None, storage_changes: pod.storage.into_iter().collect(), code_hash: pod.code.as_ref().map_or(KECCAK_EMPTY, |c| keccak(c)), code_filth: Filth::Dirty, @@ -136,6 +143,7 @@ impl Account { nonce: nonce, storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), + original_storage_cache: None, storage_changes: HashMap::new(), code_hash: KECCAK_EMPTY, code_cache: Arc::new(vec![]), @@ -154,12 +162,17 @@ impl Account { /// Create a new contract account. /// NOTE: make sure you use `init_code` on this before `commit`ing. - pub fn new_contract(balance: U256, nonce: U256) -> Account { + pub fn new_contract(balance: U256, nonce: U256, original_storage_root: H256) -> Account { Account { balance: balance, nonce: nonce, storage_root: KECCAK_NULL_RLP, storage_cache: Self::empty_storage_cache(), + original_storage_cache: if original_storage_root == KECCAK_NULL_RLP { + None + } else { + Some((original_storage_root, Self::empty_storage_cache())) + }, storage_changes: HashMap::new(), code_hash: KECCAK_EMPTY, code_cache: Arc::new(vec![]), @@ -204,11 +217,43 @@ impl Account { if let Some(value) = self.cached_storage_at(key) { return Ok(value); } - let db = SecTrieDB::new(db, &self.storage_root)?; + Self::get_and_cache_storage( + &self.storage_root, + &mut self.storage_cache.borrow_mut(), + db, + key) + } + + /// Get (and cache) the contents of the trie's storage at `key`. + /// Does not take modified storage into account. + pub fn original_storage_at(&self, db: &HashDB, key: &H256) -> TrieResult { + if let Some(value) = self.cached_original_storage_at(key) { + return Ok(value); + } + match &self.original_storage_cache { + Some((ref original_storage_root, ref original_storage_cache)) => + Self::get_and_cache_storage( + original_storage_root, + &mut original_storage_cache.borrow_mut(), + db, + key + ), + None => + Self::get_and_cache_storage( + &self.storage_root, + &mut self.storage_cache.borrow_mut(), + db, + key + ), + } + } + + fn get_and_cache_storage(storage_root: &H256, storage_cache: &mut LruCache, db: &HashDB, key: &H256) -> TrieResult { + let db = SecTrieDB::new(db, storage_root)?; let panicky_decoder = |bytes:&[u8]| ::rlp::decode(&bytes).expect("decoding db value failed"); let item: U256 = db.get_with(key, panicky_decoder)?.unwrap_or_else(U256::zero); let value: H256 = item.into(); - self.storage_cache.borrow_mut().insert(key.clone(), value.clone()); + storage_cache.insert(key.clone(), value.clone()); Ok(value) } @@ -218,10 +263,38 @@ impl Account { if let Some(value) = self.storage_changes.get(key) { return Some(value.clone()) } - if let Some(value) = self.storage_cache.borrow_mut().get_mut(key) { - return Some(value.clone()) + self.cached_moved_original_storage_at(key) + } + + /// Get cached original storage value after last state commitment. Returns `None` if the key is not in the cache. + pub fn cached_original_storage_at(&self, key: &H256) -> Option { + match &self.original_storage_cache { + Some((_, ref original_storage_cache)) => { + if let Some(value) = original_storage_cache.borrow_mut().get_mut(key) { + Some(value.clone()) + } else { + None + } + }, + None => { + self.cached_moved_original_storage_at(key) + }, + } + } + + /// Get cached original storage value since last contract creation on this address. Returns `None` if the key is not in the cache. + fn cached_moved_original_storage_at(&self, key: &H256) -> Option { + // If storage root is empty RLP, then early return zero value. Practically, this makes it so that if + // `original_storage_cache` is used, then `storage_cache` will always remain empty. + if self.storage_root == KECCAK_NULL_RLP { + return Some(H256::new()); + } + + if let Some(value) = self.storage_cache.borrow_mut().get_mut(key) { + Some(value.clone()) + } else { + None } - None } /// return the balance associated with this account. @@ -278,12 +351,13 @@ impl Account { !self.code_cache.is_empty() || (self.code_cache.is_empty() && self.code_hash == KECCAK_EMPTY) } - /// Provide a database to get `code_hash`. Should not be called if it is a contract without code. + /// Provide a database to get `code_hash`. Should not be called if it is a contract without code. Returns the cached code, if successful. + #[must_use] pub fn cache_code(&mut self, db: &HashDB) -> Option> { // TODO: fill out self.code_cache; trace!("Account::cache_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty()); - if self.is_cached() { return Some(self.code_cache.clone()) } + if self.is_cached() { return Some(self.code_cache.clone()); } match db.get(&self.code_hash) { Some(x) => { @@ -298,8 +372,7 @@ impl Account { } } - /// Provide code to cache. For correctness, should be the correct code for the - /// account. + /// Provide code to cache. For correctness, should be the correct code for the account. pub fn cache_given_code(&mut self, code: Arc) { trace!("Account::cache_given_code: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty()); @@ -307,7 +380,9 @@ impl Account { self.code_cache = code; } - /// Provide a database to get `code_size`. Should not be called if it is a contract without code. + /// Provide a database to get `code_size`. Should not be called if it is a contract without code. Returns whether + /// the cache succeeds. + #[must_use] pub fn cache_code_size(&mut self, db: &HashDB) -> bool { // TODO: fill out self.code_cache; trace!("Account::cache_code_size: ic={}; self.code_hash={:?}, self.code_cache={}", self.is_cached(), self.code_hash, self.code_cache.pretty()); @@ -324,7 +399,9 @@ impl Account { }, } } else { - false + // If the code hash is empty hash, then the code size is zero. + self.code_size = Some(0); + true } } @@ -352,7 +429,27 @@ impl Account { } /// Return the storage root associated with this account or None if it has been altered via the overlay. - pub fn storage_root(&self) -> Option<&H256> { if self.storage_is_clean() {Some(&self.storage_root)} else {None} } + pub fn storage_root(&self) -> Option { + if self.storage_is_clean() { + Some(self.storage_root) + } else { + None + } + } + + /// Return the original storage root of this account. + pub fn original_storage_root(&self) -> H256 { + if let Some((original_storage_root, _)) = self.original_storage_cache { + original_storage_root + } else { + self.storage_root + } + } + + /// Storage root where the account changes are based upon. + pub fn base_storage_root(&self) -> H256 { + self.storage_root + } /// Return the storage overlay. pub fn storage_changes(&self) -> &HashMap { &self.storage_changes } @@ -387,6 +484,7 @@ impl Account { self.storage_cache.borrow_mut().insert(k, v); } + self.original_storage_cache = None; Ok(()) } @@ -424,6 +522,7 @@ impl Account { nonce: self.nonce.clone(), storage_root: self.storage_root.clone(), storage_cache: Self::empty_storage_cache(), + original_storage_cache: self.original_storage_cache.as_ref().map(|(r, _)| (*r, Self::empty_storage_cache())), storage_changes: HashMap::new(), code_hash: self.code_hash.clone(), code_size: self.code_size.clone(), @@ -444,6 +543,7 @@ impl Account { pub fn clone_all(&self) -> Account { let mut account = self.clone_dirty(); account.storage_cache = self.storage_cache.clone(); + account.original_storage_cache = self.original_storage_cache.clone(); account } @@ -453,16 +553,21 @@ impl Account { pub fn overwrite_with(&mut self, other: Account) { self.balance = other.balance; self.nonce = other.nonce; - self.storage_root = other.storage_root; self.code_hash = other.code_hash; self.code_filth = other.code_filth; self.code_cache = other.code_cache; self.code_size = other.code_size; self.address_hash = other.address_hash; - let mut cache = self.storage_cache.borrow_mut(); - for (k, v) in other.storage_cache.into_inner() { - cache.insert(k, v); + if self.storage_root == other.storage_root { + let mut cache = self.storage_cache.borrow_mut(); + for (k, v) in other.storage_cache.into_inner() { + cache.insert(k, v); + } + } else { + self.storage_cache = other.storage_cache; } + self.original_storage_cache = other.original_storage_cache; + self.storage_root = other.storage_root; self.storage_changes = other.storage_changes; } } @@ -521,7 +626,7 @@ mod tests { let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); a.set_storage(0x00u64.into(), 0x1234u64.into()); a.commit_storage(&Default::default(), &mut db).unwrap(); a.init_code(vec![]); @@ -530,7 +635,7 @@ mod tests { }; let a = Account::from_rlp(&rlp).expect("decoding db value failed"); - assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); + assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); assert_eq!(a.storage_at(&db.immutable(), &0x00u64.into()).unwrap(), 0x1234u64.into()); assert_eq!(a.storage_at(&db.immutable(), &0x01u64.into()).unwrap(), H256::default()); } @@ -541,7 +646,7 @@ mod tests { let mut db = AccountDBMut::new(&mut db, &Address::new()); let rlp = { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); a.init_code(vec![0x55, 0x44, 0xffu8]); a.commit_code(&mut db); a.rlp() @@ -556,18 +661,18 @@ mod tests { #[test] fn commit_storage() { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.set_storage(0.into(), 0x1234.into()); assert_eq!(a.storage_root(), None); a.commit_storage(&Default::default(), &mut db).unwrap(); - assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); + assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); } #[test] fn commit_remove_commit_storage() { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.set_storage(0.into(), 0x1234.into()); @@ -576,12 +681,12 @@ mod tests { a.commit_storage(&Default::default(), &mut db).unwrap(); a.set_storage(1.into(), 0.into()); a.commit_storage(&Default::default(), &mut db).unwrap(); - assert_eq!(*a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); + assert_eq!(a.storage_root().unwrap(), "c57e1afb758b07f8d2c8f13a3b6e44fa5ff94ab266facc5a4fd3f062426e50b2".into()); } #[test] fn commit_code() { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.init_code(vec![0x55, 0x44, 0xffu8]); @@ -593,7 +698,7 @@ mod tests { #[test] fn reset_code() { - let mut a = Account::new_contract(69.into(), 0.into()); + let mut a = Account::new_contract(69.into(), 0.into(), KECCAK_NULL_RLP); let mut db = MemoryDB::new(); let mut db = AccountDBMut::new(&mut db, &Address::new()); a.init_code(vec![0x55, 0x44, 0xffu8]); @@ -624,7 +729,7 @@ mod tests { assert_eq!(*a.balance(), 69u8.into()); assert_eq!(*a.nonce(), 0u8.into()); assert_eq!(a.code_hash(), KECCAK_EMPTY); - assert_eq!(a.storage_root().unwrap(), &KECCAK_NULL_RLP); + assert_eq!(a.storage_root().unwrap(), KECCAK_NULL_RLP); } #[test] diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 0118f4d85..4c5fef097 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -181,6 +181,8 @@ impl AccountEntry { Some(acc) => { if let Some(ref mut ours) = self.account { ours.overwrite_with(acc); + } else { + self.account = Some(acc); } }, None => self.account = None, @@ -400,9 +402,12 @@ impl State { self.factories.vm.clone() } - /// Create a recoverable checkpoint of this state. - pub fn checkpoint(&mut self) { - self.checkpoints.get_mut().push(HashMap::new()); + /// Create a recoverable checkpoint of this state. Return the checkpoint index. + pub fn checkpoint(&mut self) -> usize { + let checkpoints = self.checkpoints.get_mut(); + let index = checkpoints.len(); + checkpoints.push(HashMap::new()); + index } /// Merge last checkpoint with previous. @@ -493,8 +498,10 @@ impl State { /// Create a new contract at address `contract`. If there is already an account at the address /// it will have its code reset, ready for `init_code()`. - pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256) { - self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce + nonce_offset)))); + pub fn new_contract(&mut self, contract: &Address, balance: U256, nonce_offset: U256) -> TrieResult<()> { + let original_storage_root = self.original_storage_root(contract)?; + self.insert_cache(contract, AccountEntry::new_dirty(Some(Account::new_contract(balance, self.account_start_nonce + nonce_offset, original_storage_root)))); + Ok(()) } /// Remove an existing account. @@ -535,11 +542,84 @@ impl State { /// Get the storage root of account `a`. pub fn storage_root(&self, a: &Address) -> TrieResult> { self.ensure_cached(a, RequireCache::None, true, - |a| a.as_ref().and_then(|account| account.storage_root().cloned())) + |a| a.as_ref().and_then(|account| account.storage_root())) } - /// Mutate storage of account `address` so that it is `value` for `key`. - pub fn storage_at(&self, address: &Address, key: &H256) -> TrieResult { + /// Get the original storage root since last commit of account `a`. + pub fn original_storage_root(&self, a: &Address) -> TrieResult { + Ok(self.ensure_cached(a, RequireCache::None, true, + |a| a.as_ref().map(|account| account.original_storage_root()))? + .unwrap_or(KECCAK_NULL_RLP)) + } + + /// Get the value of storage at a specific checkpoint. + pub fn checkpoint_storage_at(&self, checkpoint_index: usize, address: &Address, key: &H256) -> TrieResult> { + enum ReturnKind { + /// Use original storage at value at this address. + OriginalAt, + /// Use the downward checkpoint value. + Downward, + } + + let (checkpoints_len, kind) = { + let checkpoints = self.checkpoints.borrow(); + let checkpoints_len = checkpoints.len(); + let checkpoint = match checkpoints.get(checkpoint_index) { + Some(checkpoint) => checkpoint, + // The checkpoint was not found. Return None. + None => return Ok(None), + }; + + let kind = match checkpoint.get(address) { + // The account exists at this checkpoint. + Some(Some(AccountEntry { account: Some(ref account), .. })) => { + if let Some(value) = account.cached_storage_at(key) { + return Ok(Some(value)); + } else { + // This account has checkpoint entry, but the key is not in the entry's cache. We can use + // original_storage_at if current account's original storage root is the same as checkpoint + // account's original storage root. Otherwise, the account must be a newly created contract. + if account.base_storage_root() == self.original_storage_root(address)? { + ReturnKind::OriginalAt + } else { + // If account base storage root is different from the original storage root since last + // commit, then it can only be created from a new contract, where the base storage root + // would always be empty. Note that this branch is actually never called, because + // `cached_storage_at` handled this case. + warn!("Trying to get an account's cached storage value, but base storage root does not equal to original storage root! Assuming the value is empty."); + return Ok(Some(H256::new())); + } + } + }, + // The account didn't exist at that point. Return empty value. + Some(Some(AccountEntry { account: None, .. })) => return Ok(Some(H256::new())), + // The value was not cached at that checkpoint, meaning it was not modified at all. + Some(None) => ReturnKind::OriginalAt, + // This key does not have a checkpoint entry. + None => ReturnKind::Downward, + }; + + (checkpoints_len, kind) + }; + + match kind { + ReturnKind::Downward => { + if checkpoint_index >= checkpoints_len - 1 { + Ok(Some(self.storage_at(address, key)?)) + } else { + self.checkpoint_storage_at(checkpoint_index + 1, address, key) + } + }, + ReturnKind::OriginalAt => Ok(Some(self.original_storage_at(address, key)?)), + } + } + + fn storage_at_inner( + &self, address: &Address, key: &H256, f_cached_at: FCachedStorageAt, f_at: FStorageAt, + ) -> TrieResult where + FCachedStorageAt: Fn(&Account, &H256) -> Option, + FStorageAt: Fn(&Account, &HashDB, &H256) -> TrieResult + { // Storage key search and update works like this: // 1. If there's an entry for the account in the local cache check for the key and return it if found. // 2. If there's an entry for the account in the global cache check for the key or load it into that account. @@ -552,7 +632,7 @@ impl State { if let Some(maybe_acc) = local_cache.get(address) { match maybe_acc.account { Some(ref account) => { - if let Some(value) = account.cached_storage_at(key) { + if let Some(value) = f_cached_at(account, key) { return Ok(value); } else { local_account = Some(maybe_acc); @@ -566,7 +646,7 @@ impl State { None => Ok(H256::new()), Some(a) => { let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); - a.storage_at(account_db.as_hashdb(), key) + f_at(a, account_db.as_hashdb(), key) } }); @@ -578,7 +658,7 @@ impl State { if let Some(ref mut acc) = local_account { if let Some(ref account) = acc.account { let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(address)); - return account.storage_at(account_db.as_hashdb(), key) + return f_at(account, account_db.as_hashdb(), key) } else { return Ok(H256::new()) } @@ -594,12 +674,32 @@ impl State { let maybe_acc = db.get_with(address, from_rlp)?; let r = maybe_acc.as_ref().map_or(Ok(H256::new()), |a| { let account_db = self.factories.accountdb.readonly(self.db.as_hashdb(), a.address_hash(address)); - a.storage_at(account_db.as_hashdb(), key) + f_at(a, account_db.as_hashdb(), key) }); self.insert_cache(address, AccountEntry::new_clean(maybe_acc)); r } + /// Mutate storage of account `address` so that it is `value` for `key`. + pub fn storage_at(&self, address: &Address, key: &H256) -> TrieResult { + self.storage_at_inner( + address, + key, + |account, key| { account.cached_storage_at(key) }, + |account, db, key| { account.storage_at(db, key) }, + ) + } + + /// Get the value of storage after last state commitment. + pub fn original_storage_at(&self, address: &Address, key: &H256) -> TrieResult { + self.storage_at_inner( + address, + key, + |account, key| { account.cached_original_storage_at(key) }, + |account, db, key| { account.original_storage_at(db, key) }, + ) + } + /// Get accounts' code. pub fn code(&self, a: &Address) -> TrieResult>> { self.ensure_cached(a, RequireCache::Code, true, @@ -607,9 +707,9 @@ impl State { } /// Get an account's code hash. - pub fn code_hash(&self, a: &Address) -> TrieResult { + pub fn code_hash(&self, a: &Address) -> TrieResult> { self.ensure_cached(a, RequireCache::None, true, - |a| a.as_ref().map_or(KECCAK_EMPTY, |a| a.code_hash())) + |a| a.as_ref().map(|a| a.code_hash())) } /// Get accounts' code size. @@ -670,13 +770,13 @@ impl State { /// Initialise the code of account `a` so that it is `code`. /// NOTE: Account should have been created with `new_contract`. pub fn init_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> { - self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{})?.init_code(code); + self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce, KECCAK_NULL_RLP), |_| {})?.init_code(code); Ok(()) } /// Reset the code of account `a` so that it is `code`. pub fn reset_code(&mut self, a: &Address, code: Bytes) -> TrieResult<()> { - self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{})?.reset_code(code); + self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce, KECCAK_NULL_RLP), |_| {})?.reset_code(code); Ok(()) } @@ -759,6 +859,7 @@ impl State { /// Commits our cached account changes into the trie. pub fn commit(&mut self) -> Result<(), Error> { + assert!(self.checkpoints.borrow().is_empty()); // first, commit the sub trees. let mut accounts = self.cache.borrow_mut(); for (address, ref mut a) in accounts.iter_mut().filter(|&(_, ref a)| a.is_dirty()) { @@ -804,6 +905,7 @@ impl State { /// Clear state cache pub fn clear(&mut self) { + assert!(self.checkpoints.borrow().is_empty()); self.cache.borrow_mut().clear(); } @@ -909,31 +1011,38 @@ impl State { Ok(pod_state::diff_pod(&pod_state_pre, &pod_state_post)) } - // load required account data from the databases. - fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB) { + /// Load required account data from the databases. Returns whether the cache succeeds. + #[must_use] + fn update_account_cache(require: RequireCache, account: &mut Account, state_db: &B, db: &HashDB) -> bool { if let RequireCache::None = require { - return; + return true; } if account.is_cached() { - return; + return true; } // if there's already code in the global cache, always cache it localy let hash = account.code_hash(); match state_db.get_cached_code(&hash) { - Some(code) => account.cache_given_code(code), + Some(code) => { + account.cache_given_code(code); + true + }, None => match require { - RequireCache::None => {}, + RequireCache::None => true, RequireCache::Code => { if let Some(code) = account.cache_code(db) { // propagate code loaded from the database to // the global code cache. - state_db.cache_code(hash, code) + state_db.cache_code(hash, code); + true + } else { + false } }, RequireCache::CodeSize => { - account.cache_code_size(db); + account.cache_code_size(db) } } } @@ -948,8 +1057,11 @@ impl State { if let Some(ref mut maybe_acc) = self.cache.borrow_mut().get_mut(a) { if let Some(ref mut account) = maybe_acc.account { let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); - Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); - return Ok(f(Some(account))); + if Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + return Ok(f(Some(account))); + } else { + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + } } return Ok(f(None)); } @@ -957,12 +1069,14 @@ impl State { let result = self.db.get_cached(a, |mut acc| { if let Some(ref mut account) = acc { let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); - Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); + if !Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + } } - f(acc.map(|a| &*a)) + Ok(f(acc.map(|a| &*a))) }); match result { - Some(r) => Ok(r), + Some(r) => Ok(r?), None => { // first check if it is not in database for sure if check_null && self.db.is_known_null(a) { return Ok(f(None)); } @@ -973,7 +1087,9 @@ impl State { let mut maybe_acc = db.get_with(a, from_rlp)?; if let Some(ref mut account) = maybe_acc.as_mut() { let accountdb = self.factories.accountdb.readonly(self.db.as_hashdb(), account.address_hash(a)); - Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()); + if !Self::update_account_cache(require, account, &self.db, accountdb.as_hashdb()) { + return Err(Box::new(TrieError::IncompleteDatabase(H256::from(a)))); + } } let r = f(maybe_acc.as_ref()); self.insert_cache(a, AccountEntry::new_clean(maybe_acc)); @@ -984,7 +1100,7 @@ impl State { /// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too. fn require<'a>(&'a self, a: &Address, require_code: bool) -> TrieResult> { - self.require_or_from(a, require_code, || Account::new_basic(0u8.into(), self.account_start_nonce), |_|{}) + self.require_or_from(a, require_code, || Account::new_basic(0u8.into(), self.account_start_nonce), |_| {}) } /// Pull account `a` in our cache from the trie DB. `require_code` requires that the code be cached, too. @@ -1124,7 +1240,7 @@ mod tests { use std::sync::Arc; use std::str::FromStr; use rustc_hex::FromHex; - use hash::keccak; + use hash::{keccak, KECCAK_NULL_RLP}; use super::*; use ethkey::Secret; use ethereum_types::{H256, U256, Address}; @@ -1976,7 +2092,7 @@ mod tests { let a = Address::zero(); let (root, db) = { let mut state = get_temp_state(); - state.require_or_from(&a, false, ||Account::new_contract(42.into(), 0.into()), |_|{}).unwrap(); + state.require_or_from(&a, false, || Account::new_contract(42.into(), 0.into(), KECCAK_NULL_RLP), |_|{}).unwrap(); state.init_code(&a, vec![1, 2, 3]).unwrap(); assert_eq!(state.code(&a).unwrap(), Some(Arc::new(vec![1u8, 2, 3]))); state.commit().unwrap(); @@ -2180,6 +2296,180 @@ mod tests { assert_eq!(state.balance(&a).unwrap(), U256::from(0)); } + #[test] + fn checkpoint_revert_to_get_storage_at() { + let mut state = get_temp_state(); + let a = Address::zero(); + let k = H256::from(U256::from(0)); + + let c0 = state.checkpoint(); + let c1 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1))); + + state.revert_to_checkpoint(); // Revert to c1. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + } + + #[test] + fn checkpoint_from_empty_get_storage_at() { + let mut state = get_temp_state(); + let a = Address::zero(); + let k = H256::from(U256::from(0)); + let k2 = H256::from(U256::from(1)); + + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + state.clear(); + + let c0 = state.checkpoint(); + state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); + let c1 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + let c2 = state.checkpoint(); + let c3 = state.checkpoint(); + state.set_storage(&a, k2, H256::from(U256::from(3))).unwrap(); + state.set_storage(&a, k, H256::from(U256::from(3))).unwrap(); + let c4 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(4))).unwrap(); + let c5 = state.checkpoint(); + + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3)))); + assert_eq!(state.checkpoint_storage_at(c5, &a, &k).unwrap(), Some(H256::from(U256::from(4)))); + + state.discard_checkpoint(); // Commit/discard c5. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3)))); + + state.revert_to_checkpoint(); // Revert to c4. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + + state.discard_checkpoint(); // Commit/discard c3. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + + state.revert_to_checkpoint(); // Revert to c2. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + + state.discard_checkpoint(); // Commit/discard c1. + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + } + + #[test] + fn checkpoint_get_storage_at() { + let mut state = get_temp_state(); + let a = Address::zero(); + let k = H256::from(U256::from(0)); + let k2 = H256::from(U256::from(1)); + + state.set_storage(&a, k, H256::from(U256::from(0xffff))).unwrap(); + state.commit().unwrap(); + state.clear(); + + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0xffff))); + state.clear(); + + let cm1 = state.checkpoint(); + let c0 = state.checkpoint(); + state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); + let c1 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + let c2 = state.checkpoint(); + let c3 = state.checkpoint(); + state.set_storage(&a, k2, H256::from(U256::from(3))).unwrap(); + state.set_storage(&a, k, H256::from(U256::from(3))).unwrap(); + let c4 = state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(4))).unwrap(); + let c5 = state.checkpoint(); + + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3)))); + assert_eq!(state.checkpoint_storage_at(c5, &a, &k).unwrap(), Some(H256::from(U256::from(4)))); + + state.discard_checkpoint(); // Commit/discard c5. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c4, &a, &k).unwrap(), Some(H256::from(U256::from(3)))); + + state.revert_to_checkpoint(); // Revert to c4. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + assert_eq!(state.checkpoint_storage_at(c3, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + + state.discard_checkpoint(); // Commit/discard c3. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + assert_eq!(state.checkpoint_storage_at(c2, &a, &k).unwrap(), Some(H256::from(U256::from(1)))); + + state.revert_to_checkpoint(); // Revert to c2. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c1, &a, &k).unwrap(), Some(H256::from(U256::from(0)))); + + state.discard_checkpoint(); // Commit/discard c1. + assert_eq!(state.checkpoint_storage_at(cm1, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + assert_eq!(state.checkpoint_storage_at(c0, &a, &k).unwrap(), Some(H256::from(U256::from(0xffff)))); + } + + #[test] + fn kill_account_with_checkpoints() { + let mut state = get_temp_state(); + let a = Address::zero(); + let k = H256::from(U256::from(0)); + state.checkpoint(); + state.set_storage(&a, k, H256::from(U256::from(1))).unwrap(); + state.checkpoint(); + state.kill_account(&a); + + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(0))); + state.revert_to_checkpoint(); + assert_eq!(state.storage_at(&a, &k).unwrap(), H256::from(U256::from(1))); + } + + #[test] + fn create_contract_fail() { + let mut state = get_temp_state(); + let orig_root = state.root().clone(); + let a: Address = 1000.into(); + + state.checkpoint(); // c1 + state.new_contract(&a, U256::zero(), U256::zero()).unwrap(); + state.add_balance(&a, &U256::from(1), CleanupMode::ForceCreate).unwrap(); + state.checkpoint(); // c2 + state.add_balance(&a, &U256::from(1), CleanupMode::ForceCreate).unwrap(); + state.discard_checkpoint(); // discard c2 + state.revert_to_checkpoint(); // revert to c1 + assert_eq!(state.exists(&a).unwrap(), false); + + state.commit().unwrap(); + assert_eq!(orig_root, state.root().clone()); + } + #[test] fn create_empty() { let mut state = get_temp_state(); @@ -2217,7 +2507,7 @@ mod tests { state.add_balance(&b, &100.into(), CleanupMode::ForceCreate).unwrap(); // create a dust account state.add_balance(&c, &101.into(), CleanupMode::ForceCreate).unwrap(); // create a normal account state.add_balance(&d, &99.into(), CleanupMode::ForceCreate).unwrap(); // create another dust account - state.new_contract(&e, 100.into(), 1.into()); // create a contract account + state.new_contract(&e, 100.into(), 1.into()).unwrap(); // create a contract account state.init_code(&e, vec![0x00]).unwrap(); state.commit().unwrap(); state.drop() diff --git a/ethcore/src/state/substate.rs b/ethcore/src/state/substate.rs index c2f3c62dc..054b8b384 100644 --- a/ethcore/src/state/substate.rs +++ b/ethcore/src/state/substate.rs @@ -34,8 +34,8 @@ pub struct Substate { /// Any logs. pub logs: Vec, - /// Refund counter of SSTORE nonzero -> zero. - pub sstore_clears_count: U256, + /// Refund counter of SSTORE. + pub sstore_clears_refund: U256, /// Created contracts. pub contracts_created: Vec
, @@ -52,7 +52,7 @@ impl Substate { self.suicides.extend(s.suicides); self.touched.extend(s.touched); self.logs.extend(s.logs); - self.sstore_clears_count = self.sstore_clears_count + s.sstore_clears_count; + self.sstore_clears_refund = self.sstore_clears_refund + s.sstore_clears_refund; self.contracts_created.extend(s.contracts_created); } @@ -86,7 +86,7 @@ mod tests { topics: vec![], data: vec![] }); - sub_state.sstore_clears_count = 5.into(); + sub_state.sstore_clears_refund = (15000 * 5).into(); sub_state.suicides.insert(10u64.into()); let mut sub_state_2 = Substate::new(); @@ -96,11 +96,11 @@ mod tests { topics: vec![], data: vec![] }); - sub_state_2.sstore_clears_count = 7.into(); + sub_state_2.sstore_clears_refund = (15000 * 7).into(); sub_state.accrue(sub_state_2); assert_eq!(sub_state.contracts_created.len(), 2); - assert_eq!(sub_state.sstore_clears_count, 12.into()); + assert_eq!(sub_state.sstore_clears_refund, (15000 * 12).into()); assert_eq!(sub_state.suicides.len(), 1); } } diff --git a/ethcore/src/tests/evm.rs b/ethcore/src/tests/evm.rs index 4f4ad4241..76d3928e4 100644 --- a/ethcore/src/tests/evm.rs +++ b/ethcore/src/tests/evm.rs @@ -39,7 +39,7 @@ fn test_blockhash_eip210(factory: Factory) { let test_blockhash_contract = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b61014a565b4360003512151561009057600060405260206040f35b610100600035430312156100b357610100600035075460605260206060f3610149565b62010000600035430312156100d157600061010060003507146100d4565b60005b156100f6576101006101006000350507610100015460805260206080f3610148565b630100000060003543031215610116576000620100006000350714610119565b60005b1561013c57610100620100006000350507610200015460a052602060a0f3610147565b600060c052602060c0f35b5b5b5b5b"; let blockhash_contract_code = Arc::new(test_blockhash_contract.from_hex().unwrap()); let blockhash_contract_code_hash = keccak(blockhash_contract_code.as_ref()); - let machine = ::ethereum::new_constantinople_test_machine(); + let machine = ::ethereum::new_eip210_test_machine(); let mut env_info = EnvInfo::default(); // populate state with 256 last hashes diff --git a/ethcore/transaction/src/transaction.rs b/ethcore/transaction/src/transaction.rs index 27b8b346c..b6434384b 100644 --- a/ethcore/transaction/src/transaction.rs +++ b/ethcore/transaction/src/transaction.rs @@ -387,23 +387,6 @@ impl UnverifiedTransaction { Ok(recover(&self.signature(), &self.unsigned.hash(self.chain_id()))?) } - /// Do basic validation, checking for valid signature and minimum gas, - // TODO: consider use in block validation. - #[cfg(feature = "json-tests")] - pub fn validate(self, schedule: &Schedule, require_low: bool, allow_chain_id_of_one: bool, allow_empty_signature: bool) - -> Result - { - let chain_id = if allow_chain_id_of_one { Some(1) } else { None }; - self.verify_basic(require_low, chain_id, allow_empty_signature)?; - if !allow_empty_signature || !self.is_unsigned() { - self.recover_public()?; - } - if self.gas < U256::from(self.gas_required(&schedule)) { - return Err(error::Error::InvalidGasLimit(::unexpected::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into()) - } - Ok(self) - } - /// Verify basic signature params. Does not attempt sender recovery. pub fn verify_basic(&self, check_low_s: bool, chain_id: Option, allow_empty_signature: bool) -> Result<(), error::Error> { if check_low_s && !(allow_empty_signature && self.is_unsigned()) { diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index 166e8712a..f0d21b1a2 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -51,18 +51,21 @@ pub enum MessageCallResult { } /// Specifies how an address is calculated for a new contract. -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum CreateContractAddress { - /// Address is calculated from nonce and sender. Pre EIP-86 (Metropolis) + /// Address is calculated from sender and nonce. pWASM `create` scheme. FromSenderAndNonce, - /// Address is calculated from code hash. Default since EIP-86 - FromCodeHash, - /// Address is calculated from code hash and sender. Used by CREATE_P2SH instruction. + /// Address is calculated from sender, salt and code hash. pWASM `create2` scheme and EIP-1014 CREATE2 scheme. + FromSenderSaltAndCodeHash(H256), + /// Address is calculated from code hash and sender. Used by pwasm create ext. FromSenderAndCodeHash, } /// Externalities interface for EVMs pub trait Ext { + /// Returns the storage value for a given key if reversion happens on the current transaction. + fn initial_storage_at(&self, key: &H256) -> Result; + /// Returns a value for given key. fn storage_at(&self, key: &H256) -> Result; @@ -106,10 +109,13 @@ pub trait Ext { ) -> MessageCallResult; /// Returns code at given address - fn extcode(&self, address: &Address) -> Result>; + fn extcode(&self, address: &Address) -> Result>>; + + /// Returns code hash at given address + fn extcodehash(&self, address: &Address) -> Result>; /// Returns code size at given address - fn extcodesize(&self, address: &Address) -> Result; + fn extcodesize(&self, address: &Address) -> Result>; /// Creates log entry with given topics and data fn log(&mut self, topics: Vec, data: &[u8]) -> Result<()>; @@ -134,8 +140,11 @@ pub trait Ext { /// then A depth is 0, B is 1, C is 2 and so on. fn depth(&self) -> usize; - /// Increments sstore refunds count by 1. - fn inc_sstore_clears(&mut self); + /// Increments sstore refunds counter. + fn add_sstore_refund(&mut self, value: U256); + + /// Decrements sstore refunds counter. + fn sub_sstore_refund(&mut self, value: U256); /// Decide if any more operations should be traced. Passthrough for the VM trace. fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _current_gas: U256) -> bool { false } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 960821e72..462e96b32 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -22,10 +22,12 @@ pub struct Schedule { pub exceptional_failed_code_deposit: bool, /// Does it have a delegate cal pub have_delegate_call: bool, - /// Does it have a CREATE_P2SH instruction + /// Does it have a CREATE2 instruction pub have_create2: bool, /// Does it have a REVERT instruction pub have_revert: bool, + /// Does it have a EXTCODEHASH instruction + pub have_extcodehash: bool, /// VM stack limit pub stack_limit: usize, /// Max number of nested calls/creates @@ -92,6 +94,8 @@ pub struct Schedule { pub extcodecopy_base_gas: usize, /// Price of BALANCE pub balance_gas: usize, + /// Price of EXTCODEHASH + pub extcodehash_gas: usize, /// Price of SUICIDE pub suicide_gas: usize, /// Amount of additional gas to pay when SUICIDE credits a non-existant account @@ -113,8 +117,10 @@ pub struct Schedule { pub have_bitwise_shifting: bool, /// Kill basic accounts below this balance if touched. pub kill_dust: CleanDustMode, - /// Enable EIP-86 rules - pub eip86: bool, + /// Enable EIP-1283 rules + pub eip1283: bool, + /// VM execution does not increase null signed address nonce if this field is true. + pub keep_unsigned_nonce: bool, /// Wasm extra schedule settings, if wasm activated pub wasm: Option, } @@ -145,6 +151,10 @@ pub struct WasmCosts { pub opcodes_mul: u32, /// Cost of wasm opcode is calculated as TABLE_ENTRY_COST * `opcodes_mul` / `opcodes_div` pub opcodes_div: u32, + /// Whether create2 extern function is activated. + pub have_create2: bool, + /// Whether gasleft extern function is activated. + pub have_gasleft: bool, } impl Default for WasmCosts { @@ -162,6 +172,8 @@ impl Default for WasmCosts { max_stack_height: 64*1024, opcodes_mul: 3, opcodes_div: 8, + have_create2: false, + have_gasleft: false, } } } @@ -197,6 +209,7 @@ impl Schedule { have_revert: false, have_return_data: false, have_bitwise_shifting: false, + have_extcodehash: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -229,6 +242,7 @@ impl Schedule { copy_gas: 3, extcodesize_gas: 700, extcodecopy_base_gas: 700, + extcodehash_gas: 400, balance_gas: 400, suicide_gas: 5000, suicide_to_new_account_cost: 25000, @@ -238,7 +252,8 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, - eip86: false, + eip1283: false, + keep_unsigned_nonce: false, wasm: None, } } @@ -268,6 +283,7 @@ impl Schedule { have_revert: false, have_return_data: false, have_bitwise_shifting: false, + have_extcodehash: false, stack_limit: 1024, max_depth: 1024, tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0], @@ -300,6 +316,7 @@ impl Schedule { copy_gas: 3, extcodesize_gas: 20, extcodecopy_base_gas: 20, + extcodehash_gas: 400, balance_gas: 20, suicide_gas: 0, suicide_to_new_account_cost: 0, @@ -309,7 +326,8 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, - eip86: false, + eip1283: false, + keep_unsigned_nonce: false, wasm: None, } } diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index 9a17e0d3d..ae7a96e28 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -24,6 +24,7 @@ use { ReturnData, Ext, ContractCreateResult, MessageCallResult, CreateContractAddress, Result, GasLeft, }; +use hash::keccak; pub struct FakeLogEntry { pub topics: Vec, @@ -38,6 +39,7 @@ pub enum FakeCallType { #[derive(PartialEq, Eq, Hash, Debug)] pub struct FakeCall { pub call_type: FakeCallType, + pub create_scheme: Option, pub gas: U256, pub sender_address: Option
, pub receive_address: Option
, @@ -54,7 +56,7 @@ pub struct FakeExt { pub store: HashMap, pub suicides: HashSet
, pub calls: HashSet, - pub sstore_clears: usize, + pub sstore_clears: U256, pub depth: usize, pub blockhashes: HashMap, pub codes: HashMap>, @@ -103,6 +105,10 @@ impl FakeExt { } impl Ext for FakeExt { + fn initial_storage_at(&self, _key: &H256) -> Result { + Ok(H256::new()) + } + fn storage_at(&self, key: &H256) -> Result { Ok(self.store.get(key).unwrap_or(&H256::new()).clone()) } @@ -132,9 +138,10 @@ impl Ext for FakeExt { self.blockhashes.get(number).unwrap_or(&H256::new()).clone() } - fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult { + fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult { self.calls.insert(FakeCall { call_type: FakeCallType::Create, + create_scheme: Some(address), gas: *gas, sender_address: None, receive_address: None, @@ -158,6 +165,7 @@ impl Ext for FakeExt { self.calls.insert(FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: *gas, sender_address: Some(sender_address.clone()), receive_address: Some(receive_address.clone()), @@ -168,12 +176,16 @@ impl Ext for FakeExt { MessageCallResult::Success(*gas, ReturnData::empty()) } - fn extcode(&self, address: &Address) -> Result> { - Ok(self.codes.get(address).unwrap_or(&Arc::new(Bytes::new())).clone()) + fn extcode(&self, address: &Address) -> Result>> { + Ok(self.codes.get(address).cloned()) } - fn extcodesize(&self, address: &Address) -> Result { - Ok(self.codes.get(address).map_or(0, |c| c.len())) + fn extcodesize(&self, address: &Address) -> Result> { + Ok(self.codes.get(address).map(|c| c.len())) + } + + fn extcodehash(&self, address: &Address) -> Result> { + Ok(self.codes.get(address).map(|c| keccak(c.as_ref()))) } fn log(&mut self, topics: Vec, data: &[u8]) -> Result<()> { @@ -209,8 +221,12 @@ impl Ext for FakeExt { self.is_static } - fn inc_sstore_clears(&mut self) { - self.sstore_clears += 1; + fn add_sstore_refund(&mut self, value: U256) { + self.sstore_clears = self.sstore_clears + value; + } + + fn sub_sstore_refund(&mut self, value: U256) { + self.sstore_clears = self.sstore_clears - value; } fn trace_next_instruction(&mut self, _pc: usize, _instruction: u8, _gas: U256) -> bool { diff --git a/ethcore/wasm/src/env.rs b/ethcore/wasm/src/env.rs index 9bcbee63f..fb9e93e0f 100644 --- a/ethcore/wasm/src/env.rs +++ b/ethcore/wasm/src/env.rs @@ -17,6 +17,7 @@ //! Env module glue for wasmi interpreter use std::cell::RefCell; +use vm::WasmCosts; use wasmi::{ self, Signature, Error, FuncRef, FuncInstance, MemoryDescriptor, MemoryRef, MemoryInstance, memory_units, @@ -47,6 +48,8 @@ pub mod ids { pub const SENDER_FUNC: usize = 190; pub const ORIGIN_FUNC: usize = 200; pub const ELOG_FUNC: usize = 210; + pub const CREATE2_FUNC: usize = 220; + pub const GASLEFT_FUNC: usize = 230; pub const PANIC_FUNC: usize = 1000; pub const DEBUG_FUNC: usize = 1010; @@ -125,6 +128,11 @@ pub mod signatures { Some(I32), ); + pub const CREATE2: StaticSignature = StaticSignature( + &[I32, I32, I32, I32, I32], + Some(I32), + ); + pub const SUICIDE: StaticSignature = StaticSignature( &[I32], None, @@ -150,6 +158,11 @@ pub mod signatures { None, ); + pub const GASLEFT: StaticSignature = StaticSignature( + &[], + Some(I64), + ); + pub const GASLIMIT: StaticSignature = StaticSignature( &[I32], None, @@ -195,18 +208,23 @@ fn host(signature: signatures::StaticSignature, idx: usize) -> FuncRef { /// Maps all functions that runtime support to the corresponding contract import /// entries. /// Also manages initial memory request from the runtime. -#[derive(Default)] pub struct ImportResolver { max_memory: u32, memory: RefCell>, + + have_create2: bool, + have_gasleft: bool, } impl ImportResolver { /// New import resolver with specifed maximum amount of inital memory (in wasm pages = 64kb) - pub fn with_limit(max_memory: u32) -> ImportResolver { + pub fn with_limit(max_memory: u32, schedule: &WasmCosts) -> ImportResolver { ImportResolver { max_memory: max_memory, memory: RefCell::new(None), + + have_create2: schedule.have_create2, + have_gasleft: schedule.have_gasleft, } } @@ -263,6 +281,8 @@ impl wasmi::ModuleImportResolver for ImportResolver { "sender" => host(signatures::SENDER, ids::SENDER_FUNC), "origin" => host(signatures::ORIGIN, ids::ORIGIN_FUNC), "elog" => host(signatures::ELOG, ids::ELOG_FUNC), + "create2" if self.have_create2 => host(signatures::CREATE2, ids::CREATE2_FUNC), + "gasleft" if self.have_gasleft => host(signatures::GASLEFT, ids::GASLEFT_FUNC), _ => { return Err(wasmi::Error::Instantiation( format!("Export {} not found", field_name), diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs index f1290318e..1fcfe9371 100644 --- a/ethcore/wasm/src/lib.rs +++ b/ethcore/wasm/src/lib.rs @@ -90,7 +90,7 @@ impl vm::Vm for WasmInterpreter { let loaded_module = wasmi::Module::from_parity_wasm_module(module).map_err(Error::Interpreter)?; - let instantiation_resolver = env::ImportResolver::with_limit(16); + let instantiation_resolver = env::ImportResolver::with_limit(16, ext.schedule().wasm()); let module_instance = wasmi::ModuleInstance::new( &loaded_module, diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index d99ab8645..d7a4855f9 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -284,7 +284,8 @@ impl<'a> Runtime<'a> { self.ext.set_storage(key, val).map_err(|_| Error::StorageUpdateError)?; if former_val != H256::zero() && val == H256::zero() { - self.ext.inc_sstore_clears(); + let sstore_clears_schedule = U256::from(self.schedule().sstore_refund_gas); + self.ext.add_sstore_refund(sstore_clears_schedule); } Ok(()) @@ -321,7 +322,7 @@ impl<'a> Runtime<'a> { if self.gas_counter > self.gas_limit { return Err(Error::InvalidGasState); } Ok(self.gas_limit - self.gas_counter) } - + /// General gas charging extern. fn gas(&mut self, args: RuntimeArgs) -> Result<()> { let amount: u32 = args.nth_checked(0)?; @@ -511,29 +512,7 @@ impl<'a> Runtime<'a> { self.return_u256_ptr(args.nth_checked(0)?, val) } - /// Creates a new contract - /// - /// Arguments: - /// * endowment - how much value (in Wei) transfer to the newly created contract - /// * code_ptr - pointer to the code data - /// * code_len - lenght of the code data - /// * result_ptr - pointer to write an address of the newly created contract - pub fn create(&mut self, args: RuntimeArgs) -> Result - { - // - // method signature: - // fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; - // - trace!(target: "wasm", "runtime: CREATE"); - let endowment = self.u256_at(args.nth_checked(0)?)?; - trace!(target: "wasm", " val: {:?}", endowment); - let code_ptr: u32 = args.nth_checked(1)?; - trace!(target: "wasm", " code_ptr: {:?}", code_ptr); - let code_len: u32 = args.nth_checked(2)?; - trace!(target: "wasm", " code_len: {:?}", code_len); - let result_ptr: u32 = args.nth_checked(3)?; - trace!(target: "wasm", "result_ptr: {:?}", result_ptr); - + fn do_create(&mut self, endowment: U256, code_ptr: u32, code_len: u32, result_ptr: u32, scheme: vm::CreateContractAddress) -> Result { let code = self.memory.get(code_ptr, code_len as usize)?; self.adjusted_charge(|schedule| schedule.create_gas as u64)?; @@ -543,7 +522,7 @@ impl<'a> Runtime<'a> { * U256::from(self.ext.schedule().wasm().opcodes_mul) / U256::from(self.ext.schedule().wasm().opcodes_div); - match self.ext.create(&gas_left, &endowment, &code, vm::CreateContractAddress::FromSenderAndCodeHash) { + match self.ext.create(&gas_left, &endowment, &code, scheme) { vm::ContractCreateResult::Created(address, gas_left) => { self.memory.set(result_ptr, &*address)?; self.gas_counter = self.gas_limit - @@ -571,6 +550,59 @@ impl<'a> Runtime<'a> { } } + /// Creates a new contract + /// + /// Arguments: + /// * endowment - how much value (in Wei) transfer to the newly created contract + /// * code_ptr - pointer to the code data + /// * code_len - lenght of the code data + /// * result_ptr - pointer to write an address of the newly created contract + pub fn create(&mut self, args: RuntimeArgs) -> Result { + // + // method signature: + // fn create(endowment: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; + // + trace!(target: "wasm", "runtime: CREATE"); + let endowment = self.u256_at(args.nth_checked(0)?)?; + trace!(target: "wasm", " val: {:?}", endowment); + let code_ptr: u32 = args.nth_checked(1)?; + trace!(target: "wasm", " code_ptr: {:?}", code_ptr); + let code_len: u32 = args.nth_checked(2)?; + trace!(target: "wasm", " code_len: {:?}", code_len); + let result_ptr: u32 = args.nth_checked(3)?; + trace!(target: "wasm", "result_ptr: {:?}", result_ptr); + + self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderAndCodeHash) + } + + /// Creates a new contract using FromSenderSaltAndCodeHash scheme + /// + /// Arguments: + /// * endowment - how much value (in Wei) transfer to the newly created contract + /// * salt - salt to be used in contract creation address + /// * code_ptr - pointer to the code data + /// * code_len - lenght of the code data + /// * result_ptr - pointer to write an address of the newly created contract + pub fn create2(&mut self, args: RuntimeArgs) -> Result { + // + // method signature: + // fn create2(endowment: *const u8, salt: *const u8, code_ptr: *const u8, code_len: u32, result_ptr: *mut u8) -> i32; + // + trace!(target: "wasm", "runtime: CREATE2"); + let endowment = self.u256_at(args.nth_checked(0)?)?; + trace!(target: "wasm", " val: {:?}", endowment); + let salt: H256 = self.u256_at(args.nth_checked(1)?)?.into(); + trace!(target: "wasm", " salt: {:?}", salt); + let code_ptr: u32 = args.nth_checked(2)?; + trace!(target: "wasm", " code_ptr: {:?}", code_ptr); + let code_len: u32 = args.nth_checked(3)?; + trace!(target: "wasm", " code_len: {:?}", code_len); + let result_ptr: u32 = args.nth_checked(4)?; + trace!(target: "wasm", "result_ptr: {:?}", result_ptr); + + self.do_create(endowment, code_ptr, code_len, result_ptr, vm::CreateContractAddress::FromSenderSaltAndCodeHash(salt)) + } + fn debug(&mut self, args: RuntimeArgs) -> Result<()> { trace!(target: "wasm", "Contract debug message: {}", { @@ -629,6 +661,15 @@ impl<'a> Runtime<'a> { self.return_u256_ptr(args.nth_checked(0)?, difficulty) } + /// Signature: `fn gasleft() -> i64` + pub fn gasleft(&mut self) -> Result { + Ok(RuntimeValue::from( + self.gas_left()? * self.ext.schedule().wasm().opcodes_mul as u64 + / self.ext.schedule().wasm().opcodes_div as u64 + ) + ) + } + /// Signature: `fn gaslimit(dest: *mut u8)` pub fn gaslimit(&mut self, args: RuntimeArgs) -> Result<()> { let gas_limit = self.ext.env_info().gas_limit; @@ -744,6 +785,8 @@ mod ext_impl { SENDER_FUNC => void!(self.sender(args)), ORIGIN_FUNC => void!(self.origin(args)), ELOG_FUNC => void!(self.elog(args)), + CREATE2_FUNC => some!(self.create2(args)), + GASLEFT_FUNC => some!(self.gasleft()), _ => panic!("env module doesn't provide function at index {}", index), } } diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index 726b9ebab..35898241d 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -20,7 +20,7 @@ use byteorder::{LittleEndian, ByteOrder}; use ethereum_types::{H256, U256, Address}; use super::WasmInterpreter; -use vm::{self, Vm, GasLeft, ActionParams, ActionValue}; +use vm::{self, Vm, GasLeft, ActionParams, ActionValue, CreateContractAddress}; use vm::tests::{FakeCall, FakeExt, FakeCallType}; macro_rules! load_sample { @@ -138,7 +138,7 @@ fn logger() { U256::from(1_000_000_000), "Logger sets 0x04 key to the trasferred value" ); - assert_eq!(gas_left, U256::from(16_181)); + assert_eq!(gas_left, U256::from(17_716)); } // This test checks if the contract can allocate memory and pass pointer to the result stream properly. @@ -173,7 +173,7 @@ fn identity() { sender, "Idenity test contract does not return the sender passed" ); - assert_eq!(gas_left, U256::from(96_883)); + assert_eq!(gas_left, U256::from(98_419)); } // Dispersion test sends byte array and expect the contract to 'disperse' the original elements with @@ -207,7 +207,7 @@ fn dispersion() { result, vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0] ); - assert_eq!(gas_left, U256::from(92_371)); + assert_eq!(gas_left, U256::from(92_377)); } #[test] @@ -267,7 +267,7 @@ fn suicide() { }; assert!(ext.suicides.contains(&refund)); - assert_eq!(gas_left, U256::from(93_348)); + assert_eq!(gas_left, U256::from(93_346)); } #[test] @@ -281,14 +281,19 @@ fn create() { params.value = ActionValue::transfer(1_000_000_000); let mut ext = FakeExt::new().with_wasm(); + ext.schedule.wasm.as_mut().unwrap().have_create2 = true; let gas_left = { let mut interpreter = wasm_interpreter(); let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); match result { - GasLeft::Known(gas) => gas, - GasLeft::NeedsReturn { .. } => { - panic!("Create contract should not return anthing because ext always fails on creation"); + GasLeft::Known(_) => { + panic!("Create contract always return 40 bytes of the creation address, or in the case where it fails, return 40 bytes of zero."); + }, + GasLeft::NeedsReturn { gas_left, data, apply_state } => { + assert!(apply_state); + assert_eq!(data.as_ref(), [0u8; 40].as_ref()); // FakeExt never succeeds in create. + gas_left }, } }; @@ -297,15 +302,28 @@ fn create() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Create, - gas: U256::from(59_269), + create_scheme: Some(CreateContractAddress::FromSenderAndCodeHash), + gas: U256::from(49_674), sender_address: None, receive_address: None, - value: Some(1_000_000_000.into()), + value: Some((1_000_000_000 / 2).into()), data: vec![0u8, 2, 4, 8, 16, 32, 64, 128], code_address: None, } )); - assert_eq!(gas_left, U256::from(59_212)); + assert!(ext.calls.contains( + &FakeCall { + call_type: FakeCallType::Create, + create_scheme: Some(CreateContractAddress::FromSenderSaltAndCodeHash(H256::from([5u8].as_ref()))), + gas: U256::from(6039), + sender_address: None, + receive_address: None, + value: Some((1_000_000_000 / 2).into()), + data: vec![0u8, 2, 4, 8, 16, 32, 64, 128], + code_address: None, + } + )); + assert_eq!(gas_left, U256::from(5974)); } #[test] @@ -340,6 +358,7 @@ fn call_msg() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(33_000), sender_address: Some(receiver), receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])), @@ -352,6 +371,54 @@ fn call_msg() { assert_eq!(gas_left, U256::from(91_672)); } +// The same as `call_msg`, but send a `pwasm_ethereum::gasleft` +// value as `gas` argument to the inner pwasm_ethereum::call +#[test] +fn call_msg_gasleft() { + ::ethcore_logger::init_log(); + + let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap(); + let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap(); + let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap(); + + let mut params = ActionParams::default(); + params.sender = sender.clone(); + params.address = receiver.clone(); + params.code_address = contract_address.clone(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(load_sample!("call_gasleft.wasm"))); + params.data = Some(Vec::new()); + + let mut ext = FakeExt::new().with_wasm(); + ext.schedule.wasm.as_mut().unwrap().have_gasleft = true; + ext.balances.insert(receiver.clone(), U256::from(10000000000u64)); + + let gas_left = { + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(gas_left) => gas_left, + GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); }, + } + }; + + trace!(target: "wasm", "fake_calls: {:?}", &ext.calls); + assert!(ext.calls.contains( + &FakeCall { + call_type: FakeCallType::Call, + create_scheme: None, + gas: U256::from(91_165), + sender_address: Some(receiver), + receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])), + value: Some(1000000000.into()), + data: vec![129u8, 123, 113, 107, 101, 97], + code_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])), + } + )); + + assert_eq!(gas_left, U256::from(91_671)); +} + #[test] fn call_code() { ::ethcore_logger::init_log(); @@ -382,6 +449,7 @@ fn call_code() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(20_000), sender_address: Some(sender), receive_address: Some(receiver), @@ -394,7 +462,7 @@ fn call_code() { // siphash result let res = LittleEndian::read_u32(&result[..]); assert_eq!(res, 4198595614); - assert_eq!(gas_left, U256::from(90_038)); + assert_eq!(gas_left, U256::from(90_037)); } #[test] @@ -429,6 +497,7 @@ fn call_static() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, + create_scheme: None, gas: U256::from(20_000), sender_address: Some(receiver), receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()), @@ -442,7 +511,7 @@ fn call_static() { let res = LittleEndian::read_u32(&result[..]); assert_eq!(res, 317632590); - assert_eq!(gas_left, U256::from(90_043)); + assert_eq!(gas_left, U256::from(90_042)); } // Realloc test @@ -465,7 +534,7 @@ fn realloc() { } }; assert_eq!(result, vec![0u8; 2]); - assert_eq!(gas_left, U256::from(92_842)); + assert_eq!(gas_left, U256::from(92_848)); } #[test] @@ -487,7 +556,7 @@ fn alloc() { } }; assert_eq!(result, vec![5u8; 1024*400]); - assert_eq!(gas_left, U256::from(6_893_883)); + assert_eq!(gas_left, U256::from(6_893_881)); } // Tests that contract's ability to read from a storage @@ -515,7 +584,7 @@ fn storage_read() { }; assert_eq!(Address::from(&result[12..32]), address); - assert_eq!(gas_left, U256::from(96_833)); + assert_eq!(gas_left, U256::from(98_369)); } // Tests keccak calculation @@ -541,7 +610,7 @@ fn keccak() { }; assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); - assert_eq!(gas_left, U256::from(84_134)); + assert_eq!(gas_left, U256::from(85_949)); } // math_* tests check the ability of wasm contract to perform big integer operations @@ -570,7 +639,7 @@ fn math_add() { U256::from_dec_str("1888888888888888888888888888887").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(92_086)); + assert_eq!(gas_left, U256::from(92_072)); } // multiplication @@ -592,7 +661,7 @@ fn math_mul() { U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(91_414)); + assert_eq!(gas_left, U256::from(91_400)); } // subtraction @@ -614,7 +683,7 @@ fn math_sub() { U256::from_dec_str("111111111111111111111111111111").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(92_086)); + assert_eq!(gas_left, U256::from(92_072)); } // subtraction with overflow @@ -656,7 +725,7 @@ fn math_div() { U256::from_dec_str("1125000").unwrap(), (&result[..]).into() ); - assert_eq!(gas_left, U256::from(87_376)); + assert_eq!(gas_left, U256::from(85_700)); } #[test] @@ -684,7 +753,7 @@ fn storage_metering() { }; // 0 -> not 0 - assert_eq!(gas_left, U256::from(72_399)); + assert_eq!(gas_left, U256::from(72_164)); // #2 @@ -703,7 +772,7 @@ fn storage_metering() { }; // not 0 -> not 0 - assert_eq!(gas_left, U256::from(87_399)); + assert_eq!(gas_left, U256::from(87_164)); } // This test checks the ability of wasm contract to invoke @@ -791,7 +860,48 @@ fn externs() { "Gas limit requested and returned does not match" ); - assert_eq!(gas_left, U256::from(90_435)); + assert_eq!(gas_left, U256::from(90_428)); +} + +// This test checks the ability of wasm contract to invoke gasleft +#[test] +fn gasleft() { + ::ethcore_logger::init_log(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(load_sample!("gasleft.wasm"))); + + let mut ext = FakeExt::new().with_wasm(); + ext.schedule.wasm.as_mut().unwrap().have_gasleft = true; + + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(_) => {}, + GasLeft::NeedsReturn { gas_left, data, .. } => { + let gas = LittleEndian::read_u64(data.as_ref()); + assert_eq!(gas, 93_423); + assert_eq!(gas_left, U256::from(93_349)); + }, + } +} + +// This test should fail because +// ext.schedule.wasm.as_mut().unwrap().have_gasleft = false; +#[test] +fn gasleft_fail() { + ::ethcore_logger::init_log(); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(load_sample!("gasleft.wasm"))); + let mut ext = FakeExt::new().with_wasm(); + let mut interpreter = wasm_interpreter(); + match interpreter.exec(params, &mut ext) { + Err(_) => {}, + Ok(_) => panic!("interpreter.exec should return Err if ext.schedule.wasm.have_gasleft = false") + } } #[test] @@ -817,7 +927,7 @@ fn embedded_keccak() { }; assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); - assert_eq!(gas_left, U256::from(84_134)); + assert_eq!(gas_left, U256::from(85_949)); } /// This test checks the correctness of log extern @@ -852,7 +962,7 @@ fn events() { assert_eq!(&log_entry.data, b"gnihtemos"); assert_eq!(&result, b"gnihtemos"); - assert_eq!(gas_left, U256::from(81_351)); + assert_eq!(gas_left, U256::from(83_161)); } #[test] diff --git a/evmbin/src/info.rs b/evmbin/src/info.rs index ce824fe17..67f76fe78 100644 --- a/evmbin/src/info.rs +++ b/evmbin/src/info.rs @@ -84,7 +84,7 @@ pub fn run_action( pub fn run_transaction( name: &str, idx: usize, - spec: ðjson::state::test::ForkSpec, + spec: ðjson::spec::ForkSpec, pre_state: &pod_state::PodState, post_root: H256, env_info: &client::EnvInfo, diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 9e4d650b8..ff0bc556f 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -21,8 +21,7 @@ use hash::H256; use blockchain::state::State; use blockchain::header::Header; use blockchain::block::Block; -use state::test::ForkSpec; -use spec::{Genesis, Seal, Ethereum}; +use spec::{ForkSpec, Genesis, Seal, Ethereum}; /// Blockchain deserialization. #[derive(Debug, PartialEq, Deserialize)] diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index fd6b9fca5..806a940a2 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -116,6 +116,18 @@ pub struct EthashParams { #[serde(rename="eip649Reward")] pub eip649_reward: Option, + /// EIP-1234 transition block. + #[serde(rename="eip1234Transition")] + pub eip1234_transition: Option, + + /// EIP-1234 bomb delay. + #[serde(rename="eip1234Delay")] + pub eip1234_delay: Option, + + /// EIP-1234 base reward. + #[serde(rename="eip1234Reward")] + pub eip1234_reward: Option, + /// EXPIP-2 block height #[serde(rename="expip2Transition")] pub expip2_transition: Option, @@ -231,6 +243,9 @@ mod tests { eip649_transition: None, eip649_delay: None, eip649_reward: None, + eip1234_transition: None, + eip1234_delay: None, + eip1234_reward: None, expip2_transition: None, expip2_duration_limit: None, } @@ -275,6 +290,9 @@ mod tests { eip649_transition: None, eip649_delay: None, eip649_reward: None, + eip1234_transition: None, + eip1234_delay: None, + eip1234_reward: None, expip2_transition: None, expip2_duration_limit: None, } diff --git a/json/src/spec/mod.rs b/json/src/spec/mod.rs index 26965c887..fdede4a47 100644 --- a/json/src/spec/mod.rs +++ b/json/src/spec/mod.rs @@ -36,7 +36,7 @@ pub use self::account::Account; pub use self::builtin::{Builtin, Pricing, Linear}; pub use self::genesis::Genesis; pub use self::params::Params; -pub use self::spec::Spec; +pub use self::spec::{Spec, ForkSpec}; pub use self::seal::{Seal, Ethereum, AuthorityRoundSeal, TendermintSeal}; pub use self::engine::Engine; pub use self::state::State; diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index e03fe7081..624be09cb 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -79,9 +79,6 @@ pub struct Params { #[serde(rename="validateReceiptsTransition")] pub validate_receipts_transition: Option, /// See `CommonParams` docs. - #[serde(rename="eip86Transition")] - pub eip86_transition: Option, - /// See `CommonParams` docs. #[serde(rename="eip140Transition")] pub eip140_transition: Option, /// See `CommonParams` docs. @@ -109,6 +106,14 @@ pub struct Params { #[serde(rename="eip658Transition")] pub eip658_transition: Option, /// See `CommonParams` docs. + #[serde(rename="eip1052Transition")] + pub eip1052_transition: Option, + /// See `CommonParams` docs. + #[serde(rename="eip1283Transition")] + pub eip1283_transition: Option, + #[serde(rename="eip1014Transition")] + pub eip1014_transition: Option, + /// See `CommonParams` docs. #[serde(rename="dustProtectionTransition")] pub dust_protection_transition: Option, /// See `CommonParams` docs. @@ -143,6 +148,12 @@ pub struct Params { /// Wasm activation block height, if not activated from start #[serde(rename="wasmActivationTransition")] pub wasm_activation_transition: Option, + /// KIP4 activiation block height. + #[serde(rename="kip4Transition")] + pub kip4_transition: Option, + /// KIP6 activiation block height. + #[serde(rename="kip6Transition")] + pub kip6_transition: Option, } #[cfg(test)] diff --git a/json/src/spec/spec.rs b/json/src/spec/spec.rs index 2be695689..a15d1faf6 100644 --- a/json/src/spec/spec.rs +++ b/json/src/spec/spec.rs @@ -21,6 +21,21 @@ use serde_json; use serde_json::Error; use spec::{Params, Genesis, Engine, State, HardcodedSync}; +/// Fork spec definition +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)] +pub enum ForkSpec { + EIP150, + EIP158, + Frontier, + Homestead, + Byzantium, + Constantinople, + EIP158ToByzantiumAt5, + FrontierToHomesteadAt5, + HomesteadToDaoAt5, + HomesteadToEIP150At5, +} + /// Spec deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct Spec { diff --git a/json/src/state/test.rs b/json/src/state/test.rs index 528a49b5a..85eac0c93 100644 --- a/json/src/state/test.rs +++ b/json/src/state/test.rs @@ -21,6 +21,7 @@ use std::collections::BTreeMap; use uint::Uint; use bytes::Bytes; use hash::{Address, H256}; +use spec::ForkSpec; use state::{Env, AccountState, Transaction}; use maybe::MaybeEmpty; use serde_json::{self, Error}; @@ -97,21 +98,6 @@ impl MultiTransaction { } } -/// State test transaction deserialization. -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)] -pub enum ForkSpec { - EIP150, - EIP158, - Frontier, - Homestead, - Byzantium, - Constantinople, - EIP158ToByzantiumAt5, - FrontierToHomesteadAt5, - HomesteadToDaoAt5, - HomesteadToEIP150At5, -} - /// State test indexes deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct PostStateIndexes { diff --git a/json/src/test/mod.rs b/json/src/test/mod.rs index 8f95a9aec..e6148e0d0 100644 --- a/json/src/test/mod.rs +++ b/json/src/test/mod.rs @@ -45,6 +45,7 @@ pub struct DifficultyTestCase { #[serde(rename="currentBlockNumber")] pub current_block_number: Uint, } + /// Blockchain test deserializer. #[derive(Debug, PartialEq, Deserialize)] pub struct DifficultyTest(BTreeMap); @@ -64,3 +65,59 @@ impl DifficultyTest { serde_json::from_reader(reader) } } + +/// Test to skip (only if issue ongoing) +#[derive(Debug, PartialEq, Deserialize)] +pub struct SkipStates { + /// Block tests + pub block: Vec, + /// State tests + pub state: Vec, + +} + +/// Block test to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct BlockSkipStates { + /// Issue reference. + pub reference: String, + /// Test failing name. + pub failing: String, + /// Items failing for the test. + pub subtests: Vec, +} + +/// State test to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct StateSkipStates { + /// Issue reference. + pub reference: String, + /// Test failing name. + pub failing: String, + /// Items failing for the test. + pub subtests: BTreeMap +} + +/// State subtest to skip. +#[derive(Debug, PartialEq, Deserialize)] +pub struct StateSkipSubStates { + /// State test number of this item. Or '*' for all state. + pub subnumbers: Vec, + /// Chain for this items. + pub chain: String, +} + +impl SkipStates { + /// Loads skip states from json. + pub fn load(reader: R) -> Result where R: Read { + serde_json::from_reader(reader) + } + + /// Empty skip states. + pub fn empty() -> Self { + SkipStates { + block: Vec::new(), + state: Vec::new(), + } + } +} diff --git a/json/src/transaction/test.rs b/json/src/transaction/test.rs index e1bd588de..2c5f39f13 100644 --- a/json/src/transaction/test.rs +++ b/json/src/transaction/test.rs @@ -23,7 +23,7 @@ use serde_json::Error; use transaction::TransactionTest; /// TransactionTest test deserializer. -#[derive(Debug, PartialEq, Deserialize)] +#[derive(Debug, Deserialize)] pub struct Test(BTreeMap); impl IntoIterator for Test { diff --git a/json/src/transaction/txtest.rs b/json/src/transaction/txtest.rs index 60d65e70d..2be035b4f 100644 --- a/json/src/transaction/txtest.rs +++ b/json/src/transaction/txtest.rs @@ -16,23 +16,29 @@ //! Transaction test deserialization. -use uint::Uint; +use std::collections::BTreeMap; use bytes::Bytes; use hash::Address; -use transaction::Transaction; +use hash::H256; +use spec::ForkSpec; /// Transaction test deserialization. -#[derive(Debug, PartialEq, Deserialize)] +#[derive(Debug, Deserialize)] pub struct TransactionTest { - /// Block number. - #[serde(rename="blocknumber")] - pub block_number: Option, - /// Transaction rlp. pub rlp: Bytes, + pub _info: ::serde::de::IgnoredAny, + #[serde(flatten)] + pub post_state: BTreeMap, +} + +/// TransactionTest post state. +#[derive(Debug, PartialEq, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct PostState { /// Transaction sender. pub sender: Option
, - /// Transaction - pub transaction: Option, + /// Transaction hash. + pub hash: Option, } #[cfg(test)] @@ -43,21 +49,34 @@ mod tests { #[test] fn transaction_deserialization() { let s = r#"{ - "blocknumber" : "0", - "rlp" : "0xf83f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870b801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a3664935301", - "sender" : "e115cf6bb5656786569dd273705242ca72d84bc0", - "transaction" : { - "data" : "", - "gasLimit" : "0x5208", - "gasPrice" : "0x01", - "nonce" : "0x00", - "r" : "0x48b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353", - "s" : "0x01", - "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", - "v" : "0x1b", - "value" : "0x0b" - } + "Byzantium" : { + "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", + "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" + }, + "Constantinople" : { + "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", + "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" + }, + "EIP150" : { + }, + "EIP158" : { + "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", + "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" + }, + "Frontier" : { + }, + "Homestead" : { + }, + "_info" : { + "comment" : "", + "filledwith" : "cpp-1.3.0+commit.1829957d.Linux.g++", + "lllcversion" : "Version: 0.4.18-develop.2017.10.11+commit.81f9f86c.Linux.g++", + "source" : "src/TransactionTestsFiller/ttVValue/V_equals37Filler.json", + "sourceHash" : "89ef69312d4c0b4e3742da501263d23d2a64f180258ac93940997ac6a17b9b19" + }, + "rlp" : "0xf865808698852840a46f82d6d894095e7baea6a6c7c4c2dfeb977efac326af552d87808025a098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa01887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3" }"#; + let _deserialized: TransactionTest = serde_json::from_str(s).unwrap(); // TODO: validate all fields } diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index c6f10400a..9b789a56b 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -178,8 +178,7 @@ impl Dispatcher } fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { - let block_number = self.client.best_block_header().number(); - RpcRichRawTransaction::from_signed(signed_transaction, block_number, self.client.eip86_transition()) + RpcRichRawTransaction::from_signed(signed_transaction) } fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { @@ -405,8 +404,7 @@ impl Dispatcher for LightDispatcher { } fn enrich(&self, signed_transaction: SignedTransaction) -> RpcRichRawTransaction { - let block_number = self.client.best_block_header().number(); - RpcRichRawTransaction::from_signed(signed_transaction, block_number, self.client.eip86_transition()) + RpcRichRawTransaction::from_signed(signed_transaction) } fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result { diff --git a/rpc/src/v1/helpers/light_fetch.rs b/rpc/src/v1/helpers/light_fetch.rs index 2ec3af631..b6afde3df 100644 --- a/rpc/src/v1/helpers/light_fetch.rs +++ b/rpc/src/v1/helpers/light_fetch.rs @@ -68,7 +68,7 @@ pub struct LightFetch { } /// Extract a transaction at given index. -pub fn extract_transaction_at_index(block: encoded::Block, index: usize, eip86_transition: u64) -> Option { +pub fn extract_transaction_at_index(block: encoded::Block, index: usize) -> Option { block.transactions().into_iter().nth(index) // Verify if transaction signature is correct. .and_then(|tx| SignedTransaction::new(tx).ok()) @@ -87,7 +87,7 @@ pub fn extract_transaction_at_index(block: encoded::Block, index: usize, eip86_t cached_sender, } }) - .map(|tx| Transaction::from_localized(tx, eip86_transition)) + .map(|tx| Transaction::from_localized(tx)) } // extract the header indicated by the given `HeaderRef` from the given responses. @@ -367,7 +367,7 @@ impl LightFetch { // Get a transaction by hash. also returns the index in the block. // Only returns transactions in the canonical chain. - pub fn transaction_by_hash(&self, tx_hash: H256, eip86_transition: u64) + pub fn transaction_by_hash(&self, tx_hash: H256) -> impl Future, Error = Error> + Send { let params = (self.sync.clone(), self.on_demand.clone()); @@ -399,7 +399,7 @@ impl LightFetch { } let index = index.index as usize; - let transaction = extract_transaction_at_index(blk, index, eip86_transition); + let transaction = extract_transaction_at_index(blk, index); if transaction.as_ref().map_or(true, |tx| tx.hash != tx_hash.into()) { // index is actively wrong: indicated block has diff --git a/rpc/src/v1/impls/eth.rs b/rpc/src/v1/impls/eth.rs index 5717dd70d..e47f0c925 100644 --- a/rpc/src/v1/impls/eth.rs +++ b/rpc/src/v1/impls/eth.rs @@ -106,7 +106,6 @@ pub struct EthClient where external_miner: Arc, seed_compute: Mutex, options: EthClientOptions, - eip86_transition: u64, } #[derive(Debug)] @@ -168,7 +167,6 @@ impl EthClient EthClient BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t, self.eip86_transition)).collect()), + true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t)).collect()), false => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()), }, extra_data: Bytes::new(view.extra_data()), @@ -267,7 +265,7 @@ impl EthClient Result> { let client_transaction = |id| match self.client.transaction(id) { - Some(t) => Ok(Some(Transaction::from_localized(t, self.eip86_transition))), + Some(t) => Ok(Some(Transaction::from_localized(t))), None => Ok(None), }; @@ -304,7 +302,7 @@ impl EthClient Eth for EthClient< fn transaction_by_hash(&self, hash: RpcH256) -> BoxFuture> { let hash: H256 = hash.into(); - let block_number = self.client.chain_info().best_block_number; let tx = try_bf!(self.transaction(PendingTransactionId::Hash(hash))).or_else(|| { self.miner.transaction(&hash) - .map(|t| Transaction::from_pending(t.pending().clone(), block_number + 1, self.eip86_transition)) + .map(|t| Transaction::from_pending(t.pending().clone())) }); Box::new(future::ok(tx)) diff --git a/rpc/src/v1/impls/light/eth.rs b/rpc/src/v1/impls/light/eth.rs index d90deb648..b0ec0abad 100644 --- a/rpc/src/v1/impls/light/eth.rs +++ b/rpc/src/v1/impls/light/eth.rs @@ -142,7 +142,6 @@ impl EthClient { fn rich_block(&self, id: BlockId, include_txs: bool) -> BoxFuture { let (on_demand, sync) = (self.on_demand.clone(), self.sync.clone()); let (client, engine) = (self.client.clone(), self.client.engine().clone()); - let eip86_transition = self.client.eip86_transition(); // helper for filling out a rich block once we've got a block and a score. let fill_rich = move |block: encoded::Block, score: Option| { @@ -169,7 +168,7 @@ impl EthClient { seal_fields: header.seal().into_iter().cloned().map(Into::into).collect(), uncles: block.uncle_hashes().into_iter().map(Into::into).collect(), transactions: match include_txs { - true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t, eip86_transition)).collect()), + true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t)).collect()), _ => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()), }, extra_data: Bytes::new(header.extra_data().clone()), @@ -419,40 +418,34 @@ impl Eth for EthClient { fn transaction_by_hash(&self, hash: RpcH256) -> BoxFuture> { let hash = hash.into(); - let eip86 = self.client.eip86_transition(); { let tx_queue = self.transaction_queue.read(); if let Some(tx) = tx_queue.get(&hash) { return Box::new(future::ok(Some(Transaction::from_pending( tx.clone(), - self.client.chain_info().best_block_number, - eip86, )))); } } - Box::new(self.fetcher().transaction_by_hash(hash, eip86).map(|x| x.map(|(tx, _)| tx))) + Box::new(self.fetcher().transaction_by_hash(hash).map(|x| x.map(|(tx, _)| tx))) } fn transaction_by_block_hash_and_index(&self, hash: RpcH256, idx: Index) -> BoxFuture> { - let eip86 = self.client.eip86_transition(); Box::new(self.fetcher().block(BlockId::Hash(hash.into())).map(move |block| { - light_fetch::extract_transaction_at_index(block, idx.value(), eip86) + light_fetch::extract_transaction_at_index(block, idx.value()) })) } fn transaction_by_block_number_and_index(&self, num: BlockNumber, idx: Index) -> BoxFuture> { - let eip86 = self.client.eip86_transition(); Box::new(self.fetcher().block(Self::num_to_id(num)).map(move |block| { - light_fetch::extract_transaction_at_index(block, idx.value(), eip86) + light_fetch::extract_transaction_at_index(block, idx.value()) })) } fn transaction_receipt(&self, hash: RpcH256) -> BoxFuture> { - let eip86 = self.client.eip86_transition(); let fetcher = self.fetcher(); - Box::new(fetcher.transaction_by_hash(hash.clone().into(), eip86).and_then(move |tx| { + Box::new(fetcher.transaction_by_hash(hash.clone().into()).and_then(move |tx| { // the block hash included in the transaction object here has // already been checked for canonicality and whether it contains // the transaction. diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 3fd528d03..f74886e61 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -57,7 +57,6 @@ pub struct ParityClient { settings: Arc, signer: Option>, ws_address: Option, - eip86_transition: u64, gas_price_percentile: usize, } @@ -80,7 +79,6 @@ impl ParityClient { settings, signer, ws_address, - eip86_transition: client.eip86_transition(), client, gas_price_percentile, } @@ -260,7 +258,7 @@ impl Parity for ParityClient { txq.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp) .into_iter() .take(limit.unwrap_or_else(usize::max_value)) - .map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition)) + .map(|tx| Transaction::from_pending(tx)) .collect::>() ) } @@ -275,7 +273,7 @@ impl Parity for ParityClient { current .into_iter() .chain(future.into_iter()) - .map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition)) + .map(|tx| Transaction::from_pending(tx)) .collect::>() ) } @@ -286,7 +284,7 @@ impl Parity for ParityClient { Ok( txq.future_transactions(chain_info.best_block_number, chain_info.best_block_timestamp) .into_iter() - .map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition)) + .map(|tx| Transaction::from_pending(tx)) .collect::>() ) } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index 9f825ba89..3e20d5821 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -62,7 +62,6 @@ pub struct ParityClient { settings: Arc, signer: Option>, ws_address: Option, - eip86_transition: u64, } impl ParityClient where @@ -81,7 +80,6 @@ impl ParityClient where signer: Option>, ws_address: Option, ) -> Self { - let eip86_transition = client.eip86_transition(); ParityClient { client, miner, @@ -93,7 +91,6 @@ impl ParityClient where settings, signer, ws_address, - eip86_transition, } } } @@ -289,7 +286,6 @@ impl Parity for ParityClient where } fn pending_transactions(&self, limit: Trailing) -> Result> { - let block_number = self.client.chain_info().best_block_number; let ready_transactions = self.miner.ready_transactions( &*self.client, limit.unwrap_or_else(usize::max_value), @@ -298,18 +294,17 @@ impl Parity for ParityClient where Ok(ready_transactions .into_iter() - .map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition)) + .map(|t| Transaction::from_pending(t.pending().clone())) .collect() ) } fn all_transactions(&self) -> Result> { - let block_number = self.client.chain_info().best_block_number; let all_transactions = self.miner.queued_transactions(); Ok(all_transactions .into_iter() - .map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition)) + .map(|t| Transaction::from_pending(t.pending().clone())) .collect() ) } @@ -328,10 +323,9 @@ impl Parity for ParityClient where fn local_transactions(&self) -> Result> { let transactions = self.miner.local_transactions(); - let block_number = self.client.chain_info().best_block_number; Ok(transactions .into_iter() - .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status, block_number, self.eip86_transition))) + .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status))) .collect() ) } diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index c811b3e5d..9bbb7ceab 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -41,7 +41,6 @@ pub struct ParitySetClient { net: Arc, fetch: F, pool: CpuPool, - eip86_transition: u64, } impl ParitySetClient @@ -63,7 +62,6 @@ impl ParitySetClient net: net.clone(), fetch: fetch, pool: pool, - eip86_transition: client.eip86_transition(), } } } @@ -191,11 +189,10 @@ impl ParitySet for ParitySetClient where } fn remove_transaction(&self, hash: H256) -> Result> { - let block_number = self.client.chain_info().best_block_number; let hash = hash.into(); Ok(self.miner.remove_transaction(&hash) - .map(|t| Transaction::from_pending(t.pending().clone(), block_number + 1, self.eip86_transition)) + .map(|t| Transaction::from_pending(t.pending().clone())) ) } } diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 6e3b9855d..ba9cfcc74 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -29,7 +29,7 @@ use ethcore::spec::{Genesis, Spec}; use ethcore::test_helpers; use ethcore::views::BlockView; use ethjson::blockchain::BlockChain; -use ethjson::state::test::ForkSpec; +use ethjson::spec::ForkSpec; use io::IoChannel; use miner::external::ExternalMiner; use parking_lot::Mutex; diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index 632d8fb76..c063ee096 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -339,7 +339,7 @@ fn should_add_sign_transaction_to_the_queue() { // respond let sender = signer.take(&1.into()).unwrap(); signer.request_confirmed(sender, Ok(ConfirmationResponse::SignTransaction( - RichRawTransaction::from_signed(t.into(), 0x0, u64::max_value()) + RichRawTransaction::from_signed(t.into()) ))); break } diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index d41fc84e0..4266f60b6 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -161,8 +161,8 @@ pub struct RichRawTransaction { impl RichRawTransaction { /// Creates new `RichRawTransaction` from `SignedTransaction`. - pub fn from_signed(tx: SignedTransaction, block_number: u64, eip86_transition: u64) -> Self { - let tx = Transaction::from_signed(tx, block_number, eip86_transition); + pub fn from_signed(tx: SignedTransaction) -> Self { + let tx = Transaction::from_signed(tx); RichRawTransaction { raw: tx.raw.clone(), transaction: tx, @@ -172,9 +172,9 @@ impl RichRawTransaction { impl Transaction { /// Convert `LocalizedTransaction` into RPC Transaction. - pub fn from_localized(mut t: LocalizedTransaction, eip86_transition: u64) -> Transaction { + pub fn from_localized(mut t: LocalizedTransaction) -> Transaction { let signature = t.signature(); - let scheme = if t.block_number >= eip86_transition { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce }; + let scheme = CreateContractAddress::FromSenderAndNonce; Transaction { hash: t.hash().into(), nonce: t.nonce.into(), @@ -206,9 +206,9 @@ impl Transaction { } /// Convert `SignedTransaction` into RPC Transaction. - pub fn from_signed(t: SignedTransaction, block_number: u64, eip86_transition: u64) -> Transaction { + pub fn from_signed(t: SignedTransaction) -> Transaction { let signature = t.signature(); - let scheme = if block_number >= eip86_transition { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce }; + let scheme = CreateContractAddress::FromSenderAndNonce; Transaction { hash: t.hash().into(), nonce: t.nonce.into(), @@ -240,8 +240,8 @@ impl Transaction { } /// Convert `PendingTransaction` into RPC Transaction. - pub fn from_pending(t: PendingTransaction, block_number: u64, eip86_transition: u64) -> Transaction { - let mut r = Transaction::from_signed(t.transaction, block_number, eip86_transition); + pub fn from_pending(t: PendingTransaction) -> Transaction { + let mut r = Transaction::from_signed(t.transaction); r.condition = t.condition.map(|b| b.into()); r } @@ -249,9 +249,9 @@ impl Transaction { impl LocalTransactionStatus { /// Convert `LocalTransactionStatus` into RPC `LocalTransactionStatus`. - pub fn from(s: miner::pool::local_transactions::Status, block_number: u64, eip86_transition: u64) -> Self { + pub fn from(s: miner::pool::local_transactions::Status) -> Self { let convert = |tx: Arc| { - Transaction::from_signed(tx.signed().clone(), block_number, eip86_transition) + Transaction::from_signed(tx.signed().clone()) }; use miner::pool::local_transactions::Status::*; match s { diff --git a/test.sh b/test.sh index 63ea22d77..b49dfadaf 100755 --- a/test.sh +++ b/test.sh @@ -1,7 +1,7 @@ #!/bin/sh # Running Parity Full Test Suite -FEATURES="json-tests" +FEATURES="json-tests,ci-skip-issue" OPTIONS="--release" VALIDATE=1 THREADS=8