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

Implement caching for service transactions checker #10088

Merged
merged 41 commits into from
Mar 31, 2019

Conversation

VladLupashevskyi
Copy link
Contributor

In cases when certain address is allowed for executing free transactions it makes sense in my opinion to submit transactions which are automatically submitted by the client (such as validators reporting etc) with the gas price set to zero.

Here I propose my code improvement to achieve this by adding check for free tx certification in transact_contract fn which is called while doing validators reporting and other actions.

Looking forward for the feedback :)

@parity-cla-bot
Copy link

It looks like @VladLupashevskyi signed our Contributor License Agreement. 👍

Many thanks,

Parity Technologies CLA Bot

Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea looks reasonable I'm only concerned with circular call to state - we should make sure that all the calls are not vulnerable to deadlocks or some data races now.
(and obv the implementation needs some improvements)

let transaction = Transaction {
nonce: self.latest_nonce(&authoring_params.author),
action: Action::Call(address),
gas: self.importer.miner.sensible_gas_limit(),
gas: gas_price,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you meant to change gas_price not gas.

ethcore/src/miner/service_transaction_checker.rs Outdated Show resolved Hide resolved
@@ -2112,10 +2113,15 @@ impl BlockChainClient for Client {

fn transact_contract(&self, address: Address, data: Bytes) -> Result<(), transaction::Error> {
let authoring_params = self.importer.miner.authoring_params();
let service_transaction_checker = ServiceTransactionChecker::default();
let gas_price = match service_transaction_checker.check_address(self, address) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

address is contract address you try to call, not the sender (which should be checked here).

@@ -20,7 +20,7 @@
//! Keeps track of transactions and currently sealed pending block.

mod miner;
mod service_transaction_checker;
pub mod service_transaction_checker;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please group with other pub mod

@tomusdrw tomusdrw added A4-gotissues 💥 Pull request is reviewed and has significant issues which must be addressed. M4-core ⛓ Core client code / Rust. labels Dec 24, 2018
@5chdn 5chdn added this to the 2.3 milestone Jan 2, 2019
@VladLupashevskyi
Copy link
Contributor Author

@tomusdrw I pushed the fixes and sorry for these typos.

I am not sure what kind of deadlocks or data races could occur because free tx permission is checked for the latest mined block and not for the pending one. What I can think of is that issues could occur if we would call transact_contract inside of check_address function, but calling state modifying function inside state checking one does not make sense for me.

Maybe I am missing something, so I would be happy to get more feedback and dig into solving it :)

# Conflicts:
#	ethcore/src/client/client.rs
@5chdn 5chdn modified the milestones: 2.3, 2.4 Jan 10, 2019
@5chdn 5chdn added A0-pleasereview 🤓 Pull request needs code review. and removed A4-gotissues 💥 Pull request is reviewed and has significant issues which must be addressed. labels Jan 10, 2019
Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@tomusdrw tomusdrw added A8-looksgood 🦄 Pull request is reviewed well. and removed A0-pleasereview 🤓 Pull request needs code review. labels Jan 11, 2019

/// Checks if given address is whitelisted to send service transactions.
pub fn check_address<C: CallContract + RegistryInfo>(&self, client: &C, sender: Address) -> Result<bool, String> {
let contract_address = client.registry_address(SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME.to_owned(), BlockId::Latest)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the performance be a concern here? registry_address would need to query the state if registrar is set.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that an issue, some cache would be nice (best would be if previously queried registry entries would be refreshed after a block is imported), but the code is not super hot (only in \.transact which is called by the engine, or by the miner, called only for zero-gas-price transactions attempting to enter the pool).

@VladLupashevskyi
Copy link
Contributor Author

I added a cache for certified addresses and provided logic as @tomusdrw described.

This is first time I'm working with caching so there is definitely something to improve and I'm always happy to get a feedback :)

@VladLupashevskyi
Copy link
Contributor Author

@tomusdrw I think idea with moving ServiceTxChecker to one place sounds reasonable! I would create a public method to get the checker instance from miner, so it's done more generic than just exposing a check method.
So I'm gonna dig into this and will notify about the results!

@VladLupashevskyi
Copy link
Contributor Author

@tomusdrw I updated the code according to the comments, now it looks much cleaner! I'm thinking it would be nice to introduce some cache limiting, I would propose to use the solution I introduced in another PR for NodeFilter:

https://github.com/paritytech/parity-ethereum/blob/2202646acefc04e4a26c6fed3952728f0c355762/ethcore/node-filter/src/lib.rs#L107

where basically I used Vec in order to store sequence of recent calls to the contract and remove the oldest ones when cache hits limit.

What do you think about it?

@5chdn
Copy link
Contributor

5chdn commented Feb 7, 2019

Could you revisit this, @tomusdrw

@5chdn 5chdn added A0-pleasereview 🤓 Pull request needs code review. and removed A3-inprogress ⏳ Pull request is in progress. No review needed at this stage. labels Feb 7, 2019
Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, few nitpicks.

ethcore/src/miner/miner.rs Outdated Show resolved Hide resolved
ethcore/src/miner/miner.rs Outdated Show resolved Hide resolved
ethcore/src/miner/miner.rs Outdated Show resolved Hide resolved
ethcore/src/miner/pool_client.rs Outdated Show resolved Hide resolved

use_contract!(service_transaction, "res/contracts/service_transaction.json");

const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transaction_checker";

/// Service transactions checker.
#[derive(Default, Clone)]
pub struct ServiceTransactionChecker;
#[derive(Clone)]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need Clone?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need Clone in order to share ServiceTransactionChecker with Client and PoolClient.

miner/src/service_transaction_checker.rs Outdated Show resolved Hide resolved
@@ -44,9 +55,42 @@ impl ServiceTransactionChecker {

/// Checks if given address is whitelisted to send service transactions.
pub fn check_address<C: CallContract + RegistryInfo>(&self, client: &C, sender: Address) -> Result<bool, String> {
trace!(target: "txqueue", "Checking service transaction checker contract from {}", sender);
if let Some(allowed) = self.certified_addresses_cache.try_read().as_ref().and_then(|c| c.get(&sender)){
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.as_ref() seems redundant, also missing space before {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot do this without .as_ref() since the c doesn't live long enough in this case. I tried to do it with .map, but in this case Option<Option<&bool>> is returned, so one more check is needed. Not sure what would be better solution here.

# Conflicts:
#	Cargo.lock
#	ethcore/private-tx/src/lib.rs
#	ethcore/src/miner/miner.rs
#	ethcore/src/miner/pool_client.rs
# Conflicts:
#	Cargo.lock
#	ethcore/private-tx/src/lib.rs
#	ethcore/src/miner/miner.rs
#	ethcore/src/miner/pool_client.rs
Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

@5chdn 5chdn modified the milestones: 2.4, 2.5, 2.6 Feb 21, 2019
@soc1c soc1c added A8-looksgood 🦄 Pull request is reviewed well. and removed A0-pleasereview 🤓 Pull request needs code review. labels Feb 22, 2019
@soc1c
Copy link
Contributor

soc1c commented Feb 22, 2019

Needs a 2nd review 👍

@soc1c soc1c merged commit 7b2afdf into openethereum:master Mar 31, 2019
ordian added a commit that referenced this pull request Apr 5, 2019
* master:
  fix(light cull): poll light cull instead of timer (#10559)
  Update Issue Template to direct security issue to email (#10562)
  RPC: Implements eth_subscribe("syncing") (#10311)
  Explicitly enable or disable Stratum in config file (Issue 9785) (#10521)
  version: bump master to 2.6 (#10560)
  tx-pool: check transaction readiness before replacing (#10526)
  fix(light account response): update `tx_queue` (#10545)
  Update light client harcoded headers (#10547)
  fix(light eth_gasPrice): ask network if not in cache (#10535)
  Implement caching for service transactions checker (#10088)
  build android with cache, win fixes (#10546)
  clique: make state backfill time measurement more accurate (#10551)
  updated lru-cache to 0.1.2 (#10542)
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A8-looksgood 🦄 Pull request is reviewed well. M4-core ⛓ Core client code / Rust.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants