/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 | 52.9k | void Ser(Stream &s, const CScript& script) { |
66 | 52.9k | CompressedScript compr; |
67 | 52.9k | if (CompressScript(script, compr)) { |
68 | 0 | s << std::span{compr}; |
69 | 0 | return; |
70 | 0 | } |
71 | 52.9k | unsigned int nSize = script.size() + nSpecialScripts; |
72 | 52.9k | s << VARINT(nSize); Line | Count | Source | 491 | 4.14k | #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 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| s << VARINT(nSize); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| s << VARINT(nSize); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
|
73 | 52.9k | s << std::span{script}; |
74 | 52.9k | } _ZN17ScriptCompression3SerI10DataStreamEEvRT_RK7CScript Line | Count | Source | 65 | 4.14k | void Ser(Stream &s, const CScript& script) { | 66 | 4.14k | CompressedScript compr; | 67 | 4.14k | if (CompressScript(script, compr)) { | 68 | 0 | s << std::span{compr}; | 69 | 0 | return; | 70 | 0 | } | 71 | 4.14k | unsigned int nSize = script.size() + nSpecialScripts; | 72 | 4.14k | s << VARINT(nSize); Line | Count | Source | 491 | 4.14k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 73 | 4.14k | s << std::span{script}; | 74 | 4.14k | } |
Unexecuted instantiation: _ZN17ScriptCompression3SerI8AutoFileEEvRT_RK7CScript _ZN17ScriptCompression3SerI12SizeComputerEEvRT_RK7CScript Line | Count | Source | 65 | 16.2k | void Ser(Stream &s, const CScript& script) { | 66 | 16.2k | CompressedScript compr; | 67 | 16.2k | if (CompressScript(script, compr)) { | 68 | 0 | s << std::span{compr}; | 69 | 0 | return; | 70 | 0 | } | 71 | 16.2k | unsigned int nSize = script.size() + nSpecialScripts; | 72 | 16.2k | s << VARINT(nSize); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 73 | 16.2k | s << std::span{script}; | 74 | 16.2k | } |
_ZN17ScriptCompression3SerI10HashWriterEEvRT_RK7CScript Line | Count | Source | 65 | 16.2k | void Ser(Stream &s, const CScript& script) { | 66 | 16.2k | CompressedScript compr; | 67 | 16.2k | if (CompressScript(script, compr)) { | 68 | 0 | s << std::span{compr}; | 69 | 0 | return; | 70 | 0 | } | 71 | 16.2k | unsigned int nSize = script.size() + nSpecialScripts; | 72 | 16.2k | s << VARINT(nSize); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 73 | 16.2k | s << std::span{script}; | 74 | 16.2k | } |
_ZN17ScriptCompression3SerI14BufferedWriterI8AutoFileEEEvRT_RK7CScript Line | Count | Source | 65 | 16.2k | void Ser(Stream &s, const CScript& script) { | 66 | 16.2k | CompressedScript compr; | 67 | 16.2k | if (CompressScript(script, compr)) { | 68 | 0 | s << std::span{compr}; | 69 | 0 | return; | 70 | 0 | } | 71 | 16.2k | unsigned int nSize = script.size() + nSpecialScripts; | 72 | 16.2k | s << VARINT(nSize); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 73 | 16.2k | s << std::span{script}; | 74 | 16.2k | } |
|
75 | | |
76 | | template<typename Stream> |
77 | 550k | void Unser(Stream &s, CScript& script) { |
78 | 550k | unsigned int nSize = 0; |
79 | 550k | s >> VARINT(nSize); Line | Count | Source | 491 | 544k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| s >> VARINT(nSize); Line | Count | Source | 491 | 5.82k | #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 | 550k | 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 | 550k | nSize -= nSpecialScripts; |
87 | 550k | 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 | 550k | } else { |
92 | 550k | script.resize(nSize); |
93 | 550k | s >> std::span{script}; |
94 | 550k | } |
95 | 550k | } _ZN17ScriptCompression5UnserI10DataStreamEEvRT_R7CScript Line | Count | Source | 77 | 544k | void Unser(Stream &s, CScript& script) { | 78 | 544k | unsigned int nSize = 0; | 79 | 544k | s >> VARINT(nSize); Line | Count | Source | 491 | 544k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 80 | 544k | 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 | 544k | nSize -= nSpecialScripts; | 87 | 544k | 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 | 544k | } else { | 92 | 544k | script.resize(nSize); | 93 | 544k | s >> std::span{script}; | 94 | 544k | } | 95 | 544k | } |
_ZN17ScriptCompression5UnserI12HashVerifierI14BufferedReaderI8AutoFileEEEEvRT_R7CScript Line | Count | Source | 77 | 5.82k | void Unser(Stream &s, CScript& script) { | 78 | 5.82k | unsigned int nSize = 0; | 79 | 5.82k | s >> VARINT(nSize); Line | Count | Source | 491 | 5.82k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 80 | 5.82k | 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 | 5.82k | nSize -= nSpecialScripts; | 87 | 5.82k | 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 | 5.82k | } else { | 92 | 5.82k | script.resize(nSize); | 93 | 5.82k | s >> std::span{script}; | 94 | 5.82k | } | 95 | 5.82k | } |
Unexecuted instantiation: _ZN17ScriptCompression5UnserI8AutoFileEEvRT_R7CScript |
96 | | }; |
97 | | |
98 | | struct AmountCompression |
99 | | { |
100 | | template<typename Stream, typename I> void Ser(Stream& s, I val) |
101 | 52.9k | { |
102 | 52.9k | s << VARINT(CompressAmount(val)); Line | Count | Source | 491 | 4.14k | #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 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| s << VARINT(CompressAmount(val)); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| s << VARINT(CompressAmount(val)); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
|
103 | 52.9k | } _ZN17AmountCompression3SerI10DataStreamxEEvRT_T0_ Line | Count | Source | 101 | 4.14k | { | 102 | 4.14k | s << VARINT(CompressAmount(val)); Line | Count | Source | 491 | 4.14k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 103 | 4.14k | } |
Unexecuted instantiation: _ZN17AmountCompression3SerI8AutoFilexEEvRT_T0_ _ZN17AmountCompression3SerI12SizeComputerxEEvRT_T0_ Line | Count | Source | 101 | 16.2k | { | 102 | 16.2k | s << VARINT(CompressAmount(val)); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 103 | 16.2k | } |
_ZN17AmountCompression3SerI10HashWriterxEEvRT_T0_ Line | Count | Source | 101 | 16.2k | { | 102 | 16.2k | s << VARINT(CompressAmount(val)); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 103 | 16.2k | } |
_ZN17AmountCompression3SerI14BufferedWriterI8AutoFileExEEvRT_T0_ Line | Count | Source | 101 | 16.2k | { | 102 | 16.2k | s << VARINT(CompressAmount(val)); Line | Count | Source | 491 | 16.2k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 103 | 16.2k | } |
|
104 | | template<typename Stream, typename I> void Unser(Stream& s, I& val) |
105 | 550k | { |
106 | 550k | uint64_t v; |
107 | 550k | s >> VARINT(v); Line | Count | Source | 491 | 544k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| s >> VARINT(v); Line | Count | Source | 491 | 5.82k | #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 | 550k | val = DecompressAmount(v); |
109 | 550k | } _ZN17AmountCompression5UnserI10DataStreamxEEvRT_RT0_ Line | Count | Source | 105 | 544k | { | 106 | 544k | uint64_t v; | 107 | 544k | s >> VARINT(v); Line | Count | Source | 491 | 544k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 108 | 544k | val = DecompressAmount(v); | 109 | 544k | } |
_ZN17AmountCompression5UnserI12HashVerifierI14BufferedReaderI8AutoFileEExEEvRT_RT0_ Line | Count | Source | 105 | 5.82k | { | 106 | 5.82k | uint64_t v; | 107 | 5.82k | s >> VARINT(v); Line | Count | Source | 491 | 5.82k | #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj) |
| 108 | 5.82k | val = DecompressAmount(v); | 109 | 5.82k | } |
Unexecuted instantiation: _ZN17AmountCompression5UnserI8AutoFilexEEvRT_RT0_ |
110 | | }; |
111 | | |
112 | | /** wrapper for CTxOut that provides a more compact serialization */ |
113 | | struct TxOutCompression |
114 | | { |
115 | 603k | FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); } Line | Count | Source | 145 | 544k | #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 | 4.14k | #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 | 5.82k | #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 | 16.2k | #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 | 16.2k | #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 | 16.2k | #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 | 544k | FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); } Line | Count | Source | 145 | 544k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
_ZN16TxOutCompression16SerializationOpsI10DataStreamK6CTxOut15ActionSerializeEEvRT0_RT_T1_ Line | Count | Source | 115 | 4.14k | FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); } Line | Count | Source | 145 | 4.14k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
Unexecuted instantiation: _ZN16TxOutCompression16SerializationOpsI8AutoFileK6CTxOut15ActionSerializeEEvRT0_RT_T1_ _ZN16TxOutCompression16SerializationOpsI12HashVerifierI14BufferedReaderI8AutoFileEE6CTxOut17ActionUnserializeEEvRT0_RT_T1_ Line | Count | Source | 115 | 5.82k | FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); } Line | Count | Source | 145 | 5.82k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
_ZN16TxOutCompression16SerializationOpsI12SizeComputerK6CTxOut15ActionSerializeEEvRT0_RT_T1_ Line | Count | Source | 115 | 16.2k | FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); } Line | Count | Source | 145 | 16.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
_ZN16TxOutCompression16SerializationOpsI10HashWriterK6CTxOut15ActionSerializeEEvRT0_RT_T1_ Line | Count | Source | 115 | 16.2k | FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); } Line | Count | Source | 145 | 16.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
_ZN16TxOutCompression16SerializationOpsI14BufferedWriterI8AutoFileEK6CTxOut15ActionSerializeEEvRT0_RT_T1_ Line | Count | Source | 115 | 16.2k | FORMATTER_METHODS(CTxOut, obj) { READWRITE(Using<AmountCompression>(obj.nValue), Using<ScriptCompression>(obj.scriptPubKey)); } Line | Count | Source | 145 | 16.2k | #define READWRITE(...) (ser_action.SerReadWriteMany(s, __VA_ARGS__)) |
|
Unexecuted instantiation: _ZN16TxOutCompression16SerializationOpsI8AutoFile6CTxOut17ActionUnserializeEEvRT0_RT_T1_ |
116 | | }; |
117 | | |
118 | | #endif // BITCOIN_COMPRESSOR_H |