parent
							
								
									0180b21dd1
								
							
						
					
					
						commit
						b50fb71dd1
					
				@ -106,6 +106,9 @@ pub trait LightChainClient: Send + Sync {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/// Get the `i`th CHT root.
 | 
						/// Get the `i`th CHT root.
 | 
				
			||||||
	fn cht_root(&self, i: usize) -> Option<H256>;
 | 
						fn cht_root(&self, i: usize) -> Option<H256>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Get the EIP-86 transition block number.
 | 
				
			||||||
 | 
						fn eip86_transition(&self) -> u64;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Something which can be treated as a `LightChainClient`.
 | 
					/// Something which can be treated as a `LightChainClient`.
 | 
				
			||||||
@ -384,4 +387,8 @@ impl LightChainClient for Client {
 | 
				
			|||||||
	fn cht_root(&self, i: usize) -> Option<H256> {
 | 
						fn cht_root(&self, i: usize) -> Option<H256> {
 | 
				
			||||||
		Client::cht_root(self, i)
 | 
							Client::cht_root(self, i)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn eip86_transition(&self) -> u64 {
 | 
				
			||||||
 | 
							self.engine().params().eip86_transition
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,8 @@
 | 
				
			|||||||
		"chainID": "0x3d",
 | 
							"chainID": "0x3d",
 | 
				
			||||||
		"forkBlock": "0x1d4c00",
 | 
							"forkBlock": "0x1d4c00",
 | 
				
			||||||
		"forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f",
 | 
							"forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,8 @@
 | 
				
			|||||||
		"maximumExtraDataSize": "0x20",
 | 
							"maximumExtraDataSize": "0x20",
 | 
				
			||||||
		"minGasLimit": "0x1388",
 | 
							"minGasLimit": "0x1388",
 | 
				
			||||||
		"networkID" : "0x1",
 | 
							"networkID" : "0x1",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,8 @@
 | 
				
			|||||||
		"maximumExtraDataSize": "0x20",
 | 
							"maximumExtraDataSize": "0x20",
 | 
				
			||||||
		"minGasLimit": "0x1388",
 | 
							"minGasLimit": "0x1388",
 | 
				
			||||||
		"networkID" : "0x1",
 | 
							"networkID" : "0x1",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,8 @@
 | 
				
			|||||||
		"networkID": "0x1",
 | 
							"networkID": "0x1",
 | 
				
			||||||
		"chainID": "0x2",
 | 
							"chainID": "0x2",
 | 
				
			||||||
		"subprotocolName": "exp",
 | 
							"subprotocolName": "exp",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -147,7 +147,8 @@
 | 
				
			|||||||
		"networkID" : "0x1",
 | 
							"networkID" : "0x1",
 | 
				
			||||||
		"forkBlock": "0x1d4c00",
 | 
							"forkBlock": "0x1d4c00",
 | 
				
			||||||
		"forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb",
 | 
							"forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -143,7 +143,8 @@
 | 
				
			|||||||
		"maximumExtraDataSize": "0x20",
 | 
							"maximumExtraDataSize": "0x20",
 | 
				
			||||||
		"minGasLimit": "0x1388",
 | 
							"minGasLimit": "0x1388",
 | 
				
			||||||
		"networkID" : "0x1",
 | 
							"networkID" : "0x1",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,8 @@
 | 
				
			|||||||
		"maximumExtraDataSize": "0x20",
 | 
							"maximumExtraDataSize": "0x20",
 | 
				
			||||||
		"minGasLimit": "0x1388",
 | 
							"minGasLimit": "0x1388",
 | 
				
			||||||
		"networkID" : "0x1",
 | 
							"networkID" : "0x1",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,8 @@
 | 
				
			|||||||
		"maximumExtraDataSize": "0x20",
 | 
							"maximumExtraDataSize": "0x20",
 | 
				
			||||||
		"minGasLimit": "0x1388",
 | 
							"minGasLimit": "0x1388",
 | 
				
			||||||
		"networkID" : "0x1",
 | 
							"networkID" : "0x1",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -30,7 +30,8 @@
 | 
				
			|||||||
		"chainID": "0x3e",
 | 
							"chainID": "0x3e",
 | 
				
			||||||
		"forkBlock": "0x1b34d8",
 | 
							"forkBlock": "0x1b34d8",
 | 
				
			||||||
		"forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145",
 | 
							"forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -23,7 +23,8 @@
 | 
				
			|||||||
		"maximumExtraDataSize": "0x0400",
 | 
							"maximumExtraDataSize": "0x0400",
 | 
				
			||||||
		"minGasLimit": "125000",
 | 
							"minGasLimit": "125000",
 | 
				
			||||||
		"networkID" : "0x0",
 | 
							"networkID" : "0x0",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,8 @@
 | 
				
			|||||||
		"networkID" : "0x3",
 | 
							"networkID" : "0x3",
 | 
				
			||||||
		"forkBlock": 641350,
 | 
							"forkBlock": 641350,
 | 
				
			||||||
		"forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb",
 | 
							"forkCanonHash": "0x8033403e9fe5811a7b6d6b469905915de1c59207ce2172cbcf5d6ff14fa6a2eb",
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffff"
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -1 +1 @@
 | 
				
			|||||||
Subproject commit d520593078fa0849dcd1f907e44ed0a616892e33
 | 
					Subproject commit ef191fdc61cf76cdb9cdc147465fb447304b0ed2
 | 
				
			||||||
@ -139,11 +139,12 @@
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"params": {
 | 
						"params": {
 | 
				
			||||||
		"eip98Transition": "0x7fffffffffffffff",
 | 
					 | 
				
			||||||
		"accountStartNonce": "0x00",
 | 
							"accountStartNonce": "0x00",
 | 
				
			||||||
		"maximumExtraDataSize": "0x20",
 | 
							"maximumExtraDataSize": "0x20",
 | 
				
			||||||
		"minGasLimit": "0x1388",
 | 
							"minGasLimit": "0x1388",
 | 
				
			||||||
		"networkID" : "0x1"
 | 
							"networkID" : "0x1",
 | 
				
			||||||
 | 
							"eip98Transition": "0x7fffffffffffff",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,8 @@
 | 
				
			|||||||
		"accountStartNonce": "0x0",
 | 
							"accountStartNonce": "0x0",
 | 
				
			||||||
		"maximumExtraDataSize": "0x20",
 | 
							"maximumExtraDataSize": "0x20",
 | 
				
			||||||
		"minGasLimit": "0x1388",
 | 
							"minGasLimit": "0x1388",
 | 
				
			||||||
		"networkID" : "0x2"
 | 
							"networkID" : "0x2",
 | 
				
			||||||
 | 
							"eip86Transition": "0x7fffffffffffff"
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"genesis": {
 | 
						"genesis": {
 | 
				
			||||||
		"seal": {
 | 
							"seal": {
 | 
				
			||||||
 | 
				
			|||||||
@ -960,7 +960,7 @@ impl BlockChainClient for Client {
 | 
				
			|||||||
				return Err(err.into())
 | 
									return Err(err.into())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		let lower = t.gas_required(&self.engine.schedule(&env_info)).into();
 | 
							let lower = t.gas_required(&self.engine.schedule(env_info.number)).into();
 | 
				
			||||||
		if cond(lower)? {
 | 
							if cond(lower)? {
 | 
				
			||||||
			trace!(target: "estimate_gas", "estimate_gas succeeded with {}", lower);
 | 
								trace!(target: "estimate_gas", "estimate_gas succeeded with {}", lower);
 | 
				
			||||||
			return Ok(lower)
 | 
								return Ok(lower)
 | 
				
			||||||
@ -1259,7 +1259,8 @@ impl BlockChainClient for Client {
 | 
				
			|||||||
					.collect();
 | 
										.collect();
 | 
				
			||||||
				match (transaction, previous_receipts) {
 | 
									match (transaction, previous_receipts) {
 | 
				
			||||||
					(Some(transaction), Some(previous_receipts)) => {
 | 
										(Some(transaction), Some(previous_receipts)) => {
 | 
				
			||||||
						Some(transaction_receipt(transaction, previous_receipts))
 | 
											let schedule = self.engine().schedule(block_number);
 | 
				
			||||||
 | 
											Some(transaction_receipt(&schedule, transaction, previous_receipts))
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					_ => None,
 | 
										_ => None,
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@ -1501,11 +1502,15 @@ impl BlockChainClient for Client {
 | 
				
			|||||||
			})
 | 
								})
 | 
				
			||||||
			.and_then(|a| if a.is_zero() { None } else { Some(a) })
 | 
								.and_then(|a| if a.is_zero() { None } else { Some(a) })
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn eip86_transition(&self) -> u64 {
 | 
				
			||||||
 | 
							self.engine().params().eip86_transition
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl MiningBlockChainClient for Client {
 | 
					impl MiningBlockChainClient for Client {
 | 
				
			||||||
	fn latest_schedule(&self) -> Schedule {
 | 
						fn latest_schedule(&self) -> Schedule {
 | 
				
			||||||
		self.engine.schedule(&self.latest_env_info())
 | 
							self.engine.schedule(self.latest_env_info().number)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
 | 
						fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
 | 
				
			||||||
@ -1655,7 +1660,7 @@ impl Drop for Client {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Returns `LocalizedReceipt` given `LocalizedTransaction`
 | 
					/// Returns `LocalizedReceipt` given `LocalizedTransaction`
 | 
				
			||||||
/// and a vector of receipts from given block up to transaction index.
 | 
					/// and a vector of receipts from given block up to transaction index.
 | 
				
			||||||
fn transaction_receipt(mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
 | 
					fn transaction_receipt(schedule: &Schedule, mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt {
 | 
				
			||||||
	assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
 | 
						assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let sender = tx.sender();
 | 
						let sender = tx.sender();
 | 
				
			||||||
@ -1674,12 +1679,12 @@ fn transaction_receipt(mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>)
 | 
				
			|||||||
		transaction_hash: transaction_hash,
 | 
							transaction_hash: transaction_hash,
 | 
				
			||||||
		transaction_index: transaction_index,
 | 
							transaction_index: transaction_index,
 | 
				
			||||||
		block_hash: block_hash,
 | 
							block_hash: block_hash,
 | 
				
			||||||
		block_number:block_number,
 | 
							block_number: block_number,
 | 
				
			||||||
		cumulative_gas_used: receipt.gas_used,
 | 
							cumulative_gas_used: receipt.gas_used,
 | 
				
			||||||
		gas_used: receipt.gas_used - prior_gas_used,
 | 
							gas_used: receipt.gas_used - prior_gas_used,
 | 
				
			||||||
		contract_address: match tx.action {
 | 
							contract_address: match tx.action {
 | 
				
			||||||
			Action::Call(_) => None,
 | 
								Action::Call(_) => None,
 | 
				
			||||||
			Action::Create => Some(contract_address(&sender, &tx.nonce))
 | 
								Action::Create => Some(contract_address(schedule.create_address, &sender, &tx.nonce, &tx.data.sha3()))
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry {
 | 
							logs: receipt.logs.into_iter().enumerate().map(|(i, log)| LocalizedLogEntry {
 | 
				
			||||||
			entry: log,
 | 
								entry: log,
 | 
				
			||||||
@ -1734,6 +1739,7 @@ mod tests {
 | 
				
			|||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn should_return_correct_log_index() {
 | 
						fn should_return_correct_log_index() {
 | 
				
			||||||
		use super::transaction_receipt;
 | 
							use super::transaction_receipt;
 | 
				
			||||||
 | 
							use evm::schedule::Schedule;
 | 
				
			||||||
		use ethkey::KeyPair;
 | 
							use ethkey::KeyPair;
 | 
				
			||||||
		use log_entry::{LogEntry, LocalizedLogEntry};
 | 
							use log_entry::{LogEntry, LocalizedLogEntry};
 | 
				
			||||||
		use receipt::{Receipt, LocalizedReceipt};
 | 
							use receipt::{Receipt, LocalizedReceipt};
 | 
				
			||||||
@ -1743,6 +1749,7 @@ mod tests {
 | 
				
			|||||||
		// given
 | 
							// given
 | 
				
			||||||
		let key = KeyPair::from_secret_slice(&"test".sha3()).unwrap();
 | 
							let key = KeyPair::from_secret_slice(&"test".sha3()).unwrap();
 | 
				
			||||||
		let secret = key.secret();
 | 
							let secret = key.secret();
 | 
				
			||||||
 | 
							let schedule = Schedule::new_homestead();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let block_number = 1;
 | 
							let block_number = 1;
 | 
				
			||||||
		let block_hash = 5.into();
 | 
							let block_hash = 5.into();
 | 
				
			||||||
@ -1786,7 +1793,7 @@ mod tests {
 | 
				
			|||||||
		}];
 | 
							}];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// when
 | 
							// when
 | 
				
			||||||
		let receipt = transaction_receipt(transaction, receipts);
 | 
							let receipt = transaction_receipt(&schedule, transaction, receipts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// then
 | 
							// then
 | 
				
			||||||
		assert_eq!(receipt, LocalizedReceipt {
 | 
							assert_eq!(receipt, LocalizedReceipt {
 | 
				
			||||||
 | 
				
			|||||||
@ -353,7 +353,7 @@ pub fn get_temp_state_db() -> GuardedTempResult<StateDB> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl MiningBlockChainClient for TestBlockChainClient {
 | 
					impl MiningBlockChainClient for TestBlockChainClient {
 | 
				
			||||||
	fn latest_schedule(&self) -> Schedule {
 | 
						fn latest_schedule(&self) -> Schedule {
 | 
				
			||||||
		Schedule::new_post_eip150(24576, true, true, true)
 | 
							Schedule::new_post_eip150(24576, true, true, true, true)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
 | 
						fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) -> OpenBlock {
 | 
				
			||||||
@ -756,6 +756,8 @@ impl BlockChainClient for TestBlockChainClient {
 | 
				
			|||||||
	fn registrar_address(&self) -> Option<Address> { None }
 | 
						fn registrar_address(&self) -> Option<Address> { None }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn registry_address(&self, _name: String) -> Option<Address> { None }
 | 
						fn registry_address(&self, _name: String) -> Option<Address> { None }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn eip86_transition(&self) -> u64 { u64::max_value() }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl ProvingBlockChainClient for TestBlockChainClient {
 | 
					impl ProvingBlockChainClient for TestBlockChainClient {
 | 
				
			||||||
 | 
				
			|||||||
@ -272,6 +272,9 @@ pub trait BlockChainClient : Sync + Send {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/// Get the address of a particular blockchain service, if available.
 | 
						/// Get the address of a particular blockchain service, if available.
 | 
				
			||||||
	fn registry_address(&self, name: String) -> Option<Address>;
 | 
						fn registry_address(&self, name: String) -> Option<Address>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Get the EIP-86 transition block number.
 | 
				
			||||||
 | 
						fn eip86_transition(&self) -> u64;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl IpcConfig for BlockChainClient { }
 | 
					impl IpcConfig for BlockChainClient { }
 | 
				
			||||||
 | 
				
			|||||||
@ -26,12 +26,11 @@ use account_provider::AccountProvider;
 | 
				
			|||||||
use block::*;
 | 
					use block::*;
 | 
				
			||||||
use spec::CommonParams;
 | 
					use spec::CommonParams;
 | 
				
			||||||
use engines::{Engine, Seal, EngineError};
 | 
					use engines::{Engine, Seal, EngineError};
 | 
				
			||||||
use header::Header;
 | 
					use header::{Header, BlockNumber};
 | 
				
			||||||
use error::{Error, TransactionError, BlockError};
 | 
					use error::{Error, TransactionError, BlockError};
 | 
				
			||||||
use evm::Schedule;
 | 
					use evm::Schedule;
 | 
				
			||||||
use ethjson;
 | 
					use ethjson;
 | 
				
			||||||
use io::{IoContext, IoHandler, TimerToken, IoService};
 | 
					use io::{IoContext, IoHandler, TimerToken, IoService};
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					 | 
				
			||||||
use builtin::Builtin;
 | 
					use builtin::Builtin;
 | 
				
			||||||
use transaction::UnverifiedTransaction;
 | 
					use transaction::UnverifiedTransaction;
 | 
				
			||||||
use client::{Client, EngineClient};
 | 
					use client::{Client, EngineClient};
 | 
				
			||||||
@ -241,8 +240,9 @@ impl Engine for AuthorityRound {
 | 
				
			|||||||
		]
 | 
							]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
 | 
						fn schedule(&self, block_number: BlockNumber) -> Schedule {
 | 
				
			||||||
		Schedule::new_post_eip150(usize::max_value(), true, true, true)
 | 
							let eip86 = block_number >= self.params.eip86_transition;
 | 
				
			||||||
 | 
							Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) {
 | 
						fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) {
 | 
				
			||||||
@ -387,7 +387,6 @@ impl Engine for AuthorityRound {
 | 
				
			|||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
	use util::*;
 | 
						use util::*;
 | 
				
			||||||
	use env_info::EnvInfo;
 | 
					 | 
				
			||||||
	use header::Header;
 | 
						use header::Header;
 | 
				
			||||||
	use error::{Error, BlockError};
 | 
						use error::{Error, BlockError};
 | 
				
			||||||
	use ethkey::Secret;
 | 
						use ethkey::Secret;
 | 
				
			||||||
@ -408,15 +407,7 @@ mod tests {
 | 
				
			|||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn can_return_schedule() {
 | 
						fn can_return_schedule() {
 | 
				
			||||||
		let engine = Spec::new_test_round().engine;
 | 
							let engine = Spec::new_test_round().engine;
 | 
				
			||||||
		let schedule = engine.schedule(&EnvInfo {
 | 
							let schedule = engine.schedule(10000000);
 | 
				
			||||||
			number: 10000000,
 | 
					 | 
				
			||||||
			author: 0.into(),
 | 
					 | 
				
			||||||
			timestamp: 0,
 | 
					 | 
				
			||||||
			difficulty: 0.into(),
 | 
					 | 
				
			||||||
			last_hashes: Arc::new(vec![]),
 | 
					 | 
				
			||||||
			gas_used: 0.into(),
 | 
					 | 
				
			||||||
			gas_limit: 0.into(),
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		assert!(schedule.stack_limit > 0);
 | 
							assert!(schedule.stack_limit > 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,11 +24,10 @@ use block::*;
 | 
				
			|||||||
use builtin::Builtin;
 | 
					use builtin::Builtin;
 | 
				
			||||||
use spec::CommonParams;
 | 
					use spec::CommonParams;
 | 
				
			||||||
use engines::{Engine, Seal};
 | 
					use engines::{Engine, Seal};
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					 | 
				
			||||||
use error::{BlockError, Error};
 | 
					use error::{BlockError, Error};
 | 
				
			||||||
use evm::Schedule;
 | 
					use evm::Schedule;
 | 
				
			||||||
use ethjson;
 | 
					use ethjson;
 | 
				
			||||||
use header::Header;
 | 
					use header::{Header, BlockNumber};
 | 
				
			||||||
use client::Client;
 | 
					use client::Client;
 | 
				
			||||||
use super::signer::EngineSigner;
 | 
					use super::signer::EngineSigner;
 | 
				
			||||||
use super::validator_set::{ValidatorSet, new_validator_set};
 | 
					use super::validator_set::{ValidatorSet, new_validator_set};
 | 
				
			||||||
@ -86,7 +85,7 @@ impl Engine for BasicAuthority {
 | 
				
			|||||||
	/// Additional engine-specific information for the user/developer concerning `header`.
 | 
						/// Additional engine-specific information for the user/developer concerning `header`.
 | 
				
			||||||
	fn extra_info(&self, _header: &Header) -> BTreeMap<String, String> { map!["signature".to_owned() => "TODO".to_owned()] }
 | 
						fn extra_info(&self, _header: &Header) -> BTreeMap<String, String> { map!["signature".to_owned() => "TODO".to_owned()] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
 | 
						fn schedule(&self, _block_number: BlockNumber) -> Schedule {
 | 
				
			||||||
		Schedule::new_homestead()
 | 
							Schedule::new_homestead()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -181,7 +180,6 @@ impl Engine for BasicAuthority {
 | 
				
			|||||||
mod tests {
 | 
					mod tests {
 | 
				
			||||||
	use util::*;
 | 
						use util::*;
 | 
				
			||||||
	use block::*;
 | 
						use block::*;
 | 
				
			||||||
	use env_info::EnvInfo;
 | 
					 | 
				
			||||||
	use error::{BlockError, Error};
 | 
						use error::{BlockError, Error};
 | 
				
			||||||
	use tests::helpers::*;
 | 
						use tests::helpers::*;
 | 
				
			||||||
	use account_provider::AccountProvider;
 | 
						use account_provider::AccountProvider;
 | 
				
			||||||
@ -206,16 +204,7 @@ mod tests {
 | 
				
			|||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn can_return_schedule() {
 | 
						fn can_return_schedule() {
 | 
				
			||||||
		let engine = new_test_authority().engine;
 | 
							let engine = new_test_authority().engine;
 | 
				
			||||||
		let schedule = engine.schedule(&EnvInfo {
 | 
							let schedule = engine.schedule(10000000);
 | 
				
			||||||
			number: 10000000,
 | 
					 | 
				
			||||||
			author: 0.into(),
 | 
					 | 
				
			||||||
			timestamp: 0,
 | 
					 | 
				
			||||||
			difficulty: 0.into(),
 | 
					 | 
				
			||||||
			last_hashes: Arc::new(vec![]),
 | 
					 | 
				
			||||||
			gas_used: 0.into(),
 | 
					 | 
				
			||||||
			gas_limit: 0.into(),
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		assert!(schedule.stack_limit > 0);
 | 
							assert!(schedule.stack_limit > 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,10 +18,10 @@ use std::collections::BTreeMap;
 | 
				
			|||||||
use util::{Address, HashMap};
 | 
					use util::{Address, HashMap};
 | 
				
			||||||
use builtin::Builtin;
 | 
					use builtin::Builtin;
 | 
				
			||||||
use engines::{Engine, Seal};
 | 
					use engines::{Engine, Seal};
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					 | 
				
			||||||
use spec::CommonParams;
 | 
					use spec::CommonParams;
 | 
				
			||||||
use evm::Schedule;
 | 
					use evm::Schedule;
 | 
				
			||||||
use block::ExecutedBlock;
 | 
					use block::ExecutedBlock;
 | 
				
			||||||
 | 
					use header::BlockNumber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// An engine which does not provide any consensus mechanism, just seals blocks internally.
 | 
					/// An engine which does not provide any consensus mechanism, just seals blocks internally.
 | 
				
			||||||
pub struct InstantSeal {
 | 
					pub struct InstantSeal {
 | 
				
			||||||
@ -58,8 +58,9 @@ impl Engine for InstantSeal {
 | 
				
			|||||||
		&self.builtins
 | 
							&self.builtins
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
 | 
						fn schedule(&self, block_number: BlockNumber) -> Schedule {
 | 
				
			||||||
		Schedule::new_post_eip150(usize::max_value(), true, true, true)
 | 
							let eip86 = block_number >= self.params.eip86_transition;
 | 
				
			||||||
 | 
							Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn seals_internally(&self) -> Option<bool> { Some(true) }
 | 
						fn seals_internally(&self) -> Option<bool> { Some(true) }
 | 
				
			||||||
 | 
				
			|||||||
@ -39,10 +39,10 @@ use account_provider::AccountProvider;
 | 
				
			|||||||
use block::ExecutedBlock;
 | 
					use block::ExecutedBlock;
 | 
				
			||||||
use builtin::Builtin;
 | 
					use builtin::Builtin;
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					use env_info::EnvInfo;
 | 
				
			||||||
use error::{Error, TransactionError};
 | 
					use error::Error;
 | 
				
			||||||
use spec::CommonParams;
 | 
					use spec::CommonParams;
 | 
				
			||||||
use evm::Schedule;
 | 
					use evm::Schedule;
 | 
				
			||||||
use header::Header;
 | 
					use header::{Header, BlockNumber};
 | 
				
			||||||
use transaction::{UnverifiedTransaction, SignedTransaction};
 | 
					use transaction::{UnverifiedTransaction, SignedTransaction};
 | 
				
			||||||
use client::Client;
 | 
					use client::Client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -107,8 +107,8 @@ pub trait Engine : Sync + Send {
 | 
				
			|||||||
	/// Get the general parameters of the chain.
 | 
						/// Get the general parameters of the chain.
 | 
				
			||||||
	fn params(&self) -> &CommonParams;
 | 
						fn params(&self) -> &CommonParams;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Get the EVM schedule for the given `env_info`.
 | 
						/// Get the EVM schedule for the given `block_number`.
 | 
				
			||||||
	fn schedule(&self, env_info: &EnvInfo) -> Schedule;
 | 
						fn schedule(&self, block_number: BlockNumber) -> Schedule;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Builtin-contracts we would like to see in the chain.
 | 
						/// Builtin-contracts we would like to see in the chain.
 | 
				
			||||||
	/// (In principle these are just hints for the engine since that has the last word on them.)
 | 
						/// (In principle these are just hints for the engine since that has the last word on them.)
 | 
				
			||||||
@ -156,14 +156,7 @@ pub trait Engine : Sync + Send {
 | 
				
			|||||||
	// TODO: Add flags for which bits of the transaction to check.
 | 
						// TODO: Add flags for which bits of the transaction to check.
 | 
				
			||||||
	// TODO: consider including State in the params.
 | 
						// TODO: consider including State in the params.
 | 
				
			||||||
	fn verify_transaction_basic(&self, t: &UnverifiedTransaction, _header: &Header) -> Result<(), Error> {
 | 
						fn verify_transaction_basic(&self, t: &UnverifiedTransaction, _header: &Header) -> Result<(), Error> {
 | 
				
			||||||
		t.check_low_s()?;
 | 
							t.verify_basic(true, Some(self.params().network_id), true)?;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if let Some(n) = t.network_id() {
 | 
					 | 
				
			||||||
			if n != self.params().chain_id {
 | 
					 | 
				
			||||||
				return Err(TransactionError::InvalidNetworkId.into());
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		Ok(())
 | 
							Ok(())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ use builtin::Builtin;
 | 
				
			|||||||
use engines::Engine;
 | 
					use engines::Engine;
 | 
				
			||||||
use spec::CommonParams;
 | 
					use spec::CommonParams;
 | 
				
			||||||
use evm::Schedule;
 | 
					use evm::Schedule;
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					use header::BlockNumber;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// An engine which does not provide any consensus mechanism and does not seal blocks.
 | 
					/// An engine which does not provide any consensus mechanism and does not seal blocks.
 | 
				
			||||||
pub struct NullEngine {
 | 
					pub struct NullEngine {
 | 
				
			||||||
@ -57,7 +57,7 @@ impl Engine for NullEngine {
 | 
				
			|||||||
		&self.builtins
 | 
							&self.builtins
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
 | 
						fn schedule(&self, _block_number: BlockNumber) -> Schedule {
 | 
				
			||||||
		Schedule::new_homestead()
 | 
							Schedule::new_homestead()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -30,9 +30,8 @@ use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
 | 
				
			|||||||
use util::*;
 | 
					use util::*;
 | 
				
			||||||
use client::{Client, EngineClient};
 | 
					use client::{Client, EngineClient};
 | 
				
			||||||
use error::{Error, BlockError};
 | 
					use error::{Error, BlockError};
 | 
				
			||||||
use header::Header;
 | 
					use header::{Header, BlockNumber};
 | 
				
			||||||
use builtin::Builtin;
 | 
					use builtin::Builtin;
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					 | 
				
			||||||
use rlp::UntrustedRlp;
 | 
					use rlp::UntrustedRlp;
 | 
				
			||||||
use ethkey::{recover, public_to_address, Signature};
 | 
					use ethkey::{recover, public_to_address, Signature};
 | 
				
			||||||
use account_provider::AccountProvider;
 | 
					use account_provider::AccountProvider;
 | 
				
			||||||
@ -405,8 +404,9 @@ impl Engine for Tendermint {
 | 
				
			|||||||
		]
 | 
							]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
 | 
						fn schedule(&self, block_number: BlockNumber) -> Schedule {
 | 
				
			||||||
		Schedule::new_post_eip150(usize::max_value(), true, true, true)
 | 
							let eip86 = block_number >= self.params.eip86_transition;
 | 
				
			||||||
 | 
							Schedule::new_post_eip150(usize::max_value(), true, true, true, eip86)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) {
 | 
						fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, _gas_ceil_target: U256) {
 | 
				
			||||||
@ -658,7 +658,6 @@ mod tests {
 | 
				
			|||||||
	use block::*;
 | 
						use block::*;
 | 
				
			||||||
	use error::{Error, BlockError};
 | 
						use error::{Error, BlockError};
 | 
				
			||||||
	use header::Header;
 | 
						use header::Header;
 | 
				
			||||||
	use env_info::EnvInfo;
 | 
					 | 
				
			||||||
	use ethkey::Secret;
 | 
						use ethkey::Secret;
 | 
				
			||||||
	use client::chain_notify::ChainNotify;
 | 
						use client::chain_notify::ChainNotify;
 | 
				
			||||||
	use miner::MinerService;
 | 
						use miner::MinerService;
 | 
				
			||||||
@ -740,15 +739,7 @@ mod tests {
 | 
				
			|||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn can_return_schedule() {
 | 
						fn can_return_schedule() {
 | 
				
			||||||
		let engine = Spec::new_test_tendermint().engine;
 | 
							let engine = Spec::new_test_tendermint().engine;
 | 
				
			||||||
		let schedule = engine.schedule(&EnvInfo {
 | 
							let schedule = engine.schedule(10000000);
 | 
				
			||||||
			number: 10000000,
 | 
					 | 
				
			||||||
			author: 0.into(),
 | 
					 | 
				
			||||||
			timestamp: 0,
 | 
					 | 
				
			||||||
			difficulty: 0.into(),
 | 
					 | 
				
			||||||
			last_hashes: Arc::new(vec![]),
 | 
					 | 
				
			||||||
			gas_used: 0.into(),
 | 
					 | 
				
			||||||
			gas_limit: 0.into(),
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		assert!(schedule.stack_limit > 0);
 | 
							assert!(schedule.stack_limit > 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -196,6 +196,7 @@ mod tests {
 | 
				
			|||||||
		let s0 = Secret::from_slice(&"1".sha3()).unwrap();
 | 
							let s0 = Secret::from_slice(&"1".sha3()).unwrap();
 | 
				
			||||||
		let v0 = tap.insert_account(s0.clone(), "").unwrap();
 | 
							let v0 = tap.insert_account(s0.clone(), "").unwrap();
 | 
				
			||||||
		let v1 = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "").unwrap();
 | 
							let v1 = tap.insert_account(Secret::from_slice(&"0".sha3()).unwrap(), "").unwrap();
 | 
				
			||||||
 | 
							let network_id = Spec::new_validator_safe_contract().network_id();
 | 
				
			||||||
		let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap));
 | 
							let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap));
 | 
				
			||||||
		client.engine().register_client(Arc::downgrade(&client));
 | 
							client.engine().register_client(Arc::downgrade(&client));
 | 
				
			||||||
		let validator_contract = Address::from_str("0000000000000000000000000000000000000005").unwrap();
 | 
							let validator_contract = Address::from_str("0000000000000000000000000000000000000005").unwrap();
 | 
				
			||||||
@ -209,7 +210,7 @@ mod tests {
 | 
				
			|||||||
			action: Action::Call(validator_contract),
 | 
								action: Action::Call(validator_contract),
 | 
				
			||||||
			value: 0.into(),
 | 
								value: 0.into(),
 | 
				
			||||||
			data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
 | 
								data: "bfc708a000000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
 | 
				
			||||||
		}.sign(&s0, None);
 | 
							}.sign(&s0, Some(network_id));
 | 
				
			||||||
		client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
 | 
							client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
 | 
				
			||||||
		client.update_sealing();
 | 
							client.update_sealing();
 | 
				
			||||||
		assert_eq!(client.chain_info().best_block_number, 1);
 | 
							assert_eq!(client.chain_info().best_block_number, 1);
 | 
				
			||||||
@ -221,7 +222,7 @@ mod tests {
 | 
				
			|||||||
			action: Action::Call(validator_contract),
 | 
								action: Action::Call(validator_contract),
 | 
				
			||||||
			value: 0.into(),
 | 
								value: 0.into(),
 | 
				
			||||||
			data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
 | 
								data: "4d238c8e00000000000000000000000082a978b3f5962a5b0957d9ee9eef472ee55b42f1".from_hex().unwrap(),
 | 
				
			||||||
		}.sign(&s0, None);
 | 
							}.sign(&s0, Some(network_id));
 | 
				
			||||||
		client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
 | 
							client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
 | 
				
			||||||
		client.update_sealing();
 | 
							client.update_sealing();
 | 
				
			||||||
		// The transaction is not yet included so still unable to seal.
 | 
							// The transaction is not yet included so still unable to seal.
 | 
				
			||||||
@ -240,7 +241,7 @@ mod tests {
 | 
				
			|||||||
			action: Action::Call(Address::default()),
 | 
								action: Action::Call(Address::default()),
 | 
				
			||||||
			value: 0.into(),
 | 
								value: 0.into(),
 | 
				
			||||||
			data: Vec::new(),
 | 
								data: Vec::new(),
 | 
				
			||||||
		}.sign(&s0, None);
 | 
							}.sign(&s0, Some(network_id));
 | 
				
			||||||
		client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
 | 
							client.miner().import_own_transaction(client.as_ref(), tx.into()).unwrap();
 | 
				
			||||||
		client.update_sealing();
 | 
							client.update_sealing();
 | 
				
			||||||
		// Able to seal again.
 | 
							// Able to seal again.
 | 
				
			||||||
 | 
				
			|||||||
@ -19,8 +19,8 @@ use util::*;
 | 
				
			|||||||
use block::*;
 | 
					use block::*;
 | 
				
			||||||
use builtin::Builtin;
 | 
					use builtin::Builtin;
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					use env_info::EnvInfo;
 | 
				
			||||||
use error::{BlockError, TransactionError, Error};
 | 
					use error::{BlockError, Error, TransactionError};
 | 
				
			||||||
use header::Header;
 | 
					use header::{Header, BlockNumber};
 | 
				
			||||||
use state::CleanupMode;
 | 
					use state::CleanupMode;
 | 
				
			||||||
use spec::CommonParams;
 | 
					use spec::CommonParams;
 | 
				
			||||||
use transaction::UnverifiedTransaction;
 | 
					use transaction::UnverifiedTransaction;
 | 
				
			||||||
@ -167,19 +167,20 @@ impl Engine for Ethash {
 | 
				
			|||||||
		map!["nonce".to_owned() => format!("0x{}", header.nonce().hex()), "mixHash".to_owned() => format!("0x{}", header.mix_hash().hex())]
 | 
							map!["nonce".to_owned() => format!("0x{}", header.nonce().hex()), "mixHash".to_owned() => format!("0x{}", header.mix_hash().hex())]
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn schedule(&self, env_info: &EnvInfo) -> Schedule {
 | 
						fn schedule(&self, block_number: BlockNumber) -> Schedule {
 | 
				
			||||||
		trace!(target: "client", "Creating schedule. fCML={}, bGCML={}", self.ethash_params.homestead_transition, self.ethash_params.eip150_transition);
 | 
							trace!(target: "client", "Creating schedule. fCML={}, bGCML={}", self.ethash_params.homestead_transition, self.ethash_params.eip150_transition);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if env_info.number < self.ethash_params.homestead_transition {
 | 
							if block_number < self.ethash_params.homestead_transition {
 | 
				
			||||||
			Schedule::new_frontier()
 | 
								Schedule::new_frontier()
 | 
				
			||||||
		} else if env_info.number < self.ethash_params.eip150_transition {
 | 
							} else if block_number < self.ethash_params.eip150_transition {
 | 
				
			||||||
			Schedule::new_homestead()
 | 
								Schedule::new_homestead()
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			Schedule::new_post_eip150(
 | 
								Schedule::new_post_eip150(
 | 
				
			||||||
				self.ethash_params.max_code_size as usize,
 | 
									self.ethash_params.max_code_size as usize,
 | 
				
			||||||
				env_info.number >= self.ethash_params.eip160_transition,
 | 
									block_number >= self.ethash_params.eip160_transition,
 | 
				
			||||||
				env_info.number >= self.ethash_params.eip161abc_transition,
 | 
									block_number >= self.ethash_params.eip161abc_transition,
 | 
				
			||||||
				env_info.number >= self.ethash_params.eip161d_transition
 | 
									block_number >= self.ethash_params.eip161d_transition,
 | 
				
			||||||
 | 
									block_number >= self.params.eip86_transition
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -369,20 +370,13 @@ impl Engine for Ethash {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> result::Result<(), Error> {
 | 
						fn verify_transaction_basic(&self, t: &UnverifiedTransaction, header: &Header) -> result::Result<(), Error> {
 | 
				
			||||||
		if header.number() >= self.ethash_params.homestead_transition {
 | 
					 | 
				
			||||||
			t.check_low_s()?;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if let Some(n) = t.network_id() {
 | 
					 | 
				
			||||||
			if header.number() < self.ethash_params.eip155_transition || n != self.params().chain_id {
 | 
					 | 
				
			||||||
				return Err(TransactionError::InvalidNetworkId.into())
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if header.number() >= self.ethash_params.min_gas_price_transition && t.gas_price < self.ethash_params.min_gas_price {
 | 
							if header.number() >= self.ethash_params.min_gas_price_transition && t.gas_price < self.ethash_params.min_gas_price {
 | 
				
			||||||
			return Err(TransactionError::InsufficientGasPrice { minimal: self.ethash_params.min_gas_price, got: t.gas_price }.into());
 | 
								return Err(TransactionError::InsufficientGasPrice { minimal: self.ethash_params.min_gas_price, got: t.gas_price }.into());
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let check_low_s = header.number() >= self.ethash_params.homestead_transition;
 | 
				
			||||||
 | 
							let network_id = if header.number() >= self.ethash_params.eip155_transition { Some(self.params().chain_id) } else { None };
 | 
				
			||||||
 | 
							t.verify_basic(check_low_s, network_id, false)?;
 | 
				
			||||||
		Ok(())
 | 
							Ok(())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -512,7 +506,6 @@ mod tests {
 | 
				
			|||||||
	use block::*;
 | 
						use block::*;
 | 
				
			||||||
	use tests::helpers::*;
 | 
						use tests::helpers::*;
 | 
				
			||||||
	use engines::Engine;
 | 
						use engines::Engine;
 | 
				
			||||||
	use env_info::EnvInfo;
 | 
					 | 
				
			||||||
	use error::{BlockError, Error};
 | 
						use error::{BlockError, Error};
 | 
				
			||||||
	use header::Header;
 | 
						use header::Header;
 | 
				
			||||||
	use super::super::{new_morden, new_homestead_test};
 | 
						use super::super::{new_morden, new_homestead_test};
 | 
				
			||||||
@ -559,28 +552,10 @@ mod tests {
 | 
				
			|||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn can_return_schedule() {
 | 
						fn can_return_schedule() {
 | 
				
			||||||
		let engine = new_morden().engine;
 | 
							let engine = new_morden().engine;
 | 
				
			||||||
		let schedule = engine.schedule(&EnvInfo {
 | 
							let schedule = engine.schedule(10000000);
 | 
				
			||||||
			number: 10000000,
 | 
					 | 
				
			||||||
			author: 0.into(),
 | 
					 | 
				
			||||||
			timestamp: 0,
 | 
					 | 
				
			||||||
			difficulty: 0.into(),
 | 
					 | 
				
			||||||
			last_hashes: Arc::new(vec![]),
 | 
					 | 
				
			||||||
			gas_used: 0.into(),
 | 
					 | 
				
			||||||
			gas_limit: 0.into(),
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		assert!(schedule.stack_limit > 0);
 | 
							assert!(schedule.stack_limit > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let schedule = engine.schedule(&EnvInfo {
 | 
							let schedule = engine.schedule(100);
 | 
				
			||||||
			number: 100,
 | 
					 | 
				
			||||||
			author: 0.into(),
 | 
					 | 
				
			||||||
			timestamp: 0,
 | 
					 | 
				
			||||||
			difficulty: 0.into(),
 | 
					 | 
				
			||||||
			last_hashes: Arc::new(vec![]),
 | 
					 | 
				
			||||||
			gas_used: 0.into(),
 | 
					 | 
				
			||||||
			gas_limit: 0.into(),
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		assert!(!schedule.have_delegate_call);
 | 
							assert!(!schedule.have_delegate_call);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,17 @@ pub enum MessageCallResult {
 | 
				
			|||||||
	Failed
 | 
						Failed
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// 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)
 | 
				
			||||||
 | 
						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.
 | 
				
			||||||
 | 
						FromSenderAndCodeHash,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Externalities interface for EVMs
 | 
					/// Externalities interface for EVMs
 | 
				
			||||||
// TODO: [rob] associated error type instead of `trie::Result`. Not all EVMs are trie powered.
 | 
					// TODO: [rob] associated error type instead of `trie::Result`. Not all EVMs are trie powered.
 | 
				
			||||||
pub trait Ext {
 | 
					pub trait Ext {
 | 
				
			||||||
@ -68,7 +79,7 @@ pub trait Ext {
 | 
				
			|||||||
	/// Creates new contract.
 | 
						/// Creates new contract.
 | 
				
			||||||
	///
 | 
						///
 | 
				
			||||||
	/// Returns gas_left and contract address if contract creation was succesfull.
 | 
						/// Returns gas_left and contract address if contract creation was succesfull.
 | 
				
			||||||
	fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult;
 | 
						fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Message call.
 | 
						/// Message call.
 | 
				
			||||||
	///
 | 
						///
 | 
				
			||||||
 | 
				
			|||||||
@ -278,6 +278,7 @@ lazy_static! {
 | 
				
			|||||||
		arr[RETURN as usize] =			InstructionInfo::new("RETURN",			0, 2, 0, true, GasPriceTier::Zero);
 | 
							arr[RETURN as usize] =			InstructionInfo::new("RETURN",			0, 2, 0, true, GasPriceTier::Zero);
 | 
				
			||||||
		arr[DELEGATECALL as usize] =	InstructionInfo::new("DELEGATECALL",	0, 6, 1, true, GasPriceTier::Special);
 | 
							arr[DELEGATECALL as usize] =	InstructionInfo::new("DELEGATECALL",	0, 6, 1, true, GasPriceTier::Special);
 | 
				
			||||||
		arr[SUICIDE as usize] = 		InstructionInfo::new("SUICIDE",			0, 1, 0, true, GasPriceTier::Special);
 | 
							arr[SUICIDE as usize] = 		InstructionInfo::new("SUICIDE",			0, 1, 0, true, GasPriceTier::Special);
 | 
				
			||||||
 | 
							arr[CREATE_P2SH as usize] = 	InstructionInfo::new("CREATE_P2SH",		0, 3, 1, true, GasPriceTier::Special);
 | 
				
			||||||
		arr
 | 
							arr
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -553,6 +554,8 @@ pub const CALLCODE: Instruction = 0xf2;
 | 
				
			|||||||
pub const RETURN: Instruction = 0xf3;
 | 
					pub const RETURN: Instruction = 0xf3;
 | 
				
			||||||
/// like CALLCODE but keeps caller's value and sender
 | 
					/// like CALLCODE but keeps caller's value and sender
 | 
				
			||||||
pub const DELEGATECALL: Instruction = 0xf4;
 | 
					pub const DELEGATECALL: Instruction = 0xf4;
 | 
				
			||||||
 | 
					/// create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160
 | 
				
			||||||
 | 
					pub const CREATE_P2SH: Instruction = 0xfb;
 | 
				
			||||||
/// halt execution and register account for later deletion
 | 
					/// halt execution and register account for later deletion
 | 
				
			||||||
pub const SUICIDE: Instruction = 0xff;
 | 
					pub const SUICIDE: Instruction = 0xff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -223,7 +223,7 @@ impl<Gas: CostType> Gasometer<Gas> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				Request::GasMemProvide(gas, mem, Some(requested))
 | 
									Request::GasMemProvide(gas, mem, Some(requested))
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			instructions::CREATE => {
 | 
								instructions::CREATE | instructions::CREATE_P2SH => {
 | 
				
			||||||
				let gas = Gas::from(schedule.create_gas);
 | 
									let gas = Gas::from(schedule.create_gas);
 | 
				
			||||||
				let mem = mem_needed(stack.peek(1), stack.peek(2))?;
 | 
									let mem = mem_needed(stack.peek(1), stack.peek(2))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@ use std::marker::PhantomData;
 | 
				
			|||||||
use action_params::{ActionParams, ActionValue};
 | 
					use action_params::{ActionParams, ActionValue};
 | 
				
			||||||
use types::executed::CallType;
 | 
					use types::executed::CallType;
 | 
				
			||||||
use evm::instructions::{self, Instruction, InstructionInfo};
 | 
					use evm::instructions::{self, Instruction, InstructionInfo};
 | 
				
			||||||
use evm::{self, MessageCallResult, ContractCreateResult, GasLeft, CostType};
 | 
					use evm::{self, MessageCallResult, ContractCreateResult, GasLeft, CostType, CreateContractAddress};
 | 
				
			||||||
use bit_set::BitSet;
 | 
					use bit_set::BitSet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use util::*;
 | 
					use util::*;
 | 
				
			||||||
@ -182,7 +182,9 @@ impl<Cost: CostType> Interpreter<Cost> {
 | 
				
			|||||||
	fn verify_instruction(&self, ext: &evm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> {
 | 
						fn verify_instruction(&self, ext: &evm::Ext, instruction: Instruction, info: &InstructionInfo, stack: &Stack<U256>) -> evm::Result<()> {
 | 
				
			||||||
		let schedule = ext.schedule();
 | 
							let schedule = ext.schedule();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if !schedule.have_delegate_call && instruction == instructions::DELEGATECALL {
 | 
							if (instruction == instructions::DELEGATECALL && !schedule.have_delegate_call) ||
 | 
				
			||||||
 | 
								(instruction == instructions::CREATE_P2SH && !schedule.have_create_p2sh) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			return Err(evm::Error::BadInstruction {
 | 
								return Err(evm::Error::BadInstruction {
 | 
				
			||||||
				instruction: instruction
 | 
									instruction: instruction
 | 
				
			||||||
			});
 | 
								});
 | 
				
			||||||
@ -266,10 +268,12 @@ impl<Cost: CostType> Interpreter<Cost> {
 | 
				
			|||||||
			instructions::JUMPDEST => {
 | 
								instructions::JUMPDEST => {
 | 
				
			||||||
				// ignore
 | 
									// ignore
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			instructions::CREATE => {
 | 
								instructions::CREATE | instructions::CREATE_P2SH => {
 | 
				
			||||||
				let endowment = stack.pop_back();
 | 
									let endowment = stack.pop_back();
 | 
				
			||||||
				let init_off = stack.pop_back();
 | 
									let init_off = stack.pop_back();
 | 
				
			||||||
				let init_size = stack.pop_back();
 | 
									let init_size = stack.pop_back();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									let address_scheme = if instruction == instructions::CREATE { ext.schedule().create_address } else { CreateContractAddress::FromSenderAndCodeHash };
 | 
				
			||||||
				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");
 | 
									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");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				let contract_code = self.mem.read_slice(init_off, init_size);
 | 
									let contract_code = self.mem.read_slice(init_off, init_size);
 | 
				
			||||||
@ -280,7 +284,7 @@ impl<Cost: CostType> Interpreter<Cost> {
 | 
				
			|||||||
					return Ok(InstructionResult::UnusedGas(create_gas));
 | 
										return Ok(InstructionResult::UnusedGas(create_gas));
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code);
 | 
									let create_result = ext.create(&create_gas.as_u256(), &endowment, contract_code, address_scheme);
 | 
				
			||||||
				return match create_result {
 | 
									return match create_result {
 | 
				
			||||||
					ContractCreateResult::Created(address, gas_left) => {
 | 
										ContractCreateResult::Created(address, gas_left) => {
 | 
				
			||||||
						stack.push(address_to_u256(address));
 | 
											stack.push(address_to_u256(address));
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@ mod tests;
 | 
				
			|||||||
mod benches;
 | 
					mod benches;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub use self::evm::{Evm, Error, Finalize, GasLeft, Result, CostType};
 | 
					pub use self::evm::{Evm, Error, Finalize, GasLeft, Result, CostType};
 | 
				
			||||||
pub use self::ext::{Ext, ContractCreateResult, MessageCallResult};
 | 
					pub use self::ext::{Ext, ContractCreateResult, MessageCallResult, CreateContractAddress};
 | 
				
			||||||
pub use self::factory::{Factory, VMType};
 | 
					pub use self::factory::{Factory, VMType};
 | 
				
			||||||
pub use self::schedule::Schedule;
 | 
					pub use self::schedule::Schedule;
 | 
				
			||||||
pub use types::executed::CallType;
 | 
					pub use types::executed::CallType;
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,7 @@
 | 
				
			|||||||
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | 
					// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//! Cost schedule and other parameterisations for the EVM.
 | 
					//! Cost schedule and other parameterisations for the EVM.
 | 
				
			||||||
 | 
					use evm::CreateContractAddress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Definition of the cost schedule and other parameterisations for the EVM.
 | 
					/// Definition of the cost schedule and other parameterisations for the EVM.
 | 
				
			||||||
pub struct Schedule {
 | 
					pub struct Schedule {
 | 
				
			||||||
@ -22,6 +23,8 @@ pub struct Schedule {
 | 
				
			|||||||
	pub exceptional_failed_code_deposit: bool,
 | 
						pub exceptional_failed_code_deposit: bool,
 | 
				
			||||||
	/// Does it have a delegate cal
 | 
						/// Does it have a delegate cal
 | 
				
			||||||
	pub have_delegate_call: bool,
 | 
						pub have_delegate_call: bool,
 | 
				
			||||||
 | 
						/// Does it have a CREATE_P2SH instruction
 | 
				
			||||||
 | 
						pub have_create_p2sh: bool,
 | 
				
			||||||
	/// VM stack limit
 | 
						/// VM stack limit
 | 
				
			||||||
	pub stack_limit: usize,
 | 
						pub stack_limit: usize,
 | 
				
			||||||
	/// Max number of nested calls/creates
 | 
						/// Max number of nested calls/creates
 | 
				
			||||||
@ -99,6 +102,8 @@ pub struct Schedule {
 | 
				
			|||||||
	pub no_empty: bool,
 | 
						pub no_empty: bool,
 | 
				
			||||||
	/// Kill empty accounts if touched.
 | 
						/// Kill empty accounts if touched.
 | 
				
			||||||
	pub kill_empty: bool,
 | 
						pub kill_empty: bool,
 | 
				
			||||||
 | 
						/// Contract address generation scheme
 | 
				
			||||||
 | 
						pub create_address: CreateContractAddress,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Schedule {
 | 
					impl Schedule {
 | 
				
			||||||
@ -113,10 +118,11 @@ impl Schedule {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Schedule for the post-EIP-150-era of the Ethereum main net.
 | 
						/// Schedule for the post-EIP-150-era of the Ethereum main net.
 | 
				
			||||||
	pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool) -> Schedule {
 | 
						pub fn new_post_eip150(max_code_size: usize, fix_exp: bool, no_empty: bool, kill_empty: bool, have_create_p2sh: bool) -> Schedule {
 | 
				
			||||||
		Schedule {
 | 
							Schedule {
 | 
				
			||||||
			exceptional_failed_code_deposit: true,
 | 
								exceptional_failed_code_deposit: true,
 | 
				
			||||||
			have_delegate_call: true,
 | 
								have_delegate_call: true,
 | 
				
			||||||
 | 
								have_create_p2sh: have_create_p2sh,
 | 
				
			||||||
			stack_limit: 1024,
 | 
								stack_limit: 1024,
 | 
				
			||||||
			max_depth: 1024,
 | 
								max_depth: 1024,
 | 
				
			||||||
			tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
 | 
								tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
 | 
				
			||||||
@ -155,13 +161,20 @@ impl Schedule {
 | 
				
			|||||||
			sub_gas_cap_divisor: Some(64),
 | 
								sub_gas_cap_divisor: Some(64),
 | 
				
			||||||
			no_empty: no_empty,
 | 
								no_empty: no_empty,
 | 
				
			||||||
			kill_empty: kill_empty,
 | 
								kill_empty: kill_empty,
 | 
				
			||||||
 | 
								create_address: if have_create_p2sh { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce },
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Schedule for the Metropolis of the Ethereum main net.
 | 
				
			||||||
 | 
						pub fn new_metropolis() -> Schedule {
 | 
				
			||||||
 | 
							Self::new_post_eip150(24576, true, true, true, true)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
 | 
						fn new(efcd: bool, hdc: bool, tcg: usize) -> Schedule {
 | 
				
			||||||
		Schedule {
 | 
							Schedule {
 | 
				
			||||||
			exceptional_failed_code_deposit: efcd,
 | 
								exceptional_failed_code_deposit: efcd,
 | 
				
			||||||
			have_delegate_call: hdc,
 | 
								have_delegate_call: hdc,
 | 
				
			||||||
 | 
								have_create_p2sh: false,
 | 
				
			||||||
			stack_limit: 1024,
 | 
								stack_limit: 1024,
 | 
				
			||||||
			max_depth: 1024,
 | 
								max_depth: 1024,
 | 
				
			||||||
			tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
 | 
								tier_step_gas: [0, 2, 3, 5, 8, 10, 20, 0],
 | 
				
			||||||
@ -200,6 +213,7 @@ impl Schedule {
 | 
				
			|||||||
			sub_gas_cap_divisor: None,
 | 
								sub_gas_cap_divisor: None,
 | 
				
			||||||
			no_empty: false,
 | 
								no_empty: false,
 | 
				
			||||||
			kill_empty: false,
 | 
								kill_empty: false,
 | 
				
			||||||
 | 
								create_address: CreateContractAddress::FromSenderAndNonce,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ use util::*;
 | 
				
			|||||||
use action_params::{ActionParams, ActionValue};
 | 
					use action_params::{ActionParams, ActionValue};
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					use env_info::EnvInfo;
 | 
				
			||||||
use types::executed::CallType;
 | 
					use types::executed::CallType;
 | 
				
			||||||
use evm::{self, Ext, Schedule, Factory, GasLeft, VMType, ContractCreateResult, MessageCallResult};
 | 
					use evm::{self, Ext, Schedule, Factory, GasLeft, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress};
 | 
				
			||||||
use std::fmt::Debug;
 | 
					use std::fmt::Debug;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct FakeLogEntry {
 | 
					pub struct FakeLogEntry {
 | 
				
			||||||
@ -111,7 +111,7 @@ impl Ext for FakeExt {
 | 
				
			|||||||
		self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
 | 
							self.blockhashes.get(number).unwrap_or(&H256::new()).clone()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult {
 | 
						fn create(&mut self, gas: &U256, value: &U256, code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
 | 
				
			||||||
		self.calls.insert(FakeCall {
 | 
							self.calls.insert(FakeCall {
 | 
				
			||||||
			call_type: FakeCallType::Create,
 | 
								call_type: FakeCallType::Create,
 | 
				
			||||||
			gas: *gas,
 | 
								gas: *gas,
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ use engines::Engine;
 | 
				
			|||||||
use types::executed::CallType;
 | 
					use types::executed::CallType;
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					use env_info::EnvInfo;
 | 
				
			||||||
use error::ExecutionError;
 | 
					use error::ExecutionError;
 | 
				
			||||||
use evm::{self, Ext, Factory, Finalize};
 | 
					use evm::{self, Ext, Factory, Finalize, CreateContractAddress};
 | 
				
			||||||
use externalities::*;
 | 
					use externalities::*;
 | 
				
			||||||
use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer};
 | 
					use trace::{FlatTrace, Tracer, NoopTracer, ExecutiveTracer, VMTrace, VMTracer, ExecutiveVMTracer, NoopVMTracer};
 | 
				
			||||||
use transaction::{Action, SignedTransaction};
 | 
					use transaction::{Action, SignedTransaction};
 | 
				
			||||||
@ -34,14 +34,29 @@ pub use types::executed::{Executed, ExecutionResult};
 | 
				
			|||||||
/// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp`
 | 
					/// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp`
 | 
				
			||||||
const STACK_SIZE_PER_DEPTH: usize = 24*1024;
 | 
					const STACK_SIZE_PER_DEPTH: usize = 24*1024;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Returns new address created from address and given nonce.
 | 
					/// Returns new address created from address, nonce, and code hash
 | 
				
			||||||
pub fn contract_address(address: &Address, nonce: &U256) -> Address {
 | 
					pub fn contract_address(address_scheme: CreateContractAddress, sender: &Address, nonce: &U256, code_hash: &H256) -> Address {
 | 
				
			||||||
	use rlp::RlpStream;
 | 
						use rlp::RlpStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let mut stream = RlpStream::new_list(2);
 | 
						match address_scheme {
 | 
				
			||||||
	stream.append(address);
 | 
							CreateContractAddress::FromSenderAndNonce => {
 | 
				
			||||||
	stream.append(nonce);
 | 
								let mut stream = RlpStream::new_list(2);
 | 
				
			||||||
	From::from(stream.out().sha3())
 | 
								stream.append(sender);
 | 
				
			||||||
 | 
								stream.append(nonce);
 | 
				
			||||||
 | 
								From::from(stream.as_raw().sha3())
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							CreateContractAddress::FromCodeHash => {
 | 
				
			||||||
 | 
								let mut buffer = [0u8; 20 + 32];
 | 
				
			||||||
 | 
								&mut buffer[20..].copy_from_slice(&code_hash[..]);
 | 
				
			||||||
 | 
								From::from((&buffer[..]).sha3())
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							CreateContractAddress::FromSenderAndCodeHash => {
 | 
				
			||||||
 | 
								let mut buffer = [0u8; 20 + 32];
 | 
				
			||||||
 | 
								&mut buffer[..20].copy_from_slice(&sender[..]);
 | 
				
			||||||
 | 
								&mut buffer[20..].copy_from_slice(&code_hash[..]);
 | 
				
			||||||
 | 
								From::from((&buffer[..]).sha3())
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Transaction execution options.
 | 
					/// Transaction execution options.
 | 
				
			||||||
@ -125,7 +140,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		let sender = t.sender();
 | 
							let sender = t.sender();
 | 
				
			||||||
		let nonce = self.state.nonce(&sender)?;
 | 
							let nonce = self.state.nonce(&sender)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let schedule = self.engine.schedule(self.info);
 | 
							let schedule = self.engine.schedule(self.info.number);
 | 
				
			||||||
		let base_gas_required = U256::from(t.gas_required(&schedule));
 | 
							let base_gas_required = U256::from(t.gas_required(&schedule));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if t.gas < base_gas_required {
 | 
							if t.gas < base_gas_required {
 | 
				
			||||||
@ -160,17 +175,20 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// NOTE: there can be no invalid transactions from this point.
 | 
							// NOTE: there can be no invalid transactions from this point.
 | 
				
			||||||
		self.state.inc_nonce(&sender)?;
 | 
							if !t.is_unsigned() {
 | 
				
			||||||
 | 
								self.state.inc_nonce(&sender)?;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		self.state.sub_balance(&sender, &U256::from(gas_cost))?;
 | 
							self.state.sub_balance(&sender, &U256::from(gas_cost))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let mut substate = Substate::new();
 | 
							let mut substate = Substate::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let (gas_left, output) = match t.action {
 | 
							let (gas_left, output) = match t.action {
 | 
				
			||||||
			Action::Create => {
 | 
								Action::Create => {
 | 
				
			||||||
				let new_address = contract_address(&sender, &nonce);
 | 
									let code_hash = t.data.sha3();
 | 
				
			||||||
 | 
									let new_address = contract_address(schedule.create_address, &sender, &nonce, &code_hash);
 | 
				
			||||||
				let params = ActionParams {
 | 
									let params = ActionParams {
 | 
				
			||||||
					code_address: new_address.clone(),
 | 
										code_address: new_address.clone(),
 | 
				
			||||||
					code_hash: t.data.sha3(),
 | 
										code_hash: code_hash,
 | 
				
			||||||
					address: new_address,
 | 
										address: new_address,
 | 
				
			||||||
					sender: sender.clone(),
 | 
										sender: sender.clone(),
 | 
				
			||||||
					origin: sender.clone(),
 | 
										origin: sender.clone(),
 | 
				
			||||||
@ -253,7 +271,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		// backup used in case of running out of gas
 | 
							// backup used in case of running out of gas
 | 
				
			||||||
		self.state.checkpoint();
 | 
							self.state.checkpoint();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let schedule = self.engine.schedule(self.info);
 | 
							let schedule = self.engine.schedule(self.info.number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// at first, transfer value to destination
 | 
							// at first, transfer value to destination
 | 
				
			||||||
		if let ActionValue::Transfer(val) = params.value {
 | 
							if let ActionValue::Transfer(val) = params.value {
 | 
				
			||||||
@ -365,8 +383,14 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		params: ActionParams,
 | 
							params: ActionParams,
 | 
				
			||||||
		substate: &mut Substate,
 | 
							substate: &mut Substate,
 | 
				
			||||||
		tracer: &mut T,
 | 
							tracer: &mut T,
 | 
				
			||||||
		vm_tracer: &mut V
 | 
							vm_tracer: &mut V,
 | 
				
			||||||
	) -> evm::Result<U256> where T: Tracer, V: VMTracer {
 | 
						) -> evm::Result<U256> where T: Tracer, V: VMTracer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let schedule = self.engine.schedule(self.info.number);
 | 
				
			||||||
 | 
							if schedule.create_address != CreateContractAddress::FromSenderAndNonce && self.state.exists(¶ms.address)? {
 | 
				
			||||||
 | 
								return Err(evm::Error::OutOfGas);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// backup used in case of running out of gas
 | 
							// backup used in case of running out of gas
 | 
				
			||||||
		self.state.checkpoint();
 | 
							self.state.checkpoint();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -374,7 +398,6 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		let mut unconfirmed_substate = Substate::new();
 | 
							let mut unconfirmed_substate = Substate::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// create contract and transfer value to it if necessary
 | 
							// create contract and transfer value to it if necessary
 | 
				
			||||||
		let schedule = self.engine.schedule(self.info);
 | 
					 | 
				
			||||||
		let nonce_offset = if schedule.no_empty {1} else {0}.into();
 | 
							let nonce_offset = if schedule.no_empty {1} else {0}.into();
 | 
				
			||||||
		let prev_bal = self.state.balance(¶ms.address)?;
 | 
							let prev_bal = self.state.balance(¶ms.address)?;
 | 
				
			||||||
		if let ActionValue::Transfer(val) = params.value {
 | 
							if let ActionValue::Transfer(val) = params.value {
 | 
				
			||||||
@ -423,7 +446,7 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
 | 
				
			|||||||
		trace: Vec<FlatTrace>,
 | 
							trace: Vec<FlatTrace>,
 | 
				
			||||||
		vm_trace: Option<VMTrace>
 | 
							vm_trace: Option<VMTrace>
 | 
				
			||||||
	) -> ExecutionResult {
 | 
						) -> ExecutionResult {
 | 
				
			||||||
		let schedule = self.engine.schedule(self.info);
 | 
							let schedule = self.engine.schedule(self.info.number);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// refunds from SSTORE nonzero -> zero
 | 
							// refunds from SSTORE nonzero -> zero
 | 
				
			||||||
		let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count;
 | 
							let sstore_refunds = U256::from(schedule.sstore_refund_gas) * substate.sstore_clears_count;
 | 
				
			||||||
@ -525,7 +548,7 @@ mod tests {
 | 
				
			|||||||
	use util::bytes::BytesRef;
 | 
						use util::bytes::BytesRef;
 | 
				
			||||||
	use action_params::{ActionParams, ActionValue};
 | 
						use action_params::{ActionParams, ActionValue};
 | 
				
			||||||
	use env_info::EnvInfo;
 | 
						use env_info::EnvInfo;
 | 
				
			||||||
	use evm::{Factory, VMType};
 | 
						use evm::{Factory, VMType, CreateContractAddress};
 | 
				
			||||||
	use error::ExecutionError;
 | 
						use error::ExecutionError;
 | 
				
			||||||
	use state::{Substate, CleanupMode};
 | 
						use state::{Substate, CleanupMode};
 | 
				
			||||||
	use tests::helpers::*;
 | 
						use tests::helpers::*;
 | 
				
			||||||
@ -540,14 +563,14 @@ mod tests {
 | 
				
			|||||||
	fn test_contract_address() {
 | 
						fn test_contract_address() {
 | 
				
			||||||
		let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
 | 
							let address = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
 | 
				
			||||||
		let expected_address = Address::from_str("3f09c73a5ed19289fb9bdc72f1742566df146f56").unwrap();
 | 
							let expected_address = Address::from_str("3f09c73a5ed19289fb9bdc72f1742566df146f56").unwrap();
 | 
				
			||||||
		assert_eq!(expected_address, contract_address(&address, &U256::from(88)));
 | 
							assert_eq!(expected_address, contract_address(CreateContractAddress::FromSenderAndNonce, &address, &U256::from(88), &H256::default()));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: replace params with transactions!
 | 
						// TODO: replace params with transactions!
 | 
				
			||||||
	evm_test!{test_sender_balance: test_sender_balance_jit, test_sender_balance_int}
 | 
						evm_test!{test_sender_balance: test_sender_balance_jit, test_sender_balance_int}
 | 
				
			||||||
	fn test_sender_balance(factory: Factory) {
 | 
						fn test_sender_balance(factory: Factory) {
 | 
				
			||||||
		let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
 | 
							let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
 | 
				
			||||||
		let address = contract_address(&sender, &U256::zero());
 | 
							let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
		let mut params = ActionParams::default();
 | 
							let mut params = ActionParams::default();
 | 
				
			||||||
		params.address = address.clone();
 | 
							params.address = address.clone();
 | 
				
			||||||
		params.sender = sender.clone();
 | 
							params.sender = sender.clone();
 | 
				
			||||||
@ -602,7 +625,7 @@ mod tests {
 | 
				
			|||||||
		let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap();
 | 
							let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
							let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
				
			||||||
		let address = contract_address(&sender, &U256::zero());
 | 
							let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
		// TODO: add tests for 'callcreate'
 | 
							// TODO: add tests for 'callcreate'
 | 
				
			||||||
		//let next_address = contract_address(&address, &U256::zero());
 | 
							//let next_address = contract_address(&address, &U256::zero());
 | 
				
			||||||
		let mut params = ActionParams::default();
 | 
							let mut params = ActionParams::default();
 | 
				
			||||||
@ -658,7 +681,7 @@ mod tests {
 | 
				
			|||||||
		let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap();
 | 
							let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055".from_hex().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
							let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
				
			||||||
		let address = contract_address(&sender, &U256::zero());
 | 
							let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
		// TODO: add tests for 'callcreate'
 | 
							// TODO: add tests for 'callcreate'
 | 
				
			||||||
		//let next_address = contract_address(&address, &U256::zero());
 | 
							//let next_address = contract_address(&address, &U256::zero());
 | 
				
			||||||
		let mut params = ActionParams::default();
 | 
							let mut params = ActionParams::default();
 | 
				
			||||||
@ -770,7 +793,7 @@ mod tests {
 | 
				
			|||||||
		let code = "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap();
 | 
							let code = "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
							let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
				
			||||||
		let address = contract_address(&sender, &U256::zero());
 | 
							let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
		// TODO: add tests for 'callcreate'
 | 
							// TODO: add tests for 'callcreate'
 | 
				
			||||||
		//let next_address = contract_address(&address, &U256::zero());
 | 
							//let next_address = contract_address(&address, &U256::zero());
 | 
				
			||||||
		let mut params = ActionParams::default();
 | 
							let mut params = ActionParams::default();
 | 
				
			||||||
@ -857,7 +880,7 @@ mod tests {
 | 
				
			|||||||
		let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d600360e6f0600055".from_hex().unwrap();
 | 
							let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d600360e6f0600055".from_hex().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
							let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
				
			||||||
		let address = contract_address(&sender, &U256::zero());
 | 
							let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
		// TODO: add tests for 'callcreate'
 | 
							// TODO: add tests for 'callcreate'
 | 
				
			||||||
		//let next_address = contract_address(&address, &U256::zero());
 | 
							//let next_address = contract_address(&address, &U256::zero());
 | 
				
			||||||
		let mut params = ActionParams::default();
 | 
							let mut params = ActionParams::default();
 | 
				
			||||||
@ -909,8 +932,8 @@ mod tests {
 | 
				
			|||||||
		let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0".from_hex().unwrap();
 | 
							let code = "7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0".from_hex().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
							let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
				
			||||||
		let address = contract_address(&sender, &U256::zero());
 | 
							let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
		let next_address = contract_address(&address, &U256::zero());
 | 
							let next_address = contract_address(CreateContractAddress::FromSenderAndNonce, &address, &U256::zero(), &H256::default());
 | 
				
			||||||
		let mut params = ActionParams::default();
 | 
							let mut params = ActionParams::default();
 | 
				
			||||||
		params.address = address.clone();
 | 
							params.address = address.clone();
 | 
				
			||||||
		params.sender = sender.clone();
 | 
							params.sender = sender.clone();
 | 
				
			||||||
@ -1017,7 +1040,7 @@ mod tests {
 | 
				
			|||||||
		// 55 - sstore
 | 
							// 55 - sstore
 | 
				
			||||||
		let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
							let sender = Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap();
 | 
				
			||||||
		let code = "600160005401600055600060006000600060003060e05a03f1600155".from_hex().unwrap();
 | 
							let code = "600160005401600055600060006000600060003060e05a03f1600155".from_hex().unwrap();
 | 
				
			||||||
		let address = contract_address(&sender, &U256::zero());
 | 
							let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
		let mut params = ActionParams::default();
 | 
							let mut params = ActionParams::default();
 | 
				
			||||||
		params.address = address.clone();
 | 
							params.address = address.clone();
 | 
				
			||||||
		params.gas = U256::from(100_000);
 | 
							params.gas = U256::from(100_000);
 | 
				
			||||||
@ -1052,7 +1075,7 @@ mod tests {
 | 
				
			|||||||
			nonce: U256::zero()
 | 
								nonce: U256::zero()
 | 
				
			||||||
		}.sign(keypair.secret(), None);
 | 
							}.sign(keypair.secret(), None);
 | 
				
			||||||
		let sender = t.sender();
 | 
							let sender = t.sender();
 | 
				
			||||||
		let contract = contract_address(&sender, &U256::zero());
 | 
							let contract = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let mut state = get_temp_state();
 | 
							let mut state = get_temp_state();
 | 
				
			||||||
		state.add_balance(&sender, &U256::from(18), CleanupMode::NoEmpty).unwrap();
 | 
							state.add_balance(&sender, &U256::from(18), CleanupMode::NoEmpty).unwrap();
 | 
				
			||||||
@ -1181,7 +1204,7 @@ mod tests {
 | 
				
			|||||||
		let code = "6064640fffffffff20600055".from_hex().unwrap();
 | 
							let code = "6064640fffffffff20600055".from_hex().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
 | 
							let sender = Address::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap();
 | 
				
			||||||
		let address = contract_address(&sender, &U256::zero());
 | 
							let address = contract_address(CreateContractAddress::FromSenderAndNonce, &sender, &U256::zero(), &H256::default());
 | 
				
			||||||
		// TODO: add tests for 'callcreate'
 | 
							// TODO: add tests for 'callcreate'
 | 
				
			||||||
		//let next_address = contract_address(&address, &U256::zero());
 | 
							//let next_address = contract_address(&address, &U256::zero());
 | 
				
			||||||
		let mut params = ActionParams::default();
 | 
							let mut params = ActionParams::default();
 | 
				
			||||||
 | 
				
			|||||||
@ -21,8 +21,9 @@ use state::{Backend as StateBackend, State, Substate};
 | 
				
			|||||||
use engines::Engine;
 | 
					use engines::Engine;
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					use env_info::EnvInfo;
 | 
				
			||||||
use executive::*;
 | 
					use executive::*;
 | 
				
			||||||
use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, Factory};
 | 
					use evm::{self, Schedule, Ext, ContractCreateResult, MessageCallResult, Factory, CreateContractAddress};
 | 
				
			||||||
use types::executed::CallType;
 | 
					use types::executed::CallType;
 | 
				
			||||||
 | 
					use types::transaction::UNSIGNED_SENDER;
 | 
				
			||||||
use trace::{Tracer, VMTracer};
 | 
					use trace::{Tracer, VMTracer};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Policy for handling output data on `RETURN` opcode.
 | 
					/// Policy for handling output data on `RETURN` opcode.
 | 
				
			||||||
@ -97,7 +98,7 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
 | 
				
			|||||||
			depth: depth,
 | 
								depth: depth,
 | 
				
			||||||
			origin_info: origin_info,
 | 
								origin_info: origin_info,
 | 
				
			||||||
			substate: substate,
 | 
								substate: substate,
 | 
				
			||||||
			schedule: engine.schedule(env_info),
 | 
								schedule: engine.schedule(env_info.number),
 | 
				
			||||||
			output: output,
 | 
								output: output,
 | 
				
			||||||
			tracer: tracer,
 | 
								tracer: tracer,
 | 
				
			||||||
			vm_tracer: vm_tracer,
 | 
								vm_tracer: vm_tracer,
 | 
				
			||||||
@ -147,10 +148,11 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult {
 | 
						fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address_scheme: CreateContractAddress) -> ContractCreateResult {
 | 
				
			||||||
		// create new contract address
 | 
							// create new contract address
 | 
				
			||||||
 | 
							let code_hash = code.sha3();
 | 
				
			||||||
		let address = match self.state.nonce(&self.origin_info.address) {
 | 
							let address = match self.state.nonce(&self.origin_info.address) {
 | 
				
			||||||
			Ok(nonce) => contract_address(&self.origin_info.address, &nonce),
 | 
								Ok(nonce) => contract_address(address_scheme, &self.origin_info.address, &nonce, &code_hash),
 | 
				
			||||||
			Err(e) => {
 | 
								Err(e) => {
 | 
				
			||||||
				debug!(target: "ext", "Database corruption encountered: {:?}", e);
 | 
									debug!(target: "ext", "Database corruption encountered: {:?}", e);
 | 
				
			||||||
				return ContractCreateResult::Failed
 | 
									return ContractCreateResult::Failed
 | 
				
			||||||
@ -167,14 +169,16 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
 | 
				
			|||||||
			gas_price: self.origin_info.gas_price,
 | 
								gas_price: self.origin_info.gas_price,
 | 
				
			||||||
			value: ActionValue::Transfer(*value),
 | 
								value: ActionValue::Transfer(*value),
 | 
				
			||||||
			code: Some(Arc::new(code.to_vec())),
 | 
								code: Some(Arc::new(code.to_vec())),
 | 
				
			||||||
			code_hash: code.sha3(),
 | 
								code_hash: code_hash,
 | 
				
			||||||
			data: None,
 | 
								data: None,
 | 
				
			||||||
			call_type: CallType::None,
 | 
								call_type: CallType::None,
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if let Err(e) = self.state.inc_nonce(&self.origin_info.address) {
 | 
							if params.sender != UNSIGNED_SENDER {
 | 
				
			||||||
			debug!(target: "ext", "Database corruption encountered: {:?}", e);
 | 
								if let Err(e) = self.state.inc_nonce(&self.origin_info.address) {
 | 
				
			||||||
			return ContractCreateResult::Failed
 | 
									debug!(target: "ext", "Database corruption encountered: {:?}", e);
 | 
				
			||||||
 | 
									return ContractCreateResult::Failed
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.vm_factory, self.depth);
 | 
							let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.vm_factory, self.depth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ use executive::*;
 | 
				
			|||||||
use engines::Engine;
 | 
					use engines::Engine;
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					use env_info::EnvInfo;
 | 
				
			||||||
use evm;
 | 
					use evm;
 | 
				
			||||||
use evm::{Schedule, Ext, Factory, Finalize, VMType, ContractCreateResult, MessageCallResult};
 | 
					use evm::{Schedule, Ext, Factory, Finalize, VMType, ContractCreateResult, MessageCallResult, CreateContractAddress};
 | 
				
			||||||
use externalities::*;
 | 
					use externalities::*;
 | 
				
			||||||
use types::executed::CallType;
 | 
					use types::executed::CallType;
 | 
				
			||||||
use tests::helpers::*;
 | 
					use tests::helpers::*;
 | 
				
			||||||
@ -56,7 +56,8 @@ struct TestExt<'a, T: 'a, V: 'a, B: 'a>
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	ext: Externalities<'a, T, V, B>,
 | 
						ext: Externalities<'a, T, V, B>,
 | 
				
			||||||
	callcreates: Vec<CallCreate>,
 | 
						callcreates: Vec<CallCreate>,
 | 
				
			||||||
	contract_address: Address
 | 
						nonce: U256,
 | 
				
			||||||
 | 
						sender: Address,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
 | 
					impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
 | 
				
			||||||
@ -76,9 +77,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> TestExt<'a, T, V, B>
 | 
				
			|||||||
		vm_tracer: &'a mut V,
 | 
							vm_tracer: &'a mut V,
 | 
				
			||||||
	) -> trie::Result<Self> {
 | 
						) -> trie::Result<Self> {
 | 
				
			||||||
		Ok(TestExt {
 | 
							Ok(TestExt {
 | 
				
			||||||
			contract_address: contract_address(&address, &state.nonce(&address)?),
 | 
								nonce: state.nonce(&address)?,
 | 
				
			||||||
			ext: Externalities::new(state, info, engine, vm_factory, depth, origin_info, substate, output, tracer, vm_tracer),
 | 
								ext: Externalities::new(state, info, engine, vm_factory, depth, origin_info, substate, output, tracer, vm_tracer),
 | 
				
			||||||
			callcreates: vec![]
 | 
								callcreates: vec![],
 | 
				
			||||||
 | 
								sender: address,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -114,14 +116,15 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for TestExt<'a, T, V, B>
 | 
				
			|||||||
		self.ext.blockhash(number)
 | 
							self.ext.blockhash(number)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn create(&mut self, gas: &U256, value: &U256, code: &[u8]) -> ContractCreateResult {
 | 
						fn create(&mut self, gas: &U256, value: &U256, code: &[u8], address: CreateContractAddress) -> ContractCreateResult {
 | 
				
			||||||
		self.callcreates.push(CallCreate {
 | 
							self.callcreates.push(CallCreate {
 | 
				
			||||||
			data: code.to_vec(),
 | 
								data: code.to_vec(),
 | 
				
			||||||
			destination: None,
 | 
								destination: None,
 | 
				
			||||||
			gas_limit: *gas,
 | 
								gas_limit: *gas,
 | 
				
			||||||
			value: *value
 | 
								value: *value
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
		ContractCreateResult::Created(self.contract_address.clone(), *gas)
 | 
							let contract_address = contract_address(address, &self.sender, &self.nonce, &code.sha3());
 | 
				
			||||||
 | 
							ContractCreateResult::Created(contract_address, *gas)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn call(&mut self,
 | 
						fn call(&mut self,
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,8 @@ use ethereum;
 | 
				
			|||||||
use spec::Spec;
 | 
					use spec::Spec;
 | 
				
			||||||
use ethjson;
 | 
					use ethjson;
 | 
				
			||||||
use ethjson::state::test::ForkSpec;
 | 
					use ethjson::state::test::ForkSpec;
 | 
				
			||||||
 | 
					use types::transaction::SignedTransaction;
 | 
				
			||||||
 | 
					use env_info::EnvInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lazy_static! {
 | 
					lazy_static! {
 | 
				
			||||||
	pub static ref FRONTIER: Spec = ethereum::new_frontier_test();
 | 
						pub static ref FRONTIER: Spec = ethereum::new_frontier_test();
 | 
				
			||||||
@ -37,7 +39,7 @@ pub fn json_chain_test(json_data: &[u8]) -> Vec<String> {
 | 
				
			|||||||
	for (name, test) in tests.into_iter() {
 | 
						for (name, test) in tests.into_iter() {
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			let multitransaction = test.transaction;
 | 
								let multitransaction = test.transaction;
 | 
				
			||||||
			let env = test.env.into();
 | 
								let env: EnvInfo = test.env.into();
 | 
				
			||||||
			let pre: PodState = test.pre_state.into();
 | 
								let pre: PodState = test.pre_state.into();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (spec, states) in test.post_states {
 | 
								for (spec, states) in test.post_states {
 | 
				
			||||||
@ -54,12 +56,15 @@ pub fn json_chain_test(json_data: &[u8]) -> Vec<String> {
 | 
				
			|||||||
					let info = format!("   - {} | {:?} ({}/{}) ...", name, spec, i + 1, total);
 | 
										let info = format!("   - {} | {:?} ({}/{}) ...", name, spec, i + 1, total);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					let post_root: H256 = state.hash.into();
 | 
										let post_root: H256 = state.hash.into();
 | 
				
			||||||
					let transaction = multitransaction.select(&state.indexes).into();
 | 
										let transaction: SignedTransaction = multitransaction.select(&state.indexes).into();
 | 
				
			||||||
 | 
					 | 
				
			||||||
					let mut state = get_temp_state();
 | 
										let mut state = get_temp_state();
 | 
				
			||||||
					state.populate_from(pre.clone());
 | 
										state.populate_from(pre.clone());
 | 
				
			||||||
					state.commit().expect(&format!("State test {} failed due to internal error.", name));
 | 
										if transaction.verify_basic(true, None, env.number >= engine.params().eip86_transition).is_ok() {
 | 
				
			||||||
					let _res = state.apply(&env, &**engine, &transaction, false);
 | 
											state.commit().expect(&format!("State test {} failed due to internal error.", name));
 | 
				
			||||||
 | 
											let _res = state.apply(&env, &**engine, &transaction, false);
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											let _rest = state.commit();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					if state.root() != &post_root {
 | 
										if state.root() != &post_root {
 | 
				
			||||||
						println!("{} !!! State mismatch (got: {}, expect: {}", info, state.root(), post_root);
 | 
											println!("{} !!! State mismatch (got: {}, expect: {}", info, state.root(), post_root);
 | 
				
			||||||
						flushln!("{} fail", info);
 | 
											flushln!("{} fail", info);
 | 
				
			||||||
@ -73,7 +78,9 @@ pub fn json_chain_test(json_data: &[u8]) -> Vec<String> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	println!("!!! {:?} tests from failed.", failed.len());
 | 
						if !failed.is_empty() {
 | 
				
			||||||
 | 
							println!("!!! {:?} tests failed.", failed.len());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	failed
 | 
						failed
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,35 +18,37 @@ use super::test_common::*;
 | 
				
			|||||||
use evm;
 | 
					use evm;
 | 
				
			||||||
use ethjson;
 | 
					use ethjson;
 | 
				
			||||||
use rlp::UntrustedRlp;
 | 
					use rlp::UntrustedRlp;
 | 
				
			||||||
use transaction::{Action, UnverifiedTransaction};
 | 
					use transaction::{Action, UnverifiedTransaction, SignedTransaction};
 | 
				
			||||||
use ethstore::ethkey::public_to_address;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn do_json_test(json_data: &[u8]) -> Vec<String> {
 | 
					fn do_json_test(json_data: &[u8]) -> Vec<String> {
 | 
				
			||||||
	let tests = ethjson::transaction::Test::load(json_data).unwrap();
 | 
						let tests = ethjson::transaction::Test::load(json_data).unwrap();
 | 
				
			||||||
	let mut failed = Vec::new();
 | 
						let mut failed = Vec::new();
 | 
				
			||||||
	let old_schedule = evm::Schedule::new_frontier();
 | 
						let frontier_schedule = evm::Schedule::new_frontier();
 | 
				
			||||||
	let new_schedule = evm::Schedule::new_homestead();
 | 
						let homestead_schedule = evm::Schedule::new_homestead();
 | 
				
			||||||
 | 
						let metropolis_schedule = evm::Schedule::new_metropolis();
 | 
				
			||||||
	for (name, test) in tests.into_iter() {
 | 
						for (name, test) in tests.into_iter() {
 | 
				
			||||||
		let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); };
 | 
							let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let number: Option<u64> = test.block_number.map(Into::into);
 | 
							let number: Option<u64> = test.block_number.map(Into::into);
 | 
				
			||||||
		let schedule = match number {
 | 
							let schedule = match number {
 | 
				
			||||||
			None => &old_schedule,
 | 
								None => &frontier_schedule,
 | 
				
			||||||
			Some(x) if x < 1_150_000 => &old_schedule,
 | 
								Some(x) if x < 1_150_000 => &frontier_schedule,
 | 
				
			||||||
			Some(_) => &new_schedule
 | 
								Some(x) if x < 3_000_000 => &homestead_schedule,
 | 
				
			||||||
 | 
								Some(_) => &metropolis_schedule
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		let allow_network_id_of_one = number.map_or(false, |n| n >= 2_675_000);
 | 
							let allow_network_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<u8> = test.rlp.into();
 | 
							let rlp: Vec<u8> = test.rlp.into();
 | 
				
			||||||
		let res = UntrustedRlp::new(&rlp)
 | 
							let res = UntrustedRlp::new(&rlp)
 | 
				
			||||||
			.as_val()
 | 
								.as_val()
 | 
				
			||||||
			.map_err(From::from)
 | 
								.map_err(From::from)
 | 
				
			||||||
			.and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_network_id_of_one));
 | 
								.and_then(|t: UnverifiedTransaction| t.validate(schedule, schedule.have_delegate_call, allow_network_id_of_one, allow_unsigned));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fail_unless(test.transaction.is_none() == res.is_err(), "Validity different");
 | 
							fail_unless(test.transaction.is_none() == res.is_err(), "Validity different");
 | 
				
			||||||
		if let (Some(tx), Some(sender)) = (test.transaction, test.sender) {
 | 
							if let (Some(tx), Some(sender)) = (test.transaction, test.sender) {
 | 
				
			||||||
			let t = res.unwrap();
 | 
								let t = res.unwrap();
 | 
				
			||||||
			fail_unless(public_to_address(&t.recover_public().unwrap()) == sender.into(), "sender mismatch");
 | 
								fail_unless(SignedTransaction::new(t.clone()).unwrap().sender() == sender.into(), "sender mismatch");
 | 
				
			||||||
			let is_acceptable_network_id = match t.network_id() {
 | 
								let is_acceptable_network_id = match t.network_id() {
 | 
				
			||||||
				None => true,
 | 
									None => true,
 | 
				
			||||||
				Some(1) if allow_network_id_of_one => true,
 | 
									Some(1) if allow_network_id_of_one => true,
 | 
				
			||||||
@ -84,3 +86,7 @@ declare_test!{TransactionTests_Homestead_ttTransactionTestEip155VitaliksTests, "
 | 
				
			|||||||
declare_test!{TransactionTests_EIP155_ttTransactionTest, "TransactionTests/EIP155/ttTransactionTest"}
 | 
					declare_test!{TransactionTests_EIP155_ttTransactionTest, "TransactionTests/EIP155/ttTransactionTest"}
 | 
				
			||||||
declare_test!{TransactionTests_EIP155_ttTransactionTestEip155VitaliksTests, "TransactionTests/EIP155/ttTransactionTestEip155VitaliksTests"}
 | 
					declare_test!{TransactionTests_EIP155_ttTransactionTestEip155VitaliksTests, "TransactionTests/EIP155/ttTransactionTestEip155VitaliksTests"}
 | 
				
			||||||
declare_test!{TransactionTests_EIP155_ttTransactionTestVRule, "TransactionTests/EIP155/ttTransactionTestVRule"}
 | 
					declare_test!{TransactionTests_EIP155_ttTransactionTestVRule, "TransactionTests/EIP155/ttTransactionTestVRule"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					declare_test!{TransactionTests_Metropolis_ttMetropolisTest, "TransactionTests/Metropolis/ttMetropolisTest"}
 | 
				
			||||||
 | 
					declare_test!{TransactionTests_Metropolis_ttTransactionTest, "TransactionTests/Metropolis/ttTransactionTest"}
 | 
				
			||||||
 | 
					declare_test!{TransactionTests_Metropolis_ttTransactionTestZeroSig, "TransactionTests/Metropolis/ttTransactionTestZeroSig"}
 | 
				
			||||||
 | 
				
			|||||||
@ -170,3 +170,4 @@ mod json_tests;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub use types::*;
 | 
					pub use types::*;
 | 
				
			||||||
pub use executive::contract_address;
 | 
					pub use executive::contract_address;
 | 
				
			||||||
 | 
					pub use evm::CreateContractAddress;
 | 
				
			||||||
 | 
				
			|||||||
@ -1048,7 +1048,7 @@ impl MinerService for Miner {
 | 
				
			|||||||
								Action::Call(_) => None,
 | 
													Action::Call(_) => None,
 | 
				
			||||||
								Action::Create => {
 | 
													Action::Create => {
 | 
				
			||||||
									let sender = tx.sender();
 | 
														let sender = tx.sender();
 | 
				
			||||||
									Some(contract_address(&sender, &tx.nonce))
 | 
														Some(contract_address(self.engine.schedule(pending.header().number()).create_address, &sender, &tx.nonce, &tx.data.sha3()))
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
							logs: receipt.logs.clone(),
 | 
												logs: receipt.logs.clone(),
 | 
				
			||||||
@ -1327,6 +1327,10 @@ mod tests {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn transaction() -> SignedTransaction {
 | 
						fn transaction() -> SignedTransaction {
 | 
				
			||||||
 | 
							transaction_with_network_id(2)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn transaction_with_network_id(id: u64) -> SignedTransaction {
 | 
				
			||||||
		let keypair = Random.generate().unwrap();
 | 
							let keypair = Random.generate().unwrap();
 | 
				
			||||||
		Transaction {
 | 
							Transaction {
 | 
				
			||||||
			action: Action::Create,
 | 
								action: Action::Create,
 | 
				
			||||||
@ -1335,7 +1339,7 @@ mod tests {
 | 
				
			|||||||
			gas: U256::from(100_000),
 | 
								gas: U256::from(100_000),
 | 
				
			||||||
			gas_price: U256::zero(),
 | 
								gas_price: U256::zero(),
 | 
				
			||||||
			nonce: U256::zero(),
 | 
								nonce: U256::zero(),
 | 
				
			||||||
		}.sign(keypair.secret(), None)
 | 
							}.sign(keypair.secret(), Some(id))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
@ -1411,18 +1415,19 @@ mod tests {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn internal_seals_without_work() {
 | 
						fn internal_seals_without_work() {
 | 
				
			||||||
		let miner = Miner::with_spec(&Spec::new_instant());
 | 
							let spec = Spec::new_instant();
 | 
				
			||||||
 | 
							let miner = Miner::with_spec(&spec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let client = generate_dummy_client(2);
 | 
							let client = generate_dummy_client(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		assert_eq!(miner.import_external_transactions(&*client, vec![transaction().into()]).pop().unwrap().unwrap(), TransactionImportResult::Current);
 | 
							assert_eq!(miner.import_external_transactions(&*client, vec![transaction_with_network_id(spec.network_id()).into()]).pop().unwrap().unwrap(), TransactionImportResult::Current);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		miner.update_sealing(&*client);
 | 
							miner.update_sealing(&*client);
 | 
				
			||||||
		client.flush_queue();
 | 
							client.flush_queue();
 | 
				
			||||||
		assert!(miner.pending_block().is_none());
 | 
							assert!(miner.pending_block().is_none());
 | 
				
			||||||
		assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber);
 | 
							assert_eq!(client.chain_info().best_block_number, 3 as BlockNumber);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		assert_eq!(miner.import_own_transaction(&*client, PendingTransaction::new(transaction().into(), None)).unwrap(), TransactionImportResult::Current);
 | 
							assert_eq!(miner.import_own_transaction(&*client, PendingTransaction::new(transaction_with_network_id(spec.network_id()).into(), None)).unwrap(), TransactionImportResult::Current);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		miner.update_sealing(&*client);
 | 
							miner.update_sealing(&*client);
 | 
				
			||||||
		client.flush_queue();
 | 
							client.flush_queue();
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,8 @@ pub struct CommonParams {
 | 
				
			|||||||
	pub eip98_transition: BlockNumber,
 | 
						pub eip98_transition: BlockNumber,
 | 
				
			||||||
	/// Validate block receipts root.
 | 
						/// Validate block receipts root.
 | 
				
			||||||
	pub validate_receipts_transition: u64,
 | 
						pub validate_receipts_transition: u64,
 | 
				
			||||||
 | 
						/// Number of first block where EIP-86 (Metropolis) rules begin.
 | 
				
			||||||
 | 
						pub eip86_transition: BlockNumber,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<ethjson::spec::Params> for CommonParams {
 | 
					impl From<ethjson::spec::Params> for CommonParams {
 | 
				
			||||||
@ -71,6 +73,7 @@ impl From<ethjson::spec::Params> for CommonParams {
 | 
				
			|||||||
			fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
 | 
								fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None },
 | 
				
			||||||
			eip98_transition: p.eip98_transition.map_or(0, Into::into),
 | 
								eip98_transition: p.eip98_transition.map_or(0, Into::into),
 | 
				
			||||||
			validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
 | 
								validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
 | 
				
			||||||
 | 
								eip86_transition: p.eip86_transition.map_or(BlockNumber::max_value(), Into::into),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -306,6 +309,7 @@ impl Spec {
 | 
				
			|||||||
				call_type: CallType::None,
 | 
									call_type: CallType::None,
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
			let mut substate = Substate::new();
 | 
								let mut substate = Substate::new();
 | 
				
			||||||
 | 
								state.kill_account(address);
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				let mut exec = Executive::new(&mut state, &env_info, self.engine.as_ref(), &factories.vm);
 | 
									let mut exec = Executive::new(&mut state, &env_info, self.engine.as_ref(), &factories.vm);
 | 
				
			||||||
				if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
 | 
									if let Err(e) = exec.create(params, &mut substate, &mut NoopTracer, &mut NoopVMTracer) {
 | 
				
			||||||
@ -391,6 +395,7 @@ mod tests {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	#[test]
 | 
						#[test]
 | 
				
			||||||
	fn genesis_constructor() {
 | 
						fn genesis_constructor() {
 | 
				
			||||||
 | 
							::ethcore_logger::init_log();
 | 
				
			||||||
		let spec = Spec::new_test_constructor();
 | 
							let spec = Spec::new_test_constructor();
 | 
				
			||||||
		let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
 | 
							let db = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
 | 
				
			||||||
		let state = State::from_existing(db.boxed_clone(), spec.state_root(), spec.engine.account_start_nonce(), Default::default()).unwrap();
 | 
							let state = State::from_existing(db.boxed_clone(), spec.state_root(), spec.engine.account_start_nonce(), Default::default()).unwrap();
 | 
				
			||||||
 | 
				
			|||||||
@ -1279,7 +1279,7 @@ mod tests {
 | 
				
			|||||||
		info.number = 0x789b0;
 | 
							info.number = 0x789b0;
 | 
				
			||||||
		let engine = &*Spec::new_test().engine;
 | 
							let engine = &*Spec::new_test().engine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		println!("schedule.have_delegate_call: {:?}", engine.schedule(&info).have_delegate_call);
 | 
							println!("schedule.have_delegate_call: {:?}", engine.schedule(info.number).have_delegate_call);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let t = Transaction {
 | 
							let t = Transaction {
 | 
				
			||||||
			nonce: 0.into(),
 | 
								nonce: 0.into(),
 | 
				
			||||||
 | 
				
			|||||||
@ -162,7 +162,7 @@ fn returns_logs_with_limit() {
 | 
				
			|||||||
		to_block: BlockId::Latest,
 | 
							to_block: BlockId::Latest,
 | 
				
			||||||
		address: None,
 | 
							address: None,
 | 
				
			||||||
		topics: vec![],
 | 
							topics: vec![],
 | 
				
			||||||
		limit: Some(2),
 | 
							limit: None,
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
	assert_eq!(logs.len(), 0);
 | 
						assert_eq!(logs.len(), 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,6 @@ use builtin::Builtin;
 | 
				
			|||||||
use state::*;
 | 
					use state::*;
 | 
				
			||||||
use evm::Schedule;
 | 
					use evm::Schedule;
 | 
				
			||||||
use engines::Engine;
 | 
					use engines::Engine;
 | 
				
			||||||
use env_info::EnvInfo;
 | 
					 | 
				
			||||||
use ethereum;
 | 
					use ethereum;
 | 
				
			||||||
use ethereum::ethash::EthashParams;
 | 
					use ethereum::ethash::EthashParams;
 | 
				
			||||||
use miner::Miner;
 | 
					use miner::Miner;
 | 
				
			||||||
@ -72,7 +71,7 @@ impl Engine for TestEngine {
 | 
				
			|||||||
		self.engine.builtins()
 | 
							self.engine.builtins()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn schedule(&self, _env_info: &EnvInfo) -> Schedule {
 | 
						fn schedule(&self, _block_number: u64) -> Schedule {
 | 
				
			||||||
		let mut schedule = Schedule::new_frontier();
 | 
							let mut schedule = Schedule::new_frontier();
 | 
				
			||||||
		schedule.max_depth = self.max_depth;
 | 
							schedule.max_depth = self.max_depth;
 | 
				
			||||||
		schedule
 | 
							schedule
 | 
				
			||||||
@ -201,7 +200,7 @@ pub fn generate_dummy_client_with_spec_accounts_and_data<F>(get_test_spec: F, ac
 | 
				
			|||||||
				action: Action::Create,
 | 
									action: Action::Create,
 | 
				
			||||||
				data: vec![],
 | 
									data: vec![],
 | 
				
			||||||
				value: U256::zero(),
 | 
									value: U256::zero(),
 | 
				
			||||||
			}.sign(kp.secret(), None), None).unwrap();
 | 
								}.sign(kp.secret(), Some(test_spec.network_id())), None).unwrap();
 | 
				
			||||||
			n += 1;
 | 
								n += 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -19,13 +19,16 @@
 | 
				
			|||||||
use std::ops::Deref;
 | 
					use std::ops::Deref;
 | 
				
			||||||
use rlp::*;
 | 
					use rlp::*;
 | 
				
			||||||
use util::sha3::Hashable;
 | 
					use util::sha3::Hashable;
 | 
				
			||||||
use util::{H256, Address, U256, Bytes, HeapSizeOf};
 | 
					use util::{H256, Address, U256, Bytes, HeapSizeOf, Uint};
 | 
				
			||||||
use ethkey::{Signature, Secret, Public, recover, public_to_address, Error as EthkeyError};
 | 
					use ethkey::{Signature, Secret, Public, recover, public_to_address, Error as EthkeyError};
 | 
				
			||||||
use error::*;
 | 
					use error::*;
 | 
				
			||||||
use evm::Schedule;
 | 
					use evm::Schedule;
 | 
				
			||||||
use header::BlockNumber;
 | 
					use header::BlockNumber;
 | 
				
			||||||
use ethjson;
 | 
					use ethjson;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Fake address for unsigned transactions as defined by EIP-86.
 | 
				
			||||||
 | 
					pub const UNSIGNED_SENDER: Address = ::util::H160([0xff; 20]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug, Clone, PartialEq, Eq)]
 | 
					#[derive(Debug, Clone, PartialEq, Eq)]
 | 
				
			||||||
#[cfg_attr(feature = "ipc", binary)]
 | 
					#[cfg_attr(feature = "ipc", binary)]
 | 
				
			||||||
/// Transaction action type.
 | 
					/// Transaction action type.
 | 
				
			||||||
@ -110,8 +113,8 @@ impl HeapSizeOf for Transaction {
 | 
				
			|||||||
impl From<ethjson::state::Transaction> for SignedTransaction {
 | 
					impl From<ethjson::state::Transaction> for SignedTransaction {
 | 
				
			||||||
	fn from(t: ethjson::state::Transaction) -> Self {
 | 
						fn from(t: ethjson::state::Transaction) -> Self {
 | 
				
			||||||
		let to: Option<ethjson::hash::Address> = t.to.into();
 | 
							let to: Option<ethjson::hash::Address> = t.to.into();
 | 
				
			||||||
		let secret = Secret::from_slice(&t.secret.0).expect("Valid secret expected.");
 | 
							let secret = t.secret.map(|s| Secret::from_slice(&s.0).expect("Valid secret expected."));
 | 
				
			||||||
		Transaction {
 | 
							let tx = Transaction {
 | 
				
			||||||
			nonce: t.nonce.into(),
 | 
								nonce: t.nonce.into(),
 | 
				
			||||||
			gas_price: t.gas_price.into(),
 | 
								gas_price: t.gas_price.into(),
 | 
				
			||||||
			gas: t.gas_limit.into(),
 | 
								gas: t.gas_limit.into(),
 | 
				
			||||||
@ -121,7 +124,11 @@ impl From<ethjson::state::Transaction> for SignedTransaction {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			value: t.value.into(),
 | 
								value: t.value.into(),
 | 
				
			||||||
			data: t.data.into(),
 | 
								data: t.data.into(),
 | 
				
			||||||
		}.sign(&secret, None)
 | 
							};
 | 
				
			||||||
 | 
							match secret {
 | 
				
			||||||
 | 
								Some(s) => tx.sign(&s, None),
 | 
				
			||||||
 | 
								None => tx.null_sign(),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -180,8 +187,8 @@ impl Transaction {
 | 
				
			|||||||
	pub fn invalid_sign(self) -> UnverifiedTransaction {
 | 
						pub fn invalid_sign(self) -> UnverifiedTransaction {
 | 
				
			||||||
		UnverifiedTransaction {
 | 
							UnverifiedTransaction {
 | 
				
			||||||
			unsigned: self,
 | 
								unsigned: self,
 | 
				
			||||||
			r: U256::default(),
 | 
								r: U256::one(),
 | 
				
			||||||
			s: U256::default(),
 | 
								s: U256::one(),
 | 
				
			||||||
			v: 0,
 | 
								v: 0,
 | 
				
			||||||
			hash: 0.into(),
 | 
								hash: 0.into(),
 | 
				
			||||||
		}.compute_hash()
 | 
							}.compute_hash()
 | 
				
			||||||
@ -192,13 +199,28 @@ impl Transaction {
 | 
				
			|||||||
		SignedTransaction {
 | 
							SignedTransaction {
 | 
				
			||||||
			transaction: UnverifiedTransaction {
 | 
								transaction: UnverifiedTransaction {
 | 
				
			||||||
				unsigned: self,
 | 
									unsigned: self,
 | 
				
			||||||
				r: U256::default(),
 | 
									r: U256::one(),
 | 
				
			||||||
				s: U256::default(),
 | 
									s: U256::one(),
 | 
				
			||||||
				v: 0,
 | 
									v: 0,
 | 
				
			||||||
				hash: 0.into(),
 | 
									hash: 0.into(),
 | 
				
			||||||
			}.compute_hash(),
 | 
								}.compute_hash(),
 | 
				
			||||||
			sender: from,
 | 
								sender: from,
 | 
				
			||||||
			public: Public::default(),
 | 
								public: None,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Add EIP-86 compatible empty signature.
 | 
				
			||||||
 | 
						pub fn null_sign(self) -> SignedTransaction {
 | 
				
			||||||
 | 
							SignedTransaction {
 | 
				
			||||||
 | 
								transaction: UnverifiedTransaction {
 | 
				
			||||||
 | 
									unsigned: self,
 | 
				
			||||||
 | 
									r: U256::zero(),
 | 
				
			||||||
 | 
									s: U256::zero(),
 | 
				
			||||||
 | 
									v: 0,
 | 
				
			||||||
 | 
									hash: 0.into(),
 | 
				
			||||||
 | 
								}.compute_hash(),
 | 
				
			||||||
 | 
								sender: UNSIGNED_SENDER,
 | 
				
			||||||
 | 
								public: None,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -276,6 +298,11 @@ impl UnverifiedTransaction {
 | 
				
			|||||||
		self
 | 
							self
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Checks is signature is empty.
 | 
				
			||||||
 | 
						pub fn is_unsigned(&self) -> bool {
 | 
				
			||||||
 | 
							self.r.is_zero() && self.s.is_zero()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Append object with a signature into RLP stream
 | 
						/// Append object with a signature into RLP stream
 | 
				
			||||||
	fn rlp_append_sealed_transaction(&self, s: &mut RlpStream) {
 | 
						fn rlp_append_sealed_transaction(&self, s: &mut RlpStream) {
 | 
				
			||||||
		s.begin_list(9);
 | 
							s.begin_list(9);
 | 
				
			||||||
@ -307,6 +334,7 @@ impl UnverifiedTransaction {
 | 
				
			|||||||
	/// The network ID, or `None` if this is a global transaction.
 | 
						/// The network ID, or `None` if this is a global transaction.
 | 
				
			||||||
	pub fn network_id(&self) -> Option<u64> {
 | 
						pub fn network_id(&self) -> Option<u64> {
 | 
				
			||||||
		match self.v {
 | 
							match self.v {
 | 
				
			||||||
 | 
								v if self.is_unsigned() => Some(v),
 | 
				
			||||||
			v if v > 36 => Some((v - 35) / 2),
 | 
								v if v > 36 => Some((v - 35) / 2),
 | 
				
			||||||
			_ => None,
 | 
								_ => None,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -340,21 +368,33 @@ impl UnverifiedTransaction {
 | 
				
			|||||||
	// TODO: consider use in block validation.
 | 
						// TODO: consider use in block validation.
 | 
				
			||||||
	#[cfg(test)]
 | 
						#[cfg(test)]
 | 
				
			||||||
	#[cfg(feature = "json-tests")]
 | 
						#[cfg(feature = "json-tests")]
 | 
				
			||||||
	pub fn validate(self, schedule: &Schedule, require_low: bool, allow_network_id_of_one: bool) -> Result<UnverifiedTransaction, Error> {
 | 
						pub fn validate(self, schedule: &Schedule, require_low: bool, allow_network_id_of_one: bool, allow_empty_signature: bool) -> Result<UnverifiedTransaction, Error> {
 | 
				
			||||||
		if require_low && !self.signature().is_low_s() {
 | 
							let chain_id = if allow_network_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(TransactionError::InvalidGasLimit(::util::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<u64>, allow_empty_signature: bool) -> Result<(), Error> {
 | 
				
			||||||
 | 
							if check_low_s && !(allow_empty_signature && self.is_unsigned()) {
 | 
				
			||||||
 | 
								self.check_low_s()?;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// EIP-86: Transactions of this form MUST have gasprice = 0, nonce = 0, value = 0, and do NOT increment the nonce of account 0.
 | 
				
			||||||
 | 
							if allow_empty_signature && self.is_unsigned() && !(self.gas_price.is_zero() && self.value.is_zero() && self.nonce.is_zero()) {
 | 
				
			||||||
			return Err(EthkeyError::InvalidSignature.into())
 | 
								return Err(EthkeyError::InvalidSignature.into())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		match self.network_id() {
 | 
							match (self.network_id(), chain_id) {
 | 
				
			||||||
			None => {},
 | 
								(None, _) => {},
 | 
				
			||||||
			Some(1) if allow_network_id_of_one => {},
 | 
								(Some(n), Some(m)) if n == m => {},
 | 
				
			||||||
			_ => return Err(TransactionError::InvalidNetworkId.into()),
 | 
								_ => return Err(TransactionError::InvalidNetworkId.into()),
 | 
				
			||||||
		}
 | 
							};
 | 
				
			||||||
		self.recover_public()?;
 | 
							Ok(())
 | 
				
			||||||
		if self.gas < U256::from(self.gas_required(&schedule)) {
 | 
					 | 
				
			||||||
			Err(TransactionError::InvalidGasLimit(::util::OutOfBounds{min: Some(U256::from(self.gas_required(&schedule))), max: None, found: self.gas}).into())
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			Ok(self)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -363,7 +403,7 @@ impl UnverifiedTransaction {
 | 
				
			|||||||
pub struct SignedTransaction {
 | 
					pub struct SignedTransaction {
 | 
				
			||||||
	transaction: UnverifiedTransaction,
 | 
						transaction: UnverifiedTransaction,
 | 
				
			||||||
	sender: Address,
 | 
						sender: Address,
 | 
				
			||||||
	public: Public,
 | 
						public: Option<Public>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl HeapSizeOf for SignedTransaction {
 | 
					impl HeapSizeOf for SignedTransaction {
 | 
				
			||||||
@ -392,13 +432,21 @@ impl From<SignedTransaction> for UnverifiedTransaction {
 | 
				
			|||||||
impl SignedTransaction {
 | 
					impl SignedTransaction {
 | 
				
			||||||
	/// Try to verify transaction and recover sender.
 | 
						/// Try to verify transaction and recover sender.
 | 
				
			||||||
	pub fn new(transaction: UnverifiedTransaction) -> Result<Self, Error> {
 | 
						pub fn new(transaction: UnverifiedTransaction) -> Result<Self, Error> {
 | 
				
			||||||
		let public = transaction.recover_public()?;
 | 
							if transaction.is_unsigned() {
 | 
				
			||||||
		let sender = public_to_address(&public);
 | 
								Ok(SignedTransaction {
 | 
				
			||||||
		Ok(SignedTransaction {
 | 
									transaction: transaction,
 | 
				
			||||||
			transaction: transaction,
 | 
									sender: UNSIGNED_SENDER,
 | 
				
			||||||
			sender: sender,
 | 
									public: None,
 | 
				
			||||||
			public: public,
 | 
								})
 | 
				
			||||||
		})
 | 
							} else {
 | 
				
			||||||
 | 
								let public = transaction.recover_public()?;
 | 
				
			||||||
 | 
								let sender = public_to_address(&public);
 | 
				
			||||||
 | 
								Ok(SignedTransaction {
 | 
				
			||||||
 | 
									transaction: transaction,
 | 
				
			||||||
 | 
									sender: sender,
 | 
				
			||||||
 | 
									public: Some(public),
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Returns transaction sender.
 | 
						/// Returns transaction sender.
 | 
				
			||||||
@ -407,9 +455,14 @@ impl SignedTransaction {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Returns a public key of the sender.
 | 
						/// Returns a public key of the sender.
 | 
				
			||||||
	pub fn public_key(&self) -> Public {
 | 
						pub fn public_key(&self) -> Option<Public> {
 | 
				
			||||||
		self.public
 | 
							self.public
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/// Checks is signature is empty.
 | 
				
			||||||
 | 
						pub fn is_unsigned(&self) -> bool {
 | 
				
			||||||
 | 
							self.transaction.is_unsigned()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Signed Transaction that is a part of canon blockchain.
 | 
					/// Signed Transaction that is a part of canon blockchain.
 | 
				
			||||||
@ -435,6 +488,9 @@ impl LocalizedTransaction {
 | 
				
			|||||||
		if let Some(sender) = self.cached_sender {
 | 
							if let Some(sender) = self.cached_sender {
 | 
				
			||||||
			return sender;
 | 
								return sender;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if self.is_unsigned() {
 | 
				
			||||||
 | 
								return UNSIGNED_SENDER.clone();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		let sender = public_to_address(&self.recover_public()
 | 
							let sender = public_to_address(&self.recover_public()
 | 
				
			||||||
			.expect("LocalizedTransaction is always constructed from transaction from blockchain; Blockchain only stores verified transactions; qed"));
 | 
								.expect("LocalizedTransaction is always constructed from transaction from blockchain; Blockchain only stores verified transactions; qed"));
 | 
				
			||||||
		self.cached_sender = Some(sender);
 | 
							self.cached_sender = Some(sender);
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ use std::sync::Arc;
 | 
				
			|||||||
use std::collections::HashMap;
 | 
					use std::collections::HashMap;
 | 
				
			||||||
use util::{U256, H256, Address, Bytes, trie};
 | 
					use util::{U256, H256, Address, Bytes, trie};
 | 
				
			||||||
use ethcore::client::EnvInfo;
 | 
					use ethcore::client::EnvInfo;
 | 
				
			||||||
use ethcore::evm::{self, Ext, ContractCreateResult, MessageCallResult, Schedule, CallType};
 | 
					use ethcore::evm::{self, Ext, ContractCreateResult, MessageCallResult, Schedule, CallType, CreateContractAddress};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct FakeExt {
 | 
					pub struct FakeExt {
 | 
				
			||||||
	schedule: Schedule,
 | 
						schedule: Schedule,
 | 
				
			||||||
@ -31,7 +31,7 @@ pub struct FakeExt {
 | 
				
			|||||||
impl Default for FakeExt {
 | 
					impl Default for FakeExt {
 | 
				
			||||||
	fn default() -> Self {
 | 
						fn default() -> Self {
 | 
				
			||||||
		FakeExt {
 | 
							FakeExt {
 | 
				
			||||||
			schedule: Schedule::new_post_eip150(usize::max_value(), true, true, true),
 | 
								schedule: Schedule::new_post_eip150(usize::max_value(), true, true, true, true),
 | 
				
			||||||
			store: HashMap::new(),
 | 
								store: HashMap::new(),
 | 
				
			||||||
			depth: 1,
 | 
								depth: 1,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -68,7 +68,7 @@ impl Ext for FakeExt {
 | 
				
			|||||||
		unimplemented!();
 | 
							unimplemented!();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn create(&mut self, _gas: &U256, _value: &U256, _code: &[u8]) -> ContractCreateResult {
 | 
						fn create(&mut self, _gas: &U256, _value: &U256, _code: &[u8], _address: CreateContractAddress) -> ContractCreateResult {
 | 
				
			||||||
		unimplemented!();
 | 
							unimplemented!();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -56,6 +56,9 @@ pub struct Params {
 | 
				
			|||||||
	/// See `CommonParams` docs.
 | 
						/// See `CommonParams` docs.
 | 
				
			||||||
	#[serde(rename="validateReceiptsTransition")]
 | 
						#[serde(rename="validateReceiptsTransition")]
 | 
				
			||||||
	pub validate_receipts_transition: Option<Uint>,
 | 
						pub validate_receipts_transition: Option<Uint>,
 | 
				
			||||||
 | 
						/// See `CommonParams` docs.
 | 
				
			||||||
 | 
						#[serde(rename="eip86Transition")]
 | 
				
			||||||
 | 
						pub eip86_transition: Option<Uint>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[cfg(test)]
 | 
					#[cfg(test)]
 | 
				
			||||||
 | 
				
			|||||||
@ -75,7 +75,7 @@ pub struct MultiTransaction {
 | 
				
			|||||||
	pub nonce: Uint,
 | 
						pub nonce: Uint,
 | 
				
			||||||
	/// Secret key.
 | 
						/// Secret key.
 | 
				
			||||||
	#[serde(rename="secretKey")]
 | 
						#[serde(rename="secretKey")]
 | 
				
			||||||
	pub secret: H256,
 | 
						pub secret: Option<H256>,
 | 
				
			||||||
	/// To.
 | 
						/// To.
 | 
				
			||||||
	pub to: MaybeEmpty<Address>,
 | 
						pub to: MaybeEmpty<Address>,
 | 
				
			||||||
	/// Value set.
 | 
						/// Value set.
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ pub struct Transaction {
 | 
				
			|||||||
	pub nonce: Uint,
 | 
						pub nonce: Uint,
 | 
				
			||||||
	/// Secret key.
 | 
						/// Secret key.
 | 
				
			||||||
	#[serde(rename="secretKey")]
 | 
						#[serde(rename="secretKey")]
 | 
				
			||||||
	pub secret: H256,
 | 
						pub secret: Option<H256>,
 | 
				
			||||||
	/// To.
 | 
						/// To.
 | 
				
			||||||
	pub to: MaybeEmpty<Address>,
 | 
						pub to: MaybeEmpty<Address>,
 | 
				
			||||||
	/// Value.
 | 
						/// Value.
 | 
				
			||||||
 | 
				
			|||||||
@ -395,6 +395,7 @@ impl Dependencies for LightDependencies {
 | 
				
			|||||||
						false => None,
 | 
											false => None,
 | 
				
			||||||
					};
 | 
										};
 | 
				
			||||||
					handler.extend_with(light::ParityClient::new(
 | 
										handler.extend_with(light::ParityClient::new(
 | 
				
			||||||
 | 
											self.client.clone(),
 | 
				
			||||||
						Arc::new(dispatcher.clone()),
 | 
											Arc::new(dispatcher.clone()),
 | 
				
			||||||
						self.secret_store.clone(),
 | 
											self.secret_store.clone(),
 | 
				
			||||||
						self.logger.clone(),
 | 
											self.logger.clone(),
 | 
				
			||||||
 | 
				
			|||||||
@ -103,6 +103,7 @@ pub struct EthClient<C, SN: ?Sized, S: ?Sized, M, EM> where
 | 
				
			|||||||
	external_miner: Arc<EM>,
 | 
						external_miner: Arc<EM>,
 | 
				
			||||||
	seed_compute: Mutex<SeedHashCompute>,
 | 
						seed_compute: Mutex<SeedHashCompute>,
 | 
				
			||||||
	options: EthClientOptions,
 | 
						options: EthClientOptions,
 | 
				
			||||||
 | 
						eip86_transition: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
 | 
					impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
 | 
				
			||||||
@ -131,6 +132,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
 | 
				
			|||||||
			external_miner: em.clone(),
 | 
								external_miner: em.clone(),
 | 
				
			||||||
			seed_compute: Mutex::new(SeedHashCompute::new()),
 | 
								seed_compute: Mutex::new(SeedHashCompute::new()),
 | 
				
			||||||
			options: options,
 | 
								options: options,
 | 
				
			||||||
 | 
								eip86_transition: client.eip86_transition(),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -166,7 +168,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
 | 
				
			|||||||
						seal_fields: view.seal().into_iter().map(Into::into).collect(),
 | 
											seal_fields: view.seal().into_iter().map(Into::into).collect(),
 | 
				
			||||||
						uncles: block.uncle_hashes().into_iter().map(Into::into).collect(),
 | 
											uncles: block.uncle_hashes().into_iter().map(Into::into).collect(),
 | 
				
			||||||
						transactions: match include_txs {
 | 
											transactions: match include_txs {
 | 
				
			||||||
							true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(Into::into).collect()),
 | 
												true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t, self.eip86_transition)).collect()),
 | 
				
			||||||
							false => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()),
 | 
												false => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()),
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
						extra_data: Bytes::new(view.extra_data()),
 | 
											extra_data: Bytes::new(view.extra_data()),
 | 
				
			||||||
@ -180,7 +182,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> EthClient<C, SN, S, M, EM> where
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	fn transaction(&self, id: TransactionId) -> Result<Option<Transaction>, Error> {
 | 
						fn transaction(&self, id: TransactionId) -> Result<Option<Transaction>, Error> {
 | 
				
			||||||
		match take_weak!(self.client).transaction(id) {
 | 
							match take_weak!(self.client).transaction(id) {
 | 
				
			||||||
			Some(t) => Ok(Some(Transaction::from(t))),
 | 
								Some(t) => Ok(Some(Transaction::from_localized(t, self.eip86_transition))),
 | 
				
			||||||
			None => Ok(None),
 | 
								None => Ok(None),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -507,7 +509,8 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
 | 
				
			|||||||
		let hash: H256 = hash.into();
 | 
							let hash: H256 = hash.into();
 | 
				
			||||||
		let miner = take_weak!(self.miner);
 | 
							let miner = take_weak!(self.miner);
 | 
				
			||||||
		let client = take_weak!(self.client);
 | 
							let client = take_weak!(self.client);
 | 
				
			||||||
		Ok(self.transaction(TransactionId::Hash(hash))?.or_else(|| miner.transaction(client.chain_info().best_block_number, &hash).map(Into::into)))
 | 
							let block_number = client.chain_info().best_block_number;
 | 
				
			||||||
 | 
							Ok(self.transaction(TransactionId::Hash(hash))?.or_else(|| miner.transaction(block_number, &hash).map(|t| Transaction::from_pending(t, block_number, self.eip86_transition))))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn transaction_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> Result<Option<Transaction>, Error> {
 | 
						fn transaction_by_block_hash_and_index(&self, hash: RpcH256, index: Index) -> Result<Option<Transaction>, Error> {
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ use jsonrpc_core::Error;
 | 
				
			|||||||
use jsonrpc_macros::Trailing;
 | 
					use jsonrpc_macros::Trailing;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use light::cache::Cache as LightDataCache;
 | 
					use light::cache::Cache as LightDataCache;
 | 
				
			||||||
use light::client::Client as LightClient;
 | 
					use light::client::{Client as LightClient, LightChainClient};
 | 
				
			||||||
use light::{cht, TransactionQueue};
 | 
					use light::{cht, TransactionQueue};
 | 
				
			||||||
use light::on_demand::{request, OnDemand};
 | 
					use light::on_demand::{request, OnDemand};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -123,6 +123,7 @@ impl EthClient {
 | 
				
			|||||||
	fn rich_block(&self, id: BlockId, include_txs: bool) -> BoxFuture<Option<RichBlock>, Error> {
 | 
						fn rich_block(&self, id: BlockId, include_txs: bool) -> BoxFuture<Option<RichBlock>, Error> {
 | 
				
			||||||
		let (on_demand, sync) = (self.on_demand.clone(), self.sync.clone());
 | 
							let (on_demand, sync) = (self.on_demand.clone(), self.sync.clone());
 | 
				
			||||||
		let (client, engine) = (self.client.clone(), self.client.engine().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.
 | 
							// 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<U256>| {
 | 
							let fill_rich = move |block: encoded::Block, score: Option<U256>| {
 | 
				
			||||||
@ -149,8 +150,8 @@ impl EthClient {
 | 
				
			|||||||
					seal_fields: header.seal().into_iter().cloned().map(Into::into).collect(),
 | 
										seal_fields: header.seal().into_iter().cloned().map(Into::into).collect(),
 | 
				
			||||||
					uncles: block.uncle_hashes().into_iter().map(Into::into).collect(),
 | 
										uncles: block.uncle_hashes().into_iter().map(Into::into).collect(),
 | 
				
			||||||
					transactions: match include_txs {
 | 
										transactions: match include_txs {
 | 
				
			||||||
						true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(Into::into).collect()),
 | 
											true => BlockTransactions::Full(block.view().localized_transactions().into_iter().map(|t| Transaction::from_localized(t, eip86_transition)).collect()),
 | 
				
			||||||
						false => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()),
 | 
											_ => BlockTransactions::Hashes(block.transaction_hashes().into_iter().map(Into::into).collect()),
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					extra_data: Bytes::new(header.extra_data().to_vec()),
 | 
										extra_data: Bytes::new(header.extra_data().to_vec()),
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,8 @@ use ethstore::random_phrase;
 | 
				
			|||||||
use ethsync::LightSyncProvider;
 | 
					use ethsync::LightSyncProvider;
 | 
				
			||||||
use ethcore::account_provider::AccountProvider;
 | 
					use ethcore::account_provider::AccountProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use light::client::LightChainClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use jsonrpc_core::Error;
 | 
					use jsonrpc_core::Error;
 | 
				
			||||||
use jsonrpc_macros::Trailing;
 | 
					use jsonrpc_macros::Trailing;
 | 
				
			||||||
use v1::helpers::{errors, ipfs, SigningQueue, SignerService, NetworkSettings};
 | 
					use v1::helpers::{errors, ipfs, SigningQueue, SignerService, NetworkSettings};
 | 
				
			||||||
@ -53,11 +55,13 @@ pub struct ParityClient {
 | 
				
			|||||||
	signer: Option<Arc<SignerService>>,
 | 
						signer: Option<Arc<SignerService>>,
 | 
				
			||||||
	dapps_interface: Option<String>,
 | 
						dapps_interface: Option<String>,
 | 
				
			||||||
	dapps_port: Option<u16>,
 | 
						dapps_port: Option<u16>,
 | 
				
			||||||
 | 
						eip86_transition: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl ParityClient {
 | 
					impl ParityClient {
 | 
				
			||||||
	/// Creates new `ParityClient`.
 | 
						/// Creates new `ParityClient`.
 | 
				
			||||||
	pub fn new(
 | 
						pub fn new(
 | 
				
			||||||
 | 
							client: Arc<LightChainClient>,
 | 
				
			||||||
		light_dispatch: Arc<LightDispatcher>,
 | 
							light_dispatch: Arc<LightDispatcher>,
 | 
				
			||||||
		accounts: Arc<AccountProvider>,
 | 
							accounts: Arc<AccountProvider>,
 | 
				
			||||||
		logger: Arc<RotatingLogger>,
 | 
							logger: Arc<RotatingLogger>,
 | 
				
			||||||
@ -74,6 +78,7 @@ impl ParityClient {
 | 
				
			|||||||
			signer: signer,
 | 
								signer: signer,
 | 
				
			||||||
			dapps_interface: dapps_interface,
 | 
								dapps_interface: dapps_interface,
 | 
				
			||||||
			dapps_port: dapps_port,
 | 
								dapps_port: dapps_port,
 | 
				
			||||||
 | 
								eip86_transition: client.eip86_transition(),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -245,7 +250,7 @@ impl Parity for ParityClient {
 | 
				
			|||||||
		Ok(
 | 
							Ok(
 | 
				
			||||||
			txq.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
 | 
								txq.ready_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
 | 
				
			||||||
				.into_iter()
 | 
									.into_iter()
 | 
				
			||||||
				.map(Into::into)
 | 
									.map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition))
 | 
				
			||||||
				.collect::<Vec<_>>()
 | 
									.collect::<Vec<_>>()
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -256,7 +261,7 @@ impl Parity for ParityClient {
 | 
				
			|||||||
		Ok(
 | 
							Ok(
 | 
				
			||||||
			txq.future_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
 | 
								txq.future_transactions(chain_info.best_block_number, chain_info.best_block_timestamp)
 | 
				
			||||||
				.into_iter()
 | 
									.into_iter()
 | 
				
			||||||
				.map(Into::into)
 | 
									.map(|tx| Transaction::from_pending(tx, chain_info.best_block_number, self.eip86_transition))
 | 
				
			||||||
				.collect::<Vec<_>>()
 | 
									.collect::<Vec<_>>()
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -69,6 +69,7 @@ pub struct ParityClient<C, M, S: ?Sized, U> where
 | 
				
			|||||||
	signer: Option<Arc<SignerService>>,
 | 
						signer: Option<Arc<SignerService>>,
 | 
				
			||||||
	dapps_interface: Option<String>,
 | 
						dapps_interface: Option<String>,
 | 
				
			||||||
	dapps_port: Option<u16>,
 | 
						dapps_port: Option<u16>,
 | 
				
			||||||
 | 
						eip86_transition: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C, M, S: ?Sized, U> ParityClient<C, M, S, U> where
 | 
					impl<C, M, S: ?Sized, U> ParityClient<C, M, S, U> where
 | 
				
			||||||
@ -103,6 +104,7 @@ impl<C, M, S: ?Sized, U> ParityClient<C, M, S, U> where
 | 
				
			|||||||
			signer: signer,
 | 
								signer: signer,
 | 
				
			||||||
			dapps_interface: dapps_interface,
 | 
								dapps_interface: dapps_interface,
 | 
				
			||||||
			dapps_port: dapps_port,
 | 
								dapps_port: dapps_port,
 | 
				
			||||||
 | 
								eip86_transition: client.eip86_transition(),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -288,11 +290,13 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn pending_transactions(&self) -> Result<Vec<Transaction>, Error> {
 | 
						fn pending_transactions(&self) -> Result<Vec<Transaction>, Error> {
 | 
				
			||||||
		Ok(take_weak!(self.miner).pending_transactions().into_iter().map(Into::into).collect::<Vec<_>>())
 | 
							let block_number = take_weak!(self.client).chain_info().best_block_number;
 | 
				
			||||||
 | 
							Ok(take_weak!(self.miner).pending_transactions().into_iter().map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)).collect::<Vec<_>>())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn future_transactions(&self) -> Result<Vec<Transaction>, Error> {
 | 
						fn future_transactions(&self) -> Result<Vec<Transaction>, Error> {
 | 
				
			||||||
		Ok(take_weak!(self.miner).future_transactions().into_iter().map(Into::into).collect::<Vec<_>>())
 | 
							let block_number = take_weak!(self.client).chain_info().best_block_number;
 | 
				
			||||||
 | 
							Ok(take_weak!(self.miner).future_transactions().into_iter().map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)).collect::<Vec<_>>())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>, Error> {
 | 
						fn pending_transactions_stats(&self) -> Result<BTreeMap<H256, TransactionStats>, Error> {
 | 
				
			||||||
@ -305,9 +309,10 @@ impl<C, M, S: ?Sized, U> Parity for ParityClient<C, M, S, U> where
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	fn local_transactions(&self) -> Result<BTreeMap<H256, LocalTransactionStatus>, Error> {
 | 
						fn local_transactions(&self) -> Result<BTreeMap<H256, LocalTransactionStatus>, Error> {
 | 
				
			||||||
		let transactions = take_weak!(self.miner).local_transactions();
 | 
							let transactions = take_weak!(self.miner).local_transactions();
 | 
				
			||||||
 | 
							let block_number = take_weak!(self.client).chain_info().best_block_number;
 | 
				
			||||||
		Ok(transactions
 | 
							Ok(transactions
 | 
				
			||||||
		   .into_iter()
 | 
							   .into_iter()
 | 
				
			||||||
		   .map(|(hash, status)| (hash.into(), status.into()))
 | 
							   .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status, block_number, self.eip86_transition)))
 | 
				
			||||||
		   .collect()
 | 
							   .collect()
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -39,9 +39,12 @@ pub struct ParitySetClient<C, M, U, F = fetch::Client> {
 | 
				
			|||||||
	updater: Weak<U>,
 | 
						updater: Weak<U>,
 | 
				
			||||||
	net: Weak<ManageNetwork>,
 | 
						net: Weak<ManageNetwork>,
 | 
				
			||||||
	fetch: F,
 | 
						fetch: F,
 | 
				
			||||||
 | 
						eip86_transition: u64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<C, M, U, F> ParitySetClient<C, M, U, F> {
 | 
					impl<C, M, U, F> ParitySetClient<C, M, U, F>
 | 
				
			||||||
 | 
						where C: MiningBlockChainClient + 'static,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
	/// Creates new `ParitySetClient` with given `Fetch`.
 | 
						/// Creates new `ParitySetClient` with given `Fetch`.
 | 
				
			||||||
	pub fn new(client: &Arc<C>, miner: &Arc<M>, updater: &Arc<U>, net: &Arc<ManageNetwork>, fetch: F) -> Self {
 | 
						pub fn new(client: &Arc<C>, miner: &Arc<M>, updater: &Arc<U>, net: &Arc<ManageNetwork>, fetch: F) -> Self {
 | 
				
			||||||
		ParitySetClient {
 | 
							ParitySetClient {
 | 
				
			||||||
@ -50,6 +53,7 @@ impl<C, M, U, F> ParitySetClient<C, M, U, F> {
 | 
				
			|||||||
			updater: Arc::downgrade(updater),
 | 
								updater: Arc::downgrade(updater),
 | 
				
			||||||
			net: Arc::downgrade(net),
 | 
								net: Arc::downgrade(net),
 | 
				
			||||||
			fetch: fetch,
 | 
								fetch: fetch,
 | 
				
			||||||
 | 
								eip86_transition: client.eip86_transition(),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -175,8 +179,9 @@ impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
 | 
				
			|||||||
	fn remove_transaction(&self, hash: H256) -> Result<Option<Transaction>, Error> {
 | 
						fn remove_transaction(&self, hash: H256) -> Result<Option<Transaction>, Error> {
 | 
				
			||||||
		let miner = take_weak!(self.miner);
 | 
							let miner = take_weak!(self.miner);
 | 
				
			||||||
		let client = take_weak!(self.client);
 | 
							let client = take_weak!(self.client);
 | 
				
			||||||
 | 
							let block_number = take_weak!(self.client).chain_info().best_block_number;
 | 
				
			||||||
		let hash = hash.into();
 | 
							let hash = hash.into();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Ok(miner.remove_pending_transaction(&*client, &hash).map(Into::into))
 | 
							Ok(miner.remove_pending_transaction(&*client, &hash).map(|t| Transaction::from_pending(t, block_number, self.eip86_transition)))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -227,7 +227,7 @@ fn rpc_parity_remove_transaction() {
 | 
				
			|||||||
	let hash = signed.hash();
 | 
						let hash = signed.hash();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	let request = r#"{"jsonrpc": "2.0", "method": "parity_removeTransaction", "params":[""#.to_owned() + &format!("0x{:?}", hash) + r#""], "id": 1}"#;
 | 
						let request = r#"{"jsonrpc": "2.0", "method": "parity_removeTransaction", "params":[""#.to_owned() + &format!("0x{:?}", hash) + r#""], "id": 1}"#;
 | 
				
			||||||
	let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0x0072c69d780cdfbfc02fed5c7d184151f9a166971d045e55e27695aaa5bcb55e","input":"0x","networkId":null,"nonce":"0x1","publicKey":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","r":"0x0","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a80808080","s":"0x0","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x0","value":"0x9184e72a"},"id":1}"#;
 | 
						let response = r#"{"jsonrpc":"2.0","result":{"blockHash":null,"blockNumber":null,"condition":null,"creates":null,"from":"0x0000000000000000000000000000000000000002","gas":"0x76c0","gasPrice":"0x9184e72a000","hash":"0xa2e0da8a8064e0b9f93e95a53c2db6d01280efb8ac72a708d25487e67dd0f8fc","input":"0x","networkId":null,"nonce":"0x1","publicKey":null,"r":"0x1","raw":"0xe9018609184e72a0008276c0940000000000000000000000000000000000000005849184e72a80800101","s":"0x1","standardV":"0x4","to":"0x0000000000000000000000000000000000000005","transactionIndex":null,"v":"0x0","value":"0x9184e72a"},"id":1}"#;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	miner.pending_transactions.lock().insert(hash, signed);
 | 
						miner.pending_transactions.lock().insert(hash, signed);
 | 
				
			||||||
	assert_eq!(io.handle_request_sync(&request), Some(response.to_owned()));
 | 
						assert_eq!(io.handle_request_sync(&request), Some(response.to_owned()));
 | 
				
			||||||
 | 
				
			|||||||
@ -304,7 +304,7 @@ fn should_add_sign_transaction_to_the_queue() {
 | 
				
			|||||||
		r#""input":"0x","# +
 | 
							r#""input":"0x","# +
 | 
				
			||||||
		&format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) +
 | 
							&format!("\"networkId\":{},", t.network_id().map_or("null".to_owned(), |n| format!("{}", n))) +
 | 
				
			||||||
		r#""nonce":"0x1","# +
 | 
							r#""nonce":"0x1","# +
 | 
				
			||||||
		&format!("\"publicKey\":\"0x{:?}\",", t.public_key()) +
 | 
							&format!("\"publicKey\":\"0x{:?}\",", t.public_key().unwrap()) +
 | 
				
			||||||
		&format!("\"r\":\"0x{}\",", U256::from(signature.r()).to_hex()) +
 | 
							&format!("\"r\":\"0x{}\",", U256::from(signature.r()).to_hex()) +
 | 
				
			||||||
		&format!("\"raw\":\"0x{}\",", rlp.to_hex()) +
 | 
							&format!("\"raw\":\"0x{}\",", rlp.to_hex()) +
 | 
				
			||||||
		&format!("\"s\":\"0x{}\",", U256::from(signature.s()).to_hex()) +
 | 
							&format!("\"s\":\"0x{}\",", U256::from(signature.s()).to_hex()) +
 | 
				
			||||||
 | 
				
			|||||||
@ -16,8 +16,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use serde::{Serialize, Serializer};
 | 
					use serde::{Serialize, Serializer};
 | 
				
			||||||
use serde::ser::SerializeStruct;
 | 
					use serde::ser::SerializeStruct;
 | 
				
			||||||
 | 
					use util::Hashable;
 | 
				
			||||||
use ethcore::miner;
 | 
					use ethcore::miner;
 | 
				
			||||||
use ethcore::contract_address;
 | 
					use ethcore::{contract_address, CreateContractAddress};
 | 
				
			||||||
use ethcore::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction};
 | 
					use ethcore::transaction::{LocalizedTransaction, Action, PendingTransaction, SignedTransaction};
 | 
				
			||||||
use v1::helpers::errors;
 | 
					use v1::helpers::errors;
 | 
				
			||||||
use v1::types::{Bytes, H160, H256, U256, H512, TransactionCondition};
 | 
					use v1::types::{Bytes, H160, H256, U256, H512, TransactionCondition};
 | 
				
			||||||
@ -158,9 +159,11 @@ pub struct RichRawTransaction {
 | 
				
			|||||||
	pub transaction: Transaction
 | 
						pub transaction: Transaction
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<SignedTransaction> for RichRawTransaction {
 | 
					impl From<SignedTransaction> for RichRawTransaction {
 | 
				
			||||||
	fn from(t: SignedTransaction) -> Self {
 | 
						fn from(t: SignedTransaction) -> Self {
 | 
				
			||||||
		let tx: Transaction = t.into();
 | 
							// TODO: change transition to 0 when EIP-86 is commonly used.
 | 
				
			||||||
 | 
							let tx: Transaction = Transaction::from_signed(t, 0, u64::max_value());
 | 
				
			||||||
		RichRawTransaction {
 | 
							RichRawTransaction {
 | 
				
			||||||
			raw: tx.raw.clone(),
 | 
								raw: tx.raw.clone(),
 | 
				
			||||||
			transaction: tx,
 | 
								transaction: tx,
 | 
				
			||||||
@ -168,9 +171,11 @@ impl From<SignedTransaction> for RichRawTransaction {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<LocalizedTransaction> for Transaction {
 | 
					impl Transaction {
 | 
				
			||||||
	fn from(mut t: LocalizedTransaction) -> Transaction {
 | 
						/// Convert `LocalizedTransaction` into RPC Transaction.
 | 
				
			||||||
 | 
						pub fn from_localized(mut t: LocalizedTransaction, eip86_transition: u64) -> Transaction {
 | 
				
			||||||
		let signature = t.signature();
 | 
							let signature = t.signature();
 | 
				
			||||||
 | 
							let scheme = if t.block_number >= eip86_transition { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce };
 | 
				
			||||||
		Transaction {
 | 
							Transaction {
 | 
				
			||||||
			hash: t.hash().into(),
 | 
								hash: t.hash().into(),
 | 
				
			||||||
			nonce: t.nonce.into(),
 | 
								nonce: t.nonce.into(),
 | 
				
			||||||
@ -187,7 +192,7 @@ impl From<LocalizedTransaction> for Transaction {
 | 
				
			|||||||
			gas: t.gas.into(),
 | 
								gas: t.gas.into(),
 | 
				
			||||||
			input: Bytes::new(t.data.clone()),
 | 
								input: Bytes::new(t.data.clone()),
 | 
				
			||||||
			creates: match t.action {
 | 
								creates: match t.action {
 | 
				
			||||||
				Action::Create => Some(contract_address(&t.sender(), &t.nonce).into()),
 | 
									Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data.sha3()).into()),
 | 
				
			||||||
				Action::Call(_) => None,
 | 
									Action::Call(_) => None,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			raw: ::rlp::encode(&t.signed).to_vec().into(),
 | 
								raw: ::rlp::encode(&t.signed).to_vec().into(),
 | 
				
			||||||
@ -200,11 +205,11 @@ impl From<LocalizedTransaction> for Transaction {
 | 
				
			|||||||
			condition: None,
 | 
								condition: None,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<SignedTransaction> for Transaction {
 | 
						/// Convert `SignedTransaction` into RPC Transaction.
 | 
				
			||||||
	fn from(t: SignedTransaction) -> Transaction {
 | 
						pub fn from_signed(t: SignedTransaction, block_number: u64, eip86_transition: u64) -> Transaction {
 | 
				
			||||||
		let signature = t.signature();
 | 
							let signature = t.signature();
 | 
				
			||||||
 | 
							let scheme = if block_number >= eip86_transition { CreateContractAddress::FromCodeHash } else { CreateContractAddress::FromSenderAndNonce };
 | 
				
			||||||
		Transaction {
 | 
							Transaction {
 | 
				
			||||||
			hash: t.hash().into(),
 | 
								hash: t.hash().into(),
 | 
				
			||||||
			nonce: t.nonce.into(),
 | 
								nonce: t.nonce.into(),
 | 
				
			||||||
@ -221,11 +226,11 @@ impl From<SignedTransaction> for Transaction {
 | 
				
			|||||||
			gas: t.gas.into(),
 | 
								gas: t.gas.into(),
 | 
				
			||||||
			input: Bytes::new(t.data.clone()),
 | 
								input: Bytes::new(t.data.clone()),
 | 
				
			||||||
			creates: match t.action {
 | 
								creates: match t.action {
 | 
				
			||||||
				Action::Create => Some(contract_address(&t.sender(), &t.nonce).into()),
 | 
									Action::Create => Some(contract_address(scheme, &t.sender(), &t.nonce, &t.data.sha3()).into()),
 | 
				
			||||||
				Action::Call(_) => None,
 | 
									Action::Call(_) => None,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			raw: ::rlp::encode(&t).to_vec().into(),
 | 
								raw: ::rlp::encode(&t).to_vec().into(),
 | 
				
			||||||
			public_key: Some(t.public_key().into()),
 | 
								public_key: t.public_key().map(Into::into),
 | 
				
			||||||
			network_id: t.network_id(),
 | 
								network_id: t.network_id(),
 | 
				
			||||||
			standard_v: t.standard_v().into(),
 | 
								standard_v: t.standard_v().into(),
 | 
				
			||||||
			v: t.original_v().into(),
 | 
								v: t.original_v().into(),
 | 
				
			||||||
@ -234,28 +239,28 @@ impl From<SignedTransaction> for Transaction {
 | 
				
			|||||||
			condition: None,
 | 
								condition: None,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<PendingTransaction> for Transaction {
 | 
						/// Convert `PendingTransaction` into RPC Transaction.
 | 
				
			||||||
	fn from(t: PendingTransaction) -> Transaction {
 | 
						pub fn from_pending(t: PendingTransaction, block_number: u64, eip86_transition: u64) -> Transaction {
 | 
				
			||||||
		let mut r = Transaction::from(t.transaction);
 | 
							let mut r = Transaction::from_signed(t.transaction, block_number, eip86_transition);
 | 
				
			||||||
		r.condition = t.condition.map(|b| b.into());
 | 
							r.condition = t.condition.map(|b| b.into());
 | 
				
			||||||
		r
 | 
							r
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl From<miner::LocalTransactionStatus> for LocalTransactionStatus {
 | 
					impl LocalTransactionStatus {
 | 
				
			||||||
	fn from(s: miner::LocalTransactionStatus) -> Self {
 | 
						/// Convert `LocalTransactionStatus` into RPC `LocalTransactionStatus`.
 | 
				
			||||||
 | 
						pub fn from(s: miner::LocalTransactionStatus, block_number: u64, eip86_transition: u64) -> Self {
 | 
				
			||||||
		use ethcore::miner::LocalTransactionStatus::*;
 | 
							use ethcore::miner::LocalTransactionStatus::*;
 | 
				
			||||||
		match s {
 | 
							match s {
 | 
				
			||||||
			Pending => LocalTransactionStatus::Pending,
 | 
								Pending => LocalTransactionStatus::Pending,
 | 
				
			||||||
			Future => LocalTransactionStatus::Future,
 | 
								Future => LocalTransactionStatus::Future,
 | 
				
			||||||
			Mined(tx) => LocalTransactionStatus::Mined(tx.into()),
 | 
								Mined(tx) => LocalTransactionStatus::Mined(Transaction::from_signed(tx, block_number, eip86_transition)),
 | 
				
			||||||
			Dropped(tx) => LocalTransactionStatus::Dropped(tx.into()),
 | 
								Dropped(tx) => LocalTransactionStatus::Dropped(Transaction::from_signed(tx, block_number, eip86_transition)),
 | 
				
			||||||
			Rejected(tx, err) => LocalTransactionStatus::Rejected(tx.into(), errors::transaction_message(err)),
 | 
								Rejected(tx, err) => LocalTransactionStatus::Rejected(Transaction::from_signed(tx, block_number, eip86_transition), errors::transaction_message(err)),
 | 
				
			||||||
			Replaced(tx, gas_price, hash) => LocalTransactionStatus::Replaced(tx.into(), gas_price.into(), hash.into()),
 | 
								Replaced(tx, gas_price, hash) => LocalTransactionStatus::Replaced(Transaction::from_signed(tx, block_number, eip86_transition), gas_price.into(), hash.into()),
 | 
				
			||||||
			Invalid(tx) => LocalTransactionStatus::Invalid(tx.into()),
 | 
								Invalid(tx) => LocalTransactionStatus::Invalid(Transaction::from_signed(tx, block_number, eip86_transition)),
 | 
				
			||||||
			Canceled(tx) => LocalTransactionStatus::Canceled(tx.into()),
 | 
								Canceled(tx) => LocalTransactionStatus::Canceled(Transaction::from_pending(tx, block_number, eip86_transition)),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@ impl IoHandler<ClientIoMessage> for TestIoHandler {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn new_tx(secret: &Secret, nonce: U256) -> PendingTransaction {
 | 
					fn new_tx(secret: &Secret, nonce: U256, network_id: u64) -> PendingTransaction {
 | 
				
			||||||
	let signed = Transaction {
 | 
						let signed = Transaction {
 | 
				
			||||||
		nonce: nonce.into(),
 | 
							nonce: nonce.into(),
 | 
				
			||||||
		gas_price: 0.into(),
 | 
							gas_price: 0.into(),
 | 
				
			||||||
@ -49,7 +49,7 @@ fn new_tx(secret: &Secret, nonce: U256) -> PendingTransaction {
 | 
				
			|||||||
		action: Action::Call(Address::default()),
 | 
							action: Action::Call(Address::default()),
 | 
				
			||||||
		value: 0.into(),
 | 
							value: 0.into(),
 | 
				
			||||||
		data: Vec::new(),
 | 
							data: Vec::new(),
 | 
				
			||||||
	}.sign(secret, None);
 | 
						}.sign(secret, Some(network_id));
 | 
				
			||||||
	PendingTransaction::new(signed, None)
 | 
						PendingTransaction::new(signed, None)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -61,6 +61,7 @@ fn authority_round() {
 | 
				
			|||||||
	ap.insert_account(s0.secret().clone(), "").unwrap();
 | 
						ap.insert_account(s0.secret().clone(), "").unwrap();
 | 
				
			||||||
	ap.insert_account(s1.secret().clone(), "").unwrap();
 | 
						ap.insert_account(s1.secret().clone(), "").unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let network_id = Spec::new_test_round().network_id();
 | 
				
			||||||
	let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_round, Some(ap));
 | 
						let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_round, Some(ap));
 | 
				
			||||||
	let io_handler0: Arc<IoHandler<ClientIoMessage>> = Arc::new(TestIoHandler { client: net.peer(0).chain.clone() });
 | 
						let io_handler0: Arc<IoHandler<ClientIoMessage>> = Arc::new(TestIoHandler { client: net.peer(0).chain.clone() });
 | 
				
			||||||
	let io_handler1: Arc<IoHandler<ClientIoMessage>> = Arc::new(TestIoHandler { client: net.peer(1).chain.clone() });
 | 
						let io_handler1: Arc<IoHandler<ClientIoMessage>> = Arc::new(TestIoHandler { client: net.peer(1).chain.clone() });
 | 
				
			||||||
@ -74,15 +75,15 @@ fn authority_round() {
 | 
				
			|||||||
	// exchange statuses
 | 
						// exchange statuses
 | 
				
			||||||
	net.sync();
 | 
						net.sync();
 | 
				
			||||||
	// Trigger block proposal
 | 
						// Trigger block proposal
 | 
				
			||||||
	net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 0.into())).unwrap();
 | 
						net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 0.into(), network_id)).unwrap();
 | 
				
			||||||
	net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 0.into())).unwrap();
 | 
						net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 0.into(), network_id)).unwrap();
 | 
				
			||||||
	// Sync a block
 | 
						// Sync a block
 | 
				
			||||||
	net.sync();
 | 
						net.sync();
 | 
				
			||||||
	assert_eq!(net.peer(0).chain.chain_info().best_block_number, 1);
 | 
						assert_eq!(net.peer(0).chain.chain_info().best_block_number, 1);
 | 
				
			||||||
	assert_eq!(net.peer(1).chain.chain_info().best_block_number, 1);
 | 
						assert_eq!(net.peer(1).chain.chain_info().best_block_number, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 1.into())).unwrap();
 | 
						net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 1.into(), network_id)).unwrap();
 | 
				
			||||||
	net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 1.into())).unwrap();
 | 
						net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 1.into(), network_id)).unwrap();
 | 
				
			||||||
	// Move to next proposer step.
 | 
						// Move to next proposer step.
 | 
				
			||||||
	net.peer(0).chain.engine().step();
 | 
						net.peer(0).chain.engine().step();
 | 
				
			||||||
	net.peer(1).chain.engine().step();
 | 
						net.peer(1).chain.engine().step();
 | 
				
			||||||
@ -91,8 +92,8 @@ fn authority_round() {
 | 
				
			|||||||
	assert_eq!(net.peer(1).chain.chain_info().best_block_number, 2);
 | 
						assert_eq!(net.peer(1).chain.chain_info().best_block_number, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Fork the network with equal height.
 | 
						// Fork the network with equal height.
 | 
				
			||||||
	net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 2.into())).unwrap();
 | 
						net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 2.into(), network_id)).unwrap();
 | 
				
			||||||
	net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 2.into())).unwrap();
 | 
						net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 2.into(), network_id)).unwrap();
 | 
				
			||||||
	// Let both nodes build one block.
 | 
						// Let both nodes build one block.
 | 
				
			||||||
	net.peer(0).chain.engine().step();
 | 
						net.peer(0).chain.engine().step();
 | 
				
			||||||
	let early_hash = net.peer(0).chain.chain_info().best_block_hash;
 | 
						let early_hash = net.peer(0).chain.chain_info().best_block_hash;
 | 
				
			||||||
@ -114,8 +115,8 @@ fn authority_round() {
 | 
				
			|||||||
	assert_eq!(ci1.best_block_hash, early_hash);
 | 
						assert_eq!(ci1.best_block_hash, early_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Selfish miner
 | 
						// Selfish miner
 | 
				
			||||||
	net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 3.into())).unwrap();
 | 
						net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 3.into(), network_id)).unwrap();
 | 
				
			||||||
	net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 3.into())).unwrap();
 | 
						net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 3.into(), network_id)).unwrap();
 | 
				
			||||||
	// Node 0 is an earlier primary.
 | 
						// Node 0 is an earlier primary.
 | 
				
			||||||
	net.peer(0).chain.engine().step();
 | 
						net.peer(0).chain.engine().step();
 | 
				
			||||||
	assert_eq!(net.peer(0).chain.chain_info().best_block_number, 4);
 | 
						assert_eq!(net.peer(0).chain.chain_info().best_block_number, 4);
 | 
				
			||||||
@ -126,7 +127,7 @@ fn authority_round() {
 | 
				
			|||||||
	// Node 1 makes 2 blocks, but is a later primary on the first one.
 | 
						// Node 1 makes 2 blocks, but is a later primary on the first one.
 | 
				
			||||||
	net.peer(1).chain.engine().step();
 | 
						net.peer(1).chain.engine().step();
 | 
				
			||||||
	net.peer(1).chain.engine().step();
 | 
						net.peer(1).chain.engine().step();
 | 
				
			||||||
	net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 4.into())).unwrap();
 | 
						net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 4.into(), network_id)).unwrap();
 | 
				
			||||||
	net.peer(1).chain.engine().step();
 | 
						net.peer(1).chain.engine().step();
 | 
				
			||||||
	net.peer(1).chain.engine().step();
 | 
						net.peer(1).chain.engine().step();
 | 
				
			||||||
	assert_eq!(net.peer(1).chain.chain_info().best_block_number, 5);
 | 
						assert_eq!(net.peer(1).chain.chain_info().best_block_number, 5);
 | 
				
			||||||
@ -147,6 +148,7 @@ fn tendermint() {
 | 
				
			|||||||
	ap.insert_account(s0.secret().clone(), "").unwrap();
 | 
						ap.insert_account(s0.secret().clone(), "").unwrap();
 | 
				
			||||||
	ap.insert_account(s1.secret().clone(), "").unwrap();
 | 
						ap.insert_account(s1.secret().clone(), "").unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let network_id = Spec::new_test_tendermint().network_id();
 | 
				
			||||||
	let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_tendermint, Some(ap));
 | 
						let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_tendermint, Some(ap));
 | 
				
			||||||
	let io_handler0: Arc<IoHandler<ClientIoMessage>> = Arc::new(TestIoHandler { client: net.peer(0).chain.clone() });
 | 
						let io_handler0: Arc<IoHandler<ClientIoMessage>> = Arc::new(TestIoHandler { client: net.peer(0).chain.clone() });
 | 
				
			||||||
	let io_handler1: Arc<IoHandler<ClientIoMessage>> = Arc::new(TestIoHandler { client: net.peer(1).chain.clone() });
 | 
						let io_handler1: Arc<IoHandler<ClientIoMessage>> = Arc::new(TestIoHandler { client: net.peer(1).chain.clone() });
 | 
				
			||||||
@ -162,7 +164,7 @@ fn tendermint() {
 | 
				
			|||||||
	// Exhange statuses
 | 
						// Exhange statuses
 | 
				
			||||||
	net.sync();
 | 
						net.sync();
 | 
				
			||||||
	// Propose
 | 
						// Propose
 | 
				
			||||||
	net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 0.into())).unwrap();
 | 
						net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 0.into(), network_id)).unwrap();
 | 
				
			||||||
	net.sync();
 | 
						net.sync();
 | 
				
			||||||
	// Propose timeout, synchronous for now
 | 
						// Propose timeout, synchronous for now
 | 
				
			||||||
	net.peer(0).chain.engine().step();
 | 
						net.peer(0).chain.engine().step();
 | 
				
			||||||
@ -173,7 +175,7 @@ fn tendermint() {
 | 
				
			|||||||
	assert_eq!(net.peer(0).chain.chain_info().best_block_number, 1);
 | 
						assert_eq!(net.peer(0).chain.chain_info().best_block_number, 1);
 | 
				
			||||||
	assert_eq!(net.peer(1).chain.chain_info().best_block_number, 1);
 | 
						assert_eq!(net.peer(1).chain.chain_info().best_block_number, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 0.into())).unwrap();
 | 
						net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 0.into(), network_id)).unwrap();
 | 
				
			||||||
	// Commit timeout
 | 
						// Commit timeout
 | 
				
			||||||
	net.peer(0).chain.engine().step();
 | 
						net.peer(0).chain.engine().step();
 | 
				
			||||||
	net.peer(1).chain.engine().step();
 | 
						net.peer(1).chain.engine().step();
 | 
				
			||||||
@ -187,8 +189,8 @@ fn tendermint() {
 | 
				
			|||||||
	assert_eq!(net.peer(0).chain.chain_info().best_block_number, 2);
 | 
						assert_eq!(net.peer(0).chain.chain_info().best_block_number, 2);
 | 
				
			||||||
	assert_eq!(net.peer(1).chain.chain_info().best_block_number, 2);
 | 
						assert_eq!(net.peer(1).chain.chain_info().best_block_number, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 1.into())).unwrap();
 | 
						net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 1.into(), network_id)).unwrap();
 | 
				
			||||||
	net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 1.into())).unwrap();
 | 
						net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 1.into(), network_id)).unwrap();
 | 
				
			||||||
	// Peers get disconnected.
 | 
						// Peers get disconnected.
 | 
				
			||||||
	// Commit
 | 
						// Commit
 | 
				
			||||||
	net.peer(0).chain.engine().step();
 | 
						net.peer(0).chain.engine().step();
 | 
				
			||||||
@ -196,8 +198,8 @@ fn tendermint() {
 | 
				
			|||||||
	// Propose
 | 
						// Propose
 | 
				
			||||||
	net.peer(0).chain.engine().step();
 | 
						net.peer(0).chain.engine().step();
 | 
				
			||||||
	net.peer(1).chain.engine().step();
 | 
						net.peer(1).chain.engine().step();
 | 
				
			||||||
	net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 2.into())).unwrap();
 | 
						net.peer(0).chain.miner().import_own_transaction(&*net.peer(0).chain, new_tx(s0.secret(), 2.into(), network_id)).unwrap();
 | 
				
			||||||
	net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 2.into())).unwrap();
 | 
						net.peer(1).chain.miner().import_own_transaction(&*net.peer(1).chain, new_tx(s1.secret(), 2.into(), network_id)).unwrap();
 | 
				
			||||||
	// Send different prevotes
 | 
						// Send different prevotes
 | 
				
			||||||
	net.sync();
 | 
						net.sync();
 | 
				
			||||||
	// Prevote timeout
 | 
						// Prevote timeout
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user