git / moonbite-core / src/compressor.h · raw

// Copyright (c) 2009-2010 Satoshi Nakamoto// Copyright (c) 2009-2020 The Bitcoin Core developers// Distributed under the MIT software license, see the accompanying// file COPYING or http://www.opensource.org/licenses/mit-license.php.#ifndef BITCOIN_COMPRESSOR_H#define BITCOIN_COMPRESSOR_H#include <primitives/transaction.h>#include <script/script.h>#include <serialize.h>#include <span.h>bool CompressScript(const CScript& script, std::vector<unsigned char> &out);unsigned int GetSpecialScriptSize(unsigned int nSize);bool DecompressScript(CScript& script, unsigned int nSize, const std::vector<unsigned char> &out);/** * Compress amount. * * nAmount is of type uint64_t and thus cannot be negative. If you're passing in * a CAmount (int64_t), make sure to properly handle the case where the amount * is negative before calling CompressAmount(...). * * @pre Function defined only for 0 <= nAmount <= MAX_MONEY. */uint64_t CompressAmount(uint64_t nAmount);uint64_t DecompressAmount(uint64_t nAmount);/** Compact serializer for scripts. * *  It detects common cases and encodes them much more efficiently. *  3 special cases are defined: *  * Pay to pubkey hash (encoded as 21 bytes) *  * Pay to script hash (encoded as 21 bytes) *  * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes) * *  Other scripts up to 121 bytes require 1 byte + script length. Above *  that, scripts up to 16505 bytes require 2 bytes + script length. */struct ScriptCompression{    /**     * make this static for now (there are only 6 special scripts defined)     * this can potentially be extended together with a new nVersion for     * transactions, in which case this value becomes dependent on nVersion     * and nHeight of the enclosing transaction.     */    static const unsigned int nSpecialScripts = 6;    template<typename Stream>    void Ser(Stream &s, const CScript& script) {        std::vector<unsigned char> compr;        if (CompressScript(script, compr)) {            s << MakeSpan(compr);            return;        }        unsigned int nSize = script.size() + nSpecialScripts;        s << VARINT(nSize);        s << MakeSpan(script);    }    template<typename Stream>    void Unser(Stream &s, CScript& script) {        unsigned int nSize = 0;        s >> VARINT(nSize);        if (nSize < nSpecialScripts) {            std::vector<unsigned char> vch(GetSpecialScriptSize(nSize), 0x00);            s >> MakeSpan(vch);            DecompressScript(script, nSize, vch);            return;        }        nSize -= nSpecialScripts;        if (nSize > MAX_SCRIPT_SIZE) {            // Overly long script, replace with a short invalid one            script << OP_RETURN;            s.ignore(nSize);        } else {            script.resize(nSize);            s >> MakeSpan(script);        }    }};struct AmountCompression{    template<typename Stream, typename I> void Ser(Stream& s, I val)    {        s << VARINT(CompressAmount(val));    }    template<typename Stream, typename I> void Unser(Stream& s, I& val)    {        uint64_t v;        s >> VARINT(v);        val = DecompressAmount(v);    }};/** wrapper for CTxOut that provides a more compact serialization */struct TxOutCompression{    FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }};#endif // BITCOIN_COMPRESSOR_H