Skip to content

Commit 4f220b1

Browse files
committed
Implement HaskellDisplay for DecoderError
1 parent 0975666 commit 4f220b1

File tree

2 files changed

+66
-8
lines changed

2 files changed

+66
-8
lines changed

pallas-hardano/src/display/haskell_display.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::{
22
collections::{BTreeSet, HashMap},
3+
fmt::format,
34
net::Ipv6Addr,
45
ops::Deref,
56
};
@@ -43,7 +44,10 @@ use pallas_network::miniprotocols::localtxsubmission::{
4344
TagMismatchDescription, TxOutSource, Utxo, UtxoFailure, UtxosFailure, VKey, ValidityInterval,
4445
};
4546

46-
use super::haskells_show_string::haskell_show_string;
47+
use super::{
48+
haskell_error::{DecoderError, DeserialiseFailure},
49+
haskells_show_string::haskell_show_string,
50+
};
4751

4852
/// Trait used to generated Haskell-like string representation of a type.
4953
pub trait HaskellDisplay {
@@ -521,6 +525,28 @@ impl HaskellDisplay for BabbageContextError {
521525
}
522526
}
523527

528+
impl HaskellDisplay for DecoderError {
529+
fn to_haskell_str(&self) -> String {
530+
match self {
531+
DecoderError::DeserialiseFailure(str, failure) => format!(
532+
"DecoderErrorDeserialiseFailure {} {}",
533+
str.to_haskell_str(),
534+
failure.to_haskell_str_p()
535+
),
536+
_ => format!("DecoderError ({:?})", self),
537+
}
538+
}
539+
}
540+
impl HaskellDisplay for DeserialiseFailure {
541+
fn to_haskell_str(&self) -> String {
542+
format!(
543+
"DeserialiseFailure {} ({})",
544+
self.0.to_haskell_str(),
545+
self.1.to_haskell_str()
546+
)
547+
}
548+
}
549+
524550
impl HaskellDisplay for TxOutSource {
525551
fn to_haskell_str(&self) -> String {
526552
use TxOutSource::*;

pallas-hardano/src/display/haskell_error.rs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,22 @@ pub fn wrap_error_response(error: TxValidationError) -> TxSubmitFail {
1212
))
1313
}
1414

15-
/// Generates Haskell identical string for the error response
15+
/// Generates Haskell 'identical' string for the error response
1616
pub fn as_node_submit_error(error: TxValidationError) -> String {
1717
serde_json::to_string(&wrap_error_response(error)).unwrap()
1818
}
1919

20+
/// Generates Haskell 'similar' string for the error response in case of decode failure
21+
/// Only difference will be the provided decode failure message, Rust vs Haskell
22+
pub fn as_cbor_decode_failure(message: String, position: u64) -> String {
23+
let inner_errors = vec![DecoderError::DeserialiseFailure(
24+
"Shelley Tx".to_string(),
25+
DeserialiseFailure(position, message),
26+
)];
27+
let error = TxSubmitFail::TxSubmitFail(TxCmdError::TxReadError(inner_errors));
28+
serde_json::to_string(&error).unwrap()
29+
}
30+
2031
pub fn serialize_error(error: TxValidationError) -> serde_json::Value {
2132
serde_json::to_value(wrap_error_response(error)).unwrap()
2233
}
@@ -37,6 +48,7 @@ pub enum TxSubmitFail {
3748
#[serde(tag = "tag", content = "contents")]
3849
pub enum TxCmdError {
3950
SocketEnvError(String),
51+
#[serde(serialize_with = "use_haskell_display", rename = "TxCmdTxReadError")]
4052
TxReadError(Vec<DecoderError>),
4153
TxCmdTxSubmitValidationError(TxValidationErrorInCardanoMode),
4254
}
@@ -57,9 +69,21 @@ pub struct EraMismatch {
5769
other: String, // Era of the block, header, transaction, or query.
5870
}
5971

60-
/// TODO: Implement DecoderError errors from the Haskell codebase.
61-
/// Lots of errors, skipping for now. https://github.com/IntersectMBO/cardano-base/blob/391a2c5cfd30d2234097e000dbd8d9db21ef94d7/cardano-binary/src/Cardano/Binary/FromCBOR.hs#L90
62-
type DecoderError = String;
72+
/// https://github.com/IntersectMBO/cardano-base/blob/391a2c5cfd30d2234097e000dbd8d9db21ef94d7/cardano-binary/src/Cardano/Binary/FromCBOR.hs#L90
73+
#[derive(Debug, Serialize)]
74+
pub enum DecoderError {
75+
CanonicityViolation(String),
76+
Custom(String, String),
77+
DeserialiseFailure(String, DeserialiseFailure),
78+
EmptyList(String),
79+
Leftover(String, Vec<u8>),
80+
SizeMismatch(String, u64, u64),
81+
UnknownTag(String, u8),
82+
Void,
83+
}
84+
/// https://hackage.haskell.org/package/serialise-0.2.6.1/docs/Codec-Serialise.html#t:DeserialiseFailure
85+
#[derive(Debug, Serialize)]
86+
pub struct DeserialiseFailure(pub u64, pub String);
6387

6488
//
6589
// Haskell JSON serializations
@@ -83,7 +107,6 @@ enum TxValidationErrorJson {
83107
}
84108

85109
/// This is copy of ApplyTxError from pallas-network/src/miniprotocols/localtxsubmission/primitives.rs for Haskell json serialization
86-
87110
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
88111
#[serde(remote = "ApplyTxError")]
89112
struct ApplyTxErrorJson(
@@ -108,9 +131,10 @@ enum ShelleyBasedEraJson {
108131
Conway,
109132
}
110133

111-
fn use_haskell_display<S>(fails: &[ConwayLedgerFailure], serializer: S) -> Result<S::Ok, S::Error>
134+
fn use_haskell_display<S, T>(fails: &[T], serializer: S) -> Result<S::Ok, S::Error>
112135
where
113136
S: Serializer,
137+
T: HaskellDisplay,
114138
{
115139
let fails_str = fails.iter().map(|fail| fail.to_haskell_str());
116140
serializer.collect_seq(fails_str)
@@ -122,7 +146,15 @@ where
122146
fn test_submit_api_serialization() {
123147
let error = decode_error("81820681820764f0aab883");
124148

125-
assert_eq!("{\"tag\":\"TxSubmitFail\",\"contents\":{\"tag\":\"TxCmdTxSubmitValidationError\",\"contents\":{\"tag\":\"TxValidationErrorInCardanoMode\",\"contents\":{\"kind\":\"ShelleyTxValidationError\",\"error\":[\"ConwayMempoolFailure \\\"\\\\175619\\\"\"],\"era\":\"ShelleyBasedEraConway\"}}}}", as_node_submit_error(error));
149+
assert_eq!("{\"tag\":\"TxSubmitFail\",\"contents\":{\"tag\":\"TxCmdTxSubmitValidationError\",\"contents\":{\"tag\":\"TxValidationErrorInCardanoMode\",\"contents\":{\"kind\":\"ShelleyTxValidationError\",\"error\":[\"ConwayMempoolFailure \\\"\\\\175619\\\"\"],\"era\":\"ShelleyBasedEraConway\"}}}}",
150+
as_node_submit_error(error));
151+
}
152+
153+
#[test]
154+
#[allow(non_snake_case)]
155+
fn test_submit_api_decode_failure() {
156+
assert_eq!( "{\"tag\":\"TxSubmitFail\",\"contents\":{\"tag\":\"TxCmdTxReadError\",\"contents\":[\"DecoderErrorDeserialiseFailure \\\"Shelley Tx\\\" (DeserialiseFailure 0 (\\\"expected list len or indef\\\"))\"]}}",
157+
as_cbor_decode_failure("expected list len or indef".to_string(), 0));
126158
}
127159

128160
#[cfg(test)]

0 commit comments

Comments
 (0)