@@ -84,21 +84,19 @@ impl VerifyForeignTxProvider {
8484 let foreign_tx_request = self . verify_foreign_tx_request_store . get ( id) . await ?;
8585 let requested_chain = foreign_tx_request. request . chain ( ) ;
8686
87- // Also checked in `execute_foreign_chain_request`; resolved early here
88- // because the supporter set scopes which presignature may be taken. An
89- // availability flip after the take still costs one presignature.
9087 let chain_supporters: HashSet < ParticipantId > = {
91- let snapshot = self . supporters_by_foreign_chain . borrow ( ) ;
92- ensure_chain_is_available ( & snapshot, & foreign_tx_request. request ) . inspect_err (
88+ let snapshot = self . supporters_by_foreign_chain . borrow ( ) . clone ( ) ;
89+ ensure_chain_is_available ( & snapshot, foreign_tx_request. request . chain ( ) ) . inspect_err (
9390 |_| metrics:: MPC_NUM_VERIFY_FOREIGN_TX_UNAVAILABLE_CHAIN_REJECTIONS . inc ( ) ,
9491 ) ?;
9592 snapshot. get ( & requested_chain) . cloned ( ) . unwrap_or_default ( )
9693 } ;
9794
98- // Election is not chain support aware, so a non-supporting node can be
99- // assigned leader for a request. Owned presignatures always include this
100- // node, so `take_owned_matching` below would never resolve.
101- // TODO(#3961): narrow election to chain supporters.
95+ // Owned presignatures always include current (leader) node, so it would
96+ // never be able to find a presignature from presignatures it owns
97+ // where all participants (including itself) support the chain, so
98+ // bail at this point (before waiting for such presignature).
99+ // TODO(#3961): narrow leader selection to only chain supporters.
102100 let my_participant_id = self . ecdsa_signature_provider . my_participant_id ( ) ;
103101 if !chain_supporters. contains ( & my_participant_id) {
104102 metrics:: MPC_NUM_VERIFY_FOREIGN_TX_UNAVAILABLE_CHAIN_REJECTIONS . inc ( ) ;
@@ -187,7 +185,9 @@ impl VerifyForeignTxProvider {
187185 request : & dtos:: ForeignChainRpcRequest ,
188186 payload_version : dtos:: ForeignTxPayloadVersion ,
189187 ) -> anyhow:: Result < dtos:: ForeignTxSignPayload > {
190- ensure_chain_is_available ( & self . supporters_by_foreign_chain . borrow ( ) , request)
188+ // Check that the requested chain is still available when this
189+ // point is reached.
190+ ensure_chain_is_available ( & self . supporters_by_foreign_chain . borrow ( ) , request. chain ( ) )
191191 . inspect_err ( |_| {
192192 metrics:: MPC_NUM_VERIFY_FOREIGN_TX_UNAVAILABLE_CHAIN_REJECTIONS . inc ( )
193193 } ) ?;
@@ -455,13 +455,14 @@ struct ChainNotAvailableError {
455455/// participants supports it.
456456fn ensure_chain_is_available (
457457 supporters_by_foreign_chain : & SupportersByForeignChain ,
458- request : & dtos:: ForeignChainRpcRequest ,
458+ foreign_chain : dtos:: ForeignChain ,
459459) -> Result < ( ) , ChainNotAvailableError > {
460- let requested = request. chain ( ) ;
461- if supporters_by_foreign_chain. contains_key ( & requested) {
460+ if supporters_by_foreign_chain. contains_key ( & foreign_chain) {
462461 Ok ( ( ) )
463462 } else {
464- Err ( ChainNotAvailableError { requested } )
463+ Err ( ChainNotAvailableError {
464+ requested : foreign_chain,
465+ } )
465466 }
466467}
467468
@@ -516,7 +517,7 @@ mod tests {
516517
517518 // When, then
518519 assert_matches ! (
519- ensure_chain_is_available( & supporters, & bitcoin_request( ) ) ,
520+ ensure_chain_is_available( & supporters, bitcoin_request( ) . chain ( ) ) ,
520521 Ok ( _)
521522 ) ;
522523 }
@@ -533,7 +534,7 @@ mod tests {
533534
534535 // When, then
535536 assert_matches ! (
536- ensure_chain_is_available( & supporters, & ethereum_request) ,
537+ ensure_chain_is_available( & supporters, ethereum_request. chain ( ) ) ,
537538 Err ( ChainNotAvailableError {
538539 requested: dtos:: ForeignChain :: Ethereum
539540 } )
0 commit comments