@@ -214,7 +214,18 @@ impl StakeAddress {
214214 }
215215 }
216216
217- /// Read from a string format
217+ /// Convert to string stake1xxx format
218+ pub fn to_string ( & self ) -> Result < String > {
219+ let hrp = match self . network {
220+ AddressNetwork :: Main => bech32:: Hrp :: parse ( "stake" ) ?,
221+ AddressNetwork :: Test => bech32:: Hrp :: parse ( "stake_test" ) ?,
222+ } ;
223+
224+ let data = self . to_binary ( ) ;
225+ Ok ( bech32:: encode :: < bech32:: Bech32 > ( hrp, & data) ?)
226+ }
227+
228+ /// Read from a string format ("stake1xxx...")
218229 pub fn from_string ( text : & str ) -> Result < Self > {
219230 let ( hrp, data) = bech32:: decode ( text) ?;
220231 if let Some ( header) = data. first ( ) {
@@ -235,6 +246,23 @@ impl StakeAddress {
235246 Err ( anyhow ! ( "Empty stake address data" ) )
236247 }
237248
249+ /// Convert to binary format (29 bytes)
250+ pub fn to_binary ( & self ) -> Vec < u8 > {
251+ let network_bits = match self . network {
252+ AddressNetwork :: Main => 0b1u8 ,
253+ AddressNetwork :: Test => 0b0u8 ,
254+ } ;
255+
256+ let ( stake_bits, stake_hash) : ( u8 , & Vec < u8 > ) = match & self . payload {
257+ StakeAddressPayload :: StakeKeyHash ( data) => ( 0b1110 , data) ,
258+ StakeAddressPayload :: ScriptHash ( data) => ( 0b1111 , data) ,
259+ } ;
260+
261+ let mut data = vec ! [ network_bits | ( stake_bits << 4 ) ] ;
262+ data. extend ( stake_hash) ;
263+ data
264+ }
265+
238266 /// Read from binary format (29 bytes)
239267 pub fn from_binary ( data : & [ u8 ] ) -> Result < Self > {
240268 if data. len ( ) != 29 {
@@ -252,24 +280,7 @@ impl StakeAddress {
252280 _ => bail ! ( "Unknown header byte {:x} in stake address" , data[ 0 ] ) ,
253281 } ;
254282
255- return Ok ( StakeAddress { network, payload } ) ;
256- }
257-
258- /// Convert to string stake1xxx form
259- pub fn to_string ( & self ) -> Result < String > {
260- let ( hrp, network_bits) = match self . network {
261- AddressNetwork :: Main => ( bech32:: Hrp :: parse ( "stake" ) ?, 1u8 ) ,
262- AddressNetwork :: Test => ( bech32:: Hrp :: parse ( "stake_test" ) ?, 0u8 ) ,
263- } ;
264-
265- let ( stake_hash, stake_bits) : ( & Vec < u8 > , u8 ) = match & self . payload {
266- StakeAddressPayload :: StakeKeyHash ( data) => ( data, 0b1110 ) ,
267- StakeAddressPayload :: ScriptHash ( data) => ( data, 0b1111 ) ,
268- } ;
269-
270- let mut data = vec ! [ network_bits | ( stake_bits << 4 ) ] ;
271- data. extend ( stake_hash) ;
272- Ok ( bech32:: encode :: < bech32:: Bech32 > ( hrp, & data) ?)
283+ Ok ( StakeAddress { network, payload } )
273284 }
274285}
275286
@@ -279,20 +290,8 @@ impl<C> minicbor::Encode<C> for StakeAddress {
279290 e : & mut minicbor:: Encoder < W > ,
280291 _ctx : & mut C ,
281292 ) -> Result < ( ) , minicbor:: encode:: Error < W :: Error > > {
282- let network_bits = match self . network {
283- AddressNetwork :: Main => 0b1u8 ,
284- AddressNetwork :: Test => 0b0u8 ,
285- } ;
286-
287- let ( stake_bits, stake_hash) : ( u8 , & Vec < u8 > ) = match & self . payload {
288- StakeAddressPayload :: StakeKeyHash ( data) => ( 0b1110 , data) ,
289- StakeAddressPayload :: ScriptHash ( data) => ( 0b1111 , data) ,
290- } ;
291-
292- let mut data = vec ! [ network_bits | ( stake_bits << 4 ) ] ;
293- data. extend ( stake_hash) ;
294-
295- e. bytes ( & data) ?;
293+ let bytes = self . to_binary ( ) ;
294+ e. writer_mut ( ) . write_all ( & bytes) . map_err ( |err| minicbor:: encode:: Error :: write ( err) ) ?;
296295 Ok ( ( ) )
297296 }
298297}
@@ -302,8 +301,7 @@ impl<'b, C> minicbor::Decode<'b, C> for StakeAddress {
302301 d : & mut minicbor:: Decoder < ' b > ,
303302 _ctx : & mut C ,
304303 ) -> Result < Self , minicbor:: decode:: Error > {
305- let bytes = d. bytes ( ) ?;
306- StakeAddress :: from_binary ( bytes)
304+ StakeAddress :: from_binary ( d. input ( ) )
307305 . map_err ( |e| minicbor:: decode:: Error :: message ( e. to_string ( ) ) )
308306 }
309307}
@@ -340,10 +338,10 @@ impl Address {
340338 return Some ( ptr. clone ( ) ) ;
341339 }
342340 }
343- return None ;
341+ None
344342 }
345343
346- /// Read from string format
344+ /// Read from string format ("addr1...")
347345 pub fn from_string ( text : & str ) -> Result < Self > {
348346 if text. starts_with ( "addr1" ) || text. starts_with ( "addr_test1" ) {
349347 Ok ( Self :: Shelley ( ShelleyAddress :: from_string ( text) ?) )
@@ -374,6 +372,7 @@ impl Address {
374372mod tests {
375373 use super :: * ;
376374 use crate :: crypto:: keyhash_224;
375+ use minicbor:: { Decode , Encode } ;
377376
378377 #[ test]
379378 fn byron_address ( ) {
@@ -637,4 +636,99 @@ mod tests {
637636 "558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001"
638637 ) ;
639638 }
639+
640+ fn mainnet_stake_address ( ) -> StakeAddress {
641+ let binary =
642+ hex:: decode ( "e1558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001" ) . unwrap ( ) ;
643+ StakeAddress :: from_binary ( & binary) . unwrap ( )
644+ }
645+
646+ fn testnet_stake_address ( ) -> StakeAddress {
647+ let binary =
648+ hex:: decode ( "e0558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001" ) . unwrap ( ) ;
649+ StakeAddress :: from_binary ( & binary) . unwrap ( )
650+ }
651+
652+ #[ test]
653+ fn stake_addresses_encode_mainnet_stake ( ) {
654+ let address = mainnet_stake_address ( ) ;
655+ let expected = address. to_binary ( ) ;
656+
657+ let mut actual = Vec :: new ( ) ;
658+ let mut encoder = minicbor:: Encoder :: new ( & mut actual) ;
659+ let result = address. encode ( & mut encoder, & mut ( ) ) ;
660+
661+ assert ! ( result. is_ok( ) ) ;
662+ assert_eq ! ( actual. len( ) , 29 ) ;
663+ assert_eq ! ( & actual[ ..] , & expected[ ..] ) ;
664+ }
665+
666+ #[ test]
667+ fn stake_addresses_decode_mainnet_stake ( ) {
668+ let binary = mainnet_stake_address ( ) . to_binary ( ) ;
669+
670+ let mut decoder = minicbor:: Decoder :: new ( & binary) ;
671+ let decoded = StakeAddress :: decode ( & mut decoder, & mut ( ) ) . unwrap ( ) ;
672+
673+ assert_eq ! ( decoded. network, AddressNetwork :: Main ) ;
674+ assert_eq ! (
675+ match decoded. payload {
676+ StakeAddressPayload :: StakeKeyHash ( key) => hex:: encode( & key) ,
677+ _ => "STAKE" . to_string( ) ,
678+ } ,
679+ "558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001"
680+ ) ;
681+ }
682+ #[ test]
683+ fn stake_addresses_round_trip_mainnet_stake ( ) {
684+ let binary =
685+ hex:: decode ( "f1558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001" ) . unwrap ( ) ;
686+ let original = StakeAddress :: from_binary ( & binary) . unwrap ( ) ;
687+
688+ let mut encoded = Vec :: new ( ) ;
689+ let mut encoder = minicbor:: Encoder :: new ( & mut encoded) ;
690+ original. encode ( & mut encoder, & mut ( ) ) . unwrap ( ) ;
691+
692+ let mut decoder = minicbor:: Decoder :: new ( & encoded) ;
693+ let decoded = StakeAddress :: decode ( & mut decoder, & mut ( ) ) . unwrap ( ) ;
694+
695+ assert_eq ! ( decoded. network, AddressNetwork :: Main ) ;
696+ assert_eq ! (
697+ match decoded. payload {
698+ StakeAddressPayload :: ScriptHash ( key) => hex:: encode( & key) ,
699+ _ => "STAKE" . to_string( ) ,
700+ } ,
701+ "558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001"
702+ ) ;
703+ }
704+
705+ #[ test]
706+ fn stake_addresses_roundtrip_testnet_stake ( ) {
707+ let original = testnet_stake_address ( ) ;
708+
709+ let mut encoded = Vec :: new ( ) ;
710+ let mut encoder = minicbor:: Encoder :: new ( & mut encoded) ;
711+ original. encode ( & mut encoder, & mut ( ) ) . unwrap ( ) ;
712+
713+ let mut decoder = minicbor:: Decoder :: new ( & encoded) ;
714+ let decoded = StakeAddress :: decode ( & mut decoder, & mut ( ) ) . unwrap ( ) ;
715+
716+ assert_eq ! ( decoded. network, AddressNetwork :: Test ) ;
717+ assert_eq ! (
718+ match decoded. payload {
719+ StakeAddressPayload :: StakeKeyHash ( key) => hex:: encode( & key) ,
720+ _ => "SCRIPT" . to_string( ) ,
721+ } ,
722+ "558f3ee09b26d88fac2eddc772a9eda94cce6dbadbe9fee439bd6001"
723+ ) ;
724+ }
725+
726+ #[ test]
727+ fn stake_addresses_decode_invalid_length ( ) {
728+ let bad_data = vec ! [ 0xe1 , 0x00 , 0x01 , 0x02 , 0x03 ] ;
729+ let mut decoder = minicbor:: Decoder :: new ( & bad_data) ;
730+
731+ let result = StakeAddress :: decode ( & mut decoder, & mut ( ) ) ;
732+ assert ! ( result. is_err( ) ) ;
733+ }
640734}
0 commit comments