TxPermissions ver 3: gas price & data (#11170)

This commit is contained in:
Andreas Fackler
2019-10-18 12:12:06 +02:00
committed by Andronik Ordian
parent 9c8b7c23d1
commit ff697b64b3
4 changed files with 247 additions and 3 deletions

View File

@@ -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;
@@ -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) {
@@ -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)
@@ -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
}
@@ -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();
@@ -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() {