-
Notifications
You must be signed in to change notification settings - Fork 176
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve error handling in anomac utils join-network
#1050
Closed
Closed
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
79638b9
Add anyhow as a dependency for anoma_apps
james-chf cbb6fd2
Use a shim for join_network() for printing errors
james-chf 3d8afe6
Refactoring
james-chf 4d38186
Better shimming
james-chf 3cac5d3
Remove unused import
james-chf 5aa3514
More shimming
james-chf d2ccce5
Better trait bounds, use log_and_exit in tokio task
james-chf e1ef7cb
Add exit_if_error2 for non-eyre::Result returns
james-chf 2767395
Remove anyhow dependency
james-chf 20f42ac
Tidy up
james-chf 2e84aec
make fmt
james-chf File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,161 +44,188 @@ pub const NET_OTHER_ACCOUNTS_DIR: &str = "other"; | |
const RELEASE_PREFIX: &str = | ||
"https://github.com/heliaxdev/anoma-network-config/releases/download"; | ||
|
||
fn log_and_exit<E: std::error::Error>(error: E) { | ||
eprintln!("ERROR: {}", error); | ||
tracing::error!("{:?}", error); // ?: is using {:?} the best way to pass the error to tracing? | ||
cli::safe_exit(1); | ||
} | ||
|
||
// TODO: can these two exit_if_error helpers be combined? | ||
fn exit_if_error_ref<E: AsRef<dyn std::error::Error>>(result: Result<(), E>) { | ||
if let Err(error) = result { | ||
log_and_exit(error.as_ref()); | ||
} | ||
} | ||
|
||
fn exit_if_error<E: std::error::Error>(result: Result<(), E>) { | ||
if let Err(error) = result { | ||
log_and_exit(error); | ||
} | ||
} | ||
|
||
/// Configure Anoma to join an existing network. The chain must be released in | ||
/// the <https://github.com/heliaxdev/anoma-network-config> repository. | ||
pub async fn join_network( | ||
global_args: args::Global, | ||
args::JoinNetwork { chain_id }: args::JoinNetwork, | ||
) { | ||
use tokio::fs; | ||
|
||
let base_dir = &global_args.base_dir; | ||
let wasm_dir = global_args.wasm_dir.as_ref().cloned().or_else(|| { | ||
if let Ok(wasm_dir) = env::var(ENV_VAR_WASM_DIR) { | ||
let wasm_dir: PathBuf = wasm_dir.into(); | ||
Some(wasm_dir) | ||
} else { | ||
None | ||
} | ||
}); | ||
if let Some(wasm_dir) = wasm_dir.as_ref() { | ||
if wasm_dir.is_absolute() { | ||
eprintln!( | ||
"The arg `--wasm-dir` cannot be an absolute path. It is \ | ||
nested inside the chain directory." | ||
); | ||
cli::safe_exit(1); | ||
} | ||
} | ||
if let Err(err) = fs::canonicalize(base_dir).await { | ||
if err.kind() == std::io::ErrorKind::NotFound { | ||
// If the base-dir doesn't exist yet, create it | ||
fs::create_dir_all(base_dir).await.unwrap(); | ||
} | ||
} else { | ||
// If the base-dir exists, check if it's already got this chain ID | ||
if fs::canonicalize(base_dir.join(chain_id.as_str())) | ||
.await | ||
.is_ok() | ||
{ | ||
eprintln!("The chain directory for {} already exists.", chain_id); | ||
cli::safe_exit(1); | ||
} | ||
} | ||
let base_dir_full = fs::canonicalize(base_dir).await.unwrap(); | ||
|
||
let release_filename = format!("{}.tar.gz", chain_id); | ||
let release_url = | ||
format!("{}/{}/{}", RELEASE_PREFIX, chain_id, release_filename); | ||
let cwd = env::current_dir().unwrap(); | ||
|
||
// Read or download the release archive | ||
println!("Downloading config release from {} ...", release_url); | ||
let release = download_file(release_url).await; | ||
|
||
// Decode and unpack the archive | ||
let mut decoder = GzDecoder::new(&release[..]); | ||
let mut tar = String::new(); | ||
decoder.read_to_string(&mut tar).unwrap(); | ||
let mut archive = tar::Archive::new(tar.as_bytes()); | ||
|
||
// If the base-dir is non-default, unpack the archive into a temp dir inside | ||
// first. | ||
let (unpack_dir, non_default_dir) = | ||
if base_dir_full != cwd.join(config::DEFAULT_BASE_DIR) { | ||
(base_dir.clone(), true) | ||
} else { | ||
(PathBuf::from_str(".").unwrap(), false) | ||
}; | ||
archive.unpack(&unpack_dir).unwrap(); | ||
|
||
// Rename the base-dir from the default and rename wasm-dir, if non-default. | ||
if non_default_dir { | ||
// For compatibility for networks released with Anoma <= v0.4: | ||
// The old releases include the WASM directory at root path of the | ||
// archive. This has been moved into the chain directory, so if the | ||
// WASM dir is found at the old path, we move it to the new path. | ||
if let Ok(wasm_dir) = | ||
fs::canonicalize(unpack_dir.join(config::DEFAULT_WASM_DIR)).await | ||
{ | ||
fs::rename( | ||
&wasm_dir, | ||
unpack_dir | ||
.join(config::DEFAULT_BASE_DIR) | ||
.join(chain_id.as_str()) | ||
.join(config::DEFAULT_WASM_DIR), | ||
) | ||
.await | ||
.unwrap(); | ||
} | ||
|
||
// Move the chain dir | ||
fs::rename( | ||
unpack_dir | ||
.join(config::DEFAULT_BASE_DIR) | ||
.join(chain_id.as_str()), | ||
base_dir_full.join(chain_id.as_str()), | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
// Move the genesis file | ||
fs::rename( | ||
unpack_dir | ||
.join(config::DEFAULT_BASE_DIR) | ||
.join(format!("{}.toml", chain_id.as_str())), | ||
base_dir_full.join(format!("{}.toml", chain_id.as_str())), | ||
) | ||
.await | ||
.unwrap(); | ||
exit_if_error_ref( | ||
async { | ||
use tokio::fs; | ||
|
||
let base_dir = &global_args.base_dir; | ||
let wasm_dir = | ||
global_args.wasm_dir.as_ref().cloned().or_else(|| { | ||
if let Ok(wasm_dir) = env::var(ENV_VAR_WASM_DIR) { | ||
let wasm_dir: PathBuf = wasm_dir.into(); | ||
Some(wasm_dir) | ||
} else { | ||
None | ||
} | ||
}); | ||
if let Some(wasm_dir) = wasm_dir.as_ref() { | ||
if wasm_dir.is_absolute() { | ||
eprintln!( | ||
"The arg `--wasm-dir` cannot be an absolute path. It \ | ||
is nested inside the chain directory." | ||
); | ||
cli::safe_exit(1); | ||
} | ||
} | ||
if let Err(err) = fs::canonicalize(base_dir).await { | ||
if err.kind() == std::io::ErrorKind::NotFound { | ||
// If the base-dir doesn't exist yet, create it | ||
fs::create_dir_all(base_dir).await?; | ||
} | ||
} else { | ||
// If the base-dir exists, check if it's already got this chain | ||
// ID | ||
if fs::canonicalize(base_dir.join(chain_id.as_str())) | ||
.await | ||
.is_ok() | ||
{ | ||
eprintln!( | ||
"The chain directory for {} already exists.", | ||
chain_id | ||
); | ||
cli::safe_exit(1); | ||
} | ||
} | ||
let base_dir_full = fs::canonicalize(base_dir).await?; | ||
|
||
let release_filename = format!("{}.tar.gz", chain_id); | ||
let release_url = | ||
format!("{}/{}/{}", RELEASE_PREFIX, chain_id, release_filename); | ||
let cwd = env::current_dir()?; | ||
|
||
// Read or download the release archive | ||
println!("Downloading config release from {} ...", release_url); | ||
let release = download_file(release_url).await; | ||
|
||
// Decode and unpack the archive | ||
let mut decoder = GzDecoder::new(&release[..]); | ||
let mut tar = String::new(); | ||
decoder.read_to_string(&mut tar)?; | ||
let mut archive = tar::Archive::new(tar.as_bytes()); | ||
|
||
// If the base-dir is non-default, unpack the archive into a temp | ||
// dir inside first. | ||
let (unpack_dir, non_default_dir) = | ||
if base_dir_full != cwd.join(config::DEFAULT_BASE_DIR) { | ||
(base_dir.clone(), true) | ||
} else { | ||
(PathBuf::from_str(".")?, false) | ||
}; | ||
archive.unpack(&unpack_dir)?; | ||
|
||
// Rename the base-dir from the default and rename wasm-dir, if | ||
// non-default. | ||
if non_default_dir { | ||
// For compatibility for networks released with Anoma <= v0.4: | ||
// The old releases include the WASM directory at root path of | ||
// the archive. This has been moved into the | ||
// chain directory, so if the WASM dir is found | ||
// at the old path, we move it to the new path. | ||
if let Ok(wasm_dir) = | ||
fs::canonicalize(unpack_dir.join(config::DEFAULT_WASM_DIR)) | ||
.await | ||
{ | ||
fs::rename( | ||
&wasm_dir, | ||
unpack_dir | ||
.join(config::DEFAULT_BASE_DIR) | ||
.join(chain_id.as_str()) | ||
.join(config::DEFAULT_WASM_DIR), | ||
) | ||
.await?; | ||
} | ||
|
||
// Move the global config | ||
fs::rename( | ||
unpack_dir | ||
.join(config::DEFAULT_BASE_DIR) | ||
.join(config::global::FILENAME), | ||
base_dir_full.join(config::global::FILENAME), | ||
) | ||
.await | ||
.unwrap(); | ||
// Move the chain dir | ||
fs::rename( | ||
unpack_dir | ||
.join(config::DEFAULT_BASE_DIR) | ||
.join(chain_id.as_str()), | ||
base_dir_full.join(chain_id.as_str()), | ||
) | ||
.await?; | ||
|
||
// Move the genesis file | ||
fs::rename( | ||
unpack_dir | ||
.join(config::DEFAULT_BASE_DIR) | ||
.join(format!("{}.toml", chain_id.as_str())), | ||
base_dir_full.join(format!("{}.toml", chain_id.as_str())), | ||
) | ||
.await?; | ||
|
||
// Move the global config | ||
fs::rename( | ||
unpack_dir | ||
.join(config::DEFAULT_BASE_DIR) | ||
.join(config::global::FILENAME), | ||
base_dir_full.join(config::global::FILENAME), | ||
) | ||
.await?; | ||
|
||
// Remove the default dir | ||
fs::remove_dir_all(unpack_dir.join(config::DEFAULT_BASE_DIR)) | ||
.await?; | ||
} | ||
|
||
// Remove the default dir | ||
fs::remove_dir_all(unpack_dir.join(config::DEFAULT_BASE_DIR)) | ||
.await | ||
.unwrap(); | ||
} | ||
// Move wasm-dir and update config if it's non-default | ||
if let Some(wasm_dir) = wasm_dir.as_ref() { | ||
if wasm_dir.to_string_lossy() != config::DEFAULT_WASM_DIR { | ||
tokio::fs::rename( | ||
base_dir_full | ||
.join(chain_id.as_str()) | ||
.join(config::DEFAULT_WASM_DIR), | ||
base_dir_full.join(chain_id.as_str()).join(wasm_dir), | ||
) | ||
.await?; | ||
|
||
// Update the config | ||
let wasm_dir = wasm_dir.clone(); | ||
let base_dir = base_dir.clone(); | ||
let chain_id = chain_id.clone(); | ||
tokio::task::spawn_blocking(move || { | ||
let mut config = Config::load( | ||
&base_dir, | ||
&chain_id, | ||
global_args.mode.clone(), | ||
); | ||
config.wasm_dir = wasm_dir; | ||
|
||
// Move wasm-dir and update config if it's non-default | ||
if let Some(wasm_dir) = wasm_dir.as_ref() { | ||
if wasm_dir.to_string_lossy() != config::DEFAULT_WASM_DIR { | ||
tokio::fs::rename( | ||
base_dir_full | ||
.join(chain_id.as_str()) | ||
.join(config::DEFAULT_WASM_DIR), | ||
base_dir_full.join(chain_id.as_str()).join(wasm_dir), | ||
) | ||
.await | ||
.unwrap(); | ||
exit_if_error(config.write(&base_dir, &chain_id, true)); | ||
}) | ||
.await?; | ||
} | ||
} | ||
|
||
// Update the config | ||
let wasm_dir = wasm_dir.clone(); | ||
let base_dir = base_dir.clone(); | ||
let chain_id = chain_id.clone(); | ||
tokio::task::spawn_blocking(move || { | ||
let mut config = Config::load( | ||
&base_dir, | ||
&chain_id, | ||
global_args.mode.clone(), | ||
); | ||
config.wasm_dir = wasm_dir; | ||
config.write(&base_dir, &chain_id, true).unwrap(); | ||
}) | ||
.await | ||
.unwrap(); | ||
println!("Successfully configured for chain ID {}", chain_id); | ||
eyre::Result::<()>::Ok(()) | ||
} | ||
} | ||
|
||
println!("Successfully configured for chain ID {}", chain_id); | ||
.await, | ||
); | ||
} | ||
|
||
/// Length of a Tendermint Node ID in bytes | ||
|
@@ -666,16 +693,16 @@ pub fn init_network( | |
config.ledger.shell.base_dir = config::DEFAULT_BASE_DIR.into(); | ||
// Add a ledger P2P persistent peers | ||
config.ledger.tendermint.p2p_persistent_peers = persistent_peers | ||
.iter() | ||
.enumerate() | ||
.filter_map(|(index, peer)| | ||
// we do not add the validator in its own persistent peer list | ||
if index != ix { | ||
Some(peer.to_owned()) | ||
} else { | ||
None | ||
}) | ||
.collect(); | ||
.iter() | ||
.enumerate() | ||
.filter_map(|(index, peer)| | ||
// we do not add the validator in its own persistent peer list | ||
if index != ix { | ||
Some(peer.to_owned()) | ||
} else { | ||
None | ||
}) | ||
.collect(); | ||
Comment on lines
+696
to
+705
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unrelated formatting change |
||
config.ledger.tendermint.consensus_timeout_commit = | ||
consensus_timeout_commit; | ||
config.ledger.tendermint.p2p_allow_duplicate_ip = | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can, maybe with
map_err(AsRef::as_ref)
on the resultThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried some things out with
map_err
though was getting compiler errors about returning a reference to an owned error, will have to come back to this