zebra_rpc/methods/types/submit_block.rs
1//! Parameter and response types for the `submitblock` RPC.
2
3use tokio::sync::watch;
4
5use zebra_chain::{block, parameters::GENESIS_PREVIOUS_BLOCK_HASH};
6
7// Allow doc links to these imports.
8#[allow(unused_imports)]
9use crate::methods::get_block_template::GetBlockTemplateHandler;
10
11/// Optional argument `jsonparametersobject` for `submitblock` RPC request
12///
13/// See the notes for the [`submit_block`](crate::methods::RpcServer::submit_block) RPC.
14#[derive(Clone, Debug, PartialEq, Eq, serde::Deserialize)]
15pub struct JsonParameters {
16 /// The workid for the block template. Currently unused.
17 ///
18 /// > If the server provided a workid, it MUST be included with submissions,
19 ///
20 /// Rationale:
21 ///
22 /// > If servers allow all mutations, it may be hard to identify which job it is based on.
23 /// > While it may be possible to verify the submission by its content, it is much easier
24 /// > to compare it to the job issued. It is very easy for the miner to keep track of this.
25 /// > Therefore, using a "workid" is a very cheap solution to enable more mutations.
26 ///
27 /// <https://en.bitcoin.it/wiki/BIP_0022#Rationale>
28 #[serde(rename = "workid")]
29 pub _work_id: Option<String>,
30}
31
32/// Response to a `submitblock` RPC request.
33///
34/// Zebra never returns "duplicate-invalid", because it does not store invalid blocks.
35#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
36#[serde(rename_all = "kebab-case")]
37pub enum ErrorResponse {
38 /// Block was already committed to the non-finalized or finalized state
39 Duplicate,
40 /// Block was already added to the state queue or channel, but not yet committed to the non-finalized state
41 DuplicateInconclusive,
42 /// Block was already committed to the non-finalized state, but not on the best chain
43 Inconclusive,
44 /// Block rejected as invalid
45 Rejected,
46}
47
48/// Response to a `submitblock` RPC request.
49///
50/// Zebra never returns "duplicate-invalid", because it does not store invalid blocks.
51#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
52#[serde(untagged)]
53pub enum Response {
54 /// Block was not successfully submitted, return error
55 ErrorResponse(ErrorResponse),
56 /// Block successfully submitted, returns null
57 Accepted,
58}
59
60impl Default for Response {
61 fn default() -> Self {
62 Self::ErrorResponse(ErrorResponse::Rejected)
63 }
64}
65
66impl From<ErrorResponse> for Response {
67 fn from(error_response: ErrorResponse) -> Self {
68 Self::ErrorResponse(error_response)
69 }
70}
71
72/// A submit block channel, used to inform the gossip task about mined blocks.
73pub struct SubmitBlockChannel {
74 /// The channel sender
75 sender: watch::Sender<(block::Hash, block::Height)>,
76 /// The channel receiver
77 receiver: watch::Receiver<(block::Hash, block::Height)>,
78}
79
80impl SubmitBlockChannel {
81 /// Create a new submit block channel
82 pub fn new() -> Self {
83 let (sender, receiver) = watch::channel((GENESIS_PREVIOUS_BLOCK_HASH, block::Height::MIN));
84 Self { sender, receiver }
85 }
86
87 /// Get the channel sender
88 pub fn sender(&self) -> watch::Sender<(block::Hash, block::Height)> {
89 self.sender.clone()
90 }
91
92 /// Get the channel receiver
93 pub fn receiver(&self) -> watch::Receiver<(block::Hash, block::Height)> {
94 self.receiver.clone()
95 }
96}
97
98impl Default for SubmitBlockChannel {
99 fn default() -> Self {
100 Self::new()
101 }
102}