Skip to content
This repository has been archived by the owner on Jan 16, 2025. It is now read-only.

Put all return values in a buffer and remove json #118

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
Binary file modified assets/dusk_wallet_core.wasm
Binary file not shown.
44 changes: 19 additions & 25 deletions src/compat/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//
// Copyright (c) DUSK NETWORK. All rights reserved.

use core::mem::size_of;
use core::{array, cmp, mem::size_of};

use dusk_bls12_381::BlsScalar;
use dusk_bytes::Serializable;
Expand All @@ -13,9 +13,9 @@ use phoenix_core::{
Note, PublicKey, SecretKey, ViewKey,
};

use alloc::{string::ToString, vec::Vec};
use alloc::vec::Vec;

use crate::alloc::borrow::ToOwned;
use crate::utils::compose;
use crate::{
key::{self},
types::{self},
Expand All @@ -27,6 +27,10 @@ const TREE_LEAF_SIZE: usize = size_of::<ArchivedTreeLeaf>();

/// Returns true or false if the note is owned by the index
/// if its true then nullifier of that note if sent with it
///
/// Return buffer: [block_height: (u64 big endian bytes), key: (string
/// bytes), nullifier: (rkyv serialized bytes), note: (rkyv serialized
/// bytes)...lastPosition: (u64 big endian bytes)]
#[no_mangle]
pub fn check_note_ownership(args: i32, len: i32) -> i64 {
// SAFETY: We assume the caller has passed a valid pointer and len as the
Expand All @@ -43,14 +47,12 @@ pub fn check_note_ownership(args: i32, len: i32) -> i64 {
let mut leaf_chunk = leaves.chunks_exact(TREE_LEAF_SIZE);
let mut last_pos = 0;

let mut notes = Vec::new();
let mut nullifiers = Vec::new();
let mut block_heights = Vec::new();
let mut public_spend_keys = Vec::new();
let mut buffer = Vec::new();

let view_keys: [ViewKey; MAX_KEY] =
core::array::from_fn(|i| key::derive_vk(&seed, i as _));
let secret_keys: [SecretKey; MAX_KEY] =
core::array::from_fn(|i| key::derive_sk(&seed, i as _));
array::from_fn(|i| key::derive_sk(&seed, i as _));

for leaf_bytes in leaf_chunk.by_ref() {
let TreeLeaf { block_height, note } = match rkyv::from_bytes(leaf_bytes)
Expand All @@ -61,7 +63,7 @@ pub fn check_note_ownership(args: i32, len: i32) -> i64 {
}
};

last_pos = core::cmp::max(last_pos, *note.pos());
last_pos = cmp::max(last_pos, *note.pos());

for idx in 0..MAX_KEY {
if view_keys[idx].owns(&note) {
Expand All @@ -84,27 +86,19 @@ pub fn check_note_ownership(args: i32, len: i32) -> i64 {
Err(_) => return utils::fail(),
};

notes.push(raw_note.to_owned());
block_heights.push(block_height);
public_spend_keys.push(psk_found);
nullifiers.push(nullifier_found);
buffer.extend_from_slice(&block_height.to_be_bytes());
buffer.extend_from_slice(&psk_found.as_bytes());
buffer.extend_from_slice(&nullifier_found);
buffer.extend_from_slice(&raw_note);
}
}
}

let block_heights = block_heights
.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(",");
buffer.extend_from_slice(&last_pos.to_be_bytes());

utils::into_ptr(types::CheckNoteOwnershipResponse {
notes,
block_heights,
public_spend_keys,
nullifiers,
last_pos,
})
let (ptr, len) = utils::allocated_copy(buffer);

compose(true, ptr, len)
}

/// Given array of notes, nullifiers of those notes and some existing
Expand Down
81 changes: 74 additions & 7 deletions tests/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@

//! Wallet library tests.

use dusk_bls12_381::BlsScalar;
use dusk_bytes::Serializable;
use dusk_jubjub::JubJubScalar;
use dusk_wallet_core::{
tx,
types::{self, CrossoverType as WasmCrossover},
utils, MAX_KEY, MAX_LEN, RNG_SEED,
};
use phoenix_core::{Crossover, PublicKey, ViewKey};
use phoenix_core::{
transaction::TreeLeaf, Crossover, Note, PublicKey, ViewKey,
};
use rusk_abi::ContractId;
use serde::{Deserialize, Serialize};
use serde_json::json;
Expand Down Expand Up @@ -250,6 +253,63 @@ fn nullifiers_works() {
assert_eq!(nullifiers, response);
}

#[test]
fn ownership_check() {
let seed = [0xfa; RNG_SEED];

let (notes, _): (Vec<_>, Vec<_>) =
node::raw_notes_and_nulifiers(&seed, [10, 250, 15, 39, 55])
.into_iter()
.unzip();

let mut wallet = Wallet::default();

let mut leaves = Vec::new();

for note in notes.iter() {
let mut note_cloned = note.clone();
note_cloned.set_pos(30);

let leaf = TreeLeaf {
block_height: u64::MAX,
note: note_cloned,
};

leaves.extend(
rkyv::to_bytes::<TreeLeaf, MAX_LEN>(&leaf).unwrap().to_vec(),
);
}

let mut arg = Vec::from(seed);
arg.extend(leaves);

let response = wallet.call_raw("check_note_ownership", &arg).take_memory();

let mut chunks = response.chunks_exact(88 + 32 + 632);

// check if serialization is correct
let mut i = 0;
for chunk in chunks.by_ref() {
let block_height = u64::from_be_bytes(chunk[..8].try_into().unwrap());

let psk = String::from_utf8(chunk[8..96].to_vec()).unwrap();
let _ = rkyv::from_bytes::<BlsScalar>(&chunk[96..128]).unwrap();
let _ = rkyv::from_bytes::<Note>(&chunk[128..]).unwrap();

assert_eq!(block_height, u64::MAX);
assert_eq!(psk, String::from("3PD3wMMNyPxhfQh5N4pJ7tQRXvVQpiRQ5b53ny9eB3CCVFT8uAGfZgEsyoGwP4jDTXJqXKmBFCt1sDDCJzeQdQzD"));
i = i + 1;
}

assert_eq!(i, 5);

let remainder = chunks.remainder();

let last_pos = u64::from_be_bytes(remainder.try_into().unwrap());

assert_eq!(last_pos, 30);
}

/// A node interface. It will encapsulate all the phoenix core functionality.
mod node {
use core::mem;
Expand Down Expand Up @@ -295,6 +355,10 @@ mod node {
let openings: Vec<_> = (0..len)
.zip(notes.clone())
.map(|(_, note)| {
// SAFETY: this is highly unsafe to use,
// but for tests its fine, `opening` is uninitialized
// into a type of `tx::Opening` which is UB To make it safe,
// some other code should fill the bytes and initialize it
let opening = unsafe { mem::zeroed::<tx::Opening>() };
(opening, *note.pos())
})
Expand Down Expand Up @@ -425,7 +489,14 @@ impl Wallet {
where
T: Serialize,
{
let bytes = serde_json::to_string(&args).unwrap();
let json = serde_json::to_string(&args).unwrap();
let bytes = json.as_bytes();

self.call_raw(f, bytes)
}

pub fn call_raw(&mut self, f: &str, args: &[u8]) -> CallResult {
let bytes = args;

let len_params = [Val::I32(bytes.len() as i32)];
let mut ptr_results = [Val::I32(0)];
Expand All @@ -442,11 +513,7 @@ impl Wallet {
self.instance
.get_memory(&mut self.store, "memory")
.expect("There should be one memory")
.write(
&mut self.store,
ptr_results[0].unwrap_i32() as usize,
bytes.as_bytes(),
)
.write(&mut self.store, ptr_results[0].unwrap_i32() as usize, bytes)
.expect("Writing to memory should succeed");

let params = [ptr_results[0].clone(), len_params[0].clone()];
Expand Down
Loading