/tmp/bitcoin/src/index/txindex_key.h
Line | Count | Source |
1 | | // Copyright (c) The Bitcoin Core developers |
2 | | // Distributed under the MIT software license, see the accompanying |
3 | | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | | |
5 | | #ifndef BITCOIN_INDEX_TXINDEX_KEY_H |
6 | | #define BITCOIN_INDEX_TXINDEX_KEY_H |
7 | | |
8 | | #include <consensus/consensus.h> |
9 | | #include <crypto/siphash.h> |
10 | | #include <primitives/transaction_identifier.h> |
11 | | #include <serialize.h> |
12 | | #include <uint256.h> |
13 | | |
14 | | #include <array> |
15 | | #include <cstddef> |
16 | | #include <cstdint> |
17 | | #include <ios> |
18 | | #include <string> |
19 | | #include <utility> |
20 | | |
21 | | namespace txindex { |
22 | | /* |
23 | | * Database layout: |
24 | | * |
25 | | * ['x', hash prefix, block seq, tx offset] -> (empty) |
26 | | * ['s', block seq] -> block hash |
27 | | * ['h', block hash] -> block seq |
28 | | * ["next_block_seq"] -> next block seq to assign |
29 | | * ["txid_hash_salt"] -> txid hasher salt |
30 | | * ["best_block_v2"] -> current sync locator |
31 | | * ['t', txid] -> legacy CDiskTxPos |
32 | | * ['B'] -> legacy sync locator |
33 | | */ |
34 | | |
35 | | constexpr uint8_t DB_TXINDEX_HASHED{'x'}; |
36 | | constexpr uint8_t DB_BLOCK_SEQ{'s'}; |
37 | | constexpr uint8_t DB_BLOCK_HASH{'h'}; |
38 | | inline const std::string DB_NEXT_BLOCK_SEQ{"next_block_seq"}; |
39 | | inline const std::string DB_TXID_HASH_SALT{"txid_hash_salt"}; |
40 | | inline const std::string DB_BEST_BLOCK_V2{"best_block_v2"}; |
41 | | //! Prefix of a legacy (pre-hashing) txindex row. |
42 | | constexpr uint8_t DB_TXINDEX{'t'}; |
43 | | |
44 | | //! Empty value of a hashed txindex row, whose position is encoded in its key. |
45 | | inline constexpr std::array<std::byte, 0> EMPTY_VALUE{}; |
46 | | |
47 | | //! Serialized size of a block header, the offset of the first byte after it. |
48 | | constexpr uint32_t BLOCK_HEADER_SIZE{80}; |
49 | | |
50 | | //! The location of a transaction: the sequence number of the block that contains it |
51 | | //! and the transaction's serialized byte offset from the start of that block |
52 | | //! (including the header), so the on-disk position is simply |
53 | | //! block_data_pos + tx_offset_in_block. |
54 | | //! |
55 | | struct BlockTxPosition { |
56 | | uint32_t block_seq{0}; |
57 | | uint32_t tx_offset_in_block{0}; |
58 | | |
59 | 57 | friend bool operator==(const BlockTxPosition&, const BlockTxPosition&) = default; |
60 | | |
61 | | // tx_offset is encoded in 3-byte big-endian integer. |
62 | | // This can hold up to 16,777,216, which is >4x the maximum 4 million block weight position |
63 | | static constexpr uint32_t TX_OFFSET_SIZE{3}; |
64 | | static_assert(MAX_BLOCK_SERIALIZED_SIZE <= BigEndianFormatter<TX_OFFSET_SIZE>::MAX); |
65 | | |
66 | | SERIALIZE_METHODS(BlockTxPosition, obj) |
67 | 4.89k | { |
68 | 4.89k | READWRITE(VARINT(obj.block_seq), |
69 | 4.89k | Using<BigEndianFormatter<TX_OFFSET_SIZE>>(obj.tx_offset_in_block)); |
70 | 4.89k | } void txindex::BlockTxPosition::SerializationOps<SpanReader, txindex::BlockTxPosition, ActionUnserialize>(txindex::BlockTxPosition&, SpanReader&, ActionUnserialize) Line | Count | Source | 67 | 324 | { | 68 | 324 | READWRITE(VARINT(obj.block_seq), | 69 | 324 | Using<BigEndianFormatter<TX_OFFSET_SIZE>>(obj.tx_offset_in_block)); | 70 | 324 | } |
void txindex::BlockTxPosition::SerializationOps<DataStream, txindex::BlockTxPosition const, ActionSerialize>(txindex::BlockTxPosition const&, DataStream&, ActionSerialize) Line | Count | Source | 67 | 4.56k | { | 68 | 4.56k | READWRITE(VARINT(obj.block_seq), | 69 | 4.56k | Using<BigEndianFormatter<TX_OFFSET_SIZE>>(obj.tx_offset_in_block)); | 70 | 4.56k | } |
void txindex::BlockTxPosition::SerializationOps<DataStream, txindex::BlockTxPosition, ActionUnserialize>(txindex::BlockTxPosition&, DataStream&, ActionUnserialize) Line | Count | Source | 67 | 4 | { | 68 | 4 | READWRITE(VARINT(obj.block_seq), | 69 | 4 | Using<BigEndianFormatter<TX_OFFSET_SIZE>>(obj.tx_offset_in_block)); | 70 | 4 | } |
|
71 | | }; |
72 | | |
73 | | //! Key for looking up the hash of the block with the given sequence number. |
74 | | struct BlockSeqKey { |
75 | | uint32_t block_seq{0}; |
76 | | |
77 | | SERIALIZE_METHODS(BlockSeqKey, obj) |
78 | 4.29k | { |
79 | 4.29k | uint8_t prefix{DB_BLOCK_SEQ}; |
80 | 4.29k | READWRITE(prefix); |
81 | 4.29k | if (ser_action.ForRead() && prefix != DB_BLOCK_SEQ) throw std::ios_base::failure("Invalid format for txindex block seq key"); |
82 | 4.29k | READWRITE(VARINT(obj.block_seq)); |
83 | 4.29k | } |
84 | | }; |
85 | | |
86 | | //! Key for looking up the sequence number assigned to the block with the given hash. |
87 | | struct BlockHashKey { |
88 | | uint256 block_hash; |
89 | | |
90 | | SERIALIZE_METHODS(BlockHashKey, obj) |
91 | 8.78k | { |
92 | 8.78k | uint8_t prefix{DB_BLOCK_HASH}; |
93 | 8.78k | READWRITE(prefix); |
94 | 8.78k | if (ser_action.ForRead() && prefix != DB_BLOCK_HASH) throw std::ios_base::failure("Invalid format for txindex block hash key"); |
95 | 8.78k | READWRITE(obj.block_hash); |
96 | 8.78k | } |
97 | | }; |
98 | | |
99 | | constexpr int HASH_PREFIX_SIZE{5}; |
100 | | using TxHashKeyPrefix = uint64_t; |
101 | | |
102 | | inline TxHashKeyPrefix CreateKeyPrefix(const SipHasher13UJ& hasher, const Txid& txid) |
103 | 4.55k | { |
104 | 4.55k | return hasher.Hash(txid.ToUint256()) >> (8 * (sizeof(TxHashKeyPrefix) - HASH_PREFIX_SIZE)); |
105 | 4.55k | } |
106 | | |
107 | | struct DBKey { |
108 | | TxHashKeyPrefix hash_prefix{0}; |
109 | | BlockTxPosition pos; |
110 | | |
111 | | SERIALIZE_METHODS(DBKey, obj) |
112 | 4.88k | { |
113 | 4.88k | uint8_t prefix{DB_TXINDEX_HASHED}; |
114 | 4.88k | READWRITE(prefix); |
115 | 4.88k | if (ser_action.ForRead() && prefix != DB_TXINDEX_HASHED) throw std::ios_base::failure("Invalid format for txindex DB key"); |
116 | 4.88k | READWRITE(Using<BigEndianFormatter<HASH_PREFIX_SIZE>>(obj.hash_prefix), obj.pos); |
117 | 4.88k | } void txindex::DBKey::SerializationOps<SpanReader, txindex::DBKey, ActionUnserialize>(txindex::DBKey&, SpanReader&, ActionUnserialize) Line | Count | Source | 112 | 324 | { | 113 | 324 | uint8_t prefix{DB_TXINDEX_HASHED}; | 114 | 324 | READWRITE(prefix); | 115 | 324 | if (ser_action.ForRead() && prefix != DB_TXINDEX_HASHED) throw std::ios_base::failure("Invalid format for txindex DB key"); | 116 | 324 | READWRITE(Using<BigEndianFormatter<HASH_PREFIX_SIZE>>(obj.hash_prefix), obj.pos); | 117 | 324 | } |
void txindex::DBKey::SerializationOps<DataStream, txindex::DBKey const, ActionSerialize>(txindex::DBKey const&, DataStream&, ActionSerialize) Line | Count | Source | 112 | 4.56k | { | 113 | 4.56k | uint8_t prefix{DB_TXINDEX_HASHED}; | 114 | 4.56k | READWRITE(prefix); | 115 | 4.56k | if (ser_action.ForRead() && prefix != DB_TXINDEX_HASHED) throw std::ios_base::failure("Invalid format for txindex DB key"); | 116 | 4.56k | READWRITE(Using<BigEndianFormatter<HASH_PREFIX_SIZE>>(obj.hash_prefix), obj.pos); | 117 | 4.56k | } |
|
118 | | }; |
119 | | |
120 | | //! Key of a legacy (pre-hashing) txindex row: the full txid under the 't' prefix. |
121 | | inline std::pair<uint8_t, uint256> LegacyTxKey(const Txid& txid) |
122 | 5 | { |
123 | 5 | return {DB_TXINDEX, txid.ToUint256()}; |
124 | 5 | } |
125 | | |
126 | | } // namespace txindex |
127 | | |
128 | | #endif // BITCOIN_INDEX_TXINDEX_KEY_H |