-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[comparison-testing-tool] Add more features to the comparison testing tool #11890
[comparison-testing-tool] Add more features to the comparison testing tool #11890
Conversation
⏱️ 24h 1m total CI duration on this PR
🚨 2 jobs on the last run were significantly faster/slower than expected
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #11890 +/- ##
=========================================
- Coverage 63.9% 63.9% -0.1%
=========================================
Files 807 807
Lines 178311 178334 +23
=========================================
Hits 114052 114052
- Misses 64259 64282 +23 ☔ View full report in Codecov by Sentry. |
dc11dbd
to
47e7195
Compare
8d22bcb
to
8269ec9
Compare
Can you add an command example to use the |
target_account: Option<AccountAddress>, | ||
}, | ||
/// Online execution | ||
Online { |
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.
Hmm I wasn't quite sure what this command means. Can you add more description on what this would do?
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.
Sorry for the confusion. With this command, the tool does not need to dump the state. Instead, it will try to get each txn, use DebuggerStateView the get the state, except for the code, which is obtained from compilation of the source code and load it to the code state. The logic is defined in data_state_view.rs in this PR.
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 your explanation can go to the comment instead of /// Online execution
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.
done
aptos-move/e2e-tests/src/executor.rs
Outdated
) | ||
.unwrap(); | ||
let mut session = vm.new_session(&resolver, SessionId::void()); | ||
|
||
let mut session = vm.new_session_with_flush_flag(resolver, SessionId::void(), true); |
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.
Hmm the logic indeed looks pretty weird to me. Ideally I would avoid making changes in the MoveVM but would like to understand the problem here a bit better.
Looking at the code, the MoveVM will be spawned fresh in line 1008. The only thing that was cached previously is the WarmVMCache
which would probably cache the previous version of Aptos Framework. Is that the code you were having issue with? i.e: the older version of aptos framework is being loaded and cause execution problem?
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.
Yeah... Currently, the tool executes v1 and then v2 for each txn. After execution of v1 code, we need to reload the aptos framework compiled by v2.
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 take is we should avoid making changes here in the Move VM. Instead, we should look into how to invalidate this WarmVMCache on a framework upgrade. This is the logic the real VM is doing in the node as well so shouldn't be something new.
self.new_session_with_flush_flag(resolver, session_id, false) | ||
} | ||
|
||
pub fn new_session_with_flush_flag<'r, S: AptosMoveResolver>( |
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 why this flag is useful? Otherwise we have different APIs for sessions which are created differently. Also, what you can do instead is to have new_clean_session
which has the implementation with must_flush = true
. This way you can make this function debugger-only (mark as a cfg feature?)
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 having a private new_session_impl
and then wrapping new_session
and new_clean_session
seems cleaner than having one public API call some other public API?
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.
done
types/src/state_store/state_key.rs
Outdated
match self.inner() { | ||
StateKeyInner::AccessPath(access_path) => { | ||
!access_path.path.is_empty() | ||
&& access_path.path[0] == CODE_TAG |
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 you can check if access path is code using is_code
function?
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.
done
types/src/state_store/state_key.rs
Outdated
@@ -154,6 +154,20 @@ impl StateKey { | |||
pub fn get_shard_id(&self) -> u8 { | |||
CryptoHash::hash(self).nibble(0) | |||
} | |||
|
|||
pub fn is_aptos_path(&self) -> bool { |
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.
nit: is_aptos_code
or similar? so that the function name describes we process modules
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.
done
@@ -15,13 +15,17 @@ use std::{convert::TryFrom, fmt, str::FromStr}; | |||
pub struct AccountAddress([u8; AccountAddress::LENGTH]); | |||
|
|||
impl AccountAddress { | |||
/// Hex address: 0x4 | |||
pub const FOUR: Self = Self::get_hex_address_four(); |
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.
Why not ordering constants for addresses like 1,2,3,4?😄
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.
Yeah, it is currently order by the alphabet so four is the first one. I will change that
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.
done
} | ||
|
||
fn get_usage(&self) -> StateViewResult<StateStorageUsage> { | ||
unimplemented!() |
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.
nit: unreachable!()
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.
done
|
||
pub struct DataStateView { | ||
debugger_view: DebuggerStateView, | ||
code_data: Option<FakeDataStore>, |
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.
Why use FakeDataStore
? What does this code data do? I see we pass it into new
but how it gets populated?
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.
Sorry for the confusion. DataStateView is currently used in two places: 1) in the dump mode, I used data_read_state_keys to store the data state value, which is then dumped to the file; 2) in the online mode, I use code_data to store the bytecode compiled by V1 and V2, whenever a txn is obtained, I will use debugger_view + code_data to execute the txn. It is used in the get_state_value
function as long as it is not none
) -> Option<Result<(WriteSet, Vec<ContractEvent>), VMStatus>> { | ||
let executor = FakeExecutor::no_genesis(); | ||
let mut executor = executor.set_not_parallel(); | ||
*executor.data_store_mut() = state.clone(); | ||
*executor.data_store_mut() = state; |
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 we overwrite default data created by FakeExecutor
with empty state?
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.
yes, it happens in the online execution mode
return Some(executor.try_exec_entry_with_resolver( | ||
senders, | ||
entry_function, | ||
&executor.data_store().clone().as_move_resolver(), |
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.
Why? try_exec would use executor.data_store() and modify it, so I guess the main problem here us that you want to run something multiple times from the same state (and "uncommit") any modifications?
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.
In the current design, each txn has its own state so the corresponding state is only run once without any modifications. In the offline execution mode, the data state is from the file (obtained in the dump mode). In the online execution mode, the data state is from DebuggerStateView.
@rahxephon89 left a few (relevant and not so relevant) comments, but for my understanding, why we use We have an API inside a vm to run a block of txns on top of |
Thanks for pointing this out, @georgemitenkov! There are some APIs that I don't understand well so I have not used them. We can discuss more offline. |
299e209
to
59e0971
Compare
) -> Option<Result<(WriteSet, Vec<ContractEvent>), VMStatus>> { | ||
let executor = FakeExecutor::no_genesis(); | ||
let mut executor = executor.set_not_parallel(); | ||
*executor.data_store_mut() = state.clone(); |
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 think we need a FakeExecutor here, why not just do AptosVM::execute_block_no_limit(&vec![txn], &state)
? Then you avoid coupling the execution with data state, and can use whatever state
you want, either using V1 code or V2 code
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.
Plus our testing is a mess, I would trust execute_block_no_limit
API more than exec_...
variants
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 benefit of this API is that it 1) doesn't commit to state, so you can reuse the same state version for multiple executions, and 2) all things like aggregators are handled
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.
Thanks for the advice, @georgemitenkov. One concern I have is that for early txns, VM_BINARY_FORMAT_V6 is not enabled but the compiler only generates V6 bytecode. Is there a way to solve this issue?
59e0971
to
473c552
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
0806120
to
14b9e82
Compare
14b9e82
to
5803bee
Compare
5803bee
to
9cb17be
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
✅ Forge suite
|
✅ Forge suite
|
Description
This PR:
cargo run --begin-version <BEGIN_VERSION> --limit <LIMIT> dump --target-account <account-address> ...
online
to execute transactions without dumping the pre-state data; usage:cargo run --begin-version <BEGIN_VERSION> --limit <LIMIT> online [OPTIONS] <ENDPOINT> [OUTPUT_PATH]
Usage:
Test Plan
Manual test