@@ -150,6 +150,9 @@ struct btck_BlockTreeEntry: Handle<btck_BlockTreeEntry, CBlockIndex> {};
150150struct btck_Block : Handle<btck_Block, std::shared_ptr<const CBlock>> {};
151151struct btck_BlockValidationState : Handle<btck_BlockValidationState, BlockValidationState> {};
152152struct btck_TxValidationState : Handle<btck_TxValidationState, TxValidationState> {};
153+ // A chain is fully determined by its tip block, so it is represented by the
154+ // CBlockIndex of that tip - the same underlying type as a btck_BlockTreeEntry.
155+ struct btck_Chain : Handle<btck_Chain, CBlockIndex> {};
153156
154157namespace {
155158
@@ -494,7 +497,6 @@ struct btck_Context : Handle<btck_Context, std::shared_ptr<const Context>> {};
494497struct btck_ChainParameters : Handle<btck_ChainParameters, CChainParams> {};
495498struct btck_ChainstateManagerOptions : Handle<btck_ChainstateManagerOptions, ChainstateManagerOptions> {};
496499struct btck_ChainstateManager : Handle<btck_ChainstateManager, ChainMan> {};
497- struct btck_Chain : Handle<btck_Chain, CChain> {};
498500struct btck_BlockSpentOutputs : Handle<btck_BlockSpentOutputs, std::shared_ptr<CBlockUndo>> {};
499501struct btck_TransactionSpentOutputs : Handle<btck_TransactionSpentOutputs, CTxUndo> {};
500502struct btck_Coin : Handle<btck_Coin, Coin> {};
@@ -912,6 +914,32 @@ const btck_BlockTreeEntry* btck_block_tree_entry_get_ancestor(const btck_BlockTr
912914 return btck_BlockTreeEntry::ref (ancestor);
913915}
914916
917+ btck_BlockHeader* btck_block_tree_entry_get_block_header (const btck_BlockTreeEntry* entry)
918+ {
919+ return btck_BlockHeader::create (btck_BlockTreeEntry::get (entry).GetBlockHeader ());
920+ }
921+
922+ int32_t btck_block_tree_entry_get_height (const btck_BlockTreeEntry* entry)
923+ {
924+ return btck_BlockTreeEntry::get (entry).nHeight ;
925+ }
926+
927+ const btck_BlockHash* btck_block_tree_entry_get_block_hash (const btck_BlockTreeEntry* entry)
928+ {
929+ return btck_BlockHash::ref (btck_BlockTreeEntry::get (entry).phashBlock );
930+ }
931+
932+ int btck_block_tree_entry_equals (const btck_BlockTreeEntry* entry1, const btck_BlockTreeEntry* entry2)
933+ {
934+ return &btck_BlockTreeEntry::get (entry1) == &btck_BlockTreeEntry::get (entry2);
935+ }
936+
937+ const btck_Chain* btck_block_tree_entry_get_chain (const btck_BlockTreeEntry* entry)
938+ {
939+ // A chain and a block tree entry share the same underlying CBlockIndex.
940+ return btck_Chain::ref (&btck_BlockTreeEntry::get (entry));
941+ }
942+
915943btck_BlockValidationState* btck_block_validation_state_create ()
916944{
917945 return btck_BlockValidationState::create ();
@@ -1062,6 +1090,17 @@ btck_ChainstateManager* btck_chainstate_manager_create(
10621090 return btck_ChainstateManager::create (std::move (chainman), opts.m_context );
10631091}
10641092
1093+ const btck_Chain* btck_chainstate_manager_find (const btck_ChainstateManager* chainman, const btck_BlockHash* block_hash)
1094+ {
1095+ auto block_index = WITH_LOCK (btck_ChainstateManager::get (chainman).m_chainman ->GetMutex (),
1096+ return btck_ChainstateManager::get (chainman).m_chainman ->m_blockman .LookupBlockIndex (btck_BlockHash::get (block_hash)));
1097+ if (!block_index) {
1098+ LogDebug (BCLog::KERNEL , " A block with the given hash is not indexed." );
1099+ return nullptr ;
1100+ }
1101+ return btck_Chain::ref (block_index);
1102+ }
1103+
10651104const btck_BlockTreeEntry* btck_chainstate_manager_get_block_tree_entry_by_hash (const btck_ChainstateManager* chainman, const btck_BlockHash* block_hash)
10661105{
10671106 auto block_index = WITH_LOCK (btck_ChainstateManager::get (chainman).m_chainman ->GetMutex (),
@@ -1073,6 +1112,12 @@ const btck_BlockTreeEntry* btck_chainstate_manager_get_block_tree_entry_by_hash(
10731112 return btck_BlockTreeEntry::ref (block_index);
10741113}
10751114
1115+ const btck_Chain* btck_chainstate_manager_get_best_chain (const btck_ChainstateManager* chainstate_manager)
1116+ {
1117+ auto & chainman = *btck_ChainstateManager::get (chainstate_manager).m_chainman ;
1118+ return btck_Chain::ref (WITH_LOCK (chainman.GetMutex (), return chainman.m_best_header ));
1119+ }
1120+
10761121const btck_BlockTreeEntry* btck_chainstate_manager_get_best_entry (const btck_ChainstateManager* chainstate_manager)
10771122{
10781123 auto & chainman = *btck_ChainstateManager::get (chainstate_manager).m_chainman ;
@@ -1196,26 +1241,6 @@ btck_Block* btck_block_read(const btck_ChainstateManager* chainman, const btck_B
11961241 return btck_Block::create (block);
11971242}
11981243
1199- btck_BlockHeader* btck_block_tree_entry_get_block_header (const btck_BlockTreeEntry* entry)
1200- {
1201- return btck_BlockHeader::create (btck_BlockTreeEntry::get (entry).GetBlockHeader ());
1202- }
1203-
1204- int32_t btck_block_tree_entry_get_height (const btck_BlockTreeEntry* entry)
1205- {
1206- return btck_BlockTreeEntry::get (entry).nHeight ;
1207- }
1208-
1209- const btck_BlockHash* btck_block_tree_entry_get_block_hash (const btck_BlockTreeEntry* entry)
1210- {
1211- return btck_BlockHash::ref (btck_BlockTreeEntry::get (entry).phashBlock );
1212- }
1213-
1214- int btck_block_tree_entry_equals (const btck_BlockTreeEntry* entry1, const btck_BlockTreeEntry* entry2)
1215- {
1216- return &btck_BlockTreeEntry::get (entry1) == &btck_BlockTreeEntry::get (entry2);
1217- }
1218-
12191244btck_BlockHash* btck_block_hash_create (const unsigned char block_hash[32 ])
12201245{
12211246 return btck_BlockHash::create (std::span<const unsigned char >{block_hash, 32 });
@@ -1355,25 +1380,93 @@ btck_BlockValidationState* btck_chainstate_manager_process_block_header(
13551380
13561381const btck_Chain* btck_chainstate_manager_get_active_chain (const btck_ChainstateManager* chainman)
13571382{
1358- return btck_Chain::ref (& WITH_LOCK (btck_ChainstateManager::get (chainman).m_chainman ->GetMutex (), return btck_ChainstateManager::get (chainman).m_chainman ->ActiveChain ()));
1383+ return btck_Chain::ref (WITH_LOCK (btck_ChainstateManager::get (chainman).m_chainman ->GetMutex (), return btck_ChainstateManager::get (chainman).m_chainman ->ActiveChain (). Tip ()));
13591384}
13601385
13611386int32_t btck_chain_get_height (const btck_Chain* chain)
13621387{
13631388 LOCK (::cs_main);
1364- return btck_Chain::get (chain).Height ();
1389+ return btck_Chain::get (chain).nHeight ;
1390+ }
1391+
1392+ const btck_BlockTreeEntry* btck_chain_get_tip (const btck_Chain* chain)
1393+ {
1394+ // A chain and a block tree entry share the same underlying CBlockIndex.
1395+ return btck_BlockTreeEntry::ref (&btck_Chain::get (chain));
13651396}
13661397
13671398const btck_BlockTreeEntry* btck_chain_get_by_height (const btck_Chain* chain, int32_t height)
13681399{
13691400 LOCK (::cs_main);
1370- return btck_BlockTreeEntry::ref (btck_Chain::get (chain)[ height] );
1401+ return btck_BlockTreeEntry::ref (btck_Chain::get (chain). GetAncestor ( height) );
13711402}
13721403
13731404int btck_chain_contains (const btck_Chain* chain, const btck_BlockTreeEntry* entry)
13741405{
13751406 LOCK (::cs_main);
1376- return btck_Chain::get (chain).Contains (btck_BlockTreeEntry::get (entry)) ? 1 : 0 ;
1407+ const auto & tip{btck_Chain::get (chain)};
1408+ const auto & block{btck_BlockTreeEntry::get (entry)};
1409+ return tip.GetAncestor (block.nHeight ) == &block ? 1 : 0 ;
1410+ }
1411+
1412+ btck_BlockHeader* btck_chain_get_block_header (const btck_Chain* chain, int32_t height)
1413+ {
1414+ const auto * index{btck_Chain::get (chain).GetAncestor (height)};
1415+ if (!index) {
1416+ LogDebug (BCLog::KERNEL , " The requested height is not in the chain." );
1417+ return nullptr ;
1418+ }
1419+ return btck_BlockHeader::create (index->GetBlockHeader ());
1420+ }
1421+
1422+ const btck_BlockHash* btck_chain_get_block_hash (const btck_Chain* chain, int32_t height)
1423+ {
1424+ const auto * index{btck_Chain::get (chain).GetAncestor (height)};
1425+ if (!index) {
1426+ LogDebug (BCLog::KERNEL , " The requested height is not in the chain." );
1427+ return nullptr ;
1428+ }
1429+ return btck_BlockHash::ref (index->phashBlock );
1430+ }
1431+
1432+ const btck_Chain* btck_chain_get_ancestor (const btck_Chain* chain, int32_t height)
1433+ {
1434+ const auto * ancestor{btck_Chain::get (chain).GetAncestor (height)};
1435+ if (!ancestor) {
1436+ LogDebug (BCLog::KERNEL , " The requested height is not in the chain." );
1437+ return nullptr ;
1438+ }
1439+ return btck_Chain::ref (ancestor);
1440+ }
1441+
1442+ const btck_Chain* btck_chain_get_parent (const btck_Chain* chain)
1443+ {
1444+ const auto * pprev{btck_Chain::get (chain).pprev };
1445+ if (!pprev) {
1446+ return nullptr ;
1447+ }
1448+ return btck_Chain::ref (pprev);
1449+ }
1450+
1451+ int btck_chain_starts_with (const btck_Chain* chain, const btck_Chain* prefix)
1452+ {
1453+ const auto & tip{btck_Chain::get (chain)};
1454+ const auto & prefix_tip{btck_Chain::get (prefix)};
1455+ return tip.GetAncestor (prefix_tip.nHeight ) == &prefix_tip ? 1 : 0 ;
1456+ }
1457+
1458+ const btck_Chain* btck_chain_mismatch (const btck_Chain* chain1, const btck_Chain* chain2)
1459+ {
1460+ const auto * common{LastCommonAncestor (&btck_Chain::get (chain1), &btck_Chain::get (chain2))};
1461+ if (!common) {
1462+ return nullptr ;
1463+ }
1464+ return btck_Chain::ref (common);
1465+ }
1466+
1467+ int btck_chain_equals (const btck_Chain* chain1, const btck_Chain* chain2)
1468+ {
1469+ return &btck_Chain::get (chain1) == &btck_Chain::get (chain2) ? 1 : 0 ;
13771470}
13781471
13791472btck_BlockHeader* btck_block_header_create (const void * raw_block_header, size_t raw_block_header_len)
0 commit comments