-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Resolve "Reverted report validator transactions get added in block #10580" #11030
base: master
Are you sure you want to change the base?
Resolve "Reverted report validator transactions get added in block #10580" #11030
Conversation
It looks like @VladLupashevskyi signed our Contributor License Agreement. 👍 Many thanks, Parity Technologies CLA Bot |
Hmm. I cant figure out why tests are failing. It seems that error is 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 |
…into val-call � Conflicts: � ethcore/src/client/client.rs
I think it's ready for review :) |
There was a problem hiding this 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)] |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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), | ||
} |
There was a problem hiding this comment.
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) {} |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
benign_reporting: Mutex<ValidatorReporting>, | ||
malicious_reporting: Mutex<ValidatorReporting>, |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
Thank you @VladLupashevskyi for the answers! For now, let's change the way |
…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
I was trying to change the way how @debris What do you think about this approach, would it make sense to extend |
} | ||
|
||
#[derive(Builder, Default, Clone)] | ||
#[builder(default)] |
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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`. |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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()) |
There was a problem hiding this comment.
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"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
["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.", |
There was a problem hiding this comment.
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.", |
There was a problem hiding this comment.
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.", |
There was a problem hiding this comment.
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.
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:
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