all files / packages/web3-utils/src/ bloomFilter.js

80.65% Statements 25/31
72.73% Branches 16/22
100% Functions 4/4
86.21% Lines 25/29
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 112                                                                      16× 15×                         16×     16× 16×   16×                                                                          
/*jshint bitwise: false*/
 
/*
 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");
 
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;
 
        // test if bitpos in bloom is active
        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
};