Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
TxPermissions ver 3: gas price & data (#11170)
Browse files Browse the repository at this point in the history
  • Loading branch information
afck authored and ordian committed Oct 18, 2019
1 parent 9c8b7c2 commit ff697b6
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 3 deletions.
83 changes: 83 additions & 0 deletions ethcore/machine/res/tx_acl_gas_price.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
[
{
"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": "data",
"type": "bytes"
}
],
"name": "allowedTxTypes",
"outputs": [
{
"name": "",
"type": "uint32"
},
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]
63 changes: 60 additions & 3 deletions ethcore/machine/src/tx_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use keccak_hash::KECCAK_EMPTY;

use_contract!(transact_acl_deprecated, "res/tx_acl_deprecated.json");
use_contract!(transact_acl, "res/tx_acl.json");
use_contract!(transact_acl_gas_price, "res/tx_acl_gas_price.json");

const MAX_CACHE_SIZE: usize = 4096;

Expand Down Expand Up @@ -86,6 +87,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) {
Expand Down Expand Up @@ -115,6 +117,19 @@ impl TransactionFilter {
(tx_permissions::NONE, true)
})
},
3 => {
trace!(target: "tx_filter", "Using filter with gas price and data");
let (data, decoder) = transact_acl_gas_price::functions::allowed_tx_types::call(
sender, to, value, gas_price, transaction.data.clone()
);
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)
})
}
_ => {
error!(target: "tx_filter", "Unknown version of tx permissions contract is used");
(tx_permissions::NONE, true)
Expand All @@ -138,8 +153,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
}
Expand Down Expand Up @@ -171,7 +186,7 @@ mod test {

/// Contract code: https://gist.github.com/VladLupashevskyi/84f18eabb1e4afadf572cf92af3e7e7f
#[test]
fn transaction_filter() {
fn transaction_filter_ver_2() {
let spec_data = include_str!("../../res/tx_permission_tests/contract_ver_2_genesis.json");

let db = test_helpers::new_db();
Expand Down Expand Up @@ -248,6 +263,48 @@ mod test {
assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key6.clone().sign(key7.secret(), None), &*client));
}

/// Contract code: res/tx_permission_tests/contract_ver_3.sol
#[test]
fn transaction_filter_ver_3() {
let spec_data = include_str!("../../res/tx_permission_tests/contract_ver_3_genesis.json");

let db = test_helpers::new_db();
let tempdir = TempDir::new("").unwrap();
let spec = Spec::load(&tempdir.path(), spec_data.as_bytes()).unwrap();

let client = Client::new(
ClientConfig::default(),
&spec,
db,
Arc::new(Miner::new_for_tests(&spec, None)),
IoChannel::disconnected(),
).unwrap();
let key1 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000001")).unwrap();

// The only difference to version 2 is that the contract now knows the transaction's gas price and data.
// So we only test those: The contract allows only transactions with either nonzero gas price or short data.

let filter = TransactionFilter::from_params(spec.params()).unwrap();
let mut tx = Transaction::default();
tx.action = Action::Call(Address::from_str("0000000000000000000000000000000000000042").unwrap());
tx.data = b"01234567".to_vec();
tx.gas_price = 0.into();

let genesis = client.block_hash(BlockId::Latest).unwrap();
let block_number = 1;

// Data too long and gas price zero. This transaction is not allowed.
assert!(!filter.transaction_allowed(&genesis, block_number, &tx.clone().sign(key1.secret(), None), &*client));

// But if we either set a nonzero gas price or short data or both, it is allowed.
tx.gas_price = 1.into();
assert!(filter.transaction_allowed(&genesis, block_number, &tx.clone().sign(key1.secret(), None), &*client));
tx.data = b"01".to_vec();
assert!(filter.transaction_allowed(&genesis, block_number, &tx.clone().sign(key1.secret(), None), &*client));
tx.gas_price = 0.into();
assert!(filter.transaction_allowed(&genesis, block_number, &tx.clone().sign(key1.secret(), None), &*client));
}

/// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a
#[test]
fn transaction_filter_deprecated() {
Expand Down
60 changes: 60 additions & 0 deletions ethcore/res/tx_permission_tests/contract_ver_3.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
pragma solidity ^0.4.20;

// Adapted from https://gist.github.com/VladLupashevskyi/84f18eabb1e4afadf572cf92af3e7e7f
// and: https://github.com/poanetwork/posdao-contracts/blob/master/contracts/TxPermission.sol

contract TxPermission {
/// Allowed transaction types mask
uint32 constant None = 0;
uint32 constant All = 0xffffffff;
uint32 constant Basic = 0x01;
uint32 constant Call = 0x02;
uint32 constant Create = 0x04;
uint32 constant Private = 0x08;

/// Contract name
function contractName() public constant returns (string) {
return "TX_PERMISSION_CONTRACT";
}

/// Contract name hash
function contractNameHash() public constant returns (bytes32) {
return keccak256(contractName());
}

/// Contract version
function contractVersion() public constant returns (uint256) {
return 3;
}

/// @dev Defines the allowed transaction types which may be initiated by the specified sender with
/// the specified gas price and data. Used by the Parity engine each time a transaction is about to be
/// included into a block. See https://wiki.parity.io/Permissioning.html#how-it-works-1
/// @param _sender Transaction sender address.
/// @param _to Transaction recipient address. If creating a contract, the `_to` address is zero.
/// @param _value Transaction amount in wei.
/// @param _gasPrice Gas price in wei for the transaction.
/// @param _data Transaction data.
/// @return `uint32 typesMask` - Set of allowed transactions for `_sender` depending on tx `_to` address,
/// `_gasPrice`, and `_data`. The result is represented as a set of flags:
/// 0x01 - basic transaction (e.g. ether transferring to user wallet);
/// 0x02 - contract call;
/// 0x04 - contract creation;
/// 0x08 - private transaction.
/// `bool cache` - If `true` is returned, the same permissions will be applied from the same
/// `_sender` without calling this contract again.
function allowedTxTypes(
address _sender,
address _to,
uint256 _value,
uint256 _gasPrice,
bytes memory _data
)
public
view
returns(uint32 typesMask, bool cache)
{
if (_gasPrice > 0 || _data.length < 4) return (All, false);
return (None, false);
}
}
44 changes: 44 additions & 0 deletions ethcore/res/tx_permission_tests/contract_ver_3_genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"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",
"transactionPermissionContractTransition": "1"
},
"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": "6060604052341561000f57600080fd5b61035e8061001e6000396000f300606060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063469ab1e31461006757806375d0c0dc14610098578063a0a8e46014610126578063b9056afa1461014f575b600080fd5b341561007257600080fd5b61007a610227565b60405180826000191660001916815260200191505060405180910390f35b34156100a357600080fd5b6100ab610298565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100eb5780820151818401526020810190506100d0565b50505050905090810190601f1680156101185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013157600080fd5b6101396102db565b6040518082815260200191505060405180910390f35b341561015a57600080fd5b6101fa600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190803590602001909190803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506102e4565b604051808363ffffffff1663ffffffff168152602001821515151581526020019250505060405180910390f35b6000610231610298565b6040518082805190602001908083835b6020831015156102665780518252602082019150602081019050602083039250610241565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040518091039020905090565b6102a061031e565b6040805190810160405280601681526020017f54585f5045524d495353494f4e5f434f4e545241435400000000000000000000815250905090565b60006003905090565b60008060008411806102f7575060048351105b1561030c5763ffffffff600091509150610314565b600080915091505b9550959350505050565b6020604051908101604052806000815250905600a165627a7a72305820be61565bc09fec6e9223a1fecd2e94783ca5c6f506c03f71d479a8c3285493310029"
}
}
}

0 comments on commit ff697b6

Please sign in to comment.