Skip to content

Commit

Permalink
add edwards WIT example component & tests
Browse files Browse the repository at this point in the history
to use the seed keeper and it's WIT, we'll need a consumer of the get_seed who will use it for signing.

So let's build an example using Ed25519 curve
  • Loading branch information
DougAnderson444 committed Dec 20, 2023
1 parent 6183fcb commit 28d4381
Show file tree
Hide file tree
Showing 9 changed files with 482 additions and 1 deletion.
131 changes: 131 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = [".", "crates/*"]
members = [".", "crates/*", "examples/edwards-wit"]
resolver = "2"

[workspace.dependencies]
Expand Down
3 changes: 3 additions & 0 deletions examples/edwards-wit/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"rust-analyzer.check.overrideCommand": ["cargo", "component", "check", "--message-format=json"]
}
26 changes: 26 additions & 0 deletions examples/edwards-wit/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "edwards-wit"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
cargo-component-bindings = "0.5.0"
ed25519-dalek = "2.1"

[dev-dependencies]
wasmtime = { version = "15", features = ['component-model'] }
wasmtime-wasi = "15.0.0"
thiserror = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

[package.metadata.component]
package = "component:edwards-wit"

[package.metadata.component.dependencies]

[package.metadata.component.target.dependencies]
"seed-keeper:wallet" = { path = "../../crates/seed-keeper-wit/wit" } # directory containing the WIT package
44 changes: 44 additions & 0 deletions examples/edwards-wit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Example Plugin

Usign Edwards curve to sign a message and verify the signature.

## Create a Plugin WIT Component

1. Create a component using [`cargo component`](https://github.com/bytecodealliance/cargo-component):

```bash
cargo component new --reactor <name>
```

2. Import the seed keeper get seed interface

```wit
world yourworld {
import seed-keeper:wallet/[email protected];
// the rest of your WIT world
export operations;
}
```

3. Add the path to the wallet wit file in your Cargo.toml. This is just the interface, not the implementation of it.

```toml
[package.metadata.component.target.dependencies]
"seed-keeper:wallet" = { path = "../path/to/seed-keeper-wit/wit" } # directory containing the WIT package
```

4. Export an interface which defines a `sign` func which takes a message and returns a signature.

```wit
/// WIT interface operations exported by yourworld
interface operations {
sign: func(message: list<u8>) -> list<u8>;
verify: func(message: list<u8>, signature: list<u8>) -> bool;
}
```

## Compose

Compose this plugin together with the `seed-keeper-wit` and the `seed-keeper-wit-ui` components.
63 changes: 63 additions & 0 deletions examples/edwards-wit/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
cargo_component_bindings::generate!();

use bindings::exports::component::edwards_wit::operations::Guest;
// use bindings::seed_keeper::wallet::seed_getter::get_seed;

use ed25519_dalek::SECRET_KEY_LENGTH;
use ed25519_dalek::{Signature, Signer, SigningKey};

struct Component;

impl Guest for Component {
/// Say hello!
/// sign: func(message: list<u8>) -> list<u8>;
fn sign(message: Vec<u8>) -> Result<Vec<u8>, String> {
let seed = [1u8; 32]; // get_seed()?;
let seed: [u8; SECRET_KEY_LENGTH] = seed
.clone()
.try_into()
.map_err(|_| format!("Seed length is not 32 bytes, got {}", seed.len()).to_owned())?;
let signer = SigningKey::from_bytes(&seed);
let signature: Signature = signer.sign(&message);
Ok(signature.to_bytes().to_vec())
}

/// Verify
/// verify: func(message: list<u8>, signature: list<u8>) -> bool;
fn verify(message: Vec<u8>, signature: Vec<u8>) -> Result<bool, String> {
let seed = [1u8; 32]; // get_seed()?;
let seed: [u8; SECRET_KEY_LENGTH] = seed
.clone()
.try_into()
.map_err(|_| format!("Seed length is not 32 bytes, got {}", seed.len()).to_owned())?;
let signer = SigningKey::from_bytes(&seed);
let signature = Signature::from_bytes(
&(signature.clone().try_into().map_err(|_| {
format!("Signature length is not 64 bytes, got {}", signature.len()).to_owned()
})?),
);
Ok(signer.verify(&message, &signature).is_ok())
}
}

#[cfg(test)]
mod test_edwards_wit {
use super::*;

fn assert_keypair(keypair: &SigningKey) -> bool {
let message: &[u8] = b"This is a test of the tsunami alert system.";
let signature: Signature = keypair.sign(message);
keypair.verify(message, &signature).is_ok()
}

#[test]
fn test_keypair_from_seed() {
let seed: [u8; 32] = [
0x9d, 0x61, 0xb1, 0x9d, 0xef, 0xfd, 0x5a, 0x60, 0xba, 0x84, 0x4a, 0xf4, 0x92, 0xec,
0x2c, 0xc4, 0x44, 0x49, 0xc5, 0x69, 0x34, 0x67, 0x2b, 0x6a, 0x2f, 0x8d, 0x1d, 0x7b,
0x10, 0xac, 0x39, 0x23,
];
let keypair = SigningKey::from_bytes(&seed);
assert_keypair(&keypair);
}
}
Loading

0 comments on commit 28d4381

Please sign in to comment.