/Users/eugenesiegel/btc/bitcoin/src/compressor.h
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | // Copyright (c) 2009-2010 Satoshi Nakamoto | 
| 2 |  | // Copyright (c) 2009-present The Bitcoin Core developers | 
| 3 |  | // Distributed under the MIT software license, see the accompanying | 
| 4 |  | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | 
| 5 |  |  | 
| 6 |  | #ifndef BITCOIN_COMPRESSOR_H | 
| 7 |  | #define BITCOIN_COMPRESSOR_H | 
| 8 |  |  | 
| 9 |  | #include <prevector.h> | 
| 10 |  | #include <primitives/transaction.h> | 
| 11 |  | #include <script/script.h> | 
| 12 |  | #include <serialize.h> | 
| 13 |  | #include <span.h> | 
| 14 |  |  | 
| 15 |  | /** | 
| 16 |  |  * This saves us from making many heap allocations when serializing | 
| 17 |  |  * and deserializing compressed scripts. | 
| 18 |  |  * | 
| 19 |  |  * This prevector size is determined by the largest .resize() in the | 
| 20 |  |  * CompressScript function. The largest compressed script format is a | 
| 21 |  |  * compressed public key, which is 33 bytes. | 
| 22 |  |  */ | 
| 23 |  | using CompressedScript = prevector<33, unsigned char>; | 
| 24 |  |  | 
| 25 |  |  | 
| 26 |  | bool CompressScript(const CScript& script, CompressedScript& out); | 
| 27 |  | unsigned int GetSpecialScriptSize(unsigned int nSize); | 
| 28 |  | bool DecompressScript(CScript& script, unsigned int nSize, const CompressedScript& in); | 
| 29 |  |  | 
| 30 |  | /** | 
| 31 |  |  * Compress amount. | 
| 32 |  |  * | 
| 33 |  |  * nAmount is of type uint64_t and thus cannot be negative. If you're passing in | 
| 34 |  |  * a CAmount (int64_t), make sure to properly handle the case where the amount | 
| 35 |  |  * is negative before calling CompressAmount(...). | 
| 36 |  |  * | 
| 37 |  |  * @pre Function defined only for 0 <= nAmount <= MAX_MONEY. | 
| 38 |  |  */ | 
| 39 |  | uint64_t CompressAmount(uint64_t nAmount); | 
| 40 |  |  | 
| 41 |  | uint64_t DecompressAmount(uint64_t nAmount); | 
| 42 |  |  | 
| 43 |  | /** Compact serializer for scripts. | 
| 44 |  |  * | 
| 45 |  |  *  It detects common cases and encodes them much more efficiently. | 
| 46 |  |  *  3 special cases are defined: | 
| 47 |  |  *  * Pay to pubkey hash (encoded as 21 bytes) | 
| 48 |  |  *  * Pay to script hash (encoded as 21 bytes) | 
| 49 |  |  *  * Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes) | 
| 50 |  |  * | 
| 51 |  |  *  Other scripts up to 121 bytes require 1 byte + script length. Above | 
| 52 |  |  *  that, scripts up to 16505 bytes require 2 bytes + script length. | 
| 53 |  |  */ | 
| 54 |  | struct ScriptCompression | 
| 55 |  | { | 
| 56 |  |     /** | 
| 57 |  |      * make this static for now (there are only 6 special scripts defined) | 
| 58 |  |      * this can potentially be extended together with a new version for | 
| 59 |  |      * transactions, in which case this value becomes dependent on version | 
| 60 |  |      * and nHeight of the enclosing transaction. | 
| 61 |  |      */ | 
| 62 |  |     static const unsigned int nSpecialScripts = 6; | 
| 63 |  |  | 
| 64 |  |     template<typename Stream> | 
| 65 | 324k |     void Ser(Stream &s, const CScript& script) { | 
| 66 | 324k |         CompressedScript compr; | 
| 67 | 324k |         if (CompressScript(script, compr)) { | 
| 68 | 0 |             s << std::span{compr}; | 
| 69 | 0 |             return; | 
| 70 | 0 |         } | 
| 71 | 324k |         unsigned int nSize = script.size() + nSpecialScripts; | 
| 72 | 324k |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 10.1k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 | 
| 73 | 324k |         s << std::span{script}; | 
| 74 | 324k |     } _ZN17ScriptCompression3SerI10DataStreamEEvRT_RK7CScript| Line | Count | Source |  | 65 | 10.1k |     void Ser(Stream &s, const CScript& script) { |  | 66 | 10.1k |         CompressedScript compr; |  | 67 | 10.1k |         if (CompressScript(script, compr)) { |  | 68 | 0 |             s << std::span{compr}; |  | 69 | 0 |             return; |  | 70 | 0 |         } |  | 71 | 10.1k |         unsigned int nSize = script.size() + nSpecialScripts; |  | 72 | 10.1k |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 10.1k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 73 | 10.1k |         s << std::span{script}; |  | 74 | 10.1k |     } | 
Unexecuted instantiation: _ZN17ScriptCompression3SerI8AutoFileEEvRT_RK7CScript_ZN17ScriptCompression3SerI12SizeComputerEEvRT_RK7CScript| Line | Count | Source |  | 65 | 104k |     void Ser(Stream &s, const CScript& script) { |  | 66 | 104k |         CompressedScript compr; |  | 67 | 104k |         if (CompressScript(script, compr)) { |  | 68 | 0 |             s << std::span{compr}; |  | 69 | 0 |             return; |  | 70 | 0 |         } |  | 71 | 104k |         unsigned int nSize = script.size() + nSpecialScripts; |  | 72 | 104k |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 73 | 104k |         s << std::span{script}; |  | 74 | 104k |     } | 
_ZN17ScriptCompression3SerI10HashWriterEEvRT_RK7CScript| Line | Count | Source |  | 65 | 104k |     void Ser(Stream &s, const CScript& script) { |  | 66 | 104k |         CompressedScript compr; |  | 67 | 104k |         if (CompressScript(script, compr)) { |  | 68 | 0 |             s << std::span{compr}; |  | 69 | 0 |             return; |  | 70 | 0 |         } |  | 71 | 104k |         unsigned int nSize = script.size() + nSpecialScripts; |  | 72 | 104k |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 73 | 104k |         s << std::span{script}; |  | 74 | 104k |     } | 
_ZN17ScriptCompression3SerI14BufferedWriterI8AutoFileEEEvRT_RK7CScript| Line | Count | Source |  | 65 | 104k |     void Ser(Stream &s, const CScript& script) { |  | 66 | 104k |         CompressedScript compr; |  | 67 | 104k |         if (CompressScript(script, compr)) { |  | 68 | 0 |             s << std::span{compr}; |  | 69 | 0 |             return; |  | 70 | 0 |         } |  | 71 | 104k |         unsigned int nSize = script.size() + nSpecialScripts; |  | 72 | 104k |         s << VARINT(nSize); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 73 | 104k |         s << std::span{script}; |  | 74 | 104k |     } | 
 | 
| 75 |  |  | 
| 76 |  |     template<typename Stream> | 
| 77 | 1.34M |     void Unser(Stream &s, CScript& script) { | 
| 78 | 1.34M |         unsigned int nSize = 0; | 
| 79 | 1.34M |         s >> VARINT(nSize); | Line | Count | Source |  | 491 | 1.34M | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s >> VARINT(nSize); | Line | Count | Source |  | 491 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s >> VARINT(nSize); | Line | Count | Source |  | 491 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 | 
| 80 | 1.34M |         if (nSize < nSpecialScripts) { | 
| 81 | 0 |             CompressedScript vch(GetSpecialScriptSize(nSize), 0x00); | 
| 82 | 0 |             s >> std::span{vch}; | 
| 83 | 0 |             DecompressScript(script, nSize, vch); | 
| 84 | 0 |             return; | 
| 85 | 0 |         } | 
| 86 | 1.34M |         nSize -= nSpecialScripts; | 
| 87 | 1.34M |         if (nSize > MAX_SCRIPT_SIZE) { | 
| 88 |  |             // Overly long script, replace with a short invalid one | 
| 89 | 0 |             script << OP_RETURN; | 
| 90 | 0 |             s.ignore(nSize); | 
| 91 | 1.34M |         } else { | 
| 92 | 1.34M |             script.resize(nSize); | 
| 93 | 1.34M |             s >> std::span{script}; | 
| 94 | 1.34M |         } | 
| 95 | 1.34M |     } _ZN17ScriptCompression5UnserI10DataStreamEEvRT_R7CScript| Line | Count | Source |  | 77 | 1.34M |     void Unser(Stream &s, CScript& script) { |  | 78 | 1.34M |         unsigned int nSize = 0; |  | 79 | 1.34M |         s >> VARINT(nSize); | Line | Count | Source |  | 491 | 1.34M | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 80 | 1.34M |         if (nSize < nSpecialScripts) { |  | 81 | 0 |             CompressedScript vch(GetSpecialScriptSize(nSize), 0x00); |  | 82 | 0 |             s >> std::span{vch}; |  | 83 | 0 |             DecompressScript(script, nSize, vch); |  | 84 | 0 |             return; |  | 85 | 0 |         } |  | 86 | 1.34M |         nSize -= nSpecialScripts; |  | 87 | 1.34M |         if (nSize > MAX_SCRIPT_SIZE) { |  | 88 |  |             // Overly long script, replace with a short invalid one |  | 89 | 0 |             script << OP_RETURN; |  | 90 | 0 |             s.ignore(nSize); |  | 91 | 1.34M |         } else { |  | 92 | 1.34M |             script.resize(nSize); |  | 93 | 1.34M |             s >> std::span{script}; |  | 94 | 1.34M |         } |  | 95 | 1.34M |     } | 
Unexecuted instantiation: _ZN17ScriptCompression5UnserI12HashVerifierI14BufferedReaderI8AutoFileEEEEvRT_R7CScriptUnexecuted instantiation: _ZN17ScriptCompression5UnserI8AutoFileEEvRT_R7CScript | 
| 96 |  | }; | 
| 97 |  |  | 
| 98 |  | struct AmountCompression | 
| 99 |  | { | 
| 100 |  |     template<typename Stream, typename I> void Ser(Stream& s, I val) | 
| 101 | 324k |     { | 
| 102 | 324k |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 10.1k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 | 
| 103 | 324k |     } _ZN17AmountCompression3SerI10DataStreamxEEvRT_T0_| Line | Count | Source |  | 101 | 10.1k |     { |  | 102 | 10.1k |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 10.1k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 103 | 10.1k |     } | 
Unexecuted instantiation: _ZN17AmountCompression3SerI8AutoFilexEEvRT_T0__ZN17AmountCompression3SerI12SizeComputerxEEvRT_T0_| Line | Count | Source |  | 101 | 104k |     { |  | 102 | 104k |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 103 | 104k |     } | 
_ZN17AmountCompression3SerI10HashWriterxEEvRT_T0_| Line | Count | Source |  | 101 | 104k |     { |  | 102 | 104k |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 103 | 104k |     } | 
_ZN17AmountCompression3SerI14BufferedWriterI8AutoFileExEEvRT_T0_| Line | Count | Source |  | 101 | 104k |     { |  | 102 | 104k |         s << VARINT(CompressAmount(val)); | Line | Count | Source |  | 491 | 104k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 103 | 104k |     } | 
 | 
| 104 |  |     template<typename Stream, typename I> void Unser(Stream& s, I& val) | 
| 105 | 1.34M |     { | 
| 106 | 1.34M |         uint64_t v; | 
| 107 | 1.34M |         s >> VARINT(v); | Line | Count | Source |  | 491 | 1.34M | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s >> VARINT(v); | Line | Count | Source |  | 491 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |         s >> VARINT(v); | Line | Count | Source |  | 491 | 0 | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 | 
| 108 | 1.34M |         val = DecompressAmount(v); | 
| 109 | 1.34M |     } _ZN17AmountCompression5UnserI10DataStreamxEEvRT_RT0_| Line | Count | Source |  | 105 | 1.34M |     { |  | 106 | 1.34M |         uint64_t v; |  | 107 | 1.34M |         s >> VARINT(v); | Line | Count | Source |  | 491 | 1.34M | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) | 
 |  | 108 | 1.34M |         val = DecompressAmount(v); |  | 109 | 1.34M |     } | 
Unexecuted instantiation: _ZN17AmountCompression5UnserI12HashVerifierI14BufferedReaderI8AutoFileEExEEvRT_RT0_Unexecuted instantiation: _ZN17AmountCompression5UnserI8AutoFilexEEvRT_RT0_ | 
| 110 |  | }; | 
| 111 |  |  | 
| 112 |  | /** wrapper for CTxOut that provides a more compact serialization */ | 
| 113 |  | struct TxOutCompression | 
| 114 |  | { | 
| 115 | 1.66M |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 1.34M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 10.1k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 104k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 104k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 104k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 0 | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
_ZN16TxOutCompression16SerializationOpsI10DataStream6CTxOut17ActionUnserializeEEvRT0_RT_T1_| Line | Count | Source |  | 115 | 1.34M |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 1.34M | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
_ZN16TxOutCompression16SerializationOpsI10DataStreamK6CTxOut15ActionSerializeEEvRT0_RT_T1_| Line | Count | Source |  | 115 | 10.1k |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 10.1k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
Unexecuted instantiation: _ZN16TxOutCompression16SerializationOpsI8AutoFileK6CTxOut15ActionSerializeEEvRT0_RT_T1_Unexecuted instantiation: _ZN16TxOutCompression16SerializationOpsI12HashVerifierI14BufferedReaderI8AutoFileEE6CTxOut17ActionUnserializeEEvRT0_RT_T1__ZN16TxOutCompression16SerializationOpsI12SizeComputerK6CTxOut15ActionSerializeEEvRT0_RT_T1_| Line | Count | Source |  | 115 | 104k |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 104k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
_ZN16TxOutCompression16SerializationOpsI10HashWriterK6CTxOut15ActionSerializeEEvRT0_RT_T1_| Line | Count | Source |  | 115 | 104k |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 104k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
_ZN16TxOutCompression16SerializationOpsI14BufferedWriterI8AutoFileEK6CTxOut15ActionSerializeEEvRT0_RT_T1_| Line | Count | Source |  | 115 | 104k |     FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); }| Line | Count | Source |  | 145 | 104k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) | 
 | 
Unexecuted instantiation: _ZN16TxOutCompression16SerializationOpsI8AutoFile6CTxOut17ActionUnserializeEEvRT0_RT_T1_ | 
| 116 |  | }; | 
| 117 |  |  | 
| 118 |  | #endif // BITCOIN_COMPRESSOR_H |