33#![ allow( dead_code) ]
44
55use crate :: cip19:: { VarIntDecoder , VarIntEncoder } ;
6+ use crate :: hash:: Hash ;
67use crate :: { Credential , KeyHash , NetworkId , ScriptHash , StakeCredential } ;
78use anyhow:: { anyhow, bail, Result } ;
89use crc:: { Crc , CRC_32_ISO_HDLC } ;
@@ -147,10 +148,12 @@ pub struct ShelleyAddressPointer {
147148 serde:: Deserialize ,
148149 minicbor:: Encode ,
149150 minicbor:: Decode ,
151+ Default ,
150152) ]
151153pub enum ShelleyAddressDelegationPart {
152154 /// No delegation (enterprise addresses)
153155 #[ n( 0 ) ]
156+ #[ default]
154157 None ,
155158
156159 /// Delegation to stake key
@@ -166,12 +169,6 @@ pub enum ShelleyAddressDelegationPart {
166169 Pointer ( #[ n( 0 ) ] ShelleyAddressPointer ) ,
167170}
168171
169- impl Default for ShelleyAddressDelegationPart {
170- fn default ( ) -> Self {
171- Self :: None
172- }
173- }
174-
175172/// A Shelley-era address
176173#[ derive(
177174 Debug ,
@@ -294,7 +291,7 @@ impl ShelleyAddress {
294291 Ok ( bech32:: encode :: < bech32:: Bech32 > ( hrp, & data) ?)
295292 }
296293
297- pub fn to_bytes_key ( & self ) -> Result < Vec < u8 > > {
294+ pub fn to_bytes_key ( & self ) -> Vec < u8 > {
298295 let network_bits = match self . network {
299296 NetworkId :: Mainnet => 1u8 ,
300297 NetworkId :: Testnet => 0u8 ,
@@ -307,8 +304,10 @@ impl ShelleyAddress {
307304
308305 let mut data = Vec :: new ( ) ;
309306
310- let build_header =
311- |variant : u8 | -> u8 { network_bits | ( payment_bits << 4 ) | ( variant << 5 ) } ;
307+ let build_header = |delegation_bits : u8 | -> u8 {
308+ let addr_type = ( ( delegation_bits & 0x03 ) << 1 ) | ( payment_bits & 0x01 ) ;
309+ ( addr_type << 4 ) | ( network_bits & 0x0F )
310+ } ;
312311
313312 match & self . delegation {
314313 ShelleyAddressDelegationPart :: None => {
@@ -341,7 +340,76 @@ impl ShelleyAddress {
341340 }
342341 }
343342
344- Ok ( data)
343+ data
344+ }
345+
346+ pub fn from_bytes_key ( data : & [ u8 ] ) -> Result < Self > {
347+ if data. is_empty ( ) {
348+ return Err ( anyhow ! ( "empty address bytes" ) ) ;
349+ }
350+
351+ let header = data[ 0 ] ;
352+
353+ if header & 0x80 != 0 {
354+ return Err ( anyhow ! ( "invalid header: high bit set" ) ) ;
355+ }
356+
357+ let network = match header & 0x0F {
358+ 0 => NetworkId :: Testnet ,
359+ 1 => NetworkId :: Mainnet ,
360+ _ => return Err ( anyhow ! ( "invalid network bits in header" ) ) ,
361+ } ;
362+
363+ let addr_type = ( header >> 4 ) & 0x0F ;
364+
365+ let payment_bits = addr_type & 0x01 ;
366+ let delegation_bits = ( addr_type >> 1 ) & 0x03 ;
367+
368+ let payment_hash = {
369+ let mut arr = [ 0u8 ; 28 ] ;
370+ arr. copy_from_slice ( & data[ 1 ..29 ] ) ;
371+ Hash :: < 28 > :: new ( arr)
372+ } ;
373+
374+ let payment = match payment_bits {
375+ 0 => ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
376+ 1 => ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
377+ _ => return Err ( anyhow ! ( "invalid payment bits" ) ) ,
378+ } ;
379+
380+ let delegation = match delegation_bits {
381+ 0 => {
382+ let mut arr = [ 0u8 ; 28 ] ;
383+ arr. copy_from_slice ( & data[ 29 ..57 ] ) ;
384+ ShelleyAddressDelegationPart :: StakeKeyHash ( Hash :: < 28 > :: new ( arr) )
385+ }
386+ 1 => {
387+ let mut arr = [ 0u8 ; 28 ] ;
388+ arr. copy_from_slice ( & data[ 29 ..57 ] ) ;
389+ ShelleyAddressDelegationPart :: ScriptHash ( Hash :: < 28 > :: new ( arr) )
390+ }
391+ 2 => {
392+ let mut decoder = VarIntDecoder :: new ( & data[ 29 ..] ) ;
393+ let slot = decoder. read ( ) ?;
394+ let tx_index = decoder. read ( ) ?;
395+ let cert_index = decoder. read ( ) ?;
396+
397+ ShelleyAddressDelegationPart :: Pointer ( ShelleyAddressPointer {
398+ slot,
399+ tx_index,
400+ cert_index,
401+ } )
402+ }
403+ 3 => ShelleyAddressDelegationPart :: None ,
404+
405+ _ => return Err ( anyhow ! ( "invalid delegation bits" ) ) ,
406+ } ;
407+
408+ Ok ( ShelleyAddress {
409+ network,
410+ payment,
411+ delegation,
412+ } )
345413 }
346414
347415 pub fn stake_address_string ( & self ) -> Result < Option < String > > {
@@ -547,20 +615,15 @@ impl Default for StakeAddress {
547615}
548616
549617/// A Cardano address
550- #[ derive( Debug , Clone , PartialEq , Eq , Hash , serde:: Serialize , serde:: Deserialize ) ]
618+ #[ derive( Debug , Clone , PartialEq , Eq , Hash , serde:: Serialize , serde:: Deserialize , Default ) ]
551619pub enum Address {
620+ #[ default]
552621 None ,
553622 Byron ( ByronAddress ) ,
554623 Shelley ( ShelleyAddress ) ,
555624 Stake ( StakeAddress ) ,
556625}
557626
558- impl Default for Address {
559- fn default ( ) -> Self {
560- Self :: None
561- }
562- }
563-
564627impl Address {
565628 /// Get the stake pointer if there is one
566629 pub fn get_pointer ( & self ) -> Option < ShelleyAddressPointer > {
@@ -600,7 +663,7 @@ impl Address {
600663 match self {
601664 Address :: Byron ( b) => b. to_bytes_key ( ) ,
602665
603- Address :: Shelley ( s) => s. to_bytes_key ( ) ,
666+ Address :: Shelley ( s) => Ok ( s. to_bytes_key ( ) ) ,
604667
605668 Address :: Stake ( stake) => stake. to_bytes_key ( ) ,
606669
@@ -652,7 +715,7 @@ impl PartialOrd for BechOrdAddress {
652715#[ cfg( test) ]
653716mod tests {
654717 use super :: * ;
655- use crate :: crypto:: keyhash_224;
718+ use crate :: { crypto:: keyhash_224, hash :: Hash } ;
656719 use minicbor:: { Decode , Encode } ;
657720
658721 #[ test]
@@ -1047,4 +1110,104 @@ mod tests {
10471110 let result = StakeAddress :: decode ( & mut decoder, & mut ( ) ) ;
10481111 assert ! ( result. is_err( ) ) ;
10491112 }
1113+
1114+ #[ test]
1115+ fn test_shelley_address_to_from_bytes_key_roundtrip ( ) {
1116+ let payment_hash = Hash :: new ( [ 0x11 ; 28 ] ) ;
1117+ let stake_hash = Hash :: new ( [ 0x22 ; 28 ] ) ;
1118+ let script_hash = Hash :: new ( [ 0x33 ; 28 ] ) ;
1119+
1120+ // (KeyHash, StakeKeyHash)
1121+ let type_1 = ShelleyAddress {
1122+ network : NetworkId :: Mainnet ,
1123+ payment : ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
1124+ delegation : ShelleyAddressDelegationPart :: StakeKeyHash ( stake_hash) ,
1125+ } ;
1126+ let bytes = type_1. to_bytes_key ( ) ;
1127+ assert_eq ! ( bytes[ 0 ] , 0x01 ) ;
1128+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode base" ) ;
1129+ assert_eq ! ( type_1, decoded) ;
1130+
1131+ // (ScriptKeyHash, StakeKeyHash)
1132+ let type_2 = ShelleyAddress {
1133+ network : NetworkId :: Mainnet ,
1134+ payment : ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
1135+ delegation : ShelleyAddressDelegationPart :: StakeKeyHash ( stake_hash) ,
1136+ } ;
1137+ let bytes = type_2. to_bytes_key ( ) ;
1138+ assert_eq ! ( bytes[ 0 ] , 0x11 ) ;
1139+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode base" ) ;
1140+ assert_eq ! ( type_2, decoded) ;
1141+
1142+ // (KeyHash, ScriptHash)
1143+ let type_3 = ShelleyAddress {
1144+ network : NetworkId :: Mainnet ,
1145+ payment : ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
1146+ delegation : ShelleyAddressDelegationPart :: ScriptHash ( stake_hash) ,
1147+ } ;
1148+ let bytes = type_3. to_bytes_key ( ) ;
1149+ assert_eq ! ( bytes[ 0 ] , 0x21 ) ;
1150+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode base" ) ;
1151+ assert_eq ! ( type_3, decoded) ;
1152+
1153+ // (ScriptHash, ScriptHash)
1154+ let type_4 = ShelleyAddress {
1155+ network : NetworkId :: Mainnet ,
1156+ payment : ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
1157+ delegation : ShelleyAddressDelegationPart :: ScriptHash ( script_hash) ,
1158+ } ;
1159+ let bytes = type_4. to_bytes_key ( ) ;
1160+ assert_eq ! ( bytes[ 0 ] , 0x31 ) ;
1161+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode script" ) ;
1162+ assert_eq ! ( type_4, decoded) ;
1163+
1164+ // (KeyHash, Pointer)
1165+ let pointer = ShelleyAddressPointer {
1166+ slot : 1234 ,
1167+ tx_index : 56 ,
1168+ cert_index : 2 ,
1169+ } ;
1170+ let type_5 = ShelleyAddress {
1171+ network : NetworkId :: Mainnet ,
1172+ payment : ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
1173+ delegation : ShelleyAddressDelegationPart :: Pointer ( pointer. clone ( ) ) ,
1174+ } ;
1175+ let bytes = type_5. to_bytes_key ( ) ;
1176+ assert_eq ! ( bytes[ 0 ] , 0x41 ) ;
1177+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode pointer" ) ;
1178+ assert_eq ! ( type_5, decoded) ;
1179+
1180+ // (ScriptHash, Pointer)
1181+ let type_6 = ShelleyAddress {
1182+ network : NetworkId :: Mainnet ,
1183+ payment : ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
1184+ delegation : ShelleyAddressDelegationPart :: Pointer ( pointer) ,
1185+ } ;
1186+ let bytes = type_6. to_bytes_key ( ) ;
1187+ assert_eq ! ( bytes[ 0 ] , 0x51 ) ;
1188+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode pointer" ) ;
1189+ assert_eq ! ( type_6, decoded) ;
1190+
1191+ // (KeyHash, None)
1192+ let type_7 = ShelleyAddress {
1193+ network : NetworkId :: Mainnet ,
1194+ payment : ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
1195+ delegation : ShelleyAddressDelegationPart :: None ,
1196+ } ;
1197+ let bytes = type_7. to_bytes_key ( ) ;
1198+ assert_eq ! ( bytes[ 0 ] , 0x61 ) ;
1199+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode none" ) ;
1200+ assert_eq ! ( type_7, decoded) ;
1201+
1202+ // (ScriptHash, None)
1203+ let type_8 = ShelleyAddress {
1204+ network : NetworkId :: Mainnet ,
1205+ payment : ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
1206+ delegation : ShelleyAddressDelegationPart :: None ,
1207+ } ;
1208+ let bytes = type_8. to_bytes_key ( ) ;
1209+ assert_eq ! ( bytes[ 0 ] , 0x71 ) ;
1210+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode none" ) ;
1211+ assert_eq ! ( type_8, decoded) ;
1212+ }
10501213}
0 commit comments