Skip to content

Commit

Permalink
Merge branch 'tomas/cache-masp-keys' (#2272)
Browse files Browse the repository at this point in the history
* origin/tomas/cache-masp-keys:
  test/sdk/masp: update params tests
  changelog: #2272
  ledger: preload masp verifying keys on start-up
  cache MASP verifying keys in memory
  • Loading branch information
Gianmarco Fraccaroli committed Dec 13, 2023
2 parents 9562c16 + 8a0c465 commit 86d71bf
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 43 deletions.
2 changes: 2 additions & 0 deletions .changelog/unreleased/improvements/2272-cache-masp-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Preload and cache MASP verifying keys on ledger start-up.
([\#2272](https://github.com/anoma/namada/pull/2272))
1 change: 1 addition & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions apps/src/lib/node/ledger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ async fn run_aux(config: config::Ledger, wasm_dir: PathBuf) {
}
};

tracing::info!("Loading MASP verifying keys.");
let _ = namada_sdk::masp::preload_verifying_keys();
tracing::info!("Done loading MASP verifying keys.");

// Start ABCI server and broadcaster (the latter only if we are a validator
// node)
let (abci, broadcaster, shell_handler) = start_abci_broadcaster_shell(
Expand Down
1 change: 1 addition & 0 deletions sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ ethers.workspace = true
fd-lock = { workspace = true, optional = true }
futures.workspace = true
itertools.workspace = true
lazy_static.workspace= true
masp_primitives.workspace = true
masp_proofs.workspace = true
namada_core = {path = "../core", default-features = false, features = ["rand"]}
Expand Down
124 changes: 81 additions & 43 deletions sdk/src/masp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use std::path::PathBuf;
use borsh::{BorshDeserialize, BorshSerialize};
use borsh_ext::BorshSerializeExt;
use itertools::Either;
use lazy_static::lazy_static;
use masp_primitives::asset_type::AssetType;
#[cfg(feature = "mainnet")]
use masp_primitives::consensus::MainNetwork;
Expand Down Expand Up @@ -137,38 +138,61 @@ pub enum TransferErr {
General(#[from] Error),
}

fn load_pvks() -> (
PreparedVerifyingKey<Bls12>,
PreparedVerifyingKey<Bls12>,
PreparedVerifyingKey<Bls12>,
) {
let params_dir = get_params_dir();
let [spend_path, convert_path, output_path] =
[SPEND_NAME, CONVERT_NAME, OUTPUT_NAME].map(|p| params_dir.join(p));

#[cfg(feature = "download-params")]
if !spend_path.exists() || !convert_path.exists() || !output_path.exists() {
let paths = masp_proofs::download_masp_parameters(None).expect(
"MASP parameters were not present, expected the download to \
succeed",
);
if paths.spend != spend_path
|| paths.convert != convert_path
|| paths.output != output_path
/// MASP verifying keys
pub struct PVKs {
/// spend verifying key
spend_vk: PreparedVerifyingKey<Bls12>,
/// convert verifying key
convert_vk: PreparedVerifyingKey<Bls12>,
/// output verifying key
output_vk: PreparedVerifyingKey<Bls12>,
}

lazy_static! {
/// MASP verifying keys load from parameters
static ref VERIFIYING_KEYS: PVKs =
{
panic!(
"unrecoverable: downloaded missing masp params, but to an \
unfamiliar path"
)
let params_dir = get_params_dir();
let [spend_path, convert_path, output_path] =
[SPEND_NAME, CONVERT_NAME, OUTPUT_NAME].map(|p| params_dir.join(p));

#[cfg(feature = "download-params")]
if !spend_path.exists() || !convert_path.exists() || !output_path.exists() {
let paths = masp_proofs::download_masp_parameters(None).expect(
"MASP parameters were not present, expected the download to \
succeed",
);
if paths.spend != spend_path
|| paths.convert != convert_path
|| paths.output != output_path
{
panic!(
"unrecoverable: downloaded missing masp params, but to an \
unfamiliar path"
)
}
}
}
// size and blake2b checked here
let params = masp_proofs::load_parameters(
spend_path.as_path(),
output_path.as_path(),
convert_path.as_path(),
);
(params.spend_vk, params.convert_vk, params.output_vk)
// size and blake2b checked here
let params = masp_proofs::load_parameters(
spend_path.as_path(),
output_path.as_path(),
convert_path.as_path(),
);
PVKs {
spend_vk: params.spend_vk,
convert_vk: params.convert_vk,
output_vk: params.output_vk
}
};
}

/// Make sure the MASP params are present and load verifying keys into memory
pub fn preload_verifying_keys() -> &'static PVKs {
&VERIFIYING_KEYS
}

fn load_pvks() -> &'static PVKs {
&VERIFIYING_KEYS
}

/// check_spend wrapper
Expand Down Expand Up @@ -300,20 +324,25 @@ pub fn verify_shielded_tx(transaction: &Transaction) -> bool {

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

let (spend_pvk, convert_pvk, output_pvk) = load_pvks();
let PVKs {
spend_vk,
convert_vk,
output_vk,
} = load_pvks();

let mut ctx = SaplingVerificationContext::new(true);
let spends_valid = sapling_bundle.shielded_spends.iter().all(|spend| {
check_spend(spend, sighash.as_ref(), &mut ctx, &spend_pvk)
});
let spends_valid = sapling_bundle
.shielded_spends
.iter()
.all(|spend| check_spend(spend, sighash.as_ref(), &mut ctx, spend_vk));
let converts_valid = sapling_bundle
.shielded_converts
.iter()
.all(|convert| check_convert(convert, &mut ctx, &convert_pvk));
.all(|convert| check_convert(convert, &mut ctx, convert_vk));
let outputs_valid = sapling_bundle
.shielded_outputs
.iter()
.all(|output| check_output(output, &mut ctx, &output_pvk));
.all(|output| check_output(output, &mut ctx, output_vk));

if !(spends_valid && outputs_valid && converts_valid) {
return false;
Expand Down Expand Up @@ -2021,8 +2050,8 @@ mod tests {
.expect("expected a temp dir")
.into_path();
let fake_params_paths =
[SPEND_NAME, CONVERT_NAME, OUTPUT_NAME].map(|p| tempdir.join(p));
for path in fake_params_paths {
[SPEND_NAME, OUTPUT_NAME, CONVERT_NAME].map(|p| tempdir.join(p));
for path in &fake_params_paths {
let mut f =
std::fs::File::create(path).expect("expected a temp file");
f.write_all(b"fake params")
Expand All @@ -2033,7 +2062,11 @@ mod tests {

std::env::set_var(super::ENV_VAR_MASP_PARAMS_DIR, tempdir.as_os_str());
// should panic here
super::load_pvks();
masp_proofs::load_parameters(
&fake_params_paths[0],
&fake_params_paths[1],
&fake_params_paths[2],
);
}

/// a more involved test, using dummy parameters with the right
Expand Down Expand Up @@ -2085,11 +2118,11 @@ mod tests {
// TODO: get masp to export these consts
let fake_params_paths = [
(SPEND_NAME, 49848572u64),
(CONVERT_NAME, 22570940u64),
(OUTPUT_NAME, 16398620u64),
(CONVERT_NAME, 22570940u64),
]
.map(|(p, s)| (tempdir.join(p), s));
for (path, size) in fake_params_paths {
for (path, size) in &fake_params_paths {
let mut f =
std::fs::File::create(path).expect("expected a temp file");
fake_params
Expand All @@ -2099,14 +2132,19 @@ mod tests {
// params should always be smaller than the large masp
// circuit params. so this truncate extends the file, and
// extra bytes at the end do not make it invalid.
f.set_len(size).expect("expected to truncate the temp file");
f.set_len(*size)
.expect("expected to truncate the temp file");
f.sync_all()
.expect("expected a writable temp file (on sync)");
}

std::env::set_var(super::ENV_VAR_MASP_PARAMS_DIR, tempdir.as_os_str());
// should panic here
super::load_pvks();
masp_proofs::load_parameters(
&fake_params_paths[0].0,
&fake_params_paths[1].0,
&fake_params_paths[2].0,
);
}
}

Expand Down
1 change: 1 addition & 0 deletions wasm/Cargo.lock

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

1 change: 1 addition & 0 deletions wasm_for_tests/wasm_source/Cargo.lock

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

0 comments on commit 86d71bf

Please sign in to comment.