1#![allow(unused_imports)]
2use bitcoin_address::is_segwit_v0;
3use bitcoin_transaction_utils::is_transaction_hex_segwit;
4use bitcoind_request::command::{
5 get_best_block_hash::GetBestBlockHashCommand,
6 get_block::{
7 self, CoinbaseVin, DecodeRawTransactionResponse, GetBlockCommand, GetBlockCommandResponse,
8 GetBlockCommandTransactionResponse, GetBlockCommandVerbosity, Vout,
9 },
10 get_block_count::{self, GetBlockCountCommand},
11 get_block_hash::GetBlockHashCommand,
12 get_block_header::GetBlockHeaderCommand,
13 get_block_stats::{
14 GetBlockStatsCommand, GetBlockStatsCommandResponse,
15 GetBlockStatsCommandWithAllStatsResponse, GetBlockStatsCommandWithSelectiveStatsResponse,
16 StatsArgumentChoices, TargetBlockArgument,
17 },
18 get_blockchain_info::GetBlockchainInfoCommand,
19 get_chain_tips::GetChainTipsCommand,
20 get_chain_tx_stats::GetChainTxStatsCommand,
21 get_difficulty::GetDifficultyCommand,
22 get_mining_info::GetMiningInfoCommand,
23 get_network_hash_ps::GetNetworkHashPsCommand,
24 get_raw_transaction::{GetRawTransactionCommand, GetRawTransactionCommandResponse, Vin},
25 get_tx_out::GetTxOutCommand,
26 get_tx_out_set_info::GetTxOutSetInfoCommand,
27 CallableCommand,
28};
29
30use bitcoind_request::{Blockhash, BlockhashHexEncoded};
31mod client;
32
33use chrono::{DateTime, Duration, TimeZone, Timelike, Utc};
34pub use client::Client;
35use jsonrpc::simple_http::{self, SimpleHttpTransport};
36use std::{env, time::SystemTimeError};
37
38const BLOCKS_PER_DIFFICULTY_PERIOD: u64 = 2016;
39
40pub struct Seconds(pub i64);
41
42fn timestamp_is_from_more_than_24_hours_ago(timestamp: i64) -> bool {
43 let hour_window_to_calculate_for = 24;
44
45 let current_datetime = chrono::offset::Utc::now();
46 let window_to_cacluate_duration_in_seconds =
47 Duration::seconds(60 * 60 * hour_window_to_calculate_for);
48 let datetime_24_hours_ago = current_datetime - window_to_cacluate_duration_in_seconds;
49 let datetime_of_block = Utc.timestamp(timestamp as i64, 0);
50 datetime_of_block < datetime_24_hours_ago
51}
52
53fn timestamp_is_from_more_than_90_days_ago(timestamp: i64) -> bool {
54 let hour_window_to_calculate_for = 24 * 90;
55
56 let current_datetime = chrono::offset::Utc::now();
57 let window_to_cacluate_duration_in_seconds =
58 Duration::seconds(60 * 60 * hour_window_to_calculate_for);
59 let datetime_90_days_ago = current_datetime - window_to_cacluate_duration_in_seconds;
60 let datetime_of_block = Utc.timestamp(timestamp as i64, 0);
61 datetime_of_block < datetime_90_days_ago
62}
63
64pub fn get_block_height(client: &Client) -> u64 {
65 let client = &client.bitcoind_request_client;
66 let block_count = GetBlockCountCommand::new().call(client);
67 return block_count.unwrap().0;
68}
69
70pub fn get_time_since_last_block_in_seconds(client: &Client) -> i64 {
71 let client = &client.bitcoind_request_client;
72 let block_count = GetBlockCountCommand::new().call(client);
73 let arg = TargetBlockArgument::Height(block_count.unwrap().0);
74 let block_stats_response = GetBlockStatsCommand::new(arg).call(client);
75 let time_of_last_block = match block_stats_response.unwrap() {
76 GetBlockStatsCommandResponse::AllStats(response) => response.time,
77 GetBlockStatsCommandResponse::SelectiveStats(response) => response.time.unwrap(),
78 };
79 let current_datetime = chrono::offset::Utc::now();
80 let datetime_of_last_block = Utc.timestamp(time_of_last_block as i64, 0);
81 let difference = current_datetime.signed_duration_since(datetime_of_last_block);
82 difference.num_seconds()
83}
84
85pub fn get_average_block_time_for_last_2016_blocks(client: &Client) -> u64 {
86 let client = &client.bitcoind_request_client;
87 let block_height = GetBlockCountCommand::new().call(client).unwrap();
88 let block_stats_response =
89 GetBlockStatsCommand::new(TargetBlockArgument::Height(block_height.0)).call(client);
90 let time_of_most_recent_block = match block_stats_response.unwrap() {
91 GetBlockStatsCommandResponse::AllStats(response) => response.time,
92 GetBlockStatsCommandResponse::SelectiveStats(response) => response.time.unwrap(),
93 };
94
95 let block_stats_response_for_block_2016_old =
96 GetBlockStatsCommand::new(TargetBlockArgument::Height(block_height.0 - 2016)).call(client);
97 let time_of_block_2016_old = match block_stats_response_for_block_2016_old.unwrap() {
98 GetBlockStatsCommandResponse::AllStats(response) => response.time,
99 GetBlockStatsCommandResponse::SelectiveStats(response) => response.time.unwrap(),
100 };
101
102 let duration = time_of_most_recent_block - time_of_block_2016_old;
103 let average_seconds_per_block = duration / 2016 as u64;
104 average_seconds_per_block
105}
106
107pub fn get_average_block_time_for_since_last_difficulty_adjustement(client: &Client) -> u64 {
108 let bitcoind_request_client = &client.bitcoind_request_client;
109 let block_height = GetBlockCountCommand::new().call(bitcoind_request_client);
110 let block_stats_response =
111 GetBlockStatsCommand::new(TargetBlockArgument::Height(block_height.unwrap().0))
112 .call(bitcoind_request_client);
113 let time_of_most_recent_block = match block_stats_response.unwrap() {
114 GetBlockStatsCommandResponse::AllStats(response) => response.time,
115 GetBlockStatsCommandResponse::SelectiveStats(response) => response.time.unwrap(),
116 };
117
118 let block_height_of_last_difficulty_adjustment =
119 get_block_height_of_last_difficulty_adjustment(client);
120 let block_stats_response_for_last_difficulty_ajustment_block = GetBlockStatsCommand::new(
121 TargetBlockArgument::Height(block_height_of_last_difficulty_adjustment),
122 )
123 .call(bitcoind_request_client);
124 let time_of_last_difficulty_adjustment_block =
125 match block_stats_response_for_last_difficulty_ajustment_block.unwrap() {
126 GetBlockStatsCommandResponse::AllStats(response) => response.time,
127 GetBlockStatsCommandResponse::SelectiveStats(response) => response.time.unwrap(),
128 };
129
130 let blocks_since_last_retarget =
131 BLOCKS_PER_DIFFICULTY_PERIOD as f64 - get_blocks_count_until_retarget(client);
132
133 let duration = time_of_most_recent_block - time_of_last_difficulty_adjustment_block;
134 let average_seconds_per_block = duration / blocks_since_last_retarget as u64;
135 average_seconds_per_block
136}
137
138pub fn get_total_money_supply(client: &Client) -> f64 {
139 let client = &client.bitcoind_request_client;
141 let tx_out_set_info = GetTxOutSetInfoCommand::new().call(client);
142 tx_out_set_info.unwrap().total_amount
143}
144
145pub fn get_chain_size(client: &Client) -> u64 {
147 let client = &client.bitcoind_request_client;
148 let blockchain_info = GetBlockchainInfoCommand::new().call(client);
149 blockchain_info.unwrap().size_on_disk
150}
151
152pub fn get_utxo_set_size(client: &Client) -> u64 {
153 let client = &client.bitcoind_request_client;
154 let tx_out_set_info = GetTxOutSetInfoCommand::new().call(client);
155 tx_out_set_info.unwrap().txouts
156}
157
158pub fn get_total_transactions_count(client: &Client) -> u64 {
159 let client = &client.bitcoind_request_client;
160 let chain_tx_stats = GetChainTxStatsCommand::new().call(client);
161 chain_tx_stats.unwrap().txcount
162}
163
164pub fn get_tps_for_last_30_days(client: &Client) -> f64 {
165 let client = &client.bitcoind_request_client;
167 let chain_tx_stats = GetChainTxStatsCommand::new().call(client).unwrap();
168 let seconds_in_interval = chain_tx_stats.window_interval;
169 let transactions_count_in_window = chain_tx_stats.window_tx_count as f64;
170 let elapsed_seconds_in_window = seconds_in_interval as f64;
171 let tps = transactions_count_in_window / elapsed_seconds_in_window;
172 tps
173}
174
175pub fn get_transactions_count_over_last_30_days(client: &Client) -> u64 {
177 let client = &client.bitcoind_request_client;
178 let chain_tx_stats = GetChainTxStatsCommand::new().call(client);
179 chain_tx_stats.unwrap().window_tx_count
180}
181
182pub fn get_total_fee_for_block_at_height(client: &Client, height: u64) -> u64 {
183 let client = &client.bitcoind_request_client;
184 let block_stats = GetBlockStatsCommand::new(TargetBlockArgument::Height(height))
185 .add_selective_stats(vec![StatsArgumentChoices::TotalFee])
186 .call(client);
187 let total_fee = match block_stats.unwrap() {
188 GetBlockStatsCommandResponse::AllStats(response) => response.totalfee,
189 GetBlockStatsCommandResponse::SelectiveStats(response) => response.totalfee.unwrap(),
190 };
191 total_fee
192}
193
194fn get_subsidy_for_block_at_height(client: &Client, height: u64) -> u64 {
195 let client = &client.bitcoind_request_client;
196 let block_stats = GetBlockStatsCommand::new(TargetBlockArgument::Height(height))
197 .add_selective_stats(vec![StatsArgumentChoices::Subsidy])
198 .call(client);
199 let subsidy = match block_stats.unwrap() {
200 GetBlockStatsCommandResponse::AllStats(response) => response.subsidy,
201 GetBlockStatsCommandResponse::SelectiveStats(response) => response.subsidy.unwrap(),
202 };
203 subsidy
204}
205
206fn get_timestamp_of_block_at_height(client: &Client, height: u64) -> u64 {
207 let client = &client.bitcoind_request_client;
208 let block_stats = GetBlockStatsCommand::new(TargetBlockArgument::Height(height))
209 .add_selective_stats(vec![StatsArgumentChoices::Time])
210 .call(client);
211 let time = match block_stats.unwrap() {
212 GetBlockStatsCommandResponse::AllStats(response) => response.time,
213 GetBlockStatsCommandResponse::SelectiveStats(response) => response.time.unwrap(),
214 };
215 time
216}
217
218pub fn get_total_fee_for_24_hours(client: &Client) -> u64 {
220 let last_block_height = get_block_height(&client);
221
222 let mut total_fee = 0;
223 let mut current_block_height = last_block_height;
224 let mut next_block_timestamp = chrono::offset::Utc::now().timestamp();
225 while !timestamp_is_from_more_than_24_hours_ago(next_block_timestamp) {
227 let fee = get_total_fee_for_block_at_height(client, current_block_height);
230 let time = get_timestamp_of_block_at_height(client, current_block_height);
231
232 total_fee = total_fee + fee;
233
234 current_block_height = current_block_height - 1;
235 next_block_timestamp = time as i64;
236 }
237 total_fee
238}
239
240pub fn get_difficulty(client: &Client) -> f64 {
241 let client = &client.bitcoind_request_client;
242 let difficulty = GetDifficultyCommand::new().call(client);
243 difficulty.unwrap().0
244}
245
246pub fn get_current_difficulty_epoch(client: &Client) -> u64 {
247 let block_count = get_block_height(client);
248 let epoch = (block_count / BLOCKS_PER_DIFFICULTY_PERIOD) + 1;
249 epoch
250}
251pub fn get_block_height_of_last_difficulty_adjustment(client: &Client) -> u64 {
252 let last_epoch = get_current_difficulty_epoch(client) - 1;
253 let block_height_of_last_difficulty_adjustment = last_epoch * 2016;
254 block_height_of_last_difficulty_adjustment
255}
256
257pub fn get_mempool_transactions_count(client: &Client) -> u64 {
258 let client = &client.bitcoind_request_client;
259 let mining_info = GetMiningInfoCommand::new().call(client);
260 let mempool_transaction_count = mining_info.unwrap().pooledtx;
261 mempool_transaction_count
262}
263
264pub fn get_estimated_hash_rate_per_second_for_block_since_last_difficulty_change(
265 client: &Client,
266) -> f64 {
267 let client = &client.bitcoind_request_client;
268 let hash_rate = GetNetworkHashPsCommand::new()
269 .set_n_blocks(bitcoind_request::command::get_network_hash_ps::BlocksToIncludeArg::BlocksSinceLastDifficultyChange)
270 .call(client);
271 hash_rate.unwrap().0
272}
273
274pub fn get_estimated_hash_rate_per_second_for_last_2016_blocks(client: &Client) -> f64 {
275 let client = &client.bitcoind_request_client;
276 let blocks_to_calculate = 2016;
277 let hash_rate = GetNetworkHashPsCommand::new()
278 .set_n_blocks(
279 bitcoind_request::command::get_network_hash_ps::BlocksToIncludeArg::NBlocks(
280 blocks_to_calculate,
281 ),
282 )
283 .call(client);
284 hash_rate.unwrap().0
285}
286pub fn get_estimated_hash_rate_per_second_for_last_epoch(client: &Client) -> f64 {
287 let bitcoind_request_client = &client.bitcoind_request_client;
288 let block_height_of_last_difficulty_adjustment =
289 get_block_height_of_last_difficulty_adjustment(client);
290 let hash_rate = GetNetworkHashPsCommand::new()
291 .set_n_blocks(
292 bitcoind_request::command::get_network_hash_ps::BlocksToIncludeArg::NBlocks(
293 BLOCKS_PER_DIFFICULTY_PERIOD,
294 ),
295 )
296 .set_height(
297 bitcoind_request::command::get_network_hash_ps::HeightArg::Height(
298 block_height_of_last_difficulty_adjustment,
299 ),
300 )
301 .call(bitcoind_request_client);
302 hash_rate.unwrap().0
303}
304
305pub fn get_blocks_count_until_retarget(client: &Client) -> f64 {
306 let block_count = get_block_height(client);
307 let percent_of_epoch_complete: f64 =
308 (block_count as f64 / BLOCKS_PER_DIFFICULTY_PERIOD as f64) % 1.0;
309 let percent_of_epoch_to_go: f64 = 1.0 - percent_of_epoch_complete;
310 let blocks_until_retarget = percent_of_epoch_to_go * (BLOCKS_PER_DIFFICULTY_PERIOD as f64);
311 blocks_until_retarget
312}
313
314pub fn get_estimated_seconds_until_retarget(client: &Client) -> f64 {
315 get_average_block_time_for_since_last_difficulty_adjustement(client);
319 let blocks_count_until_retarget = get_blocks_count_until_retarget(client);
320 10.0 * 60.0 * blocks_count_until_retarget
321}
322
323pub fn get_blocks_mined_over_last_24_hours_count(client: &Client) -> u64 {
325 let block_count = get_block_height(client);
326
327 let mut next_block_timestamp: u64 = get_timestamp_of_block_at_height(client, block_count);
329 let mut traversed_blocks_count = 0;
330 while !timestamp_is_from_more_than_24_hours_ago(next_block_timestamp as i64) {
332 traversed_blocks_count = traversed_blocks_count + 1;
333
334 let block_height_to_calculate = block_count - traversed_blocks_count;
335 let time = get_timestamp_of_block_at_height(client, block_height_to_calculate);
336
337 next_block_timestamp = time as u64;
338 }
339
340 traversed_blocks_count
341}
342
343pub fn get_average_fees_per_block_over_last_24_hours(client: &Client) -> u64 {
345 let block_count = get_block_height(client);
346
347 let mut next_block_timestamp: u64 = get_timestamp_of_block_at_height(client, block_count);
349 let mut traversed_blocks_count = 0;
350 let mut total_fee = 0;
351 while !timestamp_is_from_more_than_24_hours_ago(next_block_timestamp as i64) {
353 let block_fee =
354 get_total_fee_for_block_at_height(client, block_count - traversed_blocks_count);
355 traversed_blocks_count = traversed_blocks_count + 1;
356 total_fee = total_fee + block_fee;
357
358 let next_block_height_to_calculate = block_count - traversed_blocks_count;
359 let time = get_timestamp_of_block_at_height(client, next_block_height_to_calculate);
360
361 next_block_timestamp = time as u64;
362 }
363
364 total_fee / traversed_blocks_count
365}
366
367pub fn get_average_fees_per_block_over_last_2016_blocks(client: &Client) -> u64 {
369 let block_count = get_block_height(client);
370 let mut total_fee = 0;
372
373 for i in 0..=2016 {
374 let block_fee = get_total_fee_for_block_at_height(client, block_count - i);
376 total_fee = total_fee + block_fee;
377 }
378
379 total_fee / 2016
380}
381
382pub fn get_fees_as_a_percent_of_reward_for_last_24_hours(client: &Client) -> f64 {
383 let block_count = get_block_height(client);
384
385 let mut next_block_timestamp: u64 = get_timestamp_of_block_at_height(client, block_count);
387 let mut traversed_blocks_count = 0;
388 let mut total_fee = 0.0;
389 let mut total_subsidy = 0.0;
390 while !timestamp_is_from_more_than_24_hours_ago(next_block_timestamp as i64) {
392 let block_fee =
393 get_total_fee_for_block_at_height(client, block_count - traversed_blocks_count);
394 let block_subsidy =
395 get_subsidy_for_block_at_height(client, block_count - traversed_blocks_count);
396 traversed_blocks_count = traversed_blocks_count + 1;
397 total_fee = total_fee as f64 + block_fee as f64;
398 total_subsidy = total_subsidy as f64 + block_subsidy as f64;
399
400 let next_block_height_to_calculate = block_count - traversed_blocks_count;
401 let time = get_timestamp_of_block_at_height(client, next_block_height_to_calculate);
402
403 next_block_timestamp = time as u64;
404 }
405
406 total_fee / (total_subsidy + total_fee)
407}
408
409pub fn get_fees_as_a_percent_of_reward_for_last_2016_blocks(client: &Client) -> f64 {
410 let block_count = get_block_height(client);
411 let mut total_fee = 0.0;
413 let mut total_subsidy = 0.0;
414
415 for i in 0..=2016 {
416 let block_fee = get_total_fee_for_block_at_height(client, block_count - i);
418 let block_subsidy = get_subsidy_for_block_at_height(client, block_count);
419 total_fee = total_fee as f64 + block_fee as f64;
420 total_subsidy = total_subsidy as f64 + block_subsidy as f64;
421 }
422
423 total_fee / (total_subsidy + total_fee)
424}
425
426pub fn get_block_subsidy_of_most_recent_block(client: &Client) -> u64 {
427 let block_count = get_block_height(client);
428 let block_subsidy = get_subsidy_for_block_at_height(client, block_count);
429 block_subsidy
430}
431
432struct Conf {
434 based_on_transaction_hex: bool,
435 based_on_vouts_and_vins: bool,
436 based_on_vouts: bool,
437 factor_in_change_address: bool,
438 include_coinbase_transaction: bool,
439}
440
441pub fn get_percent_of_vouts_used_segwit_over_last_24_hours(
448 client: &Client,
449) -> (f64, f64, f64, f64, f64) {
450 let is_segwit = is_segwit_v0;
451 let block_count = get_block_height(client);
452
453 let mut next_block_timestamp: u64 = get_timestamp_of_block_at_height(client, block_count);
455 let mut traversed_blocks_count = 0;
456 let mut vouts_count_minus_change_vout: u64 = 0;
457 let mut segwit_vouts_count: u64 = 0;
458 let mut transactions_count_not_including_coinbase: u64 = 0;
459 let mut segwit_spending_transactions_count_not_including_coinbase: u64 = 0;
460 let mut payments_from_segwit_spending_transactions_count_not_including_coinbase: u64 = 0;
461 let mut transactions_count_including_coinbase: u64 = 0;
462 let mut transactions_segwit_count_based_on_vouts_not_including_coinbase: u64 = 0;
463 let mut transactions_segwit_count_based_on_transaction_hex_not_including_coinbase: u64 = 0;
464 let mut transactions_segwit_count_based_on_vins_or_vouts_not_including_coinbase: u64 = 0;
465 while !timestamp_is_from_more_than_24_hours_ago(next_block_timestamp as i64) {
467 let height = block_count - traversed_blocks_count;
468 let bitcoind_request_client = &client.bitcoind_request_client;
470 let block_stats = GetBlockStatsCommand::new(TargetBlockArgument::Height(height))
472 .add_selective_stats(vec![StatsArgumentChoices::Blockhash])
473 .call(bitcoind_request_client);
474 let blockhash = match block_stats.unwrap() {
475 GetBlockStatsCommandResponse::AllStats(response) => response.blockhash,
476 GetBlockStatsCommandResponse::SelectiveStats(response) => response.blockhash.unwrap(),
477 };
478 let get_block_response = GetBlockCommand::new(Blockhash(blockhash))
479 .verbosity(GetBlockCommandVerbosity::BlockObjectWithTransactionInformation)
480 .call(&bitcoind_request_client);
481 let block_transactions_responses: Vec<GetBlockCommandTransactionResponse> =
482 match get_block_response.unwrap() {
483 GetBlockCommandResponse::Block(block) => block.tx,
484 _ => todo!(),
485 };
486 let transactions: Vec<DecodeRawTransactionResponse> = block_transactions_responses
487 .into_iter()
488 .map(
489 |block_transaction_response| match block_transaction_response {
490 GetBlockCommandTransactionResponse::Raw(transaction) => transaction,
491 GetBlockCommandTransactionResponse::Id(transaction_id) => todo!(),
492 },
493 )
494 .collect();
495 for transaction in transactions.into_iter() {
497 transactions_count_including_coinbase = transactions_count_including_coinbase + 1;
498 if !transaction.is_coinbase_transaction() {
499 transactions_count_not_including_coinbase =
500 transactions_count_not_including_coinbase + 1;
501 let transaction_hex = transaction.hex;
502 if is_transaction_hex_segwit(&transaction_hex) {
503 transactions_segwit_count_based_on_transaction_hex_not_including_coinbase =
504 transactions_segwit_count_based_on_transaction_hex_not_including_coinbase
505 + 1;
506 }
510 let vouts = transaction.vout;
511 let vins = transaction.vin;
512 let vouts_count: u64 = vouts.len() as u64;
513 let vouts_count_minus_change_vout_for_transaction = if vouts_count == 1 {
514 vouts_count
515 } else {
516 vouts_count - 1
517 };
518 if vouts_count == 1 {
520 vouts_count_minus_change_vout = vouts_count_minus_change_vout + vouts_count;
521 } else {
522 vouts_count_minus_change_vout = vouts_count_minus_change_vout + vouts_count - 1;
523 }
524 let mut is_segwit_transaction_based_on_vouts = false;
525 let mut is_segwit_transaction_based_on_vins = false;
526 for vout in vouts.iter() {
527 let is_segwit = match &vout.script_pub_key.address {
528 Some(address) => is_segwit(&address),
529 None => false,
530 };
531 if is_segwit {
532 segwit_vouts_count = segwit_vouts_count + 1;
533 is_segwit_transaction_based_on_vouts = true;
534 } else {
539 }
544 }
545 let mut vins_count = 0;
548
549 for vin in vins.iter() {
550 match &vin {
551 get_block::Vin::Coinbase(_) => {}
552 get_block::Vin::NonCoinbase(v) => {
553 vins_count = vins_count + 1;
554 let txid = &v.txid;
555 let vout_index = v.vout;
556 let transaction = GetRawTransactionCommand::new(txid.clone())
557 .verbose(true)
558 .call(bitcoind_request_client);
559
560 let vout_address = match transaction.unwrap() {
561 GetRawTransactionCommandResponse::SerializedHexEncodedData(_s) => {
562 todo!()
563 }
564 GetRawTransactionCommandResponse::Transaction(transaction) => {
565 let address = &transaction.vout[vout_index as usize]
566 .script_pub_key
567 .address;
568 let a = address.clone();
569 a
570 }
571 };
572
573 let is_segwit = match &vout_address {
574 Some(address) => is_segwit(address),
575 None => false,
576 };
577 if is_segwit {
578 is_segwit_transaction_based_on_vins = true;
579 } else {
581 }
583 }
584 }
585 }
586
587 if is_segwit_transaction_based_on_vouts {
590 transactions_segwit_count_based_on_vouts_not_including_coinbase =
591 transactions_segwit_count_based_on_vouts_not_including_coinbase + 1;
592 } else {
593 }
595
596 if is_segwit_transaction_based_on_vins {
598 segwit_spending_transactions_count_not_including_coinbase =
599 segwit_spending_transactions_count_not_including_coinbase + 1;
600
601 payments_from_segwit_spending_transactions_count_not_including_coinbase =
602 payments_from_segwit_spending_transactions_count_not_including_coinbase
603 + vouts_count_minus_change_vout_for_transaction;
604 }
605
606 if is_segwit_transaction_based_on_vouts || is_segwit_transaction_based_on_vins {
607 transactions_segwit_count_based_on_vins_or_vouts_not_including_coinbase =
608 transactions_segwit_count_based_on_vins_or_vouts_not_including_coinbase + 1;
609 } else {
610 }
612 }
613 }
614
615 traversed_blocks_count = traversed_blocks_count + 1;
616
617 let next_block_height_to_calculate = block_count - traversed_blocks_count;
618 let time = get_timestamp_of_block_at_height(client, next_block_height_to_calculate);
619
620 next_block_timestamp = time as u64;
621 }
622
623 let percent_of_transactions_with_a_segwit_vout =
628 transactions_segwit_count_based_on_vouts_not_including_coinbase as f64
629 / transactions_count_not_including_coinbase as f64;
630 let percent_of_transactions_with_a_segwit_vin_or_vout =
631 transactions_segwit_count_based_on_vins_or_vouts_not_including_coinbase as f64
632 / transactions_count_not_including_coinbase as f64;
633 let percent_based_on_transaction_hexes =
634 transactions_segwit_count_based_on_transaction_hex_not_including_coinbase as f64
635 / transactions_count_not_including_coinbase as f64;
636 let percent_of_payments_spending_segwit_per_day =
638 payments_from_segwit_spending_transactions_count_not_including_coinbase as f64
639 / vouts_count_minus_change_vout as f64;
640 let percent_of_segwit_spending_transactions_per_day =
641 segwit_spending_transactions_count_not_including_coinbase as f64
642 / transactions_count_not_including_coinbase as f64;
643
644 (
645 percent_of_transactions_with_a_segwit_vout,
646 percent_of_transactions_with_a_segwit_vin_or_vout,
647 percent_based_on_transaction_hexes,
648 percent_of_payments_spending_segwit_per_day,
649 percent_of_segwit_spending_transactions_per_day,
650 )
651}