Skip to content
Merged
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
76 changes: 63 additions & 13 deletions crates/key-server/src/tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ use crate::errors::InternalError::Failure;
use crate::signed_message::signed_request;
use crate::tests::externals::get_key;
use crate::tests::test_utils::{
build_partial_key_servers, create_committee_key_server_onchain, create_test_server,
execute_programmable_transaction,
add_partial_key_server, create_test_server, execute_programmable_transaction,
};
use crate::tests::whitelist::{add_user_to_whitelist, create_whitelist, whitelist_create_ptb};
use crate::{app, time, Certificate, DefaultEncoding, FetchKeyRequest};
Expand Down Expand Up @@ -53,6 +52,7 @@ use shared_crypto::intent::IntentMessage;
use std::str::FromStr;
use std::time::Duration;
use sui_rpc::client::Client as SuiGrpcClient;
use sui_sdk::rpc_types::ObjectChange;
use sui_sdk_types::Address;
use sui_types::base_types::{ObjectID, SuiAddress};
use sui_types::crypto::Signature;
Expand Down Expand Up @@ -376,7 +376,7 @@ async fn test_fetch_key() {

#[tokio::test]
async fn test_committee_server_hot_reload_and_verify_pop() {
let tc = SealTestCluster::new(0, "seal_testnet").await;
let tc = SealTestCluster::new(0, "seal").await;
let (seal_package, _) = tc.publish("seal").await;
let (package_id, _) = tc.registry;

Expand All @@ -398,18 +398,58 @@ async fn test_committee_server_hot_reload_and_verify_pop() {

let master_pk = G2Element::zero();
let member_address = tc.test_cluster().get_address_0();
let member2_address = tc.test_cluster().get_address_1();

// Create on-chain a committee mode KeyServer with one partial key server (party_id_0, partial_pk_0).
let key_server_id = create_committee_key_server_onchain(
tc.test_cluster(),
// Create on-chain a committee mode KeyServer with 2 partial key servers.
let mut builder = ProgrammableTransactionBuilder::new();
let partial_key_servers = add_partial_key_server(
&mut builder,
package_id,
None, // Create new VecMap
member_address,
&partial_pk_0,
party_id_0,
&master_pk,
1, // threshold
)
.await;
);
let partial_key_servers = add_partial_key_server(
&mut builder,
package_id,
Some(partial_key_servers),
member2_address,
&partial_pk_0, // Use test partial pk
party_id_1,
);

// Create committee
let name = builder.pure("test_committee".to_string()).unwrap();
let threshold_arg = builder.pure(2u16).unwrap();
let master_pk_bytes = builder.pure(master_pk.to_byte_array().to_vec()).unwrap();
let key_server = builder.programmable_move_call(
package_id,
sui_types::Identifier::new("key_server").unwrap(),
sui_types::Identifier::new("create_committee_v2").unwrap(),
vec![],
vec![name, threshold_arg, master_pk_bytes, partial_key_servers],
);
builder.transfer_arg(member_address, key_server);

let response = execute_programmable_transaction(&tc, member_address, builder.finish()).await;
let key_server_id = response
.object_changes
.unwrap()
.into_iter()
.find_map(|change| {
if let ObjectChange::Created {
object_type,
object_id,
..
} = change
&& object_type.name.as_str() == "KeyServer"
{
return Some(object_id);
}
None
})
.expect("KeyServer object not found in transaction response");

// Get object version and digest for later update.
let key_server_obj = tc
Expand Down Expand Up @@ -457,15 +497,25 @@ async fn test_committee_server_hot_reload_and_verify_pop() {
// Current version is 0.
assert_eq!(current_version.load(Ordering::Relaxed), 0);

// Update partial key servers on-chain to new partial key server (party_id_1, partial_pk_1).
// Update partial key servers on-chain with 2 servers.
let mut builder = ProgrammableTransactionBuilder::new();
let partial_key_servers = build_partial_key_servers(

let partial_key_servers = add_partial_key_server(
&mut builder,
package_id,
None, // Create new VecMap
member_address,
&partial_pk_1,
party_id_1,
);
let partial_key_servers = add_partial_key_server(
&mut builder,
package_id,
Some(partial_key_servers),
member2_address,
&partial_pk_1,
party_id_0,
);

let key_server_obj = builder
.obj(sui_types::transaction::ObjectArg::ImmOrOwnedObject((
Expand All @@ -475,7 +525,7 @@ async fn test_committee_server_hot_reload_and_verify_pop() {
)))
.unwrap();

let threshold = builder.pure(1u16).unwrap();
let threshold = builder.pure(2u16).unwrap();
builder.programmable_move_call(
package_id,
sui_types::Identifier::new("key_server").unwrap(),
Expand Down
104 changes: 20 additions & 84 deletions crates/key-server/src/tests/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::{
time::Duration,
};
use sui_rpc::client::Client as SuiGrpcClient;
use sui_sdk::rpc_types::{ObjectChange, SuiTransactionBlockResponse};
use sui_sdk::rpc_types::SuiTransactionBlockResponse;
use sui_sdk::SuiClient;
use sui_sdk_types::Address;
use sui_types::base_types::{ObjectID, SuiAddress};
Expand All @@ -34,7 +34,6 @@ use sui_types::transaction::{
TEST_ONLY_GAS_UNIT_FOR_HEAVY_COMPUTATION_STORAGE,
};
use sui_types::{Identifier, TypeTag};
use test_cluster::TestCluster;

/// Helper function to create a test server with any ServerMode.
pub(crate) async fn create_test_server(
Expand Down Expand Up @@ -163,20 +162,22 @@ pub(crate) async fn execute_programmable_transaction(
response
}

/// Helper function to create a VecMap of one member (address, partial_pk, url, party_id).
pub(crate) fn build_partial_key_servers(
/// Helper function to add a partial key server to an existing VecMap or create a new one.
/// If vec_map is None, creates a new empty VecMap first.
pub(crate) fn add_partial_key_server(
builder: &mut ProgrammableTransactionBuilder,
package_id: ObjectID,
vec_map: Option<Argument>,
member_address: SuiAddress,
partial_pk: &G2Element,
party_id: u16,
) -> Argument {
// Create partial key server
let partial_pk_bytes = builder.pure(partial_pk.to_byte_array().to_vec()).unwrap();
let url_arg = builder.pure("testurl.com".to_string()).unwrap();
let name_arg = builder.pure("testserver".to_string()).unwrap();
let party_id_arg = builder.pure(party_id).unwrap();

let partial_key_server_arg = builder.programmable_move_call(
let partial_key_server = builder.programmable_move_call(
package_id,
Identifier::new("key_server").unwrap(),
Identifier::new("create_partial_key_server").unwrap(),
Expand All @@ -192,90 +193,25 @@ pub(crate) fn build_partial_key_servers(
type_params: vec![],
}));

// Create a vecmap and insert the member.
let vec_map = builder.programmable_move_call(
vec_map_module,
Identifier::new("vec_map").unwrap(),
Identifier::new("empty").unwrap(),
vec![TypeTag::Address, partial_key_server_type.clone()],
vec![],
);
// Create new VecMap if needed
let vec_map = vec_map.unwrap_or_else(|| {
builder.programmable_move_call(
vec_map_module,
Identifier::new("vec_map").unwrap(),
Identifier::new("empty").unwrap(),
vec![TypeTag::Address, partial_key_server_type.clone()],
vec![],
)
});

// Insert into VecMap
let member_addr_arg = builder.pure(member_address).unwrap();
builder.programmable_move_call(
vec_map_module,
Identifier::new("vec_map").unwrap(),
Identifier::new("insert").unwrap(),
vec![TypeTag::Address, partial_key_server_type],
vec![vec_map, member_addr_arg, partial_key_server_arg],
vec![vec_map, member_addr_arg, partial_key_server],
);
vec_map
}

/// Helper function to create a committee KeyServer on-chain and return its ObjectID.
pub(crate) async fn create_committee_key_server_onchain(
cluster: &TestCluster,
package_id: ObjectID,
member_address: SuiAddress,
partial_pk: &G2Element,
party_id: u16,
master_pk: &G2Element,
threshold: u16,
) -> ObjectID {
let mut builder = ProgrammableTransactionBuilder::new();
let partial_key_servers = build_partial_key_servers(
&mut builder,
package_id,
member_address,
partial_pk,
party_id,
);

let name = builder.pure("test_committee".to_string()).unwrap();
let threshold_arg = builder.pure(threshold).unwrap();
let master_pk_bytes = builder.pure(master_pk.to_byte_array().to_vec()).unwrap();
let key_server = builder.programmable_move_call(
package_id,
Identifier::new("key_server").unwrap(),
Identifier::new("create_committee_v2").unwrap(),
vec![],
vec![name, threshold_arg, master_pk_bytes, partial_key_servers],
);
builder.transfer_arg(member_address, key_server);

let pt = builder.finish();
let test_builder = cluster
.test_transaction_builder_with_sender(member_address)
.await;
let gas_object = test_builder.gas_object();
let gas_price = cluster.get_reference_gas_price().await;
let gas_budget = gas_price * TEST_ONLY_GAS_UNIT_FOR_HEAVY_COMPUTATION_STORAGE;
let tx_data = TransactionData::new_programmable(
member_address,
vec![gas_object],
pt,
gas_budget,
gas_price,
);

let response = cluster.sign_and_execute_transaction(&tx_data).await;
assert!(response.status_ok().unwrap());

// Extract the created KeyServer object ID.
response
.object_changes
.unwrap()
.into_iter()
.find_map(|change| {
if let ObjectChange::Created {
object_type,
object_id,
..
} = change
&& object_type.name.as_str() == "KeyServer"
{
return Some(object_id);
}
None
})
.expect("KeyServer object not found in transaction response")
}
2 changes: 1 addition & 1 deletion move/committee/Move.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ name = "seal_committee"
edition = "2024"

[dependencies]
seal_testnet = { local = "../seal_testnet" }
seal = { local = "../seal" }
10 changes: 2 additions & 8 deletions move/committee/sources/committee.move
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@

module seal_committee::seal_committee;

use seal_testnet::key_server::{
KeyServer,
create_partial_key_server,
create_committee_v2,
PartialKeyServer
};
use seal::key_server::{KeyServer, create_partial_key_server, create_committee_v2, PartialKeyServer};
use std::string::String;
use sui::{
bls12381::{g1_from_bytes, g2_from_bytes},
Expand Down Expand Up @@ -254,8 +249,7 @@ public fun propose_for_rotation(
) {
committee.check_rotation_consistency(&old_committee);
let old_committee_id = object::id(&old_committee);
let key_server = dof::remove<ID, KeyServer>(&mut old_committee.id, old_committee_id);
key_server.assert_committee_server_v2();
let key_server: KeyServer = dof::remove(&mut old_committee.id, old_committee_id);
committee.propose_internal(partial_pks, *key_server.pk(), ctx);
committee.try_finalize_for_rotation(old_committee, key_server);
}
Expand Down
3 changes: 1 addition & 2 deletions move/committee/tests/committee_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// SPDX-License-Identifier: Apache-2.0

#[test_only]
#[allow(unused_mut_ref, unused_variable, dead_code)]
module seal_committee::seal_committee_tests;

use seal::key_server::KeyServer;
use seal_committee::seal_committee::{
Self,
Committee,
Expand All @@ -18,7 +18,6 @@ use seal_committee::seal_committee::{
commit_upgrade,
reset_proposal
};
use seal_testnet::key_server::KeyServer;
use std::string;
use sui::{bls12381::{g1_generator, g2_generator}, package, test_scenario::{Self, Scenario}};

Expand Down
16 changes: 10 additions & 6 deletions move/patterns/sources/voting.move
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public fun cast_vote(vote: &mut Vote, encrypted_vote: vector<u8>, ctx: &mut TxCo

// Check that the encryptions were created for this vote.
assert!(encrypted_vote.id() == vote.id(), EInvalidVote);
assert!(encrypted_vote.package_id() == @patterns, EInvalidVote);
assert!(encrypted_vote.package_id() == @0x0, EInvalidVote);

// This aborts if the sender is not a voter.
let index = vote.voters.find_index!(|voter| voter == ctx.sender()).destroy_some();
Expand Down Expand Up @@ -157,7 +157,7 @@ public fun finalize_vote(
// Verify the derived keys
let verified_derived_keys: vector<VerifiedDerivedKey> = verify_derived_keys(
&derived_keys.map_ref!(|k| g1_from_bytes(k)),
@patterns,
@0x0,
vote.id(),
&key_servers
.map_ref!(|ks1| vote.key_servers.find_index!(|ks2| ks1 == ks2).destroy_some())
Expand Down Expand Up @@ -191,7 +191,11 @@ public fun finalize_vote(

#[test]
fun test_vote() {
use seal::key_server::{create_and_transfer_v1, KeyServer, destroy_for_testing as ks_destroy};
use seal::key_server::{
create_and_transfer_v2_independent_server,
KeyServer,
destroy_for_testing as ks_destroy,
};
use sui::test_scenario::{Self, next_tx, ctx};

let addr1 = @0xA;
Expand All @@ -200,7 +204,7 @@ fun test_vote() {
// Setup key servers.
let pk0 =
x"a58bfa576a8efe2e2730bc664b3dbe70257d8e35106e4af7353d007dba092d722314a0aeb6bca5eed735466bbf471aef01e4da8d2efac13112c51d1411f6992b8604656ea2cf6a33ec10ce8468de20e1d7ecbfed8688a281d462f72a41602161";
create_and_transfer_v1(
create_and_transfer_v2_independent_server(
b"mysten0".to_string(),
b"https://mysten-labs.com".to_string(),
0,
Expand All @@ -212,7 +216,7 @@ fun test_vote() {

let pk1 =
x"a9ce55cfa7009c3116ea29341151f3c40809b816f4ad29baa4f95c1bb23085ef02a46cf1ae5bd570d99b0c6e9faf525306224609300b09e422ae2722a17d2a969777d53db7b52092e4d12014da84bffb1e845c2510e26b3c259ede9e42603cd6";
create_and_transfer_v1(
create_and_transfer_v2_independent_server(
b"mysten1".to_string(),
b"https://mysten-labs.com".to_string(),
0,
Expand All @@ -224,7 +228,7 @@ fun test_vote() {

let pk2 =
x"93b3220f4f3a46fb33074b590cda666c0ebc75c7157d2e6492c62b4aebc452c29f581361a836d1abcbe1386268a5685103d12dec04aadccaebfa46d4c92e2f2c0381b52d6f2474490d02280a9e9d8c889a3fce2753055e06033f39af86676651";
create_and_transfer_v1(
create_and_transfer_v2_independent_server(
b"mysten2".to_string(),
b"https://mysten-labs.com".to_string(),
0,
Expand Down
Loading
Loading