From 89f6d045c8e3dacbfbb369a3ac89c0c33de22b4c Mon Sep 17 00:00:00 2001 From: mtg0001 <106211915+mtg0001@users.noreply.github.com> Date: Sun, 2 Aug 2026 10:56:50 -0300 Subject: Keep HD change recoverable and bound message stalls (#109) Change from an HD wallet now goes to a newly derived phrase-backed key instead of reusing a spent input's key. Reusing an input key silently moved value back to a key the phrase cannot reproduce; if derivation fails the transaction is refused rather than creating unrecoverable change. Legacy wallets with no seed keep the 0.1.0 behaviour. Restore also scans past the pre-generated key-pool window before treating an empty batch as the end. The message parser no longer consumes a header it cannot complete: it reads from a copy, so the O(n) reinsert and the 100 ms sleep inside the shared message thread are gone, and a peer that sits on an incomplete payload is disconnected after two minutes. The wire cap drops from 256 MB to MAX_SIZE. New net-message self-test covers complete, incomplete, stale and oversized headers. Verified here: clean rebuild, all self-tests pass, lock order checked (no path takes cs_keyPool before cs_mapWallet), and a node built from this branch synced from genesis to the chain tip on the live network with zero rejections. --- src/net.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'src/net.h') diff --git a/src/net.h b/src/net.h index 1c0c24e..37f335e 100644 --- a/src/net.h +++ b/src/net.h @@ -67,6 +67,13 @@ static const int BTF_RECV_TIMEOUT_SECS = 30 * 60; static const int BTF_SEND_STALL_SECS = 10 * 60; static const int BTF_HANDSHAKE_GRACE_SECS = 60; +// A serialized object cannot be larger than MAX_SIZE, so no valid network +// message needs the old 256 MB header allowance. Keep the wire cap aligned with +// what the deserializer can accept and bound how long one peer may sit on a +// partial payload after a complete header has arrived. +static const unsigned int MAX_PROTOCOL_MESSAGE_SIZE = MAX_SIZE; +static const int BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS = 2 * 60; + // Ceiling on simultaneous connections. // // ThreadSocketHandler watches every peer through one select(), and select() @@ -225,7 +232,7 @@ public: } // Message size - if (nMessageSize > 0x10000000) + if (nMessageSize > MAX_PROTOCOL_MESSAGE_SIZE) { if (LogAcceptsCategory("net")) printf("CMessageHeader::IsValid() : nMessageSize too large %u\n", nMessageSize); return false; @@ -596,6 +603,9 @@ public: int64 nLastSend; int64 nLastRecv; int64 nLastSendEmpty; + int64 nIncompleteMessageStart; + unsigned int nIncompleteMessageSize; + string strIncompleteMessageCommand; // Height this peer announced in its version message, or -1 if it sent a // version message that predates the field. Knowing how far along everyone @@ -626,6 +636,9 @@ public: nLastSend = 0; nLastRecv = 0; nLastSendEmpty = GetTime(); + nIncompleteMessageStart = 0; + nIncompleteMessageSize = 0; + strIncompleteMessageCommand.clear(); nStartingHeight = -1; vfSubscribe.assign(256, false); -- cgit v1.2.3