diff --git a/.changelog/unreleased/improvements/4690-wasm-name-lookups.md b/.changelog/unreleased/improvements/4690-wasm-name-lookups.md new file mode 100644 index 00000000000..9a376c6dfae --- /dev/null +++ b/.changelog/unreleased/improvements/4690-wasm-name-lookups.md @@ -0,0 +1 @@ +- Indexers fail to identify the types of older txs since these types use wasm hashes. If those hashes were overwritten by governance proposals, the indexer is unable to determine how to deserialize these txs. This PR adds a new key to storage which allows looking up a tx type from a wasm hash, even if that hash is of code no longer in use. ([\#4690](https://github.com/anoma/namada/pull/4690)) diff --git a/crates/core/src/storage.rs b/crates/core/src/storage.rs index 2ac9959df1f..91c66dbe488 100644 --- a/crates/core/src/storage.rs +++ b/crates/core/src/storage.rs @@ -551,7 +551,7 @@ impl Key { } /// Returns a key of wasm code's hash of the given name - pub fn wasm_code_name(code_name: String) -> Self { + pub fn wasm_code_hash(code_name: String) -> Self { let mut segments = Self::from(PARAMETERS.to_owned().to_db_key()).segments; segments.push(DbKeySeg::StringSeg(WASM_KEY_PREFIX.to_owned())); @@ -580,6 +580,16 @@ impl Key { Key { segments } } + /// Returns a key of the wasm name of the given code hash + pub fn wasm_code_name(code_hash: &Hash) -> Self { + let mut segments = + Self::from(PARAMETERS.to_owned().to_db_key()).segments; + segments.push(DbKeySeg::StringSeg(WASM_KEY_PREFIX.to_owned())); + segments.push(DbKeySeg::StringSeg(WASM_HASH_PREFIX.to_owned())); + segments.push(DbKeySeg::StringSeg(code_hash.to_string())); + Key { segments } + } + /// Returns a key of the validity predicate of the given address /// Only this function can push "?" segment for validity predicate pub fn validity_predicate(addr: &Address) -> Self { diff --git a/crates/migrations/src/foreign_types.rs b/crates/migrations/src/foreign_types.rs index 9f31ecfbd08..7b7dd50c0b8 100644 --- a/crates/migrations/src/foreign_types.rs +++ b/crates/migrations/src/foreign_types.rs @@ -8,6 +8,7 @@ use namada_macros::derive_typehash; use crate::TypeHash; +derive_typehash!(String); derive_typehash!(Vec::); derive_typehash!(Vec::); derive_typehash!(u64); diff --git a/crates/node/src/shell/init_chain.rs b/crates/node/src/shell/init_chain.rs index e14d0d7ac87..171c375ffad 100644 --- a/crates/node/src/shell/init_chain.rs +++ b/crates/node/src/shell/init_chain.rs @@ -418,7 +418,8 @@ where let code_key = Key::wasm_code(&code_hash); let code_len_key = Key::wasm_code_len(&code_hash); let hash_key = Key::wasm_hash(name); - let code_name_key = Key::wasm_code_name(name.to_owned()); + let code_hash_key = Key::wasm_code_hash(name.to_owned()); + let code_name_key = Key::wasm_code_name(&code_hash); self.state.write(&code_key, code).unwrap(); self.state.write(&code_len_key, code_len).unwrap(); @@ -426,7 +427,8 @@ where if &Some(code_hash) == implicit_vp_code_hash { is_implicit_vp_stored = true; } - self.state.write(&code_name_key, code_hash).unwrap(); + self.state.write(&code_hash_key, code_hash).unwrap(); + self.state.write(&code_name_key, name).unwrap(); } else { tracing::warn!("The wasm {name} isn't allowed."); self.warn(Warning::DisallowedWasm(name.to_string())); diff --git a/crates/tx/src/data/mod.rs b/crates/tx/src/data/mod.rs index 5121d8bf152..433f54f9401 100644 --- a/crates/tx/src/data/mod.rs +++ b/crates/tx/src/data/mod.rs @@ -772,7 +772,7 @@ mod test_process_tx { let batched_result = BatchedTxResult { changed_keys: [ - namada_account::Key::wasm_code_name("test-name".to_string()), + namada_account::Key::wasm_code_hash("test-name".to_string()), namada_account::Key::wasm_hash("test-name"), ] .into(), diff --git a/examples/make-db-migration.rs b/examples/make-db-migration.rs index a86828f7eea..e9d767f9283 100644 --- a/examples/make-db-migration.rs +++ b/examples/make-db-migration.rs @@ -592,7 +592,8 @@ pub fn wasm_migration(updates: &mut Vec) { let code_key = Key::wasm_code(&new_code_hash); let code_len_key = Key::wasm_code_len(&new_code_hash); let hash_key = Key::wasm_hash(name); - let code_name_key = Key::wasm_code_name(name.to_owned()); + let code_hash_key = Key::wasm_code_hash(name.to_owned()); + let code_name_key = Key::wasm_code_name(&new_code_hash); updates.push(migrations::DbUpdateType::Add { key: code_key, @@ -613,11 +614,17 @@ pub fn wasm_migration(updates: &mut Vec) { force: false, }); updates.push(migrations::DbUpdateType::Add { - key: code_name_key, + key: code_hash_key, cf: DbColFam::SUBSPACE, value: new_code_hash.into(), force: false, }); + updates.push(migrations::DbUpdateType::Add { + key: code_name_key, + cf: DbColFam::SUBSPACE, + value: name.to_string().into(), + force: false, + }); } // Put the allow list in storage updates.push(migrations::DbUpdateType::Add { diff --git a/wasm_for_tests/tx_proposal_code/src/lib.rs b/wasm_for_tests/tx_proposal_code/src/lib.rs index 3996e41fbec..8221b7e4230 100644 --- a/wasm_for_tests/tx_proposal_code/src/lib.rs +++ b/wasm_for_tests/tx_proposal_code/src/lib.rs @@ -26,8 +26,11 @@ fn apply_tx(ctx: &mut Ctx, _tx_data: BatchedTx) -> TxResult { let wasm_code_len_key = Key::wasm_code_len(&wasm_code_hash); ctx.write(&wasm_code_len_key, 30.serialize_to_vec())?; - let wasm_code_name_key = Key::wasm_code_name("test".to_string()); - ctx.write_bytes(&wasm_code_name_key, wasm_code_name.clone())?; + let wasm_code_hash_key = Key::wasm_code_hash("test".to_string()); + ctx.write_bytes(&wasm_code_hash_key, wasm_code_hash)?; + + let wasm_code_name_key = Key::wasm_code_name(&wasm_code_hash); + ctx.write_bytes(&wasm_code_name_key, &wasm_code_name)?; let wasm_hash_key = Key::wasm_hash("test"); ctx.write_bytes(&wasm_hash_key, wasm_code_name)?;