18
18
} ,
19
19
bitcoin:: block:: Header ,
20
20
bitcoincore_rpc:: {
21
- json:: { GetBlockHeaderResult , GetBlockStatsResult } ,
21
+ json:: {
22
+ GetBlockHeaderResult , GetBlockStatsResult , GetRawTransactionResult ,
23
+ GetRawTransactionResultVout , GetRawTransactionResultVoutScriptPubKey , GetTxOutResult ,
24
+ } ,
22
25
Client ,
23
26
} ,
24
27
chrono:: SubsecRound ,
@@ -1596,6 +1599,87 @@ impl Index {
1596
1599
Ok ( Some ( result) )
1597
1600
}
1598
1601
1602
+ pub fn get_unspent_or_unconfirmed_output (
1603
+ & self ,
1604
+ txid : & Txid ,
1605
+ vout : u32 ,
1606
+ ) -> Result < Option < GetTxOutResult > > {
1607
+ if txid == & self . genesis_block_coinbase_txid {
1608
+ let Some ( output) = & self
1609
+ . genesis_block_coinbase_transaction
1610
+ . output
1611
+ . get ( vout. into_usize ( ) )
1612
+ else {
1613
+ return Ok ( None ) ;
1614
+ } ;
1615
+
1616
+ return Ok ( Some ( GetTxOutResult {
1617
+ bestblock : self . block_hash ( None ) ?. unwrap ( ) ,
1618
+ coinbase : true ,
1619
+ confirmations : self . block_count ( ) ?,
1620
+ script_pub_key : GetRawTransactionResultVoutScriptPubKey {
1621
+ address : None ,
1622
+ addresses : Vec :: new ( ) ,
1623
+ asm : output. script_pubkey . to_asm_string ( ) ,
1624
+ hex : output. script_pubkey . to_bytes ( ) ,
1625
+ req_sigs : Some ( 1 ) ,
1626
+ type_ : Some ( bitcoincore_rpc:: json:: ScriptPubkeyType :: Pubkey ) ,
1627
+ } ,
1628
+ value : output. value ,
1629
+ } ) ) ;
1630
+ }
1631
+
1632
+ Ok ( self . client . get_tx_out ( txid, vout, Some ( true ) ) ?)
1633
+ }
1634
+
1635
+ pub fn get_transaction_info ( & self , txid : & Txid ) -> Result < Option < GetRawTransactionResult > > {
1636
+ if txid == & self . genesis_block_coinbase_txid {
1637
+ let tx = & self . genesis_block_coinbase_transaction ;
1638
+
1639
+ let block = bitcoin:: blockdata:: constants:: genesis_block ( self . settings . chain ( ) . network ( ) ) ;
1640
+ let time = block. header . time . into_usize ( ) ;
1641
+
1642
+ return Ok ( Some ( GetRawTransactionResult {
1643
+ in_active_chain : Some ( true ) ,
1644
+ hex : consensus:: encode:: serialize ( tx) ,
1645
+ txid : tx. compute_txid ( ) ,
1646
+ hash : tx. compute_wtxid ( ) ,
1647
+ size : tx. total_size ( ) ,
1648
+ vsize : tx. vsize ( ) ,
1649
+ #[ allow( clippy:: cast_sign_loss) ]
1650
+ version : tx. version . 0 as u32 ,
1651
+ locktime : 0 ,
1652
+ vin : Vec :: new ( ) ,
1653
+ vout : tx
1654
+ . output
1655
+ . iter ( )
1656
+ . enumerate ( )
1657
+ . map ( |( n, output) | GetRawTransactionResultVout {
1658
+ n : n. try_into ( ) . unwrap ( ) ,
1659
+ value : output. value ,
1660
+ script_pub_key : GetRawTransactionResultVoutScriptPubKey {
1661
+ asm : output. script_pubkey . to_asm_string ( ) ,
1662
+ hex : output. script_pubkey . clone ( ) . into ( ) ,
1663
+ req_sigs : None ,
1664
+ type_ : None ,
1665
+ addresses : Vec :: new ( ) ,
1666
+ address : None ,
1667
+ } ,
1668
+ } )
1669
+ . collect ( ) ,
1670
+ blockhash : Some ( block. block_hash ( ) ) ,
1671
+ confirmations : Some ( self . block_count ( ) ?) ,
1672
+ time : Some ( time) ,
1673
+ blocktime : Some ( time) ,
1674
+ } ) ) ;
1675
+ }
1676
+
1677
+ self
1678
+ . client
1679
+ . get_raw_transaction_info ( txid, None )
1680
+ . into_option ( )
1681
+ }
1682
+
1599
1683
pub fn get_transaction ( & self , txid : Txid ) -> Result < Option < Transaction > > {
1600
1684
if txid == self . genesis_block_coinbase_txid {
1601
1685
return Ok ( Some ( self . genesis_block_coinbase_transaction . clone ( ) ) ) ;
@@ -2404,9 +2488,12 @@ impl Index {
2404
2488
pub ( crate ) fn get_output_info ( & self , outpoint : OutPoint ) -> Result < Option < ( api:: Output , TxOut ) > > {
2405
2489
let sat_ranges = self . list ( outpoint) ?;
2406
2490
2491
+ let confirmations;
2407
2492
let indexed;
2493
+ let spent;
2494
+ let txout;
2408
2495
2409
- let txout = if outpoint == OutPoint :: null ( ) || outpoint == unbound_outpoint ( ) {
2496
+ if outpoint == OutPoint :: null ( ) || outpoint == unbound_outpoint ( ) {
2410
2497
let mut value = 0 ;
2411
2498
2412
2499
if let Some ( ranges) = & sat_ranges {
@@ -2415,35 +2502,49 @@ impl Index {
2415
2502
}
2416
2503
}
2417
2504
2505
+ confirmations = 0 ;
2418
2506
indexed = true ;
2419
-
2420
- TxOut {
2507
+ spent = false ;
2508
+ txout = TxOut {
2421
2509
value : Amount :: from_sat ( value) ,
2422
2510
script_pubkey : ScriptBuf :: new ( ) ,
2423
- }
2511
+ } ;
2424
2512
} else {
2425
2513
indexed = self . contains_output ( & outpoint) ?;
2426
2514
2427
- let Some ( tx) = self . get_transaction ( outpoint. txid ) ? else {
2428
- return Ok ( None ) ;
2429
- } ;
2515
+ if let Some ( result) = self . get_unspent_or_unconfirmed_output ( & outpoint. txid , outpoint. vout ) ? {
2516
+ confirmations = result. confirmations ;
2517
+ spent = false ;
2518
+ txout = TxOut {
2519
+ value : result. value ,
2520
+ script_pubkey : ScriptBuf :: from_bytes ( result. script_pub_key . hex ) ,
2521
+ } ;
2522
+ } else {
2523
+ let Some ( result) = self . get_transaction_info ( & outpoint. txid ) ? else {
2524
+ return Ok ( None ) ;
2525
+ } ;
2430
2526
2431
- let Some ( txout ) = tx . output . into_iter ( ) . nth ( outpoint. vout as usize ) else {
2432
- return Ok ( None ) ;
2433
- } ;
2527
+ let Some ( output ) = result . vout . into_iter ( ) . nth ( outpoint. vout . into_usize ( ) ) else {
2528
+ return Ok ( None ) ;
2529
+ } ;
2434
2530
2435
- txout
2531
+ confirmations = result. confirmations . unwrap_or_default ( ) ;
2532
+ spent = true ;
2533
+ txout = TxOut {
2534
+ value : output. value ,
2535
+ script_pubkey : ScriptBuf :: from_bytes ( output. script_pub_key . hex ) ,
2536
+ } ;
2537
+ }
2436
2538
} ;
2437
2539
2438
2540
let inscriptions = self . get_inscriptions_for_output ( outpoint) ?;
2439
2541
2440
2542
let runes = self . get_rune_balances_for_output ( outpoint) ?;
2441
2543
2442
- let spent = self . is_output_spent ( outpoint) ?;
2443
-
2444
2544
Ok ( Some ( (
2445
2545
api:: Output :: new (
2446
2546
self . settings . chain ( ) ,
2547
+ confirmations,
2447
2548
inscriptions,
2448
2549
outpoint,
2449
2550
txout. clone ( ) ,
0 commit comments