Skip to content

Commit

Permalink
feat(unionlabs): parse wasm client type from wasm blob
Browse files Browse the repository at this point in the history
  • Loading branch information
hussein-aitlahcen committed Sep 26, 2023
1 parent 7c3c9bb commit 4b01ca4
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions lib/unionlabs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ ethers-core = { version = "2.0.8", optional = true }
serde_json = { version = "1.0.96", optional = true }
bitvec = "1.0.1"

wasmparser = { version = "0.113" }

paste = { version = "1.0" }

[dev-dependencies]
rand = "0.8.5"
serde_json = "1.0.96"
Expand Down
60 changes: 60 additions & 0 deletions lib/unionlabs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,3 +654,63 @@ impl<'de> Deserialize<'de> for EmptyString {
impl traits::Id for EmptyString {
type FromStrErr = EmptyStringParseError;
}

pub use paste::paste;

#[macro_export]
macro_rules! export_wasm_client_type {
($type:ident) => {
const _: unionlabs::WasmClientType = unionlabs::WasmClientType::$type;
unionlabs::paste! {
#[no_mangle]
#[used]
static [ <WASM_CLIENT_TYPE_ $type> ]: u8 = 0;
}
#[no_mangle]
#[used]
static WASM_CLIENT_TYPE_DEFINED: u8 = 0;
};
}

/// This type is used to discrimate 08-wasm light clients.
/// We need to be able to determine the light client from the light client code itself (not instantiated yet).
/// Light clients supported by voyager must export a `#[no_mangle] static WASM_CLIENT_TYPE: WasmClientType = WasmClientType::...` variable.
#[derive(Debug, PartialEq, Eq)]
pub enum WasmClientType {
EthereumMinimal,
EthereumMainnet,
Cometbls,
}

impl TryFrom<&[u8]> for WasmClientType {
type Error = ();
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let wasm_type_name = wasmparser::Parser::new(0)
.parse_all(value)
.find_map(|payload| {
payload.ok().and_then(|payload| match payload {
wasmparser::Payload::ExportSection(e) => Some(e),
_ => None,
})
})
.and_then(|exports| {
exports.into_iter().find_map(|export| {
export.ok().and_then(|export| {
if let Some(type_name) = export.name.strip_prefix("WASM_CLIENT_TYPE_")
{
Some(type_name)
} else {
None
}
})
})
})
.ok_or(())?;
Ok(match wasm_type_name {
"EthereumMinimal" => WasmClientType::EthereumMinimal,
"EthereumMainnet" => WasmClientType::EthereumMainnet,
"Cometbls" => WasmClientType::Cometbls,
_ => Err(())?,
})
}
}

0 comments on commit 4b01ca4

Please sign in to comment.