Skip to content

Commit

Permalink
Improve wasm signatures (#834)
Browse files Browse the repository at this point in the history
* Improve wasm fn signatures

* Update packages/wasm/crate/src/dex.rs

Co-authored-by: Valentine <walik19988@gmail.com>

* Update packages/wasm/crate/src/dex.rs

Co-authored-by: Valentine <walik19988@gmail.com>

* Additional jsvalues

---------

Co-authored-by: Valentine <walik19988@gmail.com>
  • Loading branch information
grod220 and Valentine1898 authored Apr 3, 2024
1 parent f0371c3 commit 2dcd7d3
Show file tree
Hide file tree
Showing 22 changed files with 188 additions and 316 deletions.
10 changes: 5 additions & 5 deletions packages/query/src/block-processor.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { RootQuerier } from './root-querier';
import { sha256Hash } from '@penumbra-zone/crypto-web/src/sha256';
import { computePositionId, getLpNftMetadata } from '@penumbra-zone/wasm/src/dex';
import { decodeSctRoot } from '@penumbra-zone/wasm/src/sct';

import {
getExchangeRateFromValidatorInfoResponse,
Expand Down Expand Up @@ -385,14 +384,15 @@ export class BlockProcessor implements BlockProcessorInterface {
}
}

// Compares the locally stored, filtered SCT root with the actual one on chain. They should match.
// This is expensive to do every block, so should only be done in development.
// Compares the locally stored, filtered TCT root with the actual one on chain. They should match.
// This is expensive to do every block, so should only be done in development for debugging purposes.
// Recommend putting it alongside a flush (when flushReasons are triggered).
// @ts-expect-error Only used ad-hoc in dev
private async assertRootValid(blockHeight: bigint): Promise<void> {
const sourceOfTruth = await this.querier.cnidarium.keyValue(`sct/anchor/${blockHeight}`);
const remoteRoot = await this.querier.cnidarium.fetchRemoteRoot(blockHeight);
const inMemoryRoot = this.viewServer.getSctRoot();

if (!decodeSctRoot(sourceOfTruth).equals(inMemoryRoot)) {
if (!remoteRoot.equals(inMemoryRoot)) {
throw new Error(
`Block height: ${blockHeight}. Wasm root does not match remote source of truth. Programmer error.`,
);
Expand Down
17 changes: 9 additions & 8 deletions packages/query/src/queriers/cnidarium.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { PromiseClient } from '@connectrpc/connect';
import { createClient } from './utils';
import { QueryService as CnidariumQueryService } from '@buf/penumbra-zone_penumbra.connectrpc_es/penumbra/cnidarium/v1/cnidarium_connect';

import {
KeyValueRequest,
KeyValueResponse_Value,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/cnidarium/v1/cnidarium_pb';
import { KeyValueRequest } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/cnidarium/v1/cnidarium_pb';
import { CnidariumQuerierInterface } from '@penumbra-zone/types/src/querier';
import { MerkleRoot } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/crypto/tct/v1/tct_pb';

export class CnidariumQuerier implements CnidariumQuerierInterface {
private readonly client: PromiseClient<typeof CnidariumQueryService>;
Expand All @@ -15,9 +12,13 @@ export class CnidariumQuerier implements CnidariumQuerierInterface {
this.client = createClient(grpcEndpoint, CnidariumQueryService);
}

async keyValue(key: string): Promise<KeyValueResponse_Value['value']> {
const keyValueRequest = new KeyValueRequest({ key });
async fetchRemoteRoot(blockHeight: bigint): Promise<MerkleRoot> {
const keyValueRequest = new KeyValueRequest({
key: `sct/tree/anchor_by_height/${blockHeight}`,
});
const keyValue = await this.client.keyValue(keyValueRequest);
return keyValue.value!.value;
if (!keyValue.value) throw new Error('no value in KeyValueResponse');

return MerkleRoot.fromBinary(keyValue.value.value);
}
}
4 changes: 2 additions & 2 deletions packages/types/src/querier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
QueryClientStatesRequest,
QueryClientStatesResponse,
} from '@buf/cosmos_ibc.bufbuild_es/ibc/core/client/v1/query_pb';
import { KeyValueResponse_Value } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/cnidarium/v1/cnidarium_pb';
import { TransactionId } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/txhash/v1/txhash_pb';
import { Transaction } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/transaction/v1/transaction_pb';
import {
Expand All @@ -17,6 +16,7 @@ import {
ValidatorPenaltyRequest,
ValidatorPenaltyResponse,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/stake/v1/stake_pb';
import { MerkleRoot } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/crypto/tct/v1/tct_pb';

export interface RootQuerierInterface {
app: AppQuerierInterface;
Expand Down Expand Up @@ -63,5 +63,5 @@ export interface StakingQuerierInterface {
}

export interface CnidariumQuerierInterface {
keyValue(key: string): Promise<KeyValueResponse_Value['value']>;
fetchRemoteRoot(blockHeight: bigint): Promise<MerkleRoot>;
}
3 changes: 2 additions & 1 deletion packages/wasm/crate/Cargo.lock

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

3 changes: 2 additions & 1 deletion packages/wasm/crate/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

[package]
name = "penumbra-wasm"
version = "0.1.0"
version = "2.0.0"
edition = "2021"

[profile.release]
Expand Down Expand Up @@ -36,6 +36,7 @@ console_error_panic_hook = { version = "0.1.7", optional = true }
decaf377 = { version = "0.5.0", features = ["r1cs"] }
hex = "0.4.3"
indexed_db_futures = "0.4.1"
prost = "0.12.3"
rand_core = { version = "0.6.4", features = ["getrandom"] }
serde = { version = "1.0.197", features = ["derive"] }
serde-wasm-bindgen = "0.6.5"
Expand Down
24 changes: 8 additions & 16 deletions packages/wasm/crate/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use penumbra_transaction::{
WitnessData,
};
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;

use crate::error::WasmResult;
use crate::utils;
Expand All @@ -20,26 +19,19 @@ use crate::utils;
/// Returns: `Action`
#[wasm_bindgen]
pub fn build_action(
transaction_plan: JsValue,
action_plan: JsValue,
transaction_plan: &[u8],
action_plan: &[u8],
full_viewing_key: &[u8],
witness_data: JsValue,
) -> WasmResult<JsValue> {
witness_data: &[u8],
) -> WasmResult<Vec<u8>> {
utils::set_panic_hook();

let transaction_plan: TransactionPlan =
serde_wasm_bindgen::from_value(transaction_plan.clone())?;

let witness: WitnessData = serde_wasm_bindgen::from_value(witness_data)?;

let action_plan: ActionPlan = serde_wasm_bindgen::from_value(action_plan)?;

let transaction_plan = TransactionPlan::decode(transaction_plan)?;
let witness = WitnessData::decode(witness_data)?;
let action_plan = ActionPlan::decode(action_plan)?;
let full_viewing_key: FullViewingKey = FullViewingKey::decode(full_viewing_key)?;

let memo_key = transaction_plan.memo.map(|memo_plan| memo_plan.key);

let action = ActionPlan::build_unauth(action_plan, &full_viewing_key, &witness, memo_key)?;

let result = serde_wasm_bindgen::to_value(&action)?;
Ok(result)
Ok(action.encode_to_vec())
}
34 changes: 16 additions & 18 deletions packages/wasm/crate/src/dex.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,34 @@
use crate::utils;
use penumbra_dex::lp::position::{Id, Position};
use penumbra_dex::lp::position::{Id, Position, State};
use penumbra_dex::lp::LpNft;
use serde_wasm_bindgen::Error;
use penumbra_proto::DomainType;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;

use crate::error::WasmResult;
use crate::utils;

/// compute position id
/// Arguments:
/// position: `Position`
/// Returns: `PositionId`
/// position: `Uint8Array representing a Position`
/// Returns: ` Uint8Array representing a PositionId`
#[wasm_bindgen]
pub fn compute_position_id(position: JsValue) -> Result<JsValue, Error> {
pub fn compute_position_id(position: &[u8]) -> WasmResult<Vec<u8>> {
utils::set_panic_hook();

let position: Position = serde_wasm_bindgen::from_value(position)?;
serde_wasm_bindgen::to_value(&position.id())
let position = Position::decode(position)?;
Ok(position.id().encode_to_vec())
}

/// get LP NFT asset
/// Arguments:
/// position_value: `lp::position::Position`
/// position_state_value: `lp::position::State`
/// Returns: `DenomMetadata`
/// position_state: `lp::position::State`
/// Returns: `Uint8Array representing a DenomMetadata`
#[wasm_bindgen]
pub fn get_lpnft_asset(
position_id_value: JsValue,
position_state_value: JsValue,
) -> Result<JsValue, Error> {
pub fn get_lpnft_asset(position_id: &[u8], position_state: &[u8]) -> WasmResult<Vec<u8>> {
utils::set_panic_hook();
let position_id: Id = serde_wasm_bindgen::from_value(position_id_value)?;
let position_state = serde_wasm_bindgen::from_value(position_state_value)?;
let position_id = Id::decode(position_id)?;
let position_state = State::decode(position_state)?;
let lp_nft = LpNft::new(position_id, position_state);
let denom = lp_nft.denom();
serde_wasm_bindgen::to_value(&denom)
Ok(denom.encode_to_vec())
}
11 changes: 7 additions & 4 deletions packages/wasm/crate/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::convert::Infallible;

use base64::DecodeError;
use base64::DecodeError as Base64DecodeError;
use hex::FromHexError;
use penumbra_tct::error::{InsertBlockError, InsertEpochError, InsertError};
use prost::DecodeError as ProstDecodeError;
use serde_wasm_bindgen::Error;
use thiserror::Error;
use wasm_bindgen::{JsError, JsValue};
use web_sys::DomException;

use penumbra_tct::error::{InsertBlockError, InsertEpochError, InsertError};

pub type WasmResult<T> = Result<T, WasmError>;

#[derive(Error, Debug)]
Expand All @@ -17,7 +17,7 @@ pub enum WasmError {
Anyhow(#[from] anyhow::Error),

#[error("{0}")]
DecodeError(#[from] DecodeError),
Base64DecodeError(#[from] Base64DecodeError),

#[error("{0}")]
Dom(#[from] DomError),
Expand All @@ -37,6 +37,9 @@ pub enum WasmError {
#[error("{0}")]
InsertError(#[from] InsertError),

#[error("Decode error: {0}")]
ProstDecodeError(#[from] ProstDecodeError),

#[error("{0}")]
Wasm(#[from] serde_wasm_bindgen::Error),
}
Expand Down
8 changes: 2 additions & 6 deletions packages/wasm/crate/src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use penumbra_proto::core::keys::v1::WalletId;
use penumbra_proto::{DomainType, Message};
use rand_core::OsRng;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::js_sys::Uint8Array;

use crate::error::WasmResult;
use crate::utils;
Expand All @@ -23,10 +22,7 @@ use crate::utils;
/// function will additionally require downloading the proving key parameter `.bin`
/// file for each key type.
#[wasm_bindgen]
pub fn load_proving_key(parameters: JsValue, key_type: &str) -> WasmResult<()> {
// Deserialize JsValue into Vec<u8>.
let parameters_bytes: Vec<u8> = Uint8Array::new(&parameters).to_vec();

pub fn load_proving_key(key: &[u8], key_type: &str) -> WasmResult<()> {
// Map key type with proving keys.
let proving_key_map = match key_type {
"spend" => &SPEND_PROOF_PROVING_KEY,
Expand All @@ -39,7 +35,7 @@ pub fn load_proving_key(parameters: JsValue, key_type: &str) -> WasmResult<()> {
};

// Load proving key.
proving_key_map.try_load_unchecked(&parameters_bytes)?;
proving_key_map.try_load_unchecked(key)?;
Ok(())
}

Expand Down
5 changes: 3 additions & 2 deletions packages/wasm/crate/src/planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use penumbra_stake::{IdentityKey, Penalty, UndelegateClaimPlan};
use penumbra_transaction::gas::GasCost;
use penumbra_transaction::memo::MemoPlaintext;
use penumbra_transaction::{plan::MemoPlan, ActionPlan, TransactionParameters, TransactionPlan};
use prost::Message;
use rand_core::OsRng;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::JsValue;
Expand Down Expand Up @@ -157,12 +158,12 @@ fn prioritize_and_filter_spendable_notes(
#[wasm_bindgen]
pub async fn plan_transaction(
idb_constants: JsValue,
request: JsValue,
request: &[u8],
full_viewing_key: &[u8],
) -> WasmResult<JsValue> {
utils::set_panic_hook();

let request: TransactionPlannerRequest = serde_wasm_bindgen::from_value(request)?;
let request = TransactionPlannerRequest::decode(request)?;

let source_address_index: AddressIndex = request
.source
Expand Down
Loading

0 comments on commit 2dcd7d3

Please sign in to comment.