Inside Bitcoin
Opening the selected file…
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.
1001case BlockValidationResult::BLOCK_INVALID_PREV:1002return btck_BlockValidationResult_INVALID_PREV;1003case BlockValidationResult::BLOCK_TIME_FUTURE:1004return btck_BlockValidationResult_TIME_FUTURE;1005case BlockValidationResult::BLOCK_HEADER_LOW_WORK:1006return btck_BlockValidationResult_HEADER_LOW_WORK;1007} // no default case, so the compiler can warn about missing cases1008assert(false);1009}1011btck_ChainstateManagerOptions* btck_chainstate_manager_options_create(const btck_Context* context, const char* data_dir, size_t data_dir_len, const char* blocks_dir, size_t blocks_dir_len)1012{1013assert(data_dir != nullptr || data_dir_len == 0);1014assert(blocks_dir != nullptr || blocks_dir_len == 0);1015if (data_dir_len == 0 || blocks_dir_len == 0) {1016LogError("Failed to create chainstate manager options: dir must be non-null and non-empty");1017return nullptr;1018}1019try {1020fs::path abs_data_dir{fs::absolute(fs::PathFromString({data_dir, data_dir_len}))};1021fs::create_directories(abs_data_dir);1022fs::path abs_blocks_dir{fs::absolute(fs::PathFromString({blocks_dir, blocks_dir_len}))};1023fs::create_directories(abs_blocks_dir);1024return btck_ChainstateManagerOptions::create(btck_Context::get(context), abs_data_dir, abs_blocks_dir);1025} catch (const std::exception& e) {1026LogError("Failed to create chainstate manager options: %s", e.what());1027return nullptr;1028}1029}1031void btck_chainstate_manager_options_set_worker_threads_num(btck_ChainstateManagerOptions* opts, int worker_threads)1032{1033LOCK(btck_ChainstateManagerOptions::get(opts).m_mutex);1034btck_ChainstateManagerOptions::get(opts).m_chainman_options.worker_threads_num = worker_threads;1035}1037int btck_chainstate_manager_options_set_database_cache_bytes(btck_ChainstateManagerOptions* chainman_opts, uint64_t database_cache_bytes)1038{1039if (database_cache_bytes < MIN_DBCACHE_BYTES || database_cache_bytes > MAX_DBCACHE_BYTES) {1040LogError("Failed to set database cache: size is outside the supported range.");1041return -1;1042}1044auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};1045LOCK(opts.m_mutex);1046opts.m_db_cache_bytes = database_cache_bytes;1047opts.m_blockman_options.block_tree_db_params.cache_bytes = kernel::CacheSizes{database_cache_bytes}.block_tree_db;1048return 0;1049}1051void btck_chainstate_manager_options_destroy(btck_ChainstateManagerOptions* options)1052{1053delete options;1054}1056int btck_chainstate_manager_options_set_wipe_dbs(btck_ChainstateManagerOptions* chainman_opts, int wipe_block_tree_db, int wipe_chainstate_db)1057{1058if (wipe_block_tree_db == 1 && wipe_chainstate_db != 1) {1059LogError("Wiping the block tree db without also wiping the chainstate db is currently unsupported.");1060return -1;1061}1062auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};1063LOCK(opts.m_mutex);1064opts.m_blockman_options.block_tree_db_params.wipe_data = wipe_block_tree_db == 1;1065opts.m_chainstate_load_options.wipe_chainstate_db = wipe_chainstate_db == 1;1066return 0;1067}1069void btck_chainstate_manager_options_update_block_tree_db_in_memory(1070btck_ChainstateManagerOptions* chainman_opts,1071int block_tree_db_in_memory)1072{1073auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};1074LOCK(opts.m_mutex);1075opts.m_blockman_options.block_tree_db_params.memory_only = block_tree_db_in_memory == 1;1076}1078void btck_chainstate_manager_options_update_chainstate_db_in_memory(1079btck_ChainstateManagerOptions* chainman_opts,1080int chainstate_db_in_memory)1081{1082auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};1083LOCK(opts.m_mutex);1084opts.m_chainstate_load_options.coins_db_in_memory = chainstate_db_in_memory == 1;1085}1087btck_ChainstateManager* btck_chainstate_manager_create(1088const btck_ChainstateManagerOptions* chainman_opts)1089{1090auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)};1091std::unique_ptr<ChainstateManager> chainman;1092try {1093LOCK(opts.m_mutex);1094chainman = std::make_unique<ChainstateManager>(*opts.m_context->m_interrupt, opts.m_chainman_options, opts.m_blockman_options);1095} catch (const std::exception& e) {1096LogError("Failed to create chainstate manager: %s", e.what());1097return nullptr;1098}1100try {1101const auto chainstate_load_opts{WITH_LOCK(opts.m_mutex, return opts.m_chainstate_load_options)};1103const kernel::CacheSizes cache_sizes{WITH_LOCK(opts.m_mutex, return opts.m_db_cache_bytes)};1104auto [status, chainstate_err]{node::LoadChainstate(*chainman, cache_sizes, chainstate_load_opts)};1105if (status != node::ChainstateLoadStatus::SUCCESS) {1106LogError("Failed to load chain state from your data directory: %s", chainstate_err.original);1107return nullptr;1108}1109std::tie(status, chainstate_err) = node::VerifyLoadedChainstate(*chainman, chainstate_load_opts);1110if (status != node::ChainstateLoadStatus::SUCCESS) {1111LogError("Failed to verify loaded chain state from your datadir: %s", chainstate_err.original);1112return nullptr;1113}1114if (auto result = chainman->ActivateBestChains(); !result) {1115LogError("%s", util::ErrorString(result).original);1116return nullptr;1117}1118} catch (const std::exception& e) {1119LogError("Failed to load chainstate: %s", e.what());1120return nullptr;1121}1123return btck_ChainstateManager::create(std::move(chainman), opts.m_context);1124}1126const btck_BlockTreeEntry* btck_chainstate_manager_get_block_tree_entry_by_hash(const btck_ChainstateManager* chainman, const btck_BlockHash* block_hash)1127{1128auto block_index = WITH_LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex(),1129return btck_ChainstateManager::get(chainman).m_chainman->m_blockman.LookupBlockIndex(btck_BlockHash::get(block_hash)));1130if (!block_index) {1131LogDebug(BCLog::KERNEL, "A block with the given hash is not indexed.");1132return nullptr;1133}1134return btck_BlockTreeEntry::ref(block_index);1135}1137const btck_BlockTreeEntry* btck_chainstate_manager_get_best_entry(const btck_ChainstateManager* chainstate_manager)1138{1139auto& chainman = *btck_ChainstateManager::get(chainstate_manager).m_chainman;1140return btck_BlockTreeEntry::ref(WITH_LOCK(chainman.GetMutex(), return chainman.m_best_header));1141}1143void btck_chainstate_manager_destroy(btck_ChainstateManager* chainman)1144{1145{1146LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex());1147for (const auto& chainstate : btck_ChainstateManager::get(chainman).m_chainman->m_chainstates) {1148if (chainstate->CanFlushToDisk()) {1149chainstate->ForceFlushStateToDisk();1150chainstate->ResetCoinsViews();1151}1152}1153}1155delete chainman;1156}1158int btck_chainstate_manager_import_blocks(btck_ChainstateManager* chainman, const char** block_file_paths_data, size_t* block_file_paths_lens, size_t block_file_paths_data_len)1159{1160try {1161std::vector<fs::path> import_files;1162import_files.reserve(block_file_paths_data_len);1163for (uint32_t i = 0; i < block_file_paths_data_len; i++) {1164if (block_file_paths_data[i] != nullptr) {1165import_files.emplace_back(std::string{block_file_paths_data[i], block_file_paths_lens[i]}.c_str());1166}1167}1168auto& chainman_ref{*btck_ChainstateManager::get(chainman).m_chainman};1169node::ImportBlocks(chainman_ref, import_files);1170WITH_LOCK(::cs_main, chainman_ref.UpdateIBDStatus());1171} catch (const std::exception& e) {1172LogError("Failed to import blocks: %s", e.what());1173return -1;1174}1175return 0;1176}1178btck_Block* btck_block_create(const void* raw_block, size_t raw_block_length)1179{1180assert(raw_block != nullptr || raw_block_length == 0);1181auto block{std::make_shared<CBlock>()};1183SpanReader stream{std::span{reinterpret_cast<const std::byte*>(raw_block), raw_block_length}};1185try {1186stream >> TX_WITH_WITNESS(*block);1187} catch (...) {1188LogDebug(BCLog::KERNEL, "Block decode failed.");1189return nullptr;1190}1192return btck_Block::create(block);1193}1195btck_Block* btck_block_copy(const btck_Block* block)1196{1197return btck_Block::copy(block);1198}1200int btck_block_check(const btck_Block* block, const btck_ConsensusParams* consensus_params, btck_BlockCheckFlags flags, btck_BlockValidationState* validation_state)1201{1202auto& state = btck_BlockValidationState::get(validation_state);1203state = BlockValidationState{};1205const bool check_pow = (flags & btck_BlockCheckFlags_POW) != 0;1206const bool check_merkle = (flags & btck_BlockCheckFlags_MERKLE) != 0;1208const bool result = CheckBlock(*btck_Block::get(block), state, btck_ConsensusParams::get(consensus_params), /*fCheckPOW=*/check_pow, /*fCheckMerkleRoot=*/check_merkle);1210return result ? 1 : 0;1211}1213size_t btck_block_count_transactions(const btck_Block* block)1214{1215return btck_Block::get(block)->vtx.size();1216}1218const btck_Transaction* btck_block_get_transaction_at(const btck_Block* block, size_t index)1219{1220assert(index < btck_Block::get(block)->vtx.size());1221return btck_Transaction::ref(&btck_Block::get(block)->vtx[index]);1222}1224btck_BlockHeader* btck_block_get_header(const btck_Block* block)1225{1226const auto& block_ptr = btck_Block::get(block);1227return btck_BlockHeader::create(static_cast<const CBlockHeader&>(*block_ptr));1228}1230int btck_block_to_bytes(const btck_Block* block, btck_WriteBytes writer, void* user_data)1231{1232try {1233WriterStream ws{writer, user_data};1234ws << TX_WITH_WITNESS(*btck_Block::get(block));1235return 0;1236} catch (...) {1237return -1;1238}1239}1241btck_BlockHash* btck_block_get_hash(const btck_Block* block)1242{1243return btck_BlockHash::create(btck_Block::get(block)->GetHash());1244}1246void btck_block_destroy(btck_Block* block)1247{1248delete block;1249}