Skip to content

Commit

Permalink
Merge branch 'origin/tomas/established-addr-bytes' (#1510)
Browse files Browse the repository at this point in the history
* origin/tomas/established-addr-bytes:
  test/wasm: update hard-coded hashes of wasm_for_tests
  channgelog: add #1510
  [ci] wasm checksums update
  wasm_for_tests: rebuild because of address breaking change
  core/types/address: use byte array of a string in established addr
  core/types/address: rename `s/HASH_LEN/HASH_HEX_LEN`
  • Loading branch information
Fraccaman committed Jun 14, 2023
2 parents 5789e88 + 011b443 commit cf8cd4c
Show file tree
Hide file tree
Showing 18 changed files with 89 additions and 45 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Improve the established address in-memory representation
and use a full SHA-256 digest for their generation.
([\#1510](https://github.com/anoma/namada/pull/1510))
4 changes: 2 additions & 2 deletions core/src/ledger/ibc/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::ibc::core::ics24_host::path::{
ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath,
};
use crate::ibc::core::ics24_host::Path;
use crate::types::address::{Address, InternalAddress, HASH_LEN};
use crate::types::address::{Address, InternalAddress, HASH_HEX_LEN};
use crate::types::storage::{self, DbKeySeg, Key, KeySeg};

const CLIENTS_COUNTER: &str = "clients/counter";
Expand Down Expand Up @@ -500,7 +500,7 @@ pub fn token_hash_from_denom(denom: impl AsRef<str>) -> Result<Option<String>> {
pub fn calc_hash(denom: impl AsRef<str>) -> String {
let mut hasher = Sha256::new();
hasher.update(denom.as_ref());
format!("{:.width$x}", hasher.finalize(), width = HASH_LEN)
format!("{:.width$x}", hasher.finalize(), width = HASH_HEX_LEN)
}

/// Key's prefix of the received token over IBC
Expand Down
83 changes: 62 additions & 21 deletions core/src/types/address.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
//! Implements transparent addresses as described in [Accounts
//! Addresses](docs/src/explore/design/ledger/accounts.md#addresses).
use std::borrow::Cow;
use std::collections::HashMap;
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::str::FromStr;

use bech32::{self, FromBase32, ToBase32, Variant};
use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
use data_encoding::HEXUPPER;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use thiserror::Error;
Expand All @@ -17,7 +19,7 @@ use crate::types::key;
use crate::types::key::PublicKeyHash;

/// The length of an established [`Address`] encoded with Borsh.
pub const ESTABLISHED_ADDRESS_BYTES_LEN: usize = 45;
pub const ESTABLISHED_ADDRESS_BYTES_LEN: usize = 21;

/// The length of [`Address`] encoded with Bech32m.
pub const ADDRESS_LEN: usize = 79 + ADDRESS_HRP.len();
Expand All @@ -27,7 +29,23 @@ pub const ADDRESS_LEN: usize = 79 + ADDRESS_HRP.len();
const ADDRESS_HRP: &str = "atest";
/// We're using "Bech32m" variant
pub const BECH32M_VARIANT: bech32::Variant = Variant::Bech32m;
pub(crate) const HASH_LEN: usize = 40;

/// Length of a hash of an address as a hexadecimal string
pub(crate) const HASH_HEX_LEN: usize = 40;

/// Length of a trimmed hash of an address.
pub(crate) const HASH_LEN: usize = 20;

/// SHA-256 hash len
///
/// ```
/// use sha2::Digest;
/// assert_eq!(
/// sha2::Sha256::output_size(),
/// namada_core::types::address::SHA_HASH_LEN
/// );
/// ```
pub const SHA_HASH_LEN: usize = 32;

/// An address string before bech32m encoding must be this size.
pub const FIXED_LEN_STRING_BYTES: usize = 45;
Expand Down Expand Up @@ -166,10 +184,15 @@ impl Address {

/// Try to get a raw hash of an address, only defined for established and
/// implicit addresses.
pub fn raw_hash(&self) -> Option<&str> {
pub fn raw_hash(&self) -> Option<Cow<str>> {
match self {
Address::Established(established) => Some(&established.hash),
Address::Implicit(ImplicitAddress(implicit)) => Some(&implicit.0),
Address::Established(established) => {
let hash_hex = HEXUPPER.encode(&established.hash);
Some(Cow::Owned(hash_hex))
}
Address::Implicit(ImplicitAddress(implicit)) => {
Some(Cow::Borrowed(&implicit.0))
}
Address::Internal(_) => None,
}
}
Expand All @@ -178,7 +201,10 @@ impl Address {
fn to_fixed_len_string(&self) -> Vec<u8> {
let mut string = match self {
Address::Established(EstablishedAddress { hash }) => {
format!("{}::{}", PREFIX_ESTABLISHED, hash)
// The bech32m's data is a hex of the first 40 chars of the hash
let hash_hex = HEXUPPER.encode(hash);
debug_assert_eq!(hash_hex.len(), HASH_HEX_LEN);
format!("{}::{}", PREFIX_ESTABLISHED, hash_hex)
}
Address::Implicit(ImplicitAddress(pkh)) => {
format!("{}::{}", PREFIX_IMPLICIT, pkh)
Expand Down Expand Up @@ -233,10 +259,24 @@ impl Address {
}
match string.split_once("::") {
Some((PREFIX_ESTABLISHED, hash)) => {
if hash.len() == HASH_LEN {
Ok(Address::Established(EstablishedAddress {
hash: hash.to_string(),
}))
if hash.len() == HASH_HEX_LEN {
let raw =
HEXUPPER.decode(hash.as_bytes()).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::InvalidInput,
e,
)
})?;
if raw.len() != HASH_LEN {
return Err(Error::new(
ErrorKind::InvalidData,
"Established address hash must be 40 characters \
long",
));
}
let mut hash: [u8; HASH_LEN] = Default::default();
hash.copy_from_slice(&raw);
Ok(Address::Established(EstablishedAddress { hash }))
} else {
Err(Error::new(
ErrorKind::InvalidData,
Expand Down Expand Up @@ -285,7 +325,7 @@ impl Address {
internal::IBC_MINT => {
Ok(Address::Internal(InternalAddress::IbcMint))
}
_ if raw.len() == HASH_LEN => Ok(Address::Internal(
_ if raw.len() == HASH_HEX_LEN => Ok(Address::Internal(
InternalAddress::IbcToken(raw.to_string()),
)),
_ => Err(Error::new(
Expand Down Expand Up @@ -389,20 +429,20 @@ impl TryFrom<Signer> for Address {
Deserialize,
)]
pub struct EstablishedAddress {
hash: String,
hash: [u8; HASH_LEN],
}

/// A generator of established addresses
#[derive(Debug, Clone, PartialEq, BorshSerialize, BorshDeserialize)]
pub struct EstablishedAddressGen {
last_hash: String,
last_hash: [u8; SHA_HASH_LEN],
}

impl EstablishedAddressGen {
/// Initialize a new address generator with a given randomness seed.
pub fn new(seed: impl AsRef<str>) -> Self {
Self {
last_hash: seed.as_ref().to_owned(),
last_hash: Sha256::digest(seed.as_ref().as_bytes()).into(),
}
}

Expand All @@ -416,12 +456,12 @@ impl EstablishedAddressGen {
let gen_bytes = self
.try_to_vec()
.expect("Encoding established addresses generator shouldn't fail");
let mut hasher = Sha256::new();
let bytes = [&gen_bytes, rng_source.as_ref()].concat();
hasher.update(bytes);
// hex of the first 40 chars of the hash
let hash = format!("{:.width$X}", hasher.finalize(), width = HASH_LEN);
self.last_hash = hash.clone();
let full_hash = Sha256::digest(&bytes);
// take first 20 bytes of the hash
let mut hash: [u8; HASH_LEN] = Default::default();
hash.copy_from_slice(&full_hash[..HASH_LEN]);
self.last_hash = full_hash.into();
Address::Established(EstablishedAddress { hash })
}
}
Expand Down Expand Up @@ -507,7 +547,8 @@ impl InternalAddress {
let mut hasher = Sha256::new();
let s = format!("{}/{}/{}", port_id, channel_id, token);
hasher.update(&s);
let hash = format!("{:.width$x}", hasher.finalize(), width = HASH_LEN);
let hash =
format!("{:.width$x}", hasher.finalize(), width = HASH_HEX_LEN);
InternalAddress::IbcToken(hash)
}
}
Expand Down Expand Up @@ -831,7 +872,7 @@ pub mod testing {
);
hasher.update(&s);
let hash =
format!("{:.width$x}", hasher.finalize(), width = HASH_LEN);
format!("{:.width$x}", hasher.finalize(), width = HASH_HEX_LEN);
InternalAddress::IbcToken(hash)
})
}
Expand Down
2 changes: 1 addition & 1 deletion core/src/types/key/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ pub trait SigScheme: Eq + Ord + Debug + Serialize + Default {
#[serde(transparent)]
pub struct PublicKeyHash(pub(crate) String);

const PKH_HASH_LEN: usize = address::HASH_LEN;
const PKH_HASH_LEN: usize = address::HASH_HEX_LEN;

impl From<PublicKeyHash> for String {
fn from(pkh: PublicKeyHash) -> Self {
Expand Down
4 changes: 2 additions & 2 deletions core/src/types/masp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use borsh::{BorshDeserialize, BorshSerialize};
use sha2::{Digest, Sha256};

use crate::types::address::{
masp, Address, DecodeError, BECH32M_VARIANT, HASH_LEN,
masp, Address, DecodeError, BECH32M_VARIANT, HASH_HEX_LEN,
};

/// human-readable part of Bech32m encoded address
Expand Down Expand Up @@ -153,7 +153,7 @@ impl PaymentAddress {
let mut hasher = Sha256::new();
hasher.update(bytes);
// hex of the first 40 chars of the hash
format!("{:.width$X}", hasher.finalize(), width = HASH_LEN)
format!("{:.width$X}", hasher.finalize(), width = HASH_HEX_LEN)
}
}

Expand Down
38 changes: 19 additions & 19 deletions wasm/checksums.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
{
"tx_bond.wasm": "tx_bond.9d034041d7085d261e2d75e548b74e0635b7c87f14173aecddbd64d8a8646d58.wasm",
"tx_change_validator_commission.wasm": "tx_change_validator_commission.5d172f38a22a045902e83d10ebdcaef88f75a0511dc5c3e224ef89d7fc594b78.wasm",
"tx_ibc.wasm": "tx_ibc.462075ed66348d74f60a7af04d5200acff673ddb1a1d16497fbc97ee846e1851.wasm",
"tx_init_account.wasm": "tx_init_account.7e827fb86331b0b62eb1162f917e522f6f426df9608d67c13caed089d63cd25f.wasm",
"tx_init_proposal.wasm": "tx_init_proposal.4fe5500d95d040ca3f2e51446bfb96cfc99596302e4e2368ee599f1a610f5968.wasm",
"tx_init_validator.wasm": "tx_init_validator.a6db44f07090f6c19dea71f1865f6acba1a4a946c29057231312188dfbfd1c9e.wasm",
"tx_reveal_pk.wasm": "tx_reveal_pk.3bb71bb884737ab184b4f543b503e512431d0e8cad24d202981c06063a11614c.wasm",
"tx_transfer.wasm": "tx_transfer.8c24cc4bb4e947a7fab4708039300cfa36b0513db55e6ca45b1d7276db1eb02c.wasm",
"tx_unbond.wasm": "tx_unbond.99aacaa049edea0704a147d2feb79702fbae8a014092f41b8483daeff5eee181.wasm",
"tx_unjail_validator.wasm": "tx_unjail_validator.d9fe28aadc5d21d9d0c8e89365e5e8e68420c8f5c15c5c12c8587120822b9ceb.wasm",
"tx_update_vp.wasm": "tx_update_vp.c5706b7f5223deb15f2fae1646ee487948dd0ac25450ca460d9dfa55f29ab2c5.wasm",
"tx_vote_proposal.wasm": "tx_vote_proposal.df21ee966e13f9c5731deea7c8a2ed62612d4706691b35564b058ed175b476ef.wasm",
"tx_withdraw.wasm": "tx_withdraw.cbb043216f2fc75b88a32bd3fbad8a05b48df4c3d6bdbc8284606a71b9be9d38.wasm",
"vp_implicit.wasm": "vp_implicit.c3b78b8b0bb9072a9a4c9e2aa1e89e04db9fdc41eecd53850698bfea89631103.wasm",
"vp_masp.wasm": "vp_masp.8c4ea33db73f13ad9c6efd1634780fd872e7acadb5a615e96f4b2cbbf8626463.wasm",
"vp_testnet_faucet.wasm": "vp_testnet_faucet.403d3d09e582968305223e66a0c35c7b91fd62ac9bc07bab32250bc9120d2114.wasm",
"vp_token.wasm": "vp_token.d1f3cbfd1fccc432e9070b3b94ce1fe21798dc41c557c9201d58d52a02c61337.wasm",
"vp_user.wasm": "vp_user.7514d52275b0d2cb403db04f62656148dbb8570c47d2ec5bd21bb53fa45987a7.wasm",
"vp_validator.wasm": "vp_validator.02eab5750ce4773c2bd350cc642f39aa5d50e58aaa2a2974313329a138335566.wasm"
"tx_bond.wasm": "tx_bond.a98b5b38666d7b28ffb83208086bbffdbf03c8e9d3199ae89db880ea784bc3ab.wasm",
"tx_change_validator_commission.wasm": "tx_change_validator_commission.606a71c0f1dc1e7c2abb54789e4a99787a7c4718c5bd31e9283c02db9c7f42fb.wasm",
"tx_ibc.wasm": "tx_ibc.cd9d2dd7b04f16bf461138491ef2e75fa815ce1e2e6b474f0dfe563fea490a3b.wasm",
"tx_init_account.wasm": "tx_init_account.ce8a35ddc8959b0a73e4a1a6fd226fd0135d7ff0ef4ba517de1cfe53cfce93c0.wasm",
"tx_init_proposal.wasm": "tx_init_proposal.14c1b8b5141101789623fd9ad826b6c3f29cbea4cfad6dec392e6a51fc4e7e66.wasm",
"tx_init_validator.wasm": "tx_init_validator.91ab5b995f11572d043a8f78670dc0f1e3a275c84807f3745eca28757c4c71a3.wasm",
"tx_reveal_pk.wasm": "tx_reveal_pk.e0301b0d4246687110d2f321f158f2465fb6cac1e23c013e88aac89550d26261.wasm",
"tx_transfer.wasm": "tx_transfer.3d5136351aef729e48eb7b3767ec735175b115556abc34f0fb73791bce3fbce9.wasm",
"tx_unbond.wasm": "tx_unbond.9dfdc31ad694e0041b43e5e2230a3afbed0eb0ea121d89af4c850d531e22cf85.wasm",
"tx_unjail_validator.wasm": "tx_unjail_validator.e5d034b4ec784939264dc8fa257a0358ccd2ecb94655f87767d791c446e3dca8.wasm",
"tx_update_vp.wasm": "tx_update_vp.15b6f09d6677c46ab74c4b034ede1d198a42015efe6d78f7fab96e503854ac46.wasm",
"tx_vote_proposal.wasm": "tx_vote_proposal.ff34e5d98abcdf46a9091d81939bfda17cdd118258788c1668d2256e1db4de12.wasm",
"tx_withdraw.wasm": "tx_withdraw.01a1e491a16d7b99317b9127dde518969cf469a2bf76b62fe11dbfc7205e9918.wasm",
"vp_implicit.wasm": "vp_implicit.44390149aa21937fe91db593b242c2810abd316eb4e767eb4eece121f59941cf.wasm",
"vp_masp.wasm": "vp_masp.2502bdf824ce741688d7c153158a56aa49b84d00c6b4835138cfb3506d376f3d.wasm",
"vp_testnet_faucet.wasm": "vp_testnet_faucet.3e222a8ecae546c06e29b056049e9251c99a6d7ec8bd430dce5775be8a4cb268.wasm",
"vp_token.wasm": "vp_token.b34f0386d05f44372368ddd59a463ed2de016be421bd130afb035500b84229f8.wasm",
"vp_user.wasm": "vp_user.bdc2def99d10d3fda732ac2a79639537a2703a496d921f9239776ad08fa66bc2.wasm",
"vp_validator.wasm": "vp_validator.d3b03ce3cab72a0365b380baf972df891154bf42b87a021ec8ac03c888afd731.wasm"
}
Binary file modified wasm_for_tests/tx_memory_limit.wasm
Binary file not shown.
Binary file modified wasm_for_tests/tx_mint_tokens.wasm
Binary file not shown.
Binary file modified wasm_for_tests/tx_no_op.wasm
Binary file not shown.
Binary file modified wasm_for_tests/tx_proposal_code.wasm
Binary file not shown.
Binary file modified wasm_for_tests/tx_read_storage_key.wasm
Binary file not shown.
Binary file modified wasm_for_tests/tx_write.wasm
Binary file not shown.
Binary file removed wasm_for_tests/tx_write_storage_key.wasm
Binary file not shown.
Binary file modified wasm_for_tests/vp_always_false.wasm
Binary file not shown.
Binary file modified wasm_for_tests/vp_always_true.wasm
Binary file not shown.
Binary file modified wasm_for_tests/vp_eval.wasm
Binary file not shown.
Binary file modified wasm_for_tests/vp_memory_limit.wasm
Binary file not shown.
Binary file modified wasm_for_tests/vp_read_storage_key.wasm
Binary file not shown.

0 comments on commit cf8cd4c

Please sign in to comment.