2525#include < bitcoin/server/define.hpp>
2626#include < bitcoin/server/parsers/parsers.hpp>
2727
28+ // TODO: rationalize confirmed state against database (to_block vs. to_strong).
29+
2830namespace libbitcoin {
2931namespace server {
3032
@@ -248,13 +250,16 @@ bool protocol_explore::handle_get_configuration(const code& ec,
248250 return true ;
249251 }
250252
251- boost::json::object object{};
252- object[" address" ] = archive ().address_enabled ();
253- object[" filter" ] = archive ().filter_enabled ();
254- object[" turbo" ] = database_settings ().turbo ;
255- object[" witness" ] = network_settings ().witness_node ();
256- object[" retarget" ] = system_settings ().forks .retarget ;
257- object[" difficult" ] = system_settings ().forks .difficult ;
253+ boost::json::object object
254+ {
255+ { " address" , archive ().address_enabled () },
256+ { " filter" , archive ().filter_enabled () },
257+ { " turbo" , database_settings ().turbo },
258+ { " witness" , network_settings ().witness_node () },
259+ { " retarget" , system_settings ().forks .retarget },
260+ { " difficult" , system_settings ().forks .difficult },
261+ };
262+
258263 send_json (std::move (object), 32 );
259264 return true ;
260265}
@@ -367,10 +372,12 @@ bool protocol_explore::handle_get_block_header_context(const code& ec,
367372 return true ;
368373 }
369374
370- boost::json::object object{};
371- object[" hash" ] = encode_hash (query.get_header_key (link));
372- object[" height" ] = context.height ;
373- object[" mtp" ] = context.mtp ;
375+ boost::json::object object
376+ {
377+ { " hash" , encode_hash (query.get_header_key (link)) },
378+ { " height" , context.height },
379+ { " mtp" , context.mtp },
380+ };
374381
375382 // The "state" element implies transactions are associated.
376383 if (query.is_associated (link))
@@ -447,7 +454,7 @@ bool protocol_explore::handle_get_block_details(const code& ec,
447454 // Internal population (optimization).
448455 block->populate ();
449456
450- // False if missing prevouts (not ready).
457+ // Missing prevouts (not ready).
451458 if (!query.populate_without_metadata (*block))
452459 {
453460 send_not_found ();
@@ -462,19 +469,21 @@ bool protocol_explore::handle_get_block_details(const code& ec,
462469 const auto subsidy = chain::block::subsidy (context.height ,
463470 settings.subsidy_interval_blocks , settings.initial_subsidy (), bip42);
464471
465- boost::json::object object{};
466- object[" hash" ] = encode_hash (block->hash ());
467- object[" height" ] = context.height ;
468- object[" count" ] = block->transactions ();
469- object[" sigops" ] = block->signature_operations (bip16, bip141);
470- object[" segregated" ] = block->is_segregated ();
471- object[" nominal" ] = block->serialized_size (false );
472- object[" maximal" ] = block->serialized_size (true );
473- object[" weight" ] = block->weight ();
474- object[" fees" ] = fees;
475- object[" subsidy" ] = subsidy;
476- object[" reward" ] = ceilinged_add (fees, subsidy);
477- object[" claim" ] = block->claim ();
472+ boost::json::object object
473+ {
474+ { " hash" , encode_hash (block->hash ()) },
475+ { " height" , context.height },
476+ { " count" , block->transactions () },
477+ { " sigops" , block->signature_operations (bip16, bip141) },
478+ { " segregated" , block->is_segregated () },
479+ { " nominal" , block->serialized_size (false ) },
480+ { " maximal" , block->serialized_size (true ) },
481+ { " weight" , block->weight () },
482+ { " fees" , fees },
483+ { " subsidy" , subsidy },
484+ { " reward" , ceilinged_add (fees, subsidy) },
485+ { " claim" , block->claim () },
486+ };
478487
479488 send_json (std::move (object), 512 );
480489 return true ;
@@ -736,26 +745,65 @@ bool protocol_explore::handle_get_tx_details(const code& ec,
736745 if (stopped (ec))
737746 return false ;
738747
739- // TODO: expand details to include tx.size and tx.weight.
748+ if (media != json)
749+ {
750+ send_not_acceptable ();
751+ return true ;
752+ }
753+
740754 const auto & query = archive ();
741- if (const auto fee = query.get_tx_fee (query.to_tx (*hash));
742- fee != max_uint64)
755+ const auto link = query.to_tx (*hash);
756+ const auto tx = query.get_transaction (link, true );
757+
758+ // Missing tx.
759+ if (!tx)
743760 {
744- switch (media)
761+ send_not_found ();
762+ return true ;
763+ }
764+
765+ // Non-coinbase missing prevouts (not ready).
766+ const auto coinbase = query.is_coinbase (link);
767+ if (!coinbase && !query.populate_without_metadata (*tx))
768+ {
769+ send_not_found ();
770+ return true ;
771+ }
772+
773+ boost::json::object object
774+ {
775+ { " wtxid" , encode_hash (tx->get_hash (true )) },
776+ { " segregated" , tx->is_segregated () },
777+ { " coinbase" , coinbase },
778+ { " nominal" , tx->serialized_size (false ) },
779+ { " maximal" , tx->serialized_size (true ) },
780+ { " weight" , tx->weight () },
781+ { " value" , tx->value () },
782+ { " spend" , tx->spend () },
783+ { " fee" , tx->fee () }
784+ };
785+
786+ size_t position{};
787+ if (query.get_tx_position (position, link))
788+ {
789+ database::context context{};
790+ if (!query.get_context (context, query.to_strong (link)))
745791 {
746- case data:
747- send_chunk (to_little_endian_size (fee));
748- return true ;
749- case text:
750- send_text (encode_base16 (to_little_endian_size (fee)));
751- return true ;
752- case json:
753- send_json (fee, two * sizeof (fee));
754- return true ;
792+ send_internal_server_error (database::error::integrity);
793+ return true ;
755794 }
795+
796+ const auto bip16 = context.is_enabled (chain::flags::bip16_rule);
797+ const auto bip141 = context.is_enabled (chain::flags::bip141_rule);
798+ object[" confirmed" ] = boost::json::object
799+ {
800+ { " height" , context.height },
801+ { " position" , position },
802+ { " sigops" , tx->signature_operations (bip16, bip141) }
803+ };
756804 }
757805
758- send_not_found ( );
806+ send_json ( std::move (object), 128 );
759807 return true ;
760808}
761809
0 commit comments