diff --git a/pallas-addresses/Cargo.toml b/pallas-addresses/Cargo.toml index 8363557..588e3fb 100644 --- a/pallas-addresses/Cargo.toml +++ b/pallas-addresses/Cargo.toml @@ -17,3 +17,4 @@ pallas-codec = { version = "0.19.0-alpha.0", path = "../pallas-codec" } base58 = "0.2.0" bech32 = "0.9.1" thiserror = "1.0.31" +crc = "3.0.1" diff --git a/pallas-addresses/src/byron.rs b/pallas-addresses/src/byron.rs index 6ce329b..a488848 100644 --- a/pallas-addresses/src/byron.rs +++ b/pallas-addresses/src/byron.rs @@ -14,8 +14,8 @@ pub type StakeholderId = Blake2b224; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum AddrDistr { - Variant0(StakeholderId), - Variant1, + SingleKeyDistribution(StakeholderId), + BootstrapEraDistribution, } impl<'b, C> minicbor::Decode<'b, C> for AddrDistr { @@ -24,8 +24,8 @@ impl<'b, C> minicbor::Decode<'b, C> for AddrDistr { let variant = d.u32()?; match variant { - 0 => Ok(AddrDistr::Variant0(d.decode_with(ctx)?)), - 1 => Ok(AddrDistr::Variant1), + 0 => Ok(AddrDistr::SingleKeyDistribution(d.decode_with(ctx)?)), + 1 => Ok(AddrDistr::BootstrapEraDistribution), _ => Err(minicbor::decode::Error::message( "invalid variant for addrdstr", )), @@ -40,14 +40,14 @@ impl minicbor::Encode<()> for AddrDistr { _ctx: &mut (), ) -> Result<(), minicbor::encode::Error> { match self { - AddrDistr::Variant0(x) => { + AddrDistr::SingleKeyDistribution(x) => { e.array(2)?; e.u32(0)?; e.encode(x)?; Ok(()) } - AddrDistr::Variant1 => { + AddrDistr::BootstrapEraDistribution => { e.array(1)?; e.u32(1)?; @@ -101,8 +101,8 @@ impl minicbor::Encode for AddrType { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub enum AddrAttrProperty { AddrDistr(AddrDistr), - Bytes(ByteVec), - Unparsed(u8, ByteVec), + DerivationPath(ByteVec), + NetworkTag(ByteVec), } impl<'b, C> minicbor::Decode<'b, C> for AddrAttrProperty { @@ -111,8 +111,11 @@ impl<'b, C> minicbor::Decode<'b, C> for AddrAttrProperty { match key { 0 => Ok(AddrAttrProperty::AddrDistr(d.decode_with(ctx)?)), - 1 => Ok(AddrAttrProperty::Bytes(d.decode_with(ctx)?)), - x => Ok(AddrAttrProperty::Unparsed(x, d.decode_with(ctx)?)), + 1 => Ok(AddrAttrProperty::DerivationPath(d.decode_with(ctx)?)), + 2 => Ok(AddrAttrProperty::NetworkTag(d.decode_with(ctx)?)), + _ => Err(minicbor::decode::Error::message( + "unknown tag for address attribute", + )), } } } @@ -125,19 +128,19 @@ impl minicbor::Encode for AddrAttrProperty { ) -> Result<(), minicbor::encode::Error> { match self { AddrAttrProperty::AddrDistr(x) => { - e.u32(0)?; + e.u8(0)?; e.encode(x)?; Ok(()) } - AddrAttrProperty::Bytes(x) => { - e.u32(1)?; + AddrAttrProperty::DerivationPath(x) => { + e.u8(1)?; e.encode(x)?; Ok(()) } - AddrAttrProperty::Unparsed(a, b) => { - e.encode(a)?; + AddrAttrProperty::NetworkTag(b) => { + e.u8(2)?; e.encode(b)?; Ok(()) @@ -146,7 +149,7 @@ impl minicbor::Encode for AddrAttrProperty { } } -pub type AddrAttr = OrderPreservingProperties; +pub type AddrAttrs = OrderPreservingProperties; #[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd)] pub struct AddressPayload { @@ -154,7 +157,7 @@ pub struct AddressPayload { pub root: AddressId, #[n(1)] - pub attributes: AddrAttr, + pub attributes: AddrAttrs, #[n(2)] pub addrtype: AddrType, @@ -167,19 +170,49 @@ pub struct ByronAddress { payload: TagWrap, #[n(1)] - crc: u64, + crc: u32, } +const CRC: crc::Crc = crc::Crc::::new(&crc::CRC_32_ISO_HDLC); + impl ByronAddress { - pub fn new(payload: &[u8], crc: u64) -> Self { + pub fn new(payload: &[u8], crc: u32) -> Self { Self { payload: TagWrap(ByteVec::from(Vec::from(payload))), crc, } } + pub fn new_bootstrap( + root: AddressId, + addrtype: AddrType, + network_tag: Option>, + ) -> Self { + let payload = AddressPayload { + root, + attributes: match network_tag { + Some(x) => vec![ + AddrAttrProperty::AddrDistr(AddrDistr::BootstrapEraDistribution), + AddrAttrProperty::NetworkTag(x.into()), + ] + .into(), + None => vec![AddrAttrProperty::AddrDistr( + AddrDistr::BootstrapEraDistribution, + )] + .into(), + }, + addrtype, + }; + + let payload = minicbor::to_vec(payload).unwrap(); + + let c = CRC.checksum(&payload); + + ByronAddress::new(&payload, c) + } + pub fn from_bytes(value: &[u8]) -> Result { - pallas_codec::minicbor::decode(value).map_err(|_| Error::InvalidByronCbor) + pallas_codec::minicbor::decode(value).map_err(Error::InvalidByronCbor) } // Tries to decode an address from its hex representation @@ -208,7 +241,7 @@ impl ByronAddress { } pub fn decode(&self) -> Result { - minicbor::decode(&self.payload.0).map_err(|_| Error::InvalidByronCbor) + minicbor::decode(&self.payload.0).map_err(Error::InvalidByronCbor) } } @@ -230,6 +263,10 @@ mod tests { #[test] fn payload_matches() { let addr = ByronAddress::from_base58(TEST_VECTOR).unwrap(); + + let crc2 = CRC.checksum(addr.payload.as_ref()); + assert_eq!(crc2, addr.crc); + let payload = addr.decode().unwrap(); assert_eq!(payload.root.to_string(), ROOT_HASH); } diff --git a/pallas-addresses/src/lib.rs b/pallas-addresses/src/lib.rs index ca3520b..baa802a 100644 --- a/pallas-addresses/src/lib.rs +++ b/pallas-addresses/src/lib.rs @@ -41,8 +41,8 @@ pub enum Error { #[error("invalid operation for address content")] InvalidForContent, - #[error("invalid CBOR for Byron address")] - InvalidByronCbor, + #[error("invalid CBOR for Byron address {0}")] + InvalidByronCbor(pallas_codec::minicbor::decode::Error), #[error("unkown hrp for network {0:08b}")] UnknownNetworkHrp(u8), @@ -377,7 +377,7 @@ parse_shelley_fn!(parse_type_7, script_hash); // type 8 (1000) are Byron addresses fn parse_type_8(header: u8, payload: &[u8]) -> Result { let vec = [&[header], payload].concat(); - let inner = pallas_codec::minicbor::decode(&vec).map_err(|_| Error::InvalidByronCbor)?; + let inner = pallas_codec::minicbor::decode(&vec).map_err(Error::InvalidByronCbor)?; Ok(Address::Byron(inner)) } diff --git a/pallas-codec/src/utils.rs b/pallas-codec/src/utils.rs index dca4f71..4b1c9dd 100644 --- a/pallas-codec/src/utils.rs +++ b/pallas-codec/src/utils.rs @@ -254,6 +254,12 @@ impl

Deref for OrderPreservingProperties

{ } } +impl

From> for OrderPreservingProperties

{ + fn from(value: Vec

) -> Self { + OrderPreservingProperties(value) + } +} + impl<'b, C, P> minicbor::decode::Decode<'b, C> for OrderPreservingProperties

where P: Decode<'b, C>, diff --git a/pallas-primitives/src/byron/model.rs b/pallas-primitives/src/byron/model.rs index 68db4ab..3c56b26 100644 --- a/pallas-primitives/src/byron/model.rs +++ b/pallas-primitives/src/byron/model.rs @@ -58,7 +58,7 @@ pub struct Address { pub payload: TagWrap, #[n(1)] - pub crc: u64, + pub crc: u32, } // Transactions