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

Commit

Permalink
Avoid race condition from trusted sources
Browse files Browse the repository at this point in the history
- refactor the miner tests a bit to cut down on code reuse
- add `trusted` param to dispatch_transaction and import_claimed_local_transaction

Add param to `import_claimed_local_transaction`

Fix fn sig in tests
  • Loading branch information
XertroV committed Jun 16, 2018
1 parent c92845b commit 07125c7
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 21 deletions.
10 changes: 6 additions & 4 deletions ethcore/src/miner/miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ impl miner::MinerService for Miner {
fn import_own_transaction<C: miner::BlockChainClient>(
&self,
chain: &C,
pending: PendingTransaction,
pending: PendingTransaction
) -> Result<(), transaction::Error> {
// note: you may want to use `import_claimed_local_transaction` instead of this one.

Expand All @@ -824,10 +824,12 @@ impl miner::MinerService for Miner {
&self,
chain: &C,
pending: PendingTransaction,
trusted: bool
) -> Result<(), transaction::Error> {
// treat the tx as local if the option is enabled, or if we have the account
let sender = pending.sender();
let treat_as_local = !self.options.tx_queue_no_unfamiliar_locals
let treat_as_local = trusted
|| !self.options.tx_queue_no_unfamiliar_locals
|| self.accounts.as_ref().map(|accts| accts.has_account(sender)).unwrap_or(false);

if treat_as_local {
Expand Down Expand Up @@ -1298,7 +1300,7 @@ mod tests {
let best_block = 0;
// when
// This transaction should not be marked as local because our account_provider doesn't have the sender
let res = miner.import_claimed_local_transaction(&client, PendingTransaction::new(transaction.clone(), None));
let res = miner.import_claimed_local_transaction(&client, PendingTransaction::new(transaction.clone(), None), false);

// then
// Check the same conditions as `should_import_external_transaction` first. Behaviour should be identical.
Expand All @@ -1313,7 +1315,7 @@ mod tests {
// when - 2nd part: create a local transaction from account_provider.
// Borrow the transaction used before & sign with our generated keypair.
let local_transaction = transaction.deconstruct().0.as_unsigned().clone().sign(keypair.secret(), Some(TEST_CHAIN_ID));
let res2 = miner.import_claimed_local_transaction(&client, PendingTransaction::new(local_transaction, None));
let res2 = miner.import_claimed_local_transaction(&client, PendingTransaction::new(local_transaction, None), false);

// then - 2nd part: we add on the results from the last pending block.
// This is borrowed from `should_make_pending_block_when_importing_own_transaction` and slightly modified.
Expand Down
2 changes: 1 addition & 1 deletion ethcore/src/miner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ pub trait MinerService : Send + Sync {

/// Imports transactions from potentially external sources, with behaviour determined
/// by the config flag `tx_queue_allow_unfamiliar_locals`
fn import_claimed_local_transaction<C>(&self, chain: &C, transaction: PendingTransaction)
fn import_claimed_local_transaction<C>(&self, chain: &C, transaction: PendingTransaction, trusted: bool)
-> Result<(), transaction::Error>
where C: BlockChainClient;

Expand Down
6 changes: 3 additions & 3 deletions rpc/src/v1/helpers/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,13 @@ impl<C: miner::BlockChainClient, M: MinerService> FullDispatcher<C, M> {
}

/// Imports transaction to the miner's queue.
pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: PendingTransaction) -> Result<H256> {
pub fn dispatch_transaction(client: &C, miner: &M, signed_transaction: PendingTransaction, trusted: bool) -> Result<H256> {
let hash = signed_transaction.transaction.hash();

// use `import_claimed_local_transaction` so we can decide (based on config flags) if we want to treat
// it as local or not. Nodes with public RPC interfaces will want these transactions to be treated like
// external transactions.
miner.import_claimed_local_transaction(client, signed_transaction)
miner.import_claimed_local_transaction(client, signed_transaction, trusted)
.map_err(errors::transaction)
.map(|_| hash)
}
Expand Down Expand Up @@ -183,7 +183,7 @@ impl<C: miner::BlockChainClient + BlockChainClient, M: MinerService> Dispatcher
}

fn dispatch_transaction(&self, signed_transaction: PendingTransaction) -> Result<H256> {
Self::dispatch_transaction(&*self.client, &*self.miner, signed_transaction)
Self::dispatch_transaction(&*self.client, &*self.miner, signed_transaction, true)
}
}

Expand Down
1 change: 1 addition & 0 deletions rpc/src/v1/impls/eth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM, T: StateInfo + 'static> Eth for EthClient<
&*self.client,
&*self.miner,
signed_transaction.into(),
false
)
})
.map(Into::into)
Expand Down
18 changes: 5 additions & 13 deletions rpc/src/v1/tests/helpers/miner_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,22 +155,14 @@ impl MinerService for TestMinerService {
}

/// Imports transactions to transaction queue.
fn import_own_transaction<C: Nonce + Sync>(&self, chain: &C, pending: PendingTransaction)
fn import_own_transaction<C: Nonce + Sync>(&self, _chain: &C, _pending: PendingTransaction)
-> Result<(), transaction::Error> {

// keep the pending nonces up to date
let sender = pending.transaction.sender();
let nonce = self.next_nonce(chain, &sender);
self.next_nonces.write().insert(sender, nonce);

// lets assume that all txs are valid
self.imported_transactions.lock().push(pending.transaction);

Ok(())
// this function is no longer called directly from RPC
unimplemented!();
}

/// Imports transactions to queue - treats as local based on config and tx source
fn import_claimed_local_transaction<C: Nonce + Sync>(&self, chain: &C, pending: PendingTransaction)
/// Imports transactions to queue - treats as local based on trusted flag, config, and tx source
fn import_claimed_local_transaction<C: Nonce + Sync>(&self, chain: &C, pending: PendingTransaction, _trusted: bool)
-> Result<(), transaction::Error> {

// keep the pending nonces up to date
Expand Down

0 comments on commit 07125c7

Please sign in to comment.