TxPermissions ver 3: gas price & data (#11170)
This commit is contained in:
committed by
Andronik Ordian
parent
9c8b7c23d1
commit
ff697b64b3
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user