diff --git a/src/chains/ethereum/ethereum/src/blockchain.ts b/src/chains/ethereum/ethereum/src/blockchain.ts index f31e7c3288..8614fc024c 100644 --- a/src/chains/ethereum/ethereum/src/blockchain.ts +++ b/src/chains/ethereum/ethereum/src/blockchain.ts @@ -328,8 +328,14 @@ export default class Blockchain extends Emittery { options.miner.blockGasLimit, initialAccounts ); - blocks.earliest = blocks.latest = - await this.#blockBeingSavedPromise.then(({ block }) => block); + blocks.latest = await this.#blockBeingSavedPromise.then( + ({ block }) => block + ); + // when we are forking, blocks.earliest is already set to what was + // retrieved from the fork + if (!blocks.earliest) { + blocks.earliest = blocks.latest; + } } } diff --git a/src/chains/ethereum/ethereum/src/data-managers/block-manager.ts b/src/chains/ethereum/ethereum/src/data-managers/block-manager.ts index 551d38740d..e30eef0b5d 100644 --- a/src/chains/ethereum/ethereum/src/data-managers/block-manager.ts +++ b/src/chains/ethereum/ethereum/src/data-managers/block-manager.ts @@ -15,6 +15,7 @@ import { TypedDatabaseTransaction } from "@ganache/ethereum-transaction"; import { GanacheLevelUp } from "../database"; +import { Ethereum } from "../api-types"; const LATEST_INDEX_KEY = BUFFER_ZERO; @@ -274,17 +275,39 @@ export default class BlockManager extends Manager { await this.#blockIndexes.put(LATEST_INDEX_KEY, number); } + async getEarliest() { + const fallback = this.#blockchain.fallback; + if (fallback) { + const json = await fallback.request>( + "eth_getBlockByNumber", + [Tag.earliest, true], + // TODO: re-enable cache once this is fixed + // https://github.com/trufflesuite/ganache/issues/3773 + { disableCache: true } + ); + if (json) { + const common = fallback.getCommonForBlockNumber( + this.#common, + BigInt(json.number) + ); + return new Block(BlockManager.rawFromJSON(json, common), common); + } + } else { + // if we're forking, there shouldn't be an earliest block saved to the db, + // it's always retrieved from the fork + for await (const data of this.base.createValueStream({ limit: 1 })) { + return new Block(data as Buffer, this.#common); + } + } + } + /** * Updates the this.latest and this.earliest properties with data * from the database. */ async updateTaggedBlocks() { const [earliest, latestBlockNumber] = await Promise.all([ - (async () => { - for await (const data of this.base.createValueStream({ limit: 1 })) { - return new Block(data as Buffer, this.#common); - } - })(), + this.getEarliest(), this.#blockIndexes.get(LATEST_INDEX_KEY).catch(e => null) ]); diff --git a/src/chains/ethereum/ethereum/tests/forking/block.test.ts b/src/chains/ethereum/ethereum/tests/forking/block.test.ts index 500e8047bc..296d535683 100644 --- a/src/chains/ethereum/ethereum/tests/forking/block.test.ts +++ b/src/chains/ethereum/ethereum/tests/forking/block.test.ts @@ -40,6 +40,22 @@ describe("forking", function () { assert.deepStrictEqual(block.parentHash, remoteBlock.hash); }); + it("after initialization our earliest block should be the fork earliest block, parentHash should match", async () => { + const res = await request.post(URL).send({ + jsonrpc: "2.0", + id: "1", + method: "eth_getBlockByNumber", + params: ["earliest", true] + }); + const remoteBlock = JSON.parse(res.text).result; + const block = await provider.send("eth_getBlockByNumber", [ + "earliest", + true + ]); + assert.deepStrictEqual(parseInt(block.number), parseInt(remoteBlock.number)); + assert.deepStrictEqual(block.hash, remoteBlock.hash); + }); + //todo: reinstate this test after https://github.com/trufflesuite/ganache/issues/3616 is fixed it.skip("should get a block from the original chain", async () => { const res = await request.post(URL).send({