From 0970f2a9ab15bb07eea6966cc3dd75fbc997a165 Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Wed, 28 Aug 2024 11:24:00 +0000 Subject: [PATCH 1/5] . --- rust/basic_bitcoin/README.md | 22 ++++++++++++++- .../src/basic_bitcoin/basic_bitcoin.did | 10 +++++++ .../src/basic_bitcoin/src/bitcoin_api.rs | 28 +++++++++++++++++++ .../src/basic_bitcoin/src/lib.rs | 26 +++++++++++++++++ 4 files changed, 85 insertions(+), 1 deletion(-) diff --git a/rust/basic_bitcoin/README.md b/rust/basic_bitcoin/README.md index b296d51a3..d0d6839aa 100644 --- a/rust/basic_bitcoin/README.md +++ b/rust/basic_bitcoin/README.md @@ -42,7 +42,7 @@ To clone and build the smart contract in **Rust**: ```bash git clone https://github.com/dfinity/examples cd examples/rust/basic_bitcoin -cargo build --release --target wasm32-unknown unknown +cargo build --release --target wasm32-unknown-unknown ``` ### Acquire cycles to deploy @@ -214,6 +214,26 @@ it sent to the network. You can track the status of this transaction using a transaction has at least one confirmation, you should be able to see it reflected in your current balance. +## Step 6: Retrieving block headers + +You can also get range of Bitcoin block headers by using the `get_block_headers` +endpoint on your canister. + +In the Candid UI, write the desired start height and optionally end height, and click on "Call": + +Alternatively, make the call using the command line. Be sure to replace `10` with your +desired start height: + +```bash +dfx canister --network=ic call basic_bitcoin get_block_headers "(10: nat32)" +``` +or replace `0` and `11` with your desired start and end height respectively: +```bash +dfx canister --network=ic call basic_bitcoin get_block_headers "(0: nat32, 11: nat32)" +``` + +Checking the balance of a Bitcoin address relies on the [bitcoin_get_block_headers](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-bitcoin_block_headers) API. + ## Conclusion In this tutorial, you were able to: diff --git a/rust/basic_bitcoin/src/basic_bitcoin/basic_bitcoin.did b/rust/basic_bitcoin/src/basic_bitcoin/basic_bitcoin.did index 097a28e64..3a2871f4a 100644 --- a/rust/basic_bitcoin/src/basic_bitcoin/basic_bitcoin.did +++ b/rust/basic_bitcoin/src/basic_bitcoin/basic_bitcoin.did @@ -32,6 +32,14 @@ type get_utxos_response = record { next_page : opt blob; }; +type block_header = blob; +type block_height = nat32; + +type get_block_headers_response = record { + tip_height : block_height; + block_headers : vec block_header; +}; + service : (network) -> { "get_p2pkh_address" : () -> (bitcoin_address); @@ -43,6 +51,8 @@ service : (network) -> { "get_utxos" : (bitcoin_address) -> (get_utxos_response); + "get_block_headers" : (start_height : block_height, end_height : opt block_height) -> (get_block_headers_response); + "get_current_fee_percentiles" : () -> (vec millisatoshi_per_vbyte); "send_from_p2pkh" : ( diff --git a/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_api.rs b/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_api.rs index c69c66d20..18ca66ba8 100644 --- a/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_api.rs +++ b/rust/basic_bitcoin/src/basic_bitcoin/src/bitcoin_api.rs @@ -1,8 +1,10 @@ +use candid::Principal; use ic_cdk::api::management_canister::bitcoin::{ bitcoin_get_balance, bitcoin_get_current_fee_percentiles, bitcoin_get_utxos, bitcoin_send_transaction, BitcoinNetwork, GetBalanceRequest, GetCurrentFeePercentilesRequest, GetUtxosRequest, GetUtxosResponse, MillisatoshiPerByte, SendTransactionRequest, }; +use crate::{GetBlockHeadersRequest, GetBlockHeadersResponse}; /// Returns the balance of the given bitcoin address. /// @@ -36,6 +38,31 @@ pub async fn get_utxos(network: BitcoinNetwork, address: String) -> GetUtxosResp utxos_res.unwrap().0 } +/// Returns the block headers in the given height range. +pub(crate) async fn get_block_headers(network: BitcoinNetwork, start_height: u32, end_height: Option) -> GetBlockHeadersResponse{ + let cycles = match network { + BitcoinNetwork::Mainnet => 10_000_000_000, + BitcoinNetwork::Testnet => 10_000_000_000, + BitcoinNetwork::Regtest => 0, + }; + + let request = GetBlockHeadersRequest{ + start_height, + end_height, + network + }; + + let res = ic_cdk::api::call::call_with_payment128::<(GetBlockHeadersRequest,), (GetBlockHeadersResponse,)>( + Principal::management_canister(), + "bitcoin_get_block_headers", + (request,), + cycles, + ) + .await; + + res.unwrap().0 +} + /// Returns the 100 fee percentiles measured in millisatoshi/byte. /// Percentiles are computed from the last 10,000 transactions (if available). /// @@ -61,3 +88,4 @@ pub async fn send_transaction(network: BitcoinNetwork, transaction: Vec) { res.unwrap(); } + diff --git a/rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs b/rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs index ec417f99e..5c930ffe3 100644 --- a/rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs +++ b/rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs @@ -3,6 +3,7 @@ mod bitcoin_wallet; mod ecdsa_api; mod schnorr_api; +use candid::{CandidType, Deserialize}; use ic_cdk::api::management_canister::bitcoin::{ BitcoinNetwork, GetUtxosResponse, MillisatoshiPerByte, }; @@ -52,6 +53,31 @@ pub async fn get_utxos(address: String) -> GetUtxosResponse { bitcoin_api::get_utxos(network, address).await } +pub type Height = u32; +pub type BlockHeader = Vec; + +/// A request for getting the block headers from a given height. +#[derive(CandidType, Debug, Deserialize, PartialEq, Eq)] +pub struct GetBlockHeadersRequest { + pub start_height: Height, + pub end_height: Option, + pub network: BitcoinNetwork, +} + +/// The response returned for a request for getting the block headers from a given height. +#[derive(CandidType, Debug, Deserialize, PartialEq, Eq, Clone)] +pub struct GetBlockHeadersResponse { + pub tip_height: Height, + pub block_headers: Vec, +} + +/// Returns the block headers in the given height range. +#[update] +pub async fn get_block_headers(start_height: u32, end_height: Option) -> GetBlockHeadersResponse{ + let network = NETWORK.with(|n| n.get()); + bitcoin_api::get_block_headers(network, start_height, end_height).await +} + /// Returns the 100 fee percentiles measured in millisatoshi/byte. /// Percentiles are computed from the last 10,000 transactions (if available). #[update] From b7c78886737bdcbc8fec08959bb9b5e1dbe1499c Mon Sep 17 00:00:00 2001 From: Dragoljub Djuric Date: Wed, 28 Aug 2024 13:34:56 +0200 Subject: [PATCH 2/5] Update rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs Co-authored-by: Dimitris Sarlis --- rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs b/rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs index 5c930ffe3..004f060b5 100644 --- a/rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs +++ b/rust/basic_bitcoin/src/basic_bitcoin/src/lib.rs @@ -56,7 +56,7 @@ pub async fn get_utxos(address: String) -> GetUtxosResponse { pub type Height = u32; pub type BlockHeader = Vec; -/// A request for getting the block headers from a given height. +/// A request for getting the block headers for a given height range. #[derive(CandidType, Debug, Deserialize, PartialEq, Eq)] pub struct GetBlockHeadersRequest { pub start_height: Height, From 39efd630eed10aa8103ba21cc3ce305fab43e021 Mon Sep 17 00:00:00 2001 From: Dragoljub Djuric Date: Wed, 28 Aug 2024 13:35:02 +0200 Subject: [PATCH 3/5] Update rust/basic_bitcoin/README.md Co-authored-by: Dimitris Sarlis --- rust/basic_bitcoin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/basic_bitcoin/README.md b/rust/basic_bitcoin/README.md index d0d6839aa..768bb302d 100644 --- a/rust/basic_bitcoin/README.md +++ b/rust/basic_bitcoin/README.md @@ -216,7 +216,7 @@ reflected in your current balance. ## Step 6: Retrieving block headers -You can also get range of Bitcoin block headers by using the `get_block_headers` +You can also get a range of Bitcoin block headers by using the `get_block_headers` endpoint on your canister. In the Candid UI, write the desired start height and optionally end height, and click on "Call": From 373ba7236980ade31f329bd74f2a4de0caebfaa9 Mon Sep 17 00:00:00 2001 From: Dragoljub Djuric Date: Wed, 28 Aug 2024 13:39:58 +0200 Subject: [PATCH 4/5] Update README.md --- rust/basic_bitcoin/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/rust/basic_bitcoin/README.md b/rust/basic_bitcoin/README.md index 768bb302d..0d6cf3cdb 100644 --- a/rust/basic_bitcoin/README.md +++ b/rust/basic_bitcoin/README.md @@ -232,8 +232,6 @@ or replace `0` and `11` with your desired start and end height respectively: dfx canister --network=ic call basic_bitcoin get_block_headers "(0: nat32, 11: nat32)" ``` -Checking the balance of a Bitcoin address relies on the [bitcoin_get_block_headers](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-bitcoin_block_headers) API. - ## Conclusion In this tutorial, you were able to: From b48003e5a8d78dc347d99e77ab6dfda8a3f14cb1 Mon Sep 17 00:00:00 2001 From: Dragoljub Djuric Date: Wed, 28 Aug 2024 14:02:54 +0200 Subject: [PATCH 5/5] Update README.md --- rust/basic_bitcoin/README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/rust/basic_bitcoin/README.md b/rust/basic_bitcoin/README.md index 0d6cf3cdb..437a42715 100644 --- a/rust/basic_bitcoin/README.md +++ b/rust/basic_bitcoin/README.md @@ -219,10 +219,7 @@ reflected in your current balance. You can also get a range of Bitcoin block headers by using the `get_block_headers` endpoint on your canister. -In the Candid UI, write the desired start height and optionally end height, and click on "Call": - -Alternatively, make the call using the command line. Be sure to replace `10` with your -desired start height: +Make the call using the command line. Be sure to replace `10` with your desired start height: ```bash dfx canister --network=ic call basic_bitcoin get_block_headers "(10: nat32)"