@@ -22,18 +22,28 @@ pub struct AccountId {
2222impl AccountId {
2323 /// Create an [`AccountId`] with the given human-readable prefix and
2424 /// public key hash.
25- pub fn new ( prefix : & str , bytes : [ u8 ; tendermint :: account :: LENGTH ] ) -> Result < Self > {
25+ pub fn new ( prefix : & str , bytes : & [ u8 ] ) -> Result < Self > {
2626 let id = bech32:: encode ( prefix, & bytes) ;
2727
2828 // TODO(tarcieri): ensure this is the proper validation for an account prefix
29- if prefix. chars ( ) . all ( |c| matches ! ( c, 'a' ..='z' ) ) {
29+ if !prefix. chars ( ) . all ( |c| matches ! ( c, 'a' ..='z' ) ) {
30+ return Err ( Error :: AccountId { id } )
31+ . wrap_err ( "expected prefix to be lowercase alphabetical characters only" ) ;
32+ }
33+
34+ if matches ! ( bytes. len( ) , 1 ..=MAX_ADDRESS_LENGTH ) {
3035 Ok ( Self {
3136 bech32 : id,
3237 hrp_length : prefix. len ( ) ,
3338 } )
3439 } else {
35- Err ( Error :: AccountId { id } )
36- . wrap_err ( "expected prefix to be lowercase alphabetical characters only" )
40+ Err ( Error :: AccountId { id } ) . wrap_err_with ( || {
41+ format ! (
42+ "account ID should be at most {} bytes long, but was {} bytes long" ,
43+ MAX_ADDRESS_LENGTH ,
44+ bytes. len( )
45+ )
46+ } )
3747 }
3848 }
3949
@@ -43,11 +53,10 @@ impl AccountId {
4353 }
4454
4555 /// Decode an account ID from Bech32 to an inner byte value.
46- pub fn to_bytes ( & self ) -> [ u8 ; tendermint :: account :: LENGTH ] {
56+ pub fn to_bytes ( & self ) -> Vec < u8 > {
4757 bech32:: decode ( & self . bech32 )
48- . ok ( )
49- . and_then ( |result| result. 1 . try_into ( ) . ok ( ) )
5058 . expect ( "malformed Bech32 AccountId" )
59+ . 1
5160 }
5261}
5362
@@ -74,33 +83,33 @@ impl FromStr for AccountId {
7483
7584 fn from_str ( s : & str ) -> Result < Self > {
7685 let ( hrp, bytes) = bech32:: decode ( s) . wrap_err ( "failed to decode bech32" ) ?;
77-
78- if matches ! ( bytes. len( ) , 1 ..=MAX_ADDRESS_LENGTH ) {
79- Ok ( Self {
80- bech32 : s. to_owned ( ) ,
81- hrp_length : hrp. len ( ) ,
82- } )
83- } else {
84- Err ( Error :: AccountId { id : s. to_owned ( ) } ) . wrap_err_with ( || {
85- format ! (
86- "account ID should be at most {} bytes long, but was {} bytes long" ,
87- MAX_ADDRESS_LENGTH ,
88- bytes. len( )
89- )
90- } )
91- }
86+ Self :: new ( & hrp, & bytes)
9287 }
9388}
9489
95- impl From < AccountId > for tendermint:: account:: Id {
96- fn from ( id : AccountId ) -> tendermint:: account:: Id {
97- tendermint:: account:: Id :: from ( & id)
90+ impl TryFrom < AccountId > for tendermint:: account:: Id {
91+ type Error = ErrorReport ;
92+
93+ fn try_from ( id : AccountId ) -> Result < tendermint:: account:: Id > {
94+ tendermint:: account:: Id :: try_from ( & id)
9895 }
9996}
10097
101- impl From < & AccountId > for tendermint:: account:: Id {
102- fn from ( id : & AccountId ) -> tendermint:: account:: Id {
103- tendermint:: account:: Id :: new ( id. to_bytes ( ) )
98+ // TODO(tarcieri): non-fixed-width account ID type
99+ impl TryFrom < & AccountId > for tendermint:: account:: Id {
100+ type Error = ErrorReport ;
101+
102+ fn try_from ( id : & AccountId ) -> Result < tendermint:: account:: Id > {
103+ let bytes = id. to_bytes ( ) ;
104+ let len = bytes. len ( ) ;
105+
106+ match bytes. try_into ( ) {
107+ Ok ( bytes) => Ok ( tendermint:: account:: Id :: new ( bytes) ) ,
108+ _ => Err ( Error :: AccountId {
109+ id : id. bech32 . clone ( ) ,
110+ } )
111+ . wrap_err_with ( || format ! ( "invalid length for account ID: {}" , len) ) ,
112+ }
104113 }
105114}
106115
0 commit comments