Skip to content

Commit 5f6a667

Browse files
committed
Calculate fees in record
1 parent e9fd437 commit 5f6a667

File tree

1 file changed

+98
-5
lines changed

1 file changed

+98
-5
lines changed

database/rocknroll/src/main.rs

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,19 @@ use std::{
1010

1111
use 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
};
1518
use 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
};
2027
use kaspa_core::info;
2128
use 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\tAccepted 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

Comments
 (0)