Skip to content

Commit

Permalink
Merge of #5993
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jan 19, 2023
2 parents de2ed81 + fde6d52 commit 17a6d7e
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use zebra_chain::{
block::{
self,
merkle::{self, AuthDataRoot},
ChainHistoryBlockTxAuthCommitmentHash, Height,
Block, ChainHistoryBlockTxAuthCommitmentHash, Height,
},
chain_sync_status::ChainSyncStatus,
chain_tip::ChainTip,
Expand Down Expand Up @@ -108,8 +108,18 @@ where
+ Sync
+ 'static,
{
let Ok(block) = block_proposal_bytes.zcash_deserialize_into::<block::Block>() else {
return Ok(ProposalRejectReason::Rejected.into())
let block: Block = match block_proposal_bytes.zcash_deserialize_into() {
Ok(block) => block,
Err(parse_error) => {
tracing::info!(
?parse_error,
"error response from block parser in CheckProposal request"
);

return Ok(
ProposalResponse::rejected("invalid proposal format", parse_error.into()).into(),
);
}
};

let chain_verifier_response = chain_verifier
Expand All @@ -127,11 +137,11 @@ where
.map(|_hash| ProposalResponse::Valid)
.unwrap_or_else(|verify_chain_error| {
tracing::info!(
verify_chain_error,
"Got error response from chain_verifier CheckProposal request"
?verify_chain_error,
"error response from chain_verifier in CheckProposal request"
);

ProposalRejectReason::Rejected.into()
ProposalResponse::rejected("invalid proposal", verify_chain_error)
})
.into())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub mod parameters;
pub mod proposal;

pub use parameters::{GetBlockTemplateCapability, GetBlockTemplateRequestMode, JsonParameters};
pub use proposal::{proposal_block_from_template, ProposalRejectReason, ProposalResponse};
pub use proposal::{proposal_block_from_template, ProposalResponse};

/// A serialized `getblocktemplate` RPC response in template mode.
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
//!
//! `ProposalResponse` is the output of the `getblocktemplate` RPC method in 'proposal' mode.
use std::{num::ParseIntError, str::FromStr, sync::Arc};
use std::{error::Error, num::ParseIntError, str::FromStr, sync::Arc};

use zebra_chain::{
block::{self, Block, Height},
serialization::{DateTime32, SerializationError, ZcashDeserializeInto},
work::equihash::Solution,
};
use zebra_node_services::BoxError;

use crate::methods::{
get_block_template_rpcs::types::{
Expand All @@ -18,47 +19,46 @@ use crate::methods::{
GetBlockHash,
};

/// Error response to a `getblocktemplate` RPC request in proposal mode.
///
/// See <https://en.bitcoin.it/wiki/BIP_0022#Appendix:_Example_Rejection_Reasons>
#[derive(Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum ProposalRejectReason {
/// Block proposal rejected as invalid.
Rejected,
}

/// Response to a `getblocktemplate` RPC request in proposal mode.
///
/// See <https://en.bitcoin.it/wiki/BIP_0023#Block_Proposal>
/// <https://en.bitcoin.it/wiki/BIP_0022#Appendix:_Example_Rejection_Reasons>
///
/// Note:
/// The error response specification at <https://en.bitcoin.it/wiki/BIP_0023#Block_Proposal>
/// seems to have a copy-paste issue, or it is under-specified. We follow the `zcashd`
/// implementation instead, which returns a single raw string.
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(untagged, rename_all = "kebab-case")]
pub enum ProposalResponse {
/// Block proposal was rejected as invalid, returns `reject-reason` and server `capabilities`.
ErrorResponse {
/// Reason the proposal was invalid as-is.
reject_reason: ProposalRejectReason,

/// The getblocktemplate RPC capabilities supported by Zebra.
capabilities: Vec<String>,
},
/// Block proposal was rejected as invalid.
/// Contains the reason that the proposal was invalid.
///
/// TODO: turn this into a typed error enum?
Rejected(String),

/// Block proposal was successfully validated, returns null.
Valid,
}

impl From<ProposalRejectReason> for ProposalResponse {
fn from(reject_reason: ProposalRejectReason) -> Self {
Self::ErrorResponse {
reject_reason,
capabilities: GetBlockTemplate::capabilities(),
}
impl ProposalResponse {
/// Return a rejected response containing an error kind and detailed error info.
pub fn rejected<S: ToString>(kind: S, error: BoxError) -> Self {
let kind = kind.to_string();

// Pretty-print the detailed error for now
ProposalResponse::Rejected(format!("{kind}: {error:#?}"))
}

/// Return a rejected response containing just the detailed error information.
pub fn error(error: BoxError) -> Self {
// Pretty-print the detailed error for now
ProposalResponse::Rejected(format!("{error:#?}"))
}
}

impl From<ProposalRejectReason> for Response {
fn from(error_response: ProposalRejectReason) -> Self {
Self::ProposalMode(ProposalResponse::from(error_response))
impl<E: Error + Send + Sync + 'static> From<E> for ProposalResponse {
fn from(error: E) -> Self {
Self::error(error.into())
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,4 @@
source: zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs
expression: block_template
---
{
"reject_reason": "rejected",
"capabilities": [
"proposal"
]
}
"invalid proposal format: Io(\n Error {\n kind: UnexpectedEof,\n message: \"failed to fill whole buffer\",\n },\n)"
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,4 @@
source: zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs
expression: block_template
---
{
"reject_reason": "rejected",
"capabilities": [
"proposal"
]
}
"invalid proposal format: Io(\n Error {\n kind: UnexpectedEof,\n message: \"failed to fill whole buffer\",\n },\n)"
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ async fn try_validate_block_template(client: &RPCRequestClient) -> Result<()> {
"got getblocktemplate proposal response"
);

if let ProposalResponse::ErrorResponse { reject_reason, .. } = json_result {
if let ProposalResponse::Rejected(reject_reason) = json_result {
Err(eyre!(
"unsuccessful block proposal validation, reason: {reject_reason:?}"
))?;
Expand Down

0 comments on commit 17a6d7e

Please sign in to comment.