# 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
    };