@@ -10,12 +10,19 @@ use std::{
1010
1111use kaspa_consensus:: {
1212 consensus:: { services:: ConsensusServices , storage:: ConsensusStorage } ,
13- model:: stores:: { acceptance_data:: AcceptanceDataStoreReader , headers:: HeaderStoreReader , pruning:: PruningStoreReader } ,
13+ model:: stores:: {
14+ acceptance_data:: AcceptanceDataStoreReader , block_transactions:: BlockTransactionsStoreReader , headers:: HeaderStoreReader ,
15+ pruning:: PruningStoreReader , utxo_diffs:: UtxoDiffsStoreReader ,
16+ } ,
1417} ;
1518use kaspa_consensus_core:: {
19+ acceptance_data:: MergesetBlockAcceptanceData ,
20+ block,
1621 config:: ConfigBuilder ,
1722 network:: { NetworkId , NetworkType } ,
18- tx:: { ScriptVec , TransactionOutpoint , UtxoEntry } ,
23+ tx:: { ScriptVec , SignableTransaction , Transaction , TransactionOutpoint , UtxoEntry } ,
24+ utxo:: utxo_diff:: ImmutableUtxoDiff ,
25+ Hash ,
1926} ;
2027use kaspa_core:: info;
2128use kaspad_lib:: daemon:: { get_app_dir, CONSENSUS_DB , DEFAULT_DATA_DIR , META_DB , UTXOINDEX_DB } ;
@@ -25,7 +32,7 @@ fn main() {
2532 let network = NetworkId :: new ( NetworkType :: Mainnet ) ;
2633 let app_dir = get_app_dir ( ) ;
2734 let db_dir = app_dir. join ( network. to_prefixed ( ) ) . join ( DEFAULT_DATA_DIR ) ;
28- let consensus_db_dir = db_dir. join ( CONSENSUS_DB ) . join ( "consensus-003 " ) ; // check your own index
35+ let consensus_db_dir = db_dir. join ( CONSENSUS_DB ) . join ( "consensus-002 " ) ; // check your own index
2936 // let utxoindex_db_dir = db_dir.join(UTXOINDEX_DB);
3037 // let meta_db_dir = db_dir.join(META_DB);
3138
@@ -48,19 +55,105 @@ fn main() {
4855 ( start. duration_since ( UNIX_EPOCH ) . unwrap ( ) . as_millis ( ) as u64 , end. duration_since ( UNIX_EPOCH ) . unwrap ( ) . as_millis ( ) as u64 ) ;
4956 let mut count = 0 ;
5057
58+ let mut fee = 0 ;
59+
5160 for cb in services. reachability_service . forward_chain_iterator ( pp, sink, false ) {
5261 let timestamp = storage. headers_store . get_timestamp ( cb) . unwrap ( ) ;
5362 if start <= timestamp && timestamp < end {
5463 let ad = storage. acceptance_data_store . get ( cb) . unwrap ( ) ;
55- let mergeset_accepted_txs_count = ad. iter ( ) . map ( |d| d. accepted_transactions . len ( ) ) . sum :: < usize > ( ) ;
64+ let ( cb_accepted_fees, mergeset_accepted_txs_count) = ad
65+ . iter ( )
66+ . map ( |d| {
67+ let cb_accepted_fees = calc_fees_in_cb ( cb, d, ad. clone ( ) , storage. clone ( ) ) ;
68+
69+ ( cb_accepted_fees, d. accepted_transactions . len ( ) )
70+ } )
71+ . reduce ( |( a, b) , ( c, d) | ( a + c, b + d) )
72+ . unwrap ( ) ;
73+
74+ fee += cb_accepted_fees;
5675 count += mergeset_accepted_txs_count;
5776 if ( count - mergeset_accepted_txs_count) / 10_000_000 != count / 10_000_000 {
5877 info ! ( "Accepted txs in range: {}" , count) ;
78+ info ! ( "Fees paid: {}" , fee) ;
5979 }
6080 }
6181 }
6282 info ! (
6383 "\n =======================================\n \t Accepted txs in range {} - {}: {}\n =======================================" ,
64- start_datetime. format( "%d/%m/%Y %H:%M" ) , end_datetime. format( "%d/%m/%Y %H:%M" ) , count
84+ start_datetime. format( "%d/%m/%Y %H:%M" ) ,
85+ end_datetime. format( "%d/%m/%Y %H:%M" ) ,
86+ count
6587 ) ;
88+ info ! ( "Fees paid: {}" , fee) ;
89+ }
90+
91+ fn calc_fees_in_cb (
92+ cb : Hash ,
93+ d : & MergesetBlockAcceptanceData ,
94+ ad : Arc < Vec < MergesetBlockAcceptanceData > > ,
95+ storage : Arc < ConsensusStorage > ,
96+ ) -> u64 {
97+ let block_txs = storage. block_transactions_store . get ( d. block_hash ) . unwrap ( ) ;
98+
99+ d. accepted_transactions
100+ . iter ( )
101+ . map ( |h| {
102+ let utxo_diff = storage. utxo_diffs_store . get ( cb) . unwrap ( ) ;
103+
104+ let tx = find_tx_from_block_txs_with_idx ( h. transaction_id , h. index_within_block , block_txs. clone ( ) ) ;
105+
106+ let removed_diffs = utxo_diff. removed ( ) ;
107+
108+ let in_sum = tx
109+ . inputs
110+ . iter ( )
111+ . map ( |ti| {
112+ if let Some ( utxo_entry) = removed_diffs. get ( & ti. previous_outpoint ) {
113+ utxo_entry. amount
114+ } else {
115+ // This handles this rare scenario:
116+ // - UTXO0 is spent by TX1 and creates UTXO1
117+ // - UTXO1 is spent by TX2 and creates UTXO2
118+ // - A chain block happens to accept both of these
119+ // In this case, removed_diff wouldn't contain the outpoint of the created-and-immediately-spent UTXO
120+ // so we use the transaction (which also has acceptance data in this block) and look at its outputs
121+ let other_txid = ti. previous_outpoint . transaction_id ;
122+ let other_tx = find_tx_from_acceptance ( other_txid, ad. clone ( ) , storage. clone ( ) ) ;
123+ assert_eq ! ( other_tx. id( ) , other_txid, "expected to find the correct other_txid" ) ;
124+ let output = & other_tx. outputs [ ti. previous_outpoint . index as usize ] ;
125+ output. value
126+ }
127+ } )
128+ . sum :: < u64 > ( ) ;
129+ let out_sum = tx. outputs . iter ( ) . map ( |to| to. value ) . sum :: < u64 > ( ) ;
130+
131+ // Saturating sub to cover the coinbase case and make that return 0
132+ in_sum. saturating_sub ( out_sum)
133+ } )
134+ . sum :: < u64 > ( )
135+ }
136+
137+ fn find_tx_from_acceptance (
138+ txid : Hash ,
139+ acceptance_data : Arc < Vec < MergesetBlockAcceptanceData > > ,
140+ storage : Arc < ConsensusStorage > ,
141+ ) -> Transaction {
142+ let ( block_hash, idx_in_block) = acceptance_data
143+ . iter ( )
144+ . find_map ( |d| {
145+ d. accepted_transactions . iter ( ) . find_map ( |a| ( a. transaction_id == txid) . then_some ( ( d. block_hash , a. index_within_block ) ) )
146+ } )
147+ . unwrap ( ) ;
148+
149+ let block_txs = storage. block_transactions_store . get ( block_hash) . unwrap ( ) ;
150+
151+ find_tx_from_block_txs_with_idx ( txid, idx_in_block, block_txs)
152+ }
153+
154+ fn find_tx_from_block_txs_with_idx ( txid : Hash , idx_in_block : u32 , block_txs : Arc < Vec < Transaction > > ) -> Transaction {
155+ let found_tx = block_txs. get ( idx_in_block as usize ) . unwrap ( ) ;
156+ assert_eq ! ( txid, found_tx. id( ) , "{} != {}" , txid, found_tx. id( ) ) ;
157+
158+ found_tx. to_owned ( )
66159}
0 commit comments