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

Resolve "Reverted report validator transactions get added in block #10580" #11030

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

VladLupashevskyi
Copy link
Contributor

Continuation of #10602

I opened the new MR since I couldnt reopen the previous MR (probably because I force pushed).

Basically here I implemented CLI flags for selecting a preferred strategy for reports as mentioned here with caching.

It's possible to use the following CLI flags:

  • benign_reporting=[force|call|disable]
  • malicious_reporting=[force|call|disable]
  • report_cache_call_every=[blk_num]

The frequency in blocks for caching is set for both reporting types. I wasn't sure whether it makes sense to make it also separated, but it will be easy to add if needed.

Please take a look and let me know if I need to improve or update something :)

Closes #10580

@parity-cla-bot
Copy link

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

Many thanks,

Parity Technologies CLA Bot

@jam10o-new jam10o-new added A0-pleasereview 🤓 Pull request needs code review. M4-core ⛓ Core client code / Rust. labels Sep 8, 2019
@VladLupashevskyi
Copy link
Contributor Author

Hmm. I cant figure out why tests are failing. It seems that error is Bad proof which is caused because of ExecutionError::Internal and this one is caused because of IncompleteDatabase. This is so strange since I haven't touched that pieces of the code.

Could somebody please throw a quick look at it, maybe there is something really simple that I've missed?

@dvdplm
Copy link
Collaborator

dvdplm commented Sep 11, 2019

Could somebody please throw a quick look at it, maybe there is something really simple that I've missed?

Nothing obvious stands out to me. I can repeat the failures locally and see Insufficient validation proof: Bad proof from zoom_to_after().

@VladLupashevskyi
Copy link
Contributor Author

@dvdplm Thank you for checking this out.

I've tried running test on different commits and it starts to fail since this one a9079db. Will dig into finding what's causing the issue.

@VladLupashevskyi
Copy link
Contributor Author

I think it's ready for review :)

@jam10o-new jam10o-new added this to the 2.7 milestone Sep 13, 2019
Copy link
Collaborator

@debris debris left a comment

Choose a reason for hiding this comment

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

All the libraries touching and utilising Engine are quite complex and we are trying to simplify them and make them easier to edit/maintain. I believe that this pull request, as is, cannot be accepted cause it is a step back in terms of complexity and simplicity of that code.

}

#[derive(Builder, Default, Clone)]
#[builder(default)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe this using this macro once is not worth bringing 5 new external dependencies to the project

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 agree, that using this one once does not make really sense! That and CallError have been introduced by @tomusdrw suggestion in this comment. I understood that intention to use builder was because it was planned to be used in other places. And according to CallError usage I assumed this one was suggested as the base boilerplate and is gonna be extended in the future for other cases which actually depend on the error type. My bad - I didn't clarify that before implementation, and I don't mind getting rid of this (I think it's not a big deal with builder macro, but more unsure about CallError), but I would like first to clarify this in order to prevent reverting the changes back and forth.

Copy link
Collaborator

Choose a reason for hiding this comment

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

@tomusdrw is there any reason to have 2 separate enum variants for CallError? We don't use them at all

Also, do you think we should commit to derive_builder and if yes, should we also use it in other places?

Copy link
Collaborator

@tomusdrw tomusdrw Oct 21, 2019

Choose a reason for hiding this comment

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

@debris The first line in the linked comment contains the answer:

I have considerations regarding the entire trait, extracting revert messages really calls for introducing a proper error type here (at least a two-value enum).

That previous PR was parsing the string to figure out that the call was reverted. So yes, I believe it's justified to have two variants.

Regarding derive_builder: I used it, cause it made the code nice and concise so it could fit in the comment. You can implement the methods manually or not use the builder pattern at all.

I think it's still worth to consider a refactor of some of the builders we already have in the code to have them derived to reduce boilerplate.

Copy link
Collaborator

Choose a reason for hiding this comment

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

my 2c on derive_builder: we already use derive_more and other proc macros so I think the "heavy" dependencies on syn, quote and proc_macro2 are already in-tree (need to be updated to the 1.0 releases though) so I don't think we add 5 new dependencies with this so think it's ok?

Reverted(String),
/// Other error
Other(String),
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

api consumer doesn't doesn't care whether the call is reverted has been reverted or not, which, imo makes this new data structure redundant

@@ -381,6 +382,9 @@ pub trait Engine: Sync + Send {
fn decode_transaction(&self, transaction: &[u8]) -> Result<UnverifiedTransaction, transaction::Error> {
self.machine().decode_transaction(transaction)
}

/// Set reporting
fn set_reporting(&self, _benign_reporting: ReportingConfig, _malicious_reporting: ReportingConfig) {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

this new method should not be here, cause:
a) it's engine specific
b) it's used only when engine is created, so it should be a part of engine creation process

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch, thank you! :) I used engine_signer logic as an example to introduce this one, but I have missed that signer can be changed during the lifetime of the Engine, which we don't need to do in this case. So this one and mutexes shall go away.

Comment on lines +487 to +488
benign_reporting: Mutex<ValidatorReporting>,
malicious_reporting: Mutex<ValidatorReporting>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

those values are set only once per lifetime of an engine - after it's creation, so they should not wrapped in the Mutex and should be set in AuthorityRound::new method

@@ -0,0 +1,7 @@
[package]
description = "Validators reporting config"
name = "validator-reporting-config"
Copy link
Collaborator

Choose a reason for hiding this comment

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

creating a new library for a single structure that is a config option for a validator-set library doesn't make sense. The content of this library should be a part of validator-set lib

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The main intention to move this into a separate module was the idea of not introducing other dependancies to the engine crate, which validator-set would bring with necessary to use just one struct from there. This was inspired by call-contract and other similar crates.

So you think it would be ok, to add validator-set to the Engine?

Copy link
Collaborator

Choose a reason for hiding this comment

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

So you think it would be ok, to add validator-set to the Engine?

No, but if you use ReportingConfig in the construction phase of the validator-set engine, the Engine trait doesn't have to know about this ReportingConfig struct at all

.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);
Copy link
Collaborator

Choose a reason for hiding this comment

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

{} implies displaying less information than {:?}. Why was it changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can't tell exactly now from top of my head, but I think this formatting is used because we map error to string before, so debug fmt is not really needed here anymore. Will double check this when I'm with my laptop next week.

@debris debris added A4-gotissues 💥 Pull request is reviewed and has significant issues which must be addressed. and removed A0-pleasereview 🤓 Pull request needs code review. labels Oct 18, 2019
@debris
Copy link
Collaborator

debris commented Oct 21, 2019

Thank you @VladLupashevskyi for the answers! For now, let's change the way validator-set engine is initialized and let's wait for @tomusdrw answers regarding call_contract.rs. You are right that it doesn't make sense to make changes back and forth :)

…into val-call

� Conflicts:
�	Cargo.lock
�	ethcore/call-contract/src/call_contract.rs
�	ethcore/engines/authority-round/src/lib.rs
�	ethcore/private-tx/src/key_server_keys.rs
�	ethcore/src/client/client.rs
�	ethcore/src/test_helpers/test_client.rs
�	miner/src/service_transaction_checker.rs
�	parity/run.rs
�	updater/src/updater.rs
@VladLupashevskyi
Copy link
Contributor Author

I was trying to change the way how validator-set engine is initialized and I found out that it will be a bit tricky to pass CLI args to it, since AuthorityRound::new finally uses Spec::load which is dependent on json specification and SpecParams, so I think the simplest way to do that is pass ReportingConfig there. However I'm not sure that it logically would fit there.

@debris What do you think about this approach, would it make sense to extend SpecParams?

}

#[derive(Builder, Default, Clone)]
#[builder(default)]
Copy link
Collaborator

Choose a reason for hiding this comment

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

my 2c on derive_builder: we already use derive_more and other proc macros so I think the "heavy" dependencies on syn, quote and proc_macro2 are already in-tree (need to be updated to the 1.0 releases though) so I don't think we add 5 new dependencies with this so think it's ok?

impl CallOptions {
/// Convenience method for creating the most common use case.
pub fn new(contract: Address, data: Bytes) -> Self {
CallOptionsBuilder::default().contract_address(contract).data(data).build().unwrap()
Copy link
Collaborator

Choose a reason for hiding this comment

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

No unwrap()s allowed outside tests; you need expect with a proper proof of why the inputs are guaranteed to be valid.

#[derive(Builder, Default, Clone)]
#[builder(default)]
/// Options to make a call to contract
pub struct CallOptions {
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 this should be called CallArgs – it's not really passing in options, is it? It's the actual arguments to the contract call.

address: Address,
data: Bytes
) -> Result<Bytes, String>;
/// Executes a transient call to a contract at given `BlockId`.
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 know what a "transient" call is: can you help me understand?

// You should have received a copy of the GNU General Public License
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.

/// Reporting config
Copy link
Collaborator

Choose a reason for hiding this comment

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

Regardless of where this ends up we need more docs here. What is its purpose, what do the variants mean, which engines is it relevant for etc.

@@ -109,11 +109,12 @@ impl TransactionFilter {
match version_u64 {
2 => {
let (data, decoder) = transact_acl::functions::allowed_tx_types::call(sender, to, value);
client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)
client.call_contract(BlockId::Hash(*parent_hash), CallOptions::new(contract_address, data))
.map_err(|e| e.to_string())
Copy link
Collaborator

Choose a reason for hiding this comment

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

:/

@@ -834,6 +834,19 @@ usage! {
"--max-round-blocks-to-import=[S]",
"Maximal number of blocks to import for each import round.",

["Reporting configuration"]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
["Reporting configuration"]
["Validator behaviour reporting"]

["Reporting configuration"]
ARG arg_benign_reporting: (Option<String>) = None, or |c: &Config| c.reporting.as_ref()?.benign_reporting.clone(),
"--benign_reporting=[force|call|disable]",
"AuRa benign reporting configuration.",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Document what the options mean. And defaults.


ARG arg_malicious_reporting: (Option<String>) = None, or |c: &Config| c.reporting.as_ref()?.malicious_reporting.clone(),
"--malicious_reporting=[force|call|disable]",
"AuRa malicious reporting configuration.",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Document what the options mean. And defaults.


ARG arg_report_cache_call_every: (u64) = 100u64, or |c: &Config| c.reporting.as_ref()?.cache_call_every.clone(),
"--report_cache_call_every=[BLOCK_NUM]",
"AuRa cache call report successfulness for specified amount if blocks.",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure I understand what this means.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A4-gotissues 💥 Pull request is reviewed and has significant issues which must be addressed. M4-core ⛓ Core client code / Rust.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reverted report validator transactions get added in block
6 participants