Skip to content

Commit 049bf22

Browse files
committed
tmp
1 parent f92e8ca commit 049bf22

6 files changed

Lines changed: 715 additions & 3 deletions

File tree

bitcoin/src/iter.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{BitcoinCoreApi, BitcoinRpcError, Error};
1+
use crate::{BitcoinCoreApi, DynBitcoinCoreApi, BitcoinRpcError, Error};
22
use bitcoincore_rpc::{
33
bitcoin::{Block, BlockHash, Transaction},
44
jsonrpc::Error as JsonRpcError,
@@ -8,8 +8,6 @@ use futures::{prelude::*, stream::StreamExt};
88
use log::trace;
99
use std::{iter, sync::Arc};
1010

11-
type DynBitcoinCoreApi = Arc<dyn BitcoinCoreApi + Send + Sync>;
12-
1311
/// Stream over transactions, starting with this in the mempool and continuing with
1412
/// transactions from previous in-chain block. The stream ends after the block at
1513
/// `stop_height` has been returned.

bitcoin/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod addr;
1010
mod electrs;
1111
mod error;
1212
mod iter;
13+
pub mod relay;
1314

1415
use async_trait::async_trait;
1516
use backoff::{backoff::Backoff, future::retry, ExponentialBackoff};
@@ -50,6 +51,7 @@ use bitcoincore_rpc::{
5051
pub use electrs::{ElectrsClient, Error as ElectrsError};
5152
pub use error::{BitcoinRpcError, ConversionError, Error};
5253
pub use iter::{reverse_stream_transactions, stream_blocks, stream_in_chain_transactions};
54+
pub use relay::*;
5355
use log::{info, trace, warn};
5456
use serde_json::error::Category as SerdeJsonCategory;
5557
pub use sp_core::H256;
@@ -104,6 +106,8 @@ const RANDOMIZATION_FACTOR: f64 = 0.25;
104106
const DERIVATION_KEY_LABEL: &str = "derivation-key";
105107
const DEPOSIT_LABEL: &str = "deposit";
106108

109+
pub type DynBitcoinCoreApi = Arc<dyn BitcoinCoreApi + Send + Sync>;
110+
107111
fn get_exponential_backoff() -> ExponentialBackoff {
108112
ExponentialBackoff {
109113
current_interval: INITIAL_INTERVAL,

bitcoin/src/relay/backing.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use super::Error;
2+
use crate::DynBitcoinCoreApi;
3+
use async_trait::async_trait;
4+
use crate::{serialize, BitcoinCoreApi, Error as BitcoinError};
5+
6+
#[async_trait]
7+
pub trait Backing {
8+
/// Returns the height of the longest chain
9+
async fn get_block_count(&self) -> Result<u32, Error>;
10+
11+
/// Returns the raw header of a block in storage
12+
///
13+
/// # Arguments
14+
///
15+
/// * `height` - The height of the block to fetch
16+
async fn get_block_header(&self, height: u32) -> Result<Option<Vec<u8>>, Error>;
17+
18+
/// Returns the (little endian) hash of a block
19+
///
20+
/// # Arguments
21+
///
22+
/// * `height` - The height of the block to fetch
23+
async fn get_block_hash(&self, height: u32) -> Result<Vec<u8>, Error>;
24+
}
25+
26+
#[async_trait]
27+
impl Backing for DynBitcoinCoreApi {
28+
async fn get_block_count(&self) -> Result<u32, Error> {
29+
let count = BitcoinCoreApi::get_block_count(&**self).await?;
30+
return Ok(count as u32);
31+
}
32+
33+
async fn get_block_header(&self, height: u32) -> Result<Option<Vec<u8>>, Error> {
34+
let block_hash = match BitcoinCoreApi::get_block_hash(&**self, height).await {
35+
Ok(h) => h,
36+
Err(BitcoinError::InvalidBitcoinHeight) => {
37+
return Ok(None);
38+
}
39+
Err(err) => return Err(err.into()),
40+
};
41+
let block_header = BitcoinCoreApi::get_block_header(&**self, &block_hash).await?;
42+
Ok(Some(serialize(&block_header)))
43+
}
44+
45+
async fn get_block_hash(&self, height: u32) -> Result<Vec<u8>, Error> {
46+
let block_hash = BitcoinCoreApi::get_block_hash(&**self, height)
47+
.await
48+
.map(|hash| serialize(&hash))?;
49+
Ok(block_hash)
50+
}
51+
}

bitcoin/src/relay/error.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#![allow(clippy::enum_variant_names)]
2+
3+
use crate::Error as BitcoinError;
4+
use thiserror::Error;
5+
6+
#[cfg(test)]
7+
use std::mem::discriminant;
8+
9+
#[derive(Error, Debug)]
10+
pub enum Error {
11+
#[error("Client already initialized")]
12+
AlreadyInitialized,
13+
#[error("Client has not been initialized")]
14+
NotInitialized,
15+
#[error("Block already submitted")]
16+
BlockExists,
17+
#[error("Cannot read the best height")]
18+
CannotFetchBestHeight,
19+
#[error("Block hash not found for the given height")]
20+
BlockHashNotFound,
21+
#[error("Block header not found for the given height")]
22+
BlockHeaderNotFound,
23+
#[error("Failed to decode hash")]
24+
DecodeHash,
25+
#[error("Failed to serialize block header")]
26+
SerializeHeader,
27+
28+
#[error("BitcoinError: {0}")]
29+
BitcoinError(#[from] BitcoinError),
30+
}
31+
32+
#[cfg(test)]
33+
impl PartialEq for Error {
34+
fn eq(&self, other: &Self) -> bool {
35+
discriminant(self) == discriminant(other)
36+
}
37+
}

bitcoin/src/relay/issuing.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use super::Error;
2+
use async_trait::async_trait;
3+
use crate::{sha256, Hash};
4+
use std::sync::Arc;
5+
6+
#[async_trait]
7+
pub trait Issuing {
8+
/// Returns true if the light client is initialized
9+
async fn is_initialized(&self) -> Result<bool, Error>;
10+
11+
/// Initialize the light client
12+
///
13+
/// # Arguments
14+
///
15+
/// * `header` - Raw block header
16+
/// * `height` - Starting height
17+
async fn initialize(&self, header: Vec<u8>, height: u32) -> Result<(), Error>;
18+
19+
/// Submit a block header and wait for inclusion
20+
///
21+
/// # Arguments
22+
///
23+
/// * `header` - Raw block header
24+
async fn submit_block_header(
25+
&self,
26+
header: Vec<u8>,
27+
) -> Result<(), Error>;
28+
29+
/// Submit a batch of block headers and wait for inclusion
30+
///
31+
/// # Arguments
32+
///
33+
/// * `headers` - Raw block headers (multiple of 80 bytes)
34+
async fn submit_block_header_batch(&self, headers: Vec<Vec<u8>>) -> Result<(), Error>;
35+
36+
/// Returns the light client's chain tip
37+
async fn get_best_height(&self) -> Result<u32, Error>;
38+
39+
/// Returns the block hash stored at a given height,
40+
/// this is assumed to be in little-endian format
41+
///
42+
/// # Arguments
43+
///
44+
/// * `height` - Height of the block to fetch
45+
async fn get_block_hash(&self, height: u32) -> Result<Vec<u8>, Error>;
46+
47+
/// Returns true if the block described by the hash
48+
/// has been stored in the light client
49+
///
50+
/// # Arguments
51+
///
52+
/// * `hash_le` - Hash (little-endian) of the block
53+
async fn is_block_stored(&self, hash_le: Vec<u8>) -> Result<bool, Error>;
54+
}

0 commit comments

Comments
 (0)