ethcore: add transition flag for transaction permission contract (#9275)
* ethcore: add transition flag for transaction permission contract * ethcore: fix transaction permission contract tests
This commit is contained in:
		
							parent
							
								
									1f18dbb17c
								
							
						
					
					
						commit
						712101b63d
					
				@ -17,7 +17,8 @@
 | 
			
		||||
		"minGasLimit": "0x1388",
 | 
			
		||||
		"networkID" : "0x69",
 | 
			
		||||
		"gasLimitBoundDivisor": "0x0400",
 | 
			
		||||
		"transactionPermissionContract": "0x0000000000000000000000000000000000000005"
 | 
			
		||||
		"transactionPermissionContract": "0x0000000000000000000000000000000000000005",
 | 
			
		||||
		"transactionPermissionContractTransition": "1"
 | 
			
		||||
	},
 | 
			
		||||
	"genesis": {
 | 
			
		||||
		"seal": {
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,8 @@
 | 
			
		||||
		"minGasLimit": "0x1388",
 | 
			
		||||
		"networkID" : "0x69",
 | 
			
		||||
		"gasLimitBoundDivisor": "0x0400",
 | 
			
		||||
		"transactionPermissionContract": "0x0000000000000000000000000000000000000005"
 | 
			
		||||
		"transactionPermissionContract": "0x0000000000000000000000000000000000000005",
 | 
			
		||||
		"transactionPermissionContractTransition": "1"
 | 
			
		||||
	},
 | 
			
		||||
	"genesis": {
 | 
			
		||||
		"seal": {
 | 
			
		||||
 | 
			
		||||
@ -343,7 +343,7 @@ impl EthereumMachine {
 | 
			
		||||
		-> Result<(), transaction::Error>
 | 
			
		||||
	{
 | 
			
		||||
		if let Some(ref filter) = self.tx_filter.as_ref() {
 | 
			
		||||
			if !filter.transaction_allowed(header.parent_hash(), t, client) {
 | 
			
		||||
			if !filter.transaction_allowed(header.parent_hash(), header.number(), t, client) {
 | 
			
		||||
				return Err(transaction::Error::NotAllowed.into())
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -139,6 +139,8 @@ pub struct CommonParams {
 | 
			
		||||
	pub max_code_size_transition: BlockNumber,
 | 
			
		||||
	/// Transaction permission managing contract address.
 | 
			
		||||
	pub transaction_permission_contract: Option<Address>,
 | 
			
		||||
	/// Block at which the transaction permission contract should start being used.
 | 
			
		||||
	pub transaction_permission_contract_transition: BlockNumber,
 | 
			
		||||
	/// Maximum size of transaction's RLP payload
 | 
			
		||||
	pub max_transaction_size: usize,
 | 
			
		||||
}
 | 
			
		||||
@ -296,6 +298,8 @@ impl From<ethjson::spec::Params> for CommonParams {
 | 
			
		||||
			max_transaction_size: p.max_transaction_size.map_or(MAX_TRANSACTION_SIZE, Into::into),
 | 
			
		||||
			max_code_size_transition: p.max_code_size_transition.map_or(0, Into::into),
 | 
			
		||||
			transaction_permission_contract: p.transaction_permission_contract.map(Into::into),
 | 
			
		||||
			transaction_permission_contract_transition:
 | 
			
		||||
				p.transaction_permission_contract_transition.map_or(0, Into::into),
 | 
			
		||||
			wasm_activation_transition: p.wasm_activation_transition.map_or_else(
 | 
			
		||||
				BlockNumber::max_value,
 | 
			
		||||
				Into::into
 | 
			
		||||
 | 
			
		||||
@ -23,6 +23,7 @@ use client::{BlockInfo, CallContract, BlockId};
 | 
			
		||||
use parking_lot::Mutex;
 | 
			
		||||
use spec::CommonParams;
 | 
			
		||||
use transaction::{Action, SignedTransaction};
 | 
			
		||||
use types::BlockNumber;
 | 
			
		||||
use hash::KECCAK_EMPTY;
 | 
			
		||||
 | 
			
		||||
use_contract!(transact_acl_deprecated, "TransactAclDeprecated", "res/contracts/tx_acl_deprecated.json");
 | 
			
		||||
@ -44,6 +45,7 @@ pub struct TransactionFilter {
 | 
			
		||||
	contract_deprecated: transact_acl_deprecated::TransactAclDeprecated,
 | 
			
		||||
	contract: transact_acl::TransactAcl,
 | 
			
		||||
	contract_address: Address,
 | 
			
		||||
	transition_block: BlockNumber,
 | 
			
		||||
	permission_cache: Mutex<LruCache<(H256, Address), u32>>,
 | 
			
		||||
	contract_version_cache: Mutex<LruCache<(H256), Option<U256>>>
 | 
			
		||||
}
 | 
			
		||||
@ -56,6 +58,7 @@ impl TransactionFilter {
 | 
			
		||||
				contract_deprecated: transact_acl_deprecated::TransactAclDeprecated::default(),
 | 
			
		||||
				contract: transact_acl::TransactAcl::default(),
 | 
			
		||||
				contract_address: address,
 | 
			
		||||
				transition_block: params.transaction_permission_contract_transition,
 | 
			
		||||
				permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
 | 
			
		||||
				contract_version_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
 | 
			
		||||
			}
 | 
			
		||||
@ -63,7 +66,9 @@ impl TransactionFilter {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Check if transaction is allowed at given block.
 | 
			
		||||
	pub fn transaction_allowed<C: BlockInfo + CallContract>(&self, parent_hash: &H256, transaction: &SignedTransaction, client: &C) -> bool {
 | 
			
		||||
	pub fn transaction_allowed<C: BlockInfo + CallContract>(&self, parent_hash: &H256, block_number: BlockNumber, transaction: &SignedTransaction, client: &C) -> bool {
 | 
			
		||||
		if block_number < self.transition_block { return true; }
 | 
			
		||||
 | 
			
		||||
		let mut permission_cache = self.permission_cache.lock();
 | 
			
		||||
		let mut contract_version_cache = self.contract_version_cache.lock();
 | 
			
		||||
 | 
			
		||||
@ -196,33 +201,38 @@ mod test {
 | 
			
		||||
		basic_tx_with_ether_and_to_key6.value = U256::from(123123);
 | 
			
		||||
 | 
			
		||||
		let genesis = client.block_hash(BlockId::Latest).unwrap();
 | 
			
		||||
		let block_number = 1;
 | 
			
		||||
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		// same tx but request is allowed because the contract only enables at block #1
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, 0, &create_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key7.clone().sign(key5.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &call_tx_with_ether.clone().sign(key5.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key6.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key7.clone().sign(key6.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx_to_key6.clone().sign(key7.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &basic_tx_with_ether_and_to_key6.clone().sign(key7.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key7.clone().sign(key5.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx_with_ether.clone().sign(key5.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key6.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key7.clone().sign(key6.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx_to_key6.clone().sign(key7.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx_with_ether_and_to_key6.clone().sign(key7.secret(), None), &*client));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Contract code: https://gist.github.com/arkpar/38a87cb50165b7e683585eec71acb05a
 | 
			
		||||
@ -254,21 +264,26 @@ mod test {
 | 
			
		||||
		call_tx.action = Action::Call(Address::from("0000000000000000000000000000000000000005"));
 | 
			
		||||
 | 
			
		||||
		let genesis = client.block_hash(BlockId::Latest).unwrap();
 | 
			
		||||
		let block_number = 1;
 | 
			
		||||
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &create_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		// same tx but request is allowed because the contract only enables at block #1
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, 0, &create_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &call_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key1.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key2.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &basic_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &create_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, &call_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key3.secret(), None), &*client));
 | 
			
		||||
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &basic_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &create_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
		assert!(!filter.transaction_allowed(&genesis, block_number, &call_tx.clone().sign(key4.secret(), None), &*client));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -143,6 +143,9 @@ pub struct Params {
 | 
			
		||||
	/// Transaction permission contract address.
 | 
			
		||||
	#[serde(rename="transactionPermissionContract")]
 | 
			
		||||
	pub transaction_permission_contract: Option<Address>,
 | 
			
		||||
	/// Block at which the transaction permission contract should start being used.
 | 
			
		||||
	#[serde(rename="transactionPermissionContractTransition")]
 | 
			
		||||
	pub transaction_permission_contract_transition: Option<Uint>,
 | 
			
		||||
	/// Wasm activation block height, if not activated from start
 | 
			
		||||
	#[serde(rename="wasmActivationTransition")]
 | 
			
		||||
	pub wasm_activation_transition: Option<Uint>,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user