@@ -22,18 +22,28 @@ pub struct AccountId {
22
22
impl AccountId {
23
23
/// Create an [`AccountId`] with the given human-readable prefix and
24
24
/// 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 > {
26
26
let id = bech32:: encode ( prefix, & bytes) ;
27
27
28
28
// 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 ) {
30
35
Ok ( Self {
31
36
bech32 : id,
32
37
hrp_length : prefix. len ( ) ,
33
38
} )
34
39
} 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
+ } )
37
47
}
38
48
}
39
49
@@ -43,11 +53,10 @@ impl AccountId {
43
53
}
44
54
45
55
/// 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 > {
47
57
bech32:: decode ( & self . bech32 )
48
- . ok ( )
49
- . and_then ( |result| result. 1 . try_into ( ) . ok ( ) )
50
58
. expect ( "malformed Bech32 AccountId" )
59
+ . 1
51
60
}
52
61
}
53
62
@@ -74,33 +83,33 @@ impl FromStr for AccountId {
74
83
75
84
fn from_str ( s : & str ) -> Result < Self > {
76
85
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)
92
87
}
93
88
}
94
89
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)
98
95
}
99
96
}
100
97
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
+ }
104
113
}
105
114
}
106
115
0 commit comments