Skip to content

Commit

Permalink
Switches to using new eth_getLogs by blockHash RPC.
Browse files Browse the repository at this point in the history
This resolves a major source of pain with Blockstream, though it does mean that it depends on very new versions of Geth/Parity that have this functionality.
  • Loading branch information
MicahZoltu committed Aug 27, 2018
1 parent e3f0041 commit 80b6465
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 115 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ethereumjs-blockstream",
"version": "5.0.0",
"version": "6.0.0",
"description": "A library to turn an unreliable remote source of Ethereum blocks into a reliable stream of blocks with removals on re-orgs and backfills on skips.",
"main": "output/source/index.js",
"types": "output/source/index.d.ts",
Expand Down
11 changes: 1 addition & 10 deletions source/log-reconciler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Block } from "./models/block";
import { Log } from "./models/log";
import { Filter, FilterOptions } from "./models/filters";
import { LogHistory } from "./models/log-history";
import { List as ImmutableList } from "immutable";

export const reconcileLogHistoryWithAddedBlock = async <TBlock extends Block, TLog extends Log>(
getLogs: (filterOptions: FilterOptions) => Promise<TLog[]>,
Expand All @@ -14,15 +13,14 @@ export const reconcileLogHistoryWithAddedBlock = async <TBlock extends Block, TL
): Promise<LogHistory<TLog>> => {
logHistory = await logHistory;
const logs = await getFilteredLogs(getLogs, newBlock, filters);
ensureBlockhash(newBlock, logs);
logHistory = await addNewLogsToHead(logHistory, logs, onLogAdded);
logHistory = await pruneOldLogs(logHistory, newBlock, historyBlockLength);
return logHistory;
}

const getFilteredLogs = async <TBlock extends Block, TLog extends Log>(getLogs: (filterOptions: FilterOptions) => Promise<Array<TLog>>, newBlock: TBlock, filters: Array<Filter>): Promise<Array<TLog>> => {
const logPromises = filters
.map(filter => ({ fromBlock: newBlock.number, toBlock: newBlock.number, address: filter.address, topics: filter.topics, }))
.map(filter => ({ blockHash: newBlock.hash, address: filter.address, topics: filter.topics, }))
.map(filter => getLogs(filter));
const nestedLogs = await Promise.all(logPromises);
return nestedLogs.reduce((allLogs, logs) => allLogs.concat(logs), []);
Expand Down Expand Up @@ -62,13 +60,6 @@ const ensureOrder = <TLog extends Log>(headLog: TLog | undefined, newLog: TLog)
if (headLogIndex >= newLogIndex) throw new Error(`received log with same block number (${newLogBlockNumber}) but index (${newLogIndex}) is the same or older than previous index (${headLogIndex})`);
}

const ensureBlockhash = <TBlock extends Block, TLog extends Log>(block: TBlock, logs: Array<TLog>) => {
// FIXME: This technique for verifying we got the right logs will not work if there were no logs present in the block! This means it is possible to miss logs. Can be fixed once https://eips.ethereum.org/EIPS/eip-234 is implemented
logs.forEach(log => {
if (log.blockHash !== block.hash) throw new Error(`Received log for block hash ${log.blockHash} when asking for logs of block ${block.hash}.`);
});
}

export const reconcileLogHistoryWithRemovedBlock = async <TBlock extends Block, TLog extends Log>(
logHistory: LogHistory<TLog>|Promise<LogHistory<TLog>>,
removedBlock: TBlock,
Expand Down
3 changes: 1 addition & 2 deletions source/models/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ export interface Filter {
}

export interface FilterOptions extends Filter {
readonly fromBlock?: string;
readonly toBlock?: string;
readonly blockHash: string
}
12 changes: 6 additions & 6 deletions tests/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export function getLogsFactory(logsPerFilter: number, fork: string = "AAAA") {
const logs = [];
let logIndex = 0;
for (let i = 0; i < logsPerFilter; ++i) {
const blockNumber = parseInt(filterOptions.toBlock!, 16);
logs.push(new MockLog(blockNumber, logIndex++, fork));
const blockHash = filterOptions.blockHash;
logs.push(new MockLog(blockHash, logIndex++, fork));
}
return logs;
};
Expand Down Expand Up @@ -71,10 +71,10 @@ export class MockLog implements Log {
readonly data: string = "0x0000000000000000000000000000000000000000000000000000000000000000";
readonly topics: string[] = [];

constructor(blockNumber: number, logIndex: number = 0x0, fork: string = "AAAA") {
const blockNumberAsHex = blockNumber.toString(16);
this.blockNumber = "0x" + blockNumberAsHex;
this.blockHash = `0xbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0cbl0c${fork}${("0000" + blockNumberAsHex).substring(blockNumberAsHex.length)}`;
constructor(blockHash: string, logIndex: number = 0x0, fork: string = "AAAA") {
const blockNumber = parseInt(blockHash.substring(62), 16);
this.blockNumber = `0x${blockNumber.toString(16)}`;
this.blockHash = blockHash;
this.logIndex = `0x${logIndex.toString(16)}`;
this.transactionIndex = this.logIndex;
}
Expand Down
Loading

0 comments on commit 80b6465

Please sign in to comment.