From 1f8298bf47e44c96f495d1f03263f1c11de83505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dillan=20Choini=C3=A8re?= Date: Thu, 21 Nov 2024 13:05:01 -0500 Subject: [PATCH] Add Block --- blocks/bitcoin/Makefile | 2 +- blocks/bitcoin/src/blocks.rs | 55 ++++++++++++++++++++++++++++++ blocks/bitcoin/src/events.rs | 16 +++++++-- blocks/bitcoin/src/inputs.rs | 0 blocks/bitcoin/src/lib.rs | 4 +++ blocks/bitcoin/src/outputs.rs | 0 blocks/bitcoin/src/pb/bitcoin.rs | 24 ++++++------- blocks/bitcoin/src/transactions.rs | 0 proto/bitcoin.proto | 12 +++---- 9 files changed, 91 insertions(+), 22 deletions(-) create mode 100644 blocks/bitcoin/src/blocks.rs create mode 100644 blocks/bitcoin/src/inputs.rs create mode 100644 blocks/bitcoin/src/outputs.rs create mode 100644 blocks/bitcoin/src/transactions.rs diff --git a/blocks/bitcoin/Makefile b/blocks/bitcoin/Makefile index f02f51a..1de21c6 100644 --- a/blocks/bitcoin/Makefile +++ b/blocks/bitcoin/Makefile @@ -27,4 +27,4 @@ protogen: .PHONY: parquet parquet: - substreams-sink-files run bitcoin.substreams.pinax.network:443 substreams.yaml map_events './out' 800000:800500 --encoder parquet --file-block-count 100 --development-mode + substreams-sink-files run bitcoin.substreams.pinax.network:443 substreams.yaml map_events './out' 800000:800100 --encoder parquet --file-block-count 100 --development-mode diff --git a/blocks/bitcoin/src/blocks.rs b/blocks/bitcoin/src/blocks.rs new file mode 100644 index 0000000..fc6652d --- /dev/null +++ b/blocks/bitcoin/src/blocks.rs @@ -0,0 +1,55 @@ +use common::structs::BlockTimestamp; +use substreams_bitcoin::pb::btc::v1::Block; + +use crate::pb::bitcoin::Block as OutputBlock; + +pub fn collect_block(block: &Block, timestamp: &BlockTimestamp) -> OutputBlock { + OutputBlock { + time: Some(timestamp.time), + height: block.height, + date: timestamp.date.clone(), + hash: block.hash.clone(), + bits: block.bits.clone(), + chainwork: block.chainwork.clone(), + difficulty: block.difficulty, + total_fees: calculate_total_fees(block), + total_reward: calculate_total_reward(block), + mint_reward: calculate_mint_reward(block.height), + merkle_root: block.merkle_root.clone(), + transaction_count: block.tx.len() as u64, + nonce: block.nonce as u32, + // Get the coinbase from the first transaction + coinbase: block.tx.first().unwrap().vin.first().unwrap().coinbase.clone(), + previous_block_hash: block.previous_hash.clone(), + size: block.size, + stripped_size: block.stripped_size, + version: block.version, + weight: block.weight, + } +} + +fn calculate_total_fees(block: &Block) -> f64 { + let total_reward = calculate_total_reward(block); + let mint_reward = calculate_mint_reward(block.height); + + total_reward - mint_reward +} + +fn calculate_total_reward(block: &Block) -> f64 { + // Assume the first transaction is the coinbase transaction + if let Some(coinbase_tx) = block.tx.first() { + coinbase_tx.vout.iter().map(|vout| vout.value).sum() + } else { + 0.0 // No transactions in the block (shouldn't happen in practice) + } +} + +fn calculate_mint_reward(height: i64) -> f64 { + // Bitcoin's block reward halving schedule + let halvings = height / 210_000; + if halvings >= 64 { + return 0.0; // All bitcoins mined + } + + 50.0 / 2_f64.powi(halvings as i32) +} diff --git a/blocks/bitcoin/src/events.rs b/blocks/bitcoin/src/events.rs index f3360cb..04f21e5 100644 --- a/blocks/bitcoin/src/events.rs +++ b/blocks/bitcoin/src/events.rs @@ -1,9 +1,19 @@ +use common::utils::build_timestamp; use substreams::{errors::Error, pb::substreams::Clock}; use substreams_bitcoin::pb::btc::v1::Block; -use crate::pb::bitcoin::Events; +use crate::{blocks::collect_block, pb::bitcoin::Events}; #[substreams::handlers::map] -pub fn map_events(_block: Block, _clock: Clock) -> Result { - Ok(Events::default()) +pub fn map_events(clock: Clock, block: Block) -> Result { + let timestamp = build_timestamp(&clock); + + let events = Events { + blocks: vec![collect_block(&block, ×tamp)], + transactions: Vec::new(), + inputs: Vec::new(), + outputs: Vec::new(), + }; + + Ok(events) } diff --git a/blocks/bitcoin/src/inputs.rs b/blocks/bitcoin/src/inputs.rs new file mode 100644 index 0000000..e69de29 diff --git a/blocks/bitcoin/src/lib.rs b/blocks/bitcoin/src/lib.rs index 30f5231..5fc9389 100644 --- a/blocks/bitcoin/src/lib.rs +++ b/blocks/bitcoin/src/lib.rs @@ -1,2 +1,6 @@ +mod blocks; mod events; +mod inputs; +mod outputs; mod pb; +mod transactions; diff --git a/blocks/bitcoin/src/outputs.rs b/blocks/bitcoin/src/outputs.rs new file mode 100644 index 0000000..e69de29 diff --git a/blocks/bitcoin/src/pb/bitcoin.rs b/blocks/bitcoin/src/pb/bitcoin.rs index 0477fb6..2b5467a 100644 --- a/blocks/bitcoin/src/pb/bitcoin.rs +++ b/blocks/bitcoin/src/pb/bitcoin.rs @@ -37,22 +37,22 @@ pub struct Block { pub mint_reward: f64, #[prost(string, tag="11")] pub merkle_root: ::prost::alloc::string::String, - #[prost(int64, tag="12")] - pub transaction_count: i64, - #[prost(int64, tag="13")] - pub nonce: i64, + #[prost(uint64, tag="12")] + pub transaction_count: u64, + #[prost(uint32, tag="13")] + pub nonce: u32, #[prost(string, tag="14")] pub coinbase: ::prost::alloc::string::String, #[prost(string, tag="15")] pub previous_block_hash: ::prost::alloc::string::String, - #[prost(int64, tag="16")] - pub size: i64, - #[prost(int64, tag="17")] - pub stripped_size: i64, - #[prost(int64, tag="18")] - pub version: i64, - #[prost(int64, tag="19")] - pub weight: i64, + #[prost(int32, tag="16")] + pub size: i32, + #[prost(int32, tag="17")] + pub stripped_size: i32, + #[prost(int32, tag="18")] + pub version: i32, + #[prost(int32, tag="19")] + pub weight: i32, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/blocks/bitcoin/src/transactions.rs b/blocks/bitcoin/src/transactions.rs new file mode 100644 index 0000000..e69de29 diff --git a/proto/bitcoin.proto b/proto/bitcoin.proto index 7a68325..44023d3 100644 --- a/proto/bitcoin.proto +++ b/proto/bitcoin.proto @@ -23,14 +23,14 @@ message Block { double total_reward = 9; double mint_reward = 10; string merkle_root = 11; - int64 transaction_count = 12; - int64 nonce = 13; + uint64 transaction_count = 12; + uint32 nonce = 13; string coinbase = 14; string previous_block_hash = 15; - int64 size = 16; - int64 stripped_size = 17; - int64 version = 18; - int64 weight = 19; + int32 size = 16; + int32 stripped_size = 17; + int32 version = 18; + int32 weight = 19; } message Transaction {