From a3fd6d8a05b8218b4961dbe776ea610ec1e261dc Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Mon, 4 Jul 2022 18:01:05 -0300 Subject: [PATCH] feat(traverse): Integrate address library --- pallas-addresses/src/lib.rs | 37 ++++++++++++++++++++-------- pallas-codec/src/utils.rs | 2 +- pallas-primitives/src/byron/model.rs | 10 ++++---- pallas-traverse/Cargo.toml | 1 + pallas-traverse/src/output.rs | 14 ++++++----- 5 files changed, 42 insertions(+), 22 deletions(-) diff --git a/pallas-addresses/src/lib.rs b/pallas-addresses/src/lib.rs index 1770c10c..0bc1d855 100644 --- a/pallas-addresses/src/lib.rs +++ b/pallas-addresses/src/lib.rs @@ -28,6 +28,9 @@ pub enum Error { #[error("invalid operation for Byron address")] InvalidForByron, + #[error("invalid CBOR for Byron address")] + InvalidByronCbor, + #[error("unkown hrp for network {0:08b}")] UnknownNetworkHrp(u8), @@ -231,9 +234,15 @@ pub enum StakePayload { #[derive(Debug, Clone, PartialEq, PartialOrd)] pub struct StakeAddress(Network, StakePayload); -/// Newtype representing a Byron address +/// New type wrapping a Byron address primitive #[derive(Debug, Clone, PartialEq, PartialOrd)] -pub struct ByronAddress(Vec); +pub struct ByronAddress(pallas_primitives::byron::Address); + +impl ByronAddress { + pub fn new(primitive: pallas_primitives::byron::Address) -> Self { + Self(primitive) + } +} /// A decoded Cardano address of any type #[derive(Debug, Clone, PartialEq, PartialOrd)] @@ -325,7 +334,8 @@ 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(); - Ok(Address::Byron(ByronAddress(vec))) + let prim = pallas_codec::minicbor::decode(&vec).map_err(|_| Error::InvalidByronCbor)?; + Ok(Address::Byron(ByronAddress(prim))) } // types 14-15 are Stake addresses @@ -378,7 +388,7 @@ impl ByronAddress { } fn to_vec(&self) -> Vec { - self.0.clone() + pallas_codec::minicbor::to_vec(&self.0).unwrap() } pub fn to_hex(&self) -> String { @@ -387,12 +397,6 @@ impl ByronAddress { } } -impl AsRef<[u8]> for ByronAddress { - fn as_ref(&self) -> &[u8] { - &self.0 - } -} - impl ShelleyAddress { pub fn new( network: Network, @@ -554,6 +558,11 @@ impl Address { bech32_to_address(bech32) } + // Tries to decode the raw bytes of an address + pub fn from_bytes(bytes: &[u8]) -> Result { + bytes_to_address(bytes) + } + /// Gets the network assoaciated with this address pub fn network(&self) -> Option { match self { @@ -615,6 +624,14 @@ impl Address { } } +impl TryFrom<&[u8]> for Address { + type Error = Error; + + fn try_from(value: &[u8]) -> Result { + bytes_to_address(value) + } +} + impl From for Address { fn from(addr: ByronAddress) -> Self { Address::Byron(addr) diff --git a/pallas-codec/src/utils.rs b/pallas-codec/src/utils.rs index a98ebe22..89e0ef9a 100644 --- a/pallas-codec/src/utils.rs +++ b/pallas-codec/src/utils.rs @@ -186,7 +186,7 @@ where /// transform key-value structures into an orderer vec of `properties`, where /// each entry represents a a cbor-encodable variant of an attribute of the /// struct. -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, PartialOrd)] pub struct OrderPreservingProperties

(Vec

); impl

Deref for OrderPreservingProperties

{ diff --git a/pallas-primitives/src/byron/model.rs b/pallas-primitives/src/byron/model.rs index 15c7b0bd..2c105b5f 100644 --- a/pallas-primitives/src/byron/model.rs +++ b/pallas-primitives/src/byron/model.rs @@ -51,7 +51,7 @@ pub type Attributes = EmptyMap; // Addresses -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, PartialOrd)] pub enum AddrDistr { Variant0(StakeholderId), Variant1, @@ -96,7 +96,7 @@ impl minicbor::Encode<()> for AddrDistr { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, PartialOrd)] pub enum AddrType { PubKey, Script, @@ -137,7 +137,7 @@ impl minicbor::Encode for AddrType { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, PartialOrd)] pub enum AddrAttrProperty { AddrDistr(AddrDistr), Bytes(ByteVec), @@ -187,7 +187,7 @@ impl minicbor::Encode for AddrAttrProperty { pub type AddrAttr = OrderPreservingProperties; -#[derive(Debug, Encode, Decode, Clone)] +#[derive(Debug, Encode, Decode, Clone, PartialEq, PartialOrd)] pub struct AddressPayload { #[n(0)] pub root: AddressId, @@ -200,7 +200,7 @@ pub struct AddressPayload { } // address = [ #6.24(bytes .cbor ([addressid, addrattr, addrtype])), u64 ] -#[derive(Debug, Encode, Decode, Clone)] +#[derive(Debug, Encode, Decode, Clone, PartialEq, PartialOrd)] pub struct Address { #[n(0)] pub payload: CborWrap, diff --git a/pallas-traverse/Cargo.toml b/pallas-traverse/Cargo.toml index f28f0968..c5e26acf 100644 --- a/pallas-traverse/Cargo.toml +++ b/pallas-traverse/Cargo.toml @@ -14,6 +14,7 @@ authors = [ [dependencies] pallas-primitives = { version = "0.11.0", path = "../pallas-primitives" } +pallas-addresses = { version = "0.11.0", path = "../pallas-addresses" } pallas-crypto = { version = "0.11.0", path = "../pallas-crypto" } pallas-codec = { version = "0.11.0", path = "../pallas-codec" } hex = "0.4.3" diff --git a/pallas-traverse/src/output.rs b/pallas-traverse/src/output.rs index 7c42197f..dd33d64b 100644 --- a/pallas-traverse/src/output.rs +++ b/pallas-traverse/src/output.rs @@ -1,5 +1,6 @@ use std::{borrow::Cow, ops::Deref}; +use pallas_addresses::{Address, ByronAddress, Error as AddressError}; use pallas_codec::minicbor; use pallas_primitives::{alonzo, babbage, byron}; @@ -18,13 +19,14 @@ impl<'b> MultiEraOutput<'b> { Self::Babbage(Box::new(Cow::Borrowed(output))) } - pub fn address(&self, hrp: &str) -> String { + pub fn to_address(&self) -> Result { match self { - MultiEraOutput::AlonzoCompatible(x) => { - x.to_bech32_address(hrp).expect("invalid address value") - } - MultiEraOutput::Babbage(x) => x.to_bech32_address(hrp).expect("invalid address value"), - MultiEraOutput::Byron(x) => x.address.to_addr_string().expect("invalid address value"), + MultiEraOutput::AlonzoCompatible(x) => Address::from_bytes(&x.address), + MultiEraOutput::Babbage(x) => match x.deref().deref() { + babbage::TransactionOutput::Legacy(x) => Address::from_bytes(&x.address), + babbage::TransactionOutput::PostAlonzo(x) => Address::from_bytes(&x.address), + }, + MultiEraOutput::Byron(x) => Ok(ByronAddress::new(x.address.clone()).into()), } }