Skip to content

Commit

Permalink
feature(rpc): add fixed values to getblocktemplate response (#5558)
Browse files Browse the repository at this point in the history
* add fixed values to getblocktemplate rpc call response

* suggestion: Avoid new uses of lazy_static (#5559)

* Avoid using lazy_static

* Add some missing documentation

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>

* minor fixes

* move docs to struct

* add fixed values to coinbase tx

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Co-authored-by: teor <teor@riseup.net>
  • Loading branch information
3 people committed Nov 8, 2022
1 parent 4c3f04e commit 4ccd074
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 54 deletions.
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.
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
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

0 comments on commit 4ccd074

Please sign in to comment.