diff --git a/ethcore/res/contracts/tx_acl_gas_price.json b/ethcore/res/contracts/tx_acl_gas_price.json new file mode 100644 index 00000000000..5a294621dab --- /dev/null +++ b/ethcore/res/contracts/tx_acl_gas_price.json @@ -0,0 +1,79 @@ +[ + { + "constant": true, + "inputs": [], + "name": "contractNameHash", + "outputs": [ + { + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "contractName", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "contractVersion", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "sender", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "value", + "type": "uint256" + }, + { + "name": "gasPrice", + "type": "uint256" + } + ], + "name": "allowedTxTypes", + "outputs": [ + { + "name": "", + "type": "uint32" + }, + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs index 3f32ab365a8..a92e5dd2d05 100644 --- a/ethcore/src/tx_filter.rs +++ b/ethcore/src/tx_filter.rs @@ -30,6 +30,7 @@ use hash::KECCAK_EMPTY; use_contract!(transact_acl_deprecated, "res/contracts/tx_acl_deprecated.json"); use_contract!(transact_acl, "res/contracts/tx_acl.json"); +use_contract!(transact_acl_gas_price, "res/contracts/tx_acl_gas_price.json"); const MAX_CACHE_SIZE: usize = 4096; @@ -81,6 +82,7 @@ impl TransactionFilter { let sender = transaction.sender(); let value = transaction.value; + let gas_price = transaction.gas_price; let key = (*parent_hash, sender); if let Some(permissions) = permission_cache.get_mut(&key) { @@ -105,17 +107,23 @@ impl TransactionFilter { client.call_contract(BlockId::Hash(*parent_hash), contract_address, data) .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) .map(|(p, f)| (p.low_u32(), f)) - .unwrap_or_else(|e| { - error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); - (tx_permissions::NONE, true) - }) - }, + } + 0xffff_ffff_ffff_fffe => { + trace!(target: "tx_filter", "Using filter with gas price"); + let (data, decoder) = transact_acl_gas_price::functions::allowed_tx_types::call(sender, to, value, gas_price); + client.call_contract(BlockId::Hash(*parent_hash), contract_address, data) + .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string())) + .map(|(p, f)| (p.low_u32(), f)) + } _ => { error!(target: "tx_filter", "Unknown version of tx permissions contract is used"); - (tx_permissions::NONE, true) + Ok((tx_permissions::NONE, true)) } - } - }, + }.unwrap_or_else(|e| { + error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); + (tx_permissions::NONE, true) + }) + } None => { trace!(target: "tx_filter", "Fallback to the deprecated version of tx permission contract"); let (data, decoder) = transact_acl_deprecated::functions::allowed_tx_types::call(sender); @@ -133,8 +141,8 @@ impl TransactionFilter { permission_cache.insert((*parent_hash, sender), permissions); } trace!(target: "tx_filter", - "Given transaction data: sender: {:?} to: {:?} value: {}. Permissions required: {:X}, got: {:X}", - sender, to, value, tx_type, permissions + "Given transaction data: sender: {:?} to: {:?} value: {}, gas_price: {}. Permissions required: {:X}, got: {:X}", + sender, to, value, gas_price, tx_type, permissions ); permissions & tx_type != 0 }