diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 3a2a92f21..366a51ffa 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -303,7 +303,7 @@ lazy_static! { arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special); arr[STATICCALL as usize] = InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special); arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special); - arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special); + arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 4, 1, GasPriceTier::Special); arr[REVERT as usize] = 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 01b09b483..5a8979a25 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -235,7 +235,11 @@ impl Gasometer { } instructions::CREATE | instructions::CREATE2 => { let gas = Gas::from(schedule.create_gas); - let mem = mem_needed(stack.peek(1), stack.peek(2))?; + let mem = match instruction { + instructions::CREATE => mem_needed(stack.peek(1), stack.peek(2))?, + instructions::CREATE2 => mem_needed(stack.peek(2), stack.peek(3))?, + _ => unreachable!("instruction can only be CREATE/CREATE2 checked above; qed"), + }; Request::GasMemProvide(gas, mem, None) } diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index 486356e22..d960d4569 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -361,6 +361,13 @@ impl Interpreter { } instructions::CREATE | instructions::CREATE2 => { let endowment = 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 init_off = stack.pop_back(); let init_size = stack.pop_back(); @@ -381,11 +388,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(), diff --git a/ethcore/src/executed.rs b/ethcore/src/executed.rs index d476dfce7..6c406f51e 100644 --- a/ethcore/src/executed.rs +++ b/ethcore/src/executed.rs @@ -117,6 +117,8 @@ pub enum ExecutionError { TransactionMalformed(String), /// Returned when a non-confidential transaction execution is requested in confidential mode. NotConfidential, + /// For confidential transactions, the code at address was not what was expected. + InvalidCode, } impl From> for ExecutionError { @@ -169,6 +171,7 @@ impl fmt::Display for ExecutionError { SenderMustExist => write!(f, "Transacting from an empty account"), Internal(ref msg) => write!(f, "{}", msg), TransactionMalformed(ref err) => write!(f, "Malformed transaction: {}", err), + InvalidCode => write!(f, "Invalid code found in state"), NotConfidential => write!( f, "Tried executing a non-confidential transaction in confidential mode" diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 8856207b8..c6cd735f8 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -68,17 +68,26 @@ pub fn contract_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; 20 + 32 + 32]; + buffer[0..20].copy_from_slice(&sender[..]); + buffer[20..(20 + 32)].copy_from_slice(&salt[..]); + buffer[(20 + 32)..].copy_from_slice(&code_hash[..]); + (From::from(keccak(&buffer[..])), Some(code_hash)) + } + CreateContractAddress::FromSaltAndCodeHash(salt) => { + let code_hash = keccak(code); + let mut buffer = [0u8; 32 + 32]; + buffer[0..32].copy_from_slice(&salt[..]); + buffer[32..].copy_from_slice(&code_hash[..]); (From::from(keccak(&buffer[..])), Some(code_hash)) } CreateContractAddress::FromSenderAndCodeHash => { let code_hash = keccak(code); let mut buffer = [0u8; 20 + 32]; - &mut buffer[..20].copy_from_slice(&sender[..]); - &mut buffer[20..].copy_from_slice(&code_hash[..]); + buffer[..20].copy_from_slice(&sender[..]); + buffer[20..].copy_from_slice(&code_hash[..]); (From::from(keccak(&buffer[..])), Some(code_hash)) } } @@ -332,7 +341,9 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { .map_err(|e| ExecutionError::TransactionMalformed(e))?; let schedule = self.machine.schedule(self.info.number); - let confidential = oasis_contract.as_ref().map_or(false, |c| c.confidential); + let confidential = oasis_contract + .as_ref() + .map_or(false, |c| c.is_confidential()); let base_gas_required = U256::from(t.gas_required(&schedule, confidential)); if t.gas < base_gas_required { @@ -386,7 +397,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 !t.is_unsigned() { self.state.inc_nonce(&sender)?; } self.state.sub_balance( @@ -397,12 +408,18 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { let (result, output) = match t.action { Action::Create => { - let (new_address, code_hash) = contract_address( - self.machine.create_address_scheme(self.info.number), - &sender, - &nonce, - &t.data, - ); + let address_scheme = oasis_contract + .as_ref() + .and_then(|oasis_contract| { + oasis_contract + .salt_if_confidential + .map(|salt| CreateContractAddress::FromSaltAndCodeHash(salt.into())) + }) + .unwrap_or_else(|| self.machine.create_address_scheme(self.info.number)); + + let (new_address, code_hash) = + contract_address(address_scheme, &sender, &nonce, &t.data); + let params = ActionParams { code_address: new_address.clone(), code_hash: code_hash, @@ -443,6 +460,23 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> { ) } Action::Call(ref address) => { + if let Some(OasisContract { + salt_if_confidential: Some(salt), + code, + .. + }) = &oasis_contract + { + let expected_address = contract_address( + CreateContractAddress::FromSaltAndCodeHash((*salt).into()), + &Default::default(), /* unused */ + &Default::default(), /* unused */ + &code, + ) + .0; + if *address != expected_address { + return Err(ExecutionError::InvalidCode); + } + } let params = ActionParams { code_address: address.clone(), address: address.clone(), @@ -2691,12 +2725,17 @@ mod tests { macro_rules! create_wasm_executive { ($factory:ident -> ($state:ident, $exec:ident)) => { + create_wasm_executive!($factory -> ($state, $exec), |state| {}); + }; + ($factory:ident -> ($state:ident, $exec:ident), |state| $state_init:block) => { let mut info = EnvInfo::default(); info.number = 100; // wasm activated at block 10 info.last_hashes = Arc::new(vec![H256::zero()]); + info.gas_limit = U256::from(0xffffffffffffffffu64); let machine = ::ethereum::new_kovan_wasm_test_machine(); let mut $state = get_temp_state_with_factory($factory); + $state_init let mut $exec = Executive::new(&mut $state, &info, &machine); }; } @@ -2768,6 +2807,49 @@ mod tests { ); } + evm_test! {test_wasm_c10l_transact: test_wasm_c10l_transact_int} + fn test_wasm_c10l_transact(factory: Factory) { + let mut initcode = + include_bytes!("../res/wasi-tests/target/service/create_ctor.wasm").to_vec(); + let salt = [1u8; 32]; + let mut code = crate::vm::OasisContract::make_header( + 1, + serde_json::json!({ "salt_if_confidential": &salt }).to_string(), + ); + code.append(&mut initcode); + + let (expected_addr, expected_code_hash) = contract_address( + CreateContractAddress::FromSaltAndCodeHash(salt.into()), + &Default::default(), + &Default::default(), + &code, + ); + let expected_code_hash = expected_code_hash.unwrap(); + + let keypair = Random.generate().unwrap(); + let t = Transaction { + action: Action::Create, + value: U256::from(1), + data: code, + gas: U256::from(0xffffffffu64), + gas_price: U256::zero(), + nonce: U256::zero(), + } + .sign(keypair.secret(), None); + + create_wasm_executive!(factory -> (state, exec), |state| { + state + .add_balance(&t.sender(), &U256::from(2), CleanupMode::NoEmpty) + .unwrap(); + }); + + let executed = exec + .transact(&t, TransactOptions::with_no_tracing()) + .unwrap(); + + assert_eq!(state.code_hash(&expected_addr), Ok(expected_code_hash)); + } + evm_test! {test_wasm_xcc: test_wasm_xcc_int} fn test_wasm_xcc(factory: Factory) { let code_xcc = diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index df6555ced..38e6a471b 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -253,12 +253,15 @@ where .borrow() .activated() { + let salt = match address_scheme { + CreateContractAddress::FromSaltAndCodeHash(salt) => salt, + _ => unreachable!( + "confidential `create` must have address derived from salt and code hash" + ), + }; let mut header_code = OasisContract::make_header( 1, - json!({ - "confidential": true - }) - .to_string(), + json!({ "salt_if_confidential": salt }).to_string(), ); header_code.append(&mut code.to_vec()); header_code @@ -307,7 +310,7 @@ where }; if !self.static_flag { - if !self.schedule.eip86 || params.sender != UNSIGNED_SENDER { + if 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; @@ -901,4 +904,86 @@ 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 mut ext_tracer = NoopExtTracer; + + 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, + &mut ext_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 mut ext_tracer = NoopExtTracer; + + 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, + &mut ext_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("b7c227636666831278bacdb8d7f52933b8698ab9").unwrap() + ); + } } diff --git a/ethcore/src/machine.rs b/ethcore/src/machine.rs index 0d797a5ca..6203af8e1 100644 --- a/ethcore/src/machine.rs +++ b/ethcore/src/machine.rs @@ -372,11 +372,7 @@ 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 - } + 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 3aa76f58c..863b8df17 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -104,8 +104,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. @@ -179,7 +177,7 @@ 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 = true; 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; @@ -200,16 +198,7 @@ impl CommonParams { /// Whether these params contain any bug-fix hard forks. pub fn contains_bugfix_hard_fork(&self) -> bool { - self.eip98_transition != 0 - && self.eip155_transition != 0 - && self.validate_receipts_transition != 0 - && self.eip86_transition != 0 - && self.eip140_transition != 0 - && self.eip210_transition != 0 - && self.eip211_transition != 0 - && self.eip214_transition != 0 - && self.validate_chain_id_transition != 0 - && self.dust_protection_transition != 0 + true } } @@ -239,9 +228,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), diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 0d26e738b..97cd9ab1f 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -1355,7 +1355,7 @@ impl State { } }; - Ok(contract.as_ref().map_or(false, |c| c.confidential)) + Ok(contract.as_ref().map_or(false, |c| c.is_confidential())) } pub fn is_encrypting(&self) -> bool { diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index fef77d4b1..653feacb0 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -53,11 +53,14 @@ pub enum MessageCallResult { /// Specifies how an address is calculated for a new contract. #[derive(Copy, Clone, PartialEq, Eq)] pub enum CreateContractAddress { - /// Address is calculated from nonce and sender. Pre EIP-86 (Metropolis) + /// Address is calculated from sender and nonce. Pre EIP-86 (Metropolis) 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. EIP-86 CREATE2 scheme. + FromSenderSaltAndCodeHash(H256), + /// Address is calculated from salt and code hash. Similar to EIP-86 CREATE2 scheme + /// except that the Addreess MAC can be verified without knowing the creator. + FromSaltAndCodeHash(H256), + /// Address is calculated from code hash and sender. Used by pwasm create ext. FromSenderAndCodeHash, } diff --git a/ethcore/vm/src/oasis_contract.rs b/ethcore/vm/src/oasis_contract.rs index e8bb0efc7..e97ef1e0a 100644 --- a/ethcore/vm/src/oasis_contract.rs +++ b/ethcore/vm/src/oasis_contract.rs @@ -12,7 +12,7 @@ pub struct OasisContract { /// Header version. pub header_version: usize, /// Flag indicating whether contract is confidential. - pub confidential: bool, + pub salt_if_confidential: Option, /// Expiration timestamp for contract's storage (None if unspecified). pub expiry: Option, /// Header, to be prepended to stored bytecode. @@ -24,10 +24,17 @@ pub struct OasisContract { #[derive(Serialize, Deserialize)] #[serde(deny_unknown_fields)] struct Header { - confidential: Option, + salt_if_confidential: Option, expiry: Option, } +/// Given that the contract state subtrie is not currently checked against the root hash, +/// the salt exists to prevent a malicious worker from substituting the contract code for +/// another that writes confidential state to the (public) io trie). +/// In this way, the address specified by the sender becomes a MAC, and hence closes the +/// aforementioned side channel. +type Salt = [u8; 32]; + impl OasisContract { pub fn from_code(raw_code: &[u8]) -> Result, String> { // check for prefix @@ -74,12 +81,13 @@ impl OasisContract { Ok(Some(Self { header_version, - confidential: h.confidential.unwrap_or(false), + salt_if_confidential: h.salt_if_confidential, expiry: h.expiry, header: raw_header, code: Arc::new(code), })) } + pub fn make_header(version: usize, json_str: String) -> Vec { // start with header prefix let mut data = ElasticArray128::from_slice(&OASIS_HEADER_PREFIX[..]); @@ -102,6 +110,10 @@ impl OasisContract { data.into_vec() } + + pub fn is_confidential(&self) -> bool { + self.salt_if_confidential.is_some() + } } fn has_header_prefix(data: &[u8]) -> bool { @@ -129,7 +141,7 @@ mod tests { let data = make_data_payload( 1, json!({ - "confidential": true, + "salt_if_confidential": &[1u8; std::mem::size_of::()], "expiry": 1577836800, }) .to_string(), @@ -137,7 +149,7 @@ mod tests { let contract = OasisContract::from_code(&data).unwrap().unwrap(); - assert_eq!(contract.confidential, true); + assert_eq!(contract.salt_if_confidential, Some([1u8; 32])); assert_eq!(contract.expiry, Some(1577836800)); assert_eq!(contract.code, Arc::new("contract code".as_bytes().to_vec())); } @@ -147,14 +159,14 @@ mod tests { let data = make_data_payload( 1, json!({ - "confidential": true, + "salt_if_confidential": &[2u8; std::mem::size_of::()], }) .to_string(), ); let contract = OasisContract::from_code(&data).unwrap().unwrap(); - assert_eq!(contract.confidential, true); + assert_eq!(contract.is_confidential(), true); assert_eq!(contract.expiry, None); } @@ -170,7 +182,7 @@ mod tests { let contract = OasisContract::from_code(&data).unwrap().unwrap(); - assert_eq!(contract.confidential, false); + assert!(!contract.is_confidential()); assert_eq!(contract.expiry, Some(1577836800)); } @@ -179,7 +191,7 @@ mod tests { let data = make_data_payload( 2, json!({ - "confidential": true, + "salt_if_confidential": null, "expiry": 1577836800, }) .to_string(), @@ -194,9 +206,7 @@ mod tests { let data = make_data_payload( 1, json!({ - "expiry": 1577836800, - "unknown": "something", - "blah": "blah", + "confidential": true, }) .to_string(), ); @@ -205,11 +215,31 @@ mod tests { assert!(result.is_err()); } + #[test] + fn test_stringified_salt() { + let mut salt = [0u8; std::mem::size_of::()]; + for i in 0..salt.len() { + salt[i] = i as u8; + } + let salt_str = format!( + "[{}]", + salt.iter() + .map(|i| i.to_string()) + .collect::>() + .join(",") + ); + let data = make_data_payload(1, format!("{{\"salt_if_confidential\":{}}}", salt_str)); + + let contract = OasisContract::from_code(&data).unwrap().unwrap(); + assert_eq!(contract.salt_if_confidential, Some(salt)); + } + #[test] fn test_duplicate_key() { let data = make_data_payload( 1, - "{\"expiry\":1577836800,\"confidential\":true,\"expiry\":1577836801}".to_string(), + "{\"expiry\":1577836800,\"salt_if_confidential\":null,\"expiry\":1577836801}" + .to_string(), ); let result = OasisContract::from_code(&data); @@ -256,7 +286,7 @@ mod tests { let invalid_confidential = make_data_payload( 1, json!({ - "confidential": "true", + "salt_if_confidential": "0123456789abcdef", "expiry": 1577836800, }) .to_string(), @@ -269,7 +299,7 @@ mod tests { let invalid_expiry = make_data_payload( 1, json!({ - "confidential": true, + "salt_if_confidential": &[3u8; std::mem::size_of::()], "expiry": "1577836800", }) .to_string(), diff --git a/ethcore/vm/src/oasis_vm.rs b/ethcore/vm/src/oasis_vm.rs index fdbf31b1a..b4de5af7c 100644 --- a/ethcore/vm/src/oasis_vm.rs +++ b/ethcore/vm/src/oasis_vm.rs @@ -100,7 +100,7 @@ impl ConfidentialVm { Ok(params .oasis_contract .as_ref() - .map_or(false, |c| c.confidential)) + .map_or(false, |c| c.is_confidential())) } // If we haven't executed a confidential contract in this transaction yet, check // if the target contract is confidential. Don't check the given oasis_contract diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 036cec0dd..fe0777084 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -24,7 +24,7 @@ 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, @@ -115,8 +115,6 @@ 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, /// Wasm extra schedule settings, if wasm activated pub wasm: Option, /// Default storage duration (in seconds) @@ -262,7 +260,6 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, - eip86: false, wasm: None, default_storage_duration: 3155695200, // 100 years } @@ -334,7 +331,6 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, - eip86: false, wasm: None, default_storage_duration: 3155695200, // 100 years } diff --git a/ethcore/wasm/src/lib.rs b/ethcore/wasm/src/lib.rs index 596cfb56c..afbca7bb3 100644 --- a/ethcore/wasm/src/lib.rs +++ b/ethcore/wasm/src/lib.rs @@ -255,10 +255,11 @@ fn subst_main_call(module: &mut elements::Module) -> bool { Some(idx) => idx, None => return false, }; - let main_fn_idx = match func_index(module, "main") { - Some(idx) => idx, - None => return false, - }; + let main_fn_idx = + match func_index(module, "__original_main").or_else(|| func_index(module, "main")) { + Some(idx) => idx, + None => return false, + }; let import_section_len: usize = module .import_section() diff --git a/ethcore/wasmer/src/lib.rs b/ethcore/wasmer/src/lib.rs index 36576648c..46b0de35a 100644 --- a/ethcore/wasmer/src/lib.rs +++ b/ethcore/wasmer/src/lib.rs @@ -209,20 +209,23 @@ impl vm::Vm for WasmRuntime { /// Replaces the call to `main` in `_start` with one to `_oasis_deploy`. fn subst_main_call(module: &mut Module) { - let module_info = module.info(); - - let start_fn_idx = match func_index(module_info, "_start") { - Some(idx) => idx, - None => return, - }; - let deploy_fn_idx = match func_index(module_info, "_oasis_deploy") { - Some(idx) => idx, - None => return, - }; - let mut main_fn_idx = match func_index(module_info, "main") { - Some(idx) => idx, - None => return, - }; + // let module_info = module.info(); + // + // let start_fn_idx = match func_index(module_info, "_start") { + // Some(idx) => idx, + // None => return, + // }; + // let deploy_fn_idx = match func_index(module_info, "_oasis_deploy") { + // Some(idx) => idx, + // None => return, + // }; + // let main_fn_idx = + // match func_index(module, "__original_main").or_else(|| func_index(module, "main")) { + // Some(idx) => idx, + // None => return, + // }; + + unimplemented!() // TODO: Unimplemented // Need to get mutable access to the exports and replace function index, same as in wasmi diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 0fe231901..fa1844795 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. diff --git a/rpc/src/v1/types/transaction.rs b/rpc/src/v1/types/transaction.rs index 0b7f117a7..dcc525499 100644 --- a/rpc/src/v1/types/transaction.rs +++ b/rpc/src/v1/types/transaction.rs @@ -162,8 +162,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, block_number: u64) -> Self { + let tx = Transaction::from_signed(tx, block_number); RichRawTransaction { raw: tx.raw.clone(), transaction: tx, @@ -173,13 +173,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(), @@ -215,17 +211,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, block_number: u64) -> 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(), @@ -261,40 +249,13 @@ 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, block_number: u64) -> Transaction { + let mut r = Transaction::from_signed(t.transaction, block_number); r.condition = t.condition.map(|b| b.into()); r } } -/*impl LocalTransactionStatus { - /// Convert `LocalTransactionStatus` into RPC `LocalTransactionStatus`. - pub fn from(s: miner::pool::local_transactions::Status, block_number: u64, eip86_transition: u64) -> Self { - let convert = |tx: Arc| { - Transaction::from_signed(tx.signed().clone(), block_number, eip86_transition) - }; - use miner::pool::local_transactions::Status::*; - match s { - Pending(_) => LocalTransactionStatus::Pending, - Mined(tx) => LocalTransactionStatus::Mined(convert(tx)), - Dropped(tx) => LocalTransactionStatus::Dropped(convert(tx)), - Rejected(tx, reason) => LocalTransactionStatus::Rejected(convert(tx), reason), - Invalid(tx) => LocalTransactionStatus::Invalid(convert(tx)), - Canceled(tx) => LocalTransactionStatus::Canceled(convert(tx)), - Replaced { old, new } => LocalTransactionStatus::Replaced( - convert(old), - new.signed().gas_price.into(), - new.signed().hash().into(), - ), - } - } -}*/ - #[cfg(test)] mod tests { use super::{LocalTransactionStatus, Transaction}; @@ -304,7 +265,10 @@ mod tests { fn test_transaction_serialize() { let t = Transaction::default(); let serialized = serde_json::to_string(&t).unwrap(); - assert_eq!(serialized, r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null}"#); + assert_eq!( + serialized, + r#"{"hash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0","blockHash":null,"blockNumber":null,"transactionIndex":null,"from":"0x0000000000000000000000000000000000000000","to":null,"value":"0x0","gasPrice":"0x0","gas":"0x0","input":"0x","creates":null,"raw":"0x","publicKey":null,"chainId":null,"standardV":"0x0","v":"0x0","r":"0x0","s":"0x0","condition":null}"# + ); } #[test] @@ -347,9 +311,9 @@ mod tests { ); assert_eq!( serde_json::to_string(&status7).unwrap(), - r#"{"status":"replaced","transaction":"#.to_owned() + - &format!("{}", tx_ser) + - r#","hash":"0x000000000000000000000000000000000000000000000000000000000000000a","gasPrice":"0x5"}"# + r#"{"status":"replaced","transaction":"#.to_owned() + + &format!("{}", tx_ser) + + r#","hash":"0x000000000000000000000000000000000000000000000000000000000000000a","gasPrice":"0x5"}"# ); } }