-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
feat(forge): fuzz dictionary #731
Conversation
@onbjerg something to consider for the REVM fuzzer. For Revm it should be easier, as we can lift the changelog per call and add it to the dictionary? |
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.
Great work. Minor nits.
state_weight: u32, | ||
random_weight: u32, |
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.
should this be under EvmOpts
? Should we make a builder that makes this struct easier to construct?
|
||
// Snapshot the state before the test starts running | ||
let pre_test_state = self.evm.borrow().state().clone(); | ||
|
||
let flattened_state = Rc::new(RefCell::new(self.evm.borrow().flatten_state())); | ||
|
||
// we dont shrink for state strategy |
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.
// we dont shrink for state strategy | |
// we dont shrink for state strategy because shrinking in a collection moves the iterator | |
// whereas here it doesn't make sense to shrink, given everything is a concrete value |
evm-adapters/src/fuzz.rs
Outdated
@@ -122,6 +160,19 @@ impl<'a, S, E: Evm<S>> FuzzedExecutor<'a, E, S> { | |||
} | |||
); | |||
|
|||
{ | |||
let new_flattened = evm.flatten_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.
let new_flattened = evm.flatten_state(); | |
// we extend the state dict with any returndata from the call in 32-byte chunks. | |
let new_flattened = evm.flatten_state(); |
) -> impl Strategy<Value = Bytes> { | ||
// We need to compose all the strategies generated for each parameter in all | ||
// possible combinations | ||
// let strategy = proptest::sample::select(state.clone().into_iter().collect::<Vec<[u8; |
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 strategy = proptest::sample::select(state.clone().into_iter().collect::<Vec<[u8; |
} else { | ||
// because of metadata bs, we may hit this codepath. just ignore it | ||
// and continue on |
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.
shouldn't be required?
} else { | |
// because of metadata bs, we may hit this codepath. just ignore it | |
// and continue on |
if let Some(code) = code { | ||
let mut i = 0; | ||
while i < code.len() { | ||
let wrapped_op = OpCode::from(Opcode(code[i])); |
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 OpCode
struct should probably have a direct from(x: u8)
method
}); | ||
} | ||
} | ||
for log in logs { |
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.
for log in logs { | |
// Flatten all log addresses, topics & data into H256 and write them to the dictionary | |
for log in logs { |
} | ||
} | ||
|
||
// we keep bytes as little endian |
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.
// we keep bytes as little endian | |
// Flatten the old and new account values & storage in H256 | |
// and insert them as little endian bytes in the dictionary |
Rolled into #985 |
Implements a fuzzing dictionary per #387
Takes a weighted union of 2 strategies, 40-60 weighted dictionary-random. Grabs state via a hack around the
deconstruct
method to get all state changes not applied (in our case, thats all of them), and flattens them into a hashset. We then pass this state hashset into the strategy creator which uses a selector to select a random value from the set as the input and transforms it into an inputSome limitations: bytes and strings types are only ever 32 bytes when pulling from state. probably improvements to be had there