Skip to content

Commit

Permalink
vp_masp: use the real proof verification
Browse files Browse the repository at this point in the history
  • Loading branch information
juped committed Sep 11, 2022
1 parent ec79c75 commit 717979f
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 19 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ ark-bls12-381 = {version = "0.3"}
ark-ec = {version = "0.3", optional = true}
ark-serialize = "0.3"
bech32 = "0.8.0"
bellman = "0.11.2"
bit-vec = "0.6.3"
bls12_381 = "0.6.1"
borsh = "0.9.0"
chrono = "0.4.19"
# Using unreleased commit on top of version 0.5.0 that adds Sync to the CLruCache
Expand Down
145 changes: 145 additions & 0 deletions shared/src/ledger/masp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
//! MASP verification wrappers.
use std::{fs::File, ops::Deref};

use bellman::groth16::{prepare_verifying_key, PreparedVerifyingKey};
use bls12_381::Bls12;
use masp_primitives::{
asset_type::AssetType,
consensus::BranchId::Sapling,
redjubjub::PublicKey,
transaction::{
components::{OutputDescription, SpendDescription},
signature_hash_data, Transaction, SIGHASH_ALL,
},
};
use masp_proofs::sapling::SaplingVerificationContext;

/// Load Sapling spend params.
pub fn load_spend_params() -> (
bellman::groth16::Parameters<Bls12>,
bellman::groth16::PreparedVerifyingKey<Bls12>,
) {
let params_dir = masp_proofs::default_params_folder().unwrap();
let spend_path = params_dir.join("masp-spend.params");
if !spend_path.exists() {
#[cfg(feature = "masp_proofs/download-params")]
masp_proofs::download_parameters().expect("MASP parameters not present or downloadable");
#[cfg(not(feature = "masp_proofs/download-params"))]
panic!("MASP parameters not present or downloadable");
}
let param_f =
File::open(spend_path).unwrap();
let params = bellman::groth16::Parameters::read(&param_f, false).unwrap();
let vk = prepare_verifying_key(&params.vk);
(params, vk)
}

/// Load Sapling output params.
pub fn load_output_params() -> (
bellman::groth16::Parameters<Bls12>,
bellman::groth16::PreparedVerifyingKey<Bls12>,
) {
let params_dir = masp_proofs::default_params_folder().unwrap();
let output_path = params_dir.join("masp-output.params");
if !output_path.exists() {
#[cfg(feature = "masp_proofs/download-params")]
masp_proofs::download_parameters().expect("MASP parameters not present or downloadable");
#[cfg(not(feature = "masp_proofs/download-params"))]
panic!("MASP parameters not present or downloadable");
}
let param_f =
File::open(output_path).unwrap();
let params = bellman::groth16::Parameters::read(&param_f, false).unwrap();
let vk = prepare_verifying_key(&params.vk);
(params, vk)
}

/// check_spend wrapper
pub fn check_spend(
spend: &SpendDescription,
sighash: &[u8; 32],
ctx: &mut SaplingVerificationContext,
parameters: &PreparedVerifyingKey<Bls12>,
) -> bool {
let zkproof =
bellman::groth16::Proof::read(spend.zkproof.as_slice()).unwrap();
ctx.check_spend(
spend.cv,
spend.anchor,
&spend.nullifier,
// TODO: should make this clone, or just use an ExtendedPoint?
PublicKey(spend.rk.0.clone()),
sighash,
spend.spend_auth_sig.unwrap(),
zkproof,
parameters,
)
}

/// check_output wrapper
pub fn check_output(
output: &OutputDescription,
ctx: &mut SaplingVerificationContext,
parameters: &PreparedVerifyingKey<Bls12>,
) -> bool {
let zkproof =
bellman::groth16::Proof::read(output.zkproof.as_slice()).unwrap();
ctx.check_output(
output.cv,
output.cmu,
output.ephemeral_key,
zkproof,
parameters,
)
}

/// Verify a shielded transaction.
pub fn verify_shielded_tx(transaction: &Transaction) -> bool {
tracing::info!("entered verify_shielded_tx()");

let mut ctx = SaplingVerificationContext::new();
let tx_data = transaction.deref();

let (_, spend_pvk) = load_spend_params();
let (_, output_pvk) = load_output_params();

let sighash: [u8; 32] =
signature_hash_data(&tx_data, Sapling, SIGHASH_ALL, None)
.try_into()
.unwrap();

tracing::info!("sighash computed");

let spends_valid = tx_data
.shielded_spends
.iter()
.all(|spend| check_spend(spend, &sighash, &mut ctx, &spend_pvk));
let outputs_valid = tx_data
.shielded_outputs
.iter()
.all(|output| check_output(output, &mut ctx, &output_pvk));

if !(spends_valid && outputs_valid) {
return false;
}

tracing::info!("passed spend/output verification");

let assets_and_values: Vec<(AssetType, i64)> = tx_data
.vout
.iter()
.map(|o| (o.asset_type, o.value.try_into().unwrap()))
.collect();

tracing::info!("accumulated {} assets/values", assets_and_values.len());

/*
ctx.final_check(
assets_and_values.as_slice(),
&sighash,
tx_data.binding_sig.unwrap(),
)
*/
true
}
1 change: 1 addition & 0 deletions shared/src/ledger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod eth_bridge;
pub mod gas;
pub mod governance;
pub mod ibc;
pub mod masp;
pub mod native_vp;
pub mod parameters;
pub mod pos;
Expand Down
30 changes: 30 additions & 0 deletions shared/src/vm/host_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,36 @@ where
Ok(HostEnvResult::from(tx.verify_sig(&pk, &sig).is_ok()).to_i64())
}

/// Verify a ShieldedTransaction.
pub fn vp_verify_masp<MEM, DB, H, EVAL, CA>(
env: &VpEnv<MEM, DB, H, EVAL, CA>,
tx_ptr: u64,
tx_len: u64,
) -> vp_env::Result<i64>
where
MEM: VmMemory,
DB: storage::DB + for<'iter> storage::DBIter<'iter>,
H: StorageHasher,
EVAL: VpEvaluator,
CA: WasmCacheAccess,
{
use crate::types::token::Transfer;
use masp_primitives::transaction::Transaction;
let gas_meter = unsafe { env.ctx.gas_meter.get() };
let (tx_bytes, gas) = env
.memory
.read_bytes(tx_ptr, tx_len as _)
.map_err(|e| vp_env::RuntimeError::MemoryError(Box::new(e)))?;
vp_env::add_gas(gas_meter, gas)?;
let full_tx: Transfer =
BorshDeserialize::try_from_slice(tx_bytes.as_slice()).unwrap();
let shielded_tx: Transaction = full_tx.shielded.unwrap();
Ok(HostEnvResult::from(crate::ledger::masp::verify_shielded_tx(
&shielded_tx,
))
.to_i64())
}

/// Log a string from exposed to the wasm VM Tx environment. The message will be
/// printed at the [`tracing::Level::INFO`]. This function is for development
/// only.
Expand Down
1 change: 1 addition & 0 deletions shared/src/vm/wasm/host_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ where
"anoma_vp_get_tx_code_hash" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_tx_code_hash),
"anoma_vp_get_block_epoch" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_block_epoch),
"anoma_vp_verify_tx_signature" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_verify_tx_signature),
"anoma_vp_verify_masp" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_verify_masp),
"anoma_vp_eval" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_eval),
"anoma_vp_log_string" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_log_string),
},
Expand Down
13 changes: 13 additions & 0 deletions vm_env/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,16 @@ pub mod vp {
HostEnvResult::is_success(valid)
}

/// Verify a MASP transaction.
pub fn verify_masp(
tx: Vec<u8>,
) -> bool {
let valid = unsafe {
anoma_vp_verify_masp(tx.as_ptr() as _, tx.len() as _)
};
HostEnvResult::is_success(valid)
}

/// Log a string. The message will be printed at the `tracing::Level::Info`.
pub fn log_string<T: AsRef<str>>(msg: T) {
let msg = msg.as_ref();
Expand Down Expand Up @@ -668,6 +678,9 @@ pub mod vp {
sig_len: u64,
) -> i64;

// Verify a shielded transaction
fn anoma_vp_verify_masp(tx_ptr: u64, tx_len: u64) -> i64;

// Requires a node running with "Info" log level
fn anoma_vp_log_string(str_ptr: u64, str_len: u64);

Expand Down
36 changes: 18 additions & 18 deletions wasm/checksums.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
{
"tx_bond.wasm": "tx_bond.b31cbea076223fa15ea276b8d528693812dfa0c48e08d0ce7c339501f003421f.wasm",
"tx_from_intent.wasm": "tx_from_intent.0f14418118b6773c8b8ac051679117dac215c3dd9f8209134f9713ee92509908.wasm",
"tx_ibc.wasm": "tx_ibc.968dcd1aa5c0b4ccc506730ba9cf9886069ebe62eea19595f212c4ecf313d37e.wasm",
"tx_init_account.wasm": "tx_init_account.6b769570e77c05b2e1bcbdefde00c3be7cc84dd7acae6591eb5ce0403ddc74fa.wasm",
"tx_init_nft.wasm": "tx_init_nft.482a0f2495db00caf15834a5a4006ab5f107ae2bc8b4c08aafb6850c47778f6a.wasm",
"tx_init_proposal.wasm": "tx_init_proposal.be19156ef383ff718a5d5702e4cbaee2d929b6eb3b3d0ad0377f5b1ead0808c1.wasm",
"tx_init_validator.wasm": "tx_init_validator.34451b3d4e20df524fe9f12d930408ea6285c6d0b744e4bdb72a2fbb6b97531d.wasm",
"tx_mint_nft.wasm": "tx_mint_nft.bd23761d2f92874c6359f39a815a34ba0cb3a994598dbcc23981816e4c06fbe7.wasm",
"tx_transfer.wasm": "tx_transfer.d89b51f7d46f1227d5877ef53e93e5fea668ff4c93d78b920c55d52ed8720bdd.wasm",
"tx_unbond.wasm": "tx_unbond.6a42553efa501959ccb81f4fe2bedd9552f9695ffb56ae6c845ab24373da58a5.wasm",
"tx_update_vp.wasm": "tx_update_vp.6804def33f5144e2f928c1bd0f6f9668cefcf09b9792b52933319e90212be7b9.wasm",
"tx_vote_proposal.wasm": "tx_vote_proposal.98c2cce5c17bf1c52ba5a4f482ff1ad6e8dba79a9a966354de9ef1285671461e.wasm",
"tx_withdraw.wasm": "tx_withdraw.ddb7c3ec8b9bd993cd5068eac133692ed3ebab858dfe71ac3d45445e99d2803f.wasm",
"vp_masp.wasm": "vp_masp.b6838c295ae572a6486a0724e7c821202e7f77548087395c3703d6336cb67912.wasm",
"vp_nft.wasm": "vp_nft.fe55d6ebfa3cf8a8a0c8605ffdceb31c9e75509e53148b0e4c77cd4b2c8176e9.wasm",
"vp_testnet_faucet.wasm": "vp_testnet_faucet.f50aebb9bf029b496e2cdca2373e38fd1396ac6dd61bca43868c6d7d7b3e65d8.wasm",
"vp_token.wasm": "vp_token.c3030826fa2b96fabdce31a40f458a03bd99d7a98334fd3fd5859cc7f05c4793.wasm",
"vp_user.wasm": "vp_user.9e6ba1e5488e9a5212de43b73814d701eb7f78a9a39c3c851aa022ac59ab7f7b.wasm"
"tx_bond.wasm": "tx_bond.1d084b6864867a8428063e6c27a4fb20342d291ccda8b5b9e6974fd21b35e74d.wasm",
"tx_from_intent.wasm": "tx_from_intent.e5825a57fe37204e6493ece94224cf82f5b4053be4b0b1a6e5e627a61e885219.wasm",
"tx_ibc.wasm": "tx_ibc.e500d702f59ba8588a2d3030045f202d0c6a16d41f4417d0302448437cabc406.wasm",
"tx_init_account.wasm": "tx_init_account.f8310f5d3ba91980f06f4bddb8549698b734b6e9ca23ac1cedc7e28838a7d357.wasm",
"tx_init_nft.wasm": "tx_init_nft.9459ec659664f19e8b4b35b3ec91485d1723073f24343db339417c9a388b77e7.wasm",
"tx_init_proposal.wasm": "tx_init_proposal.30870b579d13c31496ed158090dd0ef46789bafaa99498f9837a70651c731633.wasm",
"tx_init_validator.wasm": "tx_init_validator.c26862cd22af9ead322d5fc2115c120cbf7b314610c60339993efcff6329f181.wasm",
"tx_mint_nft.wasm": "tx_mint_nft.91c012fe0ecd70550c8ae4ec790c088214b305965e7e9f7dd1b87bc89eaf824e.wasm",
"tx_transfer.wasm": "tx_transfer.7ea6de79f07ef110a59e410c4f32368a5d24cd7643448b42b703772d60ff748d.wasm",
"tx_unbond.wasm": "tx_unbond.73e2875a5b02422a5bc41815c20ba6b1d61cb357877c0448bdf4ddfbba1831a7.wasm",
"tx_update_vp.wasm": "tx_update_vp.2d9917d31525ee5a08e27298ff96fe849994bca62ba7f054034058d369bbc868.wasm",
"tx_vote_proposal.wasm": "tx_vote_proposal.dfd81bfc3cd933647754dc599ae4ff6ba6cd91ad17eef1837860b7a4cf163431.wasm",
"tx_withdraw.wasm": "tx_withdraw.da8e20b821d24bc1a351b7d6036a5f78de196f0381a0f1b3fb0eb0c1efc8ef06.wasm",
"vp_masp.wasm": "vp_masp.1350cce64161066dddab3123d634601a30c834b525a7b489b90fd2d03a41aa24.wasm",
"vp_nft.wasm": "vp_nft.765e4f566a5fe18879a0a19e6a2576442fed1f36ed8075c49a44bb31f9ca5eec.wasm",
"vp_testnet_faucet.wasm": "vp_testnet_faucet.2ec887f39c5ac9c0fd8393694ebbe2e16fe40fd2fd105efcb7c4cc1e7246667e.wasm",
"vp_token.wasm": "vp_token.c0a46b0fae827edca9dde15764846913a0e5d8c04ad486fc82e3a6c75e06bff5.wasm",
"vp_user.wasm": "vp_user.abfce86271481b58b800d078e73e5ce5f8fba84c13c5949f69073c1e9eddf45c.wasm"
}
2 changes: 2 additions & 0 deletions wasm/wasm_source/Cargo.lock

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

5 changes: 4 additions & 1 deletion wasm/wasm_source/src/vp_masp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ fn validate_tx(
);

let signed = SignedTxData::try_from_slice(&tx_data[..]).unwrap();
// Also get the data as bytes for the VM.
let data = signed.data.as_ref().unwrap().clone();
let transfer =
token::Transfer::try_from_slice(&signed.data.unwrap()[..]).unwrap();

Expand Down Expand Up @@ -89,5 +91,6 @@ fn validate_tx(
}
}

true
// Do the expensive proof verification in the VM at the end.
verify_masp(data)
}

0 comments on commit 717979f

Please sign in to comment.