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

Fix forked transaction trace storage so it returns the correct data and doesn't modify the root trie #398

Merged
merged 14 commits into from Apr 5, 2019

Conversation

davidmurdoch
Copy link
Member

@davidmurdoch davidmurdoch commented Mar 26, 2019

This should fix /issues/439 and #362.


callback();
});
BlockchainDouble.prototype.initialize.call(self, accounts, callback);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: we don't need to call patchVm since it already gets called within createVMFromStateTrie.

@@ -107,7 +101,7 @@ ForkedBlockchain.prototype.createGenesisBlock = function(callback) {

// Update the relevant block numbers
self.forkBlockNumber = self.options.fork_block_number = blockNumber;
self.stateTrie.forkBlockNumber = blockNumber;
self.stateTrie.forkBlockNumber = self.stateTrie.options.forkBlockNumber = blockNumber;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: The stateTrie is now copyed instead of created via new ForkedStorageTrie (this aligns with how the merkle patricia trie does it internally). When copying we need to also copy the options object, so here I am making sure the forkBlockNumber is set on the object.

return callback(null, this.storageTrieCache[address]);
}
ForkedBlockchain.prototype.getLookupStorageTrie = function(stateTrie, lookupAccount) {
lookupAccount = lookupAccount || this.getLookupAccount(stateTrie);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: getLookupStorageTrie is usually called when the ephemeralVm is created; when that happens, we already have a lookupAccount fn generated, so we used that. There are other ways to call getLookupStorageTrie and those don't have (easy) access to a valid lookupAccount fn. So sometimes we have to create it.

ForkedBlockchain.prototype.getLookupStorageTrie = function(stateTrie, lookupAccount) {
lookupAccount = lookupAccount || this.getLookupAccount(stateTrie);
return (address, callback) => {
const storageTrie = stateTrie.copy();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: DRY and in-line with the way the MPT lib does it.

lookupAccount = lookupAccount || this.getLookupAccount(stateTrie);
return (address, callback) => {
const storageTrie = stateTrie.copy();
storageTrie.address = address;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: ForkedStorageTrie needs the address.

@@ -161,7 +145,8 @@ ForkedBlockchain.prototype.isFallbackBlock = function(value, callback) {
};

ForkedBlockchain.prototype.isBlockHash = function(value) {
return typeof value === "string" && value.indexOf("0x") === 0 && value.length > 42;
const isHash = typeof value === "string" && value.indexOf("0x") === 0 && value.length > 42;
return isHash || (Buffer.isBuffer(value) && value.byteLength > 20);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: Sometimes the value is a Buffer and we obviously should check the buffer to see if it big enough to be a blockhash.

@@ -171,6 +156,10 @@ ForkedBlockchain.prototype.isFallbackBlockHash = function(value, callback) {
return callback(null, false);
}

if (Buffer.isBuffer(value)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: blockHashes.get, below, only allows hex strings.

var self = this;

this.isFallbackBlockHash(number, function(err, isFallbackBlockHash) {
let checkFn;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: simplifying some of the code, which also eliminates from duplicate checks.

});
};

ForkedBlockchain.prototype.getStorage = function(address, key, number, callback) {
this.lookupStorageTrie(address, function(err, trie) {
this.getLookupStorageTrie(this.stateTrie)(address, (err, trie) => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: Make sure we use the new and improved storage trie instead of the old and busted one (which has been removed)

return trie;
};

ForkedBlockchain.prototype.lookupStorageTrie = function(address, callback) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: we have a better one now. And the cache is mostly unnecessary as it complicates things (like when the stateTrie root is from a previous block but the cache contains data from a newer block) and the cache is already properly handled in the VM, which most of the calls to this fn come from.

@@ -327,6 +303,28 @@ ForkedBlockchain.prototype.getCode = function(address, number, callback) {
});
};

ForkedBlockchain.prototype.getLookupAccount = function(trie) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: we needed to be able to lookup an account based on a trie, not a block number.

@@ -640,33 +638,4 @@ ForkedBlockchain.prototype.getBlockLogs = function(number, callback) {
});
};

ForkedBlockchain.prototype._checkpointTrie = function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: These don't get used.

@@ -70,12 +58,14 @@ ForkedStorageTrie.prototype.get = function(key, blockNumber, callback) {
callback(null, account.serialize());
});
} else {
if (to.number(blockNumber) > to.number(self.forkBlockNumber)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: Whenever we go to the main chain we shouldn't use a block number after we forked because that data is not valid for us.

// Note: For some reason, naming this function checkpoint()
// -- overriding the default function -- prevents it from
// being called.
ForkedStorageTrie.prototype.customCheckpoint = function() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change: These were never used.

var utils = require("ethereumjs-util");
var inherits = require("util").inherits;
var Web3 = require("web3");
var to = require("./to.js");

inherits(ForkedStorageTrie, MerklePatriciaTree);
inherits(ForkedStorageBaseTrie, BaseTrie);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason for change:

Most of these changes are just code reorg. We now have a "Base" trie and our normal trie. This is just to align with the MPT implementation. I wanted to use the copy mechanism, but couldn't do so without this small refactor... because of reasons (things crashed).

@davidmurdoch davidmurdoch force-pushed the fix-forked-transaction-trace-storage branch from 3371016 to 73e5982 Compare March 26, 2019 17:07
Copy link
Contributor

@nicholasjpaterno nicholasjpaterno left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't quite had the bandwidth to give this the type of review it may require, but I have read through a few times and everything seems to LGTM! Happy to approve for now, we can talk more if you're not feeling 💯 about any part of this otherwise :shipit:!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants