From 3dd85e52f26c8440d7b8f11666a28258ba8a12da Mon Sep 17 00:00:00 2001 From: benluelo Date: Tue, 30 Dec 2025 22:33:19 +0300 Subject: [PATCH] wip --- Cargo.lock | 19 ++++++++ Cargo.toml | 3 ++ cosmwasm/core/Cargo.toml | 4 ++ cosmwasm/core/src/contract.rs | 8 +++- evm/evm.nix | 5 -- flake.nix | 1 + lib/embed-commit/verifier/Cargo.toml | 7 ++- lib/kimlik/Cargo.toml | 19 ++++++++ lib/kimlik/default.nix | 7 +++ lib/kimlik/src/lib.rs | 68 ++++++++++++++++++++++++++++ lib/kimlik/verifier/Cargo.toml | 18 ++++++++ lib/kimlik/verifier/src/lib.rs | 53 ++++++++++++++++++++++ lib/kimlik/verifier/src/main.rs | 27 +++++++++++ tools/rust/buildWasmContract.nix | 18 ++++---- tools/rust/crane.nix | 7 +-- 15 files changed, 242 insertions(+), 22 deletions(-) create mode 100644 lib/kimlik/Cargo.toml create mode 100644 lib/kimlik/default.nix create mode 100644 lib/kimlik/src/lib.rs create mode 100644 lib/kimlik/verifier/Cargo.toml create mode 100644 lib/kimlik/verifier/src/lib.rs create mode 100644 lib/kimlik/verifier/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 5f97eec58ae..2c8fba1c8b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6891,6 +6891,7 @@ dependencies = [ "hex-literal 1.1.0", "ibc-union-msg", "ibc-union-spec", + "kimlik", "serde", "serde-json-wasm", "strum 0.27.2", @@ -7865,6 +7866,24 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57d8d8ce877200136358e0bbff3a77965875db3af755a11e1fa6b1b3e2df13ea" +[[package]] +name = "kimlik" +version = "0.0.0" +dependencies = [ + "cosmwasm-std", + "depolama", +] + +[[package]] +name = "kimlik-verifier" +version = "0.0.0" +dependencies = [ + "anyhow", + "clap", + "embed-commit", + "wasmtime", +] + [[package]] name = "lalrpop" version = "0.19.12" diff --git a/Cargo.toml b/Cargo.toml index 173d04b4aee..fe48fcd9016 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -286,6 +286,8 @@ members = [ "lib/starknet-types", "lib/starknet-light-client-types", "lib/cosmwasm-event", + "lib/kimlik", + "lib/kimlik/verifier", ] [workspace.package] @@ -389,6 +391,7 @@ ibc-union-light-client = { path = "cosmwasm/core/light-client ibc-union-msg = { path = "cosmwasm/core/msg", default-features = false } ibc-union-spec = { path = "lib/ibc-union-spec", default-features = false } ics23 = { path = "lib/ics23", default-features = false } +kimlik = { path = "lib/kimlik", default-features = false } lst = { path = "cosmwasm/lst", default-features = false } lst-staker = { path = "cosmwasm/lst-staker", default-features = false } macros = { path = "lib/macros", default-features = false } diff --git a/cosmwasm/core/Cargo.toml b/cosmwasm/core/Cargo.toml index 3cd0d3fca85..70de3bfd58c 100644 --- a/cosmwasm/core/Cargo.toml +++ b/cosmwasm/core/Cargo.toml @@ -29,6 +29,7 @@ embed-commit = { workspace = true } frissitheto = { workspace = true } ibc-union-msg = { workspace = true } ibc-union-spec = { workspace = true, features = ["ethabi", "serde", "bincode"] } +kimlik = { workspace = true } serde = { workspace = true, features = ["derive"] } serde-json-wasm = { workspace = true } strum = { workspace = true, features = ["derive"] } @@ -39,3 +40,6 @@ upgradable = { workspace = true } [dev-dependencies] access-manager-types = { workspace = true } hex-literal = { workspace = true } + +[build-dependencies] +kimlik = { workspace = true } diff --git a/cosmwasm/core/src/contract.rs b/cosmwasm/core/src/contract.rs index faf5398ed39..db28772aba5 100644 --- a/cosmwasm/core/src/contract.rs +++ b/cosmwasm/core/src/contract.rs @@ -61,6 +61,9 @@ use crate::{ }, }; +#[cfg(not(feature = "library"))] +::kimlik::set_id!("ibc-union"); + type ContractResult = Result; pub mod events { @@ -793,10 +796,13 @@ pub mod version { #[cfg_attr(not(feature = "library"), entry_point)] pub fn migrate( - deps: DepsMut, + #[allow(unused_mut, reason = "used in cfg'd code")] mut deps: DepsMut, _env: Env, msg: UpgradeMsg, ) -> Result { + #[cfg(not(feature = "library"))] + kimlik::check_id(deps.branch())?; + msg.run(deps, init, |_, _, version| match version { version::INIT => Err(StdError::generic_err("unsupported version: INIT").into()), diff --git a/evm/evm.nix b/evm/evm.nix index 09b13d215ca..f8fb38ef6e3 100644 --- a/evm/evm.nix +++ b/evm/evm.nix @@ -3,13 +3,11 @@ _: { { self', pkgs, - proto, nix-filter, ensureAtRepositoryRoot, system, mkCi, gitRev, - dbg, ... }: let @@ -870,7 +868,6 @@ _: { { chain-id, rpc-url, - private-key, verify ? true, verifier ? if verify then throw "verifier must be set in order to verify" else "", @@ -914,8 +911,6 @@ _: { { chain-id, rpc-url, - private-key, - weth, verify ? true, verifier ? if verify then throw "verifier must be set in order to verify" else "", diff --git a/flake.nix b/flake.nix index 3a67a5f7e9d..2bec37e2686 100644 --- a/flake.nix +++ b/flake.nix @@ -235,6 +235,7 @@ ./zkgm-dev/zkgm-dev.nix ./sentinel2/sentinel.nix ./lib/embed-commit + ./lib/kimlik ./networks/services/voyager.nix ./tools/union-test/tests/e2e.nix treefmt-nix.flakeModule diff --git a/lib/embed-commit/verifier/Cargo.toml b/lib/embed-commit/verifier/Cargo.toml index dc5555ead64..6da7aba1774 100644 --- a/lib/embed-commit/verifier/Cargo.toml +++ b/lib/embed-commit/verifier/Cargo.toml @@ -1,8 +1,13 @@ [package] -edition = "2021" name = "embed-commit-verifier" version = "0.0.0" +authors = { workspace = true } +edition = { workspace = true } +license-file = { workspace = true } +publish = false +repository = { workspace = true } + [lints] workspace = true diff --git a/lib/kimlik/Cargo.toml b/lib/kimlik/Cargo.toml new file mode 100644 index 00000000000..edc836f2e9f --- /dev/null +++ b/lib/kimlik/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "kimlik" +version = "0.0.0" + +authors = { workspace = true } +edition = { workspace = true } +license-file = { workspace = true } +publish = { workspace = true } +repository = { workspace = true } + +[package.metadata.kimlik] +id = "test" + +[lints] +workspace = true + +[dependencies] +cosmwasm-std = { workspace = true } +depolama = { workspace = true } diff --git a/lib/kimlik/default.nix b/lib/kimlik/default.nix new file mode 100644 index 00000000000..f1bb925af5f --- /dev/null +++ b/lib/kimlik/default.nix @@ -0,0 +1,7 @@ +_: { + perSystem = + { crane, ... }: + { + packages = crane.buildWorkspaceMember "lib/kimlik/verifier" { }; + }; +} diff --git a/lib/kimlik/src/lib.rs b/lib/kimlik/src/lib.rs new file mode 100644 index 00000000000..3d20daf27df --- /dev/null +++ b/lib/kimlik/src/lib.rs @@ -0,0 +1,68 @@ +use cosmwasm_std::{StdError, StdResult}; +use depolama::{Bytes, Prefix, Store, ValueCodec}; +#[doc(hidden)] +pub use {cosmwasm_std, depolama}; + +#[macro_export] +macro_rules! set_id { + ($KIMLIK:literal) => { + const _: &str = $KIMLIK; + + pub mod kimlik { + use $crate::{ + cosmwasm_std::{DepsMut, StdError, StdResult}, + depolama::StorageExt, + }; + + static KIMLIK: &str = $KIMLIK; + + #[cfg(target_arch = "wasm32")] + #[repr(C)] + struct Id(*const u8, usize); + + #[cfg(target_arch = "wasm32")] + #[unsafe(no_mangle)] + extern "C" fn kimlik() -> Id { + Id(KIMLIK.as_ptr(), KIMLIK.len()) + } + + pub fn check_id(deps: DepsMut) -> StdResult<()> { + deps.storage + .upsert_item::<::kimlik::Kimlik, _>(|maybe_id| match maybe_id { + Some(id) => { + if id == KIMLIK { + Ok(KIMLIK.to_owned()) + } else { + Err(StdError::generic_err(format!( + "invalid kimlik: current id is {id}, but the new id is {KIMLIK}", + ))) + } + } + None => Ok(KIMLIK.to_owned()), + }) + .map(|_| ()) + } + } + }; +} + +pub enum Kimlik {} + +impl Store for Kimlik { + const PREFIX: Prefix = Prefix::new(b"kimlik"); + + type Key = (); + type Value = String; +} + +impl ValueCodec for Kimlik { + fn encode_value(value: &String) -> Bytes { + value.as_bytes().into() + } + + fn decode_value(raw: &Bytes) -> StdResult { + str::from_utf8(raw.as_ref()) + .map_err(|e| StdError::generic_err(format!("invalid kimlik: {e}"))) + .map(ToOwned::to_owned) + } +} diff --git a/lib/kimlik/verifier/Cargo.toml b/lib/kimlik/verifier/Cargo.toml new file mode 100644 index 00000000000..98c36175b82 --- /dev/null +++ b/lib/kimlik/verifier/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "kimlik-verifier" +version = "0.0.0" + +authors = { workspace = true } +edition = { workspace = true } +license-file = { workspace = true } +publish = false +repository = { workspace = true } + +[lints] +workspace = true + +[dependencies] +anyhow = { workspace = true } +clap = { workspace = true, features = ["default", "derive", "env", "error-context", "color"] } +embed-commit = { workspace = true } +wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", rev = "b2e585cfa2992142058e691c1a522b801830bc7b" } # https://github.com/bytecodealliance/wasmtime/pull/10352, https://github.com/bytecodealliance/wasmtime/pull/10330 diff --git a/lib/kimlik/verifier/src/lib.rs b/lib/kimlik/verifier/src/lib.rs new file mode 100644 index 00000000000..b7578d6d917 --- /dev/null +++ b/lib/kimlik/verifier/src/lib.rs @@ -0,0 +1,53 @@ +#![warn(clippy::pedantic, clippy::unwrap_used)] + +use anyhow::{Context, Result}; +use wasmtime::{Engine, Linker, Module, Store}; + +/// Extract the kimlik stored in the provided wasm blob. +/// +/// # Errors +/// +/// This function will return an error if the provided wasm blob does not contain the expected kimlik export. +pub fn extract(bz: &[u8]) -> Result { + let engine = Engine::default(); + let module = Module::from_binary(&engine, bz)?; + let mut linker = Linker::new(&engine); + let mut store: Store<()> = Store::new(&engine, ()); + + // stub all imports as they're unused when evaluating kimlik. + for import in module.imports() { + linker.func_new( + import.module(), + import.name(), + import.ty().unwrap_func().clone(), + |_, _, _| unimplemented!(), + )?; + } + + let instance = linker.instantiate(&mut store, &module)?; + + let kimlik_fn = instance.get_typed_func::(&mut store, "kimlik")?; + + kimlik_fn.call(&mut store, 0)?; + + let memory = instance + .get_memory(&mut store, "memory") + .context("reading memory export")?; + + let ptr = i32::from_le_bytes( + memory.data(&store)[0..4] + .try_into() + .context("reading pointer")?, + ); + let len = i32::from_le_bytes( + memory.data(&store)[4..8] + .try_into() + .context("reading length")?, + ); + + #[allow(clippy::cast_sign_loss)] + let kimlik = str::from_utf8(&memory.data(&store)[(ptr as usize)..((ptr + len) as usize)]) + .context("kimlik is not utf8")?; + + Ok(kimlik.to_owned()) +} diff --git a/lib/kimlik/verifier/src/main.rs b/lib/kimlik/verifier/src/main.rs new file mode 100644 index 00000000000..97df681cf06 --- /dev/null +++ b/lib/kimlik/verifier/src/main.rs @@ -0,0 +1,27 @@ +#![warn(clippy::pedantic, clippy::unwrap_used)] + +use std::path::PathBuf; + +use anyhow::{Context, Result}; +use clap::Parser; +use kimlik_verifier::extract; + +#[derive(Parser)] +enum App { + /// Extract the kimlik id embedded in the provided wasm blob. + Extract { path: PathBuf }, +} + +fn main() -> Result<()> { + match App::parse() { + App::Extract { path } => { + let file = std::fs::read(path).context("reading wasm blob")?; + + let id = extract(&file)?; + + println!("{id}"); + } + } + + Ok(()) +} diff --git a/tools/rust/buildWasmContract.nix b/tools/rust/buildWasmContract.nix index ab607dbd21d..67113acd580 100644 --- a/tools/rust/buildWasmContract.nix +++ b/tools/rust/buildWasmContract.nix @@ -3,10 +3,6 @@ crateCargoToml, pkgs, lib, - craneLib, - rust, - dbg, - gitRev, }: let CARGO_BUILD_TARGET = "wasm32-unknown-unknown"; @@ -32,12 +28,18 @@ let echo "File size: $file_size bytes" fi '') + (file_name: '' + id=$(${ + pkgs.lib.getExe (buildWorkspaceMember "lib/kimlik/verifier" { }).kimlik-verifier + } extract "${file_name}") + + echo "Contract ID: $id" + '') ] ]; cargoBuildInstallPhase = { - features, contractFileNameWithoutExt, checks, maxSize, @@ -89,11 +91,7 @@ let rustflags = mkRustflags buildWithOz; cargoBuildInstallPhase = cargoBuildInstallPhase { - inherit - features - checks - maxSize - ; + inherit checks maxSize; contractFileNameWithoutExt = contract-basename; }; extraEnv = { diff --git a/tools/rust/crane.nix b/tools/rust/crane.nix index 37fbdc1adfa..7eb76dc4b1a 100644 --- a/tools/rust/crane.nix +++ b/tools/rust/crane.nix @@ -1,8 +1,9 @@ # cspell:ignore tomls -{ inputs, ... }: +{ inputs, self, ... }: { perSystem = args@{ + system, pkgsUnstable, pkgs, rust, @@ -635,10 +636,6 @@ crateCargoToml pkgs lib - rust - craneLib - dbg - gitRev ; };