Home Reference Source Test

src/main/generic/utils/Services.js

class Services {
    /**
     * @constructor
     * @param {number} [provided=Services.NONE] Bitmap of services that can be provided by this node
     * @param {number} [accepted=Services.NONE] Bitmap of services that can be accepted by this node
     */
    constructor(provided = Services.NONE, accepted = Services.NONE) {
        this._provided = provided;
        this._accepted = accepted;
    }

    /**
     * @type {number}
     */
    get provided() {
        return this._provided;
    }

    /**
     * @type {number}
     */
    get accepted() {
        return this._accepted;
    }

    /**
     * @param {number} services Bitmap of services that can be provided
     */
    set provided(services) {
        this._provided = services;
    }

    /**
     * @param {number} services Bitmap of services that can be accepted
     */
    set accepted(services) {
        this._accepted = services;
    }

    /**
     * @param {number} services Bitmap of the services to check
     * @returns {boolean}
     * @deprecated
     */
    static isFullNode(services) {
        return (services & Services.FLAG_FULL) !== 0;
    }

    /**
     * @param {number} services Bitmap of the services to check
     * @returns {boolean}
     * @deprecated
     */
    static isLightNode(services) {
        return (services & Services.FLAG_LIGHT) !== 0;
    }

    /**
     * @param {number} services Bitmap of the services to check
     * @returns {boolean}
     * @deprecated
     */
    static isNanoNode(services) {
        return services === Services.FLAG_NANO;
    }

    /**
     * @param {number} flags
     * @param {...number} services
     */
    static providesServices(flags, ...services) {
        flags = Services.legacyProvideToCurrent(flags);
        const all = services.reduce((a, b) => a | b) & Services.ALL_CURRENT;
        return (flags & all) === all;
    }

    static legacyProvideToCurrent(flags) {
        if (flags === Services.FLAG_NANO) flags = Services.PROVIDES_NANO;
        if (flags === Services.FLAG_LIGHT) flags = Services.PROVIDES_LIGHT;
        if (flags === Services.FLAG_FULL) flags = Services.PROVIDES_FULL;
        return flags;
    }

    /**
     * @param {number} flags
     * @returns {Array.<string>}
     */
    static toNameArray(flags) {
        const res = [];
        let i = 1;
        do {
            if ((flags % i) === i && Services.NAMES[i]) res.push(Services.NAMES[i]);
            i <<= 1;
        } while (i < Services.ALL_CURRENT);
        return res;
    }
}

Services.NONE    = 0;

/** @deprecated */
Services.FLAG_NANO  = 1 << 0;
/** @deprecated */
Services.FLAG_LIGHT = 1 << 1;
/** @deprecated */
Services.FLAG_FULL  = 1 << 2;
/** @deprecated */
Services.ALL_LEGACY = (1 << 3) - 1;

/**
 * The node provides at least the latest {@link Policy.NUM_BLOCKS_VERIFICATION} as full blocks.
 */
Services.FULL_BLOCKS       = 1 << 3;
/**
 * The node provides the full block history.
 *
 * If {@link Services.FULL_BLOCKS} is set, these blocks are provided as full blocks.
 */
Services.BLOCK_HISTORY     = 1 << 4;
/**
 * The node provides a proof that a certain block is included in the current chain.
 *
 * If {@link Services.FULL_BLOCKS} is set, these blocks may be requested as full blocks.
 *
 * However, if {@link Services.BLOCK_HISTORY} is not set, this service is only provided for the latest
 * {@link Policy.NUM_BLOCKS_VERIFICATION} blocks.
 */
Services.BLOCK_PROOF       = 1 << 5;
/**
 * The node provides a chain proof for the tip of the current main chain.
 */
Services.CHAIN_PROOF       = 1 << 6;
/**
 * The node provides inclusion and exclusion proofs for accounts that are necessary to verify active accounts as well as
 * accounts in all transactions it provided from its mempool.
 *
 * However, if {@link Services.ACCOUNTS_CHUNKS} is not set, the node may occasionally not provide a proof if it
 * decided to prune the account from local storage.
 */
Services.ACCOUNTS_PROOF    = 1 << 7;
/**
 * The node provides the full accounts tree in form of chunks.
 * This implies that the client stores the full accounts tree.
 */
Services.ACCOUNTS_CHUNKS   = 1 << 8;
/**
 * The node tries to stay on sync with the network wide mempool and will provide access to it.
 *
 * Nodes that do not have this flag set may occasionally announce transactions from their mempool and/or reply to
 * mempool requests to announce locally crafted transactions.
 */
Services.MEMPOOL           = 1 << 9;
/**
 * The node provides an index of transactions allowing it to find historic transactions by address or by hash.
 *
 * Nodes that have this flag set may prune any part of their transaction index at their discretion, they do not claim
 * completeness of their results either.
 */
Services.TRANSACTION_INDEX = 1 << 10;
/**
 * The node provides proofs for details from the block body, i.e. transaction proofs.
 *
 * However, if {@link Services.BLOCK_HISTORY} is not set, this service is only provided for the latest
 * {@link Policy.NUM_BLOCKS_VERIFICATION} blocks.
 */
Services.BODY_PROOF        = 1 << 11;
Services.ALL_CURRENT       = (1 << 12) - 1 - Services.ALL_LEGACY;

Services.NAMES = {};
Services.NAMES[Services.FULL_BLOCKS] = 'FULL_BLOCKS';
Services.NAMES[Services.BLOCK_HISTORY] = 'BLOCK_HISTORY';
Services.NAMES[Services.BLOCK_PROOF] = 'BLOCK_PROOF';
Services.NAMES[Services.CHAIN_PROOF] = 'CHAIN_PROOF';
Services.NAMES[Services.ACCOUNTS_PROOF] = 'ACCOUNTS_PROOF';
Services.NAMES[Services.ACCOUNTS_CHUNKS] = 'ACCOUNTS_CHUNKS';
Services.NAMES[Services.MEMPOOL] = 'MEMPOOL';
Services.NAMES[Services.TRANSACTION_INDEX] = 'TRANSACTION_INDEX';
Services.NAMES[Services.BODY_PROOF] = 'BODY_PROOF';

Services.PROVIDES_FULL =        Services.FLAG_FULL | Services.ALL_CURRENT;
Services.PROVIDES_LIGHT =       Services.FLAG_LIGHT | Services.FULL_BLOCKS | Services.BLOCK_PROOF |
                                Services.CHAIN_PROOF | Services.ACCOUNTS_PROOF | Services.ACCOUNTS_CHUNKS |
                                Services.MEMPOOL | Services.BODY_PROOF;
Services.PROVIDES_NANO =        Services.FLAG_NANO | Services.CHAIN_PROOF;
Services.PROVIDES_PICO =        Services.NONE;

Services.ACCEPTS_FULL =         Services.FLAG_FULL | Services.FULL_BLOCKS | Services.BLOCK_HISTORY;
Services.ACCEPTS_LIGHT =        Services.FLAG_LIGHT | Services.FLAG_FULL | Services.FULL_BLOCKS | Services.CHAIN_PROOF |
                                Services.ACCOUNTS_CHUNKS;
Services.ACCEPTS_NANO =         Services.FLAG_NANO | Services.FLAG_LIGHT | Services.FLAG_FULL | Services.CHAIN_PROOF;
Services.ACCEPTS_PICO =         Services.FLAG_NANO | Services.FLAG_LIGHT | Services.FLAG_FULL;

Services.ACCEPTS_SPV =          Services.BLOCK_PROOF | Services.ACCOUNTS_PROOF | Services.MEMPOOL |
                                Services.TRANSACTION_INDEX | Services.BODY_PROOF;

Class.register(Services);