Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

established addr use full sha256 hash for generation #1510

Merged
merged 6 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.e72837fe265346308458d4e5f2399633bcf553ea13679434ea54fa578c13a912.wasm",
"tx_change_validator_commission.wasm": "tx_change_validator_commission.4006b3a3251970b40290e1c898809ac914f9450c1f82e3026fdadca96eb42810.wasm",
"tx_ibc.wasm": "tx_ibc.012d3f1da7532f3ff92bb56499c349ea3e5b6abaf4bdb7b8faa0177bf7ea2b93.wasm",
"tx_init_account.wasm": "tx_init_account.6359caa0d6fda1d896b84a881351c6827aca66240988b438697c966dec231be2.wasm",
"tx_init_proposal.wasm": "tx_init_proposal.339f4454df0be8ae670c5df84645c7b156f478726dc1e964a93cea4f8b6a4651.wasm",
"tx_init_validator.wasm": "tx_init_validator.a45ef2fc87cf2760107cd682a34772207da3ee96de778e5e83f22256df99ff7d.wasm",
"tx_reveal_pk.wasm": "tx_reveal_pk.b7541013221fedb42d9bdd4be6e972deac147b8c930b03db282f0b7811198554.wasm",
"tx_transfer.wasm": "tx_transfer.8b6fb1f418fea7d8909ed45160b9614f6ff50421fd766ce7ac9c1767af848aa7.wasm",
"tx_unbond.wasm": "tx_unbond.7f4c904a13ec2d4716457290a5af1f2f8853ccb817276583fccb33a63add07bd.wasm",
"tx_unjail_validator.wasm": "tx_unjail_validator.aadc50cd196eb818dd3f743c1be3f2973e9fdcbe9f1d7334dedbfee38f822ccc.wasm",
"tx_update_vp.wasm": "tx_update_vp.e5d25854a23186925caa2169869b1505e29132b8a8b396e911379d53ce5cf418.wasm",
"tx_vote_proposal.wasm": "tx_vote_proposal.22b3358af6611d1786f6d49ccbf0757e3065a43fb37e8df0055f2173c8e14653.wasm",
"tx_withdraw.wasm": "tx_withdraw.04b5fe0ffb4c873a8d839ededcc616658e88af346a5c6a709c37eec8088486b4.wasm",
"vp_implicit.wasm": "vp_implicit.1e8355b50da06a5dcf9d2a8ab8ddc440f486ce039538dee415ab8625b1b11bae.wasm",
"vp_masp.wasm": "vp_masp.7487613c4391eef753360c55e63979fad3855259f2fdb0e945fe702342ef5979.wasm",
"vp_testnet_faucet.wasm": "vp_testnet_faucet.d3cafc4d31f1081a8cedfbfdb45e674235231716668a6b1309beece16fe5ea5d.wasm",
"vp_token.wasm": "vp_token.495362b8949a5f77da12c5562c38e25584a7477cf6e1b229a8b209a67e6504d0.wasm",
"vp_user.wasm": "vp_user.c7b65fe31adb835d341ef82a6f02f72ee6c6bf457c22ad24422acb3d54387517.wasm",
"vp_validator.wasm": "vp_validator.64283182a94de72f35364414040f780c2d51d629e73e915f1803c9e71a2f5fd2.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"
}
2 changes: 1 addition & 1 deletion wasm/wasm_source/src/vp_implicit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ mod tests {
tx_env.store_wasm_code(vp_code);

// hardcoded hash of VP_ALWAYS_TRUE_WASM
tx_env.init_parameters(None, None, Some(vec!["2AC0BCB5D9E2019180F99BEB84A77E32728CDABAAD8C4F0EF3762594EC836A9D".to_string()]));
tx_env.init_parameters(None, None, Some(vec!["944A06740903B2EAB1FECAC4BFA25DD48330689A0F9D69C79C05B151C039CBAC".to_string()]));

// Spawn the accounts to be able to modify their storage
tx_env.spawn_accounts([&vp_owner]);
Expand Down
2 changes: 1 addition & 1 deletion wasm/wasm_source/src/vp_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ mod tests {
tx_env.store_wasm_code(vp_code);

// hardcoded hash of VP_ALWAYS_TRUE_WASM
tx_env.init_parameters(None, None, Some(vec!["2AC0BCB5D9E2019180F99BEB84A77E32728CDABAAD8C4F0EF3762594EC836A9D".to_string()]));
tx_env.init_parameters(None, None, Some(vec!["944A06740903B2EAB1FECAC4BFA25DD48330689A0F9D69C79C05B151C039CBAC".to_string()]));

// Spawn the accounts to be able to modify their storage
tx_env.spawn_accounts([&vp_owner]);
Expand Down
2 changes: 1 addition & 1 deletion wasm/wasm_source/src/vp_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ mod tests {
tx_env.store_wasm_code(vp_code);

// hardcoded hash of VP_ALWAYS_TRUE_WASM
tx_env.init_parameters(None, None, Some(vec!["2AC0BCB5D9E2019180F99BEB84A77E32728CDABAAD8C4F0EF3762594EC836A9D".to_string()]));
tx_env.init_parameters(None, None, Some(vec!["944A06740903B2EAB1FECAC4BFA25DD48330689A0F9D69C79C05B151C039CBAC".to_string()]));

// Spawn the accounts to be able to modify their storage
tx_env.spawn_accounts([&vp_owner]);
Expand Down
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 modified 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.