mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-09 01:29:39 +00:00
fix: rebuild artifacts
This commit is contained in:
parent
636fc9dd30
commit
9927e6e690
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3600,7 +3600,6 @@ dependencies = [
|
|||||||
"sequencer_service_rpc",
|
"sequencer_service_rpc",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"test_program_methods",
|
|
||||||
"testcontainers",
|
"testcontainers",
|
||||||
"testnet_initial_state",
|
"testnet_initial_state",
|
||||||
"token_core",
|
"token_core",
|
||||||
|
|||||||
BIN
artifacts/test_program_methods/group_pda_router.bin
Normal file
BIN
artifacts/test_program_methods/group_pda_router.bin
Normal file
Binary file not shown.
Binary file not shown.
@ -22,7 +22,6 @@ ata_core.workspace = true
|
|||||||
indexer_service_rpc.workspace = true
|
indexer_service_rpc.workspace = true
|
||||||
sequencer_service_rpc = { workspace = true, features = ["client"] }
|
sequencer_service_rpc = { workspace = true, features = ["client"] }
|
||||||
wallet-ffi.workspace = true
|
wallet-ffi.workspace = true
|
||||||
test_program_methods.workspace = true
|
|
||||||
testnet_initial_state.workspace = true
|
testnet_initial_state.workspace = true
|
||||||
|
|
||||||
url.workspace = true
|
url.workspace = true
|
||||||
|
|||||||
@ -1,145 +0,0 @@
|
|||||||
#![expect(
|
|
||||||
clippy::tests_outside_test_module,
|
|
||||||
reason = "Integration test file, not inside a #[cfg(test)] module"
|
|
||||||
)]
|
|
||||||
|
|
||||||
//! Group-owned private PDA lifecycle integration test.
|
|
||||||
//!
|
|
||||||
//! Demonstrates:
|
|
||||||
//! 1. GMS creation and sealed distribution between controllers.
|
|
||||||
//! 2. Key agreement: both controllers derive identical keys from the shared GMS.
|
|
||||||
//! 3. Forward secrecy: ratcheting the GMS produces different keys, locking out removed members.
|
|
||||||
|
|
||||||
use anyhow::{Context as _, Result};
|
|
||||||
use integration_tests::TestContext;
|
|
||||||
use key_protocol::key_management::group_key_holder::GroupKeyHolder;
|
|
||||||
use log::info;
|
|
||||||
use nssa::{AccountId, program::Program};
|
|
||||||
use nssa_core::program::PdaSeed;
|
|
||||||
use tokio::test;
|
|
||||||
|
|
||||||
/// Group PDA lifecycle: create group, distribute GMS, verify key agreement, revoke.
|
|
||||||
#[test]
|
|
||||||
async fn group_pda_lifecycle() -> Result<()> {
|
|
||||||
let ctx = TestContext::new().await?;
|
|
||||||
|
|
||||||
let alice_holder = GroupKeyHolder::new();
|
|
||||||
assert_eq!(alice_holder.epoch(), 0);
|
|
||||||
let pda_seed = PdaSeed::new([42_u8; 32]);
|
|
||||||
let group_pda_spender =
|
|
||||||
Program::new(test_program_methods::GROUP_PDA_SPENDER_ELF.to_vec()).unwrap();
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// Act 1: GMS creation and sealed distribution
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
info!("Act 1: creating group and distributing GMS");
|
|
||||||
|
|
||||||
let alice_npk = alice_holder
|
|
||||||
.derive_keys_for_pda(&pda_seed)
|
|
||||||
.generate_nullifier_public_key();
|
|
||||||
|
|
||||||
let bob_private_account = ctx.existing_private_accounts()[1];
|
|
||||||
let (bob_keychain, _) = ctx
|
|
||||||
.wallet()
|
|
||||||
.storage()
|
|
||||||
.user_data
|
|
||||||
.get_private_account(bob_private_account)
|
|
||||||
.cloned()
|
|
||||||
.context("Bob's private account not found")?;
|
|
||||||
|
|
||||||
// Alice seals GMS for Bob, Bob unseals
|
|
||||||
let sealed = alice_holder.seal_for(&bob_keychain.viewing_public_key);
|
|
||||||
let bob_holder =
|
|
||||||
GroupKeyHolder::unseal(&sealed, &bob_keychain.private_key_holder.viewing_secret_key)
|
|
||||||
.expect("Bob should unseal the GMS");
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// Act 2: Key agreement
|
|
||||||
//
|
|
||||||
// Both controllers independently derive identical keys for the same PDA
|
|
||||||
// seed. Neither communicated any per-PDA keys — they derived them from
|
|
||||||
// the shared GMS.
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
info!("Act 2: verifying key agreement");
|
|
||||||
|
|
||||||
let bob_npk = bob_holder
|
|
||||||
.derive_keys_for_pda(&pda_seed)
|
|
||||||
.generate_nullifier_public_key();
|
|
||||||
assert_eq!(
|
|
||||||
alice_npk, bob_npk,
|
|
||||||
"Key agreement: identical NPK from shared GMS"
|
|
||||||
);
|
|
||||||
|
|
||||||
let group_account_id =
|
|
||||||
AccountId::for_private_pda(&group_pda_spender.id(), &pda_seed, &alice_npk);
|
|
||||||
info!("Group PDA AccountId: {group_account_id}");
|
|
||||||
|
|
||||||
// Both derive the same AccountId independently
|
|
||||||
let bob_account_id = AccountId::for_private_pda(&group_pda_spender.id(), &pda_seed, &bob_npk);
|
|
||||||
assert_eq!(group_account_id, bob_account_id);
|
|
||||||
|
|
||||||
info!("Act 2 complete: key agreement verified");
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// Act 3: Revocation and forward secrecy
|
|
||||||
//
|
|
||||||
// Alice ratchets the GMS to exclude Bob. The new keys produce a different
|
|
||||||
// NPK and therefore a different AccountId. Bob's frozen holder can no
|
|
||||||
// longer derive the new keys.
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
|
|
||||||
info!("Act 3: ratchet and forward secrecy");
|
|
||||||
|
|
||||||
let mut ratcheted_holder = alice_holder;
|
|
||||||
ratcheted_holder.ratchet([99_u8; 32]);
|
|
||||||
assert_eq!(ratcheted_holder.epoch(), 1);
|
|
||||||
|
|
||||||
let ratcheted_npk = ratcheted_holder
|
|
||||||
.derive_keys_for_pda(&pda_seed)
|
|
||||||
.generate_nullifier_public_key();
|
|
||||||
|
|
||||||
let bob_stale_npk = bob_holder
|
|
||||||
.derive_keys_for_pda(&pda_seed)
|
|
||||||
.generate_nullifier_public_key();
|
|
||||||
|
|
||||||
// Forward secrecy: ratcheted keys differ from Bob's stale keys
|
|
||||||
assert_ne!(ratcheted_npk, bob_stale_npk);
|
|
||||||
assert_ne!(ratcheted_npk, alice_npk);
|
|
||||||
|
|
||||||
// Different AccountId after ratchet
|
|
||||||
let new_account_id =
|
|
||||||
AccountId::for_private_pda(&group_pda_spender.id(), &pda_seed, &ratcheted_npk);
|
|
||||||
assert_ne!(group_account_id, new_account_id);
|
|
||||||
|
|
||||||
// Bob's stale keys still point to the old address
|
|
||||||
let bob_stale_account_id =
|
|
||||||
AccountId::for_private_pda(&group_pda_spender.id(), &pda_seed, &bob_stale_npk);
|
|
||||||
assert_eq!(bob_stale_account_id, group_account_id);
|
|
||||||
assert_ne!(bob_stale_account_id, new_account_id);
|
|
||||||
|
|
||||||
// Sealed round-trip of ratcheted GMS
|
|
||||||
let (alice_kc, _) = ctx
|
|
||||||
.wallet()
|
|
||||||
.storage()
|
|
||||||
.user_data
|
|
||||||
.get_private_account(ctx.existing_private_accounts()[0])
|
|
||||||
.cloned()
|
|
||||||
.context("Alice's keys not found")?;
|
|
||||||
let sealed_ratcheted = ratcheted_holder.seal_for(&alice_kc.viewing_public_key);
|
|
||||||
let restored = GroupKeyHolder::unseal(
|
|
||||||
&sealed_ratcheted,
|
|
||||||
&alice_kc.private_key_holder.viewing_secret_key,
|
|
||||||
)
|
|
||||||
.expect("Should unseal ratcheted GMS");
|
|
||||||
assert_eq!(
|
|
||||||
restored.dangerous_raw_gms(),
|
|
||||||
ratcheted_holder.dangerous_raw_gms()
|
|
||||||
);
|
|
||||||
assert_eq!(restored.epoch(), 1);
|
|
||||||
|
|
||||||
info!("Act 3 complete: forward secrecy verified");
|
|
||||||
info!("Group PDA lifecycle test complete");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@ -598,4 +598,73 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Full lifecycle: create group, distribute GMS via seal/unseal, verify key
|
||||||
|
/// agreement, ratchet for forward secrecy.
|
||||||
|
#[test]
|
||||||
|
fn group_pda_lifecycle() {
|
||||||
|
use nssa_core::account::AccountId;
|
||||||
|
|
||||||
|
let alice_holder = GroupKeyHolder::new();
|
||||||
|
assert_eq!(alice_holder.epoch(), 0);
|
||||||
|
let pda_seed = PdaSeed::new([42_u8; 32]);
|
||||||
|
let program_id: nssa_core::program::ProgramId = [1; 8];
|
||||||
|
|
||||||
|
// Derive Alice's keys
|
||||||
|
let alice_keys = alice_holder.derive_keys_for_pda(&pda_seed);
|
||||||
|
let alice_npk = alice_keys.generate_nullifier_public_key();
|
||||||
|
|
||||||
|
// Seal GMS for Bob using Bob's viewing key, Bob unseals
|
||||||
|
let bob_ssk = SecretSpendingKey([77_u8; 32]);
|
||||||
|
let bob_keys = bob_ssk.produce_private_key_holder(None);
|
||||||
|
let bob_vpk = bob_keys.generate_viewing_public_key();
|
||||||
|
let bob_vsk = bob_keys.viewing_secret_key;
|
||||||
|
|
||||||
|
let sealed = alice_holder.seal_for(&bob_vpk);
|
||||||
|
let bob_holder =
|
||||||
|
GroupKeyHolder::unseal(&sealed, &bob_vsk).expect("Bob should unseal the GMS");
|
||||||
|
|
||||||
|
// Key agreement: both derive identical NPK and AccountId
|
||||||
|
let bob_npk = bob_holder
|
||||||
|
.derive_keys_for_pda(&pda_seed)
|
||||||
|
.generate_nullifier_public_key();
|
||||||
|
assert_eq!(alice_npk, bob_npk);
|
||||||
|
|
||||||
|
let alice_account_id = AccountId::for_private_pda(&program_id, &pda_seed, &alice_npk);
|
||||||
|
let bob_account_id = AccountId::for_private_pda(&program_id, &pda_seed, &bob_npk);
|
||||||
|
assert_eq!(alice_account_id, bob_account_id);
|
||||||
|
|
||||||
|
// Ratchet: forward secrecy
|
||||||
|
let mut ratcheted_holder = alice_holder;
|
||||||
|
ratcheted_holder.ratchet([99_u8; 32]);
|
||||||
|
assert_eq!(ratcheted_holder.epoch(), 1);
|
||||||
|
|
||||||
|
let ratcheted_npk = ratcheted_holder
|
||||||
|
.derive_keys_for_pda(&pda_seed)
|
||||||
|
.generate_nullifier_public_key();
|
||||||
|
let bob_stale_npk = bob_holder
|
||||||
|
.derive_keys_for_pda(&pda_seed)
|
||||||
|
.generate_nullifier_public_key();
|
||||||
|
|
||||||
|
assert_ne!(ratcheted_npk, bob_stale_npk);
|
||||||
|
assert_ne!(ratcheted_npk, alice_npk);
|
||||||
|
|
||||||
|
let new_account_id = AccountId::for_private_pda(&program_id, &pda_seed, &ratcheted_npk);
|
||||||
|
assert_ne!(alice_account_id, new_account_id);
|
||||||
|
|
||||||
|
// Bob's stale keys point to old address
|
||||||
|
let bob_stale_id = AccountId::for_private_pda(&program_id, &pda_seed, &bob_stale_npk);
|
||||||
|
assert_eq!(bob_stale_id, alice_account_id);
|
||||||
|
assert_ne!(bob_stale_id, new_account_id);
|
||||||
|
|
||||||
|
// Sealed round-trip of ratcheted GMS
|
||||||
|
let sealed_ratcheted = ratcheted_holder.seal_for(&bob_vpk);
|
||||||
|
let restored = GroupKeyHolder::unseal(&sealed_ratcheted, &bob_vsk)
|
||||||
|
.expect("Should unseal ratcheted GMS");
|
||||||
|
assert_eq!(
|
||||||
|
restored.dangerous_raw_gms(),
|
||||||
|
ratcheted_holder.dangerous_raw_gms()
|
||||||
|
);
|
||||||
|
assert_eq!(restored.epoch(), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user