Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
fix: evm_revert fails in some cases (#4136)
Browse files Browse the repository at this point in the history
Co-authored-by: Micaiah Reid <[email protected]>
Co-authored-by: David Murdoch <[email protected]>
  • Loading branch information
3 people authored Jan 9, 2023
1 parent a3ae75f commit 7de4695
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 34 deletions.
4 changes: 2 additions & 2 deletions src/chains/ethereum/ethereum/src/forking/trie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ export class ForkTrie extends GanacheTrie {
endBlockNumber: Quantity
) {
const db = this.metadataDB;
const stream = db.createReadStream({
const stream = db.createKeyStream({
gte: lexico.encode([startBlockNumber.toBuffer()]),
lt: lexico.encode([
Quantity.from(endBlockNumber.toBigInt() + 1n).toBuffer()
])
});
const batch = db.batch();
for await (const [key] of stream) {
for await (const key of stream) {
batch.del(key);
}
await batch.write();
Expand Down
97 changes: 65 additions & 32 deletions src/chains/ethereum/ethereum/tests/forking/forking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -825,31 +825,52 @@ describe("forking", function () {
); //sanity check
}
}

/**
* - Initializes `localProvider` as a fork of `remoteProvider`.
* - Sets `value1` to `localInitialValue` (if it is not null).
* - Creates a snapshot .
* - Iterates `snapshotValues`, setting `value1` to each of those values.
* - Reverts.
* - Ensures that `value1` has reverted to either `localInitialValue` or
* `remoteInitialValue` (if the `localInitialValue` was not provided).
*/
async function initializeSnapshotSetRevertThenTest(
initialValue: number,
remoteInitialValue: number,
localInitialValue: number | null,
snapshotValues: number[]
) {
const expectedValueAfterRevert =
localInitialValue == null ? remoteInitialValue : localInitialValue;

const { localProvider } = await startLocalChain(PORT, {
disableCache: true
});
const subId = await localProvider.send("eth_subscribe", ["newHeads"]);

// set value1 to {initialValue} (delete it)
await set(localProvider, 1, initialValue);
const message = await localProvider.once("message");
const initialBlockNumber = parseInt(
(message.data.result as any).number,
16
);
assert.strictEqual(
Quantity.from(
await get(localProvider, "value1", initialBlockNumber)
).toNumber(),
initialValue
); // sanity check
if (localInitialValue !== null) {
// set value1 to {initialValue} (note: if the value is `0` it actually deletes it from the state)
await set(localProvider, 1, localInitialValue);
await localProvider.once("message");

assert.strictEqual(
+(await get(
localProvider,
"value1",
await getBlockNumber(localProvider)
)),
localInitialValue
); // sanity check
}

const initialBlockNumber = await getBlockNumber(localProvider);

const snapId = await localProvider.send("evm_snapshot");
await testPermutations(localProvider, initialValue, snapshotValues);
await testPermutations(
localProvider,
expectedValueAfterRevert,
snapshotValues
);
await localProvider.send("evm_revert", [snapId]);

assert.strictEqual(
Expand All @@ -858,21 +879,23 @@ describe("forking", function () {
); // sanity check

assert.strictEqual(
Quantity.from(
await get(localProvider, "value1", initialBlockNumber)
).toNumber(),
initialValue,
+(await get(localProvider, "value1", initialBlockNumber)),
expectedValueAfterRevert,
"value was not reverted to `initialValue` after evm_revert"
);

// Finally, check all permutations outside of the snapshot/revert to
// make sure deleted state was properly reverted
await testPermutations(localProvider, initialValue, snapshotValues);
await testPermutations(
localProvider,
expectedValueAfterRevert,
snapshotValues
);

await localProvider.send("eth_unsubscribe", [subId]);
}

const initialValues = [0, 1];
const initialValues = [null, 0, 1]; // null means to _not_ set an initial value
// test all permutations of values: 0, 1, 2
const permutations = [
[0],
Expand Down Expand Up @@ -900,20 +923,30 @@ describe("forking", function () {
const subId = await remoteProvider.send("eth_subscribe", [
"newHeads"
]);
// set the remoteProvider's value1 initialValue to {remoteInitialValue}
await set(remoteProvider, 1, remoteInitialValue);
const message = await remoteProvider.once("message");
await remoteProvider.send("eth_unsubscribe", [subId]);
const blockNumber = parseInt(
(message.data.result as any).number,
16
// set the remoteProvider's value1 initialValue to {remoteInitialValue} (only if not null)
if (remoteInitialValue !== null) {
await set(remoteProvider, 1, remoteInitialValue);
await remoteProvider.once("message");
await remoteProvider.send("eth_unsubscribe", [subId]);
const blockNumber = await getBlockNumber(remoteProvider);
assert.strictEqual(
parseInt(
await get(remoteProvider, "value1", blockNumber),
16
),
remoteInitialValue
); // sanity check to make sure our initial conditions are correct
}

const blockNumber = await getBlockNumber(remoteProvider);
const startValue = await get(
remoteProvider,
"value1",
blockNumber
);
assert.strictEqual(
parseInt(await get(remoteProvider, "value1", blockNumber), 16),
remoteInitialValue
); // sanity check to make sure our initial conditions are correct

await initializeSnapshotSetRevertThenTest(
+startValue,
initialValue,
permutation
);
Expand Down

0 comments on commit 7de4695

Please sign in to comment.