diff --git a/ethcore/native_contracts/build.rs b/ethcore/native_contracts/build.rs index 97953505702..e7985b3880b 100644 --- a/ethcore/native_contracts/build.rs +++ b/ethcore/native_contracts/build.rs @@ -29,7 +29,6 @@ const SECRETSTORE_ACL_STORAGE_ABI: &'static str = include_str!("res/secretstore_ const VALIDATOR_SET_ABI: &'static str = include_str!("res/validator_set.json"); const VALIDATOR_REPORT_ABI: &'static str = include_str!("res/validator_report.json"); const PEER_SET_ABI: &'static str = include_str!("res/peer_set.json"); -const TX_ACL_ABI: &'static str = include_str!("res/tx_acl.json"); const TEST_VALIDATOR_SET_ABI: &'static str = include_str!("res/test_validator_set.json"); @@ -56,7 +55,6 @@ fn main() { build_file("ValidatorSet", VALIDATOR_SET_ABI, "validator_set.rs"); build_file("ValidatorReport", VALIDATOR_REPORT_ABI, "validator_report.rs"); build_file("PeerSet", PEER_SET_ABI, "peer_set.rs"); - build_file("TransactAcl", TX_ACL_ABI, "tx_acl.rs"); build_test_contracts(); } diff --git a/ethcore/native_contracts/generator/src/lib.rs b/ethcore/native_contracts/generator/src/lib.rs index 8de7555d23d..996ee496926 100644 --- a/ethcore/native_contracts/generator/src/lib.rs +++ b/ethcore/native_contracts/generator/src/lib.rs @@ -302,8 +302,7 @@ fn detokenize(name: &str, output_type: ParamType) -> String { } ParamType::Uint(width) => { let read_uint = match width { - 8 => "u[31] as u8".into(), - 16 | 32 | 64 => format!("BigEndian::read_u{}(&u[{}..])", width, 32 - (width / 8)), + 8 | 16 | 32 | 64 => format!("bigint::prelude::U256(u).low_u64() as u{}", width), _ => format!("bigint::prelude::U{}::from(&u[..])", width), }; diff --git a/ethcore/native_contracts/res/tx_acl.json b/ethcore/native_contracts/res/tx_acl.json deleted file mode 100644 index cff9956de9c..00000000000 --- a/ethcore/native_contracts/res/tx_acl.json +++ /dev/null @@ -1 +0,0 @@ -[{"constant":false,"inputs":[{"name":"sender","type":"address"}],"name":"allowedTxTypes","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"nonpayable","type":"function"}] diff --git a/ethcore/native_contracts/src/lib.rs b/ethcore/native_contracts/src/lib.rs index c37a135041e..733dea80e6a 100644 --- a/ethcore/native_contracts/src/lib.rs +++ b/ethcore/native_contracts/src/lib.rs @@ -31,7 +31,6 @@ mod secretstore_acl_storage; mod validator_set; mod validator_report; mod peer_set; -mod tx_acl; pub mod test_contracts; @@ -43,4 +42,3 @@ pub use self::secretstore_acl_storage::SecretStoreAclStorage; pub use self::validator_set::ValidatorSet; pub use self::validator_report::ValidatorReport; pub use self::peer_set::PeerSet; -pub use self::tx_acl::TransactAcl; diff --git a/ethcore/native_contracts/src/tx_acl.rs b/ethcore/native_contracts/src/tx_acl.rs deleted file mode 100644 index 1ab4c8e5deb..00000000000 --- a/ethcore/native_contracts/src/tx_acl.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -#![allow(unused_mut, unused_variables, unused_imports)] - -//! Transact permissions contract. - -include!(concat!(env!("OUT_DIR"), "/tx_acl.rs")); diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 8948faa25f9..1b2e96c00f4 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -1448,10 +1448,6 @@ impl BlockChainClient for Client { self.state_at(id).and_then(|s| s.code(address).ok()).map(|c| c.map(|c| (&*c).clone())) } - fn code_hash(&self, address: &Address, id: BlockId) -> Option { - self.state_at(id).and_then(|s| s.code_hash(address).ok()) - } - fn balance(&self, address: &Address, id: BlockId) -> Option { self.state_at(id).and_then(|s| s.balance(address).ok()) } diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index aabd744f968..64dd7957034 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -456,13 +456,6 @@ impl BlockChainClient for TestBlockChainClient { } } - fn code_hash(&self, address: &Address, id: BlockId) -> Option { - match id { - BlockId::Latest | BlockId::Pending => self.code.read().get(address).map(|c| keccak(&c)), - _ => None, - } - } - fn balance(&self, address: &Address, id: BlockId) -> Option { match id { BlockId::Latest | BlockId::Pending => Some(self.balances.read().get(address).cloned().unwrap_or_else(U256::zero)), diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index 4a1f8a0c5e7..09eefb22b63 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -98,9 +98,6 @@ pub trait BlockChainClient : Sync + Send { .expect("code will return Some if given BlockId::Latest; qed") } - /// Get address code hash at given block's state. - fn code_hash(&self, address: &Address, id: BlockId) -> Option; - /// Get address balance at the given block's state. /// /// May not return None if given BlockId::Latest. diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 8b0554e5adf..ae27a0940d1 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -83,8 +83,6 @@ pub enum TransactionError { CodeBanned, /// Invalid chain ID given. InvalidChainId, - /// Not enough permissions given by permission contract. - NotAllowed, } impl fmt::Display for TransactionError { @@ -109,7 +107,6 @@ impl fmt::Display for TransactionError { RecipientBanned => "Recipient is temporarily banned.".into(), CodeBanned => "Contract code is temporarily banned.".into(), InvalidChainId => "Transaction of this chain ID is not allowed on this chain.".into(), - NotAllowed => "Sender does not have permissions to execute this type of transction".into(), }; f.write_fmt(format_args!("Transaction error ({})", msg)) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index b11700e09f7..0b3cab6ef16 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -17,7 +17,7 @@ use std::path::Path; use std::cmp; use std::collections::{BTreeMap, HashMap}; -use std::sync::{Arc, Weak}; +use std::sync::Arc; use hash::{KECCAK_EMPTY_LIST_RLP}; use ethash::{quick_get_difficulty, slow_get_seedhash, EthashManager}; use bigint::prelude::U256; @@ -32,15 +32,13 @@ use trace::{Tracer, ExecutiveTracer, RewardType}; use header::{Header, BlockNumber}; use state::CleanupMode; use spec::CommonParams; -use transaction::{UnverifiedTransaction, SignedTransaction}; +use transaction::UnverifiedTransaction; use engines::{self, Engine}; use evm::Schedule; use ethjson; use rlp::{self, UntrustedRlp}; use vm::LastHashes; use semantic_version::SemanticVersion; -use tx_filter::{TransactionFilter}; -use client::{Client, BlockChainClient}; /// Parity tries to round block.gas_limit to multiple of this constant pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); @@ -146,7 +144,6 @@ pub struct Ethash { ethash_params: EthashParams, builtins: BTreeMap, pow: EthashManager, - tx_filter: Option, } impl Ethash { @@ -158,7 +155,6 @@ impl Ethash { builtins: BTreeMap, ) -> Arc { Arc::new(Ethash { - tx_filter: TransactionFilter::from_params(¶ms), params, ethash_params, builtins, @@ -444,14 +440,6 @@ impl Engine for Arc { Ok(()) } - fn verify_transaction(&self, t: UnverifiedTransaction, header: &Header) -> Result { - let signed = SignedTransaction::new(t)?; - if !self.tx_filter.as_ref().map_or(true, |filter| filter.transaction_allowed(header.parent_hash(), &signed)) { - return Err(From::from(TransactionError::NotAllowed)); - } - Ok(signed) - } - fn epoch_verifier<'a>(&self, _header: &Header, _proof: &'a [u8]) -> engines::ConstructedVerifier<'a> { engines::ConstructedVerifier::Trusted(Box::new(self.clone())) } @@ -459,13 +447,6 @@ impl Engine for Arc { fn snapshot_components(&self) -> Option> { Some(Box::new(::snapshot::PowSnapshot::new(SNAPSHOT_BLOCKS, MAX_SNAPSHOT_BLOCKS))) } - - fn register_client(&self, client: Weak) { - if let Some(ref filter) = self.tx_filter { - filter.register_client(client as Weak); - } - } - } // Try to round gas_limit a bit so that: diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 2f2329d6473..3828875439e 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -173,7 +173,6 @@ mod executive; mod externalities; mod blockchain; mod factory; -mod tx_filter; #[cfg(test)] mod tests; diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 202daba13f7..bd53700da50 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -106,8 +106,6 @@ pub struct CommonParams { pub registrar: Address, /// Node permission managing contract address. pub node_permission_contract: Option
, - /// Transaction permission managing contract address. - pub transaction_permission_contract: Option
, } impl CommonParams { @@ -180,7 +178,6 @@ impl From for CommonParams { block_reward: p.block_reward.map_or_else(U256::zero, Into::into), registrar: p.registrar.map_or_else(Address::new, Into::into), node_permission_contract: p.node_permission_contract.map(Into::into), - transaction_permission_contract: p.transaction_permission_contract.map(Into::into), } } } diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs deleted file mode 100644 index 0ba98660826..00000000000 --- a/ethcore/src/tx_filter.rs +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -//! Smart contract based transaction filter. - -use std::sync::Weak; -use std::collections::HashMap; -use std::collections::hash_map::Entry; -use native_contracts::TransactAcl as Contract; -use client::{BlockChainClient, BlockId, ChainNotify}; -use util::{Address, Bytes}; -use bigint::hash::H256; -use parking_lot::{Mutex, RwLock}; -use futures::{self, Future}; -use spec::CommonParams; -use transaction::{Action, SignedTransaction}; -use hash::KECCAK_EMPTY; - -const MAX_CACHE_SIZE: usize = 4096; - -mod tx_permissions { - pub const _ALL: u32 = 0xffffffff; - pub const NONE: u32 = 0x0; - pub const BASIC: u32 = 0b00000001; - pub const CALL: u32 = 0b00000010; - pub const CREATE: u32 = 0b00000100; - pub const _PRIVATE: u32 = 0b00001000; -} - -/// Connection filter that uses a contract to manage permissions. -pub struct TransactionFilter { - contract: Mutex>, - client: RwLock>>, - contract_address: Address, - permission_cache: Mutex>, -} - -impl TransactionFilter { - /// Create a new instance if address is specified in params. - pub fn from_params(params: &CommonParams) -> Option { - params.transaction_permission_contract.map(|address| - TransactionFilter { - contract: Mutex::new(None), - client: RwLock::new(None), - contract_address: address, - permission_cache: Mutex::new(HashMap::new()), - } - ) - } - - /// Clear cached permissions. - pub fn clear_cache(&self) { - self.permission_cache.lock().clear(); - } - - /// Set client reference to be used for contract call. - pub fn register_client(&self, client: Weak) { - *self.client.write() = Some(client); - } - - /// Check if transaction is allowed at given block. - pub fn transaction_allowed(&self, parent_hash: &H256, transaction: &SignedTransaction) -> bool { - self.client.read().as_ref().map_or(false, |client| { - let mut cache = self.permission_cache.lock(); let len = cache.len(); - let client = match client.upgrade() { - Some(client) => client, - _ => return false, - }; - let tx_type = match transaction.action { - Action::Create => tx_permissions::CREATE, - Action::Call(address) => if client.code_hash(&address, BlockId::Hash(*parent_hash)).map_or(false, |c| c != KECCAK_EMPTY) { - tx_permissions::CALL - } else { - tx_permissions::BASIC - } - }; - let sender = transaction.sender(); - match cache.entry((*parent_hash, sender)) { - Entry::Occupied(entry) => *entry.get() & tx_type != 0, - Entry::Vacant(entry) => { - let mut contract = self.contract.lock(); - if contract.is_none() { - *contract = Some(Contract::new(self.contract_address)); - } - - let permissions = match &*contract { - &Some(ref contract) => { - contract.allowed_tx_types( - |addr, data| futures::done(client.call_contract(BlockId::Hash(*parent_hash), addr, data)), - sender, - ).wait().unwrap_or_else(|e| { - debug!("Error callling tx permissions contract: {:?}", e); - tx_permissions::NONE - }) - } - _ => tx_permissions::NONE, - }; - - if len < MAX_CACHE_SIZE { - entry.insert(permissions); - } - trace!("Permissions required: {}, got: {}", tx_type, permissions); - permissions & tx_type != 0 - } - } - }) - } -} - -impl ChainNotify for TransactionFilter { - fn new_blocks(&self, imported: Vec, _invalid: Vec, _enacted: Vec, _retracted: Vec, _sealed: Vec, _proposed: Vec, _duration: u64) { - if !imported.is_empty() { - self.clear_cache(); - } - } -} - -#[cfg(test)] -mod test { - use std::sync::{Arc, Weak}; - use spec::Spec; - use client::{BlockChainClient, Client, ClientConfig, BlockId}; - use miner::Miner; - use util::{Address}; - use io::IoChannel; - use ethkey::{Secret, KeyPair}; - use super::TransactionFilter; - use transaction::{Transaction, Action}; - - /// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a - #[test] - fn transaction_filter() { - let spec_data = r#" - { - "name": "TestNodeFilterContract", - "engine": { - "authorityRound": { - "params": { - "stepDuration": 1, - "startStep": 2, - "validators": { - "contract": "0x0000000000000000000000000000000000000000" - } - } - } - }, - "params": { - "accountStartNonce": "0x0", - "maximumExtraDataSize": "0x20", - "minGasLimit": "0x1388", - "networkID" : "0x69", - "gasLimitBoundDivisor": "0x0400", - "transactionPermissionContract": "0x0000000000000000000000000000000000000005" - }, - "genesis": { - "seal": { - "generic": "0xc180" - }, - "difficulty": "0x20000", - "author": "0x0000000000000000000000000000000000000000", - "timestamp": "0x00", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "extraData": "0x", - "gasLimit": "0x222222" - }, - "accounts": { - "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { - "balance": "1", - "constructor": "6060604052341561000f57600080fd5b5b6101868061001f6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063e17512211461003e575b600080fd5b341561004957600080fd5b610075600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610097565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b6000737e5f4552091a69125d5dfcb7b8c2659029395bdf8273ffffffffffffffffffffffffffffffffffffffff1614156100d75763ffffffff9050610155565b732b5ad5c4795c026514f8317c7a215e218dccd6cf8273ffffffffffffffffffffffffffffffffffffffff1614156101155760026001179050610155565b736813eb9362372eef6200f3b1dbc3f819671cba698273ffffffffffffffffffffffffffffffffffffffff1614156101505760019050610155565b600090505b9190505600a165627a7a72305820f1f21cb978925a8a92c6e30c8c81adf598adff6d1ef941cf5ed6c0ec7ad1ae3d0029" - } - } - } - "#; - - let spec = Spec::load(::std::env::temp_dir(), spec_data.as_bytes()).unwrap(); - let client_db = Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0))); - - let client = Client::new( - ClientConfig::default(), - &spec, - client_db, - Arc::new(Miner::with_spec(&spec)), - IoChannel::disconnected(), - ).unwrap(); - let key1 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000001")).unwrap(); - let key2 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000002")).unwrap(); - let key3 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000003")).unwrap(); - let key4 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000004")).unwrap(); - - let filter = TransactionFilter::from_params(spec.params()).unwrap(); - filter.register_client(Arc::downgrade(&client) as Weak); - let mut basic_tx = Transaction::default(); - basic_tx.action = Action::Call(Address::from("000000000000000000000000000000000000032")); - let create_tx = Transaction::default(); - let mut call_tx = Transaction::default(); - call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005")); - - let genesis = client.block_hash(BlockId::Latest).unwrap(); - - assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None))); - assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None))); - assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None))); - - assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key2.secret(), None))); - assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None))); - assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.secret(), None))); - - assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key3.secret(), None))); - assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None))); - assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.secret(), None))); - - assert!(!filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key4.secret(), None))); - assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None))); - assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.secret(), None))); - } -} - diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 4561bcada1b..b90eef5ea14 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -108,9 +108,6 @@ pub struct Params { /// Node permission contract address. #[serde(rename="nodePermissionContract")] pub node_permission_contract: Option
, - /// Transaction permission contract address. - #[serde(rename="transactionPermissionContract")] - pub transaction_permission_contract: Option
, } #[cfg(test)] diff --git a/rpc/src/v1/helpers/errors.rs b/rpc/src/v1/helpers/errors.rs index 23cbbfefcd1..559f3a6b948 100644 --- a/rpc/src/v1/helpers/errors.rs +++ b/rpc/src/v1/helpers/errors.rs @@ -315,7 +315,6 @@ pub fn transaction_message(error: TransactionError) -> String { SenderBanned => "Sender is banned in local queue.".into(), RecipientBanned => "Recipient is banned in local queue.".into(), CodeBanned => "Code is banned in local queue.".into(), - NotAllowed => "Transaction is not permitted.".into(), } }