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}