From 82bf506cd542e2e30bc80ea63791ba608da5b57f Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Thu, 31 Aug 2023 10:36:40 -0500 Subject: [PATCH 1/6] Support specifying RPC address via --node in CLI commands --- rest/src/main.rs | 22 ++--- src/bin/nomic.rs | 180 +++++++++++++++++++++++++++++++---------- src/bitcoin/relayer.rs | 51 +++++++----- src/lib.rs | 8 +- src/network.rs | 58 ++++++++----- src/utils.rs | 20 +++-- tests/bitcoin.rs | 39 +++++---- 7 files changed, 261 insertions(+), 117 deletions(-) diff --git a/rest/src/main.rs b/rest/src/main.rs index 2d5d78cd..205e729f 100644 --- a/rest/src/main.rs +++ b/rest/src/main.rs @@ -3,7 +3,7 @@ extern crate rocket; use nomic::{ app::{App, InnerApp, Nom}, - app_client_testnet, + app_client, orga::{ coins::{Address, Amount, Decimal}, plugins::*, @@ -27,7 +27,7 @@ lazy_static::lazy_static! { async fn bank_balances(address: &str) -> Result> { let address: Address = address.parse().unwrap(); - let balance: u64 = app_client_testnet() + let balance: u64 = app_client() .query(|app| app.accounts.balance(address)) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))? @@ -55,7 +55,7 @@ async fn bank_balances(address: &str) -> Result> { async fn bank_balances_2(address: &str) -> Result> { let address: Address = address.parse().unwrap(); - let balance: u64 = app_client_testnet() + let balance: u64 = app_client() .query(|app| app.accounts.balance(address)) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))? @@ -76,13 +76,13 @@ async fn bank_balances_2(address: &str) -> Result> { async fn auth_accounts(addr_str: &str) -> Result> { let address: Address = addr_str.parse().unwrap(); - let balance: u64 = app_client_testnet() + let balance: u64 = app_client() .query(|app| app.accounts.balance(address)) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))? .into(); - let mut nonce: u64 = app_client_testnet() + let mut nonce: u64 = app_client() .query_root(|app| app.inner.inner.borrow().inner.inner.inner.nonce(address)) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))? @@ -111,13 +111,13 @@ async fn auth_accounts(addr_str: &str) -> Result> { async fn auth_accounts2(addr_str: &str) -> Result> { let address: Address = addr_str.parse().unwrap(); - let balance: u64 = app_client_testnet() + let balance: u64 = app_client() .query(|app| app.accounts.balance(address)) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))? .into(); - let mut nonce: u64 = app_client_testnet() + let mut nonce: u64 = app_client() .query_root(|app| app.inner.inner.borrow().inner.inner.inner.nonce(address)) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))? @@ -286,7 +286,7 @@ async fn query(query: &str, height: Option) -> Result Result> { let address: Address = address.parse().unwrap(); - let delegations = app_client_testnet() + let delegations = app_client() .query(|app| app.staking.delegations(address)) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))?; @@ -315,7 +315,7 @@ async fn staking_delegators_delegations(address: &str) -> Result Result> { let address: Address = address.parse().unwrap(); - let delegations = app_client_testnet() + let delegations = app_client() .query(|app| app.staking.delegations(address)) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))?; @@ -439,7 +439,7 @@ async fn distribution_delegatrs_rewards_2(_address: &str) -> Value { #[get("/cosmos/mint/v1beta1/inflation")] async fn minting_inflation() -> Result> { - let validators = app_client_testnet() + let validators = app_client() .query(|app| app.staking.all_validators()) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))?; @@ -459,7 +459,7 @@ async fn minting_inflation() -> Result> { #[get("/minting/inflation")] async fn minting_inflation_2() -> Result> { - let validators = app_client_testnet() + let validators = app_client() .query(|app| app.staking.all_validators()) .await .map_err(|e| BadRequest(Some(format!("{:?}", e))))?; diff --git a/src/bin/nomic.rs b/src/bin/nomic.rs index 5945a790..19482f30 100644 --- a/src/bin/nomic.rs +++ b/src/bin/nomic.rs @@ -8,8 +8,7 @@ use bitcoind::bitcoincore_rpc::{Auth, Client as BtcClient}; use clap::Parser; use nomic::app::DepositCommitment; use nomic::app::InnerApp; -use nomic::app::{self, Nom}; -use nomic::app_client_testnet; +use nomic::app::Nom; use nomic::bitcoin::{relayer::Relayer, signer::Signer}; use nomic::error::Result; use orga::abci::Node; @@ -37,10 +36,6 @@ const BANNER: &str = r#" ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ "#; -fn app_client() -> AppClient { - app_client_testnet().with_wallet(wallet()) -} - fn wallet() -> SimpleWallet { let path = home::home_dir().unwrap().join(".orga-wallet"); SimpleWallet::open(path).unwrap() @@ -329,6 +324,7 @@ impl StartCmd { if let Some(signal_version) = cmd.signal_version { let signal_version = hex::decode(signal_version).unwrap(); let rt = tokio::runtime::Runtime::new().unwrap(); + let client = self.config.client().with_wallet(wallet()); std::thread::spawn(move || { rt.block_on(async move { dbg!(); @@ -342,7 +338,7 @@ impl StartCmd { loop { let signal_version = signal_version.clone().try_into().unwrap(); tokio::time::sleep(std::time::Duration::from_secs(5)).await; - if let Err(err) = app_client() + if let Err(err) = client .call( |app| build_call!(app.signal(signal_version)), |app| build_call!(app.app_noop()), @@ -640,11 +636,17 @@ async fn get_bootstrap_state(rpc_servers: &[&str]) -> Result<(i64, String)> { pub struct SendCmd { to_addr: Address, amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, } impl SendCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.accounts.take_as_funding(MIN_FEE.into())), |app| build_call!(app.accounts.transfer(self.to_addr, self.amount.into())), @@ -657,11 +659,17 @@ impl SendCmd { pub struct SendNbtcCmd { to_addr: Address, amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, } impl SendNbtcCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.bitcoin.transfer(self.to_addr, self.amount.into())), |app| build_call!(app.app_noop()), @@ -673,6 +681,9 @@ impl SendNbtcCmd { #[derive(Parser, Debug)] pub struct BalanceCmd { address: Option
, + + #[clap(flatten)] + config: nomic::network::Config, } impl BalanceCmd { @@ -680,19 +691,19 @@ impl BalanceCmd { let address = self.address.unwrap_or_else(my_address); println!("address: {}", address); - let balance = app_client() - .query(|app| app.accounts.balance(address)) - .await?; + let client = self.config.client(); + + let balance = client.query(|app| app.accounts.balance(address)).await?; println!("{} NOM", balance); - let balance = app_client() + let balance = client .query(|app| app.bitcoin.accounts.balance(address)) .await?; println!("{} NBTC", balance); #[cfg(feature = "testnet")] { - let balance = app_client().query(|app| app.escrowed_nbtc(address)).await?; + let balance = client.query(|app| app.escrowed_nbtc(address)).await?; println!("{} IBC-escrowed NBTC", balance); } @@ -701,12 +712,17 @@ impl BalanceCmd { } #[derive(Parser, Debug)] -pub struct DelegationsCmd; +pub struct DelegationsCmd { + #[clap(flatten)] + config: nomic::network::Config, +} impl DelegationsCmd { async fn run(&self) -> Result<()> { let address = my_address(); - let delegations = app_client() + let delegations = self + .config + .client() .query(|app| app.staking.delegations(address)) .await?; @@ -750,11 +766,16 @@ impl DelegationsCmd { } #[derive(Parser, Debug)] -pub struct ValidatorsCmd; +pub struct ValidatorsCmd { + #[clap(flatten)] + config: nomic::network::Config, +} impl ValidatorsCmd { async fn run(&self) -> Result<()> { - let mut validators = app_client() + let mut validators = self + .config + .client() .query(|app| app.staking.all_validators()) .await?; @@ -777,11 +798,17 @@ impl ValidatorsCmd { pub struct DelegateCmd { validator_addr: Address, amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, } impl DelegateCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.accounts.take_as_funding((self.amount + MIN_FEE).into())), |app| { @@ -806,6 +833,9 @@ pub struct DeclareCmd { website: String, identity: String, details: String, + + #[clap(flatten)] + config: nomic::network::Config, } #[derive(Debug, Serialize, Deserialize)] @@ -845,7 +875,10 @@ impl DeclareCmd { min_self_delegation: self.min_self_delegation.into(), }; - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.accounts.take_as_funding((self.amount + MIN_FEE).into())), |app| build_call!(app.staking.declare_self(declaration.clone())), @@ -862,6 +895,9 @@ pub struct EditCmd { website: String, identity: String, details: String, + + #[clap(flatten)] + config: nomic::network::Config, } impl EditCmd { @@ -876,7 +912,10 @@ impl EditCmd { .map_err(|_| orga::Error::App("invalid json".to_string()))?; let info_bytes = info_json.as_bytes().to_vec(); - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.accounts.take_as_funding(MIN_FEE.into())), |app| { @@ -895,11 +934,17 @@ impl EditCmd { pub struct UnbondCmd { validator_addr: Address, amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, } impl UnbondCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.accounts.take_as_funding(MIN_FEE.into())), |app| { @@ -917,11 +962,17 @@ pub struct RedelegateCmd { src_validator_addr: Address, dest_validator_addr: Address, amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, } impl RedelegateCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.accounts.take_as_funding(MIN_FEE.into())), |app| { @@ -937,11 +988,17 @@ impl RedelegateCmd { } #[derive(Parser, Debug)] -pub struct UnjailCmd {} +pub struct UnjailCmd { + #[clap(flatten)] + config: nomic::network::Config, +} impl UnjailCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.accounts.take_as_funding(MIN_FEE.into())), |app| build_call!(app.staking.unjail()), @@ -951,11 +1008,17 @@ impl UnjailCmd { } #[derive(Parser, Debug)] -pub struct ClaimCmd; +pub struct ClaimCmd { + #[clap(flatten)] + config: nomic::network::Config, +} impl ClaimCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.staking.claim_all()), |app| build_call!(app.deposit_rewards()), @@ -967,11 +1030,14 @@ impl ClaimCmd { #[derive(Parser, Debug)] pub struct AirdropCmd { address: Option
, + + #[clap(flatten)] + config: nomic::network::Config, } impl AirdropCmd { async fn run(&self) -> Result<()> { - let client = app_client(); + let client = self.config.client(); let addr = self.address.unwrap_or_else(my_address); let acct = match client.query(|app| app.airdrop.get(addr)).await? { @@ -991,11 +1057,14 @@ impl AirdropCmd { #[derive(Parser, Debug)] pub struct ClaimAirdropCmd { address: Option
, + + #[clap(flatten)] + config: nomic::network::Config, } impl ClaimAirdropCmd { async fn run(&self) -> Result<()> { - let client = app_client(); + let client = self.config.client(); let addr = self.address.unwrap_or_else(my_address); let acct = match client.query(|app| app.airdrop.get(addr)).await? { @@ -1009,7 +1078,9 @@ impl ClaimAirdropCmd { let mut claimed = false; if acct.airdrop1.claimable > 0 { - app_client() + self.config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.airdrop.claim_airdrop1()), |app| build_call!(app.accounts.give_from_funding_all()), @@ -1020,7 +1091,9 @@ impl ClaimAirdropCmd { } if acct.airdrop2.claimable > 0 { - app_client() + self.config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.airdrop.claim_airdrop2()), |app| build_call!(app.accounts.give_from_funding_all()), @@ -1071,7 +1144,7 @@ impl RelayerCmd { let create_relayer = async || { let btc_client = self.btc_client().await.unwrap(); - Relayer::new(btc_client) + Relayer::new(btc_client, self.config.node.as_ref().unwrap().to_string()) }; let mut relayer = create_relayer().await; @@ -1127,7 +1200,8 @@ impl SignerCmd { key_path, self.max_withdrawal_rate, self.max_sigset_change_rate, - app_client, + // TODO: check for custom RPC port, allow config, etc + || nomic::app_client("http://localhost:26657"), )? .start(); @@ -1142,11 +1216,16 @@ impl SignerCmd { #[derive(Parser, Debug)] pub struct SetSignatoryKeyCmd { xpub: bitcoin::util::bip32::ExtendedPubKey, + + #[clap(flatten)] + config: nomic::network::Config, } impl SetSignatoryKeyCmd { async fn run(&self) -> Result<()> { - app_client() + self.config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.accounts.take_as_funding(MIN_FEE.into())), |app| build_call!(app.bitcoin.set_signatory_key(self.xpub.into())), @@ -1157,8 +1236,11 @@ impl SetSignatoryKeyCmd { } } -async fn deposit(dest: DepositCommitment) -> Result<()> { - let sigset = app_client() +async fn deposit( + dest: DepositCommitment, + client: AppClient, +) -> Result<()> { + let sigset = client .query(|app| Ok(app.bitcoin.checkpoints.active_sigset()?)) .await?; let script = sigset.output_script(dest.commitment_bytes()?.as_slice())?; @@ -1190,13 +1272,16 @@ async fn deposit(dest: DepositCommitment) -> Result<()> { #[derive(Parser, Debug)] pub struct DepositCmd { address: Option
, + + #[clap(flatten)] + config: nomic::network::Config, } impl DepositCmd { async fn run(&self) -> Result<()> { let dest_addr = self.address.unwrap_or_else(my_address); - deposit(DepositCommitment::Address(dest_addr)).await + deposit(DepositCommitment::Address(dest_addr), self.config.client()).await } } @@ -1233,6 +1318,9 @@ impl InterchainDepositCmd { pub struct WithdrawCmd { dest: bitcoin::Address, amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, } impl WithdrawCmd { @@ -1241,7 +1329,9 @@ impl WithdrawCmd { let script = self.dest.script_pubkey(); - app_client() + self.config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.withdraw_nbtc(Adapter::new(script), self.amount.into())), |app| build_call!(app.app_noop()), @@ -1262,7 +1352,10 @@ pub struct IbcDepositNbtcCmd { #[cfg(feature = "testnet")] impl IbcDepositNbtcCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.ibc_deposit_nbtc(self.to, self.amount.into())), |app| build_call!(app.app_noop()), @@ -1280,7 +1373,10 @@ pub struct IbcWithdrawNbtcCmd { #[cfg(feature = "testnet")] impl IbcWithdrawNbtcCmd { async fn run(&self) -> Result<()> { - Ok(app_client() + Ok(self + .config + .client() + .with_wallet(wallet()) .call( |app| build_call!(app.ibc_withdraw_nbtc(self.amount.into())), |app| build_call!(app.app_noop()), @@ -1301,7 +1397,7 @@ impl GrpcCmd { async fn run(&self) -> Result<()> { use orga::ibc::GrpcOpts; orga::ibc::start_grpc( - || app_client().sub(|app| app.ibc), + || self.config.client().sub(|app| app.ibc), &GrpcOpts { host: "127.0.0.1".to_string(), port: self.port, @@ -1338,7 +1434,7 @@ impl IbcTransferCmd { // receiver: self.receiver.clone(), // }; - // Ok(app_client() + // Ok(self.config.client() // .pay_from(async move |client| { // client // .ibc_deposit_nbtc(my_address(), self.amount.into()) diff --git a/src/bitcoin/relayer.rs b/src/bitcoin/relayer.rs index 5323e72b..86d7cace 100644 --- a/src/bitcoin/relayer.rs +++ b/src/bitcoin/relayer.rs @@ -1,7 +1,7 @@ use super::signatory::Signatory; use super::SignatorySet; use crate::app::DepositCommitment; -use crate::app_client_testnet; +use crate::app_client; use crate::bitcoin::{adapter::Adapter, header_queue::WrappedHeader}; use crate::error::Error; use crate::error::Result; @@ -34,20 +34,22 @@ const HEADER_BATCH_SIZE: usize = 250; pub struct Relayer { btc_client: BitcoinRpcClient, + app_client_addr: String, scripts: Option, } impl Relayer { - pub fn new(btc_client: BitcoinRpcClient) -> Self { + pub fn new(btc_client: BitcoinRpcClient, app_client_addr: String) -> Self { Relayer { btc_client, + app_client_addr, scripts: None, } } async fn sidechain_block_hash(&self) -> Result { - let hash = app_client_testnet() + let hash = app_client(&self.app_client_addr) .query(|app| Ok(app.bitcoin.headers.hash()?)) .await?; let hash = BlockHash::from_slice(hash.as_slice())?; @@ -95,7 +97,7 @@ impl Relayer { pub async fn start_deposit_relay>(mut self, store_path: P) -> Result<()> { info!("Starting deposit relay..."); - let scripts = WatchedScriptStore::open(store_path).await?; + let scripts = WatchedScriptStore::open(store_path, &self.app_client_addr).await?; self.scripts = Some(scripts); let (server, mut recv) = self.create_address_server(); @@ -121,6 +123,9 @@ impl Relayer { let sigsets = Arc::new(Mutex::new(BTreeMap::new())); + // TODO: pass into closures more cleanly + let app_client_addr: &'static str = self.app_client_addr.clone().leak(); + // TODO: configurable listen address use bytes::Bytes; use warp::Filter; @@ -145,7 +150,7 @@ impl Relayer { let sigset = match sigsets.get(&query.sigset_index) { Some(sigset) => sigset, None => { - app_client_testnet() + app_client(app_client_addr) .query(|app| { let sigset = app .bitcoin @@ -191,8 +196,8 @@ impl Relayer { ); let sigset_route = warp::path("sigset") - .and_then(async move || { - let sigset = app_client_testnet() + .and_then(move || async { + let sigset = app_client(app_client_addr) .query(|app| { let sigset: RawSignatorySet = app.bitcoin.checkpoints.active_sigset()?.into(); @@ -292,7 +297,7 @@ impl Relayer { let mut relayed = HashSet::new(); loop { - let disbursal_txs = app_client_testnet() + let disbursal_txs = app_client() .query(|app| Ok(app.bitcoin.checkpoints.emergency_disbursal_txs()?)) .await?; @@ -346,7 +351,7 @@ impl Relayer { } async fn relay_checkpoints(&mut self) -> Result<()> { - let last_checkpoint = app_client_testnet() + let last_checkpoint = app_client(&self.app_client_addr) .query(|app| Ok(app.bitcoin.checkpoints.last_completed_tx()?)) .await?; info!("Last checkpoint tx: {}", last_checkpoint.txid()); @@ -354,7 +359,7 @@ impl Relayer { let mut relayed = HashSet::new(); loop { - let txs = app_client_testnet() + let txs = app_client(&self.app_client_addr) .query(|app| Ok(app.bitcoin.checkpoints.completed_txs()?)) .await?; for tx in txs { @@ -389,7 +394,7 @@ impl Relayer { recv: &mut Receiver<(DepositCommitment, u32)>, ) -> Result<()> { while let Ok((addr, sigset_index)) = recv.try_recv() { - let sigset_res = app_client_testnet() + let sigset_res = app_client(&self.app_client_addr) .query(|app| Ok(app.bitcoin.checkpoints.get(sigset_index)?.sigset.clone())) .await; let sigset = match sigset_res { @@ -479,7 +484,7 @@ impl Relayer { let outpoint = (txid.into_inner(), output.vout); let dest = output.dest.clone(); let vout = output.vout; - let contains_outpoint = app_client_testnet() + let contains_outpoint = app_client(&self.app_client_addr) .query(|app| app.bitcoin.processed_outpoints.contains(outpoint)) .await?; @@ -499,7 +504,7 @@ impl Relayer { let tx = Adapter::new(tx); let proof = Adapter::new(proof); - let res = app_client_testnet() + let res = app_client(&self.app_client_addr) .call( move |app| { build_call!(app.relay_deposit( @@ -558,13 +563,13 @@ impl Relayer { batch[0].height(), batch.len(), ); - app_client_testnet() + app_client(&self.app_client_addr) .call( |app| build_call!(app.bitcoin.headers.add(batch.clone().into_iter().collect())), |app| build_call!(app.app_noop()), ) .await?; - let res = app_client_testnet() + let res = app_client(&self.app_client_addr) .call( move |app| build_call!(app.bitcoin.headers.add(batch.clone().into())), |app| build_call!(app.app_noop()), @@ -757,11 +762,11 @@ pub struct WatchedScriptStore { } impl WatchedScriptStore { - pub async fn open>(path: P) -> Result { + pub async fn open>(path: P, app_client_addr: &str) -> Result { let path = path.as_ref().join("watched-addrs.csv"); let mut scripts = WatchedScripts::new(); - Self::maybe_load(&path, &mut scripts).await?; + Self::maybe_load(&path, &mut scripts, app_client_addr).await?; let tmp_path = path.with_file_name("watched-addrs-tmp.csv"); let mut tmp_file = File::create(&tmp_path)?; @@ -779,7 +784,11 @@ impl WatchedScriptStore { Ok(WatchedScriptStore { scripts, file }) } - async fn maybe_load>(path: P, scripts: &mut WatchedScripts) -> Result<()> { + async fn maybe_load>( + path: P, + scripts: &mut WatchedScripts, + app_client_addr: &str, + ) -> Result<()> { let file = match File::open(&path) { Err(ref e) if e.kind() == io::ErrorKind::NotFound => return Ok(()), Err(e) => return Err(e.into()), @@ -787,7 +796,7 @@ impl WatchedScriptStore { }; let mut sigsets = BTreeMap::new(); - app_client_testnet() + app_client(app_client_addr) .query(|app| { for (index, checkpoint) in app.bitcoin.checkpoints.all()? { sigsets.insert(index, checkpoint.sigset.clone()); @@ -855,7 +864,7 @@ mod tests { BitcoinRpcClient::new(&bitcoind_url, Auth::CookieFile(bitcoin_cookie_file)).unwrap(); bitcoind.client.generate_to_address(25, &address).unwrap(); - let relayer = Relayer::new(rpc_client); + let relayer = Relayer::new(rpc_client, "http://localhost:26657".to_string()); let block_hash = bitcoind.client.get_block_hash(30).unwrap(); let headers = relayer.get_header_batch(block_hash).unwrap(); @@ -887,7 +896,7 @@ mod tests { BitcoinRpcClient::new(&bitcoind_url, Auth::CookieFile(bitcoin_cookie_file)).unwrap(); bitcoind.client.generate_to_address(7, &address).unwrap(); - let relayer = Relayer::new(rpc_client); + let relayer = Relayer::new(rpc_client, "http://localhost:26657".to_string()); let block_hash = bitcoind.client.get_block_hash(30).unwrap(); let headers = relayer.get_header_batch(block_hash).unwrap(); diff --git a/src/lib.rs b/src/lib.rs index a0361b39..65c276bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ #![feature(specialization)] #![feature(type_alias_impl_trait)] #![feature(async_closure)] +#![feature(string_leak)] #[cfg(feature = "full")] use orga::{ @@ -19,12 +20,15 @@ pub mod app; pub mod bitcoin; pub mod error; pub mod incentives; +#[cfg(feature = "full")] pub mod network; +#[cfg(feature = "full")] pub mod utils; #[cfg(feature = "full")] -pub fn app_client_testnet( +pub fn app_client( + addr: &str, ) -> AppClient { - let client = HttpClient::new("http://localhost:26657").unwrap(); + let client = HttpClient::new(addr).unwrap(); AppClient::new(client, Unsigned) } diff --git a/src/network.rs b/src/network.rs index 0afc9ec7..a3ffd114 100644 --- a/src/network.rs +++ b/src/network.rs @@ -1,5 +1,12 @@ -use crate::error::{Error, Result}; +use crate::{ + app::{InnerApp, Nom}, + error::{Error, Result}, +}; use clap::{self, ArgMatches, Args, Command, CommandFactory, ErrorKind, FromArgMatches, Parser}; +use orga::{ + client::{wallet::Unsigned, AppClient}, + tendermint::client::HttpClient, +}; use serde::{Deserialize, Serialize}; #[cfg(feature = "full")] use std::path::PathBuf; @@ -62,7 +69,9 @@ pub struct InnerConfig { #[clap(long, global = true)] pub network: Option, #[clap(long, global = true)] - home: Option, + pub home: Option, + #[clap(long, global = true)] + pub node: Option, #[clap(global = true)] pub tendermint_flags: Vec, @@ -70,7 +79,9 @@ pub struct InnerConfig { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(transparent)] -pub struct Config(InnerConfig); +pub struct Config { + args: InnerConfig, +} impl Config { #[cfg(feature = "full")] @@ -88,23 +99,30 @@ impl Config { } pub fn is_empty(&self) -> bool { - self.0.network.is_none() - && self.0.chain_id.is_none() - && self.0.genesis.is_none() - && self.0.home.is_none() + self.args.network.is_none() + && self.args.chain_id.is_none() + && self.args.genesis.is_none() + && self.args.home.is_none() + } + + pub fn client(&self) -> AppClient { + // TODO: get port from config for default + let default_addr = "http://localhost:26657".to_string(); + let node = self.args.node.as_ref().unwrap_or(&default_addr); + crate::app_client(node) } } impl Deref for Config { type Target = InnerConfig; fn deref(&self) -> &Self::Target { - &self.0 + &self.args } } impl DerefMut for Config { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 + &mut self.args } } @@ -112,7 +130,9 @@ impl Parser for Config {} impl FromArgMatches for Config { fn from_arg_matches(matches: &ArgMatches) -> std::result::Result { - let mut config = Self(Default::default()); + let mut config = Self { + args: Default::default(), + }; config.update_from_arg_matches(matches)?; Ok(config) } @@ -121,24 +141,24 @@ impl FromArgMatches for Config { &mut self, matches: &ArgMatches, ) -> std::result::Result<(), clap::Error> { - self.0.update_from_arg_matches(matches)?; + self.args.update_from_arg_matches(matches)?; if self.is_empty() { - self.0.network = match env!("GIT_BRANCH") { + self.args.network = match env!("GIT_BRANCH") { "main" => Some(Network::Mainnet), "testnet" => Some(Network::Testnet), _ => None, }; - if let Some(network) = self.0.network { + if let Some(network) = self.args.network { log::debug!("Using default network: {:?}", network); } else { log::debug!("Built on branch with no default network."); } } - if let Some(network) = self.0.network { + if let Some(network) = self.args.network { let mut net_config = network.config(); - let arg_config = &self.0; + let arg_config = &self.args; if arg_config.chain_id.is_some() { return Err(clap::Error::raw( @@ -174,14 +194,14 @@ impl FromArgMatches for Config { .tendermint_flags .extend(arg_config.tendermint_flags.iter().cloned()); - self.0 = net_config; + self.args = net_config; } - if let Some(genesis) = self.0.genesis.as_ref() { + if let Some(genesis) = self.args.genesis.as_ref() { let genesis: serde_json::Value = genesis.parse().unwrap(); let gensis_cid = genesis["chain_id"].as_str().unwrap(); - if let Some(cid) = self.0.chain_id.as_ref() { + if let Some(cid) = self.args.chain_id.as_ref() { if cid != gensis_cid { return Err(clap::Error::raw( ErrorKind::ArgumentConflict, @@ -192,7 +212,7 @@ impl FromArgMatches for Config { )); } } else { - self.0.chain_id = Some(gensis_cid.to_string()); + self.args.chain_id = Some(gensis_cid.to_string()); } } diff --git a/src/utils.rs b/src/utils.rs index aef8dcf2..df2c727a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,7 +2,9 @@ #[cfg(feature = "full")] use crate::app::App; +use crate::app::InnerApp; use crate::app::Nom; +use crate::app_client; #[cfg(feature = "full")] use crate::bitcoin::adapter::Adapter; #[cfg(feature = "full")] @@ -10,7 +12,6 @@ use crate::bitcoin::header_queue::Config as HeaderQueueConfig; #[cfg(feature = "full")] use crate::bitcoin::signer::Signer; use crate::error::{Error, Result}; -use crate::{app::InnerApp, app_client_testnet}; use bitcoin::hashes::hex::ToHex; use bitcoin::secp256k1::{self, rand, SecretKey}; #[cfg(feature = "full")] @@ -53,6 +54,8 @@ use std::str::FromStr; use std::time::Duration; use std::time::{SystemTime, UNIX_EPOCH}; +const DEFAULT_RPC: &str = "http://localhost:26657"; + pub fn retry(f: F, max_retries: u32) -> std::result::Result where F: Fn() -> std::result::Result, @@ -235,7 +238,7 @@ pub async fn declare_validator(home: &Path, wallet: DerivedKey) -> Result<()> { min_self_delegation: 0.into(), }; - app_client_testnet() + app_client(DEFAULT_RPC) .with_wallet(wallet) .call( move |app| build_call!(app.accounts.take_as_funding((100000 + MIN_FEE).into())), @@ -250,7 +253,10 @@ pub async fn declare_validator(home: &Path, wallet: DerivedKey) -> Result<()> { pub async fn poll_for_blocks() { info!("Scanning for blocks..."); loop { - match app_client_testnet().query(|app| app.app_noop_query()).await { + match app_client(DEFAULT_RPC) + .query(|app| app.app_noop_query()) + .await + { Ok(_) => { break; } @@ -264,7 +270,7 @@ pub async fn poll_for_blocks() { pub async fn poll_for_signatory_key() { info!("Scanning for signatory key..."); loop { - match app_client_testnet() + match app_client(DEFAULT_RPC) .query(|app| Ok(app.bitcoin.checkpoints.active_sigset()?)) .await { @@ -276,13 +282,13 @@ pub async fn poll_for_signatory_key() { pub async fn poll_for_completed_checkpoint(num_checkpoints: u32) { info!("Scanning for signed checkpoints..."); - let mut checkpoint_len = app_client_testnet() + let mut checkpoint_len = app_client(DEFAULT_RPC) .query(|app| Ok(app.bitcoin.checkpoints.completed()?.len())) .await .unwrap(); while checkpoint_len < num_checkpoints as usize { - checkpoint_len = app_client_testnet() + checkpoint_len = app_client(DEFAULT_RPC) .query(|app| Ok(app.bitcoin.checkpoints.completed()?.len())) .await .unwrap(); @@ -293,7 +299,7 @@ pub async fn poll_for_completed_checkpoint(num_checkpoints: u32) { pub async fn poll_for_bitcoin_header(height: u32) -> Result<()> { info!("Scanning for bitcoin header {}...", height); loop { - let current_height = app_client_testnet() + let current_height = app_client(DEFAULT_RPC) .query(|app| Ok(app.bitcoin.headers.height()?)) .await?; if current_height >= height { diff --git a/tests/bitcoin.rs b/tests/bitcoin.rs index e2a51b36..bf77a59a 100644 --- a/tests/bitcoin.rs +++ b/tests/bitcoin.rs @@ -8,8 +8,7 @@ use bitcoind::bitcoincore_rpc::RpcApi; use bitcoind::{BitcoinD, Conf}; use log::info; use nomic::app::DepositCommitment; -use nomic::app::{InnerApp, Nom}; -use nomic::app_client_testnet; +use nomic::app::{self, InnerApp, Nom}; use nomic::bitcoin::relayer::DepositAddress; use nomic::bitcoin::relayer::Relayer; use nomic::error::{Error, Result}; @@ -19,8 +18,10 @@ use nomic::utils::{ setup_test_signer, setup_time_context, test_bitcoin_client, KeyData, }; use orga::abci::Node; -use orga::client::wallet::DerivedKey; -use orga::client::AppClient; +use orga::client::{ + wallet::{DerivedKey, Unsigned}, + AppClient, +}; use orga::coins::{Address, Amount}; use orga::encoding::Encode; use orga::macros::build_call; @@ -36,9 +37,15 @@ use tempfile::tempdir; static INIT: Once = Once::new(); +fn app_client( +) -> AppClient +{ + nomic::app_client("http://localhost:26657") +} + async fn generate_deposit_address(address: &Address) -> Result { info!("Generating deposit address for {}...", address); - let sigset = app_client_testnet() + let sigset = app_client() .query(|app| Ok(app.bitcoin.checkpoints.active_sigset()?)) .await?; let script = sigset.output_script( @@ -129,7 +136,7 @@ async fn withdraw_bitcoin( let wallet = DerivedKey::from_secret_key(key); let dest_script = nomic::bitcoin::adapter::Adapter::new(dest_address.script_pubkey()); - app_client_testnet() + app_client() .with_wallet(wallet) .call( move |app| build_call!(app.withdraw_nbtc(dest_script, Amount::from(usats))), @@ -142,7 +149,7 @@ async fn withdraw_bitcoin( fn client_provider() -> AppClient { let val_priv_key = load_privkey().unwrap(); let wallet = DerivedKey::from_secret_key(val_priv_key); - app_client_testnet().with_wallet(wallet) + app_client().with_wallet(wallet) } #[tokio::test] @@ -178,13 +185,15 @@ async fn bitcoin_test() { .unwrap(); }); - let mut relayer = Relayer::new(test_bitcoin_client(&bitcoind)); + let rpc_addr = "http://localhost:26657".to_string(); + + let mut relayer = Relayer::new(test_bitcoin_client(&bitcoind), rpc_addr.clone()); let headers = relayer.start_header_relay(); - let relayer = Relayer::new(test_bitcoin_client(&bitcoind)); + let relayer = Relayer::new(test_bitcoin_client(&bitcoind), rpc_addr.clone()); let deposits = relayer.start_deposit_relay(&header_relayer_path); - let mut relayer = Relayer::new(test_bitcoin_client(&bitcoind)); + let mut relayer = Relayer::new(test_bitcoin_client(&bitcoind), rpc_addr.clone()); let checkpoints = relayer.start_checkpoint_relay(); #[cfg(feature = "emergency-disbursal")] @@ -246,7 +255,7 @@ async fn bitcoin_test() { poll_for_bitcoin_header(1120).await.unwrap(); - let balance = app_client_testnet() + let balance = app_client() .query(|app| app.bitcoin.accounts.balance(funded_accounts[0].address)) .await .unwrap(); @@ -271,7 +280,7 @@ async fn bitcoin_test() { poll_for_bitcoin_header(1121).await.unwrap(); poll_for_completed_checkpoint(1).await; - let balance = app_client_testnet() + let balance = app_client() .query(|app| app.bitcoin.accounts.balance(funded_accounts[0].address)) .await .unwrap(); @@ -295,7 +304,7 @@ async fn bitcoin_test() { poll_for_bitcoin_header(1122).await.unwrap(); poll_for_completed_checkpoint(2).await; - let balance = app_client_testnet() + let balance = app_client() .query(|app| app.bitcoin.accounts.balance(funded_accounts[1].address)) .await .unwrap(); @@ -315,7 +324,7 @@ async fn bitcoin_test() { poll_for_bitcoin_header(1123).await.unwrap(); poll_for_completed_checkpoint(3).await; - let balance = app_client_testnet() + let balance = app_client() .query(|app| app.bitcoin.accounts.balance(funded_accounts[0].address)) .await .unwrap(); @@ -349,7 +358,7 @@ async fn bitcoin_test() { for (i, account) in funded_accounts[0..=1].iter().enumerate() { let dump_address = wallet.get_new_address(None, None).unwrap(); - let disbursal_txs = app_client_testnet() + let disbursal_txs = app_client() .query(|app| Ok(app.bitcoin.checkpoints.emergency_disbursal_txs()?)) .await .unwrap(); From af0800e97bd4bc5ac8af9749bfefe15442d644a4 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Thu, 31 Aug 2023 13:55:09 -0500 Subject: [PATCH 2/6] Fix --node changes for all features --- src/bin/nomic.rs | 15 ++++++++++++++- src/bitcoin/checkpoint.rs | 8 -------- src/bitcoin/relayer.rs | 2 +- tests/bitcoin.rs | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/bin/nomic.rs b/src/bin/nomic.rs index 19482f30..25b3fabd 100644 --- a/src/bin/nomic.rs +++ b/src/bin/nomic.rs @@ -1347,6 +1347,9 @@ impl WithdrawCmd { pub struct IbcDepositNbtcCmd { to: Address, amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, } #[cfg(feature = "testnet")] @@ -1368,6 +1371,9 @@ impl IbcDepositNbtcCmd { #[derive(Parser, Debug)] pub struct IbcWithdrawNbtcCmd { amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, } #[cfg(feature = "testnet")] @@ -1390,6 +1396,9 @@ impl IbcWithdrawNbtcCmd { pub struct GrpcCmd { #[clap(default_value_t = 9001)] port: u16, + + #[clap(flatten)] + config: nomic::network::Config, } #[cfg(feature = "testnet")] @@ -1397,7 +1406,8 @@ impl GrpcCmd { async fn run(&self) -> Result<()> { use orga::ibc::GrpcOpts; orga::ibc::start_grpc( - || self.config.client().sub(|app| app.ibc), + // TODO: support configuring RPC address + || nomic::app_client("http://localhost:26657").sub(|app| app.ibc), &GrpcOpts { host: "127.0.0.1".to_string(), port: self.port, @@ -1417,6 +1427,9 @@ pub struct IbcTransferCmd { channel_id: String, port_id: String, denom: String, + + #[clap(flatten)] + config: nomic::network::Config, } #[cfg(feature = "testnet")] diff --git a/src/bitcoin/checkpoint.rs b/src/bitcoin/checkpoint.rs index f63c7fd6..c2ba906b 100644 --- a/src/bitcoin/checkpoint.rs +++ b/src/bitcoin/checkpoint.rs @@ -1342,14 +1342,6 @@ impl CheckpointQueue { #[cfg(test)] mod test { - use bitcoin::{ - util::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey}, - OutPoint, PubkeyHash, Script, Txid, - }; - use rand::Rng; - - use crate::bitcoin::{signatory::Signatory, threshold_sig::Share}; - use super::*; fn push_bitcoin_tx_output(tx: &mut BitcoinTx, value: u64) { diff --git a/src/bitcoin/relayer.rs b/src/bitcoin/relayer.rs index 86d7cace..73f11e76 100644 --- a/src/bitcoin/relayer.rs +++ b/src/bitcoin/relayer.rs @@ -297,7 +297,7 @@ impl Relayer { let mut relayed = HashSet::new(); loop { - let disbursal_txs = app_client() + let disbursal_txs = app_client(&self.app_client_addr) .query(|app| Ok(app.bitcoin.checkpoints.emergency_disbursal_txs()?)) .await?; diff --git a/tests/bitcoin.rs b/tests/bitcoin.rs index bf77a59a..a7a69d16 100644 --- a/tests/bitcoin.rs +++ b/tests/bitcoin.rs @@ -197,7 +197,7 @@ async fn bitcoin_test() { let checkpoints = relayer.start_checkpoint_relay(); #[cfg(feature = "emergency-disbursal")] - let mut relayer = Relayer::new(test_bitcoin_client(&bitcoind)); + let mut relayer = Relayer::new(test_bitcoin_client(&bitcoind), rpc_addr.clone()); #[cfg(feature = "emergency-disbursal")] let disbursal = relayer.start_emergency_disbursal_transaction_relay(); #[cfg(not(feature = "emergency-disbursal"))] From 6be765b3d82a12e05a260777094b515b47034e70 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Thu, 31 Aug 2023 14:23:34 -0500 Subject: [PATCH 3/6] Fix imports --- src/bitcoin/checkpoint.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/bitcoin/checkpoint.rs b/src/bitcoin/checkpoint.rs index c2ba906b..3e36b84d 100644 --- a/src/bitcoin/checkpoint.rs +++ b/src/bitcoin/checkpoint.rs @@ -1342,6 +1342,17 @@ impl CheckpointQueue { #[cfg(test)] mod test { + #[cfg(all(feature = "full", not(feature = "emergency-disbursal")))] + use bitcoin::{ + util::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey}, + OutPoint, PubkeyHash, Script, Txid, + }; + #[cfg(all(feature = "full", not(feature = "emergency-disbursal")))] + use rand::Rng; + + #[cfg(all(feature = "full", not(feature = "emergency-disbursal")))] + use crate::bitcoin::{signatory::Signatory, threshold_sig::Share}; + use super::*; fn push_bitcoin_tx_output(tx: &mut BitcoinTx, value: u64) { @@ -1433,7 +1444,7 @@ mod test { power: 100, sig: None, }, - ); + )?; Ok::<_, Error>(input) }; @@ -1452,7 +1463,7 @@ mod test { power: 100, sig: Some(Signature([123; 64])), }, - ); + )?; input.signatures.signed = 100; Ok::<_, Error>(input) }; From 338df2a93273816326b9fea03810648994a44c1f Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Thu, 31 Aug 2023 14:28:07 -0500 Subject: [PATCH 4/6] Fix rest build --- rest/src/main.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rest/src/main.rs b/rest/src/main.rs index 205e729f..f9f28b6e 100644 --- a/rest/src/main.rs +++ b/rest/src/main.rs @@ -3,11 +3,12 @@ extern crate rocket; use nomic::{ app::{App, InnerApp, Nom}, - app_client, orga::{ + client::{wallet::Unsigned, AppClient}, coins::{Address, Amount, Decimal}, plugins::*, query::Query, + tendermint::client::HttpClient, }, }; use rocket::response::status::BadRequest; @@ -23,6 +24,10 @@ lazy_static::lazy_static! { static ref QUERY_CACHE: Arc>> = Arc::new(RwLock::new(HashMap::new())); } +fn app_client() -> AppClient { + nomic::app_client("http://localhost:26657") +} + #[get("/cosmos/bank/v1beta1/balances/
")] async fn bank_balances(address: &str) -> Result> { let address: Address = address.parse().unwrap(); From f904ee7a2ca292ef830d8a8392b56a7c21d4076e Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Thu, 31 Aug 2023 15:20:20 -0500 Subject: [PATCH 5/6] Set default node config value --- src/network.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/network.rs b/src/network.rs index a3ffd114..fe5f6007 100644 --- a/src/network.rs +++ b/src/network.rs @@ -106,9 +106,7 @@ impl Config { } pub fn client(&self) -> AppClient { - // TODO: get port from config for default - let default_addr = "http://localhost:26657".to_string(); - let node = self.args.node.as_ref().unwrap_or(&default_addr); + let node = self.args.node.as_ref().unwrap(); crate::app_client(node) } } @@ -216,6 +214,11 @@ impl FromArgMatches for Config { } } + if self.args.node.is_none() { + // TODO: get port from Tendermint config.toml for default + self.args.node = Some("http://localhost:26657".to_string()); + } + Ok(()) } } From feb3b6fd769f0025ad20c108e884f39d7ca73d3a Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Thu, 31 Aug 2023 15:20:52 -0500 Subject: [PATCH 6/6] Fix update-status command for --node option --- src/bin/nomic.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bin/nomic.rs b/src/bin/nomic.rs index dca0b998..8be6bd27 100644 --- a/src/bin/nomic.rs +++ b/src/bin/nomic.rs @@ -1487,15 +1487,19 @@ impl ExportCmd { } #[derive(Parser, Debug)] -pub struct UpgradeStatusCmd {} +pub struct UpgradeStatusCmd { + #[clap(flatten)] + config: nomic::network::Config, +} impl UpgradeStatusCmd { async fn run(&self) -> Result<()> { use orga::coins::staking::ValidatorQueryInfo; use orga::coins::VersionedAddress; use std::collections::{HashMap, HashSet}; - let client = app_client(); - let tm_client = tendermint_rpc::HttpClient::new("http://localhost:26657").unwrap(); + let client = self.config.client(); + let tm_client = + tendermint_rpc::HttpClient::new(self.config.node.as_ref().unwrap().as_str()).unwrap(); let curr_height = tm_client .status() .await