Merge pull request #7359 from VladLupashevskyi/transactions-permission-contract-fix

Added checking tx-type using transactions permission contract for miners
This commit is contained in:
Marek Kotewicz 2017-12-29 11:46:10 +01:00 committed by GitHub
commit 2586eaef92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 1 deletions

View File

@ -1840,6 +1840,8 @@ impl BlockChainClient for Client {
} }
impl MiningBlockChainClient for Client { impl MiningBlockChainClient for Client {
fn as_block_chain_client(&self) -> &BlockChainClient { self }
fn latest_schedule(&self) -> Schedule { fn latest_schedule(&self) -> Schedule {
self.engine.schedule(self.latest_env_info().number) self.engine.schedule(self.latest_env_info().number)
} }

View File

@ -365,6 +365,8 @@ pub fn get_temp_state_db() -> GuardedTempResult<StateDB> {
} }
impl MiningBlockChainClient for TestBlockChainClient { impl MiningBlockChainClient for TestBlockChainClient {
fn as_block_chain_client(&self) -> &BlockChainClient { self }
fn latest_schedule(&self) -> Schedule { fn latest_schedule(&self) -> Schedule {
Schedule::new_post_eip150(24576, true, true, true) Schedule::new_post_eip150(24576, true, true, true)
} }

View File

@ -308,6 +308,9 @@ pub trait MiningBlockChainClient: BlockChainClient {
/// Returns latest schedule. /// Returns latest schedule.
fn latest_schedule(&self) -> Schedule; fn latest_schedule(&self) -> Schedule;
/// Returns base of this trait
fn as_block_chain_client(&self) -> &BlockChainClient;
} }
/// Client facilities used by internally sealing Engines. /// Client facilities used by internally sealing Engines.

View File

@ -410,6 +410,7 @@ impl Miner {
}; };
let mut invalid_transactions = HashSet::new(); let mut invalid_transactions = HashSet::new();
let mut non_allowed_transactions = HashSet::new();
let mut transactions_to_penalize = HashSet::new(); let mut transactions_to_penalize = HashSet::new();
let block_number = open_block.block().fields().header.number(); let block_number = open_block.block().fields().header.number();
@ -418,7 +419,15 @@ impl Miner {
for tx in transactions { for tx in transactions {
let hash = tx.hash(); let hash = tx.hash();
let start = Instant::now(); let start = Instant::now();
let result = open_block.push_transaction(tx, None); // Check whether transaction type is allowed for sender
let result = match self.engine.machine().verify_transaction(&tx, open_block.header(), chain.as_block_chain_client()) {
Err(Error::Transaction(TransactionError::NotAllowed)) => {
Err(TransactionError::NotAllowed.into())
}
_ => {
open_block.push_transaction(tx, None)
}
};
let took = start.elapsed(); let took = start.elapsed();
// Check for heavy transactions // Check for heavy transactions
@ -459,6 +468,12 @@ impl Miner {
}, },
// already have transaction - ignore // already have transaction - ignore
Err(Error::Transaction(TransactionError::AlreadyImported)) => {}, Err(Error::Transaction(TransactionError::AlreadyImported)) => {},
Err(Error::Transaction(TransactionError::NotAllowed)) => {
non_allowed_transactions.insert(hash);
debug!(target: "miner",
"Skipping non-allowed transaction for sender {:?}",
hash);
},
Err(e) => { Err(e) => {
invalid_transactions.insert(hash); invalid_transactions.insert(hash);
debug!(target: "miner", debug!(target: "miner",
@ -481,6 +496,9 @@ impl Miner {
for hash in invalid_transactions { for hash in invalid_transactions {
queue.remove(&hash, &fetch_nonce, RemovalReason::Invalid); queue.remove(&hash, &fetch_nonce, RemovalReason::Invalid);
} }
for hash in non_allowed_transactions {
queue.remove(&hash, &fetch_nonce, RemovalReason::NotAllowed);
}
for hash in transactions_to_penalize { for hash in transactions_to_penalize {
queue.penalize(&hash); queue.penalize(&hash);
} }
@ -679,6 +697,9 @@ impl Miner {
Err(e) Err(e)
}, },
Ok(transaction) => { Ok(transaction) => {
// This check goes here because verify_transaction takes SignedTransaction parameter
self.engine.machine().verify_transaction(&transaction, &best_block_header, client.as_block_chain_client())?;
let origin = self.accounts.as_ref().and_then(|accounts| { let origin = self.accounts.as_ref().and_then(|accounts| {
match accounts.has_account(transaction.sender()).unwrap_or(false) { match accounts.has_account(transaction.sender()).unwrap_or(false) {
true => Some(TransactionOrigin::Local), true => Some(TransactionOrigin::Local),

View File

@ -543,6 +543,8 @@ pub enum RemovalReason {
Invalid, Invalid,
/// Transaction was canceled /// Transaction was canceled
Canceled, Canceled,
/// Transaction is not allowed,
NotAllowed,
} }
/// Point in time when transaction was inserted. /// Point in time when transaction was inserted.
@ -1012,6 +1014,9 @@ impl TransactionQueue {
RemovalReason::Invalid => self.local_transactions.mark_invalid( RemovalReason::Invalid => self.local_transactions.mark_invalid(
transaction.transaction.into() transaction.transaction.into()
), ),
RemovalReason::NotAllowed => self.local_transactions.mark_invalid(
transaction.transaction.into()
),
RemovalReason::Canceled => self.local_transactions.mark_canceled( RemovalReason::Canceled => self.local_transactions.mark_canceled(
PendingTransaction::new(transaction.transaction, transaction.condition) PendingTransaction::new(transaction.transaction, transaction.condition)
), ),