Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1001BOOST_CHECK(!ParseFixedPoint("1.1e-", 8, &amount));1002BOOST_CHECK(!ParseFixedPoint("1.", 8, &amount));1004// Test with 3 decimal places for fee rates in sat/vB.1005BOOST_CHECK(ParseFixedPoint("0.001", 3, &amount));1006BOOST_CHECK_EQUAL(amount, CAmount{1});1007BOOST_CHECK(!ParseFixedPoint("0.0009", 3, &amount));1008BOOST_CHECK(!ParseFixedPoint("31.00100001", 3, &amount));1009BOOST_CHECK(!ParseFixedPoint("31.0011", 3, &amount));1010BOOST_CHECK(!ParseFixedPoint("31.99999999", 3, &amount));1011BOOST_CHECK(!ParseFixedPoint("31.999999999999999999999", 3, &amount));1012}1014#ifndef WIN32 // Cannot do this test on WIN32 due to lack of fork()1015static constexpr char LockCommand = 'L';1016static constexpr char UnlockCommand = 'U';1017static constexpr char ExitCommand = 'X';1018enum : char {1019ResSuccess = 2, // Start with 2 to avoid accidental collision with common values 0 and 11020ResErrorWrite,1021ResErrorLock,1022ResUnlockSuccess,1023};1025[[noreturn]] static void TestOtherProcess(fs::path dirname, fs::path lockname, int fd)1026{1027char ch;1028while (true) {1029int rv = read(fd, &ch, 1); // Wait for command1030assert(rv == 1);1031switch (ch) {1032case LockCommand:1033ch = [&] {1034switch (util::LockDirectory(dirname, lockname)) {1035case util::LockResult::Success: return ResSuccess;1036case util::LockResult::ErrorWrite: return ResErrorWrite;1037case util::LockResult::ErrorLock: return ResErrorLock;1038} // no default case, so the compiler can warn about missing cases1039assert(false);1040}();1041rv = write(fd, &ch, 1);1042assert(rv == 1);1043break;1044case UnlockCommand:1045ReleaseDirectoryLocks();1046ch = ResUnlockSuccess; // Always succeeds1047rv = write(fd, &ch, 1);1048assert(rv == 1);1049break;1050case ExitCommand:1051close(fd);1052exit(0);1053default:1054assert(0);1055}1056}1057}1058#endif1060BOOST_AUTO_TEST_CASE(test_LockDirectory)1061{1062fs::path dirname = m_args.GetDataDirBase() / "lock_dir";1063const fs::path lockname = ".lock";1064#ifndef WIN321065// Fork another process for testing before creating the lock, so that we1066// won't fork while holding the lock (which might be undefined, and is not1067// relevant as test case as that is avoided with -daemonize).1068int fd[2];1069BOOST_CHECK_EQUAL(socketpair(AF_UNIX, SOCK_STREAM, 0, fd), 0);1070pid_t pid = fork();1071if (!pid) {1072BOOST_CHECK_EQUAL(close(fd[1]), 0); // Child: close parent end1073TestOtherProcess(dirname, lockname, fd[0]);1074}1075BOOST_CHECK_EQUAL(close(fd[0]), 0); // Parent: close child end1077char ch;1078// Lock on non-existent directory should fail1079BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);1080BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);1081BOOST_CHECK_EQUAL(ch, ResErrorWrite);1082#endif1083// Lock on non-existent directory should fail1084BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::ErrorWrite);1086fs::create_directories(dirname);1088// Probing lock on new directory should succeed1089BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);1091// Persistent lock on new directory should succeed1092BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success);1094// Another lock on the directory from the same thread should succeed1095BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname), util::LockResult::Success);1097// Another lock on the directory from a different thread within the same process should succeed1098util::LockResult threadresult;1099std::thread thr([&] { threadresult = util::LockDirectory(dirname, lockname); });1100thr.join();1101BOOST_CHECK_EQUAL(threadresult, util::LockResult::Success);1102#ifndef WIN321103// Try to acquire lock in child process while we're holding it, this should fail.1104BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);1105BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);1106BOOST_CHECK_EQUAL(ch, ResErrorLock);1108// Give up our lock1109ReleaseDirectoryLocks();1110// Probing lock from our side now should succeed, but not hold on to the lock.1111BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);1113// Try to acquire the lock in the child process, this should be successful.1114BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);1115BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);1116BOOST_CHECK_EQUAL(ch, ResSuccess);1118// When we try to probe the lock now, it should fail.1119BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::ErrorLock);1121// Unlock the lock in the child process1122BOOST_CHECK_EQUAL(write(fd[1], &UnlockCommand, 1), 1);1123BOOST_CHECK_EQUAL(read(fd[1], &ch, 1), 1);1124BOOST_CHECK_EQUAL(ch, ResUnlockSuccess);1126// When we try to probe the lock now, it should succeed.1127BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);1129// Re-lock the lock in the child process, then wait for it to exit, check1130// successful return. After that, we check that exiting the process1131// has released the lock as we would expect by probing it.1132int processstatus;1133BOOST_CHECK_EQUAL(write(fd[1], &LockCommand, 1), 1);1134// The following line invokes the ~CNetCleanup dtor without1135// a paired SetupNetworking call. This is acceptable as long as1136// ~CNetCleanup is a no-op for non-Windows platforms.1137BOOST_CHECK_EQUAL(write(fd[1], &ExitCommand, 1), 1);1138BOOST_CHECK_EQUAL(waitpid(pid, &processstatus, 0), pid);1139BOOST_CHECK_EQUAL(processstatus, 0);1140BOOST_CHECK_EQUAL(util::LockDirectory(dirname, lockname, true), util::LockResult::Success);1142BOOST_CHECK_EQUAL(close(fd[1]), 0); // Close our side of the socketpair1143#endif1144// Clean up1145ReleaseDirectoryLocks();1146fs::remove(dirname / lockname);1147fs::remove(dirname);1148}1150BOOST_AUTO_TEST_CASE(test_ToLower)1151{1152BOOST_CHECK_EQUAL(ToLower('@'), '@');1153BOOST_CHECK_EQUAL(ToLower('A'), 'a');1154BOOST_CHECK_EQUAL(ToLower('Z'), 'z');1155BOOST_CHECK_EQUAL(ToLower('['), '[');1156BOOST_CHECK_EQUAL(ToLower(0), 0);1157BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');1159BOOST_CHECK_EQUAL(ToLower(""), "");1160BOOST_CHECK_EQUAL(ToLower("#HODL"), "#hodl");1161BOOST_CHECK_EQUAL(ToLower("\x00\xfe\xff"), "\x00\xfe\xff");1162}1164BOOST_AUTO_TEST_CASE(test_ToUpper)1165{1166BOOST_CHECK_EQUAL(ToUpper('`'), '`');1167BOOST_CHECK_EQUAL(ToUpper('a'), 'A');1168BOOST_CHECK_EQUAL(ToUpper('z'), 'Z');1169BOOST_CHECK_EQUAL(ToUpper('{'), '{');1170BOOST_CHECK_EQUAL(ToUpper(0), 0);1171BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');1173BOOST_CHECK_EQUAL(ToUpper(""), "");1174BOOST_CHECK_EQUAL(ToUpper("#hodl"), "#HODL");1175BOOST_CHECK_EQUAL(ToUpper("\x00\xfe\xff"), "\x00\xfe\xff");1176}1178BOOST_AUTO_TEST_CASE(test_Capitalize)1179{1180BOOST_CHECK_EQUAL(Capitalize(""), "");1181BOOST_CHECK_EQUAL(Capitalize("bitcoin"), "Bitcoin");1182BOOST_CHECK_EQUAL(Capitalize("\x00\xfe\xff"), "\x00\xfe\xff");1183}1185static std::string SpanToStr(const std::span<const char>& span)1186{1187return std::string(span.begin(), span.end());1188}1190BOOST_AUTO_TEST_CASE(test_script_parsing)1191{1192using namespace script;1193std::string input;1194std::span<const char> sp;1195bool success;1197// Const(...): parse a constant, update span to skip it if successful1198input = "MilkToastHoney";1199sp = input;1200success = Const("", sp); // empty1201BOOST_CHECK(success);1202BOOST_CHECK_EQUAL(SpanToStr(sp), "MilkToastHoney");1204success = Const("Milk", sp, /*skip=*/false);1205BOOST_CHECK(success);1206BOOST_CHECK_EQUAL(SpanToStr(sp), "MilkToastHoney");1208success = Const("Milk", sp);1209BOOST_CHECK(success);1210BOOST_CHECK_EQUAL(SpanToStr(sp), "ToastHoney");1212success = Const("Bread", sp, /*skip=*/false);1213BOOST_CHECK(!success);1215success = Const("Bread", sp);1216BOOST_CHECK(!success);1218success = Const("Toast", sp, /*skip=*/false);1219BOOST_CHECK(success);1220BOOST_CHECK_EQUAL(SpanToStr(sp), "ToastHoney");1222success = Const("Toast", sp);1223BOOST_CHECK(success);1224BOOST_CHECK_EQUAL(SpanToStr(sp), "Honey");1226success = Const("Honeybadger", sp);1227BOOST_CHECK(!success);1229success = Const("Honey", sp, /*skip=*/false);1230BOOST_CHECK(success);1231BOOST_CHECK_EQUAL(SpanToStr(sp), "Honey");1233success = Const("Honey", sp);1234BOOST_CHECK(success);1235BOOST_CHECK_EQUAL(SpanToStr(sp), "");1236// Func(...): parse a function call, update span to argument if successful1237input = "Foo(Bar(xy,z()))";1238sp = input;1240success = Func("FooBar", sp);1241BOOST_CHECK(!success);1243success = Func("Foo(", sp);1244BOOST_CHECK(!success);1246success = Func("Foo", sp);1247BOOST_CHECK(success);1248BOOST_CHECK_EQUAL(SpanToStr(sp), "Bar(xy,z())");1250success = Func("Bar", sp);
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.