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}