UNPKG

@tevm/utils

Version:

A custom implementation of ethereumjs blockchain

105 lines (93 loc) 2.92 kB
// This is adapted from @ethereumjs/vm package not the @ethereumjs/util package import { DefensiveNullCheckError, InvalidBytesSizeError } from '@tevm/errors' import { hexToBytes, keccak256 } from './viem.js' const zeros = (bytes: number): Uint8Array => { return new Uint8Array(bytes) } const BYTE_SIZE = 256 /** * A simple Bloom filter implementation originally from ethereumjs */ export class Bloom { bitvector: Uint8Array /** * Represents a Bloom filter. * @throws {InvalidBytesSizeError} If the byte size of the bitvector is not 256. */ constructor(bitvector?: Uint8Array) { if (!bitvector) { this.bitvector = zeros(BYTE_SIZE) } else { if (bitvector.length !== BYTE_SIZE) throw new InvalidBytesSizeError(BYTE_SIZE, bitvector.length) this.bitvector = bitvector } } /** * Adds an element to a bit vector of a 64 byte bloom filter. * @param e - The element to add * @throws {never} */ add(e: Uint8Array) { const eBytes = hexToBytes(keccak256(e)) const mask = 2047 // binary 11111111111 for (let i = 0; i < 3; i++) { const first2bytes = new DataView(eBytes.buffer).getUint16(i * 2) const loc = mask & first2bytes const byteLoc = loc >> 3 const bitLoc = 1 << (loc % 8) let item = this.bitvector[BYTE_SIZE - byteLoc - 1] if (item === undefined) { throw new DefensiveNullCheckError('item is not defined. There is a bug in the implementation') } item |= bitLoc this.bitvector[BYTE_SIZE - byteLoc - 1] = item } } /** * Checks if an element is in the bloom. * @param e - The element to check * @throws {never} */ check(e: Uint8Array): boolean { const eBytes = hexToBytes(keccak256(e)) const mask = 2047 // binary 11111111111 let match = true for (let i = 0; i < 3 && match; i++) { const first2bytes = new DataView(eBytes.buffer).getUint16(i * 2) const loc = mask & first2bytes const byteLoc = loc >> 3 const bitLoc = 1 << (loc % 8) const item = this.bitvector[BYTE_SIZE - byteLoc - 1] if (item === undefined) { throw new DefensiveNullCheckError('item is not defined. There is a bug in the implementation') } match = (item & bitLoc) !== 0 } return Boolean(match) } /** * Checks if multiple topics are in a bloom. * @returns `true` if every topic is in the bloom * @throws {never} */ multiCheck(topics: Uint8Array[]): boolean { return topics.every((t: Uint8Array) => this.check(t)) } /** * Bitwise or blooms together. * @throws {never} */ or(bloom: Bloom) { for (let i = 0; i <= BYTE_SIZE; i++) { const a = this.bitvector[i] const b = bloom.bitvector[i] if (a === undefined) { throw new DefensiveNullCheckError('a is not defined. Please open an issue in the tevm github repo') } if (b === undefined) { throw new DefensiveNullCheckError('b is not defined. Please open an issue in the tevm github repo') } this.bitvector[i] = a | b } } }