-
Notifications
You must be signed in to change notification settings - Fork 841
feat: bus mapping for sload and sstore #418
feat: bus mapping for sload and sstore #418
Conversation
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 just reviewed SSTORE
opcode implementation in bus-mapping and some other stuff you added but stopped due to:
-
The PR is marked as Ready for Review but is not up to date with
main
. That basically causes that you haven't synced with Modularize mock crate for easier and more customizable testing setup generation #349 and therefore, you've implemented a test-utils module which should most probably be removed. -
Also, the tests for SSTORE are missing a lot of different cases which are only testeable with the additions to
mock
crate inmain
.
My suggestion:
- Remove all of the test-utils you've introduced in this PR (makes the review much more complex as there are a lot of files and different topics to review/address) when in theory the PR just wants to implement SSTORE and SLOAD bus-mapping opcodes.
- The circuit impl is only done for SSTORE. Either you add both or none and do it in another follow-up PR.
Before introducing test-suit/mock changes or new utils, please, file an issue before so that this does not happen again and work is lost or unusable.
Also, make sure that the PRs are more atomic. As otherways, the review time that consumes is massive and not so productive.
Thanks. Carlos.
@@ -1466,6 +1460,7 @@ impl<'a> CircuitInputBuilder { | |||
|
|||
for (index, geth_step) in geth_trace.struct_logs.iter().enumerate() { | |||
let mut state_ref = self.state_ref(&mut tx, &mut tx_ctx); | |||
log::trace!("handle {}th opcode {:?} ", index, geth_step.op); |
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 prefer tokio/tracing for these things. But maybe it's not the best option.
Maybe @ed255 has some suggestions
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'm happy with using the log crate here, it's very lightweight and if logs aren't activated they don't add any performance penalty as far as I know. I don't know about tokio/tracing so I can't comment on that.
// Fields with transaction lifespan, will be clear in `clear_access_list_and_refund`. | ||
access_list_account: HashSet<Address>, | ||
access_list_account_storage: HashSet<(Address, U256)>, | ||
// `dirty_storage` constains writes during current transaction. |
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.
// `dirty_storage` constains writes during current transaction. | |
// `dirty_storage` contains writes during current transaction. |
#[serde(default)] | ||
refund: Gas, |
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.
Maybe add a comment to highlight that this does not pertain to the original GethExecStepInternal
(alias StructLogs in Geth) and that it has been only added to allow compilation. As the only place where this is needed is in GethExecStep
.
Also, maybe an Option<Gas>
type makes everything easier IDK. And you just need to add it in GethExecStep
without touching the internal one.
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.
BTW, how was this working before that PR if we did not have this field in the struct??
Has it appeared after the change to latest
for the geth version used??
@@ -1,7 +1,7 @@ | |||
version: '3' | |||
services: | |||
geth0: | |||
image: "ethereum/client-go:stable" | |||
image: "ethereum/client-go:latest" |
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.
Are we sure about that? Note that Geth is now with the integration of the merge and ETH2 so I'm not sure if we want all that stuff inside in our tests now.
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.
Is there any reason specific to that PR that requires the latest version?
#[cfg(test)] | ||
#[ctor::ctor] | ||
fn init_env_logger() { | ||
// Enable RUST_LOG during tests | ||
env_logger::init(); | ||
} |
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.
2 concerns about this:
- Can we make it feature-dependant? I'm not sure if we will always want to print all the logs for all the tests as we will not see anything else than logs and the stdout will explode really quickly.
- Why
ctor
as opposite tolazy_static
+ initialization function? Is it a common practice?
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 understand the concerns here!
For the first point, this would be a dev feature right? I don't think rust supports dev features though (I don't think we should expose a public feature that starts the env_logger, as that's a decision that must be made by the consumer of the library). Nevertheless, for the concern about having lots of outputs by default, we could mitigate this by setting the default log level to error
, and then via the RUST_LOG
env var you can dynamically enable lower levels.
For the second point, I find the usage of ctor
interesting, because it guarantees that env_logger::init()
is called once always in tests at the beginning, without requiring updating the tests themselves. Using lazy_static
would require that every test function calls a setup function (or use a crate that handles test setup, but in any case we still need to add 1 line for each test function, which is cumbersome).
let geth_step = &geth_steps[0]; | ||
let mut exec_step = state.new_step(geth_step)?; | ||
|
||
let _call_id = state.call()?.call_id; |
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.
If not used, remove this.
let value_prev = *value_prev; | ||
let (_, committed_value) = state.sdb.get_committed_storage(&contract_addr, &key); | ||
let committed_value = *committed_value; |
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.
let value_prev = *value_prev; | |
let (_, committed_value) = state.sdb.get_committed_storage(&contract_addr, &key); | |
let committed_value = *committed_value; | |
let value_prev = value_prev.clone(); | |
let (_, committed_value) = state.sdb.get_committed_storage(&contract_addr, &key); | |
let committed_value = committed_value.clone(); |
Make the clones explicit please.
value: true, | ||
value_prev: is_warm, |
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.
use pretty_assertions::assert_eq; | ||
|
||
#[test] | ||
fn sstore_opcode_impl() { |
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 test is missing several things IMO:
- Refund logic was added to the crate but is never tested to be working correctly. I think SSTORE should have a testcase where it does not only write but also plays with the refund.
- We should also add testcases for
COLD
&WARM
situations. - This should be using the
mock::TestContext
helpers added in Modularize mock crate for easier and more customizable testing setup generation #349.
Please take a look to it and how to use it and it will allow you to perform all the testing you need.
So we cannot reopen this.... sorry .. will open a pr |
…merged into `ErrorOutOfGasMemoryCopy`. (privacy-scaling-explorations#418)
Some explanation:
dirty_storage
is added to statedb.rs, just like StateDB in go-ethereum.refund
in trace