feature(rpc): add fixed values to getblocktemplate response (#5558)
* 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>
This commit is contained in:
parent
4c3f04eb80
commit
4ccd0741b6
|
@ -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};
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
@ -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"));
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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::{
|
||||
|
@ -33,6 +35,7 @@ use crate::methods::{
|
|||
};
|
||||
|
||||
pub mod config;
|
||||
pub mod constants;
|
||||
pub(crate) mod types;
|
||||
|
||||
/// getblocktemplate RPC method signatures.
|
||||
|
@ -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(),
|
||||
|
@ -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,
|
||||
|
@ -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(),
|
||||
|
@ -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: empty_string.clone(),
|
||||
nonce_range: constants::GET_BLOCK_TEMPLATE_NONCE_RANGE_FIELD.to_string(),
|
||||
|
||||
sigop_limit: 0,
|
||||
size_limit: 0,
|
||||
sigop_limit: MAX_BLOCK_SIGOPS,
|
||||
|
||||
size_limit: MAX_BLOCK_BYTES,
|
||||
|
||||
cur_time: 0,
|
||||
|
||||
|
|
|
@ -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"];
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
@ -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,
|
||||
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue