diff --git a/openapi.yaml b/openapi.yaml index e7793967118..abc70299814 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -28,7 +28,7 @@ paths: default: getinfo id: type: string - default: QWlDS9bxlK + default: dX2SRjFwfc params: type: array items: {} @@ -61,7 +61,7 @@ paths: default: getblockchaininfo id: type: string - default: XSg3wvZykA + default: LoRrjyRM4l params: type: array items: {} @@ -99,7 +99,7 @@ paths: default: getaddressbalance id: type: string - default: GEd1QJWprH + default: WWIvpPiJo0 params: type: array items: {} @@ -147,7 +147,7 @@ paths: default: sendrawtransaction id: type: string - default: nhQi7D6Oru + default: '5tVg2R9ZeI' params: type: array items: {} @@ -196,7 +196,7 @@ paths: default: getblock id: type: string - default: qIEYMzgbJZ + default: vZ5KPOdiue params: type: array items: {} @@ -239,7 +239,7 @@ paths: default: getbestblockhash id: type: string - default: P9UBS8IXXU + default: IifeYgN2ZK params: type: array items: {} @@ -272,7 +272,7 @@ paths: default: getbestblockheightandhash id: type: string - default: gQNhsomx7N + default: tNLKsWqtNW params: type: array items: {} @@ -305,7 +305,7 @@ paths: default: getrawmempool id: type: string - default: c2ScL31PtX + default: IZ6todle9t params: type: array items: {} @@ -343,7 +343,7 @@ paths: default: z_gettreestate id: type: string - default: JQ0mENKbdm + default: SSZAwyUO6t params: type: array items: {} @@ -393,7 +393,7 @@ paths: default: z_getsubtreesbyindex id: type: string - default: bZUCv4t0f4 + default: '3fJMQ0Hfxt' params: type: array items: {} @@ -432,7 +432,7 @@ paths: default: getrawtransaction id: type: string - default: I0FAejAi4r + default: RTdE1YnNxy params: type: array items: {} @@ -480,7 +480,7 @@ paths: default: getaddresstxids id: type: string - default: '3fMzDHOglf' + default: ifahwzVoYe params: type: array items: {} @@ -528,7 +528,7 @@ paths: default: getaddressutxos id: type: string - default: LE2AR8Tr6X + default: PcPdZ7aiKy params: type: array items: {} @@ -571,7 +571,7 @@ paths: default: stop id: type: string - default: PbxxqB0ZpF + default: rWlJLGe7VJ params: type: array items: {} @@ -604,7 +604,7 @@ paths: default: getblockcount id: type: string - default: WO6BAIKSCg + default: f4p3Cb4sDu params: type: array items: {} @@ -642,7 +642,7 @@ paths: default: getblockhash id: type: string - default: vHpKNIQRLF + default: '3QXvqbEWqb' params: type: array items: {} @@ -690,7 +690,7 @@ paths: default: getblocktemplate id: type: string - default: L04jp5F2QW + default: GXKjn81k0D params: type: array items: {} @@ -728,7 +728,7 @@ paths: default: submitblock id: type: string - default: Izn7vhiMaA + default: cwGy92Mwn9 params: type: array items: {} @@ -761,7 +761,7 @@ paths: default: getmininginfo id: type: string - default: SgyuBQbMik + default: '4ZFY9ljh5I' params: type: array items: {} @@ -794,7 +794,7 @@ paths: default: getnetworksolps id: type: string - default: FXg2iH3eaX + default: tJlKGzARjU params: type: array items: {} @@ -827,7 +827,7 @@ paths: default: getnetworkhashps id: type: string - default: '2PWjf8QqfI' + default: '7pUkOt26PB' params: type: array items: {} @@ -860,7 +860,7 @@ paths: default: getpeerinfo id: type: string - default: OE9s5wkP0w + default: JjnSrPKeyS params: type: array items: {} @@ -898,7 +898,7 @@ paths: default: validateaddress id: type: string - default: '6FS4iGA4Ht' + default: pxZQt6VQ9U params: type: array items: {} @@ -936,7 +936,7 @@ paths: default: z_validateaddress id: type: string - default: utp8tN61yU + default: x2R2oRhdZE params: type: array items: {} @@ -974,7 +974,7 @@ paths: default: getblocksubsidy id: type: string - default: dgNZGo7lNa + default: vkhYJS3FH8 params: type: array items: {} @@ -1017,7 +1017,7 @@ paths: default: getdifficulty id: type: string - default: KEJv30D2MI + default: bC6q9c3xYO params: type: array items: {} @@ -1055,7 +1055,7 @@ paths: default: z_listunifiedreceivers id: type: string - default: lfBqvYghGm + default: EQvPXkcJC2 params: type: array items: {} @@ -1071,3 +1071,51 @@ paths: result: type: object default: '{"orchard":"orchard address if any","sapling":"sapling address if any","p2pkh":"p2pkh address if any","p2sh":"p2sh address if any"}' + /generate: + post: + tags: + - generating + description: |- + Mine blocks immediately. Returns the block hashes of the generated blocks. + + **Request body `params` arguments:** + + - `num_blocks` - Number of blocks to be generated. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + method: + type: string + default: generate + id: + type: string + default: w41FKROii3 + params: + type: array + items: {} + default: '[1]' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + result: + type: object + default: '{}' + '400': + description: Bad request + content: + application/json: + schema: + type: object + properties: + error: + type: string + default: Invalid parameters diff --git a/zebra-rpc/src/methods/get_block_template_rpcs.rs b/zebra-rpc/src/methods/get_block_template_rpcs.rs index c8c83e9315a..826f8d3e930 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs.rs @@ -19,7 +19,7 @@ use zebra_chain::{ Network, NetworkKind, NetworkUpgrade, POW_AVERAGING_WINDOW, }, primitives, - serialization::ZcashDeserializeInto, + serialization::{ZcashDeserializeInto, ZcashSerialize}, transparent::{ self, EXTRA_ZEBRA_COINBASE_DATA, MAX_COINBASE_DATA_LEN, MAX_COINBASE_HEIGHT_DATA_LEN, }, @@ -47,7 +47,9 @@ use crate::methods::{ // TODO: move the types/* modules directly under get_block_template_rpcs, // and combine any modules with the same names. types::{ - get_block_template::GetBlockTemplate, + get_block_template::{ + proposal::TimeSource, proposal_block_from_template, GetBlockTemplate, + }, get_mining_info, long_poll::LongPollInput, peer_info::PeerInfo, @@ -283,6 +285,22 @@ pub trait GetBlockTemplateRpc { &self, address: String, ) -> BoxFuture>; + + #[rpc(name = "generate")] + /// Mine blocks immediately. Returns the block hashes of the generated blocks. + /// + /// # Parameters + /// + /// - `num_blocks`: (numeric, required, example=1) Number of blocks to be generated. + /// + /// # Notes + /// + /// Only works if the network of the running zebrad process is `Regtest`. + /// + /// zcashd reference: [`generate`](https://zcash.github.io/rpc/generate.html) + /// method: post + /// tags: generating + fn generate(&self, num_blocks: u32) -> BoxFuture>>; } /// RPC method implementations. @@ -1357,6 +1375,61 @@ where } .boxed() } + + fn generate(&self, num_blocks: u32) -> BoxFuture>> { + let rpc: GetBlockTemplateRpcImpl< + Mempool, + State, + Tip, + BlockVerifierRouter, + SyncStatus, + AddressBook, + > = self.clone(); + let network = self.network.clone(); + + async move { + if !network.is_regtest() { + return Err(Error { + code: ErrorCode::ServerError(0), + message: "generate is only supported on regtest".to_string(), + data: None, + }); + } + + let mut block_hashes = Vec::new(); + for _ in 0..num_blocks { + let block_template = rpc.get_block_template(None).await.map_server_error()?; + + let get_block_template::Response::TemplateMode(block_template) = block_template + else { + return Err(Error { + code: ErrorCode::ServerError(0), + message: "error generating block template".to_string(), + data: None, + }); + }; + + let proposal_block = proposal_block_from_template( + &block_template, + TimeSource::CurTime, + NetworkUpgrade::current(&network, Height(block_template.height)), + ) + .map_server_error()?; + let hex_proposal_block = + HexData(proposal_block.zcash_serialize_to_vec().map_server_error()?); + + let _submit = rpc + .submit_block(hex_proposal_block, None) + .await + .map_server_error()?; + + block_hashes.push(GetBlockHash(proposal_block.hash())); + } + + Ok(block_hashes) + } + .boxed() + } } // Put support functions in a submodule, to keep this file small.