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

Commit

Permalink
test: add tests and some fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Andres Adjimann committed Sep 21, 2022
1 parent 6d0170f commit e02c536
Show file tree
Hide file tree
Showing 4 changed files with 366 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ export default class BlockManager extends Manager<Block> {
return Quantity.from(tagOrBlockNumber);
}

// TODO: This won't work when we have a fallback/fork and it is
// TODO: called from api.eth_getBlockTransactionCountByHash
async getNumberFromHash(hash: string | Buffer | Tag) {
return this.#blockIndexes.get(Data.toBuffer(hash)).catch(e => {
if (e.status === NOTFOUND) return null;
Expand Down Expand Up @@ -295,6 +297,7 @@ export default class BlockManager extends Manager<Block> {
this.#blockIndexes.get(LATEST_INDEX_KEY).catch(e => null)
]);

// TODO: this must take into account fallback/fork.
if (earliest) this.earliest = earliest;

if (latestBlockNumber) {
Expand Down
52 changes: 33 additions & 19 deletions src/chains/ethereum/ethereum/src/data-managers/blocklog-manager.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { BlockLogs, FilterArgs } from "@ganache/ethereum-utils";
import { BlockLogs, FilterArgs, RangeFilterArgs, Tag } from "@ganache/ethereum-utils";
import { LevelUp } from "levelup";
import Manager from "./manager";
import { Quantity } from "@ganache/utils";
import Blockchain from "../blockchain";
import { parseFilter, parseFilterDetails } from "../helpers/filter-parsing";
import { parseFilter, parseFilterDetails, parseFilterRange } from "../helpers/filter-parsing";
import { Ethereum } from "../api-types";

export default class BlockLogManager extends Manager<BlockLogs> {
#blockchain: Blockchain;

constructor(base: LevelUp, blockchain: Blockchain) {
super(base, BlockLogs);
this.#blockchain = blockchain;
Expand All @@ -31,38 +32,51 @@ export default class BlockLogManager extends Manager<BlockLogs> {
async getLogs(filter: FilterArgs): Promise<Ethereum.Logs> {
const blockchain = this.#blockchain;
if ("blockHash" in filter) {
// TODO: revert back to getNumberFromHash (when they add support for fallback/forks)
const block = await blockchain.blocks.getByHash(filter.blockHash);
if (!block) return [];
const blockNumber = block.header.number;
const logs = await this.get(blockNumber.toBuffer());
const { addresses, topics } = parseFilterDetails(filter);
const blockNumber = await blockchain.blocks.getNumberFromHash(
filter.blockHash
);
if (!blockNumber) return [];

const logs = await this.get(blockNumber);
return logs ? [...logs.filter(addresses, topics)] : [];
}
const { addresses, topics, fromBlock, toBlock } = parseFilter(
filter,
blockchain
);
const from = Quantity.min(fromBlock, toBlock);
const rangeFilter = filter as RangeFilterArgs;

let { fromBlock, toBlock } = parseFilterRange(rangeFilter, blockchain);
const fork = this.#blockchain.fallback;
if (!fork) {
return await this.getLocal(from.toNumber(), toBlock.toNumber(), filter);
return await this.getLocal(fromBlock, toBlock, filter);
}
if (rangeFilter.fromBlock == Tag.earliest) {
fromBlock = await this.forkEarliest();
}
if (rangeFilter.toBlock == Tag.earliest) {
toBlock = await this.forkEarliest();
}
fromBlock = Quantity.min(fromBlock, toBlock);

const ret: Ethereum.Logs = [];
if (fork.isValidForkBlockNumber(from)) {
ret.push(...await this.getFromFork(from, Quantity.min(toBlock, fork.blockNumber), filter));
if (fork.isValidForkBlockNumber(fromBlock)) {
ret.push(...await this.getFromFork(fromBlock, Quantity.min(toBlock, fork.blockNumber), filter));
}
if (!fork.isValidForkBlockNumber(toBlock)) {
ret.push(...await this.getLocal(fork.blockNumber.toNumber() + 1, toBlock.toNumber(), filter));
const blockNumberPlusOne = Quantity.from(fork.blockNumber.toNumber() + 1);
ret.push(...await this.getLocal(Quantity.max(fromBlock, blockNumberPlusOne), toBlock, filter));
}
return ret;
}

getLocal(from: number, toBlockNumber: number, filter: FilterArgs): Promise<Ethereum.Logs> {
// TODO: Use block-manager earliest when fixed (currently it doesn't support fallback/fork correctly)
async forkEarliest() {
const fork = this.#blockchain.fallback;
const block = await fork.request<any>("eth_getBlockByNumber", [Tag.earliest, false], { disableCache: true });
return Quantity.from(block.number);
}

getLocal(from: Quantity, to: Quantity, filter: FilterArgs): Promise<Ethereum.Logs> {
const { addresses, topics } = parseFilter(filter, this.#blockchain);
const pendingLogsPromises: Promise<BlockLogs>[] = [];
for (let i = from; i <= toBlockNumber; i++) {
for (let i = from.toNumber(); i <= to.toNumber(); i++) {
pendingLogsPromises.push(this.get(Quantity.toBuffer(i)));
}
return Promise.all(pendingLogsPromises).then(blockLogsRange => {
Expand Down
16 changes: 16 additions & 0 deletions src/chains/ethereum/ethereum/tests/forking/contracts/Logs.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

contract Logs {
event Event(uint256 indexed first, uint256 indexed second);

constructor() {
emit Event(1, 2);
}

function logNTimes(uint8 n) public {
for (uint8 i = 0; i < n; i++) {
emit Event(i, i);
}
}
}
Loading

0 comments on commit e02c536

Please sign in to comment.