Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDK usage in qemu-example #38

Merged
merged 1 commit into from Feb 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 5 additions & 5 deletions .gitignore
@@ -1,7 +1,7 @@
# Generated by Cargo
# will have compiled files and executables
**/target/

.idea/
*.iml

# These are backup files generated by rustfmt
**/debug/
**/target/
Cargo.lock
**/*.rs.bk
1 change: 1 addition & 0 deletions cardano-sdk-playground/Cargo.toml → Cargo.toml
Expand Up @@ -2,4 +2,5 @@
members = [
"cardano-embedded-sdk",
"rust-ed25519-bip32",
"qemu-example",
]
Expand Up @@ -4,12 +4,12 @@ version = "0.1.0"
edition = "2021"

[dependencies]
bech32 = { version = "0.7.2", default-features = false }
bech32 = { version = "0.9.1", default-features = false }
cryptoxide = { version = "0.4.2", default-features = false }
ed25519-bip32 = { version = "0.4.1", path = "../rust-ed25519-bip32" }
hex = { version = "0.4.0", features = ["alloc"], default-features = false }
rand_core = { version = "0.6.4", default-features = false }
derivation-path = "0.2.0"
derivation-path = { version = "0.2.0", default-features = false }

cfg-if = "1.0.0"

Expand Down
Expand Up @@ -3,7 +3,7 @@ use core::error::Error as StdError;
use core::fmt;
use core::result::Result as StdResult;

use bech32::{Error as Bech32Error, FromBase32, ToBase32};
use bech32::{Error as Bech32Error, FromBase32, ToBase32, Variant};

pub type Result<T> = StdResult<T, Error>;

Expand All @@ -18,12 +18,12 @@ pub trait Bech32 {
}

pub fn to_bech32_from_bytes<B: Bech32>(bytes: &[u8]) -> String {
bech32::encode(B::BECH32_HRP, bytes.to_base32())
bech32::encode(B::BECH32_HRP, bytes.to_base32(), Variant::Bech32)
.unwrap_or_else(|e| panic!("Failed to build bech32: {e}"))
}

pub fn try_from_bech32_to_bytes<B: Bech32>(bech32_str: &str) -> Result<Vec<u8>> {
let (hrp, bech32_data) = bech32::decode(bech32_str)?;
let (hrp, bech32_data, _) = bech32::decode(bech32_str)?;
if hrp != B::BECH32_HRP {
return Err(Error::HrpInvalid {
expected: B::BECH32_HRP,
Expand Down Expand Up @@ -71,7 +71,7 @@ impl fmt::Display for Error {
impl StdError for Error {
fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self {
Error::Bech32Malformed(cause) => Some(cause),
Error::Bech32Malformed(_cause) => None, // TODO: fix, Some(cause),
Error::DataInvalid(cause) => Some(&**cause),
_ => None,
}
Expand Down
Expand Up @@ -10,7 +10,7 @@ use crate::impl_mockchain as chain;
use chain::key;
use crypto::bech32::Bech32 as _;

use bech32::ToBase32;
use bech32::{ToBase32, Variant};
use cryptoxide::blake2b::Blake2b;
use rand_core::{CryptoRng, RngCore};

Expand Down Expand Up @@ -449,7 +449,7 @@ macro_rules! impl_hash_type {
}

pub fn to_bech32(&self, prefix: &str) -> Result<String, JsError> {
bech32::encode(&prefix, self.to_bytes().to_base32())
bech32::encode(&prefix, self.to_bytes().to_base32(), Variant::Bech32)
.map_err(|e| JsError::from_str(&format! {"{:?}", e}))
}

Expand Down
6 changes: 0 additions & 6 deletions cardano-sdk-playground/.gitignore

This file was deleted.

4 changes: 2 additions & 2 deletions flake.nix
Expand Up @@ -65,8 +65,8 @@
}
''
echo $(cargo version)
cd ${./.}/cardano-sdk-playground
cargo fmt -p cardano-embedded-sdk --check
cd ${./.}/cardano-embedded-sdk
cargo fmt --check
touch $out
'';

Expand Down
3 changes: 3 additions & 0 deletions qemu-example/Cargo.toml
Expand Up @@ -13,6 +13,9 @@ panic-halt = "0.2.0"
# bip32-ed25519 = { git = "https://github.com/digitalbitbox/rust-bip32-ed25519", tag = "v0.1.0", optional = true }
bip32-ed25519 = { git = "https://github.com/digitalbitbox/rust-bip32-ed25519", tag = "v0.1.0" }

cardano-embedded-sdk = { vestion = "0.1.0", path = "../cardano-embedded-sdk" }
derivation-path = { version = "0.2.0", default-features = false }

# Uncomment for the panic example.
# panic-itm = "0.4.1"

Expand Down
74 changes: 62 additions & 12 deletions qemu-example/src/main.rs
Expand Up @@ -10,34 +10,84 @@ use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch

// use cortex_m::asm;
use alloc_cortex_m::CortexMHeap;
use bip32_ed25519::{Xprv, ED25519_EXPANDED_SECRET_KEY_SIZE};
use core::alloc::Layout;
use cortex_m_rt::entry;
use cortex_m_semihosting::{debug, hprintln};

use cardano_embedded_sdk::api as embedano;
use cardano_embedded_sdk::bip::bip39::{dictionary, Entropy, Mnemonics};
use cardano_embedded_sdk::types::{harden, TxId, XPrvKey};
use derivation_path::DerivationPath;

#[global_allocator]
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();

const HEAP_SIZE: usize = 1024; // in bytes

const TEST_SEED: &[u8] = b"\xf8\xcb\x28\x85\x37\x60\x2b\x90\xd1\x29\x75\x4b\xdd\x0e\x4b\xed\xf9\xe2\x92\x3a\x04\xb6\x86\x7e\xdb\xeb\xc7\x93\xa7\x17\x6f\x5d\xca\xc5\xc9\x5d\x5f\xd2\x3a\x8e\x01\x6c\x95\x57\x69\x0e\xad\x1f\x00\x2b\x0f\x35\xd7\x06\xff\x8e\x59\x84\x1c\x09\xe0\xb6\xbb\x23\xf0\xa5\x91\x06\x42\xd0\x77\x98\x17\x40\x2e\x5e\x7a\x75\x54\x95\xe7\x44\xf5\x5c\xf1\x1e\x49\xee\xfd\x22\xa4\x60\xe9\xb2\xf7\x53";

#[entry]
fn main() -> ! {
hprintln!("Test: Generating keys");
hprintln!("Test: Generating keys").unwrap();

// from example/allocator.rs
unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) }

let root_xprv_key = Xprv::from_normalize(
&TEST_SEED[..ED25519_EXPANDED_SECRET_KEY_SIZE],
&TEST_SEED[ED25519_EXPANDED_SECRET_KEY_SIZE..],
);
let mnemonics = "aim wool into nose tell ball arm expand design push elevator multiply glove lonely minimum";
let mnemonics = Mnemonics::from_string(&dictionary::ENGLISH, mnemonics).unwrap();

let password = b"embedano";
let entropy = Entropy::from_mnemonics(&mnemonics).unwrap();

// Make derivation path for account 0 and address 0 according to CIP-1852
let path: DerivationPath = "m/1852'/1815'/0'/0/0".parse().unwrap();

// Try to parse transaction id and sign it
let tx_id =
TxId::from_hex("bb1eb401cd03b0cd8caa08997df0a2ab226772c4d3a08adfb5a60ba34de12dfb").unwrap();
let signature = embedano::sign_tx_id(&tx_id, &entropy, password, &path);

// Derive key pair using same path ant try to verify signature from `sign_tx_id`
let (_prv_key, pub_key) = embedano::derive_key_pair(&entropy, password, &path);
assert!(pub_key.verify(tx_id.to_bytes(), &signature));

// Check if public key can be derived from given entropy by signing nonce
let nonce = b"some nonce";
// Define what key type of public key we pass to prove function.
// This will affect what address derivation will be used and how many indexes will be checked.
// As earlier we used derivation path "m/1852'/1815'/0'/0/0" to make keys,
// `pub_key` corresponds to address 0 of account 0 so as `key_type`.
let key_type = embedano::KeyType::AddressKey {
account_gap: 5,
address_gap: 5,
};
let proof_sig =
embedano::prove_ownership(nonce, &pub_key, &entropy, password, key_type).unwrap();
// If we got Some(signature), then we can verify proof with public key we tested.
assert!(pub_key.verify(nonce, &proof_sig));

// Function above defined on top of types in `types.rs` that can provide more fine grinded control.
// E.g.:

// Create root private key from entropy
let root_key = XPrvKey::from_entropy(&entropy, password);
hprintln!("Root key: {}", root_key.to_hex()).unwrap();

// Derive private key for same path that was used in `derive_key_pair` above
let prv_key = root_key
.derive(harden(1852))
.derive(harden(1815))
.derive(harden(0))
.derive(0)
.derive(0);
hprintln!("Private key: {}", prv_key.to_hex()).unwrap();

let root_xpub_key = root_xprv_key.public();
// Derive corresponding public key
let pub_key = prv_key.to_public();
hprintln!("Public key: {}", pub_key.to_hex()).unwrap();

hprintln!("XPrv: {:?}", root_xprv_key).unwrap();
hprintln!("XPub: {:?}", root_xpub_key.pubkey_bytes()).unwrap();
// Sign and verify using derived keys
let some_data = b"some data";
let signature = prv_key.sign(some_data);
hprintln!("Verify: {}", pub_key.verify(some_data, &signature)).unwrap();

debug::exit(debug::EXIT_SUCCESS);

Expand All @@ -48,7 +98,7 @@ fn main() -> ! {
fn alloc_error(_layout: Layout) -> ! {
hprintln!("ALLOC ERROR").unwrap();
debug::exit(debug::EXIT_FAILURE);
let f: [u32] = todo!();
//let f: [u32] = todo!();

loop {}
}