All files / web3-utils/src bloomFilter.js

79.31% Statements 23/29
72.73% Branches 16/22
100% Functions 4/4
85.19% Lines 23/27
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 100 101 102 103 104 105 106 107 108 109 110 111                                                                1x         16x 15x     1x       1x 1x             8x   8x   16x 16x   16x   16x 4x       4x                       1x 3x     3x       3x                       1x 5x 5x   5x     1x        
/*
 This file is part of web3.js.
 
 web3.js is free software: you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 web3.js is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public License
 along with web3.js.  If not, see <http://www.gnu.org/licenses/>.
 */
 
/**
 * @file bloom.js
 * @author Bas van Kervel <bas@ethereum.org>
 * @date 2017
 */
 
/**
 * Ethereum bloom filter support.
 *
 * TODO UNDOCUMENTED
 *
 * @module bloom
 * @class [bloom] bloom
 */
 
var utils = require("./utils.js");
 
/* eslint-disable no-bitwise */
 
function codePointToInt(codePoint) {
    if (codePoint >= 48 && codePoint <= 57) { /*['0'..'9'] -> [0..9]*/
        return codePoint-48;
    }
 
    Iif (codePoint >= 65 && codePoint <= 70) { /*['A'..'F'] -> [10..15]*/
        return codePoint-55;
    }
 
    Eif (codePoint >= 97 && codePoint <= 102) { /*['a'..'f'] -> [10..15]*/
        return codePoint-87;
    }
 
    throw "invalid bloom";
}
 
function testBytes(bloom, bytes) {
    var hash = utils.sha3(bytes).replace('0x','');
 
    for (var i = 0; i < 12; i += 4) {
        // calculate bit position in bloom filter that must be active
        var bitpos = ((parseInt(hash.substr(i, 2), 16) << 8) + parseInt(hash.substr((i+2), 2), 16)) & 2047;
        var code = codePointToInt(bloom.charCodeAt(bloom.length - 1 - Math.floor(bitpos/4)));
 
        var offset = 1 << (bitpos % 4);
 
        if ((code&offset) !== offset) {
            return false;
        }
    }
 
    return true;
}
 
/**
 * Returns true if address is part of the given bloom.
 * note: false positives are possible.
 *
 * @method testAddress
 * @param {String} hex encoded bloom
 * @param {String} address in hex notation
 * @returns {Boolean} topic is (probably) part of the block
 */
var testAddress = function(bloom, address) {
    Iif (!utils.isBloom(bloom)) {
        throw 'Invalid bloom given';
    }
    Iif (!utils.isAddress(address)) {
        throw 'Invalid address given: "'+ address +'\"';
    }
 
    return testBytes(bloom, address);
};
 
/**
 * Returns true if the topic is part of the given bloom.
 * note: false positives are possible.
 *
 * @method hasTopic
 * @param {String} hex encoded bloom
 * @param {String} address in hex notation
 * @returns {Boolean} topic is (probably) part of the block
 */
var testTopic = function(bloom, topic) {
    Iif (!utils.isBloom(bloom)) throw "invalid bloom";
    Iif (!utils.isTopic(topic)) throw "invalid topic";
 
    return testBytes(bloom, topic);
};
 
module.exports = {
    testAddress: testAddress,
    testTopic:   testTopic
};