Skip to content

Commit 84476db

Browse files
committed
Added EthClient::Noop to match Charon's implementation
1 parent 1580d10 commit 84476db

File tree

3 files changed

+36
-22
lines changed

3 files changed

+36
-22
lines changed

crates/cli/src/commands/create_dkg.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ async fn run_create_dkg(mut args: CreateDkgArgs) -> Result<(), CreateDkgError> {
331331
});
332332
}
333333

334+
// Taking total number of operators, operator_enrs and operator_addresses are
335+
// mutually exclusive so no if statement is needed.
334336
let num_operators = operators.len() as u64;
335337
let safe_thresh = safe_threshold(num_operators)?;
336338
let threshold = if args.threshold == 0 {
@@ -387,10 +389,7 @@ async fn run_create_dkg(mut args: CreateDkgArgs) -> Result<(), CreateDkgError> {
387389
pluto_cluster::eip712sigs::sign_cluster_definition_hash(key, &def)?;
388390
}
389391

390-
// Verify signatures when an ETH1 endpoint is available. Skipped when the
391-
// endpoint is empty because the client cannot connect — safe for DKG create
392-
// since operators have no signatures at this stage.
393-
if !args.publish && !args.execution_engine_addr.is_empty() {
392+
if !args.publish {
394393
let eth1 = pluto_eth1wrap::EthClient::new(&args.execution_engine_addr).await?;
395394
def.verify_signatures(&eth1).await?;
396395
}
@@ -541,6 +540,10 @@ fn is_main_or_gnosis(network: &str) -> bool {
541540
network == MAINNET.name || network == GNOSIS.name
542541
}
543542

543+
// Ports cluster.Threshold from charon (cluster/helpers.go), which computes
544+
// ceil(2n/3) using math.Ceil(float64(2*n) / 3). The integer identity
545+
// ceil(a/b) == (a + b - 1) / b gives ceil(2n/3) == (2n + 2) / 3, producing
546+
// identical results for all n.
544547
fn safe_threshold(num_operators: u64) -> Result<u64, CreateDkgError> {
545548
let two_n = num_operators
546549
.checked_mul(2)
@@ -752,12 +755,12 @@ mod tests {
752755
)]
753756
#[test_case(
754757
CreateDkgArgs { threshold: 1, ..default_args() },
755-
"Create DKG error: threshold must be greater than 1" ;
758+
"Create DKG error: threshold must be greater than 1 (threshold=1, min=2)" ;
756759
"threshold_below_minimum"
757760
)]
758761
#[test_case(
759762
CreateDkgArgs { operator_enrs: VALID_ENRS[..3].iter().map(|s| s.to_string()).collect(), threshold: 4, ..default_args() },
760-
"Create DKG error: threshold cannot be greater than number of operators" ;
763+
"Create DKG error: threshold (4) cannot be greater than number of operators (3)" ;
761764
"threshold_above_maximum"
762765
)]
763766
#[tokio::test]

crates/dkg/src/disk.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,8 +551,6 @@ mod tests {
551551
}
552552

553553
async fn noop_eth1_client() -> pluto_eth1wrap::EthClient {
554-
pluto_eth1wrap::EthClient::new("http://0.0.0.0:0")
555-
.await
556-
.unwrap()
554+
pluto_eth1wrap::EthClient::new("").await.unwrap()
557555
}
558556
}

crates/eth1wrap/src/lib.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,32 @@ pub enum EthClientError {
3333
/// The Ethereum Address was invalid.
3434
#[error("Invalid address: {0}")]
3535
InvalidAddress(#[from] alloy::primitives::AddressError),
36+
37+
/// No execution engine endpoint was configured.
38+
#[error("execution engine endpoint is not set")]
39+
NoExecutionEngineAddr,
3640
}
3741

3842
/// Defines the interface for the Ethereum EL RPC client.
39-
pub struct EthClient(DynProvider);
40-
41-
impl std::ops::Deref for EthClient {
42-
type Target = DynProvider;
43-
44-
fn deref(&self) -> &DynProvider {
45-
&self.0
46-
}
43+
pub enum EthClient {
44+
/// Connected client backed by a live provider.
45+
Connected(DynProvider),
46+
/// Noop client returned when no address is provided. Mirrors Go's
47+
/// noopClient.
48+
Noop,
4749
}
4850

4951
impl EthClient {
50-
/// Create a new `EthClient` connected to the given address using defaults
51-
/// for retry.
52+
/// Create a new `EthClient`. When `address` is empty a noop client is
53+
/// returned that errors with [`EthClientError::NoExecutionEngineAddr`]
54+
/// if `verify_smart_contract_based_signature` is ever called, matching
55+
/// Go's `NewDefaultEthClientRunner("")` behaviour.
5256
pub async fn new(address: impl AsRef<str>) -> Result<EthClient> {
57+
let address = address.as_ref();
58+
if address.is_empty() {
59+
return Ok(EthClient::Noop);
60+
}
61+
5362
// The maximum number of retries for rate limit errors.
5463
const MAX_RETRY: u32 = 10;
5564
// The initial backoff in milliseconds.
@@ -61,12 +70,12 @@ impl EthClient {
6170

6271
let client = ClientBuilder::default()
6372
.layer(retry_layer)
64-
.connect(address.as_ref())
73+
.connect(address)
6574
.await?;
6675

6776
let provider = ProviderBuilder::new().connect_client(client);
6877

69-
Ok(EthClient(provider.erased()))
78+
Ok(EthClient::Connected(provider.erased()))
7079
}
7180

7281
/// Check if `sig` is a valid signature of `hash` according to ERC-1271.
@@ -76,12 +85,16 @@ impl EthClient {
7685
hash: [u8; 32],
7786
sig: &[u8],
7887
) -> Result<bool> {
88+
let EthClient::Connected(provider) = self else {
89+
return Err(EthClientError::NoExecutionEngineAddr);
90+
};
91+
7992
// Magic value defined in [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271).
8093
const MAGIC_VALUE: [u8; 4] = [0x16, 0x26, 0xba, 0x7e];
8194

8295
let address = alloy::primitives::Address::parse_checksummed(contract_address, None)?;
8396

84-
let instance = IERC1271::new(address, &self.0);
97+
let instance = IERC1271::new(address, provider);
8598

8699
let call = instance
87100
.isValidSignature(hash.into(), sig.to_vec().into())

0 commit comments

Comments
 (0)