upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/selftest.cpp
diff options
context:
space:
mode:
authormtg0001 <106211915+mtg0001@users.noreply.github.com>2026-08-02 10:56:50 -0300
committerGitHub <noreply@github.com>2026-08-02 10:56:50 -0300
commit89f6d045c8e3dacbfbb369a3ac89c0c33de22b4c (patch)
tree3ff7c5ed2c0814a51e5746320f42bfe9c893c56b /src/selftest.cpp
parentee340c535dd26c034e18c4d97bf225a56bf91f6f (diff)
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.
Diffstat (limited to 'src/selftest.cpp')
-rw-r--r--src/selftest.cpp65
1 files changed, 64 insertions, 1 deletions
diff --git a/src/selftest.cpp b/src/selftest.cpp
index 88e9863..c04adf4 100644
--- a/src/selftest.cpp
+++ b/src/selftest.cpp
@@ -470,6 +470,67 @@ static int RunWalletHDSelfTest()
470 return nFail == 0 ? 0 : 1; 470 return nFail == 0 ? 0 : 1;
471} 471}
472 472
473static int RunNetMessageSelfTest()
474{
475 fflush(stdout);
476 printf("net-message self-test\n");
477
478 int nFail = 0;
479 try
480 {
481 CNode complete(INVALID_SOCKET, CAddress("127.0.0.1"));
482 complete.nVersion = VERSION;
483 complete.vRecv << CMessageHeader("ping", 0);
484 nFail += Check(ProcessMessages(&complete), "a complete empty message processes") ? 0 : 1;
485 nFail += Check(complete.vRecv.empty(), "a complete message is consumed") ? 0 : 1;
486 nFail += Check(!complete.fDisconnect, "a valid ping does not disconnect the peer") ? 0 : 1;
487
488 CNode partial(INVALID_SOCKET, CAddress("127.0.0.1"));
489 partial.nVersion = VERSION;
490 partial.vRecv << CMessageHeader("block", 100);
491 unsigned int nPartialBefore = partial.vRecv.size();
492 nFail += Check(ProcessMessages(&partial), "an incomplete message returns cleanly") ? 0 : 1;
493 nFail += Check(partial.vRecv.size() == nPartialBefore,
494 "an incomplete message keeps one header in the buffer") ? 0 : 1;
495 nFail += Check(partial.nIncompleteMessageStart != 0,
496 "an incomplete message starts a timeout clock") ? 0 : 1;
497 nFail += Check(!partial.fDisconnect,
498 "a fresh incomplete message does not disconnect immediately") ? 0 : 1;
499
500 CNode stale(INVALID_SOCKET, CAddress("127.0.0.1"));
501 stale.nVersion = VERSION;
502 stale.vRecv << CMessageHeader("block", 100);
503 stale.nIncompleteMessageStart = GetTime() - BTF_INCOMPLETE_MESSAGE_TIMEOUT_SECS - 1;
504 stale.nIncompleteMessageSize = 100;
505 stale.strIncompleteMessageCommand = "block";
506 ProcessMessages(&stale);
507 nFail += Check(stale.fDisconnect,
508 "a stale incomplete message disconnects the peer") ? 0 : 1;
509
510 CNode oversized(INVALID_SOCKET, CAddress("127.0.0.1"));
511 oversized.nVersion = VERSION;
512 oversized.vRecv << CMessageHeader("block", MAX_PROTOCOL_MESSAGE_SIZE + 1);
513 ProcessMessages(&oversized);
514 nFail += Check(oversized.fDisconnect,
515 "an oversized message header disconnects the peer") ? 0 : 1;
516 }
517 catch (const std::exception& e)
518 {
519 printf(" FAIL exception: %s\n", e.what());
520 nFail++;
521 }
522 catch (...)
523 {
524 printf(" FAIL unknown exception\n");
525 nFail++;
526 }
527
528 printf("%s (%d failure%s)\n", nFail == 0 ? "ALL TESTS PASSED" : "TESTS FAILED",
529 nFail, nFail == 1 ? "" : "s");
530 fflush(stdout);
531 return nFail == 0 ? 0 : 1;
532}
533
473int RunSelfTest(const std::string& name) 534int RunSelfTest(const std::string& name)
474{ 535{
475 AttachTerminal(); 536 AttachTerminal();
@@ -478,8 +539,10 @@ int RunSelfTest(const std::string& name)
478 return RunWalletKeyPoolSelfTest(); 539 return RunWalletKeyPoolSelfTest();
479 if (name == "wallet-hd") 540 if (name == "wallet-hd")
480 return RunWalletHDSelfTest(); 541 return RunWalletHDSelfTest();
542 if (name == "net-message")
543 return RunNetMessageSelfTest();
481 544
482 printf("Unknown self-test '%s'\n", name.c_str()); 545 printf("Unknown self-test '%s'\n", name.c_str());
483 printf("Known self-tests: wallet-keypool, wallet-hd\n"); 546 printf("Known self-tests: wallet-keypool, wallet-hd, net-message\n");
484 return 1; 547 return 1;
485} 548}