Skip to content
Draft

wip #5363

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
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ members = [
"lib/starknet-types",
"lib/starknet-light-client-types",
"lib/cosmwasm-event",
"lib/kimlik",
"lib/kimlik/verifier",
]

[workspace.package]
Expand Down Expand Up @@ -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 }
Expand Down
4 changes: 4 additions & 0 deletions cosmwasm/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand All @@ -39,3 +40,6 @@ upgradable = { workspace = true }
[dev-dependencies]
access-manager-types = { workspace = true }
hex-literal = { workspace = true }

[build-dependencies]
kimlik = { workspace = true }
8 changes: 7 additions & 1 deletion cosmwasm/core/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ use crate::{
},
};

#[cfg(not(feature = "library"))]
::kimlik::set_id!("ibc-union");

type ContractResult = Result<Response, ContractError>;

pub mod events {
Expand Down Expand Up @@ -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<InitMsg, MigrateMsg>,
) -> Result<Response, ContractError> {
#[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()),

Expand Down
5 changes: 0 additions & 5 deletions evm/evm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ _: {
{
self',
pkgs,
proto,
nix-filter,
ensureAtRepositoryRoot,
system,
mkCi,
gitRev,
dbg,
...
}:
let
Expand Down Expand Up @@ -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 "",
Expand Down Expand Up @@ -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 "",
Expand Down
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion lib/embed-commit/verifier/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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

Expand Down
19 changes: 19 additions & 0 deletions lib/kimlik/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 }
7 changes: 7 additions & 0 deletions lib/kimlik/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
_: {
perSystem =
{ crane, ... }:
{
packages = crane.buildWorkspaceMember "lib/kimlik/verifier" { };
};
}
68 changes: 68 additions & 0 deletions lib/kimlik/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<String> for Kimlik {
fn encode_value(value: &String) -> Bytes {
value.as_bytes().into()
}

fn decode_value(raw: &Bytes) -> StdResult<String> {
str::from_utf8(raw.as_ref())
.map_err(|e| StdError::generic_err(format!("invalid kimlik: {e}")))
.map(ToOwned::to_owned)
}
}
18 changes: 18 additions & 0 deletions lib/kimlik/verifier/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
53 changes: 53 additions & 0 deletions lib/kimlik/verifier/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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<String> {
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::<i32, ()>(&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())
}
27 changes: 27 additions & 0 deletions lib/kimlik/verifier/src/main.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
18 changes: 8 additions & 10 deletions tools/rust/buildWasmContract.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
crateCargoToml,
pkgs,
lib,
craneLib,
rust,
dbg,
gitRev,
}:
let
CARGO_BUILD_TARGET = "wasm32-unknown-unknown";
Expand All @@ -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,
Expand Down Expand Up @@ -89,11 +91,7 @@ let
rustflags = mkRustflags buildWithOz;

cargoBuildInstallPhase = cargoBuildInstallPhase {
inherit
features
checks
maxSize
;
inherit checks maxSize;
contractFileNameWithoutExt = contract-basename;
};
extraEnv = {
Expand Down
Loading
Loading