Skip to content

Commit 75fd7b5

Browse files
cc98f9e merge bitcoin#23670: Build minisketch test in make check, not in make (Kittywhiskers Van Gogh) 606a444 merge bitcoin#26686: Enable erlay setting in process_message(s) targets (Kittywhiskers Van Gogh) 38a16a2 merge bitcoin#26359: Erlay support signaling follow-ups (Kittywhiskers Van Gogh) b55a6f7 merge bitcoin#26448: fix intermittent failure in p2p_sendtxrcncl.py (Kittywhiskers Van Gogh) 36be978 merge bitcoin#26396: Avoid SetTxRelay for feeler connections (Kittywhiskers Van Gogh) 62dc9cb merge bitcoin#26381: Fix intermittent issue in p2p_sendtxrcncl.py (Kittywhiskers Van Gogh) 6a7868d merge bitcoin#23443: Erlay support signaling (Kittywhiskers Van Gogh) fdc3c07 partial bitcoin#19953: Implement BIP 340-342 validation (Kittywhiskers Van Gogh) 477157d merge bitcoin#26272: Prevent UB in `minisketch_tests.cpp` (Kittywhiskers Van Gogh) 0cf7401 merge bitcoin#23496: Add minisketch fuzz test (Kittywhiskers Van Gogh) 49ef53c merge bitcoin#23491: Move minisketchwrapper to src/node (Kittywhiskers Van Gogh) Pull request description: ## Additional Information * Dependent on #6332 * Dependent on #6365 * Erlay requires nodes to be `WTXIDRELAY` (as defined by BIP-339, [source](https://github.com/bitcoin/bips/blob/17c04f9fa1ecae173d6864b65717e13dfc1880af/bip-0339.mediawiki))-capable ([source](https://github.com/bitcoin/bips/blob/17c04f9fa1ecae173d6864b65717e13dfc1880af/bip-0330.mediawiki#sendtxrcncl)) as prior to `WTXIDRELAY` adoption, TXIDs of SegWit transactions didn't include the witness data in the hash, which meant, the witness data was malleable ([source](https://bitcoin.stackexchange.com/a/107394)), which would be a relevant factor when you are building out a reconciliation system where you need TXIDs to authoritatively identify a transaction's contents. As Dash _doesn't_ support SegWit, this requirement can be dispensed with. It has instead been replaced with checking if the node is running Dash Core v22 or above to retain the underlying test logic (but this can also be dispensed with as `SENDTXRCNCL` will simply be ignored by older nodes and major releases are _generally_ mandatory upgrades anyways) ## Breaking Changes None expected. ## Checklist - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)** - [x] I have added or updated relevant unit/integration/functional/e2e tests - [x] I have made corresponding changes to the documentation **(note: N/A)** - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: PastaPastaPasta: utACK cc98f9e UdjinM6: utACK cc98f9e Tree-SHA512: fe985f4df6c96c0a7b984882815a1bce7f23c54370198d099e41a59ac4c46c283a2b8dd95f5c8fc12eb1dc1330c4e5c21626b76d33d83d395326e8eb19d564ce
2 parents 25c3355 + cc98f9e commit 75fd7b5

25 files changed

+796
-14
lines changed

src/Makefile.am

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ noinst_LTLIBRARIES =
104104

105105
bin_PROGRAMS =
106106
noinst_PROGRAMS =
107+
check_PROGRAMS =
107108
TESTS =
108109
BENCHMARKS =
109110

@@ -258,7 +259,6 @@ BITCOIN_CORE_H = \
258259
memusage.h \
259260
merkleblock.h \
260261
messagesigner.h \
261-
minisketchwrapper.h \
262262
net.h \
263263
net_permissions.h \
264264
net_processing.h \
@@ -275,8 +275,10 @@ BITCOIN_CORE_H = \
275275
node/context.h \
276276
node/eviction.h \
277277
node/miner.h \
278+
node/minisketchwrapper.h \
278279
node/psbt.h \
279280
node/transaction.h \
281+
node/txreconciliation.h \
280282
node/ui_interface.h \
281283
node/utxo_snapshot.h \
282284
noui.h \
@@ -494,7 +496,6 @@ libbitcoin_server_a_SOURCES = \
494496
masternode/payments.cpp \
495497
masternode/sync.cpp \
496498
masternode/utils.cpp \
497-
minisketchwrapper.cpp \
498499
net.cpp \
499500
netfulfilledman.cpp \
500501
netgroup.cpp \
@@ -507,8 +508,10 @@ libbitcoin_server_a_SOURCES = \
507508
node/eviction.cpp \
508509
node/interfaces.cpp \
509510
node/miner.cpp \
511+
node/minisketchwrapper.cpp \
510512
node/psbt.cpp \
511513
node/transaction.cpp \
514+
node/txreconciliation.cpp \
512515
node/ui_interface.cpp \
513516
noui.cpp \
514517
policy/fees.cpp \

src/Makefile.minisketch.include

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ if ENABLE_TESTS
3131
if !ENABLE_FUZZ
3232
MINISKETCH_TEST = minisketch/test
3333
TESTS += $(MINISKETCH_TEST)
34-
noinst_PROGRAMS += $(MINISKETCH_TEST)
34+
check_PROGRAMS += $(MINISKETCH_TEST)
3535

3636
minisketch_test_SOURCES = $(MINISKETCH_TEST_SOURCES_INT)
3737
minisketch_test_CPPFLAGS = $(AM_CPPFLAGS) $(LIBMINISKETCH_CPPFLAGS)

src/Makefile.test.include

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ FUZZ_SUITE_LD_COMMON = \
5757
$(LIBLEVELDB_SSE42) \
5858
$(LIBMEMENV) \
5959
$(LIBSECP256K1) \
60+
$(MINISKETCH_LIBS) \
6061
$(EVENT_LIBS) \
6162
$(EVENT_PTHREADS_LIBS) \
6263
$(GMP_LIBS) \
@@ -173,6 +174,7 @@ BITCOIN_TESTS =\
173174
test/torcontrol_tests.cpp \
174175
test/transaction_tests.cpp \
175176
test/txindex_tests.cpp \
177+
test/txreconciliation_tests.cpp \
176178
test/txvalidation_tests.cpp \
177179
test/txvalidationcache_tests.cpp \
178180
test/uint256_tests.cpp \
@@ -289,6 +291,7 @@ test_fuzz_fuzz_SOURCES = \
289291
test/fuzz/locale.cpp \
290292
test/fuzz/merkleblock.cpp \
291293
test/fuzz/message.cpp \
294+
test/fuzz/minisketch.cpp \
292295
test/fuzz/muhash.cpp \
293296
test/fuzz/multiplication_overflow.cpp \
294297
test/fuzz/net.cpp \

src/hash.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <crypto/common.h>
88
#include <crypto/hmac_sha512.h>
99

10+
#include <string>
1011

1112
inline uint32_t ROTL32(uint32_t x, int8_t r)
1213
{
@@ -84,3 +85,12 @@ uint256 SHA256Uint256(const uint256& input)
8485
CSHA256().Write(input.begin(), 32).Finalize(result.begin());
8586
return result;
8687
}
88+
89+
CHashWriter TaggedHash(const std::string& tag)
90+
{
91+
CHashWriter writer(SER_GETHASH, 0);
92+
uint256 taghash;
93+
CSHA256().Write((const unsigned char*)tag.data(), tag.size()).Finalize(taghash.begin());
94+
writer << taghash << taghash;
95+
return writer;
96+
}

src/hash.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <uint256.h>
1717
#include <version.h>
1818

19+
#include <string>
1920
#include <vector>
2021

2122
typedef uint256 ChainCode;
@@ -241,4 +242,12 @@ unsigned int MurmurHash3(unsigned int nHashSeed, Span<const unsigned char> vData
241242

242243
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
243244

245+
/** Return a CHashWriter primed for tagged hashes (as specified in BIP 340).
246+
*
247+
* The returned object will have SHA256(tag) written to it twice (= 64 bytes).
248+
* A tagged hash can be computed by feeding the message into this object, and
249+
* then calling CHashWriter::GetSHA256().
250+
*/
251+
CHashWriter TaggedHash(const std::string& tag);
252+
244253
#endif // BITCOIN_HASH_H

src/init.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <node/blockstorage.h>
4141
#include <node/context.h>
4242
#include <node/ui_interface.h>
43+
#include <node/txreconciliation.h>
4344
#include <policy/feerate.h>
4445
#include <policy/fees.h>
4546
#include <policy/policy.h>
@@ -578,6 +579,7 @@ void SetupServerArgs(ArgsManager& argsman)
578579
argsman.AddArg("-v2transport", strprintf("Support v2 transport (default: %u)", DEFAULT_V2_TRANSPORT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
579580
argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
580581
argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
582+
argsman.AddArg("-txreconciliation", strprintf("Enable transaction reconciliations per BIP 330 (default: %d)", DEFAULT_TXRECONCILIATION_ENABLE), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CONNECTION);
581583
argsman.AddArg("-peertimeout=<n>", strprintf("Specify a p2p connection timeout delay in seconds. After connecting to a peer, wait this amount of time before considering disconnection based on inactivity (minimum: 1, default: %d)", DEFAULT_PEER_CONNECT_TIMEOUT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
582584
argsman.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
583585
argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port>. Nodes not using the default ports (default: %u, testnet: %u, regtest: %u) are unlikely to get incoming connections. Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);

src/logging.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ const CLogCategoryDesc LogCategories[] =
161161
{BCLog::I2P, "i2p"},
162162
{BCLog::IPC, "ipc"},
163163
{BCLog::LOCK, "lock"},
164+
{BCLog::TXRECONCILIATION, "txreconciliation"},
164165
{BCLog::ALL, "1"},
165166
{BCLog::ALL, "all"},
166167

src/logging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ namespace BCLog {
6262
I2P = (1 << 22),
6363
IPC = (1 << 23),
6464
LOCK = (1 << 24),
65+
TXRECONCILIATION = (1 << 27),
6566

6667
//Start Dash
6768
CHAINLOCKS = ((uint64_t)1 << 32),

src/net_processing.cpp

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <netbase.h>
2121
#include <net_types.h>
2222
#include <node/blockstorage.h>
23+
#include <node/txreconciliation.h>
2324
#include <policy/policy.h>
2425
#include <primitives/block.h>
2526
#include <primitives/transaction.h>
@@ -730,6 +731,7 @@ class PeerManagerImpl final : public PeerManager
730731
BanMan* const m_banman;
731732
ChainstateManager& m_chainman;
732733
CTxMemPool& m_mempool;
734+
std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
733735
const std::unique_ptr<CDeterministicMNManager>& m_dmnman;
734736
const std::unique_ptr<CJContext>& m_cj_ctx;
735737
const std::unique_ptr<LLMQContext>& m_llmq_ctx;
@@ -1633,6 +1635,7 @@ void PeerManagerImpl::FinalizeNode(const CNode& node) {
16331635
mapBlocksInFlight.erase(entry.pindex->GetBlockHash());
16341636
}
16351637
WITH_LOCK(g_cs_orphans, m_orphanage.EraseForPeer(nodeid));
1638+
if (m_txreconciliation) m_txreconciliation->ForgetPeer(nodeid);
16361639
m_num_preferred_download_peers -= state->fPreferredDownload;
16371640
m_peers_downloading_from -= (state->nBlocksInFlight != 0);
16381641
assert(m_peers_downloading_from >= 0);
@@ -1935,6 +1938,11 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn
19351938
m_mn_activeman(mn_activeman),
19361939
m_ignore_incoming_txs(ignore_incoming_txs)
19371940
{
1941+
// While Erlay support is incomplete, it must be enabled explicitly via -txreconciliation.
1942+
// This argument can go away after Erlay support is complete.
1943+
if (gArgs.GetBoolArg("-txreconciliation", DEFAULT_TXRECONCILIATION_ENABLE)) {
1944+
m_txreconciliation = std::make_unique<TxReconciliationTracker>(TXRECONCILIATION_VERSION);
1945+
}
19381946
}
19391947

19401948
void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
@@ -3509,8 +3517,6 @@ void PeerManagerImpl::ProcessMessage(
35093517
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDADDRV2));
35103518
}
35113519

3512-
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
3513-
35143520
pfrom.m_has_all_wanted_services = HasAllDesirableServiceFlags(nServices);
35153521
peer->m_their_services = nServices;
35163522
pfrom.SetAddrLocal(addrMe);
@@ -3536,6 +3542,22 @@ void PeerManagerImpl::ProcessMessage(
35363542
if (fRelay) pfrom.m_relays_txs = true;
35373543
}
35383544

3545+
if (greatest_common_version >= INCREASE_MAX_HEADERS2_VERSION && m_txreconciliation) {
3546+
// Per BIP-330, we announce txreconciliation support if:
3547+
// - protocol version per the peer's VERSION message supports INCREASE_MAX_HEADERS2_VERSION;
3548+
// - transaction relay is supported per the peer's VERSION message (see m_relays_txs);
3549+
// - this is not a block-relay-only connection and not a feeler (see m_relays_txs);
3550+
// - this is not an addr fetch connection;
3551+
// - we are not in -blocksonly mode.
3552+
if (pfrom.m_relays_txs && !pfrom.IsAddrFetchConn() && !m_ignore_incoming_txs) {
3553+
const uint64_t recon_salt = m_txreconciliation->PreRegisterPeer(pfrom.GetId());
3554+
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::SENDTXRCNCL,
3555+
TXRECONCILIATION_VERSION, recon_salt));
3556+
}
3557+
}
3558+
3559+
m_connman.PushMessage(&pfrom, msg_maker.Make(NetMsgType::VERACK));
3560+
35393561
// Potentially mark this peer as a preferred download peer.
35403562
{
35413563
LOCK(cs_main);
@@ -3677,6 +3699,15 @@ void PeerManagerImpl::ProcessMessage(
36773699
}
36783700
}
36793701

3702+
if (m_txreconciliation) {
3703+
if (pfrom.nVersion < INCREASE_MAX_HEADERS2_VERSION || !m_txreconciliation->IsPeerRegistered(pfrom.GetId())) {
3704+
// We could have optimistically pre-registered/registered the peer. In that case,
3705+
// we should forget about the reconciliation state here if the node version is below
3706+
// our minimum supported version.
3707+
m_txreconciliation->ForgetPeer(pfrom.GetId());
3708+
}
3709+
}
3710+
36803711
pfrom.fSuccessfullyConnected = true;
36813712
return;
36823713
}
@@ -3727,6 +3758,61 @@ void PeerManagerImpl::ProcessMessage(
37273758
return;
37283759
}
37293760

3761+
// Received from a peer demonstrating readiness to announce transactions via reconciliations.
3762+
// This feature negotiation must happen between VERSION and VERACK to avoid relay problems
3763+
// from switching announcement protocols after the connection is up.
3764+
if (msg_type == NetMsgType::SENDTXRCNCL) {
3765+
if (!m_txreconciliation) {
3766+
LogPrint(BCLog::NET, "sendtxrcncl from peer=%d ignored, as our node does not have txreconciliation enabled\n", pfrom.GetId());
3767+
return;
3768+
}
3769+
3770+
if (pfrom.fSuccessfullyConnected) {
3771+
LogPrint(BCLog::NET, "sendtxrcncl received after verack from peer=%d; disconnecting\n", pfrom.GetId());
3772+
pfrom.fDisconnect = true;
3773+
return;
3774+
}
3775+
3776+
// Peer must not offer us reconciliations if we specified no tx relay support in VERSION.
3777+
if (RejectIncomingTxs(pfrom)) {
3778+
LogPrint(BCLog::NET, "sendtxrcncl received from peer=%d to which we indicated no tx relay; disconnecting\n", pfrom.GetId());
3779+
pfrom.fDisconnect = true;
3780+
return;
3781+
}
3782+
3783+
// Peer must not offer us reconciliations if they specified no tx relay support in VERSION.
3784+
// This flag might also be false in other cases, but the RejectIncomingTxs check above
3785+
// eliminates them, so that this flag fully represents what we are looking for.
3786+
if (!pfrom.m_relays_txs) {
3787+
LogPrint(BCLog::NET, "sendtxrcncl received from peer=%d which indicated no tx relay to us; disconnecting\n", pfrom.GetId());
3788+
pfrom.fDisconnect = true;
3789+
return;
3790+
}
3791+
3792+
uint32_t peer_txreconcl_version;
3793+
uint64_t remote_salt;
3794+
vRecv >> peer_txreconcl_version >> remote_salt;
3795+
3796+
const ReconciliationRegisterResult result = m_txreconciliation->RegisterPeer(pfrom.GetId(), pfrom.IsInboundConn(),
3797+
peer_txreconcl_version, remote_salt);
3798+
switch (result) {
3799+
case ReconciliationRegisterResult::NOT_FOUND:
3800+
LogPrint(BCLog::NET, "Ignore unexpected txreconciliation signal from peer=%d\n", pfrom.GetId());
3801+
break;
3802+
case ReconciliationRegisterResult::SUCCESS:
3803+
break;
3804+
case ReconciliationRegisterResult::ALREADY_REGISTERED:
3805+
LogPrint(BCLog::NET, "txreconciliation protocol violation from peer=%d (sendtxrcncl received from already registered peer); disconnecting\n", pfrom.GetId());
3806+
pfrom.fDisconnect = true;
3807+
return;
3808+
case ReconciliationRegisterResult::PROTOCOL_VIOLATION:
3809+
LogPrint(BCLog::NET, "txreconciliation protocol violation from peer=%d; disconnecting\n", pfrom.GetId());
3810+
pfrom.fDisconnect = true;
3811+
return;
3812+
}
3813+
return;
3814+
}
3815+
37303816
if (!pfrom.fSuccessfullyConnected) {
37313817
LogPrint(BCLog::NET, "Unsupported message \"%s\" prior to verack from peer=%d\n", SanitizeString(msg_type), pfrom.GetId());
37323818
return;

src/minisketchwrapper.cpp renamed to src/node/minisketchwrapper.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#include <minisketchwrapper.h>
5+
#include <node/minisketchwrapper.h>
66

77
#include <logging.h>
88
#include <util/time.h>

0 commit comments

Comments
 (0)