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

Commit

Permalink
WIP - resolve common from blocknumber+timestamp, where it's not avail…
Browse files Browse the repository at this point in the history
…able, just fetch from the fork ¯\_(ツ)_/¯
  • Loading branch information
jeffsmale90 committed Jun 22, 2023
1 parent 20167dc commit 4ffc97f
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 53 deletions.
10 changes: 2 additions & 8 deletions src/chains/ethereum/ethereum/src/blockchain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1116,10 +1116,7 @@ export default class Blockchain extends Emittery<BlockchainTypedEvents> {
const to = hasToAddress ? new Address(transaction.to.toBuffer()) : null;

const common = this.fallback
? this.fallback.getCommonForBlockNumber(
this.common,
BigInt(transaction.block.header.number.toString())
)
? this.fallback.getCommonForBlock(this.common, transaction.block.header)
: this.common;

const gasLeft =
Expand Down Expand Up @@ -1253,10 +1250,7 @@ export default class Blockchain extends Emittery<BlockchainTypedEvents> {
} as any;

const common = this.fallback
? this.fallback.getCommonForBlockNumber(
this.common,
BigInt(block.header.number.toString())
)
? this.fallback.getCommonForBlock(this.common, block.header)
: this.common;

// TODO: prefixCodeHashes should eventually be conditional
Expand Down
39 changes: 23 additions & 16 deletions src/chains/ethereum/ethereum/src/data-managers/block-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
BlockRawTransaction,
EthereumRawBlock,
EthereumRawBlockHeader,
GanacheRawBlock,
Head,
serialize,
WithdrawalRaw
Expand All @@ -21,7 +22,7 @@ import {
} from "@ganache/ethereum-transaction";
import { GanacheLevelUp } from "../database";
import { Ethereum } from "../api-types";
import { encode } from "@ganache/rlp";
import { decode, encode } from "@ganache/rlp";

const LATEST_INDEX_KEY = BUFFER_ZERO;

Expand Down Expand Up @@ -171,10 +172,10 @@ export default class BlockManager extends Manager<Block> {
if (json == null) {
return null;
} else {
const common = fallback.getCommonForBlockNumber(
this.#common,
BigInt(json.number)
);
const common = fallback.getCommonForBlock(this.#common, {
number: BigInt(json.number),
timestamp: BigInt(json.timestamp)
});

return BlockManager.rawFromJSON(json, common);
}
Expand Down Expand Up @@ -226,12 +227,13 @@ export default class BlockManager extends Manager<Block> {
true
]);
if (json) {
const blockNumber = BigInt(json.number);
if (blockNumber <= fallback.blockNumber.toBigInt()) {
const common = fallback.getCommonForBlockNumber(
this.#common,
blockNumber
);
const number = BigInt(json.number);
const timestamp = BigInt(json.timestamp);
if (number <= fallback.blockNumber.toBigInt()) {
const common = fallback.getCommonForBlock(this.#common, {
number,
timestamp
});
return new Block(BlockManager.rawFromJSON(json, common), common);
}
}
Expand Down Expand Up @@ -272,9 +274,14 @@ export default class BlockManager extends Manager<Block> {
if (fallback) {
const block = await this.fromFallback(blockNumber);
if (block) {
const header: EthereumRawBlockHeader =
decode<GanacheRawBlock>(block)[0];
return new Block(
block,
fallback.getCommonForBlockNumber(common, blockNumber.toBigInt())
fallback.getCommonForBlock(common, {
number: blockNumber.toBigInt(),
timestamp: Quantity.toBigInt(header[11])
})
);
}
}
Expand Down Expand Up @@ -319,10 +326,10 @@ export default class BlockManager extends Manager<Block> {
{ disableCache: true }
);
if (json) {
const common = fallback.getCommonForBlockNumber(
this.#common,
BigInt(json.number)
);
const common = fallback.getCommonForBlock(this.#common, {
number: BigInt(json.number),
timestamp: BigInt(json.timestamp)
});
return new Block(BlockManager.rawFromJSON(json, common), common);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,17 @@ export default class TransactionManager extends Manager<NoOp> {
index.toBuffer(),
Quantity.toBuffer(tx.gasPrice)
];
const common = fallback.getCommonForBlockNumber(
fallback.common,
blockNumber.toBigInt()
);
const block = await fallback.request<any>("eth_getBlockByNumber", [
blockNumber.toString(),
false
]);
if (block == null) return null;

const common = fallback.getCommonForBlock(fallback.common, {
number: blockNumber.toBigInt(),
timestamp: Quantity.toBigInt(block.timestamp)
});

const runTx = TransactionFactory.fromRpc(tx, common, extra);
return runTx.serializeForDb(blockHash, blockNumber, index);
};
Expand Down
14 changes: 10 additions & 4 deletions src/chains/ethereum/ethereum/src/forking/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,16 @@ export class ForkCache extends Cache {
* Looks up address in underlying trie.
* @param address - Address of account
*/
const lookupAccount = async (address: Address) => {
const lookupAccount: (
address: Address
) => Promise<Account | undefined> = async (address: Address) => {
const rlp = await (trie as ForkTrie).get(address.buf);
return rlp ? Account.fromRlpSerializedAccount(rlp) : new Account();
}
super({ getCb: lookupAccount, putCb: trie.put.bind(trie), deleteCb: trie.del.bind(trie) });
return rlp ? Account.fromRlpSerializedAccount(rlp) : undefined;
};
super({
getCb: lookupAccount,
putCb: trie.put.bind(trie),
deleteCb: trie.del.bind(trie)
});
}
}
46 changes: 25 additions & 21 deletions src/chains/ethereum/ethereum/src/forking/fork.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,12 @@ export class Fork {
cacheProm,
this.#setCommonFromChain(chainIdPromise)
]);
const common = this.getCommonForBlockNumber(
this.common,
this.blockNumber.toBigInt()
);

const blockFromFallback = await fetchBlock(this, this.blockNumber);
const timestamp = BigInt(blockFromFallback.timestamp);
const number = BigInt(blockFromFallback.number);

const common = this.getCommonForBlock(this.common, { timestamp, number });
this.block = new Block(BlockManager.rawFromJSON(block, common), common);
if (!chainOptions.time && minerOptions.timestampIncrement !== "clock") {
chainOptions.time = new Date(
Expand All @@ -238,6 +240,7 @@ export class Fork {
1000
);
}

if (cache) await this.initCache(cache);
}
private async initCache(cache: PersistentCache) {
Expand Down Expand Up @@ -275,18 +278,11 @@ export class Fork {
: this.blockNumber;
}

/**
* If the `blockNumber` is before our `fork.blockNumber`, return a `Common`
* instance, applying the rules from the remote chain's `common` via its
* original `chainId`. If the remote chain's `chainId` is now "known", return
* a `Common` with our local `common`'s rules applied, but with the remote
* chain's `chainId`. If the block is greater than or equal to our
* `fork.blockNumber` return `common`.
* @param common -
* @param blockNumber -
*/
public getCommonForBlockNumber(common: Common, blockNumber: BigInt) {
if (blockNumber <= this.blockNumber.toBigInt()) {
public getCommonForBlock(
common: Common,
block: { number: bigint; timestamp: bigint }
): Common {
if (block.number <= this.blockNumber.toBigInt()) {
// we are at or before our fork block

let forkCommon: Common;
Expand All @@ -295,11 +291,19 @@ export class Fork {
let hardfork;
// hardforks are iterated from earliest to latest
for (const hf of common.hardforks()) {
if (hf.block === null) continue;
if (blockNumber >= BigInt(hf.block)) {
hardfork = hf.name;
} else {
break;
if (hf.timestamp) {
const hfTimestamp = BigInt(hf.timestamp);
if (block.timestamp >= hfTimestamp) {
hardfork = hf.name;
} else {
break;
}
} else if (hf.block) {
if (block.number >= BigInt(hf.block)) {
hardfork = hf.name;
} else {
break;
}
}
}
forkCommon = new Common({ chain: this.chainId, hardfork });
Expand Down

0 comments on commit 4ffc97f

Please sign in to comment.