diff --git a/ethcore/light/src/client/mod.rs b/ethcore/light/src/client/mod.rs index 8205ae2ab3b..623d82ac183 100644 --- a/ethcore/light/src/client/mod.rs +++ b/ethcore/light/src/client/mod.rs @@ -619,6 +619,12 @@ impl ::ethcore::client::ChainInfo for Client { } } +impl ::ethcore::client::Nonce for Client { + fn nonce(&self, _address: ðereum_types::H160, _blockid: ethcore::client::BlockId) -> std::option::Option { + panic!("we never call this function on a light client, so this is unreachable; qed") + } +} + impl ::ethcore::client::EngineClient for Client { fn update_sealing(&self) { } fn submit_seal(&self, _block_hash: H256, _seal: Vec>) { } diff --git a/ethcore/res/contracts/validator_report.json b/ethcore/res/contracts/validator_report.json index 093f4bebdff..98c5d23e080 100644 --- a/ethcore/res/contracts/validator_report.json +++ b/ethcore/res/contracts/validator_report.json @@ -1,4 +1,5 @@ [ - {"constant":false,"inputs":[{"name":"validator","type":"address"},{"name":"blockNumber","type":"uint256"},{"name":"proof","type":"bytes"}],"name":"reportMalicious","outputs":[],"payable":false,"type":"function"}, - {"constant":false,"inputs":[{"name":"validator","type":"address"},{"name":"blockNumber","type":"uint256"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"} + { "constant": false, "inputs": [ { "name": "validator", "type": "address" }, { "name": "blockNum", "type": "uint256" }, { "name": "", "type": "bytes" } ], "name": "reportMalicious", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, + {"constant":false,"inputs":[{"name":"validator","type":"address"},{"name":"blockNumber","type":"uint256"}],"name":"reportBenign","outputs":[],"payable":false,"type":"function"}, + { "constant": true, "inputs": [ { "name": "validator", "type": "address" }, { "name": "blockNum", "type": "uint256" } ], "name": "maliceReportedForBlock", "outputs": [ { "name": "", "type": "address[]" } ], "payable": false, "stateMutability": "view", "type": "function" } ] diff --git a/ethcore/res/contracts/validator_set_aura.json b/ethcore/res/contracts/validator_set_aura.json index a42eee20a6c..43ec223de64 100644 --- a/ethcore/res/contracts/validator_set_aura.json +++ b/ethcore/res/contracts/validator_set_aura.json @@ -61,5 +61,47 @@ ], "name": "InitiateChange", "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "name": "_miningAddress", + "type": "address" + } + ], + "name": "isValidatorBanned", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_maliciousMiningAddress", + "type": "address" + }, + { + "name": "_blockNumber", + "type": "uint256" + } + ], + "name": "maliceReportedForBlock", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" } ] diff --git a/ethcore/res/contracts/validator_set_aura.json.txt b/ethcore/res/contracts/validator_set_aura.json.txt new file mode 100644 index 00000000000..f912cf10e39 --- /dev/null +++ b/ethcore/res/contracts/validator_set_aura.json.txt @@ -0,0 +1,7 @@ +getValidators +initiateChange +emitInitiateChangeCallable +emitInitiateChange +maliceReportedForBlock +finalizeChange +InitiateChange diff --git a/ethcore/res/validator_contract.json b/ethcore/res/validator_contract.json index 59aede3353b..86b6ae8b7cb 100644 --- a/ethcore/res/validator_contract.json +++ b/ethcore/res/validator_contract.json @@ -37,7 +37,7 @@ "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", - "constructor": "60806040526040805190810160405280737d577a597b2742b498cb5cf0c26cdcd726d39e6e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020017382a978b3f5962a5b0957d9ee9eef472ee55b42f173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525060009060026100a9929190610159565b503480156100b657600080fd5b5060008090505b60008054905081101561015357806001600080848154811015156100dd57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806001019150506100bd565b50610226565b8280548282559060005260206000209081019282156101d2579160200282015b828111156101d15782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190610179565b5b5090506101df91906101e3565b5090565b61022391905b8082111561021f57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016101e9565b5090565b90565b610618806102356000396000f3fe608060405260043610610088576000357c01000000000000000000000000000000000000000000000000000000009004806335aa2e441461008d5780633d3b54581461010857806368ffa02d14610137578063752862111461019257806393b4e25e146101a9578063b7ab4db5146101c0578063d69f13bb1461022c578063d8f2e0bf14610287575b600080fd5b34801561009957600080fd5b506100c6600480360360208110156100b057600080fd5b81019080803590602001909291905050506102de565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561011457600080fd5b5061011d61031c565b604051808215151515815260200191505060405180910390f35b34801561014357600080fd5b506101906004803603604081101561015a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610325565b005b34801561019e57600080fd5b506101a761049e565b005b3480156101b557600080fd5b506101be6104a0565b005b3480156101cc57600080fd5b506101d56104a2565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156102185780820151818401526020810190506101fd565b505050509050019250505060405180910390f35b34801561023857600080fd5b506102856004803603604081101561024f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610530565b005b34801561029357600080fd5b5061029c610575565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000818154811015156102ed57fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006001905090565b600060016000805490500381548110151561033c57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020548154811015156103b557fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009055600060016000805490500381548110151561045757fe5b9060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000805480919060019003610499919061059b565b505050565b565b565b6060600080548060200260200160405190810160405280929190818152602001828054801561052657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116104dc575b5050505050905090565b81600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b8154818355818111156105c2578183600052602060002091820191016105c191906105c7565b5b505050565b6105e991905b808211156105e55760008160009055506001016105cd565b5090565b9056fea165627a7a723058209ddf89214270830c0be6b514c27eb8eedf1bb989eb9b46867d20749faef133490029" + "constructor": "60806040526040805190810160405280737d577a597b2742b498cb5cf0c26cdcd726d39e6e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020017382a978b3f5962a5b0957d9ee9eef472ee55b42f173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525060009060026100a9929190610159565b503480156100b657600080fd5b5060008090505b60008054905081101561015357806001600080848154811015156100dd57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806001019150506100bd565b50610226565b8280548282559060005260206000209081019282156101d2579160200282015b828111156101d15782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190610179565b5b5090506101df91906101e3565b5090565b61022391905b8082111561021f57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016101e9565b5090565b90565b610de3806102356000396000f3fe6080604052600436106100a9576000357c01000000000000000000000000000000000000000000000000000000009004806335aa2e44146100ae5780633d3b54581461012957806375286211146101585780639300c9261461016f57806393b4e25e14610234578063a92252ae1461024b578063b56b366b146102b4578063b7ab4db514610364578063c476dd40146103d0578063d69f13bb14610480578063d8f2e0bf146104db575b600080fd5b3480156100ba57600080fd5b506100e7600480360360208110156100d157600080fd5b8101908080359060200190929190505050610532565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561013557600080fd5b5061013e610570565b604051808215151515815260200191505060405180910390f35b34801561016457600080fd5b5061016d61057a565b005b34801561017b57600080fd5b506102326004803603602081101561019257600080fd5b81019080803590602001906401000000008111156101af57600080fd5b8201836020820111156101c157600080fd5b803590602001918460208302840111640100000000831117156101e357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050919291929050505061057c565b005b34801561024057600080fd5b50610249610647565b005b34801561025757600080fd5b5061029a6004803603602081101561026e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106fa565b604051808215151515815260200191505060405180910390f35b3480156102c057600080fd5b5061030d600480360360408110156102d757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506107ab565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610350578082015181840152602081019050610335565b505050509050019250505060405180910390f35b34801561037057600080fd5b506103796108a7565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156103bc5780820151818401526020810190506103a1565b505050509050019250505060405180910390f35b3480156103dc57600080fd5b5061047e600480360360608110156103f357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561043a57600080fd5b82018360208201111561044c57600080fd5b8035906020019184600183028401116401000000008311171561046e57600080fd5b9091929391929390505050610935565b005b34801561048c57600080fd5b506104d9600480360360408110156104a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c2e565b005b3480156104e757600080fd5b506104f0610c73565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008181548110151561054157fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000804311905090565b565b8060009080519060200190610592929190610c99565b5060014303407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c8960006040518080602001828103825283818154815260200191508054801561063657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116105ec575b50509250505060405180910390a250565b60014303407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c896000604051808060200182810382528381815481526020019150805480156106ea57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116106a0575b50509250505060405180910390a2565b60008173ffffffffffffffffffffffffffffffffffffffff166000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110151561076157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6060600260008484604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405160208183030381529060405280519060200120815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561089a57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610850575b5050505050905092915050565b6060600080548060200260200160405190810160405280929190818152602001828054801561092b57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116108e1575b5050505050905090565b600260008585604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040528051906020012081526020019081526020016000203390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508373ffffffffffffffffffffffffffffffffffffffff166000600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054815481101515610a6b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610c28576000600160008054905003815481101515610ac957fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054815481101515610b4257fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090556000600160008054905003815481101515610be457fe5b9060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000805480919060019003610c269190610d23565b505b50505050565b81600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b828054828255906000526020600020908101928215610d12579160200282015b82811115610d115782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190610cb9565b5b509050610d1f9190610d4f565b5090565b815481835581811115610d4a57818360005260206000209182019101610d499190610d92565b5b505050565b610d8f91905b80821115610d8b57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101610d55565b5090565b90565b610db491905b80821115610db0576000816000905550600101610d98565b5090565b9056fea165627a7a7230582034f862f72c47fac1ba2693934a579f7a71d54a90c302cfe8660c741c821b55c00029" }, "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } diff --git a/ethcore/res/validator_contract.sol b/ethcore/res/validator_contract.sol index e206567922f..e2acde7b847 100644 --- a/ethcore/res/validator_contract.sol +++ b/ethcore/res/validator_contract.sol @@ -12,7 +12,7 @@ contract TestList { ]; mapping(address => uint) indices; - // Should remain 0 because `reportBenign` is no longer used. + mapping(bytes32 => address[]) maliceReported; address public disliked; event InitiateChange(bytes32 indexed parentHash, address[] newSet); @@ -28,27 +28,48 @@ contract TestList { return validators; } + function setValidators(address[] memory _validators) public { + validators = _validators; + emit InitiateChange(blockhash(block.number - 1), validators); + } + // Removes a validator from the list. - function reportMalicious(address validator) public { - validators[indices[validator]] = validators[validators.length-1]; - delete indices[validator]; - delete validators[validators.length-1]; - validators.length--; + function reportMalicious(address validator, uint256 blockNum, bytes calldata) external { + maliceReported[keccak256(abi.encode(validator, blockNum))].push(msg.sender); + if (validators[indices[validator]] == validator) { + validators[indices[validator]] = validators[validators.length-1]; + delete indices[validator]; + delete validators[validators.length-1]; + validators.length--; + } + } + + // Returns the list of all validators that reported the given validator as malicious for the given block. + function maliceReportedForBlock(address validator, uint256 blockNum) public view returns(address[] memory) { + return maliceReported[keccak256(abi.encode(validator, blockNum))]; } // Benign validator behaviour report. Kept here for regression testing. - function reportBenign(address validator) public { + function reportBenign(address validator, uint256) public { disliked = validator; } // Checks if `emitInitiateChange` can be called. - function emitInitiateChangeCallable() pure public returns (bool) { - return true; + function emitInitiateChangeCallable() view public returns (bool) { + return block.number > 0; } - // Emits an `InitiateChange` event in production code. Does nothing in the test. - function emitInitiateChange() pure public {} + // Checks if a validator has been removed. + function isValidatorBanned(address validator) view public returns (bool) { + return validators[indices[validator]] != validator; + } + + // Emits an `InitiateChange` event. + function emitInitiateChange() public { + emit InitiateChange(blockhash(block.number - 1), validators); + } // Applies a validator set change in production code. Does nothing in the test. function finalizeChange() pure public {} } + diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 34ca84197d1..e45edf3fad0 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -2187,10 +2187,10 @@ impl BlockChainClient for Client { Ok(SignedTransaction::new(transaction.with_signature(signature, chain_id))?) } - fn transact(&self, action: Action, data: Bytes, gas: Option, gas_price: Option) + fn transact(&self, action: Action, data: Bytes, gas: Option, gas_price: Option, nonce: Option) -> Result<(), transaction::Error> { - let signed = self.create_transaction(action, data, gas, gas_price, None)?; + let signed = self.create_transaction(action, data, gas, gas_price, nonce)?; self.importer.miner.import_own_transaction(self, signed.into()) } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index 23695a62e58..77fd3d77606 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -896,8 +896,14 @@ impl BlockChainClient for TestBlockChainClient { Ok(SignedTransaction::new(transaction.with_signature(sig, chain_id)).unwrap()) } - fn transact(&self, action: Action, data: Bytes, gas: Option, gas_price: Option) - -> Result<(), transaction::Error> + fn transact( + &self, + action: Action, + data: Bytes, + gas: Option, + gas_price: Option, + _nonce: Option, + ) -> Result<(), transaction::Error> { let signed = self.create_transaction(action, data, gas, gas_price, None)?; self.miner.import_own_transaction(self, signed.into()) diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index b5916fa9835..db4b11accb3 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -376,11 +376,12 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra fn pruning_info(&self) -> PruningInfo; /// Schedule state-altering transaction to be executed on the next pending block. - fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> { - self.transact(Action::Call(address), data, None, None) + fn transact_contract(&self, address: Address, data: Bytes, nonce: Option) -> Result<(), transaction::Error> { + self.transact(Action::Call(address), data, None, None, nonce) } - /// Returns a signed transaction. If gas limit, gas price, or nonce are not specified, the defaults are used. + /// Returns a signed transaction. If gas limit, gas price, or nonce are not + /// specified, the defaults are used. fn create_transaction( &self, action: Action, @@ -390,10 +391,11 @@ pub trait BlockChainClient : Sync + Send + AccountData + BlockChain + CallContra nonce: Option ) -> Result; - /// Schedule state-altering transaction to be executed on the next pending block with the given gas parameters. + /// Schedule state-altering transaction to be executed on the next pending + /// block with the given gas and nonce parameters. /// /// If they are `None`, sensible values are selected automatically. - fn transact(&self, action: Action, data: Bytes, gas: Option, gas_price: Option) + fn transact(&self, action: Action, data: Bytes, gas: Option, gas_price: Option, nonce: Option) -> Result<(), transaction::Error>; /// Get the address of the registry itself. @@ -441,7 +443,7 @@ pub trait BroadcastProposalBlock { pub trait SealedBlockImporter: ImportSealedBlock + BroadcastProposalBlock {} /// Client facilities used by internally sealing Engines. -pub trait EngineClient: Sync + Send + ChainInfo { +pub trait EngineClient: Sync + Send + ChainInfo + Nonce { /// Make a new block and seal it. fn update_sealing(&self); diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index 6cd8b47bf48..ea15afc0747 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -959,6 +959,7 @@ impl Engine for AuthorityRound { header_expected_seal_fields(header, self.empty_steps_transition) } + #[cfg(test)] fn step(&self) { self.step.inner.increment(); self.step.can_propose.store(true, AtomicOrdering::SeqCst); @@ -1289,7 +1290,12 @@ impl Engine for AuthorityRound { }, }; - block_reward::apply_block_rewards(&rewards, block, &self.machine) + block_reward::apply_block_rewards(&rewards, block, &self.machine)?; + + match self.signer.read().as_ref() { + Some(signer) => self.validators.on_close_block(block.header(), &signer.address()), + None => Ok(()), // We are not a validator, so we can't report malicious validators. + } } /// Make calls to the randomness and validator set contracts. diff --git a/ethcore/src/engines/validator_set/contract.rs b/ethcore/src/engines/validator_set/contract.rs index 9defe203f96..b9ff3fb6f05 100644 --- a/ethcore/src/engines/validator_set/contract.rs +++ b/ethcore/src/engines/validator_set/contract.rs @@ -24,8 +24,9 @@ use ethereum_types::{H256, Address}; use machine::{AuxiliaryData, Call, EthereumMachine}; use parking_lot::RwLock; use types::BlockNumber; +use types::ids::BlockId; use types::header::Header; -use types::transaction::Action; +use types::transaction::{self, Action}; use client::EngineClient; @@ -38,7 +39,7 @@ use_contract!(validator_report, "res/contracts/validator_report.json"); pub struct ValidatorContract { contract_address: Address, validators: ValidatorSafeContract, - client: RwLock>>, // TODO [keorn]: remove + client: RwLock>>, // TODO [keorn]: remove } impl ValidatorContract { @@ -52,20 +53,28 @@ impl ValidatorContract { } impl ValidatorContract { - fn transact(&self, data: Bytes) -> Result<(), String> { - let client = self.client.read().as_ref() - .and_then(Weak::upgrade) - .ok_or_else(|| "No client!")?; - - match client.as_full_client() { - Some(c) => { - c.transact(Action::Call(self.contract_address), data, None, Some(0.into())) - .map_err(|e| format!("Transaction import error: {}", e))?; - Ok(()) - }, - None => Err("No full client!".into()), + fn transact(&self, data: Bytes) -> Result<(), ::error::Error> { + let client = self.client.read().as_ref().and_then(Weak::upgrade).ok_or("No client!")?; + let full_client = client.as_full_client().ok_or("No full client!")?; + match full_client.transact(Action::Call(self.contract_address), data, None, Some(0.into()), None) { + Ok(()) | Err(transaction::Error::AlreadyImported) => Ok(()), + Err(e) => Err(e)?, } } + + fn do_report_malicious(&self, address: &Address, block: BlockNumber, proof: Bytes) -> Result<(), ::error::Error> { + let client = self.client.read().as_ref().and_then(Weak::upgrade).ok_or("No client!")?; + let latest = client.block_header(BlockId::Latest).ok_or("No latest block!")?; + if !self.contains(&latest.parent_hash(), address) { + warn!(target: "engine", "Not reporting {} on block {}: Not a validator", address, block); + return Ok(()); + } + let data = validator_report::functions::report_malicious::encode_input(*address, block, proof); + self.validators.queue_report((*address, block, data.clone())); + self.transact(data)?; + warn!(target: "engine", "Reported malicious validator {} at block {}", address, block); + Ok(()) + } } impl ValidatorSet for ValidatorContract { @@ -84,6 +93,10 @@ impl ValidatorSet for ValidatorContract { self.validators.on_epoch_begin(first, header, call) } + fn on_close_block(&self, header: &Header, address: &Address) -> Result<(), ::error::Error> { + self.validators.on_close_block(header, address) + } + fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result, String> { self.validators.genesis_epoch_data(header, call) } @@ -118,17 +131,15 @@ impl ValidatorSet for ValidatorContract { } fn report_malicious(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber, proof: Bytes) { - let data = validator_report::functions::report_malicious::encode_input(*address, block, proof); - match self.transact(data) { - Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address), - Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), + if let Err(s) = self.do_report_malicious(address, block, proof) { + warn!(target: "engine", "Validator {} could not be reported ({}) on block {}", address, s, block); } } fn report_benign(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber) { let data = validator_report::functions::report_benign::encode_input(*address, block); match self.transact(data) { - Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address), + Ok(()) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address), Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), } } @@ -144,6 +155,7 @@ mod tests { use std::sync::Arc; use rustc_hex::FromHex; use hash::keccak; + use ethabi::FunctionOutputDecoder; use ethereum_types::{H520, Address}; use bytes::ToPretty; use rlp::encode; @@ -199,21 +211,16 @@ mod tests { header.set_author(v1); header.set_number(2); header.set_parent_hash(client.chain_info().best_block_hash); - - // Regression test: Check that the removed method `reportBenign` was not called. `reportBenign` was previously - // called when the designated proposer would release a block from the future (bad clock). - let verify_block_basic = client.engine().verify_block_basic(&header); - assert!(verify_block_basic.is_err()); + // `reportBenign` when the designated proposer releases block from the future (bad clock). + assert!(client.engine().verify_block_basic(&header).is_err()); // Seal a block. client.engine().step(); assert_eq!(client.chain_info().best_block_number, 1); - // "d8f2e0bf" accesses the field `disliked`. + // Check if the unresponsive validator is `disliked`. "d8f2e0bf" accesses the field `disliked`. assert_eq!( - client.call_contract(BlockId::Latest, validator_contract, - "d8f2e0bf".from_hex().unwrap()).unwrap().to_hex(), - "0000000000000000000000000000000000000000000000000000000000000000" + client.call_contract(BlockId::Latest, validator_contract, "d8f2e0bf".from_hex().unwrap()).unwrap().to_hex(), + "0000000000000000000000007d577a597b2742b498cb5cf0c26cdcd726d39e6e" ); - // Simulate a misbehaving validator by handling a double proposal. let header = client.best_block_header(); assert!(client.engine().verify_block_family(&header, &header).is_err()); @@ -221,9 +228,12 @@ mod tests { client.engine().step(); client.engine().step(); assert_eq!(client.chain_info().best_block_number, 2); + let (data, decoder) = super::validator_report::functions::malice_reported_for_block::call(v1, 1); + let reported_enc = client.call_contract(BlockId::Latest, validator_contract, data).expect("call failed"); + assert_ne!(Vec::
::new(), decoder.decode(&reported_enc).expect("decoding failed")); // Check if misbehaving validator was removed. - client.transact_contract(Default::default(), Default::default()).unwrap(); + client.transact_contract(Default::default(), Default::default(), Default::default()).unwrap(); client.engine().step(); client.engine().step(); assert_eq!(client.chain_info().best_block_number, 2); diff --git a/ethcore/src/engines/validator_set/mod.rs b/ethcore/src/engines/validator_set/mod.rs index cf1adfbbdb9..bef39592601 100644 --- a/ethcore/src/engines/validator_set/mod.rs +++ b/ethcore/src/engines/validator_set/mod.rs @@ -92,6 +92,11 @@ pub trait ValidatorSet: Send + Sync + 'static { Ok(()) } + /// Called on the close of every block. + fn on_close_block(&self, _header: &Header, _address: &Address) -> Result<(), ::error::Error> { + Ok(()) + } + /// Called for each new block this node is creating. If this block is /// the first block of an epoch, this is called *after* on_epoch_begin(), /// but with the same parameters. diff --git a/ethcore/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index 213b504d24c..bb250359947 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -91,6 +91,9 @@ impl ValidatorSet for Multi { self.map_children(header, &mut |set: &dyn ValidatorSet, first| set.on_prepare_block(first, header, call)) } + fn on_close_block(&self, header: &Header, address: &Address) -> Result<(), ::error::Error> { + self.map_children(header, &mut |set: &dyn ValidatorSet, _first| set.on_close_block(header, address)) + } fn on_epoch_begin(&self, _first: bool, header: &Header, call: &mut SystemCall) -> Result<(), ::error::Error> { self.map_children(header, &mut |set: &dyn ValidatorSet, first| set.on_epoch_begin(first, header, call)) @@ -192,7 +195,7 @@ mod tests { // Wrong signer for the first block. let signer = Box::new((tap.clone(), v1, "".into())); client.miner().set_author(miner::Author::Sealer(signer)); - client.transact_contract(Default::default(), Default::default()).unwrap(); + client.transact_contract(Default::default(), Default::default(), Default::default()).unwrap(); ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 0); // Right signer for the first block. @@ -201,7 +204,7 @@ mod tests { ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); // This time v0 is wrong. - client.transact_contract(Default::default(), Default::default()).unwrap(); + client.transact_contract(Default::default(), Default::default(), Default::default()).unwrap(); ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 1); let signer = Box::new((tap.clone(), v1, "".into())); @@ -209,7 +212,7 @@ mod tests { ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 2); // v1 is still good. - client.transact_contract(Default::default(), Default::default()).unwrap(); + client.transact_contract(Default::default(), Default::default(), Default::default()).unwrap(); ::client::EngineClient::update_sealing(&*client); assert_eq!(client.chain_info().best_block_number, 3); diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index c4cc142a245..e3888474f5f 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -16,6 +16,7 @@ /// Validator set maintained in a contract, updated using `getValidators` method. +use std::collections::VecDeque; use std::sync::{Weak, Arc}; use bytes::Bytes; @@ -24,21 +25,29 @@ use ethereum_types::{H256, U256, Address, Bloom}; use hash::keccak; use kvdb::DBValue; use memory_cache::MemoryLruCache; -use parking_lot::RwLock; +use parking_lot::{RwLock, Mutex}; use rlp::{Rlp, RlpStream}; +use types::BlockNumber; use types::header::Header; use types::ids::BlockId; use types::log_entry::LogEntry; use types::receipt::Receipt; +use types::transaction::{self, Action}; use unexpected::Mismatch; use client::EngineClient; +use error::{BlockError, Error, ErrorKind}; use machine::{AuxiliaryData, Call, EthereumMachine, AuxiliaryRequest}; use super::{SystemCall, ValidatorSet}; use super::simple_list::SimpleList; use_contract!(validator_set, "res/contracts/validator_set_aura.json"); +/// The maximum number of reports to keep queued. +const MAX_QUEUED_REPORTS: usize = 10; +/// The maximum number of returned malice reports to resend. +const MAX_RETURNED_REPORTS: usize = 10; + const MEMOIZE_CAPACITY: usize = 500; // TODO: ethabi should be able to generate this. @@ -76,6 +85,9 @@ pub struct ValidatorSafeContract { contract_address: Address, validators: RwLock>, client: RwLock>>, // TODO [keorn]: remove + queued_reports: Mutex)>>, + /// The block number where we resent the queued reports last time. + resent_reports_in_block: Mutex, } // first proof is just a state proof call of `getValidators` at header's state. @@ -93,7 +105,7 @@ fn encode_first_proof(header: &Header, state_items: &[Vec]) -> Bytes { fn check_first_proof(machine: &EthereumMachine, contract_address: Address, old_header: Header, state_items: &[DBValue]) -> Result, String> { - use types::transaction::{Action, Transaction}; + use types::transaction::Transaction; // TODO: match client contract_call_tx more cleanly without duplication. const PROVIDED_GAS: u64 = 50_000_000; @@ -142,13 +154,13 @@ fn check_first_proof(machine: &EthereumMachine, contract_address: Address, old_h } } -fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec), ::error::Error> { +fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec), Error> { let header = rlp.val_at(0)?; let state_items = rlp.at(1)?.iter().map(|x| { let mut val = DBValue::new(); val.append_slice(x.data()?); Ok(val) - }).collect::>()?; + }).collect::>()?; Ok((header, state_items)) } @@ -162,7 +174,7 @@ fn encode_proof(header: &Header, receipts: &[Receipt]) -> Bytes { stream.drain() } -fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec), ::error::Error> { +fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec), Error> { Ok((rlp.val_at(0)?, rlp.list_at(1)?)) } @@ -191,11 +203,29 @@ fn prove_initial(contract_address: Address, header: &Header, caller: &Call) -> R } impl ValidatorSafeContract { + fn transact(&self, data: Bytes, nonce: U256) -> Result<(), Error> { + let client = self.client.read().as_ref().and_then(Weak::upgrade).ok_or("No client!")?; + let full_client = client.as_full_client().ok_or("No full client!")?; + + match full_client.transact(Action::Call(self.contract_address), data, None, Some(0.into()), Some(nonce)) { + Ok(()) | Err(transaction::Error::AlreadyImported) => Ok(()), + Err(e) => Err(e)?, + } + } + + pub(crate) fn queue_report(&self, data: (Address, BlockNumber, Vec)) { + self.queued_reports + .lock() + .push_back(data) + } + pub fn new(contract_address: Address) -> Self { ValidatorSafeContract { contract_address, validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)), client: RwLock::new(None), + queued_reports: Mutex::new(VecDeque::new()), + resent_reports_in_block: Mutex::new(0), } } @@ -274,6 +304,55 @@ impl ValidatorSafeContract { Some(matched_event) => Some(SimpleList::new(matched_event.new_set)) } } + + fn filter_report_queue(&self, our_address: &Address, latest_block: BlockNumber) -> Result<(), Error>{ + let client = self.client.read().as_ref().and_then(Weak::upgrade).ok_or("No client!")?; + let client = client.as_full_client().ok_or("No full client!")?; + + self.queued_reports.lock().retain(|&(malicious_validator_address, block, ref _data)| { + trace!(target: "engine", "Checking if report can be removed from cache"); + if block > latest_block { + return false; // Report cannot be used, as it is for a block that isn’t in the current chain + } + if latest_block > 100 && latest_block - 100 > block { + return false; // Report is too old and cannot be used + } + // Check if the validator is already banned... + let (data, decoder) = validator_set::functions::is_validator_banned::call(malicious_validator_address); + match client.call_contract(BlockId::Latest, self.contract_address, data) + .and_then(|result| decoder.decode(&result[..]).map_err(|e| e.to_string())) + { + Ok(true) => { + trace!(target: "engine", "Successfully removed report from report cache"); + return false; + } + Ok(false) => (), + Err(err) => { + warn!(target: "engine", "Failed to query ban status {:?}, dropping pending report.", err); + return false; + } + } + // ...or if our report has already been processed. + let (data, decoder) = validator_set::functions::malice_reported_for_block::call( + malicious_validator_address, block + ); + match client.call_contract(BlockId::Latest, self.contract_address, data) + .and_then(|result| decoder.decode(&result[..]).map_err(|e| e.to_string())) + { + Ok(ref reporters) if reporters.contains(&our_address) => { + trace!(target: "engine", "Successfully removed report from report cache"); + false + } + Ok(_) => true, + Err(err) => { + warn!(target: "engine", "Failed to query malice reports {:?}, dropping pending report.", err); + false + } + } + }); + + Ok(()) + } } impl ValidatorSet for ValidatorSafeContract { @@ -292,23 +371,70 @@ impl ValidatorSet for ValidatorSafeContract { } fn on_prepare_block(&self, _first: bool, header: &Header, caller: &mut SystemCall) - -> Result, ::error::Error> + -> Result, Error> { + self.filter_report_queue(header.author(), header.number())?; let (data, decoder) = validator_set::functions::emit_initiate_change_callable::call(); - if !caller(self.contract_address, data) + let mut returned_transactions = if !caller(self.contract_address, data) .and_then(|x| decoder.decode(&x) .map_err(|x| format!("chain spec bug: could not decode: {:?}", x))) .map_err(::engines::EngineError::FailedSystemCall)? { trace!(target: "engine", "New block #{} issued ― no need to call emitInitiateChange()", header.number()); - return Ok(Vec::new()); + Vec::new() + } else { + trace!(target: "engine", "New block issued #{} ― calling emitInitiateChange()", header.number()); + let (data, _decoder) = validator_set::functions::emit_initiate_change::call(); + vec![(self.contract_address, data)] + }; + let queued_reports = self.queued_reports.lock(); + for (_address, _block, data) in queued_reports.iter().take(MAX_RETURNED_REPORTS) { + returned_transactions.push((self.contract_address, data.clone())) } + Ok(returned_transactions) + } + + fn on_close_block(&self, header: &Header, our_address: &Address) -> Result<(), Error> { + let client = self.client.read().as_ref().and_then(Weak::upgrade).ok_or("No client!")?; + let client = client.as_full_client().ok_or("No full client!")?; + + let latest_block = header.number().max(client.block_number(BlockId::Latest).unwrap_or(0)) + 1; + self.filter_report_queue(our_address, latest_block)?; - trace!(target: "engine", "New block issued #{} ― calling emitInitiateChange()", header.number()); - let (data, _decoder) = validator_set::functions::emit_initiate_change::call(); - Ok(vec![(self.contract_address, data)]) + let mut queue = self.queued_reports.lock(); + + if queue.len() > MAX_QUEUED_REPORTS { + warn!(target: "engine", "Removing report from report cache, even though it has not been finalized"); + queue.truncate(MAX_QUEUED_REPORTS); + } + + let mut resent_reports_in_block = self.resent_reports_in_block.lock(); + // Skip at least one block after sending malicious reports last time. + if header.number() > *resent_reports_in_block + 1 { + *resent_reports_in_block = header.number(); + let mut nonce = client.latest_nonce(our_address); + for (address, block, data) in &*queue { + debug!(target: "engine", "Retrying to report validator {} for misbehavior on block {} with nonce {}.", + address, block, nonce); + while match self.transact(data.clone(), nonce) { + Ok(()) => false, + Err(Error(ErrorKind::Transaction(transaction::Error::Old), _)) => true, + Err(err) => { + warn!(target: "engine", "Cannot report validator {} for misbehavior on block {}: {}", + address, block, err); + false + } + } { + warn!(target: "engine", "Nonce {} already used. Incrementing.", nonce); + nonce += U256::from(1); + } + nonce += U256::from(1); + } + } + + Ok(()) } - fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> { + fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), Error> { let data = validator_set::functions::finalize_change::encode_input(); caller(self.contract_address, data) .map(drop) @@ -362,8 +488,8 @@ impl ValidatorSet for ValidatorSafeContract { } } - fn epoch_set(&self, first: bool, machine: &EthereumMachine, _number: ::types::BlockNumber, proof: &[u8]) - -> Result<(SimpleList, Option), ::error::Error> + fn epoch_set(&self, first: bool, machine: &EthereumMachine, _number: BlockNumber, proof: &[u8]) + -> Result<(SimpleList, Option), Error> { let rlp = Rlp::new(proof); @@ -389,7 +515,7 @@ impl ValidatorSet for ValidatorSafeContract { receipts.iter().map(::rlp::encode) ); if found_root != *old_header.receipts_root() { - return Err(::error::BlockError::InvalidReceiptsRoot( + return Err(BlockError::InvalidReceiptsRoot( Mismatch { expected: *old_header.receipts_root(), found: found_root } ).into()); } diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index 0d7ae26e936..4ea29282346 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -52,10 +52,16 @@ lazy_static! { static ref RICH_SECRET: Secret = secret!("1"); } -/// Contract code used here: https://gist.github.com/anonymous/2a43783647e0f0dfcc359bd6fd81d6d9 -/// Account with secrets keccak("1") is initially the validator. +/// Contract code used here: `ethcore/res/validator_contract.sol`, but with: +/// ```ignore +/// address[] public validators = [ +/// 0x7d577a597B2742b498Cb5Cf0C26cDCD726d39E6e +/// ]; +/// ``` +/// I.e. only the account with secrets keccak("1") is initially the validator. /// Transitions to the contract at block 2, initially same validator set. -/// Create a new Spec with AuthorityRound which uses a contract at address 5 to determine the current validators using `getValidators`. +/// Create a new Spec with AuthorityRound which uses a contract at address 5 to determine the current validators using +/// `getValidators`. /// `test_validator_set::ValidatorSet` provides a native wrapper for the ABi. fn spec_fixed_to_contract() -> Spec { let data = include_bytes!("test_validator_contract.json"); diff --git a/ethcore/src/snapshot/tests/test_validator_contract.json b/ethcore/src/snapshot/tests/test_validator_contract.json index b0aeb8785c9..2607fd353c3 100644 --- a/ethcore/src/snapshot/tests/test_validator_contract.json +++ b/ethcore/src/snapshot/tests/test_validator_contract.json @@ -43,11 +43,11 @@ "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, "0000000000000000000000000000000000000005": { "balance": "1", - "constructor": "6060604052602060405190810160405280737d577a597b2742b498cb5cf0c26cdcd726d39e6e73ffffffffffffffffffffffffffffffffffffffff16815250600090600161004e92919061005c565b50341561005757fe5b610129565b8280548282559060005260206000209081019282156100d5579160200282015b828111156100d45782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061007c565b5b5090506100e291906100e6565b5090565b61012691905b8082111561012257600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016100ec565b5090565b90565b61056f806101386000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806375286211146100675780639300c92614610079578063b7ab4db5146100d0578063c476dd4014610145578063d69f13bb146101c7575bfe5b341561006f57fe5b610077610206565b005b341561008157fe5b6100ce600480803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610275565b005b34156100d857fe5b6100e061031f565b6040518080602001828103825283818151815260200191508051906020019060200280838360008314610132575b8051825260208311156101325760208201915060208101905060208303925061010e565b5050509050019250505060405180910390f35b341561014d57fe5b6101c5600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506103b4565b005b34156101cf57fe5b610204600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103ba565b005b73fffffffffffffffffffffffffffffffffffffffe3373ffffffffffffffffffffffffffffffffffffffff1614151561023f5760006000fd5b600060018054905014151561027257600160009080546102609291906103bf565b5060006001816102709190610411565b505b5b565b806001908051906020019061028b92919061043d565b506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89826040518080602001828103825283818151815260200191508051906020019060200280838360008314610309575b805182526020831115610309576020820191506020810190506020830392506102e5565b5050509050019250505060405180910390a25b50565b6103276104c7565b60008054806020026020016040519081016040528092919081815260200182805480156103a957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161035f575b505050505090505b90565b5b505050565b5b5050565b8280548282559060005260206000209081019282156104005760005260206000209182015b828111156103ff5782548255916001019190600101906103e4565b5b50905061040d91906104db565b5090565b81548183558181151161043857818360005260206000209182019101610437919061051e565b5b505050565b8280548282559060005260206000209081019282156104b6579160200282015b828111156104b55782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061045d565b5b5090506104c391906104db565b5090565b602060405190810160405280600081525090565b61051b91905b8082111561051757600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016104e1565b5090565b90565b61054091905b8082111561053c576000816000905550600101610524565b5090565b905600a165627a7a7230582041ce7e5c820bc89b1a330a3233c4f3013e77433ecba368fa234adf758d87fe1d0029" + "constructor": "6080604052602060405190810160405280737d577a597b2742b498cb5cf0c26cdcd726d39e6e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152506000906001610064929190610114565b5034801561007157600080fd5b5060008090505b60008054905081101561010e578060016000808481548110151561009857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508080600101915050610078565b506101e1565b82805482825590600052602060002090810192821561018d579160200282015b8281111561018c5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190610134565b5b50905061019a919061019e565b5090565b6101de91905b808211156101da57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016101a4565b5090565b90565b610de3806101f06000396000f3fe6080604052600436106100a9576000357c01000000000000000000000000000000000000000000000000000000009004806335aa2e44146100ae5780633d3b54581461012957806375286211146101585780639300c9261461016f57806393b4e25e14610234578063a92252ae1461024b578063b56b366b146102b4578063b7ab4db514610364578063c476dd40146103d0578063d69f13bb14610480578063d8f2e0bf146104db575b600080fd5b3480156100ba57600080fd5b506100e7600480360360208110156100d157600080fd5b8101908080359060200190929190505050610532565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561013557600080fd5b5061013e610570565b604051808215151515815260200191505060405180910390f35b34801561016457600080fd5b5061016d61057a565b005b34801561017b57600080fd5b506102326004803603602081101561019257600080fd5b81019080803590602001906401000000008111156101af57600080fd5b8201836020820111156101c157600080fd5b803590602001918460208302840111640100000000831117156101e357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050919291929050505061057c565b005b34801561024057600080fd5b50610249610647565b005b34801561025757600080fd5b5061029a6004803603602081101561026e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106fa565b604051808215151515815260200191505060405180910390f35b3480156102c057600080fd5b5061030d600480360360408110156102d757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506107ab565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610350578082015181840152602081019050610335565b505050509050019250505060405180910390f35b34801561037057600080fd5b506103796108a7565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156103bc5780820151818401526020810190506103a1565b505050509050019250505060405180910390f35b3480156103dc57600080fd5b5061047e600480360360608110156103f357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561043a57600080fd5b82018360208201111561044c57600080fd5b8035906020019184600183028401116401000000008311171561046e57600080fd5b9091929391929390505050610935565b005b34801561048c57600080fd5b506104d9600480360360408110156104a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c2e565b005b3480156104e757600080fd5b506104f0610c73565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008181548110151561054157fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000804311905090565b565b8060009080519060200190610592929190610c99565b5060014303407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c8960006040518080602001828103825283818154815260200191508054801561063657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116105ec575b50509250505060405180910390a250565b60014303407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c896000604051808060200182810382528381815481526020019150805480156106ea57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116106a0575b50509250505060405180910390a2565b60008173ffffffffffffffffffffffffffffffffffffffff166000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110151561076157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6060600260008484604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405160208183030381529060405280519060200120815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561089a57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610850575b5050505050905092915050565b6060600080548060200260200160405190810160405280929190818152602001828054801561092b57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116108e1575b5050505050905090565b600260008585604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040528051906020012081526020019081526020016000203390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508373ffffffffffffffffffffffffffffffffffffffff166000600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054815481101515610a6b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610c28576000600160008054905003815481101515610ac957fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054815481101515610b4257fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090556000600160008054905003815481101515610be457fe5b9060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000805480919060019003610c269190610d23565b505b50505050565b81600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b828054828255906000526020600020908101928215610d12579160200282015b82811115610d115782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190610cb9565b5b509050610d1f9190610d4f565b5090565b815481835581811115610d4a57818360005260206000209182019101610d499190610d92565b5b505050565b610d8f91905b80821115610d8b57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101610d55565b5090565b90565b610db491905b80821115610db0576000816000905550600101610d98565b5090565b9056fea165627a7a72305820552bf4a0b6e428be32af0e3e7f636489f8732daf59baf34f515e9e0089a0cb6b0029" }, "0000000000000000000000000000000000000006": { "balance": "1", - "constructor": "6060604052602060405190810160405280737d577a597b2742b498cb5cf0c26cdcd726d39e6e73ffffffffffffffffffffffffffffffffffffffff16815250600090600161004e92919061005c565b50341561005757fe5b610129565b8280548282559060005260206000209081019282156100d5579160200282015b828111156100d45782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061007c565b5b5090506100e291906100e6565b5090565b61012691905b8082111561012257600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016100ec565b5090565b90565b61056f806101386000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806375286211146100675780639300c92614610079578063b7ab4db5146100d0578063c476dd4014610145578063d69f13bb146101c7575bfe5b341561006f57fe5b610077610206565b005b341561008157fe5b6100ce600480803590602001908201803590602001908080602002602001604051908101604052809392919081815260200183836020028082843782019150505050505091905050610275565b005b34156100d857fe5b6100e061031f565b6040518080602001828103825283818151815260200191508051906020019060200280838360008314610132575b8051825260208311156101325760208201915060208101905060208303925061010e565b5050509050019250505060405180910390f35b341561014d57fe5b6101c5600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506103b4565b005b34156101cf57fe5b610204600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919080359060200190919050506103ba565b005b73fffffffffffffffffffffffffffffffffffffffe3373ffffffffffffffffffffffffffffffffffffffff1614151561023f5760006000fd5b600060018054905014151561027257600160009080546102609291906103bf565b5060006001816102709190610411565b505b5b565b806001908051906020019061028b92919061043d565b506001430340600019167f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c89826040518080602001828103825283818151815260200191508051906020019060200280838360008314610309575b805182526020831115610309576020820191506020810190506020830392506102e5565b5050509050019250505060405180910390a25b50565b6103276104c7565b60008054806020026020016040519081016040528092919081815260200182805480156103a957602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001906001019080831161035f575b505050505090505b90565b5b505050565b5b5050565b8280548282559060005260206000209081019282156104005760005260206000209182015b828111156103ff5782548255916001019190600101906103e4565b5b50905061040d91906104db565b5090565b81548183558181151161043857818360005260206000209182019101610437919061051e565b5b505050565b8280548282559060005260206000209081019282156104b6579160200282015b828111156104b55782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509160200191906001019061045d565b5b5090506104c391906104db565b5090565b602060405190810160405280600081525090565b61051b91905b8082111561051757600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016104e1565b5090565b90565b61054091905b8082111561053c576000816000905550600101610524565b5090565b905600a165627a7a7230582041ce7e5c820bc89b1a330a3233c4f3013e77433ecba368fa234adf758d87fe1d0029" + "constructor": "6080604052602060405190810160405280737d577a597b2742b498cb5cf0c26cdcd726d39e6e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152506000906001610064929190610114565b5034801561007157600080fd5b5060008090505b60008054905081101561010e578060016000808481548110151561009857fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508080600101915050610078565b506101e1565b82805482825590600052602060002090810192821561018d579160200282015b8281111561018c5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190610134565b5b50905061019a919061019e565b5090565b6101de91905b808211156101da57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff0219169055506001016101a4565b5090565b90565b610de3806101f06000396000f3fe6080604052600436106100a9576000357c01000000000000000000000000000000000000000000000000000000009004806335aa2e44146100ae5780633d3b54581461012957806375286211146101585780639300c9261461016f57806393b4e25e14610234578063a92252ae1461024b578063b56b366b146102b4578063b7ab4db514610364578063c476dd40146103d0578063d69f13bb14610480578063d8f2e0bf146104db575b600080fd5b3480156100ba57600080fd5b506100e7600480360360208110156100d157600080fd5b8101908080359060200190929190505050610532565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561013557600080fd5b5061013e610570565b604051808215151515815260200191505060405180910390f35b34801561016457600080fd5b5061016d61057a565b005b34801561017b57600080fd5b506102326004803603602081101561019257600080fd5b81019080803590602001906401000000008111156101af57600080fd5b8201836020820111156101c157600080fd5b803590602001918460208302840111640100000000831117156101e357600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f82011690508083019250505050505050919291929050505061057c565b005b34801561024057600080fd5b50610249610647565b005b34801561025757600080fd5b5061029a6004803603602081101561026e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506106fa565b604051808215151515815260200191505060405180910390f35b3480156102c057600080fd5b5061030d600480360360408110156102d757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506107ab565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610350578082015181840152602081019050610335565b505050509050019250505060405180910390f35b34801561037057600080fd5b506103796108a7565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156103bc5780820151818401526020810190506103a1565b505050509050019250505060405180910390f35b3480156103dc57600080fd5b5061047e600480360360608110156103f357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019064010000000081111561043a57600080fd5b82018360208201111561044c57600080fd5b8035906020019184600183028401116401000000008311171561046e57600080fd5b9091929391929390505050610935565b005b34801561048c57600080fd5b506104d9600480360360408110156104a357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610c2e565b005b3480156104e757600080fd5b506104f0610c73565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60008181548110151561054157fe5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000804311905090565b565b8060009080519060200190610592929190610c99565b5060014303407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c8960006040518080602001828103825283818154815260200191508054801561063657602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116105ec575b50509250505060405180910390a250565b60014303407f55252fa6eee4741b4e24a74a70e9c11fd2c2281df8d6ea13126ff845f7825c896000604051808060200182810382528381815481526020019150805480156106ea57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116106a0575b50509250505060405180910390a2565b60008173ffffffffffffffffffffffffffffffffffffffff166000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205481548110151561076157fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6060600260008484604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405160208183030381529060405280519060200120815260200190815260200160002080548060200260200160405190810160405280929190818152602001828054801561089a57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610850575b5050505050905092915050565b6060600080548060200260200160405190810160405280929190818152602001828054801561092b57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116108e1575b5050505050905090565b600260008585604051602001808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001925050506040516020818303038152906040528051906020012081526020019081526020016000203390806001815401808255809150509060018203906000526020600020016000909192909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550508373ffffffffffffffffffffffffffffffffffffffff166000600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054815481101515610a6b57fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415610c28576000600160008054905003815481101515610ac957fe5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166000600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054815481101515610b4257fe5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600090556000600160008054905003815481101515610be457fe5b9060005260206000200160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000805480919060019003610c269190610d23565b505b50505050565b81600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b828054828255906000526020600020908101928215610d12579160200282015b82811115610d115782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190610cb9565b5b509050610d1f9190610d4f565b5090565b815481835581811115610d4a57818360005260206000209182019101610d499190610d92565b5b505050565b610d8f91905b80821115610d8b57600081816101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905550600101610d55565b5090565b90565b610db491905b80821115610db0576000816000905550600101610d98565b5090565b9056fea165627a7a72305820552bf4a0b6e428be32af0e3e7f636489f8732daf59baf34f515e9e0089a0cb6b0029" }, "0x7d577a597b2742b498cb5cf0c26cdcd726d39e6e": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }, "0x82a978b3f5962a5b0957d9ee9eef472ee55b42f1": { "balance": "1606938044258990275541962092341162602522202993782792835301376" } diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 4bd46b2bb63..4813fbc1040 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -847,8 +847,6 @@ impl Spec { /// constructor. pub fn genesis_epoch_data(&self) -> Result, String> { use types::transaction::{Action, Transaction}; - use journaldb; - use kvdb_memorydb; let genesis = self.genesis_header(); diff --git a/ethcore/types/src/transaction/error.rs b/ethcore/types/src/transaction/error.rs index ab10636643f..60da33eaf62 100644 --- a/ethcore/types/src/transaction/error.rs +++ b/ethcore/types/src/transaction/error.rs @@ -116,7 +116,7 @@ impl fmt::Display for Error { CodeBanned => "Contract code is temporarily banned.".into(), InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(), InvalidSignature(ref err) => format!("Transaction has invalid signature: {}.", err), - NotAllowed => "Sender does not have permissions to execute this type of transction".into(), + NotAllowed => "Sender does not have permissions to execute this type of transaction".into(), TooBig => "Transaction too big".into(), InvalidRlp(ref err) => format!("Transaction has invalid RLP structure: {}.", err), }; diff --git a/ethcore/types/src/views/view_rlp.rs b/ethcore/types/src/views/view_rlp.rs index a6c789de989..9e668845e1d 100644 --- a/ethcore/types/src/views/view_rlp.rs +++ b/ethcore/types/src/views/view_rlp.rs @@ -127,6 +127,7 @@ impl<'a, 'view> Iterator for ViewRlpIterator<'a, 'view> { } } +/// Create a `ViewRlp` #[macro_export] macro_rules! view { ($view: ident, $bytes: expr) => { diff --git a/scripts/get-abi b/scripts/get-abi new file mode 100755 index 00000000000..16894e2f680 --- /dev/null +++ b/scripts/get-abi @@ -0,0 +1,35 @@ +#!/usr/bin/python3 -- +""" +Get the ABI of a contract JSON file (specified in ``sys.argv[1]``) and write it +to ``sys.argv[2]``. Both ``sys.argv[1]`` and ``sys.argv[2]`` must end in +.json. Additionally, a file named ``sys.argv[2] + '.txt'`` must exist. It +must have one line for each symbol in the ABI that will be placed in the output. + +The input file must be encoded in UTF-8, and the output file will be encoded in +UTF-8. +""" + +__version__ = '0.0.1' +__all__ = ['main'] +import re +_re = re.compile(r'\A[A-Za-z_][A-Za-z0-9_]*\n\Z') +def main(input_file, output_file, used_file): + import os, json + _type, _dict, _open, _set = type, dict, open, set + with _open(used_file, 'r', encoding='UTF-8') as used_stream: + used_functions = _set(i.strip() for i in used_stream if _re.match(i)) + with _open(input_file, 'r', encoding='UTF-8') as input_stream, \ + _open(output_file, 'w', encoding='UTF-8') as output_stream: + my_list = [i for i in json.load(input_stream)['abi'] + if _type(i) is _dict and i.get('name') in used_functions] + json.dump(my_list, output_stream, sort_keys=True, indent = '\t') +if __name__ == '__main__': + import sys, json + if len(sys.argv) != 3: + print('must have 2 arguments, not {}'.format(len(sys.argv) - 1), + file=sys.stderr) + sys.exit(1) + try: + main(sys.argv[1], sys.argv[2], sys.argv[2] + '.txt') + except (OSError, UnicodeError, json.decoder.JSONDecodeError) as e: + print('Failed to generate ABI file: {}'.format(e), file=sys.stderr)