Skip to content

Commit

Permalink
Merge of #5462
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Oct 26, 2022
2 parents a330285 + 575e89d commit c41c8bd
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 6 deletions.
4 changes: 2 additions & 2 deletions zebra-rpc/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ use zebra_state::{OutputIndex, OutputLocation, TransactionLocation};
use crate::queue::Queue;

#[cfg(feature = "getblocktemplate-rpcs")]
mod get_block_template;
mod get_block_template_rpcs;

#[cfg(feature = "getblocktemplate-rpcs")]
pub use get_block_template::{GetBlockTemplateRpc, GetBlockTemplateRpcImpl};
pub use get_block_template_rpcs::{GetBlockTemplateRpc, GetBlockTemplateRpcImpl};

#[cfg(test)]
mod tests;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ use jsonrpc_core::{self, BoxFuture, Error, ErrorCode, Result};
use jsonrpc_derive::rpc;
use tower::{Service, ServiceExt};

use crate::methods::{GetBlockHash, MISSING_BLOCK_ERROR_CODE};
pub(crate) mod types;

use crate::methods::{
get_block_template_rpcs::types::{
coinbase::Coinbase, default_roots::DefaultRoots, get_block_template::GetBlockTemplate,
},
GetBlockHash, MISSING_BLOCK_ERROR_CODE,
};

/// getblocktemplate RPC method signatures.
#[rpc(server)]
Expand Down Expand Up @@ -35,8 +42,19 @@ pub trait GetBlockTemplateRpc {
///
/// - If `index` is positive then index = block height.
/// - If `index` is negative then -1 is the last known valid block.
/// - This rpc method is available only if zebra is built with `--features getblocktemplate-rpcs`.
#[rpc(name = "getblockhash")]
fn get_block_hash(&self, index: i32) -> BoxFuture<Result<GetBlockHash>>;

/// Documentation to be filled as we go.
///
/// zcashd reference: [`getblocktemplate`](https://zcash-rpc.github.io/getblocktemplate.html)
///
/// # Notes
///
/// - This rpc method is available only if zebra is built with `--features getblocktemplate-rpcs`.
#[rpc(name = "getblocktemplate")]
fn get_block_template(&self) -> BoxFuture<Result<GetBlockTemplate>>;
}

/// RPC method implementations.
Expand Down Expand Up @@ -139,6 +157,40 @@ where
}
.boxed()
}

fn get_block_template(&self) -> BoxFuture<Result<GetBlockTemplate>> {
async move {
let empty_string = String::from("");

// Returns empty `GetBlockTemplate`
Ok(GetBlockTemplate {
capabilities: vec![],
version: 0,
previous_block_hash: empty_string.clone(),
block_commitments_hash: empty_string.clone(),
light_client_root_hash: empty_string.clone(),
final_sapling_root_hash: empty_string.clone(),
default_roots: DefaultRoots {
merkle_root: empty_string.clone(),
chain_history_root: empty_string.clone(),
auth_data_root: empty_string.clone(),
block_commitments_hash: empty_string.clone(),
},
transactions: vec![],
coinbase_txn: Coinbase {},
target: empty_string.clone(),
min_time: 0,
mutable: vec![],
nonce_range: empty_string.clone(),
sigop_limit: 0,
size_limit: 0,
cur_time: 0,
bits: empty_string,
height: 0,
})
}
.boxed()
}
}

/// Given a potentially negative index, find the corresponding `Height`.
Expand Down
6 changes: 6 additions & 0 deletions zebra-rpc/src/methods/get_block_template_rpcs/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//! Types used in mining RPC methods.
pub(crate) mod coinbase;
pub(crate) mod default_roots;
pub(crate) mod get_block_template;
pub(crate) mod transaction;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//! The `Coinbase` type is part of the `getblocktemplate` RPC method output.
/// documentation and fields to be added in #5453.
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Coinbase {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! The `DefaultRoots` type is part of the `getblocktemplate` RPC method output.
/// Documentation to be added in #5452 or #5455.
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct DefaultRoots {
/// Add documentation.
#[serde(rename = "merkleroot")]
pub merkle_root: String,
/// Add documentation.
#[serde(rename = "chainhistoryroot")]
pub chain_history_root: String,
/// Add documentation.
#[serde(rename = "authdataroot")]
pub auth_data_root: String,
/// Add documentation.
#[serde(rename = "blockcommitmentshash")]
pub block_commitments_hash: String,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//! The `GetBlockTempate` type is the output of the `getblocktemplate` RPC method.
use crate::methods::get_block_template_rpcs::types::{
coinbase::Coinbase, default_roots::DefaultRoots, transaction::Transaction,
};

/// Documentation to be added after we document all the individual fields.
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct GetBlockTemplate {
/// Add documentation.
pub capabilities: Vec<String>,
/// Add documentation.
pub version: usize,
/// Add documentation.
#[serde(rename = "previousblockhash")]
pub previous_block_hash: String,
/// Add documentation.
#[serde(rename = "blockcommitmentshash")]
pub block_commitments_hash: String,
/// Add documentation.
#[serde(rename = "lightclientroothash")]
pub light_client_root_hash: String,
/// Add documentation.
#[serde(rename = "finalsaplingroothash")]
pub final_sapling_root_hash: String,
/// Add documentation.
#[serde(rename = "defaultroots")]
pub default_roots: DefaultRoots,
/// Add documentation.
pub transactions: Vec<Transaction>,
/// Add documentation.
#[serde(rename = "coinbasetxn")]
pub coinbase_txn: Coinbase,
/// Add documentation.
pub target: String,
/// Add documentation.
#[serde(rename = "mintime")]
pub min_time: u32,
/// Add documentation.
pub mutable: Vec<String>,
/// Add documentation.
#[serde(rename = "noncerange")]
pub nonce_range: String,
/// Add documentation.
#[serde(rename = "sigoplimit")]
pub sigop_limit: u32,
/// Add documentation.
#[serde(rename = "sizelimit")]
pub size_limit: u32,
/// Add documentation.
#[serde(rename = "curtime")]
pub cur_time: u32,
/// Add documentation.
pub bits: String,
/// Add documentation.
pub height: u32,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//! The `Transaction` type is part of the `getblocktemplate` RPC method output.
/// Documentation and fields to be added in #5454.
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct Transaction {}
16 changes: 16 additions & 0 deletions zebra-rpc/src/methods/tests/snapshot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@ async fn test_rpc_response_data_for_network(network: Network) {
.expect("We should have a GetBlockHash struct");

snapshot_rpc_getblockhash(get_block_hash, &settings);

// `getblocktemplate`
let get_block_template = get_block_template_rpc
.get_block_template()
.await
.expect("We should have a GetBlockTemplate struct");
snapshot_rpc_getblocktemplate(get_block_template, &settings);
}
}

Expand Down Expand Up @@ -292,6 +299,15 @@ fn snapshot_rpc_getblockhash(block_hash: GetBlockHash, settings: &insta::Setting
settings.bind(|| insta::assert_json_snapshot!("get_block_hash", block_hash));
}

#[cfg(feature = "getblocktemplate-rpcs")]
/// Snapshot `getblocktemplate` response, using `cargo insta` and JSON serialization.
fn snapshot_rpc_getblocktemplate(
block_template: crate::methods::get_block_template_rpcs::types::get_block_template::GetBlockTemplate,
settings: &insta::Settings,
) {
settings.bind(|| insta::assert_json_snapshot!("get_block_template", block_template));
}

/// Utility function to convert a `Network` to a lowercase string.
fn network_string(network: Network) -> String {
let mut net_suffix = network.to_string();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
source: zebra-rpc/src/methods/tests/snapshot.rs
assertion_line: 308
expression: block_template
---
{
"capabilities": [],
"version": 0,
"previousblockhash": "",
"blockcommitmentshash": "",
"lightclientroothash": "",
"finalsaplingroothash": "",
"defaultroots": {
"merkleroot": "",
"chainhistoryroot": "",
"authdataroot": "",
"blockcommitmentshash": ""
},
"transactions": [],
"coinbasetxn": {},
"target": "",
"mintime": 0,
"mutable": [],
"noncerange": "",
"sigoplimit": 0,
"sizelimit": 0,
"curtime": 0,
"bits": "",
"height": 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
source: zebra-rpc/src/methods/tests/snapshot.rs
assertion_line: 308
expression: block_template
---
{
"capabilities": [],
"version": 0,
"previousblockhash": "",
"blockcommitmentshash": "",
"lightclientroothash": "",
"finalsaplingroothash": "",
"defaultroots": {
"merkleroot": "",
"chainhistoryroot": "",
"authdataroot": "",
"blockcommitmentshash": ""
},
"transactions": [],
"coinbasetxn": {},
"target": "",
"mintime": 0,
"mutable": [],
"noncerange": "",
"sigoplimit": 0,
"sizelimit": 0,
"curtime": 0,
"bits": "",
"height": 0
}
73 changes: 70 additions & 3 deletions zebra-rpc/src/methods/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,7 @@ async fn rpc_getblockcount() {

// Init RPC
let get_block_template_rpc =
get_block_template::GetBlockTemplateRpcImpl::new(latest_chain_tip.clone(), read_state);
get_block_template_rpcs::GetBlockTemplateRpcImpl::new(latest_chain_tip.clone(), read_state);

// Get the tip height using RPC method `get_block_count`
let get_block_count = get_block_template_rpc
Expand Down Expand Up @@ -686,7 +686,7 @@ async fn rpc_getblockcount_empty_state() {
);

let get_block_template_rpc =
get_block_template::GetBlockTemplateRpcImpl::new(latest_chain_tip.clone(), read_state);
get_block_template_rpcs::GetBlockTemplateRpcImpl::new(latest_chain_tip.clone(), read_state);

// Get the tip height using RPC method `get_block_count
let get_block_count = get_block_template_rpc.get_block_count();
Expand Down Expand Up @@ -730,7 +730,7 @@ async fn rpc_getblockhash() {
latest_chain_tip.clone(),
);
let get_block_template_rpc =
get_block_template::GetBlockTemplateRpcImpl::new(latest_chain_tip, read_state);
get_block_template_rpcs::GetBlockTemplateRpcImpl::new(latest_chain_tip, read_state);

// Query the hashes using positive indexes
for (i, block) in blocks.iter().enumerate() {
Expand All @@ -757,3 +757,70 @@ async fn rpc_getblockhash() {

mempool.expect_no_requests().await;
}

#[cfg(feature = "getblocktemplate-rpcs")]
#[tokio::test(flavor = "multi_thread")]
async fn rpc_getblocktemplate() {
let _init_guard = zebra_test::init();

// Create a continuous chain of mainnet blocks from genesis
let blocks: Vec<Arc<Block>> = zebra_test::vectors::CONTINUOUS_MAINNET_BLOCKS
.iter()
.map(|(_height, block_bytes)| block_bytes.zcash_deserialize_into().unwrap())
.collect();

let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
// Create a populated state service
let (_state, read_state, latest_chain_tip, _chain_tip_change) =
zebra_state::populated_state(blocks.clone(), Mainnet).await;

// Init RPCs
let _rpc = RpcImpl::new(
"RPC test",
Mainnet,
false,
Buffer::new(mempool.clone(), 1),
Buffer::new(read_state.clone(), 1),
latest_chain_tip.clone(),
);
let get_block_template_rpc =
get_block_template_rpcs::GetBlockTemplateRpcImpl::new(latest_chain_tip, read_state);

let get_block_template = get_block_template_rpc
.get_block_template()
.await
.expect("We should have a GetBlockTemplate struct");

assert!(get_block_template.capabilities.is_empty());
assert_eq!(get_block_template.version, 0);
assert!(get_block_template.previous_block_hash.is_empty());
assert!(get_block_template.block_commitments_hash.is_empty());
assert!(get_block_template.light_client_root_hash.is_empty());
assert!(get_block_template.final_sapling_root_hash.is_empty());
assert!(get_block_template.default_roots.merkle_root.is_empty());
assert!(get_block_template
.default_roots
.chain_history_root
.is_empty());
assert!(get_block_template.default_roots.auth_data_root.is_empty());
assert!(get_block_template
.default_roots
.block_commitments_hash
.is_empty());
assert!(get_block_template.transactions.is_empty());
assert_eq!(
get_block_template.coinbase_txn,
get_block_template_rpcs::types::coinbase::Coinbase {}
);
assert!(get_block_template.target.is_empty());
assert_eq!(get_block_template.min_time, 0);
assert!(get_block_template.mutable.is_empty());
assert!(get_block_template.nonce_range.is_empty());
assert_eq!(get_block_template.sigop_limit, 0);
assert_eq!(get_block_template.size_limit, 0);
assert_eq!(get_block_template.cur_time, 0);
assert!(get_block_template.bits.is_empty());
assert_eq!(get_block_template.height, 0);

mempool.expect_no_requests().await;
}

0 comments on commit c41c8bd

Please sign in to comment.