diff --git a/pallas-primitives/src/byron/model.rs b/pallas-primitives/src/byron/model.rs index 5e90622..4121b74 100644 --- a/pallas-primitives/src/byron/model.rs +++ b/pallas-primitives/src/byron/model.rs @@ -8,6 +8,7 @@ use pallas_crypto::hash::Hash; use crate::utils::{ CborWrap, EmptyMap, KeyValuePairs, MaybeIndefArray, OrderPreservingProperties, TagWrap, + ZeroOrOneArray, }; // Basic Cardano Types @@ -612,46 +613,46 @@ impl minicbor::Encode for TxFeePol { #[derive(Debug, Encode, Decode)] pub struct BVerMod { #[n(0)] - pub script_version: (Option,), + pub script_version: ZeroOrOneArray, #[n(1)] - pub slot_duration: (Option,), + pub slot_duration: ZeroOrOneArray, #[n(2)] - pub max_block_size: (Option,), + pub max_block_size: ZeroOrOneArray, #[n(3)] - pub max_header_size: (Option,), + pub max_header_size: ZeroOrOneArray, #[n(4)] - pub max_tx_size: (Option,), + pub max_tx_size: ZeroOrOneArray, #[n(5)] - pub max_proposal_size: (Option,), + pub max_proposal_size: ZeroOrOneArray, #[n(6)] - pub mpc_thd: (Option,), + pub mpc_thd: ZeroOrOneArray, #[n(7)] - pub heavy_del_thd: (Option,), + pub heavy_del_thd: ZeroOrOneArray, #[n(8)] - pub update_vote_thd: (Option,), + pub update_vote_thd: ZeroOrOneArray, #[n(9)] - pub update_proposal_thd: (Option,), + pub update_proposal_thd: ZeroOrOneArray, #[n(10)] - pub update_implicit: (Option,), + pub update_implicit: ZeroOrOneArray, #[n(11)] - pub soft_fork_rule: (Option<(u64, u64, u64)>,), + pub soft_fork_rule: ZeroOrOneArray<(u64, u64, u64)>, #[n(12)] - pub tx_fee_policy: (Option,), + pub tx_fee_policy: ZeroOrOneArray, #[n(13)] - pub unlock_stake_epoch: (Option,), + pub unlock_stake_epoch: ZeroOrOneArray, } pub type UpData = (ByronHash, ByronHash, ByronHash, ByronHash); @@ -668,7 +669,9 @@ pub struct UpProp { pub software_version: Option<(String, u32)>, #[n(3)] - pub data: Option>, + // HACK: CDDL show a tag wrap 258, but chain data doesn't present the tag + //pub data: TagWrap<(String, UpData), 258>, + pub data: KeyValuePairs, #[n(4)] pub attributes: Option, @@ -698,7 +701,7 @@ pub struct UpVote { #[derive(Debug, Encode, Decode)] pub struct Up { #[n(0)] - pub proposal: Option, + pub proposal: ZeroOrOneArray, #[n(1)] pub votes: MaybeIndefArray, @@ -959,6 +962,7 @@ mod tests { include_str!("test_data/test2.block"), include_str!("test_data/test3.block"), include_str!("test_data/test4.block"), + include_str!("test_data/test5.block"), ]; for (idx, block_str) in test_blocks.iter().enumerate() { diff --git a/pallas-primitives/src/byron/test_data/test5.block b/pallas-primitives/src/byron/test_data/test5.block new file mode 100644 index 0000000..5016be6 --- /dev/null +++ b/pallas-primitives/src/byron/test_data/test5.block @@ -0,0 +1 @@ +820183851a2d964a0958201d1c6f61db4509a5978d54bd4dd1bad192c4b56086c9b6e419c9b1efa21419138483015820b44c5c051cf7546c6a9a7fc98cb51edc24e46869ddb49daabd01e6afff3cfec5582050689a01eff76204cf488438b0dd871947c2cbc34e858516ecb5e22193609e6283015820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b58202475b9c6d41c4f82c2d9c602fa037dc7f4140606067ddf222917acc020ddc0be8482031921ee58401bc97a2fe02c297880ce8ecfd997fe4c1ec09ee10feeee9f686760166b05281d6283468ffd93becb0c956ccddd642df9b1244c915911185fa49355f6f22bfab9811a00011ef2820282840058401bc97a2fe02c297880ce8ecfd997fe4c1ec09ee10feeee9f686760166b05281d6283468ffd93becb0c956ccddd642df9b1244c915911185fa49355f6f22bfab9584061261a95b7613ee6bf2067dad77b70349729b0c50d57bc1cf30de0db4a1e73a885d0054af7c23fc6c37919dba41c602a57e2d0f9329a7954b867338d6fb2c9455840e03e62f083df5576360e60a32e22bbb07b3c8df4fcab8079f1d6f61af3954d242ba8a06516c395939f24096f3df14e103a7d9c2b80a68a9363cf1f27c7a4e3075840b5c04dbfca8d6e5dcf873569105a6f93040a927c33984221dbb54a82f2523b8cfe579a67f5e1f8200d0d888315c5c65969ea32c967aa20a33d447ff1c67da3008483000000826a63617264616e6f2d736c01a058204ba92aa320c60acc9ad7b9a64f2eda55c4d2ec28e604faf186708b4f0c4e8edf849f82839f8200d8185824825820e6e6c92426711a3ad8c254bf116c68a2c71de5fb5c61a0add8bc5c57497e05bc00ff9f8282d818584283581c656cb181ad933fa9e497d6e67eabdfb2bbd63f230676ddebbe41acdda101581e581cac02fdd1d62f3ad946d729fa2839419f1192554f4b48913c6a26889b001ac279d5cb1b000000199be4bedf8282d818584283581c293da0dcde147aa40929309c7ee99afcf3ddbc9880008708a3189f63a101581e581cca3e553c9c63c5090ff02243e47896711682220940aa695e754b0f47001a8d1241f01a00989680ffa0818200d818588582584082503efed69e7f816a6ea1cc6e9b7d2c909f9427f7ad68764d946041eb735ac487b2168c3c31dbcb1f8c713484d95b41b80a5458c5bce8d2b6d12000d8287cc0584084b8f026ec86a56b02cd88a0ba40c770e5807b71e3c8ccc9a98465816aa2fd24e2f6efd3a1bc5837b2a82f572c779848313f87be10beccba9698d335b919a802ff8301a0d90102809fff828187830000008e810081194e20811a001e8480811a001e848081191000811902bc811b000012309ce54000811b00000045d964b800811b000000e8d4a51000811b00005af3107a400081192710808080826c63736c2d64616564616c757301a2676d61636f73363484582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113145820966d92b90edc99f3e946fe16490d0313c56c5c9b570c453c6d1e5cc08cdb6184582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113146577696e363484582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c1113145820828339268d84c542d3543a878ccba21887fbf01fb154d333b945217dedba9c3a582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314582003170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314a05840e8c03a03c0b2ddbea4195caf39f41e669f7d251ecf221fbb2f275c0a5d7e05d190dcc246f56c8e33ac0037066e2f664ddaa985ea5284082643308dde4f5bfedf58405e59935bcabe470872bf305dec2e15a3442d3cf5bc2e3c02d8e1d680e31530ead6ad5ba788f2c185ff0162cb46cddc7360a32c3ba88e5fae63a8c36b8b46450f9f845840e8c03a03c0b2ddbea4195caf39f41e669f7d251ecf221fbb2f275c0a5d7e05d190dcc246f56c8e33ac0037066e2f664ddaa985ea5284082643308dde4f5bfedf58200d7d3b53a0ef9ce40fa9222cfc2b725f52c0136c01ad366115b48f94d8ef2c6df55840d723f2794e5206c38b9ed6433190cd75e89ab1e3d9324c89fe0925b924c81b2fadbf83f3e232f583efcb1eae345e3149073e2d85c0eb85324874f13118ce340dff81a0 \ No newline at end of file diff --git a/pallas-primitives/src/utils.rs b/pallas-primitives/src/utils.rs index b9e08e2..b5bb668 100644 --- a/pallas-primitives/src/utils.rs +++ b/pallas-primitives/src/utils.rs @@ -318,3 +318,61 @@ impl minicbor::encode::Encode for EmptyMap { Ok(()) } } + +/// An array with zero or one elements +/// +/// A common pattern seen in the CDDL is to represent optional values as an +/// array containing zero or more items. This structure reflects that pattern +/// while providing semantic meaning. +#[derive(Debug)] +pub struct ZeroOrOneArray(Option); + +impl Deref for ZeroOrOneArray { + type Target = Option; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'b, T> minicbor::decode::Decode<'b> for ZeroOrOneArray +where + T: Decode<'b>, +{ + fn decode(d: &mut minicbor::Decoder<'b>) -> Result { + let len = d.array()?; + + match len { + Some(0) => Ok(ZeroOrOneArray(None)), + Some(1) => Ok(ZeroOrOneArray(Some(d.decode()?))), + Some(_) => Err(minicbor::decode::Error::Message( + "found invalid len for zero-or-one pattern", + )), + None => Err(minicbor::decode::Error::Message( + "found invalid indefinite len array for zero-or-one pattern", + )), + } + } +} + +impl minicbor::encode::Encode for ZeroOrOneArray +where + T: minicbor::Encode, +{ + fn encode( + &self, + e: &mut minicbor::Encoder, + ) -> Result<(), minicbor::encode::Error> { + match &self.0 { + Some(x) => { + e.array(1)?; + e.encode(x)?; + } + None => { + e.array(0)?; + } + } + + Ok(()) + } +}