@@ -12,12 +12,13 @@ use near_mpc_contract_interface::{
1212 client:: MpcContractHandle ,
1313 method_names,
1414 types:: {
15- AccountId as ContractAccountId , Attestation , AuthScheme , CKDAppPublicKey , ChainEntry ,
16- ChainRouting , DomainConfig , DomainId , DomainPurpose , Ed25519PublicKey , EpochId ,
17- ForeignChain , GovernanceThreshold , GovernanceThresholdParameters , MockAttestation ,
18- ParticipantId , ParticipantInfo , Participants , Payload , ProposeUpdateArgs ,
19- ProposedGovernanceThresholdParameters , Protocol , ProtocolContractState , ProviderConfig ,
20- ProviderId , ReconstructionThreshold , SignRequestArgs ,
15+ AccountId as ContractAccountId , Attestation , AuthScheme , BackupServiceInfo ,
16+ CKDAppPublicKey , ChainEntry , ChainRouting , DestinationNodeInfo , DomainConfig , DomainId ,
17+ DomainPurpose , Ed25519PublicKey , EpochId , ForeignChain , GovernanceThreshold ,
18+ GovernanceThresholdParameters , MockAttestation , ParticipantId , ParticipantInfo ,
19+ Participants , Payload , ProposeUpdateArgs , ProposedGovernanceThresholdParameters , Protocol ,
20+ ProtocolContractState , ProviderConfig , ProviderId , ReconstructionThreshold ,
21+ SignRequestArgs ,
2122 } ,
2223} ;
2324use rand:: SeedableRng ;
@@ -48,7 +49,6 @@ pub fn cluster_poll_retry() -> ConstantBuilder {
4849 )
4950}
5051
51- const NODE_MANAGEMENT_DEPOSIT : near_kit:: NearToken = near_kit:: NearToken :: from_yoctonear ( 1 ) ;
5252// The contract's default `key_event_timeout_blocks = 30` is ~18 s on
5353// mainnet (~600 ms blocks). The e2e sandbox runs ~8 blocks/s, so the
5454// same 30 collapses to ~3.7 s — too tight for the resharing
@@ -57,7 +57,6 @@ const NODE_MANAGEMENT_DEPOSIT: near_kit::NearToken = near_kit::NearToken::from_y
5757// load. Override to 240 blocks (~30 s in sandbox) as a comfortable
5858// budget over mainnet's effective headroom.
5959const KEY_EVENT_TIMEOUT_BLOCKS : u64 = 240 ;
60- const VOTE_FOREIGN_CHAIN_GAS : near_kit:: Gas = near_kit:: Gas :: from_tgas ( 30 ) ;
6160const CONTRACT_DEPLOY_TIMEOUT : Duration = Duration :: from_secs ( 15 ) ;
6261const PROPOSER_NODE_INDEX : usize = 0 ;
6362
@@ -520,9 +519,34 @@ impl MpcCluster {
520519 /// `Initializing` state. Does NOT wait for key generation to complete —
521520 /// use `add_domains_and_wait` for the full flow.
522521 pub async fn start_add_domains ( & self , domains : Vec < DomainConfig > ) -> anyhow:: Result < ( ) > {
523- let args = json ! ( { "domains" : & domains } ) ;
524- self . call_from_all_nodes_concurrently ( method_names:: VOTE_ADD_DOMAINS , args)
525- . await ?;
522+ let handles: Vec < _ > = self
523+ . nodes
524+ . iter ( )
525+ . zip ( self . node_keys . iter ( ) )
526+ . enumerate ( )
527+ . filter ( |( _, ( node, _) ) | matches ! ( node, MpcNodeState :: Running ( _) ) )
528+ . map ( |( i, ( node, key) ) | {
529+ let client = self
530+ . blockchain
531+ . client_for ( node. account_id ( ) . as_ref ( ) , key) ?;
532+ Ok ( (
533+ i,
534+ node. account_id ( ) . clone ( ) ,
535+ self . contract . handle_for ( client) ,
536+ ) )
537+ } )
538+ . collect :: < anyhow:: Result < Vec < _ > > > ( ) ?;
539+
540+ let votes = handles. iter ( ) . map ( |( i, account, contract_handle) | {
541+ let domains = domains. clone ( ) ;
542+ async move {
543+ contract_handle
544+ . vote_add_domains ( domains)
545+ . await
546+ . with_context ( || format ! ( "node {i} ({account}) failed to vote_add_domains" ) )
547+ }
548+ } ) ;
549+ futures:: future:: try_join_all ( votes) . await ?;
526550
527551 self . wait_for_state (
528552 |s| matches ! ( s, ProtocolContractState :: Initializing ( _) ) ,
@@ -539,13 +563,9 @@ impl MpcCluster {
539563 node_index : usize ,
540564 next_domain_id : u64 ,
541565 ) -> anyhow:: Result < near_kit:: FinalExecutionOutcome > {
542- let client = self . operator_client_for ( node_index) ?;
543566 self . contract
544- . call_from (
545- & client,
546- method_names:: VOTE_CANCEL_KEYGEN ,
547- json ! ( { "next_domain_id" : next_domain_id } ) ,
548- )
567+ . handle_for ( self . operator_client_for ( node_index) ?)
568+ . vote_cancel_keygen ( next_domain_id)
549569 . await
550570 . with_context ( || format ! ( "node {node_index} failed to send cancel keygen vote" ) )
551571 }
@@ -582,8 +602,8 @@ impl MpcCluster {
582602 } ;
583603
584604 tracing:: info!( ?prospective_epoch_id, new_threshold, "voting for resharing" ) ;
585- let args = json ! ( { " prospective_epoch_id" : prospective_epoch_id , " proposal" : proposal } ) ;
586- self . vote_resharing ( current_participants , args ) . await ?;
605+ self . vote_resharing ( current_participants , prospective_epoch_id, proposal)
606+ . await ?;
587607
588608 self . wait_for_state (
589609 |s| matches ! ( s, ProtocolContractState :: Resharing ( _) ) ,
@@ -641,7 +661,8 @@ impl MpcCluster {
641661 async fn vote_resharing (
642662 & self ,
643663 current_participants : & Participants ,
644- args : serde_json:: Value ,
664+ prospective_epoch_id : EpochId ,
665+ proposal : ProposedGovernanceThresholdParameters ,
645666 ) -> anyhow:: Result < ( ) > {
646667 let current_accounts: std:: collections:: HashSet < _ > = current_participants
647668 . participants
@@ -664,10 +685,10 @@ impl MpcCluster {
664685 }
665686
666687 for i in participants_first. iter ( ) . chain ( candidates_second. iter ( ) ) {
667- let client = self . operator_client_for ( * i) ?;
668688 let outcome = self
669689 . contract
670- . call_from ( & client, method_names:: VOTE_NEW_PARAMETERS , args. clone ( ) )
690+ . handle_for ( self . operator_client_for ( * i) ?)
691+ . vote_new_parameters ( prospective_epoch_id, proposal. clone ( ) )
671692 . await
672693 . with_context ( || format ! ( "node {i} failed to send resharing vote" ) ) ?;
673694 if !outcome. is_success ( ) {
@@ -689,9 +710,9 @@ impl MpcCluster {
689710 & self ,
690711 node_index : usize ,
691712 ) -> anyhow:: Result < near_kit:: FinalExecutionOutcome > {
692- let client = self . operator_client_for ( node_index) ?;
693713 self . contract
694- . call_from ( & client, method_names:: VOTE_CANCEL_RESHARING , json ! ( { } ) )
714+ . handle_for ( self . operator_client_for ( node_index) ?)
715+ . vote_cancel_resharing ( )
695716 . await
696717 . with_context ( || format ! ( "node {node_index} failed to send cancel resharing vote" ) )
697718 }
@@ -758,40 +779,6 @@ impl MpcCluster {
758779 Ok ( ( ) )
759780 }
760781
761- async fn call_from_all_nodes_concurrently (
762- & self ,
763- method : & str ,
764- args : serde_json:: Value ,
765- ) -> anyhow:: Result < ( ) > {
766- let clients: Vec < _ > = self
767- . nodes
768- . iter ( )
769- . zip ( self . node_keys . iter ( ) )
770- . enumerate ( )
771- . filter ( |( _, ( node, _) ) | matches ! ( node, MpcNodeState :: Running ( _) ) )
772- . map ( |( i, ( node, key) ) | {
773- let client = self
774- . blockchain
775- . client_for ( node. account_id ( ) . as_ref ( ) , key) ?;
776- Ok ( ( i, node. account_id ( ) . clone ( ) , client) )
777- } )
778- . collect :: < anyhow:: Result < Vec < _ > > > ( ) ?;
779-
780- let futures = clients. iter ( ) . map ( |( i, account, client) | {
781- let args = args. clone ( ) ;
782- let method = method. to_string ( ) ;
783- async move {
784- self . contract
785- . call_from ( client, & method, args)
786- . await
787- . with_context ( || format ! ( "node {i} ({account}) failed to call {method}" ) )
788- }
789- } ) ;
790-
791- futures:: future:: try_join_all ( futures) . await ?;
792- Ok ( ( ) )
793- }
794-
795782 pub fn client_for ( & self , account_id : & AccountId ) -> anyhow:: Result < NearKitCaller > {
796783 let key = self
797784 . user_accounts
@@ -871,17 +858,13 @@ impl MpcCluster {
871858 pub async fn register_backup_service (
872859 & self ,
873860 node_index : usize ,
874- backup_service_info : serde_json :: Value ,
861+ backup_service_info : BackupServiceInfo ,
875862 ) -> anyhow:: Result < near_kit:: FinalExecutionOutcome > {
876- let client = self . operator_client_for ( node_index) ?;
877863 self . contract
878- . call_from_deposit (
879- & client,
880- method_names:: REGISTER_BACKUP_SERVICE ,
881- json ! ( { "backup_service_info" : backup_service_info } ) ,
882- NODE_MANAGEMENT_DEPOSIT ,
883- )
864+ . handle_for ( self . operator_client_for ( node_index) ?)
865+ . register_backup_service ( backup_service_info)
884866 . await
867+ . context ( "failed to register backup service" )
885868 }
886869 /// View the foreign chains the contract accepts requests for.
887870 pub async fn view_foreign_chains_supported_by_contract (
@@ -907,19 +890,11 @@ impl MpcCluster {
907890 node_index : usize ,
908891 foreign_chain_support : & near_mpc_contract_interface:: types:: SupportedForeignChains ,
909892 ) -> anyhow:: Result < near_kit:: FinalExecutionOutcome > {
910- let node = & self . nodes [ node_index] ;
911- let client = self
912- . blockchain
913- . client_for ( node. account_id ( ) . as_ref ( ) , & self . operator_keys [ node_index] ) ?;
914893 self . contract
915- . call_from (
916- & client,
917- method_names:: REGISTER_FOREIGN_CHAIN_SUPPORT ,
918- json ! ( {
919- "foreign_chain_support" : serde_json:: to_value( foreign_chain_support) ?,
920- } ) ,
921- )
894+ . handle_for ( self . operator_client_for ( node_index) ?)
895+ . register_foreign_chain_support ( foreign_chain_support. clone ( ) )
922896 . await
897+ . context ( "failed to register foreign chain support" )
923898 }
924899
925900 pub async fn view_available_foreign_chains (
@@ -997,13 +972,8 @@ impl MpcCluster {
997972 . operator_client_for ( idx)
998973 . with_context ( || format ! ( "whitelist_foreign_chains: node {idx}" ) ) ?;
999974 self . contract
1000- . call_from_borsh_with_deposit (
1001- & client,
1002- method_names:: VOTE_UPDATE_FOREIGN_CHAIN_PROVIDERS ,
1003- batch. clone ( ) ,
1004- VOTE_FOREIGN_CHAIN_GAS ,
1005- near_kit:: NearToken :: from_yoctonear ( 0 ) ,
1006- )
975+ . handle_for ( client)
976+ . vote_update_foreign_chain_providers ( batch. clone ( ) )
1007977 . await
1008978 . with_context ( || {
1009979 format ! ( "vote_update_foreign_chain_providers from node {idx} failed" )
@@ -1016,17 +986,13 @@ impl MpcCluster {
1016986 pub async fn start_node_migration (
1017987 & self ,
1018988 node_index : usize ,
1019- destination_node_info : serde_json :: Value ,
989+ destination_node_info : DestinationNodeInfo ,
1020990 ) -> anyhow:: Result < near_kit:: FinalExecutionOutcome > {
1021- let client = self . operator_client_for ( node_index) ?;
1022991 self . contract
1023- . call_from_deposit (
1024- & client,
1025- method_names:: START_NODE_MIGRATION ,
1026- json ! ( { "destination_node_info" : destination_node_info } ) ,
1027- NODE_MANAGEMENT_DEPOSIT ,
1028- )
992+ . handle_for ( self . operator_client_for ( node_index) ?)
993+ . start_node_migration ( destination_node_info)
1029994 . await
995+ . context ( "failed to start node migration" )
1030996 }
1031997
1032998 /// Update the registered URL of a specific node, called from that node's own operator account.
@@ -1035,15 +1001,11 @@ impl MpcCluster {
10351001 node_index : usize ,
10361002 url : String ,
10371003 ) -> anyhow:: Result < near_kit:: FinalExecutionOutcome > {
1038- let client = self . operator_client_for ( node_index) ?;
10391004 self . contract
1040- . call_from_deposit (
1041- & client,
1042- method_names:: UPDATE_PARTICIPANT_URL ,
1043- json ! ( { "url" : url } ) ,
1044- NODE_MANAGEMENT_DEPOSIT ,
1045- )
1005+ . handle_for ( self . operator_client_for ( node_index) ?)
1006+ . update_participant_url ( url)
10461007 . await
1008+ . context ( "failed to update participant url" )
10471009 }
10481010
10491011 /// Send a verify_foreign_transaction request from the default user account.
@@ -1191,10 +1153,10 @@ impl MpcNodeState {
11911153 }
11921154 }
11931155
1194- pub fn near_signer_public_key_str ( & self ) -> String {
1156+ pub fn near_signer_public_key ( & self ) -> Ed25519PublicKey {
11951157 match self {
1196- MpcNodeState :: Running ( n) => n. setup ( ) . near_signer_public_key_str ( ) ,
1197- MpcNodeState :: Stopped ( s) => s. near_signer_public_key_str ( ) ,
1158+ MpcNodeState :: Running ( n) => n. setup ( ) . near_signer_public_key ( ) ,
1159+ MpcNodeState :: Stopped ( s) => s. near_signer_public_key ( ) ,
11981160 }
11991161 }
12001162}
@@ -1335,13 +1297,13 @@ async fn add_initial_domains(
13351297 domains : & [ DomainConfig ] ,
13361298) -> anyhow:: Result < ( ) > {
13371299 tracing:: info!( count = domains. len( ) , "adding domains" ) ;
1338- let args = json ! ( { "domains" : domains } ) ;
13391300
13401301 for & i in participant_indices {
13411302 let account = format ! ( "node{i}.{SANDBOX_ROOT_ACCOUNT}" ) ;
13421303 let client = blockchain. client_for ( & account, & operator_keys[ i] ) ?;
13431304 contract
1344- . call_from ( & client, method_names:: VOTE_ADD_DOMAINS , args. clone ( ) )
1305+ . handle_for ( client)
1306+ . vote_add_domains ( domains. to_vec ( ) )
13451307 . await
13461308 . with_context ( || format ! ( "node {i} failed to vote add domains" ) ) ?;
13471309 }
0 commit comments