2121
2222#include < algorithm>
2323#include < iterator>
24+ #include < numeric>
2425#include < unordered_map>
2526#include < utility>
2627#include < bitcoin/system.hpp>
@@ -326,7 +327,7 @@ uint32_t CLASS::to_spend_index(const tx_link& parent_fk,
326327 const spend_link& spend_fk) const NOEXCEPT
327328{
328329 uint32_t index{};
329- for (const auto & in_fk: to_tx_spends (parent_fk))
330+ for (const auto & in_fk: to_spends (parent_fk))
330331 {
331332 if (in_fk == spend_fk) return index;
332333 ++index;
@@ -341,7 +342,7 @@ uint32_t CLASS::to_output_index(const tx_link& parent_fk,
341342 const output_link& output_fk) const NOEXCEPT
342343{
343344 uint32_t index{};
344- for (const auto & out_fk: to_tx_outputs (parent_fk))
345+ for (const auto & out_fk: to_outputs (parent_fk))
345346 {
346347 if (out_fk == output_fk) return index;
347348 ++index;
@@ -356,7 +357,7 @@ spend_link CLASS::to_spender(const tx_link& link,
356357 const foreign_point& point) const NOEXCEPT
357358{
358359 table::spend::get_key spend{};
359- for (const auto & spend_fk: to_tx_spends (link))
360+ for (const auto & spend_fk: to_spends (link))
360361 if (store_.spend .get (spend_fk, spend) && (spend.key == point))
361362 return spend_fk;
362363
@@ -410,7 +411,7 @@ spend_links CLASS::to_spenders(const foreign_point& point) const NOEXCEPT
410411 return fault;
411412
412413 auto found{ false };
413- for (const auto & spend_fk: to_tx_spends (spender.parent_fk ))
414+ for (const auto & spend_fk: to_spends (spender.parent_fk ))
414415 {
415416 table::spend::get_key spend{};
416417 if (!store_.spend .get (it, spend_fk, spend))
@@ -435,7 +436,22 @@ spend_links CLASS::to_spenders(const foreign_point& point) const NOEXCEPT
435436// ----------------------------------------------------------------------------
436437
437438TEMPLATE
438- output_links CLASS::to_tx_outputs (const tx_link& link) const NOEXCEPT
439+ spend_links CLASS::to_spends (const tx_link& link) const NOEXCEPT
440+ {
441+ table::transaction::get_puts tx{};
442+ if (!store_.tx .get (link, tx))
443+ return {};
444+
445+ table::puts::get_spends puts{};
446+ puts.spend_fks .resize (tx.ins_count );
447+ if (!store_.puts .get (tx.puts_fk , puts))
448+ return {};
449+
450+ return std::move (puts.spend_fks );
451+ }
452+
453+ TEMPLATE
454+ output_links CLASS::to_outputs (const tx_link& link) const NOEXCEPT
439455{
440456 table::transaction::get_puts tx{};
441457 if (!store_.tx .get (link, tx))
@@ -450,18 +466,18 @@ output_links CLASS::to_tx_outputs(const tx_link& link) const NOEXCEPT
450466}
451467
452468TEMPLATE
453- spend_links CLASS::to_tx_spends (const tx_link& link) const NOEXCEPT
469+ output_links CLASS::to_prevouts (const tx_link& link) const NOEXCEPT
454470{
455- table::transaction::get_puts tx{} ;
456- if (!store_. tx . get (link, tx ))
471+ const auto spends = to_spends (link) ;
472+ if (spends. empty ( ))
457473 return {};
458474
459- table::puts::get_spends puts {};
460- puts. spend_fks . resize (tx. ins_count );
461- if (!store_. puts . get (tx. puts_fk , puts) )
462- return {} ;
475+ output_links prevouts {};
476+ prevouts. reserve (spends. size () );
477+ for ( const auto & spend: spends )
478+ prevouts. push_back ( to_prevout (spend)) ;
463479
464- return std::move (puts. spend_fks ) ;
480+ return prevouts ;
465481}
466482
467483// protected
@@ -502,29 +518,71 @@ spend_set CLASS::to_spend_set(const tx_link& link) const NOEXCEPT
502518 return set;
503519}
504520
505- // block to txs/ puts (forward navigation)
521+ // txs to puts (forward navigation)
506522// ----------------------------------------------------------------------------
507523
508524TEMPLATE
509- tx_links CLASS::to_transactions (const header_link& link ) const NOEXCEPT
525+ spend_links CLASS::to_spends (const tx_links& txs ) const NOEXCEPT
510526{
511- table::txs::get_txs txs{};
512- if (!store_.txs .find (link, txs))
513- return {};
527+ spend_links spends{};
528+ for (const auto & tx: txs)
529+ {
530+ const auto tx_spends = to_spends (tx);
531+ spends.insert (spends.end (), tx_spends.begin (), tx_spends.end ());
532+ }
514533
515- return std::move (txs. tx_fks ) ;
534+ return spends ;
516535}
517536
518537TEMPLATE
519- tx_links CLASS::to_spending_transactions (const header_link& link ) const NOEXCEPT
538+ output_links CLASS::to_outputs (const tx_links& txs ) const NOEXCEPT
520539{
521- table::txs::get_spending_txs txs{};
522- if (!store_.txs .find (link, txs))
523- return {};
540+ output_links outputs{};
541+ for (const auto & tx: txs)
542+ {
543+ const auto tx_outputs = to_outputs (tx);
544+ outputs.insert (outputs.end (), tx_outputs.begin (), tx_outputs.end ());
545+ }
524546
525- return std::move (txs.tx_fks );
547+ return outputs;
548+ }
549+
550+ TEMPLATE
551+ output_links CLASS::to_prevouts (const tx_links& txs) const NOEXCEPT
552+ {
553+ const auto ins = to_spends (txs);
554+ output_links outs (ins.size ());
555+ const auto fn = [this ](auto spend) NOEXCEPT{ return to_prevout (spend); };
556+
557+ // C++17 incomplete on GCC/CLang, so presently parallel only on MSVC++.
558+ std_transform (bc::par_unseq, ins.begin (), ins.end (), outs.begin (), fn);
559+ return outs;
560+ }
561+
562+ // block to puts (forward navigation)
563+ // ----------------------------------------------------------------------------
564+
565+ TEMPLATE
566+ spend_links CLASS::to_block_spends (const header_link& link) const NOEXCEPT
567+ {
568+ return to_spends (to_spending_transactions (link));
526569}
527570
571+ TEMPLATE
572+ output_links CLASS::to_block_outputs (const header_link& link) const NOEXCEPT
573+ {
574+ return to_outputs (to_transactions (link));
575+ }
576+
577+ TEMPLATE
578+ output_links CLASS::to_block_prevouts (const header_link& link) const NOEXCEPT
579+ {
580+ return to_prevouts (to_spending_transactions (link));
581+ }
582+
583+ // block to txs (forward navigation)
584+ // ----------------------------------------------------------------------------
585+
528586TEMPLATE
529587tx_link CLASS::to_coinbase (const header_link& link) const NOEXCEPT
530588{
@@ -536,33 +594,23 @@ tx_link CLASS::to_coinbase(const header_link& link) const NOEXCEPT
536594}
537595
538596TEMPLATE
539- spend_links CLASS::to_block_spends (const header_link& link) const NOEXCEPT
597+ tx_links CLASS::to_transactions (const header_link& link) const NOEXCEPT
540598{
541- spend_links spends{};
542- const auto txs = to_transactions (link);
543-
544- for (const auto & tx: txs)
545- {
546- const auto tx_spends = to_tx_spends (tx);
547- spends.insert (spends.end (), tx_spends.begin (), tx_spends.end ());
548- }
599+ table::txs::get_txs txs{};
600+ if (!store_.txs .find (link, txs))
601+ return {};
549602
550- return spends ;
603+ return std::move (txs. tx_fks ) ;
551604}
552605
553606TEMPLATE
554- output_links CLASS::to_block_outputs (const header_link& link) const NOEXCEPT
607+ tx_links CLASS::to_spending_transactions (const header_link& link) const NOEXCEPT
555608{
556- output_links outputs{};
557- const auto txs = to_transactions (link);
558-
559- for (const auto & tx: txs)
560- {
561- const auto tx_outputs = to_tx_outputs (tx);
562- outputs.insert (outputs.end (), tx_outputs.begin (), tx_outputs.end ());
563- }
609+ table::txs::get_spending_txs txs{};
610+ if (!store_.txs .find (link, txs))
611+ return {};
564612
565- return outputs ;
613+ return std::move (txs. tx_fks ) ;
566614}
567615
568616// hashmap enumeration
0 commit comments