Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature(rpc): add fixed values to getblocktemplate response #5558

Merged
merged 10 commits into from
Nov 8, 2022
2 changes: 1 addition & 1 deletion zebra-chain/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use commitment::{
ChainHistoryBlockTxAuthCommitmentHash, ChainHistoryMmrRootHash, Commitment, CommitmentError,
};
pub use hash::Hash;
pub use header::{BlockTimeError, CountedHeader, Header};
pub use header::{BlockTimeError, CountedHeader, Header, ZCASH_BLOCK_VERSION};
pub use height::Height;
pub use serialize::{SerializedBlock, MAX_BLOCK_BYTES};

Expand Down
6 changes: 6 additions & 0 deletions zebra-chain/src/block/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ const BLOCK_HEADER_LENGTH: usize =
/// A CountedHeader has BLOCK_HEADER_LENGTH bytes + 1 or more bytes for the transaction count
pub(crate) const MIN_COUNTED_HEADER_LEN: usize = BLOCK_HEADER_LENGTH + 1;

/// The Zcash accepted block version.
///
/// The consensus rules do not force the block version to be this value but just equal or greater than it.
/// However, it is suggested that submitted block versions to be of this exact value.
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
pub const ZCASH_BLOCK_VERSION: u32 = 4;

impl TrustedPreallocate for CountedHeader {
fn max_allocation() -> u64 {
// Every vector type requires a length field of at least one byte for de/serialization.
Expand Down
4 changes: 2 additions & 2 deletions zebra-chain/src/block/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{
work::{difficulty::CompactDifficulty, equihash},
};

use super::{merkle, Block, CountedHeader, Hash, Header};
use super::{header::ZCASH_BLOCK_VERSION, merkle, Block, CountedHeader, Hash, Header};

/// The maximum size of a Zcash block, in bytes.
///
Expand Down Expand Up @@ -77,7 +77,7 @@ impl ZcashDeserialize for Header {
// > The block version number MUST be greater than or equal to 4.
//
// https://zips.z.cash/protocol/protocol.pdf#blockheader
if version < 4 {
if version < ZCASH_BLOCK_VERSION {
return Err(SerializationError::Parse("version must be at least 4"));
}

Expand Down
2 changes: 1 addition & 1 deletion zebra-consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub mod chain;
#[allow(missing_docs)]
pub mod error;

pub use block::VerifyBlockError;
pub use block::{VerifyBlockError, MAX_BLOCK_SIGOPS};
pub use chain::VerifyChainError;
pub use checkpoint::{
CheckpointList, VerifyCheckpointError, MAX_CHECKPOINT_BYTE_COUNT, MAX_CHECKPOINT_HEIGHT_GAP,
Expand Down
36 changes: 23 additions & 13 deletions zebra-rpc/src/methods/get_block_template_rpcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ use zebra_chain::{
block::{
self,
merkle::{self, AuthDataRoot},
Block,
Block, MAX_BLOCK_BYTES, ZCASH_BLOCK_VERSION,
},
chain_tip::ChainTip,
parameters::Network,
serialization::ZcashDeserializeInto,
transaction::{UnminedTx, VerifiedUnminedTx},
};
use zebra_consensus::{BlockError, VerifyBlockError, VerifyChainError, VerifyCheckpointError};
use zebra_consensus::{
BlockError, VerifyBlockError, VerifyChainError, VerifyCheckpointError, MAX_BLOCK_SIGOPS,
};
use zebra_node_services::mempool;

use crate::methods::{
Expand All @@ -33,6 +35,7 @@ use crate::methods::{
};

pub mod config;
pub mod constants;
pub(crate) mod types;

/// getblocktemplate RPC method signatures.
Expand Down Expand Up @@ -273,12 +276,12 @@ where

TODO: create a method Transaction::new_v5_coinbase(network, tip_height, miner_fee),
and call it here.
*/
*/
let coinbase_tx = if mempool_txs.is_empty() {
let empty_string = String::from("");
return Ok(GetBlockTemplate {
capabilities: vec![],
version: 0,
version: ZCASH_BLOCK_VERSION,
previous_block_hash: GetBlockHash([0; 32].into()),
block_commitments_hash: [0; 32].into(),
light_client_root_hash: [0; 32].into(),
Expand All @@ -301,10 +304,13 @@ where
},
target: empty_string.clone(),
min_time: 0,
mutable: vec![],
nonce_range: empty_string.clone(),
sigop_limit: 0,
size_limit: 0,
mutable: constants::GET_BLOCK_TEMPLATE_MUTABLE_FIELD
.iter()
.map(ToString::to_string)
.collect(),
nonce_range: constants::GET_BLOCK_TEMPLATE_NONCE_RANGE_FIELD.to_string(),
sigop_limit: MAX_BLOCK_SIGOPS,
size_limit: MAX_BLOCK_BYTES,
cur_time: 0,
bits: empty_string,
height: 0,
Expand All @@ -323,7 +329,7 @@ where
Ok(GetBlockTemplate {
capabilities: vec![],

version: 0,
version: ZCASH_BLOCK_VERSION,

previous_block_hash: GetBlockHash([0; 32].into()),
block_commitments_hash: [0; 32].into(),
Expand All @@ -344,12 +350,16 @@ where

min_time: 0,

mutable: vec![],
mutable: constants::GET_BLOCK_TEMPLATE_MUTABLE_FIELD
.iter()
.map(ToString::to_string)
.collect(),

nonce_range: constants::GET_BLOCK_TEMPLATE_NONCE_RANGE_FIELD.to_string(),

nonce_range: empty_string.clone(),
sigop_limit: MAX_BLOCK_SIGOPS,

sigop_limit: 0,
size_limit: 0,
size_limit: MAX_BLOCK_BYTES,

cur_time: 0,

Expand Down
7 changes: 7 additions & 0 deletions zebra-rpc/src/methods/get_block_template_rpcs/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Constant values used in mining rpcs methods.

/// A range of valid nonces that goes from `u32::MIN` to `u32::MAX` as a string.
pub const GET_BLOCK_TEMPLATE_NONCE_RANGE_FIELD: &str = "00000000ffffffff";

/// A hardcoded list of fields that the miner can change from the block.
pub const GET_BLOCK_TEMPLATE_MUTABLE_FIELD: &[&str] = &["time", "transactions", "prevblock"];
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use zebra_chain::block::{
ChainHistoryBlockTxAuthCommitmentHash, ChainHistoryMmrRootHash,
};

/// Documentation to be added in #5452 or #5455.
/// The block header roots for [`GetBlockTemplate.transactions`].
///
/// If the transactions in the block template are modified, these roots must be recalculated
/// [according to the specification](https://zcash.github.io/rpc/getblocktemplate.html).
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub struct DefaultRoots {
/// The merkle root of the transaction IDs in the block.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,47 @@ use crate::methods::{
/// 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.
/// The getblocktemplate RPC capabilities supported by Zebra.
///
/// At the moment, Zebra does not support any of the extra capabilities from the specification:
/// - `proposal`: <https://en.bitcoin.it/wiki/BIP_0023#Block_Proposal>
/// - `longpoll`: <https://en.bitcoin.it/wiki/BIP_0022#Optional:_Long_Polling>
/// - `serverlist`: <https://en.bitcoin.it/wiki/BIP_0023#Logical_Services>
pub capabilities: Vec<String>,

/// The version of the block format.
/// Always 4 for new Zcash blocks.
//
// TODO: add a default block version constant to zebra-chain.
pub version: u32,

/// Add documentation.
/// The hash of the previous block.
#[serde(rename = "previousblockhash")]
pub previous_block_hash: GetBlockHash,

/// Add documentation.
/// The block commitment for the new block's header.
///
/// Same as [`DefaultRoots.block_commitments_hash`], see that field for details.
#[serde(rename = "blockcommitmentshash")]
#[serde(with = "hex")]
pub block_commitments_hash: ChainHistoryBlockTxAuthCommitmentHash,

/// Add documentation.
/// Legacy backwards-compatibility header root field.
///
/// Same as [`DefaultRoots.block_commitments_hash`], see that field for details.
#[serde(rename = "lightclientroothash")]
#[serde(with = "hex")]
pub light_client_root_hash: ChainHistoryBlockTxAuthCommitmentHash,

/// Add documentation.
/// Legacy backwards-compatibility header root field.
///
/// Same as [`DefaultRoots.block_commitments_hash`], see that field for details.
#[serde(rename = "finalsaplingroothash")]
#[serde(with = "hex")]
pub final_sapling_root_hash: ChainHistoryBlockTxAuthCommitmentHash,

/// Add documentation.
/// The block header roots for [`GetBlockTemplate.transactions`].
///
/// If the transactions in the block template are modified, these roots must be recalculated
/// [according to the specification](https://zcash.github.io/rpc/getblocktemplate.html).
#[serde(rename = "defaultroots")]
pub default_roots: DefaultRoots,

Expand All @@ -62,22 +74,18 @@ pub struct GetBlockTemplate {
// TODO: use DateTime32 type?
pub min_time: u32,

/// Add documentation.
/// Hardcoded list of block fields the miner is allowed to change.
pub mutable: Vec<String>,

/// Add documentation.
/// A range of valid nonces that goes from `u32::MIN` to `u32::MAX`.
#[serde(rename = "noncerange")]
pub nonce_range: String,

/// Add documentation.
///
/// The same as `MAX_BLOCK_SIGOPS`.
/// Max legacy signature operations in the block.
#[serde(rename = "sigoplimit")]
pub sigop_limit: u64,

/// Add documentation.
///
/// The same as `MAX_BLOCK_BYTES`.
/// Max block size in bytes
#[serde(rename = "sizelimit")]
pub size_limit: u64,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use zebra_state::LatestChainTip;
use zebra_test::mock_service::{MockService, PanicAssertion};

use crate::methods::{
get_block_template_rpcs::types::{hex_data::HexData, submit_block},
get_block_template_rpcs::types::{
get_block_template::GetBlockTemplate, hex_data::HexData, submit_block,
},
GetBlockHash, GetBlockTemplateRpc, GetBlockTemplateRpcImpl,
};

Expand Down Expand Up @@ -122,10 +124,7 @@ fn snapshot_rpc_getblockhash(block_hash: GetBlockHash, settings: &insta::Setting
}

/// 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,
) {
fn snapshot_rpc_getblocktemplate(block_template: GetBlockTemplate, settings: &insta::Settings) {
settings.bind(|| insta::assert_json_snapshot!("get_block_template", block_template));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
---
source: zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs
assertion_line: 128
teor2345 marked this conversation as resolved.
Show resolved Hide resolved
expression: block_template
---
{
"capabilities": [],
"version": 0,
"version": 4,
"previousblockhash": "0000000000000000000000000000000000000000000000000000000000000000",
"blockcommitmentshash": "0000000000000000000000000000000000000000000000000000000000000000",
"lightclientroothash": "0000000000000000000000000000000000000000000000000000000000000000",
Expand All @@ -27,10 +28,14 @@ expression: block_template
},
"target": "",
"mintime": 0,
"mutable": [],
"noncerange": "",
"sigoplimit": 0,
"sizelimit": 0,
"mutable": [
"time",
"transactions",
"prevblock"
],
"noncerange": "00000000ffffffff",
"sigoplimit": 20000,
"sizelimit": 2000000,
"curtime": 0,
"bits": "",
"height": 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
---
source: zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs
assertion_line: 128
expression: block_template
---
{
"capabilities": [],
"version": 0,
"version": 4,
"previousblockhash": "0000000000000000000000000000000000000000000000000000000000000000",
"blockcommitmentshash": "0000000000000000000000000000000000000000000000000000000000000000",
"lightclientroothash": "0000000000000000000000000000000000000000000000000000000000000000",
Expand All @@ -27,10 +28,14 @@ expression: block_template
},
"target": "",
"mintime": 0,
"mutable": [],
"noncerange": "",
"sigoplimit": 0,
"sizelimit": 0,
"mutable": [
"time",
"transactions",
"prevblock"
],
"noncerange": "00000000ffffffff",
"sigoplimit": 20000,
"sizelimit": 2000000,
"curtime": 0,
"bits": "",
"height": 0
Expand Down
22 changes: 17 additions & 5 deletions zebra-rpc/src/methods/tests/vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,12 @@ async fn rpc_getblockhash() {
async fn rpc_getblocktemplate() {
use std::panic;

use crate::methods::get_block_template_rpcs::constants::{
GET_BLOCK_TEMPLATE_MUTABLE_FIELD, GET_BLOCK_TEMPLATE_NONCE_RANGE_FIELD,
};
use zebra_chain::block::{MAX_BLOCK_BYTES, ZCASH_BLOCK_VERSION};
use zebra_consensus::MAX_BLOCK_SIGOPS;

let _init_guard = zebra_test::init();

// Create a continuous chain of mainnet blocks from genesis
Expand Down Expand Up @@ -835,14 +841,20 @@ async fn rpc_getblocktemplate() {
.expect("unexpected error in getblocktemplate RPC call");

assert!(get_block_template.capabilities.is_empty());
assert_eq!(get_block_template.version, 0);
assert_eq!(get_block_template.version, ZCASH_BLOCK_VERSION);
assert!(get_block_template.transactions.is_empty());
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.mutable,
GET_BLOCK_TEMPLATE_MUTABLE_FIELD.to_vec()
);
assert_eq!(
get_block_template.nonce_range,
GET_BLOCK_TEMPLATE_NONCE_RANGE_FIELD
);
assert_eq!(get_block_template.sigop_limit, MAX_BLOCK_SIGOPS);
assert_eq!(get_block_template.size_limit, MAX_BLOCK_BYTES);
assert_eq!(get_block_template.cur_time, 0);
assert!(get_block_template.bits.is_empty());
assert_eq!(get_block_template.height, 0);
Expand Down