Skip to main content

zebra_rpc/methods/types/
submit_block.rs

1//! Parameter and response types for the `submitblock` RPC.
2
3use tokio::sync::mpsc;
4
5use zebra_chain::block;
6
7// Allow doc links to these imports.
8#[allow(unused_imports)]
9use crate::methods::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, schemars::JsonSchema)]
15pub struct SubmitBlockParameters {
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 SubmitBlockErrorResponse {
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 SubmitBlockResponse {
54    /// Block was not successfully submitted, return error
55    ErrorResponse(SubmitBlockErrorResponse),
56    /// Block successfully submitted, returns null
57    Accepted,
58}
59
60impl Default for SubmitBlockResponse {
61    fn default() -> Self {
62        Self::ErrorResponse(SubmitBlockErrorResponse::Rejected)
63    }
64}
65
66impl From<SubmitBlockErrorResponse> for SubmitBlockResponse {
67    fn from(error_response: SubmitBlockErrorResponse) -> 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: mpsc::Sender<(block::Hash, block::Height)>,
76    /// The channel receiver
77    receiver: mpsc::Receiver<(block::Hash, block::Height)>,
78}
79
80impl SubmitBlockChannel {
81    /// Creates a new submit block channel
82    pub fn new() -> Self {
83        /// How many unread messages the submit block channel should buffer before rejecting sends.
84        ///
85        /// This should be large enough to usually avoid rejecting sends. This channel is used by
86        /// the block hash gossip task, which waits for a ready peer in the peer set while
87        /// processing messages from this channel and could be much slower to gossip block hashes
88        /// than it is to commit blocks and produce new block templates.
89        const SUBMIT_BLOCK_CHANNEL_CAPACITY: usize = 10_000;
90
91        let (sender, receiver) = mpsc::channel(SUBMIT_BLOCK_CHANNEL_CAPACITY);
92        Self { sender, receiver }
93    }
94
95    /// Get the channel sender
96    pub fn sender(&self) -> mpsc::Sender<(block::Hash, block::Height)> {
97        self.sender.clone()
98    }
99
100    /// Get the channel receiver
101    pub fn receiver(self) -> mpsc::Receiver<(block::Hash, block::Height)> {
102        self.receiver
103    }
104}
105
106impl Default for SubmitBlockChannel {
107    fn default() -> Self {
108        Self::new()
109    }
110}