Skip to content

Commit 63f36a8

Browse files
[cli] Fix windows faucet wallet issue (#24384)
## Description This PR fixes an issue flagged in #24041. Unfortunately, Windows does not allow clients to connect to 0.0.0.0, which was the case here, and led to an error when the faucet had to make an RPC client to node. ## Test plan Existing tests. Manually tested on Windows! --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] gRPC: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: - [ ] Indexing Framework:
1 parent d16d497 commit 63f36a8

File tree

5 files changed

+35
-39
lines changed

5 files changed

+35
-39
lines changed

crates/sui-indexer-alt-reader/src/consistent_reader.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,7 @@ impl ConsistentReader {
102102
endpoint = endpoint.timeout(timeout);
103103
}
104104

105-
let channel = endpoint
106-
.connect()
107-
.await
108-
.context("Failed to connect to gRPC endpoint")?;
105+
let channel = endpoint.connect_lazy();
109106

110107
Some(ConsistentServiceClient::new(channel))
111108
} else {

crates/sui-indexer-alt-reader/src/fullnode_client.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,7 @@ impl FullnodeClient {
6161
let execution_client = if let Some(url) = &args.fullnode_rpc_url {
6262
let channel = Channel::from_shared(url.clone())
6363
.context("Failed to create channel for gRPC endpoint")?
64-
.connect()
65-
.await
66-
.context("Failed to connect to gRPC endpoint")?;
64+
.connect_lazy();
6765

6866
Some(TransactionExecutionServiceClient::new(channel))
6967
} else {

crates/sui-indexer-alt-reader/src/ledger_grpc_reader.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,7 @@ impl LedgerGrpcReader {
5151
if let Some(timeout) = args.statement_timeout() {
5252
endpoint = endpoint.timeout(timeout);
5353
}
54-
let channel = endpoint
55-
.tls_config(tls_config)?
56-
.connect()
57-
.await
58-
.context("Failed to connect to gRPC endpoint")?;
54+
let channel = endpoint.tls_config(tls_config)?.connect_lazy();
5955

6056
let client = LedgerServiceClient::new(channel.clone());
6157
Ok(Self(client))

crates/sui-keys/src/keystore.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ impl FileBasedKeystore {
407407
});
408408

409409
let reader =
410-
BufReader::new(std::fs::File::open(path).with_context(|| {
410+
BufReader::new(fs::File::open(path).with_context(|| {
411411
format!("Cannot open the keystore file: {}", path.display())
412412
})?);
413413
let kp_strings: Vec<String> = serde_json::from_reader(reader).with_context(|| {
@@ -430,7 +430,7 @@ impl FileBasedKeystore {
430430
aliases_path.set_extension(ALIASES_FILE_EXTENSION);
431431

432432
let aliases = if aliases_path.exists() {
433-
let reader = BufReader::new(std::fs::File::open(&aliases_path).with_context(|| {
433+
let reader = BufReader::new(fs::File::open(&aliases_path).with_context(|| {
434434
format!(
435435
"Cannot open aliases file in keystore: {}",
436436
aliases_path.display()
@@ -484,7 +484,7 @@ impl FileBasedKeystore {
484484
)
485485
})?;
486486

487-
std::fs::write(aliases_path, aliases_store)?;
487+
fs::write(aliases_path, aliases_store)?;
488488
aliases
489489
};
490490

@@ -513,7 +513,7 @@ impl FileBasedKeystore {
513513
let mut aliases_path = path.clone();
514514
aliases_path.set_extension(ALIASES_FILE_EXTENSION);
515515
// no reactor for tokio::fs::write in simtest, so we use spawn_blocking
516-
tokio::task::spawn_blocking(move || std::fs::write(aliases_path, aliases_store))
516+
tokio::task::spawn_blocking(move || fs::write(aliases_path, aliases_store))
517517
.await?
518518
.with_context(|| format!("Cannot write aliases to file: {}", path.display()))?;
519519
}
@@ -536,7 +536,7 @@ impl FileBasedKeystore {
536536
let keystore_path = path.clone();
537537
// no reactor for tokio::fs::write in simtest, so we use spawn_blocking
538538
tokio::task::spawn_blocking(move || {
539-
let ret = std::fs::write(&keystore_path, store);
539+
let ret = fs::write(&keystore_path, store);
540540
#[cfg(unix)]
541541
if ret.is_ok() {
542542
let _ = set_reduced_file_permissions(&keystore_path).inspect_err(|error| {

crates/sui/src/sui_commands.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use prometheus::Registry;
2323
use rand::rngs::OsRng;
2424
use std::collections::BTreeMap;
2525
use std::io::{Write, stdout};
26-
use std::net::{AddrParseError, IpAddr, Ipv4Addr, SocketAddr};
26+
use std::net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
2727
use std::num::NonZeroUsize;
2828
use std::ops::Deref;
2929
use std::path::{Path, PathBuf};
@@ -1049,7 +1049,7 @@ async fn start(
10491049
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
10501050
info!("Cluster started");
10511051

1052-
let fullnode_rpc_url = format!("http://{fullnode_rpc_address}");
1052+
let fullnode_rpc_url = socket_addr_to_url(fullnode_rpc_address)?.to_string();
10531053
info!("Fullnode RPC URL: {fullnode_rpc_url}");
10541054

10551055
let prometheus_registry = Registry::new();
@@ -1151,7 +1151,7 @@ async fn start(
11511151
rpc_services.push(handle);
11521152

11531153
info!("Consistent Store started at {address}");
1154-
Some(format!("http://{address}"))
1154+
Some(address)
11551155
} else {
11561156
None
11571157
};
@@ -1167,12 +1167,9 @@ async fn start(
11671167
no_ide: false,
11681168
};
11691169

1170+
let consistent_store_url = consistent_store_url.map(socket_addr_to_url).transpose()?;
11701171
let consistent_reader_args = ConsistentReaderArgs {
1171-
consistent_store_url: consistent_store_url
1172-
.as_ref()
1173-
.map(|url| Url::parse(url))
1174-
.transpose()
1175-
.context("Failed to parse consistent store URL")?,
1172+
consistent_store_url,
11761173
..Default::default()
11771174
};
11781175

@@ -1223,6 +1220,7 @@ async fn start(
12231220
if let Some(input) = with_faucet {
12241221
let faucet_address = parse_host_port(input, DEFAULT_FAUCET_PORT)
12251222
.map_err(|_| anyhow!("Invalid faucet host and port"))?;
1223+
12261224
info!("Starting the faucet service at {faucet_address}");
12271225

12281226
let host_ip = match faucet_address {
@@ -1247,12 +1245,13 @@ async fn start(
12471245
.import(None, SuiKeyPair::Ed25519(kp))
12481246
.await
12491247
.unwrap();
1248+
12501249
SuiClientConfig {
12511250
keystore,
12521251
external_keys: None,
12531252
envs: vec![SuiEnv {
12541253
alias: "localnet".to_string(),
1255-
rpc: fullnode_rpc_url,
1254+
rpc: fullnode_rpc_url.clone(),
12561255
ws: None,
12571256
basic_auth: None,
12581257
chain_id: None,
@@ -1542,21 +1541,10 @@ async fn genesis(
15421541
client_config.active_address = active_address;
15431542
}
15441543

1545-
// On windows, using 0.0.0.0 will usually yield in an networking error. This localnet ip
1546-
// address must bind to 127.0.0.1 if the default 0.0.0.0 is used.
1547-
let localnet_ip =
1548-
if fullnode_config.json_rpc_address.ip() == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) {
1549-
"127.0.0.1".to_string()
1550-
} else {
1551-
fullnode_config.json_rpc_address.ip().to_string()
1552-
};
1544+
let rpc = socket_addr_to_url(fullnode_config.json_rpc_address)?.to_string();
15531545
client_config.add_env(SuiEnv {
15541546
alias: "localnet".to_string(),
1555-
rpc: format!(
1556-
"http://{}:{}",
1557-
localnet_ip,
1558-
fullnode_config.json_rpc_address.port()
1559-
),
1547+
rpc,
15601548
ws: None,
15611549
basic_auth: None,
15621550
chain_id: None,
@@ -1870,3 +1858,20 @@ pub async fn get_replay_node(
18701858
Chain::Unknown => bail!(err_msg),
18711859
})
18721860
}
1861+
1862+
/// Converts a socket address to a Url by setting the scheme to HTTP.
1863+
fn socket_addr_to_url(addr: SocketAddr) -> Result<Url, anyhow::Error> {
1864+
let ip = normalize_bind_addr(addr);
1865+
Url::parse(&format!("http://{ip}:{}", addr.port()))
1866+
.with_context(|| format!("Failed to parse {addr} into a Url"))
1867+
}
1868+
1869+
/// Resolves an unspecified ip address to a localhost IP address. Particularly on Windows, clients
1870+
/// cannot connect to 0.0.0.0 addresses.
1871+
fn normalize_bind_addr(addr: SocketAddr) -> IpAddr {
1872+
match addr.ip() {
1873+
IpAddr::V4(v4) if v4.is_unspecified() => IpAddr::V4(Ipv4Addr::LOCALHOST),
1874+
IpAddr::V6(v6) if v6.is_unspecified() => IpAddr::V6(Ipv6Addr::LOCALHOST),
1875+
ip => ip,
1876+
}
1877+
}

0 commit comments

Comments
 (0)