Skip to content
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

feat(cli): bridge sudo change command #1550

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 40 additions & 2 deletions charts/deploy.just
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ deploy-astrotrek:
-n astria-dev-cluster \

delete-astrotrek:
@just delete chart astrotrek
@just delete chart astrotrek

deploy-hermes-local:
helm install hermes-local-chart ./charts/hermes \
Expand Down Expand Up @@ -222,6 +222,8 @@ rollup_multiplier := "1000000000"
# 10 RIA
sequencer_transfer_amount := "10"
sequencer_rpc_url := "http://rpc.sequencer.localdev.me"
sequencer_funded_address:= "astria1qrt4kfc9ggyy548u7rg0d64sgq5c952kzk9tg9"
sequencer_funded_pkey := "934ab488f9e1900f6a08f50605ce1409ca9d95ebdc400dafc2e8a4306419fd52"
sequencer_bridge_address := "astria13ahqz4pjqfmynk9ylrqv4fwe4957x2p0h5782u"
sequencer_bridge_pkey := "dfa7108e38ab71f89f356c72afc38600d5758f11a8c337164713e4471411d2e0"
sequencer_chain_id := "sequencer-test-chain-0"
Expand Down Expand Up @@ -335,7 +337,6 @@ run-smoke-test tag=defaultTag:
echo "Bridge Out Sequencer failure"
exit 1
fi

echo "Testing TX Finalization"
CHECKS=0
BLOCK_NUM_HEX=$(just evm-get-transaction-receipt {{bridge_tx_hash}} | jq -r '.blockNumber')
Expand Down Expand Up @@ -461,6 +462,43 @@ run-smoke-cli tag=defaultTag:
exit 1
fi

echo "Testing Bridge sudo address change"
astria-cli sequencer bridge-sudo-change {{sequencer_bridge_address}} --private-key={{sequencer_bridge_pkey}} --new-sudo-address={{sequencer_funded_address}} --sequencer-url={{sequencer_rpc_url}} --sequencer.chain-id={{sequencer_chain_id}}
CHECKS=0
while (( $CHECKS < $MAX_CHECKS )); do
CHECKS=$((CHECKS+1))
SUDO_ADDRESS=$(astria-cli sequencer get-bridge-account {{sequencer_bridge_address}} --sequencer-url {{sequencer_rpc_url}} | awk '/Sudo Address/{print $(NF)}')
echo "Check $CHECKS, Sudo address: $SUDO_ADDRESS, Expected: {{sequencer_funded_address}}"
if [ "$SUDO_ADDRESS" == "{{sequencer_funded_address}}" ]; then
echo "Bridge Sudo change success"
break
else
sleep 1
fi
done
if (( $CHECKS >= $MAX_CHECKS )); then
echo "Bridge Sudo Change failure"
exit 1
fi

echo "Reverting Bridge sudo address"
astria-cli sequencer bridge-sudo-change {{sequencer_bridge_address}} --private-key={{sequencer_funded_pkey}} --new-sudo-address={{sequencer_bridge_address}} --sequencer-url={{sequencer_rpc_url}} --sequencer.chain-id={{sequencer_chain_id}}
CHECKS=0
while (( $CHECKS < $MAX_CHECKS )); do
CHECKS=$((CHECKS+1))
SUDO_ADDRESS=$(astria-cli sequencer get-bridge-account {{sequencer_bridge_address}} --sequencer-url {{sequencer_rpc_url}} | awk '/Sudo Address/{print $(NF)}')
echo "Check $CHECKS, Sudo address: $SUDO_ADDRESS, Expected: {{sequencer_bridge_address}}"
if [ "$SUDO_ADDRESS" == "{{sequencer_bridge_address}}" ]; then
echo "Bridge Sudo change back success"
break
else
sleep 1
fi
done
if (( $CHECKS >= $MAX_CHECKS )); then
echo "Bridge Sudo Change failure"
exit 1
fi
exit 0

#############################################
Expand Down
3 changes: 3 additions & 0 deletions crates/astria-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ impl Cli {
}

/// Commands that can be run
// allow: these are one-shot variants. the size doesn't matter as they are
// passed around only once.
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)]
pub(crate) enum Command {
Bridge {
Expand Down
66 changes: 66 additions & 0 deletions crates/astria-cli/src/cli/sequencer.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use astria_core::primitive::v1::asset;
use astria_sequencer_client::Address;
use clap::{
ArgGroup,
Args,
Subcommand,
};

/// Interact with a Sequencer node
// allow: these are one-shot variants. the size doesn't matter as they are
// passed around only once.
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Subcommand)]
pub(crate) enum Command {
/// Commands for interacting with Sequencer accounts
Expand Down Expand Up @@ -40,6 +44,10 @@ pub(crate) enum Command {
InitBridgeAccount(InitBridgeAccountArgs),
/// Command for transferring to a bridge account
BridgeLock(BridgeLockArgs),
/// Command for changing the bridge account sudo address or withdrawer address
BridgeSudoChange(BridgeSudoChangeArgs),
/// Command for getting bridge account information
GetBridgeAccount(BridgeAccountArgs),
}

#[derive(Debug, Subcommand)]
Expand Down Expand Up @@ -105,6 +113,19 @@ pub(crate) struct BasicAccountArgs {
pub(crate) address: Address,
}

#[derive(Args, Debug)]
pub(crate) struct BridgeAccountArgs {
/// The url of the Sequencer node
#[arg(
long,
env = "SEQUENCER_URL",
default_value = crate::cli::DEFAULT_SEQUENCER_RPC
)]
pub(crate) sequencer_url: String,
/// The address of the Sequencer bridge account
pub(crate) address: Address,
}

#[derive(Args, Debug)]
pub(crate) struct Bech32mAddressArgs {
/// The hex formatted byte part of the bech32m address
Expand Down Expand Up @@ -291,6 +312,51 @@ pub(crate) struct BridgeLockArgs {
pub(crate) fee_asset: asset::Denom,
}

#[derive(Args, Debug)]
#[command(group(ArgGroup::new("new_address")
.required(true)
.multiple(true)
.args(&["new_sudo_address", "new_withdrawer_address"])))]
pub(crate) struct BridgeSudoChangeArgs {
/// The bridge account whose privileges will be modified.
pub(crate) bridge_address: Address,
/// The new address to receive sudo privileges.
#[arg(long, default_value = None)]
pub(crate) new_sudo_address: Option<Address>,
/// The new address to receive withdrawer privileges.
#[arg(long, default_value = None)]
pub(crate) new_withdrawer_address: Option<Address>,
/// The prefix to construct a bech32m address given the private key.
#[arg(long, default_value = "astria")]
pub(crate) prefix: String,
// TODO: https://github.com/astriaorg/astria/issues/594
// Don't use a plain text private, prefer wrapper like from
// the secrecy crate with specialized `Debug` and `Drop` implementations
// that overwrite the key on drop and don't reveal it when printing.
#[arg(long, env = "SEQUENCER_PRIVATE_KEY")]
pub(crate) private_key: String,
/// The url of the Sequencer node
#[arg(
long,
env = "SEQUENCER_URL",
default_value = crate::cli::DEFAULT_SEQUENCER_RPC
)]
pub(crate) sequencer_url: String,
/// The chain id of the sequencing chain being used
#[arg(
long = "sequencer.chain-id",
env = "ROLLUP_SEQUENCER_CHAIN_ID",
default_value = crate::cli::DEFAULT_SEQUENCER_CHAIN_ID
)]
pub(crate) sequencer_chain_id: String,
/// The asset to lock.
#[arg(long, default_value = "nria")]
pub(crate) asset: asset::Denom,
/// The asset to pay the transfer fees with.
#[arg(long, default_value = "nria")]
pub(crate) fee_asset: asset::Denom,
}

#[derive(Debug, Subcommand)]
pub(crate) enum BlockHeightCommand {
/// Get the current block height of the Sequencer node
Expand Down
6 changes: 6 additions & 0 deletions crates/astria-cli/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ pub async fn run(cli: Cli) -> eyre::Result<()> {
sequencer::init_bridge_account(&args).await?;
}
SequencerCommand::BridgeLock(args) => sequencer::bridge_lock(&args).await?,
SequencerCommand::BridgeSudoChange(args) => {
sequencer::bridge_sudo_change(&args).await?;
}
SequencerCommand::GetBridgeAccount(args) => {
sequencer::get_bridge_account(&args).await?;
}
},
}
} else {
Expand Down
63 changes: 63 additions & 0 deletions crates/astria-cli/src/commands/sequencer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use astria_core::{
action::{
Action,
BridgeLockAction,
BridgeSudoChangeAction,
FeeAssetChangeAction,
IbcRelayerChangeAction,
InitBridgeAccountAction,
Expand Down Expand Up @@ -39,7 +40,9 @@ use crate::cli::sequencer::{
BasicAccountArgs,
Bech32mAddressArgs,
BlockHeightGetArgs,
BridgeAccountArgs,
BridgeLockArgs,
BridgeSudoChangeArgs,
FeeAssetChangeArgs,
IbcRelayerChangeArgs,
InitBridgeAccountArgs,
Expand Down Expand Up @@ -162,6 +165,36 @@ pub(crate) async fn get_block_height(args: &BlockHeightGetArgs) -> eyre::Result<
Ok(())
}

/// Gets bridge account information
///
/// # Arguments
///
/// * `args` - The arguments passed to the command
///
/// # Errors
///
/// * If the http client cannot be created
/// * If the bridge account information cannot be retrieved
pub(crate) async fn get_bridge_account(args: &BridgeAccountArgs) -> eyre::Result<()> {
let sequencer_client = HttpClient::new(args.sequencer_url.as_str())
.wrap_err("failed constructing http sequencer client")?;

let res = sequencer_client
.get_bridge_account_info(args.address)
.await
.wrap_err("failed to get bridge account")?;
let Some(info) = res.info else {
return Err(eyre::eyre!("no bridge account information found"));
};
println!("Bridge Account Information for address: {}", args.address);
println!(" Rollup Id: {}", info.rollup_id);
println!(" Asset: {}", info.asset);
println!(" Sudo Address: {}", info.sudo_address);
println!(" Withdrawer Address {}", info.withdrawer_address);

Ok(())
}

/// Returns a bech32m sequencer address given a prefix and hex-encoded byte slice
pub(crate) fn make_bech32m(args: &Bech32mAddressArgs) -> eyre::Result<()> {
use hex::FromHex as _;
Expand Down Expand Up @@ -330,6 +363,36 @@ pub(crate) async fn bridge_lock(args: &BridgeLockArgs) -> eyre::Result<()> {
Ok(())
}

/// Bridge Sudo Change action
///
/// # Arguments
///
/// * `args` - The arguments passed to the command
///
/// # Errors
///
/// * If the http client cannot be created
/// * If the transaction failed to be included
pub(crate) async fn bridge_sudo_change(args: &BridgeSudoChangeArgs) -> eyre::Result<()> {
let res = submit_transaction(
args.sequencer_url.as_str(),
args.sequencer_chain_id.clone(),
&args.prefix,
args.private_key.as_str(),
Action::BridgeSudoChange(BridgeSudoChangeAction {
bridge_address: args.bridge_address,
new_sudo_address: args.new_sudo_address,
new_withdrawer_address: args.new_withdrawer_address,
fee_asset: args.fee_asset.clone(),
}),
)
.await
.wrap_err("failed to submit BridgeSudoChnage transaction")?;
println!("BridgeSudoChange completed!");
println!("Included in block: {}", res.height);
Ok(())
}

/// Adds a fee asset
///
/// # Arguments
Expand Down