upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/compactblock.h
diff options
context:
space:
mode:
authorbitflash-maintainer <noreply@bitflash.invalid>2026-09-06 01:53:03 +0000
committerbitflash-maintainer <noreply@bitflash.invalid>2026-09-06 01:53:03 +0000
commitef9f06d43fc6577c15df2256abbb25b20d4227b8 (patch)
tree7e9132aa871fdc01cb95268d2f5ea3bb11853ddf /src/compactblock.h
parentbe63e83d79e7e00e6b8ca889a70e6a19886aa1d8 (diff)
parentceae3d076b5ad11ee84729ae43f14e9312896646 (diff)
Merge branch 'chore/main-catchup-2026-08-26' into 'main'HEADmain
Bring main onto the line this project actually ships (incl. the 1.2.23 compactblock port) Closes #6, #7, #8, #11, #35, #34, #29, #28, #27, and #16 See merge request !16
Diffstat (limited to 'src/compactblock.h')
-rw-r--r--src/compactblock.h113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/compactblock.h b/src/compactblock.h
new file mode 100644
index 0000000..745ee3b
--- /dev/null
+++ b/src/compactblock.h
@@ -0,0 +1,113 @@
1// Copyright (c) 2026 Bitflash developers
2// Distributed under the MIT/X11 software license.
3//
4// Compact block relay (BIP152-style). Instead of sending a peer's full set
5// of transactions for a block they're about to receive -- almost all of
6// which they already have in their mempool from normal tx relay -- send a
7// short (48-bit, keyed-hash) ID per transaction instead. A peer that already
8// has every referenced transaction reconstructs the full block locally from
9// its mempool without any of the transaction bytes crossing the wire at
10// all; only genuinely missing transactions (typically just the coinbase)
11// need a follow-up round trip.
12//
13// Compatibility: this is purely additive. A peer that never sends
14// "sendcmpct" is never sent a compact block -- it keeps getting full
15// "block" messages exactly as before (see the getdata handler in
16// main.cpp). Old, unupgraded nodes on the live network are completely
17// unaffected; ProcessMessage's unknown-command handling means they simply
18// never see the new message types. No coordinated network upgrade needed.
19//
20// Deliberately scoped down from full BIP152: no high-bandwidth (unsolicited
21// push) mode, no differential-index encoding for prefilled transactions,
22// only the current chain tip is ever offered in compact form (an old block
23// is unlikely to still overlap much with any peer's current mempool, so the
24// bandwidth win doesn't apply -- full "block" is sent for those, same as
25// today). Only the coinbase is prefilled; every other transaction position
26// carries a short ID.
27
28#ifndef BITFLASH_COMPACTBLOCK_H
29#define BITFLASH_COMPACTBLOCK_H
30
31// Requires CBlock/CTransaction already visible -- #include "headers.h" (or
32// main.h) before this file. Deliberately doesn't include main.h itself:
33// main.h has no include guard (matches this codebase's existing headers, it
34// relies on being pulled in exactly once via headers.h), so a second
35// #include "main.h" here would break every translation unit that already
36// brought it in via headers.h first.
37#include <vector>
38
39// The compact representation of a block: header fields, a per-block nonce
40// (keys the short-ID hash so IDs can't be precomputed/ground across blocks),
41// the coinbase in full, and a 48-bit short ID for every other transaction
42// in block order.
43class CCmpctBlock
44{
45public:
46 // header
47 int nVersion;
48 uint256 hashPrevBlock;
49 uint256 hashMerkleRoot;
50 unsigned int nTime;
51 unsigned int nBits;
52 unsigned int nNonce;
53
54 // Keys the short-ID hash for this block specifically -- chosen fresh
55 // per block (not reused from nNonce, which is public PoW data an
56 // attacker already knows and could otherwise grind against).
57 uint64 shortIdNonce;
58
59 // Sent in full. In this implementation: always exactly the coinbase,
60 // at index 0.
61 std::vector<unsigned int> vPrefilledIndex;
62 std::vector<CTransaction> vPrefilledTx;
63
64 // One short ID per NON-prefilled transaction, in ascending block-index
65 // order (i.e. the Nth entry here belongs to the Nth block position that
66 // isn't in vPrefilledIndex).
67 std::vector<uint64> vShortTxId;
68
69 IMPLEMENT_SERIALIZE
70 (
71 READWRITE(this->nVersion);
72 nVersion = this->nVersion;
73 READWRITE(hashPrevBlock);
74 READWRITE(hashMerkleRoot);
75 READWRITE(nTime);
76 READWRITE(nBits);
77 READWRITE(nNonce);
78 READWRITE(shortIdNonce);
79 READWRITE(vPrefilledIndex);
80 READWRITE(vPrefilledTx);
81 READWRITE(vShortTxId);
82 )
83
84 uint256 HeaderHash() const;
85};
86
87// Compute the 48-bit short ID for a transaction under a given block's
88// short-ID nonce. Keyed (via the block's hashPrevBlock + shortIdNonce) so
89// IDs from one block can't be precomputed before that block exists, and
90// differ block to block even for the same transaction.
91uint64 ComputeShortTxId(const uint256& hashPrevBlock, uint64 shortIdNonce, const uint256& txid);
92
93// Build the compact form of `block` (which must have vtx[0] as the
94// coinbase, as every block on this chain does).
95bool BuildCompactBlock(const CBlock& block, CCmpctBlock& out);
96
97// Attempt to reconstruct a full block from a received compact block using
98// the local mempool. On full success, returns true and fills `outBlock`.
99// On partial success (some transactions not found locally), returns false
100// and fills `vMissingIndex` with the block-position indices that still need
101// to be requested via "getblocktxn" -- outBlock is left partially built
102// (coinbase and any resolved positions filled; caller must not use it until
103// FillMissingAndFinish completes it).
104bool TryReconstructBlock(const CCmpctBlock& cmpct, CBlock& outBlock, std::vector<unsigned int>& vMissingIndex);
105
106// Complete a partially-reconstructed block (from a prior TryReconstructBlock
107// that returned false) using the transactions received in a "blocktxn"
108// response. vTxn must be in the same order as the indices this node
109// requested via "getblocktxn" for this block.
110bool FillMissingAndFinish(CBlock& outBlock, const std::vector<unsigned int>& vMissingIndex,
111 const std::vector<CTransaction>& vTxn);
112
113#endif