Skip to content
Open
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
9 changes: 6 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ env:
CARGO_TERM_COLOR: always
jobs:
build-and-test:
name: build-and-test (${{ matrix.os }}, ${{ matrix.rust_toolchain }})
name: build-and-test (${{ matrix.os }}, ${{ matrix.rust_toolchain }}, ${{ matrix.features || 'default' }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
rust_toolchain: [stable, beta]
os: [ubuntu-latest, macos-latest]
features: ["", "mesa-hardfork"]
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@master
Expand All @@ -26,9 +27,11 @@ jobs:
- name: Install test prerequisites
uses: ./.github/actions/setup-frost-prereqs
- name: Build
run: cargo build --verbose
run: cargo build --verbose ${{ matrix.features && format('--features {0}', matrix.features) }}
- name: Run tests
run: cargo test --verbose
run: cargo test --verbose ${{ matrix.features && format('--features {0}', matrix.features) }}
- name: Test mina-tx with frost-bluepallas-compat
run: cargo test -p mina-tx --verbose --features frost-bluepallas-compat${{ matrix.features && format(',{0}', matrix.features) }}
check-format-and-audit:
runs-on: ubuntu-latest
steps:
Expand Down
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.

11 changes: 6 additions & 5 deletions frost-bluepallas/examples/graphql-broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ use std::{fs, path::PathBuf};

use ark_ff::PrimeField;
use frost_bluepallas::signing_utilities::generate_signature_from_sk;
use mina_signer::{CompressedPubKey, Keypair, NetworkId, PubKey};
use mina_signer::{CompressedPubKey, Keypair, PubKey};
use mina_tx::NetworkId;
use mina_tx::{
legacy_tx::LegacyTransaction,
pallas_message::{translate_minask, translate_sig, PallasMessage},
Expand Down Expand Up @@ -74,15 +75,15 @@ fn build_legacy_payment(from: &PubKey, to: &PubKey) -> TransactionEnvelope {
.set_memo_str("FROST payment test")
.expect("memo fits")
.set_valid_until(4_294_967_295);
TransactionEnvelope::new_legacy(NetworkId::TESTNET, tx)
TransactionEnvelope::new_legacy(NetworkId::Testnet, tx)
}

fn build_legacy_delegation(from: &PubKey, to: &PubKey) -> TransactionEnvelope {
let tx = LegacyTransaction::new_delegation(from.clone(), to.clone(), 10_000_000, 1)
.set_memo_str("FROST delegation test")
.expect("memo fits")
.set_valid_until(4_294_967_295);
TransactionEnvelope::new_legacy(NetworkId::TESTNET, tx)
TransactionEnvelope::new_legacy(NetworkId::Testnet, tx)
}

fn build_zkapp_tx(from: &CompressedPubKey) -> TransactionEnvelope {
Expand Down Expand Up @@ -137,7 +138,7 @@ fn build_zkapp_tx(from: &CompressedPubKey) -> TransactionEnvelope {
memo,
};

TransactionEnvelope::new_zkapp(NetworkId::TESTNET, cmd)
TransactionEnvelope::new_zkapp(NetworkId::Testnet, cmd)
}

// ---------------------------------------------------------------------------
Expand All @@ -147,7 +148,7 @@ fn build_zkapp_tx(from: &CompressedPubKey) -> TransactionEnvelope {
fn sign_envelope(envelope: TransactionEnvelope, keypair: &Keypair) -> TransactionSignature {
let signing_key = translate_minask(keypair).expect("valid keypair");

let msg = envelope.to_pallas_message().serialize();
let msg = envelope.to_pallas_message().serialize().unwrap();

let (frost_sig, _vk) = generate_signature_from_sk::<PallasMessage, _>(
&msg,
Expand Down
6 changes: 3 additions & 3 deletions frost-bluepallas/examples/mina-sign-tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.set_memo_str("Hello Mina x FROST from the Rasp")
.unwrap();

let tx = TransactionEnvelope::new_legacy(mina_signer::NetworkId::TESTNET, tx);
let tx = TransactionEnvelope::new_legacy(mina_tx::NetworkId::Testnet, tx);

println!(
"Unsigned Transaction: {}",
Expand All @@ -38,7 +38,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
//let tx = tx.set_memo_str("Hello World!");
let signing_key = translate_minask(&mina_keypair)?;

let msg = tx.to_pallas_message().serialize();
let msg = tx.to_pallas_message().serialize().unwrap();

// Sign the transaction with FROST
let (sig, vk) = frost_bluepallas::signing_utilities::generate_signature_from_sk::<
Expand Down Expand Up @@ -73,7 +73,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let chall = frost_bluepallas::BluePallas::<PallasMessage>::challenge(sig.R(), &vk, &msg)?;
println!("Challenge: {:?}", chall);

let mut ctx = mina_signer::create_legacy(mina_signer::NetworkId::TESTNET);
let mut ctx = mina_signer::create_legacy(mina_tx::NetworkId::Testnet);
let res = ctx.verify(&mina_sig, &mina_keypair.public, &tx);
if res {
println!("Mina signature verification succeeded");
Expand Down
5 changes: 3 additions & 2 deletions frost-bluepallas/tests/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ pub mod samples;
pub mod types;

use frost_bluepallas::BluePallas;
use mina_signer::{NetworkId, Signer};
use mina_signer::Signer;
use mina_tx::pallas_message::{translate_pk, translate_sig, PallasMessage};
use mina_tx::NetworkId;

type Suite = BluePallas<PallasMessage>;

Expand All @@ -23,7 +24,7 @@ pub fn verify_signature(
let pub_key = translate_pk(&group_pubkey).unwrap();
// Check that signature validation has the expected result.

let mut ctx = mina_signer::create_legacy::<PallasMessage>(NetworkId::TESTNET);
let mut ctx = mina_signer::create_legacy::<PallasMessage>(NetworkId::Testnet);
let pallas_message = PallasMessage::deserialize(msg)
.unwrap_or_else(|_| PallasMessage::from_raw_bytes_default(msg));
assert!(ctx.verify(&sig, &pub_key, &pallas_message));
Expand Down
3 changes: 3 additions & 0 deletions mina-frost-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,6 @@ mina-hasher.workspace = true
ark-ff.workspace = true
frost-bluepallas = { path = "../frost-bluepallas", features = ["test-utils"] }
mina-tx = { path = "../mina-tx", features = ["test-utils"] }

[features]
mesa-hardfork = ["mina-tx/mesa-hardfork"]
2 changes: 1 addition & 1 deletion mina-frost-client/src/coordinator/coordinate_signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub async fn coordinate_signing(
// Aggregate signatures using frost_bluepallas modified behaviour
let group_signature = {
let transaction = TransactionEnvelope::deserialize(signing_package.message())?;
let pallas_message_bytes = transaction.to_pallas_message().serialize();
let pallas_message_bytes = transaction.to_pallas_message().serialize()?;
let signing_package_for_crypto = SigningPackage::new(commitments, &pallas_message_bytes);
frost_bluepallas::aggregate(
&signing_package_for_crypto,
Expand Down
2 changes: 1 addition & 1 deletion mina-frost-client/src/participant/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub async fn sign(

let signing_package = round_2_config.signing_package.first().unwrap();
let transaction = TransactionEnvelope::deserialize(signing_package.message())?;
let pallas_message_bytes = transaction.to_pallas_message().serialize();
let pallas_message_bytes = transaction.to_pallas_message().serialize()?;
let signing_package_for_crypto = frost_core::SigningPackage::new(
signing_package.signing_commitments().clone(),
&pallas_message_bytes,
Expand Down
8 changes: 5 additions & 3 deletions mina-frost-client/src/trusted_dealer/tests/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use frost_bluepallas as frost;
use mina_hasher::ROInput;
use mina_signer::NetworkId;
use mina_tx::pallas_message::PallasMessage;
use mina_tx::NetworkId;
use rand::rngs::ThreadRng;
use std::collections::BTreeMap;

Expand Down Expand Up @@ -56,10 +56,12 @@ pub fn round_2(
// Signing input must be an explicitly encoded PallasMessage.
let pallas_message = PallasMessage::from_parts(
ROInput::new().append_bytes(message),
NetworkId::TESTNET,
NetworkId::Testnet,
true,
);
let serialized_message = pallas_message.serialize();
let serialized_message = pallas_message
.serialize()
.expect("PallasMessage serialization should succeed");
let signing_package = frost::SigningPackage::new(commitments_map, &serialized_message);
let mut signature_shares = BTreeMap::new();
for participant_identifier in nonces_map.keys() {
Expand Down
140 changes: 140 additions & 0 deletions mina-frost-client/tests/compat_pre_to_mesa.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//! Compatibility test:
//! - create participants and group config with pre-Mesa binary
//! - sign a Mesa transaction with Mesa binary using those same config files

mod helpers;

use helpers::{
build_client_binary, form_group_with_dkg, greet_participants, group_keys_from_config,
introduce_participant, network_to_cli_arg, parse_and_verify_signature, sign_with_binary,
start_frostd, write_json_str_pretty, ChildGuard, CliParticipant, SigningParticipant,
};
use mina_tx::zkapp_tx::test_vectors::{get_zkapp_test_vectors, ZkAppTestVector};
use mina_tx::{TransactionEnvelope, TransactionKind};
use std::{fs, path::Path};
use tempfile::TempDir;

const SERVER_URL: &str = "localhost:2744";
const SIG_FILE: &str = "signature.json";
const THRESHOLD: usize = 2;
const NUM_PARTICIPANTS: usize = 3;

fn write_vector_message(message_path: &Path, vector: &ZkAppTestVector) -> String {
let envelope: TransactionEnvelope = vector.clone().into();
let network_cli_arg = network_to_cli_arg(&envelope.network_id());

let zkapp = match envelope.inner() {
TransactionKind::ZkApp(zkapp) => zkapp,
_ => panic!("compatibility vector must be a zkApp transaction"),
};
let json = serde_json::to_string(&zkapp).expect("failed serializing compatibility payload");

write_json_str_pretty(message_path, &json)
.expect("failed writing compatibility transaction payload");

network_cli_arg
}

fn run_compat_case(
case_name: &str,
group_binary: &Path,
sign_binary: &Path,
root: &Path,
vector: &ZkAppTestVector,
) {
let workdir = root.join(case_name);
fs::create_dir_all(&workdir)
.unwrap_or_else(|_| panic!("failed to create case directory {}", workdir.display()));

let participants = (0..NUM_PARTICIPANTS)
.map(|i| introduce_participant(group_binary, &workdir, &format!("p{}", i)))
.collect::<Vec<CliParticipant>>();

greet_participants(group_binary, &workdir, &participants);

form_group_with_dkg(
group_binary,
&workdir,
&participants,
THRESHOLD,
SERVER_URL,
&format!("compat-{case_name}"),
)
.unwrap_or_else(|_| panic!("failed to form group for case {case_name}"));

let (group_pk_hex, group_pk_mina) =
group_keys_from_config(group_binary, &workdir, &participants[0].toml);

let message_path = workdir.join(format!("{}.json", vector.name));
let network_id = write_vector_message(&message_path, vector);

let signing_participants = participants
.iter()
.map(|p| SigningParticipant {
config_path: p.toml.clone(),
pubkey_hex: p.pubkey_hex.clone(),
})
.collect::<Vec<_>>();

sign_with_binary(
sign_binary,
&workdir,
&group_pk_hex,
&message_path,
SIG_FILE,
&network_id,
SERVER_URL,
THRESHOLD,
&signing_participants,
);

let signature_path = workdir.join(SIG_FILE);
assert!(
signature_path.exists(),
"[{}] signature file was not produced at {}",
case_name,
signature_path.display()
);
parse_and_verify_signature(
&group_pk_mina,
&message_path,
&signature_path,
&network_id,
false,
);
}

#[test]
fn compatibility_matrix_between_pre_and_mesa_binaries() {
let pre_binary = build_client_binary(env!("CARGO_MANIFEST_DIR"), Some("pre-compat"), false);
let mesa_binary = build_client_binary(env!("CARGO_MANIFEST_DIR"), Some("mesa-compat"), true);

let temp_dir = TempDir::new().expect("failed to create temp compatibility test directory");
let root = temp_dir.path();

let _frostd = ChildGuard(start_frostd(root).expect("failed to start frostd"));

let vectors = get_zkapp_test_vectors();
assert!(
!vectors.is_empty(),
"expected at least one zkapp test vector for active feature"
);
let vector = vectors[0].clone();

let mesa_active = mina_tx::zkapp_tx::IS_MESA_HARDFORK;
let (case_name, group_binary, sign_binary) = if mesa_active {
(
format!("pre_to_mesa__{}", vector.name),
pre_binary.as_path(),
mesa_binary.as_path(),
)
} else {
(
format!("mesa_to_pre__{}", vector.name),
mesa_binary.as_path(),
pre_binary.as_path(),
)
};

run_compat_case(case_name.as_str(), group_binary, sign_binary, root, &vector);
}
Loading