bitcoinkernel.cpp
1 // Copyright (c) 2022-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #define BITCOINKERNEL_BUILD 6 7 #include <kernel/bitcoinkernel.h> 8 9 #include <chain.h> 10 #include <coins.h> 11 #include <consensus/validation.h> 12 #include <dbwrapper.h> 13 #include <kernel/caches.h> 14 #include <kernel/chainparams.h> 15 #include <kernel/checks.h> 16 #include <kernel/context.h> 17 #include <kernel/notifications_interface.h> 18 #include <kernel/warning.h> 19 #include <logging.h> 20 #include <node/blockstorage.h> 21 #include <node/chainstate.h> 22 #include <primitives/block.h> 23 #include <primitives/transaction.h> 24 #include <script/interpreter.h> 25 #include <script/script.h> 26 #include <serialize.h> 27 #include <streams.h> 28 #include <sync.h> 29 #include <uint256.h> 30 #include <undo.h> 31 #include <util/check.h> 32 #include <util/fs.h> 33 #include <util/result.h> 34 #include <util/signalinterrupt.h> 35 #include <util/task_runner.h> 36 #include <util/translation.h> 37 #include <validation.h> 38 #include <validationinterface.h> 39 40 #include <cstddef> 41 #include <cstring> 42 #include <exception> 43 #include <functional> 44 #include <list> 45 #include <memory> 46 #include <span> 47 #include <stdexcept> 48 #include <string> 49 #include <tuple> 50 #include <utility> 51 #include <vector> 52 53 using kernel::ChainstateRole; 54 using util::ImmediateTaskRunner; 55 56 // Define G_TRANSLATION_FUN symbol in libbitcoinkernel library so users of the 57 // library aren't required to export this symbol 58 extern const TranslateFn G_TRANSLATION_FUN{nullptr}; 59 60 static const kernel::Context btck_context_static{}; 61 62 namespace { 63 64 bool is_valid_flag_combination(script_verify_flags flags) 65 { 66 if (flags & SCRIPT_VERIFY_CLEANSTACK && ~flags & (SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS)) return false; 67 if (flags & SCRIPT_VERIFY_WITNESS && ~flags & SCRIPT_VERIFY_P2SH) return false; 68 return true; 69 } 70 71 class WriterStream 72 { 73 private: 74 btck_WriteBytes m_writer; 75 void* m_user_data; 76 77 public: 78 WriterStream(btck_WriteBytes writer, void* user_data) 79 : m_writer{writer}, m_user_data{user_data} {} 80 81 // 82 // Stream subset 83 // 84 void write(std::span<const std::byte> src) 85 { 86 if (m_writer(src.data(), src.size(), m_user_data) != 0) { 87 throw std::runtime_error("Failed to write serialization data"); 88 } 89 } 90 91 template <typename T> 92 WriterStream& operator<<(const T& obj) 93 { 94 ::Serialize(*this, obj); 95 return *this; 96 } 97 }; 98 99 template <typename C, typename CPP> 100 struct Handle { 101 static C* ref(CPP* cpp_type) 102 { 103 return reinterpret_cast<C*>(cpp_type); 104 } 105 106 static const C* ref(const CPP* cpp_type) 107 { 108 return reinterpret_cast<const C*>(cpp_type); 109 } 110 111 template <typename... Args> 112 static C* create(Args&&... args) 113 { 114 auto cpp_obj{std::make_unique<CPP>(std::forward<Args>(args)...)}; 115 return ref(cpp_obj.release()); 116 } 117 118 static C* copy(const C* ptr) 119 { 120 auto cpp_obj{std::make_unique<CPP>(get(ptr))}; 121 return ref(cpp_obj.release()); 122 } 123 124 static const CPP& get(const C* ptr) 125 { 126 return *reinterpret_cast<const CPP*>(ptr); 127 } 128 129 static CPP& get(C* ptr) 130 { 131 return *reinterpret_cast<CPP*>(ptr); 132 } 133 134 static void operator delete(void* ptr) 135 { 136 delete reinterpret_cast<CPP*>(ptr); 137 } 138 }; 139 140 } // namespace 141 142 struct btck_BlockTreeEntry: Handle<btck_BlockTreeEntry, CBlockIndex> {}; 143 struct btck_Block : Handle<btck_Block, std::shared_ptr<const CBlock>> {}; 144 struct btck_BlockValidationState : Handle<btck_BlockValidationState, BlockValidationState> {}; 145 146 namespace { 147 148 BCLog::Level get_bclog_level(btck_LogLevel level) 149 { 150 switch (level) { 151 case btck_LogLevel_INFO: { 152 return BCLog::Level::Info; 153 } 154 case btck_LogLevel_DEBUG: { 155 return BCLog::Level::Debug; 156 } 157 case btck_LogLevel_TRACE: { 158 return BCLog::Level::Trace; 159 } 160 } 161 assert(false); 162 } 163 164 BCLog::LogFlags get_bclog_flag(btck_LogCategory category) 165 { 166 switch (category) { 167 case btck_LogCategory_BENCH: { 168 return BCLog::LogFlags::BENCH; 169 } 170 case btck_LogCategory_BLOCKSTORAGE: { 171 return BCLog::LogFlags::BLOCKSTORAGE; 172 } 173 case btck_LogCategory_COINDB: { 174 return BCLog::LogFlags::COINDB; 175 } 176 case btck_LogCategory_LEVELDB: { 177 return BCLog::LogFlags::LEVELDB; 178 } 179 case btck_LogCategory_MEMPOOL: { 180 return BCLog::LogFlags::MEMPOOL; 181 } 182 case btck_LogCategory_PRUNE: { 183 return BCLog::LogFlags::PRUNE; 184 } 185 case btck_LogCategory_RAND: { 186 return BCLog::LogFlags::RAND; 187 } 188 case btck_LogCategory_REINDEX: { 189 return BCLog::LogFlags::REINDEX; 190 } 191 case btck_LogCategory_VALIDATION: { 192 return BCLog::LogFlags::VALIDATION; 193 } 194 case btck_LogCategory_KERNEL: { 195 return BCLog::LogFlags::KERNEL; 196 } 197 case btck_LogCategory_ALL: { 198 return BCLog::LogFlags::ALL; 199 } 200 } 201 assert(false); 202 } 203 204 btck_SynchronizationState cast_state(SynchronizationState state) 205 { 206 switch (state) { 207 case SynchronizationState::INIT_REINDEX: 208 return btck_SynchronizationState_INIT_REINDEX; 209 case SynchronizationState::INIT_DOWNLOAD: 210 return btck_SynchronizationState_INIT_DOWNLOAD; 211 case SynchronizationState::POST_INIT: 212 return btck_SynchronizationState_POST_INIT; 213 } // no default case, so the compiler can warn about missing cases 214 assert(false); 215 } 216 217 btck_Warning cast_btck_warning(kernel::Warning warning) 218 { 219 switch (warning) { 220 case kernel::Warning::UNKNOWN_NEW_RULES_ACTIVATED: 221 return btck_Warning_UNKNOWN_NEW_RULES_ACTIVATED; 222 case kernel::Warning::LARGE_WORK_INVALID_CHAIN: 223 return btck_Warning_LARGE_WORK_INVALID_CHAIN; 224 } // no default case, so the compiler can warn about missing cases 225 assert(false); 226 } 227 228 struct LoggingConnection { 229 std::unique_ptr<std::list<std::function<void(const std::string&)>>::iterator> m_connection; 230 void* m_user_data; 231 std::function<void(void* user_data)> m_deleter; 232 233 LoggingConnection(btck_LogCallback callback, void* user_data, btck_DestroyCallback user_data_destroy_callback) 234 { 235 LOCK(cs_main); 236 237 auto connection{LogInstance().PushBackCallback([callback, user_data](const std::string& str) { callback(user_data, str.c_str(), str.length()); })}; 238 239 // Only start logging if we just added the connection. 240 if (LogInstance().NumConnections() == 1 && !LogInstance().StartLogging()) { 241 LogError("Logger start failed."); 242 LogInstance().DeleteCallback(connection); 243 if (user_data && user_data_destroy_callback) { 244 user_data_destroy_callback(user_data); 245 } 246 throw std::runtime_error("Failed to start logging"); 247 } 248 249 m_connection = std::make_unique<std::list<std::function<void(const std::string&)>>::iterator>(connection); 250 m_user_data = user_data; 251 m_deleter = user_data_destroy_callback; 252 253 LogDebug(BCLog::KERNEL, "Logger connected."); 254 } 255 256 ~LoggingConnection() 257 { 258 LOCK(cs_main); 259 LogDebug(BCLog::KERNEL, "Logger disconnecting."); 260 261 // Switch back to buffering by calling DisconnectTestLogger if the 262 // connection that we are about to remove is the last one. 263 if (LogInstance().NumConnections() == 1) { 264 LogInstance().DisconnectTestLogger(); 265 } else { 266 LogInstance().DeleteCallback(*m_connection); 267 } 268 269 m_connection.reset(); 270 if (m_user_data && m_deleter) { 271 m_deleter(m_user_data); 272 } 273 } 274 }; 275 276 class KernelNotifications final : public kernel::Notifications 277 { 278 private: 279 btck_NotificationInterfaceCallbacks m_cbs; 280 281 public: 282 KernelNotifications(btck_NotificationInterfaceCallbacks cbs) 283 : m_cbs{cbs} 284 { 285 } 286 287 ~KernelNotifications() 288 { 289 if (m_cbs.user_data && m_cbs.user_data_destroy) { 290 m_cbs.user_data_destroy(m_cbs.user_data); 291 } 292 m_cbs.user_data_destroy = nullptr; 293 m_cbs.user_data = nullptr; 294 } 295 296 kernel::InterruptResult blockTip(SynchronizationState state, const CBlockIndex& index, double verification_progress) override 297 { 298 if (m_cbs.block_tip) m_cbs.block_tip(m_cbs.user_data, cast_state(state), btck_BlockTreeEntry::ref(&index), verification_progress); 299 return {}; 300 } 301 void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) override 302 { 303 if (m_cbs.header_tip) m_cbs.header_tip(m_cbs.user_data, cast_state(state), height, timestamp, presync ? 1 : 0); 304 } 305 void progress(const bilingual_str& title, int progress_percent, bool resume_possible) override 306 { 307 if (m_cbs.progress) m_cbs.progress(m_cbs.user_data, title.original.c_str(), title.original.length(), progress_percent, resume_possible ? 1 : 0); 308 } 309 void warningSet(kernel::Warning id, const bilingual_str& message) override 310 { 311 if (m_cbs.warning_set) m_cbs.warning_set(m_cbs.user_data, cast_btck_warning(id), message.original.c_str(), message.original.length()); 312 } 313 void warningUnset(kernel::Warning id) override 314 { 315 if (m_cbs.warning_unset) m_cbs.warning_unset(m_cbs.user_data, cast_btck_warning(id)); 316 } 317 void flushError(const bilingual_str& message) override 318 { 319 if (m_cbs.flush_error) m_cbs.flush_error(m_cbs.user_data, message.original.c_str(), message.original.length()); 320 } 321 void fatalError(const bilingual_str& message) override 322 { 323 if (m_cbs.fatal_error) m_cbs.fatal_error(m_cbs.user_data, message.original.c_str(), message.original.length()); 324 } 325 }; 326 327 class KernelValidationInterface final : public CValidationInterface 328 { 329 public: 330 btck_ValidationInterfaceCallbacks m_cbs; 331 332 explicit KernelValidationInterface(const btck_ValidationInterfaceCallbacks vi_cbs) : m_cbs{vi_cbs} {} 333 334 ~KernelValidationInterface() 335 { 336 if (m_cbs.user_data && m_cbs.user_data_destroy) { 337 m_cbs.user_data_destroy(m_cbs.user_data); 338 } 339 m_cbs.user_data = nullptr; 340 m_cbs.user_data_destroy = nullptr; 341 } 342 343 protected: 344 void BlockChecked(const std::shared_ptr<const CBlock>& block, const BlockValidationState& stateIn) override 345 { 346 if (m_cbs.block_checked) { 347 m_cbs.block_checked(m_cbs.user_data, 348 btck_Block::copy(btck_Block::ref(&block)), 349 btck_BlockValidationState::ref(&stateIn)); 350 } 351 } 352 353 void NewPoWValidBlock(const CBlockIndex* pindex, const std::shared_ptr<const CBlock>& block) override 354 { 355 if (m_cbs.pow_valid_block) { 356 m_cbs.pow_valid_block(m_cbs.user_data, 357 btck_Block::copy(btck_Block::ref(&block)), 358 btck_BlockTreeEntry::ref(pindex)); 359 } 360 } 361 362 void BlockConnected(const ChainstateRole& role, const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override 363 { 364 if (m_cbs.block_connected) { 365 m_cbs.block_connected(m_cbs.user_data, 366 btck_Block::copy(btck_Block::ref(&block)), 367 btck_BlockTreeEntry::ref(pindex)); 368 } 369 } 370 371 void BlockDisconnected(const std::shared_ptr<const CBlock>& block, const CBlockIndex* pindex) override 372 { 373 if (m_cbs.block_disconnected) { 374 m_cbs.block_disconnected(m_cbs.user_data, 375 btck_Block::copy(btck_Block::ref(&block)), 376 btck_BlockTreeEntry::ref(pindex)); 377 } 378 } 379 }; 380 381 struct ContextOptions { 382 mutable Mutex m_mutex; 383 std::unique_ptr<const CChainParams> m_chainparams GUARDED_BY(m_mutex); 384 std::shared_ptr<KernelNotifications> m_notifications GUARDED_BY(m_mutex); 385 std::shared_ptr<KernelValidationInterface> m_validation_interface GUARDED_BY(m_mutex); 386 }; 387 388 class Context 389 { 390 public: 391 std::unique_ptr<kernel::Context> m_context; 392 393 std::shared_ptr<KernelNotifications> m_notifications; 394 395 std::unique_ptr<util::SignalInterrupt> m_interrupt; 396 397 std::unique_ptr<ValidationSignals> m_signals; 398 399 std::unique_ptr<const CChainParams> m_chainparams; 400 401 std::shared_ptr<KernelValidationInterface> m_validation_interface; 402 403 Context(const ContextOptions* options, bool& sane) 404 : m_context{std::make_unique<kernel::Context>()}, 405 m_interrupt{std::make_unique<util::SignalInterrupt>()} 406 { 407 if (options) { 408 LOCK(options->m_mutex); 409 if (options->m_chainparams) { 410 m_chainparams = std::make_unique<const CChainParams>(*options->m_chainparams); 411 } 412 if (options->m_notifications) { 413 m_notifications = options->m_notifications; 414 } 415 if (options->m_validation_interface) { 416 m_signals = std::make_unique<ValidationSignals>(std::make_unique<ImmediateTaskRunner>()); 417 m_validation_interface = options->m_validation_interface; 418 m_signals->RegisterSharedValidationInterface(m_validation_interface); 419 } 420 } 421 422 if (!m_chainparams) { 423 m_chainparams = CChainParams::Main(); 424 } 425 if (!m_notifications) { 426 m_notifications = std::make_shared<KernelNotifications>(btck_NotificationInterfaceCallbacks{ 427 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}); 428 } 429 430 if (!kernel::SanityChecks(*m_context)) { 431 sane = false; 432 } 433 } 434 435 ~Context() 436 { 437 if (m_signals) { 438 m_signals->UnregisterSharedValidationInterface(m_validation_interface); 439 } 440 } 441 }; 442 443 //! Helper struct to wrap the ChainstateManager-related Options 444 struct ChainstateManagerOptions { 445 mutable Mutex m_mutex; 446 ChainstateManager::Options m_chainman_options GUARDED_BY(m_mutex); 447 node::BlockManager::Options m_blockman_options GUARDED_BY(m_mutex); 448 std::shared_ptr<const Context> m_context; 449 node::ChainstateLoadOptions m_chainstate_load_options GUARDED_BY(m_mutex); 450 451 ChainstateManagerOptions(const std::shared_ptr<const Context>& context, const fs::path& data_dir, const fs::path& blocks_dir) 452 : m_chainman_options{ChainstateManager::Options{ 453 .chainparams = *context->m_chainparams, 454 .datadir = data_dir, 455 .notifications = *context->m_notifications, 456 .signals = context->m_signals.get()}}, 457 m_blockman_options{node::BlockManager::Options{ 458 .chainparams = *context->m_chainparams, 459 .blocks_dir = blocks_dir, 460 .notifications = *context->m_notifications, 461 .block_tree_db_params = DBParams{ 462 .path = data_dir / "blocks" / "index", 463 .cache_bytes = kernel::CacheSizes{DEFAULT_KERNEL_CACHE}.block_tree_db, 464 }}}, 465 m_context{context}, m_chainstate_load_options{node::ChainstateLoadOptions{}} 466 { 467 } 468 }; 469 470 struct ChainMan { 471 std::unique_ptr<ChainstateManager> m_chainman; 472 std::shared_ptr<const Context> m_context; 473 474 ChainMan(std::unique_ptr<ChainstateManager> chainman, std::shared_ptr<const Context> context) 475 : m_chainman(std::move(chainman)), m_context(std::move(context)) {} 476 }; 477 478 } // namespace 479 480 struct btck_Transaction : Handle<btck_Transaction, std::shared_ptr<const CTransaction>> {}; 481 struct btck_TransactionOutput : Handle<btck_TransactionOutput, CTxOut> {}; 482 struct btck_ScriptPubkey : Handle<btck_ScriptPubkey, CScript> {}; 483 struct btck_LoggingConnection : Handle<btck_LoggingConnection, LoggingConnection> {}; 484 struct btck_ContextOptions : Handle<btck_ContextOptions, ContextOptions> {}; 485 struct btck_Context : Handle<btck_Context, std::shared_ptr<const Context>> {}; 486 struct btck_ChainParameters : Handle<btck_ChainParameters, CChainParams> {}; 487 struct btck_ChainstateManagerOptions : Handle<btck_ChainstateManagerOptions, ChainstateManagerOptions> {}; 488 struct btck_ChainstateManager : Handle<btck_ChainstateManager, ChainMan> {}; 489 struct btck_Chain : Handle<btck_Chain, CChain> {}; 490 struct btck_BlockSpentOutputs : Handle<btck_BlockSpentOutputs, std::shared_ptr<CBlockUndo>> {}; 491 struct btck_TransactionSpentOutputs : Handle<btck_TransactionSpentOutputs, CTxUndo> {}; 492 struct btck_Coin : Handle<btck_Coin, Coin> {}; 493 struct btck_BlockHash : Handle<btck_BlockHash, uint256> {}; 494 struct btck_TransactionInput : Handle<btck_TransactionInput, CTxIn> {}; 495 struct btck_TransactionOutPoint: Handle<btck_TransactionOutPoint, COutPoint> {}; 496 struct btck_Txid: Handle<btck_Txid, Txid> {}; 497 struct btck_PrecomputedTransactionData : Handle<btck_PrecomputedTransactionData, PrecomputedTransactionData> {}; 498 struct btck_BlockHeader: Handle<btck_BlockHeader, CBlockHeader> {}; 499 500 btck_Transaction* btck_transaction_create(const void* raw_transaction, size_t raw_transaction_len) 501 { 502 if (raw_transaction == nullptr && raw_transaction_len != 0) { 503 return nullptr; 504 } 505 try { 506 SpanReader stream{std::span{reinterpret_cast<const std::byte*>(raw_transaction), raw_transaction_len}}; 507 return btck_Transaction::create(std::make_shared<const CTransaction>(deserialize, TX_WITH_WITNESS, stream)); 508 } catch (...) { 509 return nullptr; 510 } 511 } 512 513 size_t btck_transaction_count_outputs(const btck_Transaction* transaction) 514 { 515 return btck_Transaction::get(transaction)->vout.size(); 516 } 517 518 const btck_TransactionOutput* btck_transaction_get_output_at(const btck_Transaction* transaction, size_t output_index) 519 { 520 const CTransaction& tx = *btck_Transaction::get(transaction); 521 assert(output_index < tx.vout.size()); 522 return btck_TransactionOutput::ref(&tx.vout[output_index]); 523 } 524 525 size_t btck_transaction_count_inputs(const btck_Transaction* transaction) 526 { 527 return btck_Transaction::get(transaction)->vin.size(); 528 } 529 530 const btck_TransactionInput* btck_transaction_get_input_at(const btck_Transaction* transaction, size_t input_index) 531 { 532 assert(input_index < btck_Transaction::get(transaction)->vin.size()); 533 return btck_TransactionInput::ref(&btck_Transaction::get(transaction)->vin[input_index]); 534 } 535 536 const btck_Txid* btck_transaction_get_txid(const btck_Transaction* transaction) 537 { 538 return btck_Txid::ref(&btck_Transaction::get(transaction)->GetHash()); 539 } 540 541 btck_Transaction* btck_transaction_copy(const btck_Transaction* transaction) 542 { 543 return btck_Transaction::copy(transaction); 544 } 545 546 int btck_transaction_to_bytes(const btck_Transaction* transaction, btck_WriteBytes writer, void* user_data) 547 { 548 try { 549 WriterStream ws{writer, user_data}; 550 ws << TX_WITH_WITNESS(btck_Transaction::get(transaction)); 551 return 0; 552 } catch (...) { 553 return -1; 554 } 555 } 556 557 void btck_transaction_destroy(btck_Transaction* transaction) 558 { 559 delete transaction; 560 } 561 562 btck_ScriptPubkey* btck_script_pubkey_create(const void* script_pubkey, size_t script_pubkey_len) 563 { 564 if (script_pubkey == nullptr && script_pubkey_len != 0) { 565 return nullptr; 566 } 567 auto data = std::span{reinterpret_cast<const uint8_t*>(script_pubkey), script_pubkey_len}; 568 return btck_ScriptPubkey::create(data.begin(), data.end()); 569 } 570 571 int btck_script_pubkey_to_bytes(const btck_ScriptPubkey* script_pubkey_, btck_WriteBytes writer, void* user_data) 572 { 573 const auto& script_pubkey{btck_ScriptPubkey::get(script_pubkey_)}; 574 return writer(script_pubkey.data(), script_pubkey.size(), user_data); 575 } 576 577 btck_ScriptPubkey* btck_script_pubkey_copy(const btck_ScriptPubkey* script_pubkey) 578 { 579 return btck_ScriptPubkey::copy(script_pubkey); 580 } 581 582 void btck_script_pubkey_destroy(btck_ScriptPubkey* script_pubkey) 583 { 584 delete script_pubkey; 585 } 586 587 btck_TransactionOutput* btck_transaction_output_create(const btck_ScriptPubkey* script_pubkey, int64_t amount) 588 { 589 return btck_TransactionOutput::create(amount, btck_ScriptPubkey::get(script_pubkey)); 590 } 591 592 btck_TransactionOutput* btck_transaction_output_copy(const btck_TransactionOutput* output) 593 { 594 return btck_TransactionOutput::copy(output); 595 } 596 597 const btck_ScriptPubkey* btck_transaction_output_get_script_pubkey(const btck_TransactionOutput* output) 598 { 599 return btck_ScriptPubkey::ref(&btck_TransactionOutput::get(output).scriptPubKey); 600 } 601 602 int64_t btck_transaction_output_get_amount(const btck_TransactionOutput* output) 603 { 604 return btck_TransactionOutput::get(output).nValue; 605 } 606 607 void btck_transaction_output_destroy(btck_TransactionOutput* output) 608 { 609 delete output; 610 } 611 612 btck_PrecomputedTransactionData* btck_precomputed_transaction_data_create( 613 const btck_Transaction* tx_to, 614 const btck_TransactionOutput** spent_outputs_, size_t spent_outputs_len) 615 { 616 try { 617 const CTransaction& tx{*btck_Transaction::get(tx_to)}; 618 auto txdata{btck_PrecomputedTransactionData::create()}; 619 if (spent_outputs_ != nullptr && spent_outputs_len > 0) { 620 assert(spent_outputs_len == tx.vin.size()); 621 std::vector<CTxOut> spent_outputs; 622 spent_outputs.reserve(spent_outputs_len); 623 for (size_t i = 0; i < spent_outputs_len; i++) { 624 const CTxOut& tx_out{btck_TransactionOutput::get(spent_outputs_[i])}; 625 spent_outputs.push_back(tx_out); 626 } 627 btck_PrecomputedTransactionData::get(txdata).Init(tx, std::move(spent_outputs)); 628 } else { 629 btck_PrecomputedTransactionData::get(txdata).Init(tx, {}); 630 } 631 632 return txdata; 633 } catch (...) { 634 return nullptr; 635 } 636 } 637 638 btck_PrecomputedTransactionData* btck_precomputed_transaction_data_copy(const btck_PrecomputedTransactionData* precomputed_txdata) 639 { 640 return btck_PrecomputedTransactionData::copy(precomputed_txdata); 641 } 642 643 void btck_precomputed_transaction_data_destroy(btck_PrecomputedTransactionData* precomputed_txdata) 644 { 645 delete precomputed_txdata; 646 } 647 648 int btck_script_pubkey_verify(const btck_ScriptPubkey* script_pubkey, 649 const int64_t amount, 650 const btck_Transaction* tx_to, 651 const btck_PrecomputedTransactionData* precomputed_txdata, 652 const unsigned int input_index, 653 const btck_ScriptVerificationFlags flags, 654 btck_ScriptVerifyStatus* status) 655 { 656 // Assert that all specified flags are part of the interface before continuing 657 assert((flags & ~btck_ScriptVerificationFlags_ALL) == 0); 658 659 if (!is_valid_flag_combination(script_verify_flags::from_int(flags))) { 660 if (status) *status = btck_ScriptVerifyStatus_ERROR_INVALID_FLAGS_COMBINATION; 661 return 0; 662 } 663 664 const CTransaction& tx{*btck_Transaction::get(tx_to)}; 665 assert(input_index < tx.vin.size()); 666 667 const PrecomputedTransactionData& txdata{precomputed_txdata ? btck_PrecomputedTransactionData::get(precomputed_txdata) : PrecomputedTransactionData(tx)}; 668 669 if (flags & btck_ScriptVerificationFlags_TAPROOT && txdata.m_spent_outputs.empty()) { 670 if (status) *status = btck_ScriptVerifyStatus_ERROR_SPENT_OUTPUTS_REQUIRED; 671 return 0; 672 } 673 674 if (status) *status = btck_ScriptVerifyStatus_OK; 675 676 bool result = VerifyScript(tx.vin[input_index].scriptSig, 677 btck_ScriptPubkey::get(script_pubkey), 678 &tx.vin[input_index].scriptWitness, 679 script_verify_flags::from_int(flags), 680 TransactionSignatureChecker(&tx, input_index, amount, txdata, MissingDataBehavior::FAIL), 681 nullptr); 682 return result ? 1 : 0; 683 } 684 685 btck_TransactionInput* btck_transaction_input_copy(const btck_TransactionInput* input) 686 { 687 return btck_TransactionInput::copy(input); 688 } 689 690 const btck_TransactionOutPoint* btck_transaction_input_get_out_point(const btck_TransactionInput* input) 691 { 692 return btck_TransactionOutPoint::ref(&btck_TransactionInput::get(input).prevout); 693 } 694 695 void btck_transaction_input_destroy(btck_TransactionInput* input) 696 { 697 delete input; 698 } 699 700 btck_TransactionOutPoint* btck_transaction_out_point_copy(const btck_TransactionOutPoint* out_point) 701 { 702 return btck_TransactionOutPoint::copy(out_point); 703 } 704 705 uint32_t btck_transaction_out_point_get_index(const btck_TransactionOutPoint* out_point) 706 { 707 return btck_TransactionOutPoint::get(out_point).n; 708 } 709 710 const btck_Txid* btck_transaction_out_point_get_txid(const btck_TransactionOutPoint* out_point) 711 { 712 return btck_Txid::ref(&btck_TransactionOutPoint::get(out_point).hash); 713 } 714 715 void btck_transaction_out_point_destroy(btck_TransactionOutPoint* out_point) 716 { 717 delete out_point; 718 } 719 720 btck_Txid* btck_txid_copy(const btck_Txid* txid) 721 { 722 return btck_Txid::copy(txid); 723 } 724 725 void btck_txid_to_bytes(const btck_Txid* txid, unsigned char output[32]) 726 { 727 std::memcpy(output, btck_Txid::get(txid).begin(), 32); 728 } 729 730 int btck_txid_equals(const btck_Txid* txid1, const btck_Txid* txid2) 731 { 732 return btck_Txid::get(txid1) == btck_Txid::get(txid2); 733 } 734 735 void btck_txid_destroy(btck_Txid* txid) 736 { 737 delete txid; 738 } 739 740 void btck_logging_set_options(const btck_LoggingOptions options) 741 { 742 LOCK(cs_main); 743 LogInstance().m_log_timestamps = options.log_timestamps; 744 LogInstance().m_log_time_micros = options.log_time_micros; 745 LogInstance().m_log_threadnames = options.log_threadnames; 746 LogInstance().m_log_sourcelocations = options.log_sourcelocations; 747 LogInstance().m_always_print_category_level = options.always_print_category_levels; 748 } 749 750 void btck_logging_set_level_category(btck_LogCategory category, btck_LogLevel level) 751 { 752 LOCK(cs_main); 753 if (category == btck_LogCategory_ALL) { 754 LogInstance().SetLogLevel(get_bclog_level(level)); 755 } 756 757 LogInstance().AddCategoryLogLevel(get_bclog_flag(category), get_bclog_level(level)); 758 } 759 760 void btck_logging_enable_category(btck_LogCategory category) 761 { 762 LogInstance().EnableCategory(get_bclog_flag(category)); 763 } 764 765 void btck_logging_disable_category(btck_LogCategory category) 766 { 767 LogInstance().DisableCategory(get_bclog_flag(category)); 768 } 769 770 void btck_logging_disable() 771 { 772 LogInstance().DisableLogging(); 773 } 774 775 btck_LoggingConnection* btck_logging_connection_create(btck_LogCallback callback, void* user_data, btck_DestroyCallback user_data_destroy_callback) 776 { 777 try { 778 return btck_LoggingConnection::create(callback, user_data, user_data_destroy_callback); 779 } catch (const std::exception&) { 780 return nullptr; 781 } 782 } 783 784 void btck_logging_connection_destroy(btck_LoggingConnection* connection) 785 { 786 delete connection; 787 } 788 789 btck_ChainParameters* btck_chain_parameters_create(const btck_ChainType chain_type) 790 { 791 switch (chain_type) { 792 case btck_ChainType_MAINNET: { 793 return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::Main().release())); 794 } 795 case btck_ChainType_TESTNET: { 796 return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::TestNet().release())); 797 } 798 case btck_ChainType_TESTNET_4: { 799 return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::TestNet4().release())); 800 } 801 case btck_ChainType_SIGNET: { 802 return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::SigNet({}).release())); 803 } 804 case btck_ChainType_REGTEST: { 805 return btck_ChainParameters::ref(const_cast<CChainParams*>(CChainParams::RegTest({}).release())); 806 } 807 } 808 assert(false); 809 } 810 811 btck_ChainParameters* btck_chain_parameters_copy(const btck_ChainParameters* chain_parameters) 812 { 813 return btck_ChainParameters::copy(chain_parameters); 814 } 815 816 void btck_chain_parameters_destroy(btck_ChainParameters* chain_parameters) 817 { 818 delete chain_parameters; 819 } 820 821 btck_ContextOptions* btck_context_options_create() 822 { 823 return btck_ContextOptions::create(); 824 } 825 826 void btck_context_options_set_chainparams(btck_ContextOptions* options, const btck_ChainParameters* chain_parameters) 827 { 828 // Copy the chainparams, so the caller can free it again 829 LOCK(btck_ContextOptions::get(options).m_mutex); 830 btck_ContextOptions::get(options).m_chainparams = std::make_unique<const CChainParams>(btck_ChainParameters::get(chain_parameters)); 831 } 832 833 void btck_context_options_set_notifications(btck_ContextOptions* options, btck_NotificationInterfaceCallbacks notifications) 834 { 835 // The KernelNotifications are copy-initialized, so the caller can free them again. 836 LOCK(btck_ContextOptions::get(options).m_mutex); 837 btck_ContextOptions::get(options).m_notifications = std::make_shared<KernelNotifications>(notifications); 838 } 839 840 void btck_context_options_set_validation_interface(btck_ContextOptions* options, btck_ValidationInterfaceCallbacks vi_cbs) 841 { 842 LOCK(btck_ContextOptions::get(options).m_mutex); 843 btck_ContextOptions::get(options).m_validation_interface = std::make_shared<KernelValidationInterface>(vi_cbs); 844 } 845 846 void btck_context_options_destroy(btck_ContextOptions* options) 847 { 848 delete options; 849 } 850 851 btck_Context* btck_context_create(const btck_ContextOptions* options) 852 { 853 bool sane{true}; 854 const ContextOptions* opts = options ? &btck_ContextOptions::get(options) : nullptr; 855 auto context{std::make_shared<const Context>(opts, sane)}; 856 if (!sane) { 857 LogError("Kernel context sanity check failed."); 858 return nullptr; 859 } 860 return btck_Context::create(context); 861 } 862 863 btck_Context* btck_context_copy(const btck_Context* context) 864 { 865 return btck_Context::copy(context); 866 } 867 868 int btck_context_interrupt(btck_Context* context) 869 { 870 return (*btck_Context::get(context)->m_interrupt)() ? 0 : -1; 871 } 872 873 void btck_context_destroy(btck_Context* context) 874 { 875 delete context; 876 } 877 878 const btck_BlockTreeEntry* btck_block_tree_entry_get_previous(const btck_BlockTreeEntry* entry) 879 { 880 if (!btck_BlockTreeEntry::get(entry).pprev) { 881 LogInfo("Genesis block has no previous."); 882 return nullptr; 883 } 884 885 return btck_BlockTreeEntry::ref(btck_BlockTreeEntry::get(entry).pprev); 886 } 887 888 btck_BlockValidationState* btck_block_validation_state_create() 889 { 890 return btck_BlockValidationState::create(); 891 } 892 893 btck_BlockValidationState* btck_block_validation_state_copy(const btck_BlockValidationState* state) 894 { 895 return btck_BlockValidationState::copy(state); 896 } 897 898 void btck_block_validation_state_destroy(btck_BlockValidationState* state) 899 { 900 delete state; 901 } 902 903 btck_ValidationMode btck_block_validation_state_get_validation_mode(const btck_BlockValidationState* block_validation_state_) 904 { 905 auto& block_validation_state = btck_BlockValidationState::get(block_validation_state_); 906 if (block_validation_state.IsValid()) return btck_ValidationMode_VALID; 907 if (block_validation_state.IsInvalid()) return btck_ValidationMode_INVALID; 908 return btck_ValidationMode_INTERNAL_ERROR; 909 } 910 911 btck_BlockValidationResult btck_block_validation_state_get_block_validation_result(const btck_BlockValidationState* block_validation_state_) 912 { 913 auto& block_validation_state = btck_BlockValidationState::get(block_validation_state_); 914 switch (block_validation_state.GetResult()) { 915 case BlockValidationResult::BLOCK_RESULT_UNSET: 916 return btck_BlockValidationResult_UNSET; 917 case BlockValidationResult::BLOCK_CONSENSUS: 918 return btck_BlockValidationResult_CONSENSUS; 919 case BlockValidationResult::BLOCK_CACHED_INVALID: 920 return btck_BlockValidationResult_CACHED_INVALID; 921 case BlockValidationResult::BLOCK_INVALID_HEADER: 922 return btck_BlockValidationResult_INVALID_HEADER; 923 case BlockValidationResult::BLOCK_MUTATED: 924 return btck_BlockValidationResult_MUTATED; 925 case BlockValidationResult::BLOCK_MISSING_PREV: 926 return btck_BlockValidationResult_MISSING_PREV; 927 case BlockValidationResult::BLOCK_INVALID_PREV: 928 return btck_BlockValidationResult_INVALID_PREV; 929 case BlockValidationResult::BLOCK_TIME_FUTURE: 930 return btck_BlockValidationResult_TIME_FUTURE; 931 case BlockValidationResult::BLOCK_HEADER_LOW_WORK: 932 return btck_BlockValidationResult_HEADER_LOW_WORK; 933 } // no default case, so the compiler can warn about missing cases 934 assert(false); 935 } 936 937 btck_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) 938 { 939 if (data_dir == nullptr || data_dir_len == 0 || blocks_dir == nullptr || blocks_dir_len == 0) { 940 LogError("Failed to create chainstate manager options: dir must be non-null and non-empty"); 941 return nullptr; 942 } 943 try { 944 fs::path abs_data_dir{fs::absolute(fs::PathFromString({data_dir, data_dir_len}))}; 945 fs::create_directories(abs_data_dir); 946 fs::path abs_blocks_dir{fs::absolute(fs::PathFromString({blocks_dir, blocks_dir_len}))}; 947 fs::create_directories(abs_blocks_dir); 948 return btck_ChainstateManagerOptions::create(btck_Context::get(context), abs_data_dir, abs_blocks_dir); 949 } catch (const std::exception& e) { 950 LogError("Failed to create chainstate manager options: %s", e.what()); 951 return nullptr; 952 } 953 } 954 955 void btck_chainstate_manager_options_set_worker_threads_num(btck_ChainstateManagerOptions* opts, int worker_threads) 956 { 957 LOCK(btck_ChainstateManagerOptions::get(opts).m_mutex); 958 btck_ChainstateManagerOptions::get(opts).m_chainman_options.worker_threads_num = worker_threads; 959 } 960 961 void btck_chainstate_manager_options_destroy(btck_ChainstateManagerOptions* options) 962 { 963 delete options; 964 } 965 966 int btck_chainstate_manager_options_set_wipe_dbs(btck_ChainstateManagerOptions* chainman_opts, int wipe_block_tree_db, int wipe_chainstate_db) 967 { 968 if (wipe_block_tree_db == 1 && wipe_chainstate_db != 1) { 969 LogError("Wiping the block tree db without also wiping the chainstate db is currently unsupported."); 970 return -1; 971 } 972 auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)}; 973 LOCK(opts.m_mutex); 974 opts.m_blockman_options.block_tree_db_params.wipe_data = wipe_block_tree_db == 1; 975 opts.m_chainstate_load_options.wipe_chainstate_db = wipe_chainstate_db == 1; 976 return 0; 977 } 978 979 void btck_chainstate_manager_options_update_block_tree_db_in_memory( 980 btck_ChainstateManagerOptions* chainman_opts, 981 int block_tree_db_in_memory) 982 { 983 auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)}; 984 LOCK(opts.m_mutex); 985 opts.m_blockman_options.block_tree_db_params.memory_only = block_tree_db_in_memory == 1; 986 } 987 988 void btck_chainstate_manager_options_update_chainstate_db_in_memory( 989 btck_ChainstateManagerOptions* chainman_opts, 990 int chainstate_db_in_memory) 991 { 992 auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)}; 993 LOCK(opts.m_mutex); 994 opts.m_chainstate_load_options.coins_db_in_memory = chainstate_db_in_memory == 1; 995 } 996 997 btck_ChainstateManager* btck_chainstate_manager_create( 998 const btck_ChainstateManagerOptions* chainman_opts) 999 { 1000 auto& opts{btck_ChainstateManagerOptions::get(chainman_opts)}; 1001 std::unique_ptr<ChainstateManager> chainman; 1002 try { 1003 LOCK(opts.m_mutex); 1004 chainman = std::make_unique<ChainstateManager>(*opts.m_context->m_interrupt, opts.m_chainman_options, opts.m_blockman_options); 1005 } catch (const std::exception& e) { 1006 LogError("Failed to create chainstate manager: %s", e.what()); 1007 return nullptr; 1008 } 1009 1010 try { 1011 const auto chainstate_load_opts{WITH_LOCK(opts.m_mutex, return opts.m_chainstate_load_options)}; 1012 1013 kernel::CacheSizes cache_sizes{DEFAULT_KERNEL_CACHE}; 1014 auto [status, chainstate_err]{node::LoadChainstate(*chainman, cache_sizes, chainstate_load_opts)}; 1015 if (status != node::ChainstateLoadStatus::SUCCESS) { 1016 LogError("Failed to load chain state from your data directory: %s", chainstate_err.original); 1017 return nullptr; 1018 } 1019 std::tie(status, chainstate_err) = node::VerifyLoadedChainstate(*chainman, chainstate_load_opts); 1020 if (status != node::ChainstateLoadStatus::SUCCESS) { 1021 LogError("Failed to verify loaded chain state from your datadir: %s", chainstate_err.original); 1022 return nullptr; 1023 } 1024 if (auto result = chainman->ActivateBestChains(); !result) { 1025 LogError("%s", util::ErrorString(result).original); 1026 return nullptr; 1027 } 1028 } catch (const std::exception& e) { 1029 LogError("Failed to load chainstate: %s", e.what()); 1030 return nullptr; 1031 } 1032 1033 return btck_ChainstateManager::create(std::move(chainman), opts.m_context); 1034 } 1035 1036 const btck_BlockTreeEntry* btck_chainstate_manager_get_block_tree_entry_by_hash(const btck_ChainstateManager* chainman, const btck_BlockHash* block_hash) 1037 { 1038 auto block_index = WITH_LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex(), 1039 return btck_ChainstateManager::get(chainman).m_chainman->m_blockman.LookupBlockIndex(btck_BlockHash::get(block_hash))); 1040 if (!block_index) { 1041 LogDebug(BCLog::KERNEL, "A block with the given hash is not indexed."); 1042 return nullptr; 1043 } 1044 return btck_BlockTreeEntry::ref(block_index); 1045 } 1046 1047 const btck_BlockTreeEntry* btck_chainstate_manager_get_best_entry(const btck_ChainstateManager* chainstate_manager) 1048 { 1049 auto& chainman = *btck_ChainstateManager::get(chainstate_manager).m_chainman; 1050 return btck_BlockTreeEntry::ref(WITH_LOCK(chainman.GetMutex(), return chainman.m_best_header)); 1051 } 1052 1053 void btck_chainstate_manager_destroy(btck_ChainstateManager* chainman) 1054 { 1055 { 1056 LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex()); 1057 for (const auto& chainstate : btck_ChainstateManager::get(chainman).m_chainman->m_chainstates) { 1058 if (chainstate->CanFlushToDisk()) { 1059 chainstate->ForceFlushStateToDisk(); 1060 chainstate->ResetCoinsViews(); 1061 } 1062 } 1063 } 1064 1065 delete chainman; 1066 } 1067 1068 int 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) 1069 { 1070 try { 1071 std::vector<fs::path> import_files; 1072 import_files.reserve(block_file_paths_data_len); 1073 for (uint32_t i = 0; i < block_file_paths_data_len; i++) { 1074 if (block_file_paths_data[i] != nullptr) { 1075 import_files.emplace_back(std::string{block_file_paths_data[i], block_file_paths_lens[i]}.c_str()); 1076 } 1077 } 1078 auto& chainman_ref{*btck_ChainstateManager::get(chainman).m_chainman}; 1079 node::ImportBlocks(chainman_ref, import_files); 1080 WITH_LOCK(::cs_main, chainman_ref.UpdateIBDStatus()); 1081 } catch (const std::exception& e) { 1082 LogError("Failed to import blocks: %s", e.what()); 1083 return -1; 1084 } 1085 return 0; 1086 } 1087 1088 btck_Block* btck_block_create(const void* raw_block, size_t raw_block_length) 1089 { 1090 if (raw_block == nullptr && raw_block_length != 0) { 1091 return nullptr; 1092 } 1093 auto block{std::make_shared<CBlock>()}; 1094 1095 SpanReader stream{std::span{reinterpret_cast<const std::byte*>(raw_block), raw_block_length}}; 1096 1097 try { 1098 stream >> TX_WITH_WITNESS(*block); 1099 } catch (...) { 1100 LogDebug(BCLog::KERNEL, "Block decode failed."); 1101 return nullptr; 1102 } 1103 1104 return btck_Block::create(block); 1105 } 1106 1107 btck_Block* btck_block_copy(const btck_Block* block) 1108 { 1109 return btck_Block::copy(block); 1110 } 1111 1112 size_t btck_block_count_transactions(const btck_Block* block) 1113 { 1114 return btck_Block::get(block)->vtx.size(); 1115 } 1116 1117 const btck_Transaction* btck_block_get_transaction_at(const btck_Block* block, size_t index) 1118 { 1119 assert(index < btck_Block::get(block)->vtx.size()); 1120 return btck_Transaction::ref(&btck_Block::get(block)->vtx[index]); 1121 } 1122 1123 btck_BlockHeader* btck_block_get_header(const btck_Block* block) 1124 { 1125 const auto& block_ptr = btck_Block::get(block); 1126 return btck_BlockHeader::create(static_cast<const CBlockHeader&>(*block_ptr)); 1127 } 1128 1129 int btck_block_to_bytes(const btck_Block* block, btck_WriteBytes writer, void* user_data) 1130 { 1131 try { 1132 WriterStream ws{writer, user_data}; 1133 ws << TX_WITH_WITNESS(*btck_Block::get(block)); 1134 return 0; 1135 } catch (...) { 1136 return -1; 1137 } 1138 } 1139 1140 btck_BlockHash* btck_block_get_hash(const btck_Block* block) 1141 { 1142 return btck_BlockHash::create(btck_Block::get(block)->GetHash()); 1143 } 1144 1145 void btck_block_destroy(btck_Block* block) 1146 { 1147 delete block; 1148 } 1149 1150 btck_Block* btck_block_read(const btck_ChainstateManager* chainman, const btck_BlockTreeEntry* entry) 1151 { 1152 auto block{std::make_shared<CBlock>()}; 1153 if (!btck_ChainstateManager::get(chainman).m_chainman->m_blockman.ReadBlock(*block, btck_BlockTreeEntry::get(entry))) { 1154 LogError("Failed to read block."); 1155 return nullptr; 1156 } 1157 return btck_Block::create(block); 1158 } 1159 1160 btck_BlockHeader* btck_block_tree_entry_get_block_header(const btck_BlockTreeEntry* entry) 1161 { 1162 return btck_BlockHeader::create(btck_BlockTreeEntry::get(entry).GetBlockHeader()); 1163 } 1164 1165 int32_t btck_block_tree_entry_get_height(const btck_BlockTreeEntry* entry) 1166 { 1167 return btck_BlockTreeEntry::get(entry).nHeight; 1168 } 1169 1170 const btck_BlockHash* btck_block_tree_entry_get_block_hash(const btck_BlockTreeEntry* entry) 1171 { 1172 return btck_BlockHash::ref(btck_BlockTreeEntry::get(entry).phashBlock); 1173 } 1174 1175 int btck_block_tree_entry_equals(const btck_BlockTreeEntry* entry1, const btck_BlockTreeEntry* entry2) 1176 { 1177 return &btck_BlockTreeEntry::get(entry1) == &btck_BlockTreeEntry::get(entry2); 1178 } 1179 1180 btck_BlockHash* btck_block_hash_create(const unsigned char block_hash[32]) 1181 { 1182 return btck_BlockHash::create(std::span<const unsigned char>{block_hash, 32}); 1183 } 1184 1185 btck_BlockHash* btck_block_hash_copy(const btck_BlockHash* block_hash) 1186 { 1187 return btck_BlockHash::copy(block_hash); 1188 } 1189 1190 void btck_block_hash_to_bytes(const btck_BlockHash* block_hash, unsigned char output[32]) 1191 { 1192 std::memcpy(output, btck_BlockHash::get(block_hash).begin(), 32); 1193 } 1194 1195 int btck_block_hash_equals(const btck_BlockHash* hash1, const btck_BlockHash* hash2) 1196 { 1197 return btck_BlockHash::get(hash1) == btck_BlockHash::get(hash2); 1198 } 1199 1200 void btck_block_hash_destroy(btck_BlockHash* hash) 1201 { 1202 delete hash; 1203 } 1204 1205 btck_BlockSpentOutputs* btck_block_spent_outputs_read(const btck_ChainstateManager* chainman, const btck_BlockTreeEntry* entry) 1206 { 1207 auto block_undo{std::make_shared<CBlockUndo>()}; 1208 if (btck_BlockTreeEntry::get(entry).nHeight < 1) { 1209 LogDebug(BCLog::KERNEL, "The genesis block does not have any spent outputs."); 1210 return btck_BlockSpentOutputs::create(block_undo); 1211 } 1212 if (!btck_ChainstateManager::get(chainman).m_chainman->m_blockman.ReadBlockUndo(*block_undo, btck_BlockTreeEntry::get(entry))) { 1213 LogError("Failed to read block spent outputs data."); 1214 return nullptr; 1215 } 1216 return btck_BlockSpentOutputs::create(block_undo); 1217 } 1218 1219 btck_BlockSpentOutputs* btck_block_spent_outputs_copy(const btck_BlockSpentOutputs* block_spent_outputs) 1220 { 1221 return btck_BlockSpentOutputs::copy(block_spent_outputs); 1222 } 1223 1224 size_t btck_block_spent_outputs_count(const btck_BlockSpentOutputs* block_spent_outputs) 1225 { 1226 return btck_BlockSpentOutputs::get(block_spent_outputs)->vtxundo.size(); 1227 } 1228 1229 const btck_TransactionSpentOutputs* btck_block_spent_outputs_get_transaction_spent_outputs_at(const btck_BlockSpentOutputs* block_spent_outputs, size_t transaction_index) 1230 { 1231 assert(transaction_index < btck_BlockSpentOutputs::get(block_spent_outputs)->vtxundo.size()); 1232 const auto* tx_undo{&btck_BlockSpentOutputs::get(block_spent_outputs)->vtxundo.at(transaction_index)}; 1233 return btck_TransactionSpentOutputs::ref(tx_undo); 1234 } 1235 1236 void btck_block_spent_outputs_destroy(btck_BlockSpentOutputs* block_spent_outputs) 1237 { 1238 delete block_spent_outputs; 1239 } 1240 1241 btck_TransactionSpentOutputs* btck_transaction_spent_outputs_copy(const btck_TransactionSpentOutputs* transaction_spent_outputs) 1242 { 1243 return btck_TransactionSpentOutputs::copy(transaction_spent_outputs); 1244 } 1245 1246 size_t btck_transaction_spent_outputs_count(const btck_TransactionSpentOutputs* transaction_spent_outputs) 1247 { 1248 return btck_TransactionSpentOutputs::get(transaction_spent_outputs).vprevout.size(); 1249 } 1250 1251 void btck_transaction_spent_outputs_destroy(btck_TransactionSpentOutputs* transaction_spent_outputs) 1252 { 1253 delete transaction_spent_outputs; 1254 } 1255 1256 const btck_Coin* btck_transaction_spent_outputs_get_coin_at(const btck_TransactionSpentOutputs* transaction_spent_outputs, size_t coin_index) 1257 { 1258 assert(coin_index < btck_TransactionSpentOutputs::get(transaction_spent_outputs).vprevout.size()); 1259 const Coin* coin{&btck_TransactionSpentOutputs::get(transaction_spent_outputs).vprevout.at(coin_index)}; 1260 return btck_Coin::ref(coin); 1261 } 1262 1263 btck_Coin* btck_coin_copy(const btck_Coin* coin) 1264 { 1265 return btck_Coin::copy(coin); 1266 } 1267 1268 uint32_t btck_coin_confirmation_height(const btck_Coin* coin) 1269 { 1270 return btck_Coin::get(coin).nHeight; 1271 } 1272 1273 int btck_coin_is_coinbase(const btck_Coin* coin) 1274 { 1275 return btck_Coin::get(coin).IsCoinBase() ? 1 : 0; 1276 } 1277 1278 const btck_TransactionOutput* btck_coin_get_output(const btck_Coin* coin) 1279 { 1280 return btck_TransactionOutput::ref(&btck_Coin::get(coin).out); 1281 } 1282 1283 void btck_coin_destroy(btck_Coin* coin) 1284 { 1285 delete coin; 1286 } 1287 1288 int btck_chainstate_manager_process_block( 1289 btck_ChainstateManager* chainman, 1290 const btck_Block* block, 1291 int* _new_block) 1292 { 1293 bool new_block; 1294 auto result = btck_ChainstateManager::get(chainman).m_chainman->ProcessNewBlock(btck_Block::get(block), /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/&new_block); 1295 if (_new_block) { 1296 *_new_block = new_block ? 1 : 0; 1297 } 1298 return result ? 0 : -1; 1299 } 1300 1301 int btck_chainstate_manager_process_block_header( 1302 btck_ChainstateManager* chainstate_manager, 1303 const btck_BlockHeader* header, 1304 btck_BlockValidationState* state) 1305 { 1306 try { 1307 auto& chainman = btck_ChainstateManager::get(chainstate_manager).m_chainman; 1308 auto result = chainman->ProcessNewBlockHeaders({&btck_BlockHeader::get(header), 1}, /*min_pow_checked=*/true, btck_BlockValidationState::get(state), /*ppindex=*/nullptr); 1309 1310 return result ? 0 : -1; 1311 } catch (const std::exception& e) { 1312 LogError("Failed to process block header: %s", e.what()); 1313 return -1; 1314 } 1315 } 1316 1317 const btck_Chain* btck_chainstate_manager_get_active_chain(const btck_ChainstateManager* chainman) 1318 { 1319 return btck_Chain::ref(&WITH_LOCK(btck_ChainstateManager::get(chainman).m_chainman->GetMutex(), return btck_ChainstateManager::get(chainman).m_chainman->ActiveChain())); 1320 } 1321 1322 int btck_chain_get_height(const btck_Chain* chain) 1323 { 1324 LOCK(::cs_main); 1325 return btck_Chain::get(chain).Height(); 1326 } 1327 1328 const btck_BlockTreeEntry* btck_chain_get_by_height(const btck_Chain* chain, int height) 1329 { 1330 LOCK(::cs_main); 1331 return btck_BlockTreeEntry::ref(btck_Chain::get(chain)[height]); 1332 } 1333 1334 int btck_chain_contains(const btck_Chain* chain, const btck_BlockTreeEntry* entry) 1335 { 1336 LOCK(::cs_main); 1337 return btck_Chain::get(chain).Contains(&btck_BlockTreeEntry::get(entry)) ? 1 : 0; 1338 } 1339 1340 btck_BlockHeader* btck_block_header_create(const void* raw_block_header, size_t raw_block_header_len) 1341 { 1342 if (raw_block_header == nullptr && raw_block_header_len != 0) { 1343 return nullptr; 1344 } 1345 auto header{std::make_unique<CBlockHeader>()}; 1346 SpanReader stream{std::span{reinterpret_cast<const std::byte*>(raw_block_header), raw_block_header_len}}; 1347 1348 try { 1349 stream >> *header; 1350 } catch (...) { 1351 LogError("Block header decode failed."); 1352 return nullptr; 1353 } 1354 1355 return btck_BlockHeader::ref(header.release()); 1356 } 1357 1358 btck_BlockHeader* btck_block_header_copy(const btck_BlockHeader* header) 1359 { 1360 return btck_BlockHeader::copy(header); 1361 } 1362 1363 btck_BlockHash* btck_block_header_get_hash(const btck_BlockHeader* header) 1364 { 1365 return btck_BlockHash::create(btck_BlockHeader::get(header).GetHash()); 1366 } 1367 1368 const btck_BlockHash* btck_block_header_get_prev_hash(const btck_BlockHeader* header) 1369 { 1370 return btck_BlockHash::ref(&btck_BlockHeader::get(header).hashPrevBlock); 1371 } 1372 1373 uint32_t btck_block_header_get_timestamp(const btck_BlockHeader* header) 1374 { 1375 return btck_BlockHeader::get(header).nTime; 1376 } 1377 1378 uint32_t btck_block_header_get_bits(const btck_BlockHeader* header) 1379 { 1380 return btck_BlockHeader::get(header).nBits; 1381 } 1382 1383 int32_t btck_block_header_get_version(const btck_BlockHeader* header) 1384 { 1385 return btck_BlockHeader::get(header).nVersion; 1386 } 1387 1388 uint32_t btck_block_header_get_nonce(const btck_BlockHeader* header) 1389 { 1390 return btck_BlockHeader::get(header).nNonce; 1391 } 1392 1393 void btck_block_header_destroy(btck_BlockHeader* header) 1394 { 1395 delete header; 1396 }