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 } ;
@@ -294,7 +295,7 @@ impl ShelleyAddress {
294295 Ok ( bech32:: encode :: < bech32:: Bech32 > ( hrp, & data) ?)
295296 }
296297
297- pub fn to_bytes_key ( & self ) -> Result < Vec < u8 > > {
298+ pub fn to_bytes_key ( & self ) -> Vec < u8 > {
298299 let network_bits = match self . network {
299300 NetworkId :: Mainnet => 1u8 ,
300301 NetworkId :: Testnet => 0u8 ,
@@ -307,8 +308,10 @@ impl ShelleyAddress {
307308
308309 let mut data = Vec :: new ( ) ;
309310
310- let build_header =
311- |variant : u8 | -> u8 { network_bits | ( payment_bits << 4 ) | ( variant << 5 ) } ;
311+ let build_header = |delegation_bits : u8 | -> u8 {
312+ let addr_type = ( ( delegation_bits & 0x03 ) << 1 ) | ( payment_bits & 0x01 ) ;
313+ ( addr_type << 4 ) | ( network_bits & 0x0F )
314+ } ;
312315
313316 match & self . delegation {
314317 ShelleyAddressDelegationPart :: None => {
@@ -341,7 +344,76 @@ impl ShelleyAddress {
341344 }
342345 }
343346
344- Ok ( data)
347+ data
348+ }
349+
350+ pub fn from_bytes_key ( data : & [ u8 ] ) -> Result < Self > {
351+ if data. is_empty ( ) {
352+ return Err ( anyhow ! ( "empty address bytes" ) ) ;
353+ }
354+
355+ let header = data[ 0 ] ;
356+
357+ if header & 0x80 != 0 {
358+ return Err ( anyhow ! ( "invalid header: high bit set" ) ) ;
359+ }
360+
361+ let network = match header & 0x0F {
362+ 0 => NetworkId :: Testnet ,
363+ 1 => NetworkId :: Mainnet ,
364+ _ => return Err ( anyhow ! ( "invalid network bits in header" ) ) ,
365+ } ;
366+
367+ let addr_type = ( header >> 4 ) & 0x0F ;
368+
369+ let payment_bits = addr_type & 0x01 ;
370+ let delegation_bits = ( addr_type >> 1 ) & 0x03 ;
371+
372+ let payment_hash = {
373+ let mut arr = [ 0u8 ; 28 ] ;
374+ arr. copy_from_slice ( & data[ 1 ..29 ] ) ;
375+ Hash :: < 28 > :: new ( arr)
376+ } ;
377+
378+ let payment = match payment_bits {
379+ 0 => ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
380+ 1 => ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
381+ _ => return Err ( anyhow ! ( "invalid payment bits" ) ) ,
382+ } ;
383+
384+ let delegation = match delegation_bits {
385+ 0 => {
386+ let mut arr = [ 0u8 ; 28 ] ;
387+ arr. copy_from_slice ( & data[ 29 ..57 ] ) ;
388+ ShelleyAddressDelegationPart :: StakeKeyHash ( Hash :: < 28 > :: new ( arr) )
389+ }
390+ 1 => {
391+ let mut arr = [ 0u8 ; 28 ] ;
392+ arr. copy_from_slice ( & data[ 29 ..57 ] ) ;
393+ ShelleyAddressDelegationPart :: ScriptHash ( Hash :: < 28 > :: new ( arr) )
394+ }
395+ 2 => {
396+ let mut decoder = VarIntDecoder :: new ( & data[ 29 ..] ) ;
397+ let slot = decoder. read ( ) ?;
398+ let tx_index = decoder. read ( ) ?;
399+ let cert_index = decoder. read ( ) ?;
400+
401+ ShelleyAddressDelegationPart :: Pointer ( ShelleyAddressPointer {
402+ slot,
403+ tx_index,
404+ cert_index,
405+ } )
406+ }
407+ 3 => ShelleyAddressDelegationPart :: None ,
408+
409+ _ => return Err ( anyhow ! ( "invalid delegation bits" ) ) ,
410+ } ;
411+
412+ Ok ( ShelleyAddress {
413+ network,
414+ payment,
415+ delegation,
416+ } )
345417 }
346418
347419 pub fn stake_address_string ( & self ) -> Result < Option < String > > {
@@ -600,7 +672,7 @@ impl Address {
600672 match self {
601673 Address :: Byron ( b) => b. to_bytes_key ( ) ,
602674
603- Address :: Shelley ( s) => s. to_bytes_key ( ) ,
675+ Address :: Shelley ( s) => Ok ( s. to_bytes_key ( ) ) ,
604676
605677 Address :: Stake ( stake) => stake. to_bytes_key ( ) ,
606678
@@ -652,7 +724,7 @@ impl PartialOrd for BechOrdAddress {
652724#[ cfg( test) ]
653725mod tests {
654726 use super :: * ;
655- use crate :: crypto:: keyhash_224;
727+ use crate :: { crypto:: keyhash_224, hash :: Hash } ;
656728 use minicbor:: { Decode , Encode } ;
657729
658730 #[ test]
@@ -1047,4 +1119,104 @@ mod tests {
10471119 let result = StakeAddress :: decode ( & mut decoder, & mut ( ) ) ;
10481120 assert ! ( result. is_err( ) ) ;
10491121 }
1122+
1123+ #[ test]
1124+ fn test_shelley_address_to_from_bytes_key_roundtrip ( ) {
1125+ let payment_hash = Hash :: new ( [ 0x11 ; 28 ] ) ;
1126+ let stake_hash = Hash :: new ( [ 0x22 ; 28 ] ) ;
1127+ let script_hash = Hash :: new ( [ 0x33 ; 28 ] ) ;
1128+
1129+ // (KeyHash, StakeKeyHash)
1130+ let type_1 = ShelleyAddress {
1131+ network : NetworkId :: Mainnet ,
1132+ payment : ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
1133+ delegation : ShelleyAddressDelegationPart :: StakeKeyHash ( stake_hash) ,
1134+ } ;
1135+ let bytes = type_1. to_bytes_key ( ) ;
1136+ assert_eq ! ( bytes[ 0 ] , 0x01 ) ;
1137+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode base" ) ;
1138+ assert_eq ! ( type_1, decoded) ;
1139+
1140+ // (ScriptKeyHash, StakeKeyHash)
1141+ let type_2 = ShelleyAddress {
1142+ network : NetworkId :: Mainnet ,
1143+ payment : ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
1144+ delegation : ShelleyAddressDelegationPart :: StakeKeyHash ( stake_hash) ,
1145+ } ;
1146+ let bytes = type_2. to_bytes_key ( ) ;
1147+ assert_eq ! ( bytes[ 0 ] , 0x11 ) ;
1148+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode base" ) ;
1149+ assert_eq ! ( type_2, decoded) ;
1150+
1151+ // (KeyHash, ScriptHash)
1152+ let type_3 = ShelleyAddress {
1153+ network : NetworkId :: Mainnet ,
1154+ payment : ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
1155+ delegation : ShelleyAddressDelegationPart :: ScriptHash ( stake_hash) ,
1156+ } ;
1157+ let bytes = type_3. to_bytes_key ( ) ;
1158+ assert_eq ! ( bytes[ 0 ] , 0x21 ) ;
1159+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode base" ) ;
1160+ assert_eq ! ( type_3, decoded) ;
1161+
1162+ // (ScriptHash, ScriptHash)
1163+ let type_4 = ShelleyAddress {
1164+ network : NetworkId :: Mainnet ,
1165+ payment : ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
1166+ delegation : ShelleyAddressDelegationPart :: ScriptHash ( script_hash) ,
1167+ } ;
1168+ let bytes = type_4. to_bytes_key ( ) ;
1169+ assert_eq ! ( bytes[ 0 ] , 0x31 ) ;
1170+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode script" ) ;
1171+ assert_eq ! ( type_4, decoded) ;
1172+
1173+ // (KeyHash, Pointer)
1174+ let pointer = ShelleyAddressPointer {
1175+ slot : 1234 ,
1176+ tx_index : 56 ,
1177+ cert_index : 2 ,
1178+ } ;
1179+ let type_5 = ShelleyAddress {
1180+ network : NetworkId :: Mainnet ,
1181+ payment : ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
1182+ delegation : ShelleyAddressDelegationPart :: Pointer ( pointer. clone ( ) ) ,
1183+ } ;
1184+ let bytes = type_5. to_bytes_key ( ) ;
1185+ assert_eq ! ( bytes[ 0 ] , 0x41 ) ;
1186+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode pointer" ) ;
1187+ assert_eq ! ( type_5, decoded) ;
1188+
1189+ // (ScriptHash, Pointer)
1190+ let type_6 = ShelleyAddress {
1191+ network : NetworkId :: Mainnet ,
1192+ payment : ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
1193+ delegation : ShelleyAddressDelegationPart :: Pointer ( pointer) ,
1194+ } ;
1195+ let bytes = type_6. to_bytes_key ( ) ;
1196+ assert_eq ! ( bytes[ 0 ] , 0x51 ) ;
1197+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode pointer" ) ;
1198+ assert_eq ! ( type_6, decoded) ;
1199+
1200+ // (KeyHash, None)
1201+ let type_7 = ShelleyAddress {
1202+ network : NetworkId :: Mainnet ,
1203+ payment : ShelleyAddressPaymentPart :: PaymentKeyHash ( payment_hash) ,
1204+ delegation : ShelleyAddressDelegationPart :: None ,
1205+ } ;
1206+ let bytes = type_7. to_bytes_key ( ) ;
1207+ assert_eq ! ( bytes[ 0 ] , 0x61 ) ;
1208+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode none" ) ;
1209+ assert_eq ! ( type_7, decoded) ;
1210+
1211+ // (ScriptHash, None)
1212+ let type_8 = ShelleyAddress {
1213+ network : NetworkId :: Mainnet ,
1214+ payment : ShelleyAddressPaymentPart :: ScriptHash ( payment_hash) ,
1215+ delegation : ShelleyAddressDelegationPart :: None ,
1216+ } ;
1217+ let bytes = type_8. to_bytes_key ( ) ;
1218+ assert_eq ! ( bytes[ 0 ] , 0x71 ) ;
1219+ let decoded = ShelleyAddress :: from_bytes_key ( & bytes) . expect ( "decode none" ) ;
1220+ assert_eq ! ( type_8, decoded) ;
1221+ }
10501222}
0 commit comments