All files / src/util bloom.js

100% Statements 26/26
100% Branches 24/24
100% Functions 6/6
100% Lines 25/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                            19x 1x           18x       15x   3x               38x   35x     3x   1x     2x   1x     1x                 19x 4x   15x   37x         37x     37x   37x 4x     11x                 4x       3x       3x 3x    
/**
 * @file bloom
 * @author joshstevens19
 * @link https://github.com/joshstevens19/ethereum-bloom-filters
 */
import sha256 from './sha256';
import {
  Address,
  getAddressObjectFromRep
} from './proto';
/**
 * @deprecated Use the new Bloom instead
 */
function isBloom(bloom) {
  if (bloom instanceof Buffer || bloom instanceof Uint8Array) {
    return bloom.length === 256;
  }
  // if (!/^(0x)?[0-9a-f]{512}$/i.test(bloom)) {
  //   return false;
  // }
 
  if (
    /^(0x)?[0-9a-f]{512}$/.test(bloom)
    || /^(0x)?[0-9A-F]{512}$/.test(bloom)
  ) {
    return true;
  }
  return false;
}
 
/**
 * @param codePoint
 * @return {number}
 */
function codePointToInt(codePoint) {
  if (codePoint >= 48 && codePoint <= 57) {
    /* ['0'..'9'] -> [0..9] */
    return codePoint - 48;
  }
 
  if (codePoint >= 65 && codePoint <= 70) {
    /* ['A'..'F'] -> [10..15] */
    return codePoint - 55;
  }
 
  if (codePoint >= 97 && codePoint <= 102) {
    /* ['a'..'f'] -> [10..15] */
    return codePoint - 87;
  }
 
  throw new Error('invalid bloom');
}
 
/**
 * @param {string} bloom hex string
 * @param {string} hash hex string
 * @return {boolean}
 */
export function isInBloom(bloom, hash) {
  if (!isBloom(bloom)) {
    throw new Error('Invalid Bloom');
  }
  for (let i = 0; i < 12; i += 4) {
    // calculate bit position in bloom filter that must be active
    const bitpos = ((parseInt(hash.substr(i, 2), 16) << 8)
      + parseInt(hash.substr(i + 2, 2), 16))
      & 2047;
 
    // test if bitpos in bloom is active
    const code = codePointToInt(
      bloom.charCodeAt(bloom.length - 1 - Math.floor(bitpos / 4)),
    );
    const offset = 1 << bitpos % 4;
 
    if ((code & offset) !== offset) {
      return false;
    }
  }
  return true;
}
 
/**
 * @param {string} bloom base64 string
 * @param {string} eventName utf-8 string, such as `Transferred`
 * @return {boolean}
 */
export function isEventInBloom(bloom, eventName) {
  return isInBloom(Buffer.from(bloom, 'base64').toString('hex'), sha256(eventName));
}
 
export function isIndexedInBloom(bloom, indexed) {
  return isInBloom(Buffer.from(bloom, 'base64').toString('hex'), sha256(Buffer.from(indexed, 'base64')));
}
 
export function isAddressInBloom(bloom, address) {
  const encodedAddress = Address.encode(getAddressObjectFromRep(address)).finish();
  return isInBloom(Buffer.from(bloom, 'base64').toString('hex'), sha256(encodedAddress));
}