Skip to content

Commit 0554ac2

Browse files
committed
cosmrs: fully variable-width AccountId
This commit changes the constructor and `to_bytes` methods to fully support variable-width account IDs, as added in cosmos/cosmos-sdk#8363. This is a breaking change.
1 parent b9c9caa commit 0554ac2

File tree

3 files changed

+39
-30
lines changed

3 files changed

+39
-30
lines changed

cosmrs/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cosmrs"
3-
version = "0.5.1"
3+
version = "0.6.0-pre"
44
authors = ["Tony Arcieri <[email protected]>"]
55
license = "Apache-2.0"
66
repository = "https://github.com/cosmos/cosmos-rust/tree/main/cosmrs"

cosmrs/src/base.rs

+37-28
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,28 @@ pub struct AccountId {
2222
impl 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

cosmrs/src/crypto/public_key.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ impl PublicKey {
3535
match &self.0 {
3636
tendermint::PublicKey::Secp256k1(encoded_point) => {
3737
let id = tendermint::account::Id::from(*encoded_point);
38-
AccountId::new(prefix, id.as_bytes().try_into()?)
38+
AccountId::new(prefix, id.as_bytes())
3939
}
4040
_ => Err(Error::Crypto.into()),
4141
}

0 commit comments

Comments
 (0)