diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3000d15b..3373a292 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: toolchain: nightly-2023-05-08 override: true - name: Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -51,7 +51,7 @@ jobs: toolchain: nightly-2023-05-08 override: true - name: Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -76,7 +76,7 @@ jobs: toolchain: nightly-2023-05-08 override: true - name: Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -137,7 +137,7 @@ jobs: override: true - name: Cache id: cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo @@ -192,7 +192,7 @@ jobs: components: clippy override: true - name: Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: | ~/.cargo diff --git a/Cargo.lock b/Cargo.lock index d89de8ac..0b83e786 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2365,7 +2365,7 @@ dependencies = [ [[package]] name = "nomic" -version = "7.0.0" +version = "7.1.0" dependencies = [ "base64 0.13.1", "bech32", @@ -2544,7 +2544,7 @@ dependencies = [ [[package]] name = "orga" version = "0.3.1" -source = "git+https://github.com/nomic-io/orga.git?rev=38682a1eafc9c3566aa5de4601a1aff06eb79c4f#38682a1eafc9c3566aa5de4601a1aff06eb79c4f" +source = "git+https://github.com/nomic-io/orga.git?rev=bd9b07a96c21669bf0de52640ad81eaf8d7f0aae#bd9b07a96c21669bf0de52640ad81eaf8d7f0aae" dependencies = [ "abci2", "async-trait", @@ -2605,7 +2605,7 @@ dependencies = [ [[package]] name = "orga-macros" version = "0.3.1" -source = "git+https://github.com/nomic-io/orga.git?rev=38682a1eafc9c3566aa5de4601a1aff06eb79c4f#38682a1eafc9c3566aa5de4601a1aff06eb79c4f" +source = "git+https://github.com/nomic-io/orga.git?rev=bd9b07a96c21669bf0de52640ad81eaf8d7f0aae#bd9b07a96c21669bf0de52640ad81eaf8d7f0aae" dependencies = [ "darling", "heck 0.3.3", diff --git a/Cargo.toml b/Cargo.toml index bf573a83..bc978952 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nomic" -version = "7.0.0" +version = "7.1.0" authors = ["The Turbofish Team "] edition = "2021" default-run = "nomic" [dependencies] bitcoin = { version = "0.29.2", features = ["serde", "rand"] } -orga = { git = "https://github.com/nomic-io/orga.git", rev = "38682a1eafc9c3566aa5de4601a1aff06eb79c4f", features = [ +orga = { git = "https://github.com/nomic-io/orga.git", rev = "bd9b07a96c21669bf0de52640ad81eaf8d7f0aae", features = [ "merk-verify", ] } thiserror = "1.0.30" @@ -66,7 +66,7 @@ toml = { version = "0.7.2", features = ["parse"] } semver = "1.0.18" [features] -default = ["full", "feat-ibc", "legacy-bin"] +default = ["full", "feat-ibc", "testnet"] full = [ "bitcoincore-rpc-async", "clap", diff --git a/build.rs b/build.rs index 49e2d49d..eba729fd 100644 --- a/build.rs +++ b/build.rs @@ -35,14 +35,14 @@ fn main() { include_str!("networks/stakenet.toml") }; let config: toml::Value = toml::from_str(toml).unwrap(); - config - .as_table() - .unwrap() - .get("legacy_version") - .unwrap() - .as_str() - .unwrap() - .to_string() + if let Some(legacy_version) = config.as_table().unwrap().get("legacy_version") { + legacy_version.as_str().unwrap().to_string() + } else { + println!("No legacy_version set in network config"); + println!("cargo:rustc-env=NOMIC_LEGACY_BUILD_PATH=/dev/null"); + println!("cargo:rustc-env=NOMIC_LEGACY_BUILD_VERSION="); + return; + } }; if version_req_str.chars().next().unwrap().is_numeric() { version_req_str = format!("={}", version_req_str); diff --git a/networks/testnet.toml b/networks/testnet.toml index 4b2371e6..ceffa1f4 100644 --- a/networks/testnet.toml +++ b/networks/testnet.toml @@ -1,25 +1,16 @@ state_sync_rpc = [ "http://147.182.171.216:26667", "http://147.182.171.216:26677", - "https://rpc.nomic-testnet.basementnodes.ca" ] -tendermint_flags = [ - "--p2p.seeds", - """ +tendermint_flags = ["--p2p.seeds", """ 6a6c1af342ce45d550e30ddc187bbbb81167d9b8@147.182.171.216:26656,\ - """, -] -btc_relayer = [ - "https://relayer.nomic-testnet.mappum.io:8443" -] - -legacy_version = "6.4" + """] +btc_relayer = ["https://relayer.nomic-testnet.mappum.io:8443"] genesis = """ { - "genesis_time": "2022-10-05T00:00:00Z", - "chain_id": "nomic-testnet-4d", - "initial_height": "0", + "app_hash": "", + "chain_id": "nomic-testnet-5", "consensus_params": { "block": { "max_bytes": "22020096", @@ -27,16 +18,29 @@ genesis = """ "time_iota_ms": "1000" }, "evidence": { - "max_age_num_blocks": "100000", "max_age_duration": "172800000000000", + "max_age_num_blocks": "100000", "max_bytes": "1048576" }, "validator": { - "pub_key_types": ["ed25519"] + "pub_key_types": [ + "ed25519" + ] }, "version": {} }, - "validators": [], - "app_hash": "" + "genesis_time": "2024-02-14T19:53:11.939148Z", + "initial_height": "0", + "validators": [ + { + "address": "044AD55B10017D73B72269396305A71B82CD1216", + "name": "", + "power": "10", + "pub_key": { + "type": "tendermint/PubKeyEd25519", + "value": "orlC75T55Qe9hgqGZzkPMIOeTn7kvsA2+/d2gZWHL2g=" + } + } + ] } """ diff --git a/src/app.rs b/src/app.rs index b36b16ac..aefe8f82 100644 --- a/src/app.rs +++ b/src/app.rs @@ -66,9 +66,9 @@ const STRATEGIC_RESERVE_ADDRESS: &str = "nomic1d5n325zrf4elfu0heqd59gna5j6xyunhe const VALIDATOR_BOOTSTRAP_ADDRESS: &str = "nomic1fd9mxxt84lw3jdcsmjh6jy8m6luafhqd8dcqeq"; const IBC_FEE_USATS: u64 = 1_000_000; -const DECLARE_FEE_USATS: u64 = 100_000_000; +const CALL_FEE_USATS: u64 = 100_000_000; -#[orga(version = 4)] +#[orga(version = 5)] pub struct InnerApp { #[call] pub accounts: Accounts, @@ -93,7 +93,7 @@ pub struct InnerApp { #[call] pub ibc: Ibc, #[cfg(not(feature = "testnet"))] - #[orga(version(V4))] + #[orga(version(V4, V5))] #[call] pub ibc: Ibc, @@ -105,13 +105,13 @@ pub struct InnerApp { #[cfg(feature = "testnet")] pub cosmos: Cosmos, #[cfg(not(feature = "testnet"))] - #[orga(version(V4))] + #[orga(version(V4, V5))] pub cosmos: Cosmos, } #[orga] impl InnerApp { - pub const CONSENSUS_VERSION: u8 = 10; + pub const CONSENSUS_VERSION: u8 = 11; #[cfg(feature = "full")] fn configure_faucets(&mut self) -> Result<()> { @@ -328,16 +328,21 @@ impl InnerApp { #[call] pub fn declare_with_nbtc(&mut self, declaration: Declaration) -> Result<()> { - self.deduct_nbtc_fee(DECLARE_FEE_USATS.into())?; + self.deduct_nbtc_fee(CALL_FEE_USATS.into())?; let signer = self.signer()?; self.staking.declare(signer, declaration, 0.into()) } + #[call] + pub fn pay_nbtc_fee(&mut self) -> Result<()> { + self.deduct_nbtc_fee(CALL_FEE_USATS.into()) + } + fn deduct_nbtc_fee(&mut self, amount: Amount) -> Result<()> { disable_fee(); let signer = self.signer()?; - self.bitcoin.accounts.withdraw(signer, amount)?.burn(); - + let fee = self.bitcoin.accounts.withdraw(signer, amount)?; + self.bitcoin.give_rewards(fee)?; Ok(()) } @@ -424,6 +429,18 @@ mod abci { .current_version .insert((), vec![Self::CONSENSUS_VERSION].try_into().unwrap())?; + #[cfg(feature = "testnet")] + { + self.upgrade.activation_delay_seconds = 20 * 60; + + include_str!("../testnet_addresses.csv") + .lines() + .try_for_each(|line| { + let address = line.parse().unwrap(); + self.accounts.deposit(address, Coin::mint(10_000_000_000)) + })?; + } + Ok(()) } } @@ -923,12 +940,30 @@ impl ConvertSdkTx for InnerApp { crate::bitcoin::adapter::Adapter::new(recovery_addr.script_pubkey()); let funding_amt = MIN_FEE; - let payer = build_call!(self.accounts.take_as_funding(funding_amt.into())); + let payer = build_call!(self.pay_nbtc_fee()); let paid = build_call!(self.bitcoin.set_recovery_script(script.clone())); Ok(PaidCall { payer, paid }) } + "nomic/PayToFeePool" => { + let msg = msg + .value + .as_object() + .ok_or_else(|| Error::App("Invalid message value".to_string()))?; + + let amount: u64 = msg["amount"] + .as_str() + .ok_or_else(|| Error::App("Invalid amount".to_string()))? + .parse() + .map_err(|e: std::num::ParseIntError| Error::App(e.to_string()))?; + + let payer = build_call!(self.bitcoin.transfer_to_fee_pool(amount.into())); + let paid = build_call!(self.app_noop()); + + Ok(PaidCall { payer, paid }) + } + _ => Err(Error::App("Unsupported message type".into())), } } diff --git a/src/app/migrations.rs b/src/app/migrations.rs index 26488c83..1222e63f 100644 --- a/src/app/migrations.rs +++ b/src/app/migrations.rs @@ -1,6 +1,6 @@ use crate::incentives::Incentives; -use super::{InnerAppV0, InnerAppV1, InnerAppV2, InnerAppV3, InnerAppV4}; +use super::{InnerAppV0, InnerAppV1, InnerAppV2, InnerAppV3, InnerAppV4, InnerAppV5}; use orga::{ coins::Take, ibc::Ibc, @@ -87,3 +87,30 @@ impl MigrateFrom for InnerAppV4 { }) } } + +impl MigrateFrom for InnerAppV5 { + fn migrate_from(other: InnerAppV4) -> Result { + #[cfg(not(feature = "testnet"))] + { + todo!() + } + + Ok(Self { + accounts: other.accounts, + staking: other.staking, + airdrop: other.airdrop, + community_pool: other.community_pool, + incentive_pool: other.incentive_pool, + staking_rewards: other.staking_rewards, + dev_rewards: other.dev_rewards, + community_pool_rewards: other.community_pool_rewards, + incentive_pool_rewards: other.incentive_pool_rewards, + bitcoin: other.bitcoin, + reward_timer: other.reward_timer, + upgrade: other.upgrade, + incentives: other.incentives, + ibc: other.ibc, + cosmos: other.cosmos, + }) + } +} diff --git a/src/bin/nomic.rs b/src/bin/nomic.rs index 9211f464..19a13bb4 100644 --- a/src/bin/nomic.rs +++ b/src/bin/nomic.rs @@ -4,14 +4,18 @@ #![feature(async_closure)] #![feature(never_type)] +use bitcoin::consensus::{Decodable, Encodable}; use bitcoin::secp256k1; use bitcoin::util::bip32::ExtendedPubKey; +use bitcoincore_rpc_async::RpcApi; use bitcoincore_rpc_async::{Auth, Client as BtcClient}; use clap::Parser; use nomic::app::Dest; use nomic::app::IbcDest; use nomic::app::InnerApp; use nomic::app::Nom; +use nomic::bitcoin::adapter::Adapter; +use nomic::bitcoin::signatory::SignatorySet; use nomic::bitcoin::Nbtc; use nomic::bitcoin::{relayer::Relayer, signer::Signer}; use nomic::error::Result; @@ -35,6 +39,8 @@ use std::fs::Permissions; use std::os::unix::fs::PermissionsExt; use std::path::PathBuf; use std::str::FromStr; +use std::time::SystemTime; +use std::time::UNIX_EPOCH; use tendermint_rpc::Client as _; const BANNER: &str = r#" @@ -100,6 +106,8 @@ pub enum Command { RelayOpKeys(RelayOpKeysCmd), SetRecoveryAddress(SetRecoveryAddressCmd), SigningStatus(SigningStatusCmd), + RecoverDeposit(RecoverDepositCmd), + PayToFeePool(PayToFeePoolCmd), } impl Command { @@ -161,6 +169,8 @@ impl Command { RelayOpKeys(cmd) => cmd.run().await, SetRecoveryAddress(cmd) => cmd.run().await, SigningStatus(cmd) => cmd.run().await, + RecoverDeposit(cmd) => cmd.run().await, + PayToFeePool(cmd) => cmd.run().await, } }) } @@ -432,17 +442,19 @@ fn legacy_bin(config: &nomic::network::Config) -> Result> { #[cfg(feature = "legacy-bin")] { - if !bin_dir.exists() { - std::fs::create_dir_all(&bin_dir)?; - } + if !env!("NOMIC_LEGACY_BUILD_VERSION").is_empty() { + if !bin_dir.exists() { + std::fs::create_dir_all(&bin_dir)?; + } - let bin_name = env!("NOMIC_LEGACY_BUILD_VERSION").trim().replace(' ', "-"); - let bin_path = bin_dir.join(bin_name); - let bin_bytes = include_bytes!(env!("NOMIC_LEGACY_BUILD_PATH")); - if !bin_path.exists() { - log::debug!("Writing legacy binary to {}...", bin_path.display()); - std::fs::write(&bin_path, bin_bytes).unwrap(); - std::fs::set_permissions(bin_path, Permissions::from_mode(0o777)).unwrap(); + let bin_name = env!("NOMIC_LEGACY_BUILD_VERSION").trim().replace(' ', "-"); + let bin_path = bin_dir.join(bin_name); + let bin_bytes = include_bytes!(env!("NOMIC_LEGACY_BUILD_PATH")); + if !bin_path.exists() { + log::debug!("Writing legacy binary to {}...", bin_path.display()); + std::fs::write(&bin_path, bin_bytes).unwrap(); + std::fs::set_permissions(bin_path, Permissions::from_mode(0o777)).unwrap(); + } } } @@ -1199,12 +1211,12 @@ impl RelayerCmd { #[derive(Parser, Debug)] pub struct SignerCmd { - // TODO: should be a flag - reset_limits_at_index: Option, - #[clap(flatten)] config: nomic::network::Config, + #[clap(long)] + reset_limits_at_index: Option, + /// Limits the fraction of the total reserve that may be withdrawn within /// the trailing 24-hour period #[clap(long, default_value_t = 0.1)] @@ -1217,6 +1229,14 @@ pub struct SignerCmd { #[clap(long, default_value_t = 0.1)] max_sigset_change_rate: f64, + /// The minimum number of Bitcoin blocks that must be mined before the signer will contribute its + /// signature to the current signing checkpoint. This setting can be used to change the rate at which the + /// network produces checkpoints (higher values cause less frequent checkpoints). + /// + /// Signatures will always be contributed to previously completed checkpoints. + #[clap(long, default_value_t = 6)] + min_blocks_per_checkpoint: u64, + #[clap(long)] prometheus_addr: Option, @@ -1239,6 +1259,7 @@ impl SignerCmd { self.xpriv_paths.clone(), self.max_withdrawal_rate, self.max_sigset_change_rate, + self.min_blocks_per_checkpoint, self.reset_limits_at_index, // TODO: check for custom RPC port, allow config, etc || nomic::app_client("http://localhost:26657").with_wallet(wallet()), @@ -1376,7 +1397,6 @@ const ONE_DAY_NS: u64 = 86400 * 1_000_000_000; impl InterchainDepositCmd { async fn run(&self) -> Result<()> { use orga::encoding::Adapter; - use std::time::SystemTime; let now_ns = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) @@ -1407,8 +1427,6 @@ pub struct WithdrawCmd { impl WithdrawCmd { async fn run(&self) -> Result<()> { - use nomic::bitcoin::adapter::Adapter; - let script = self.dest.script_pubkey(); self.config @@ -1891,6 +1909,232 @@ impl SigningStatusCmd { } } +#[derive(Parser, Debug)] +pub struct RecoverDepositCmd { + #[clap(short = 'p', long, default_value_t = 8332)] + rpc_port: u16, + #[clap(short = 'u', long)] + rpc_user: Option, + #[clap(short = 'P', long)] + rpc_pass: Option, + + #[clap(long)] + channel: Option, + #[clap(long)] + remote_addr: Option, + + #[clap(long)] + nomic_addr: Address, + #[clap(long)] + deposit_addr: bitcoin::Address, + #[clap(long)] + block_hash: bitcoin::BlockHash, + #[clap(long)] + txid: bitcoin::Txid, + #[clap(long)] + vout: u32, + + #[clap(long)] + reserve_script_path: PathBuf, + + #[clap(flatten)] + config: nomic::network::Config, +} + +impl RecoverDepositCmd { + async fn btc_client(&self) -> Result { + let rpc_url = format!("http://localhost:{}", self.rpc_port); + let auth = match (self.rpc_user.clone(), self.rpc_pass.clone()) { + (Some(user), Some(pass)) => Auth::UserPass(user, pass), + _ => Auth::None, + }; + + let btc_client = BtcClient::new(rpc_url, auth) + .await + .map_err(|e| orga::Error::App(e.to_string()))?; + + Ok(btc_client) + } + + async fn relay_deposit(&self, dest: Dest, sigset_index: u32) -> Result<()> { + let nomic_client = self.config.client(); + let btc_client = self.btc_client().await?; + + let block_height = btc_client.get_block_info(&self.block_hash).await?.height as u32; + + let tx = btc_client + .get_raw_transaction(&self.txid, Some(&self.block_hash)) + .await?; + + let proof_bytes = btc_client + .get_tx_out_proof(&[tx.txid()], Some(&self.block_hash)) + .await?; + let proof = ::bitcoin::MerkleBlock::consensus_decode(&mut proof_bytes.as_slice())?.txn; + { + let mut tx_bytes = vec![]; + tx.consensus_encode(&mut tx_bytes)?; + let tx = ::bitcoin::Transaction::consensus_decode(&mut tx_bytes.as_slice())?; + let tx = Adapter::new(tx); + let proof = Adapter::new(proof); + + let dest2 = dest.clone(); + nomic_client + .call( + move |app| { + build_call!(app.relay_deposit( + tx, + block_height, + proof, + self.vout, + sigset_index, + dest2 + )) + }, + |app| build_call!(app.app_noop()), + ) + .await?; + } + + log::info!( + "Relayed deposit: {} sats, {:?}", + tx.output[self.vout as usize].value, + dest + ); + + Ok(()) + } + + async fn run(&self) -> Result<()> { + if self.channel.is_some() != self.remote_addr.is_some() { + return Err(nomic::error::Error::Orga(orga::Error::App( + "Both --channel and --remote-prefix must be specified".to_string(), + ))); + } + + let threshold = self + .config + .client() + .query(|app| Ok(app.bitcoin.checkpoints.config.sigset_threshold)) + .await?; + + // TODO: support passing in script csv by path + let sigsets: Vec<(u32, SignatorySet)> = std::fs::read_to_string(&self.reserve_script_path)? + .lines() + .map(|line| { + let mut split = line.split(','); + (split.next().unwrap(), split.next().unwrap()) + }) + .map(|(i, script_hex)| { + let i = i.parse::().unwrap(); + let script = bitcoin::Script::from(hex::decode(script_hex).unwrap()); + let (sigset, _) = SignatorySet::from_script(&script, threshold).unwrap(); + (i, sigset) + }) + .collect(); + + dbg!(sigsets.len()); + + if let (Some(channel), Some(remote_addr)) = + (self.channel.as_ref(), self.remote_addr.as_ref()) + { + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs(); + let start = (now + 60 * 60 * 24 * 7 - (now % (60 * 60))) * 1_000_000_000; + let mut dest = Dest::Ibc(IbcDest { + source_port: "transfer".to_string().try_into().unwrap(), + source_channel: channel.bytes().collect::>().try_into().unwrap(), + receiver: orga::encoding::Adapter(remote_addr.to_string().into()), + sender: orga::encoding::Adapter(self.nomic_addr.to_string().into()), + timeout_timestamp: start, + memo: "".to_string().try_into().unwrap(), + }); + + dbg!(&dest); + + let mut i = 0; + let mut dest_bytes = dest.commitment_bytes().unwrap(); + loop { + for (sigset_index, sigset) in sigsets.iter() { + if i % 10_000 == 0 { + if let Dest::Ibc(dest) = &dest { + println!("{} {}", i, dest.timeout_timestamp); + } else { + unreachable!() + } + } + + let script = sigset.output_script(&dest_bytes, threshold).unwrap(); + let addr = + bitcoin::Address::from_script(&script, nomic::bitcoin::NETWORK).unwrap(); + if addr.to_string().to_lowercase() + == self.deposit_addr.to_string().to_lowercase() + { + if let Dest::Ibc(ibc_dest) = &dest { + println!( + "Found at sigset index {}, timeout_timestamp {}", + sigset_index, ibc_dest.timeout_timestamp, + ); + } else { + unreachable!() + } + + return self.relay_deposit(dest, *sigset_index).await; + } + + i += 1; + } + + if let Dest::Ibc(ibc_dest) = &mut dest { + ibc_dest.timeout_timestamp -= 60 * 60 * 1_000_000_000; + dest_bytes = dest.commitment_bytes().unwrap(); + } else { + unreachable!() + } + } + } + + let dest = Dest::Address(self.nomic_addr); + let dest_bytes = dest.commitment_bytes().unwrap(); + + for (sigset_index, sigset) in sigsets.iter() { + let script = sigset.output_script(&dest_bytes, threshold).unwrap(); + let addr = bitcoin::Address::from_script(&script, nomic::bitcoin::NETWORK).unwrap(); + if addr.to_string().to_lowercase() == self.deposit_addr.to_string().to_lowercase() { + println!("Found at sigset index {}", sigset_index,); + return self.relay_deposit(dest, *sigset_index).await; + } + } + + Err(nomic::error::Error::Orga(orga::Error::App( + "Deposit address not found in any sigset".to_string(), + ))) + } +} + +#[derive(Parser, Debug)] +pub struct PayToFeePoolCmd { + amount: u64, + + #[clap(flatten)] + config: nomic::network::Config, +} + +impl PayToFeePoolCmd { + async fn run(&self) -> Result<()> { + Ok(self + .config + .client() + .with_wallet(wallet()) + .call( + |app| build_call!(app.bitcoin.transfer_to_fee_pool(self.amount.into())), + |app| build_call!(app.app_noop()), + ) + .await?) + } +} + pub fn main() { if std::env::var("NOMIC_LOG_SIMPLE").is_ok() { pretty_env_logger::formatted_builder() diff --git a/src/bitcoin/checkpoint.rs b/src/bitcoin/checkpoint.rs index d7ee6510..4eeb6056 100644 --- a/src/bitcoin/checkpoint.rs +++ b/src/bitcoin/checkpoint.rs @@ -1076,6 +1076,8 @@ impl Config { min_checkpoint_interval: 15, emergency_disbursal_lock_time_interval: 60, emergency_disbursal_max_tx_size: 11, + user_fee_factor: 20_000, + max_age: 60 * 60 * 24 * 7 * 3, ..Config::bitcoin() } } @@ -1090,7 +1092,7 @@ impl Config { target_checkpoint_inclusion: 2, min_fee_rate: 2, // relay threshold is 1 sat/vbyte max_fee_rate: 200, - user_fee_factor: 20000, // 2x + user_fee_factor: 21000, // 2.1x sigset_threshold: SIGSET_THRESHOLD, emergency_disbursal_min_tx_amt: 1000, #[cfg(feature = "testnet")] @@ -1985,7 +1987,7 @@ impl CheckpointQueue { fee_pool: &mut i64, parent_config: &super::Config, ) -> Result { - if !self.should_push(sig_keys, ×tamping_commitment)? { + if !self.should_push(sig_keys, ×tamping_commitment, btc_height)? { return Ok(false); } @@ -2098,6 +2100,7 @@ impl CheckpointQueue { &mut self, sig_keys: &Map, timestamping_commitment: &[u8], + btc_height: u32, ) -> Result { // Do not push if there is a checkpoint in the `Signing` state. There // should only ever be at most one checkpoint in this state. @@ -2118,6 +2121,17 @@ impl CheckpointQueue { return Ok(false); } + // Do not push if Bitcoin headers are being backfilled (e.g. the + // current latest height is less than the height at which the last + // confirmed checkpoint was signed). + if let Ok(last_completed_index) = self.last_completed_index() { + let last_completed = self.get(last_completed_index)?; + let last_signed_height = last_completed.signed_at_btc_height.unwrap_or(0); + if btc_height < last_signed_height { + return Ok(false); + } + } + // Don't push if there are no pending deposits, withdrawals, or // transfers, or if not enough has been collected to pay for the // miner fee, unless the maximum checkpoint interval has elapsed diff --git a/src/bitcoin/header_queue.rs b/src/bitcoin/header_queue.rs index 43bef15f..69dea250 100644 --- a/src/bitcoin/header_queue.rs +++ b/src/bitcoin/header_queue.rs @@ -13,7 +13,7 @@ use orga::prelude::*; use orga::Error as OrgaError; use orga::Result as OrgaResult; -const MAX_LENGTH: u64 = 4032; +const MAX_LENGTH: u64 = 24_192; // ~6 months const MAX_RELAY: u64 = 250; const MAX_TIME_INCREASE: u32 = 2 * 60 * 60; const RETARGET_INTERVAL: u32 = 2016; diff --git a/src/bitcoin/mod.rs b/src/bitcoin/mod.rs index e7672ec0..45b005fe 100644 --- a/src/bitcoin/mod.rs +++ b/src/bitcoin/mod.rs @@ -216,7 +216,7 @@ impl Config { max_withdrawal_script_length: 64, transfer_fee: 1_000_000, #[cfg(feature = "testnet")] - min_confirmations: 0, + min_confirmations: 1, #[cfg(not(feature = "testnet"))] min_confirmations: 5, units_per_sat: 1_000_000, @@ -227,7 +227,7 @@ impl Config { #[cfg(not(feature = "testnet"))] capacity_limit: 21 * 100_000_000, // 21 BTC max_deposit_age: 60 * 60 * 24 * 5, - fee_pool_target_balance: 10_000_000, // 0.1 BTC + fee_pool_target_balance: 100_000_000, // 1 BTC fee_pool_reward_split: (1, 10), } } @@ -236,6 +236,8 @@ impl Config { Self { min_withdrawal_checkpoints: 1, max_offline_checkpoints: 1, + min_confirmations: 0, + fee_pool_target_balance: 10_000_000, ..Self::bitcoin() } } @@ -519,7 +521,7 @@ impl Bitcoin { #[cfg(feature = "full")] pub fn should_push_checkpoint(&mut self) -> Result { self.checkpoints - .should_push(self.signatory_keys.map(), &[0; 32]) + .should_push(self.signatory_keys.map(), &[0; 32], self.headers.height()?) // TODO: we shouldn't need this slice, commitment should be fixed-length } @@ -1071,7 +1073,7 @@ impl Bitcoin { coin.burn(); self.fee_pool += amount as i64; - self.checkpoints.building_mut()?.fees_collected += amount; + self.checkpoints.building_mut()?.fees_collected += amount / self.config.units_per_sat; Ok(()) } @@ -1107,6 +1109,26 @@ impl Bitcoin { self.give_miner_fee(taken_coins) } + + #[call] + pub fn transfer_to_fee_pool(&mut self, amount: Amount) -> Result<()> { + if amount < 100 * self.config.units_per_sat { + return Err(Error::Orga(OrgaError::App( + "Minimum transfer to fee pool is 100 sat".into(), + ))); + } + + exempt_from_fee()?; + + let signer = self + .context::() + .ok_or_else(|| Error::Orga(OrgaError::App("No Signer context available".into())))? + .signer + .ok_or_else(|| Error::Orga(OrgaError::App("Call must be signed".into())))?; + + let coins = self.accounts.withdraw(signer, amount)?; + self.give_miner_fee(coins) + } } /// The current rates of change of the reserve output and signatory set, in @@ -1350,6 +1372,9 @@ mod tests { btc.add_withdrawal(Adapter::new(Script::new()), 459_459_927_000_000.into()) .unwrap(); + + let mut building_mut = btc.checkpoints.building_mut().unwrap(); + building_mut.fees_collected = 100_000_000; }; let sign_batch = |btc_height| { diff --git a/src/bitcoin/relayer.rs b/src/bitcoin/relayer.rs index b3db274b..ec294654 100644 --- a/src/bitcoin/relayer.rs +++ b/src/bitcoin/relayer.rs @@ -246,8 +246,11 @@ impl Relayer { let sigset = app_client(app_client_addr) .query(|app: crate::app::InnerApp| { let building = app.bitcoin.checkpoints.building()?; - let est_miner_fee = building.fee_rate - * app.bitcoin.checkpoints.active_sigset()?.est_witness_vsize(); + let est_miner_fee = + (app.bitcoin.checkpoints.active_sigset()?.est_witness_vsize() + 40) + * building.fee_rate + * app.bitcoin.checkpoints.config.user_fee_factor + / 10_000; let deposits_enabled = building.deposits_enabled; let sigset = RawSignatorySet::new( app.bitcoin.checkpoints.active_sigset()?, diff --git a/src/bitcoin/signatory.rs b/src/bitcoin/signatory.rs index dce9f8ed..3a342457 100644 --- a/src/bitcoin/signatory.rs +++ b/src/bitcoin/signatory.rs @@ -31,7 +31,6 @@ use orga::plugins::Time; use orga::plugins::Validators; use orga::Error as OrgaError; -use super::threshold_sig::VersionedPubkey; use super::ConsensusKey; use super::Xpub; @@ -55,7 +54,7 @@ pub const MAX_SIGNATORIES: u64 = 20; #[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)] pub struct Signatory { pub voting_power: u64, - pub pubkey: VersionedPubkey, + pub pubkey: Pubkey, } /// Deterministically derive the public key for a signatory in a signatory set, @@ -236,7 +235,7 @@ impl SignatorySet { take_op(ins, OP_ENDIF)?; Ok::<_, Error>(Signatory { - pubkey: pubkey.into(), + pubkey, voting_power: voting_power as u64, }) } @@ -251,7 +250,7 @@ impl SignatorySet { take_op(ins, OP_ENDIF)?; Ok::<_, Error>(Signatory { - pubkey: pubkey.into(), + pubkey, voting_power: voting_power as u64, }) } diff --git a/src/bitcoin/signer.rs b/src/bitcoin/signer.rs index ac11077d..05eb9d7a 100644 --- a/src/bitcoin/signer.rs +++ b/src/bitcoin/signer.rs @@ -72,6 +72,7 @@ pub struct Signer { xprivs: Vec, max_withdrawal_rate: f64, max_sigset_change_rate: f64, + min_blocks_per_checkpoint: u64, reset_index: Option, app_client: F, exporter_addr: Option, @@ -82,6 +83,7 @@ impl Signer where F: Fn() -> AppClient, { + #![allow(clippy::too_many_arguments)] /// Create a new signer, loading the extended private key from the given /// path (`key_path`) if it exists. If the key does not exist, one will be /// generated and written to the path, then submitted to the chain, becoming @@ -98,6 +100,8 @@ where /// - `max_sigset_change_rate`: The maximum rate at which the signatory set /// can change in a 24-hour period, temporarily halting signing if the limit /// is reached. + /// - `min_checkpoint_seconds`: The minimum amount of time that must pass + /// before this signer will contribute its signature. /// - `reset_index`: A checkpoint index at which the rate limits should be /// reset, used to manually override the limits if the signer has checked on /// the pending withdrawals and decided they are legitimate. @@ -110,6 +114,7 @@ where xpriv_paths: Vec

, max_withdrawal_rate: f64, max_sigset_change_rate: f64, + min_checkpoint_seconds: u64, reset_index: Option, app_client: F, exporter_addr: Option, @@ -134,6 +139,7 @@ where xprivs, max_withdrawal_rate, max_sigset_change_rate, + min_checkpoint_seconds, reset_index, app_client, exporter_addr, @@ -152,6 +158,8 @@ where /// - `max_sigset_change_rate`: The maximum rate at which the signatory set /// can change in a 24-hour period, temporarily halting signing if the limit /// is reached. + /// - `min_blocks_per_checkpoint`: The minimum number of new Bitcoin blocks + /// that must be mined before this signer will contribute its signature. /// - `reset_index`: A checkpoint index at which the rate limits should be /// reset, used to manually override the limits if the signer has checked on /// the pending withdrawals and decided they are legitimate. @@ -162,6 +170,7 @@ where xprivs: Vec, max_withdrawal_rate: f64, max_sigset_change_rate: f64, + min_blocks_per_checkpoint: u64, reset_index: Option, app_client: F, exporter_addr: Option, @@ -174,6 +183,7 @@ where xprivs, max_withdrawal_rate, max_sigset_change_rate, + min_blocks_per_checkpoint, reset_index, app_client, exporter_addr, @@ -322,7 +332,7 @@ where let (status, timestamp) = self .client() - .query(|app| { + .query(|app: InnerApp| { let cp = app.bitcoin.checkpoints.get(index)?; Ok((cp.status, cp.create_time())) }) @@ -344,7 +354,38 @@ where return Ok(matches!(status, CheckpointStatus::Complete)); } - self.check_change_rates().await?; + if matches!(status, CheckpointStatus::Signing) { + self.check_change_rates().await?; + let current_btc_height = self + .client() + .query(|app: InnerApp| Ok(app.bitcoin.headers.height()?)) + .await? as u64; + let last_signed_btc_height: Option = self + .client() + .query(|app: InnerApp| { + Ok(app + .bitcoin + .checkpoints + .get(index.saturating_sub(1))? + .signed_at_btc_height) + }) + .await? + .map(|v| v as u64); + + if let Some(last_signed_btc_height) = last_signed_btc_height { + if current_btc_height < last_signed_btc_height + self.min_blocks_per_checkpoint { + let delta = last_signed_btc_height + self.min_blocks_per_checkpoint + - current_btc_height; + info!( + "Checkpoint is too recent, {} more Bitcoin block{} required", + delta, + if delta == 1 { "" } else { "s" }, + ); + return Ok(false); + } + } + } + info!("Signing checkpoint ({} inputs)...", to_sign.len()); let sigs = sign(&secp, xpriv, &to_sign)?; @@ -487,6 +528,7 @@ mod test { Vec::default(), 1.0, 1.0, + 0, None, || app_client("http://localhost:26657"), None, @@ -512,6 +554,7 @@ mod test { vec![temp_dir.path().join("xpriv-primary")], 1.0, 1.0, + 0, None, || app_client("http://localhost:26657"), None, @@ -531,6 +574,7 @@ mod test { vec![temp_dir.path().join("xpriv-primary")], 1.0, 1.0, + 0, None, || app_client("http://localhost:26657"), None, @@ -557,6 +601,7 @@ mod test { xpriv_paths, 1.0, 1.0, + 0, None, || app_client("http://localhost:26657"), None, diff --git a/src/bitcoin/testnet_checkpoint.json b/src/bitcoin/testnet_checkpoint.json index c3b5b406..67b13980 100644 --- a/src/bitcoin/testnet_checkpoint.json +++ b/src/bitcoin/testnet_checkpoint.json @@ -1,11 +1,11 @@ [ - 2437344, + 2574432, { - "version": 543162368, - "prev_blockhash": "00000000000000054a4bd09b4cf258f0bdd86feb97fdc38d66753f3e04a70524", - "merkle_root": "b272ff64ae20a2664408d47dc54c9dfdf953b44935ffd9dc1bd30f6b24991489", - "time": 1686553059, - "bits": 421617023, - "nonce": 250238008 + "version": 536870912, + "prev_blockhash": "000000000000001f6d8dc4976552a596eff2eb0df15b0d9ee61a55091a2050c2", + "merkle_root": "03a2f5712c4c44daafa6475007de611b91be9738fc005788b7072153d651f36f", + "time": 1705736135, + "bits": 422015362, + "nonce": 3433041756 } ] diff --git a/src/bitcoin/threshold_sig.rs b/src/bitcoin/threshold_sig.rs index 1c1d0740..1e92a2e7 100644 --- a/src/bitcoin/threshold_sig.rs +++ b/src/bitcoin/threshold_sig.rs @@ -10,10 +10,7 @@ use orga::collections::Map; use orga::encoding::{Decode, Encode}; use orga::macros::Describe; use orga::migrate::{Migrate, MigrateFrom}; -use orga::prelude::FieldCall; -use orga::query::FieldQuery; use orga::state::State; -use orga::store::Store; use orga::{orga, Error, Result}; use serde::Serialize; @@ -29,21 +26,13 @@ pub struct Signature( ); /// A compressed secp256k1 public key. -#[orga(skip(Default, Migrate), version = 1)] +#[orga(skip(Default), version = 1)] #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Copy)] pub struct Pubkey { #[serde(serialize_with = "<[_]>::serialize")] bytes: [u8; PUBLIC_KEY_SIZE], } -impl Migrate for Pubkey { - fn migrate(_src: Store, _dest: Store, bytes: &mut &[u8]) -> Result { - let mut buf = [0; PUBLIC_KEY_SIZE]; - bytes.read_exact(buf.as_mut())?; - Ok(Self { bytes: buf }) - } -} - impl Default for Pubkey { fn default() -> Self { Pubkey { @@ -92,9 +81,7 @@ impl Pubkey { impl MigrateFrom for PubkeyV1 { fn migrate_from(value: PubkeyV0) -> Result { - let mut bytes = [0; PUBLIC_KEY_SIZE]; - bytes[1..].copy_from_slice(value.bytes.as_slice()); - Ok(PubkeyV1 { bytes }) + Ok(PubkeyV1 { bytes: value.bytes }) } } @@ -106,70 +93,6 @@ impl From for Pubkey { } } -/// See `Pubkey` - this type is separate to always include a version byte in its -/// `Encode` and `Decode` implementations, unlike `Pubkey` which only includes -/// it in its `State` implementation. This distinction will be removed once all -/// networks have migrated to include a version byte in their `Pubkey` type. -#[derive( - Encode, - Decode, - State, - FieldQuery, - FieldCall, - Clone, - Debug, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Serialize, - Describe, - Migrate, -)] -pub struct VersionedPubkey { - #[serde(serialize_with = "<[_]>::serialize")] - bytes: [u8; PUBLIC_KEY_SIZE], -} - -impl Default for VersionedPubkey { - fn default() -> Self { - VersionedPubkey { - bytes: [0; PUBLIC_KEY_SIZE], - } - } -} - -impl VersionedPubkey { - pub fn as_slice(&self) -> &[u8] { - &self.bytes - } -} - -impl From for VersionedPubkey { - fn from(pubkey: Pubkey) -> Self { - VersionedPubkey { - bytes: pubkey.bytes, - } - } -} - -impl From for Pubkey { - fn from(pubkey: VersionedPubkey) -> Self { - Pubkey { - bytes: pubkey.bytes, - } - } -} - -impl From for VersionedPubkey { - fn from(pubkey: PublicKey) -> Self { - VersionedPubkey { - bytes: pubkey.serialize(), - } - } -} - /// `ThresholdSig` is a state type used to coordinate the signing of a message /// by a set of signers. /// @@ -246,7 +169,7 @@ impl ThresholdSig { for signatory in signatories.iter() { ts.sigs.insert( - signatory.pubkey.into(), + signatory.pubkey, Share { power: signatory.voting_power, sig: None, @@ -417,7 +340,6 @@ impl ThresholdSig { } use std::fmt::Debug; -use std::io::Read; impl Debug for ThresholdSig { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("ThresholdSig") diff --git a/src/cosmos.rs b/src/cosmos.rs index 5d9c9c9e..6de66996 100644 --- a/src/cosmos.rs +++ b/src/cosmos.rs @@ -1,7 +1,7 @@ use crate::{ bitcoin::{ signatory::{derive_pubkey, Signatory, SignatorySet}, - threshold_sig::{Pubkey, VersionedPubkey}, + threshold_sig::Pubkey, Nbtc, Xpub, }, error::Result, @@ -198,8 +198,7 @@ impl Cosmos { .map_err(|_| OrgaError::App("Invalid public key".to_string()))? .key .as_slice(), - )? - .into(); + )?; let mut chain = self.chains.entry(client_id)?.or_default()?; if let Some(existing_key) = chain.op_keys_by_cons.get(cons_key.clone())? { @@ -334,7 +333,7 @@ impl Proof { #[orga] pub struct Chain { - pub op_keys_by_cons: Map, VersionedPubkey>, + pub op_keys_by_cons: Map, Pubkey>, } #[orga] diff --git a/src/utils.rs b/src/utils.rs index 8b7f3ddd..1ad7fd7a 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -239,6 +239,7 @@ where Vec::default(), 0.1, 1.0, + 0, None, client, None, @@ -382,15 +383,18 @@ pub async fn poll_for_updated_balance(address: Address, expected_balance: u64) - return initial_balance.into(); } + let mut count = 0; loop { let balance = app_client(DEFAULT_RPC) .query(|app| app.bitcoin.accounts.balance(address)) .await .unwrap(); - if balance != initial_balance { + if count >= 60 || balance != initial_balance { break balance.into(); } + tokio::time::sleep(Duration::from_secs(1)).await; + count += 1; } } diff --git a/testnet_addresses.csv b/testnet_addresses.csv new file mode 100644 index 00000000..21d4d36c --- /dev/null +++ b/testnet_addresses.csv @@ -0,0 +1,1000 @@ +nomic1p72gksuyyc304764w4l2f0em7yu03y3sh9d38j +nomic1nk636qct5tpsyr06s2nmrpvgx79ur0jesdvntp +nomic15r6m2ekr886gd9rkx6e2sm78ek35h02akcvuzv +nomic10f9hd22esf0c4cn9xexpdzuhe99hagkkqnmc3q +nomic1as5u7u59uylu8uz9ynqfene5qyz8fdsr9hnwhm +nomic1pqdqlwfj8sgrpfj9ryr4rs9tzasnkn6ncz54uk +nomic1zd5xv7fq0f64u9cv4j0xte7mrepex0mczw9g6q +nomic1jzcemjl3qw4deu6duanrracete3zp960acm2wc +nomic19w0u8880sz9ja3zewlrkrazvcf66juz4wxzagu +nomic1yylghnyrcy2xe35rs9m6jpsh5vcrnwm2nlgq66 +nomic1ax4e7jl8hwnnnsltjtqu04mmp7cpulwz9xaeev +nomic1psdm7lrc29hlzj5axv5tlrt8huj8lmghuaqnv0 +nomic1lt4styturu2q5qhgrpllq97cwhjh943kggdv5h +nomic1s7etsu4shngp35zq5nef5629hpqulclsd529hn +nomic1ranmykue4y0sxh8xfj6t7vd6nlx5vky3zyf3rj +nomic1huwakhh0cntj7f28ddegruk3dg6cj65er8d8m6 +nomic1qph80j6g0vk8g8w2d0xmuum0tu565hmheqzpz4 +nomic1kfhwgrrrznd4fgwaz2l3rqnh3r9fygzeum89fw +nomic1gnz30c42clfyh975y8ummegc7sdcnp8c95kggp +nomic1xwk8llz7p2apv0xc9calf0cplx06qddy7xvtfq +nomic1r60rlckuz23r8yfuvr4aqxtmf0nasp43mm22z4 +nomic1pceq7npe9ylnyrt02nzskt54szgxzwtj64flg8 +nomic13ye4czwvptppx7makqrt578y4tcxg3l2xar3fr +nomic106e0e5mxkzw8unqypl6azdx08xa2qhhg2lfe4m +nomic16j9u5ww0h776aqsh003dkas4mu02f3vxe3ynwj +nomic1ap6uxvxqer25y5ev0ce0syqlnmyy45yu6ed9cc +nomic10qyjx22fdjtcxdx8upzzd3n7d9cs3kwlfpp0m6 +nomic1zm79pz6s5tvf4dsxv2vg45hnee8hynsv55m9xs +nomic1v05aas8hndgs8r86ekj6hwfz6xesxeumh6s7uq +nomic1ex0jq0lju0rm0umd9s4y50frsnjyaxx37mmgd2 +nomic1t66d4thfctrksdkdve4y7r3h06e5llwgrde2km +nomic1rertplfaqqjdyu5m0h8tdtu0xuudf8ey3nqttg +nomic19wqx447yaye76yc6rc34ln888xcc0yg9vvfyhj +nomic1mxa8y6sjlvukkt07uv34vjs7hrmw355pdt988u +nomic1t7xnf609dxv2vfzw0yjsl3fwhprs0tczhmlwfk +nomic17czz0ftq5w52hzcgjmwzx82u0a4d5fgnxgj6t9 +nomic16zlzmce8klra8je5qu24q8pw7tgplnt6xcwh97 +nomic1gxr53f9jx5cxn3dmkzr2eq93g05yey30tclyu8 +nomic13l7kryzx3jrqxsa6w876y0tuxmwgknjejjz44h +nomic1gqh8znymursj37jw456q80f8hnnuqhrw86utt3 +nomic1wjcdyfyzvcs4r9zjg2l8t5zzf46ukudt0f2zdf +nomic1h9kk80r23yzfjdspmlpczga3qgm5l6qsdy8z5f +nomic1q3k0h4axh5mnh47sp7keqea38ygyt77hsr6m9d +nomic1dfrashdc8t6rtzrwryacy8gutmv7guqr6j6wky +nomic1v4x2n8lxjrj9ej0hhl8jwza2kzgpyswtzrzz3t +nomic1dcfc7usggxup7lz7ysk976c334mnzjq9g6uv0z +nomic1zglcvru504scyum4vscgz3chw906qxm8mcmhgg +nomic17cc8c5ug5t8qsz2cfmxtfpkj9lackyquyse0ww +nomic1wsj79nhlfvcw75hfejh7nt9sy66qyvp3xa9qz9 +nomic139rww6jtavcywuthytmnh0mxsu5dd0uu0e7ru3 +nomic1tuzdqwynm2xtpm2jjpr80cjrf46hcp2nd602j5 +nomic1e8u7rzaecgsywzqc0wsmae6u2d0jylaqzzfym6 +nomic16yuewmcpm84wpzu27g77f0elwzfk4ndca5nxr0 +nomic1hf67k5gzs99jg5s2hluys373cqs79g90a7ufkq +nomic1ffkpmjxz7wqy5qdg7qafzwgpdw8qn3wg5fuhj7 +nomic1kqfjv53g7ll9u6ngvsu5l5nfv9ht24m42lcv55 +nomic1zptg33u2gql3e6tcnpwnxkt4n32cur8pq5t73u +nomic158gnjm0eqld7qpe03jzxk9atnmw0yegpw6dsl9 +nomic10qf7p3xvjpphv3eyvf92mg2lgtgz88szn4dqez +nomic1lv3wuy5dtyrsez7suqnh9hqesyphgxpwmxyx6n +nomic1alk8j20ffcpzqq3yywngg8gdcnv24caplfnkw2 +nomic1fd2hlkk8mz4j3stjd0vv894evxhmq0fkkzv44s +nomic17v8w550v4rxgftsey4aqtfjjla0xf7ccc3wz7w +nomic17vxf0y0x0gkhan33yhpeuxhyzd5069vn50h6rl +nomic1sss9dkqpq3lfd3fk34d400pu8r9083fdqgq3ps +nomic1u6lezvtey6fupwnduhd7v5q6w4r7l208gdkzx6 +nomic18f22qngc7s0xmzd2mal8gctafznqx6xsvnecgh +nomic14dp6r96t5pwj2zq3j6j44e99a34xdj3w6h2479 +nomic18tgy7tmpng6qspxgwl4alvc0myq6ln7unukk23 +nomic18rh48fmz5e6vax6y0vpt4gwhu64vl9cnzfccw0 +nomic12z5p547fu3k6n3jcwv0u8znrqrnjph0kg4j8s5 +nomic1akvpc777swtk09asunakfdyhf5fnh4ffejm340 +nomic1u2r5lns2p60xhjhzshfk8rre0wjdf8acf54qh6 +nomic17uq9n4lrmevwljafyhvz20qae6t42pvwt5qtgx +nomic1w9pkvf5wwwmdshv35ftej0ssx7nzgqc6s4qpja +nomic1ljk3jy8xyu6e95le00lna96fad4aaapcksahgm +nomic1aww500ndp0hlkh2hpn6fnhnwxtxpyqtr7p9hny +nomic1y59ng7zhlylwcwmjs8dh2zqrst0j4f6gj42vsx +nomic1lpuamle9upg8xztkdq2ctru2wvuukr9ralut2s +nomic1rsxk522vywtgpv3uasl0f5fmg4zh83xa98ecjn +nomic1aympg8znel6p9zlq7hk8d9tl70pgs3vnn9nvn4 +nomic1vlex8y05d4c0zl2g5fzwj2wggvwhnurrp8wjc6 +nomic1cf72ak6autu0wxc23zfl45q04dpvp98hxq37k3 +nomic1273zsxhxd5dlgcr2zjf5x25275hjcp3uru7tha +nomic1dja4k7hfuwxjg8uwen3euvn3z5nsv2ncpdpc9q +nomic1egemy4l9ykydgvk3zx76wpd2xw8j9tvpkkf9te +nomic1yxye2anen8t30vlhpj36hfdzr7wk4ml0wl6u5j +nomic13ugmpjgtpzqfmgz0835teyjycvhv266r7dhcyx +nomic1chywz2q3e6mqfkw7p96utnmzl55xxnlx750d02 +nomic15kuyqke44arum9afduxagd0lpd6gx6dew8hp4l +nomic1t0pdyze7vfu42krk4dl8zxqg89hphwewrhrczy +nomic104g8u70dj0hdt7dvejhum5rhk55kgmc5kg7wqd +nomic1seq2v0pvfdkscfr3par50qnt9cu4ytw3q8e0lw +nomic13pj6tvt8su7tlatwa8cpw0z3pqe9fkxvwt75s3 +nomic1s55epqkzdfq93c24y4d4m2amdjcydkde6thqhd +nomic15hxq8y8w6hwpjxxzqk63uh97258jv2xdlwsfww +nomic16a24tysqtre4234lafk75ptawyr4yqwp9jzdqv +nomic1sphpyfa4agzc5gs098g04774278g0d0mdudw6u +nomic1nyw5g9yjtcrcsvk4j5tzrk5fh9yjhshlpt3x05 +nomic1yvwjyl887wu9k34ggk6tjmw7sv42sx2zxalaqk +nomic1chlmc3um9qrs66g3afvcpwtexfnhdf3aumyfdg +nomic1ez498svz3wykfvgs8uhlzxe00qtvfphezgfwn5 +nomic15wnjx4z4knp0h9cfru3cp0txpy5n9g5pxxt4vn +nomic15veazlm428h9cu0z8tpnvcegrzfj6dlmfn3r9v +nomic1y4psr78r93s3x3hsv8f909xz74l9qae4csc6v2 +nomic13f98v89503kdc0y5eu0254cdpplralp2xm05kc +nomic19aqncq3fcz6dugt0h24vta77nt3lkje764f06k +nomic1xp3gq2e6cjpfqdefahq9da0l77z9lr0j5g8vvt +nomic1wl49fq3y5n57kj6aqjegx8fs3u2luyzc8yjfz2 +nomic1jp7h4k0rvna5hv2f6cxd90jjvjkscdv6smqmdj +nomic18ftcgpfmflcqpmy79vlqnenxhmz6na5u4fheze +nomic1dflr8zxf4c5rjrtuy8uhadyfra0n2h06hau2mz +nomic1t3h8l90f4mcq7qyeedlcutwpwg4mvvh3npvhk7 +nomic1t0x5t0r2d4cq9k2rjf9e2csm6442g3hpcqmnp7 +nomic1hjpgq3hjyhjd3zv2hfcjs4ey4c2m6kwy85pgqa +nomic1rrqheue98hvkjurrgnjzedes5znveqr6ryffdr +nomic1j40zu4ljp9fsw7267x2flltpzgy0qfwuc2d5p6 +nomic15s8jvd6hrd4hr6zr92xnaz3ph8zl96v9udtp3j +nomic1qgpjdqwm7qyes7dw4kxeh60v96n73gpef2ahxg +nomic1v96n0kpe5s4yztkltxfklue3950qsll30knju2 +nomic1v0jtl2vt9s2f9uqf7kne3pjgfkn9gtxhnx376m +nomic1v58ufupkp38cg4awxpgkfgn7k0elqxnuy2rsey +nomic1hcqjney83mcm50jvf70lk3h6yytkke0x0dgrr5 +nomic1e3y33s5zuckqzjeny0njzqqjy9j785txv940ql +nomic19eu98asqetctjvgfhkp2faydsjekecxyeuk2hh +nomic1k6ku8dyturcwz2tl8d5kpu658ny63xje8w0vvq +nomic1y9vq20zaeljcch80uh4kgaw8gczpw7wpq0u75z +nomic1mxpyg8u68k6a8wdu3hs5whcpw9q285pc53a6tf +nomic1p5fcfm2aypfnsxq0c95tjfq7x7s675fdwxduy9 +nomic1u80fuxv7q7wh00klkclz3r4mynmsa7f6tzm3q9 +nomic19fjj4hen45asuq7zah8s7usmd44nhcyvlvcw64 +nomic1ncus6prmh83yf5vwtxaf9qnaksckfk7ny770xq +nomic15yfteczvqvhcs574dwgxl4pfjuh884zqqegchj +nomic1h2p6ftjkz5q7cn6l2zw864gpx9gxrkq34328z3 +nomic1axw0250f5grefkp9rms36sxd9rz9s2hs8mw8de +nomic1yavf40mhfjgrc5d5gchxzl7tpr0ldvw5623l28 +nomic1qz9ml20945genaszrxvk7zxch6cn8jc2w8am0u +nomic19myh8xv33u4rseg6ck9vnceyca05c69q9gv9g3 +nomic1qm9q5lcutcvdah6qh5eefzapcnhas9vmkudpnw +nomic1x2xdz0ax490vshnfjlgkl75yw7v458tancsu6l +nomic1lvqvt0s85fjc37kl6dk64qrlzjn6ura0945gaw +nomic1ezty2jdsfx5u35myl8vrth8e9e5524agw4ns2s +nomic1j7zc45957urrx7lvd93jqkr40gff9gy6p86q8d +nomic1nxmm88uccpf6dg36kzqfmfkw3552gcd9sa76tw +nomic17dt3cm803ephj47l4z4ej36u5y0reny4uxa5w4 +nomic1exv9vd7mf2wme3stntvdnklx9kgph2ktq5667x +nomic1207hw09d5k6wefg2fu4828zcts8vmu0pxpcncu +nomic107tcy3hrjedrrnfenf365e3attf0gpgkntafjy +nomic1p9lujm5arq9zdzdzr4ffx5rj77urffu2was4t3 +nomic17uld3yhlryf7v8zzl0v6eekaf87zvnguqkj6rg +nomic10numeh299y20p5hrnmkn0wv4cm6n23zj5qwx0p +nomic17y2uu22dtayks39n5nggmyc6jzkcthc85c9s6n +nomic1ak0v68rxfdug9tdkalxks674gm2hrn0l70xytc +nomic1c5gurl2vqae3v5t25aswnh0x66xkp9940t4njc +nomic10g36sgpgg948aug2m4aumqt7vpyck59y79j4hx +nomic1ntjukg6eqks0wxckw6x5t0j890pewv59jyrd70 +nomic1k3zhx2vn7s24wnf2456frnc7wcrjnw7wlgasph +nomic1yk3nm9n8kd94rr5rsczuu86nuxp9qt2axkrjsg +nomic1k75lydjhc6w5fv658fe5rfakmgwfmf97ss3tzv +nomic1ylz207r6y9xyamez8v9hr2v9ypvxuykr5xvc4l +nomic1tfrw29k87a5srgrpv08k99mzr2mqcmd048yuqy +nomic1r000nhpy9fvtm3km404tngn8y8qyv4fpun300s +nomic1qpktdl30qqcr5n9wkgkh8py8a25hfzk3klrzjj +nomic1r4c2g5wex39kcdeahgxjaxnr2wnv7jvxvhjn2p +nomic1nju6dv4kam9zrvmunnyu3yvca8vqd0k535zpzd +nomic1p4r84d3fzha58mctjgfy05u42p8zhp4fm520dw +nomic1s2qslv6garwnuqgjdg8faxghuwu32en4kx9er3 +nomic1pvhgy9cwc789q6tc5l86ec8hmk6xhfdlh36pzs +nomic1zjw5ndqh6qkrld5f48w9l74ylftapfwud0n65k +nomic1lezdxy9ntzlyx3vzaatxrvft3fe4ydg9he0x9g +nomic1dnqf4s9ss0me7fxlq28993awv6wyjhre44cfng +nomic1j5az0zsgacwks4v5qvlwpqycqvgw3nlscjsvh2 +nomic1j0yd66z8cestmequhfc06853a33du7p9e36cd3 +nomic1rcsmgga6qtyqxfu0psamr7c7cc64pzxty22cgc +nomic1uxf8zpr59tpasfpl7eu3v4r64nnaq6d5j8dny5 +nomic10g3hzsme335q8r2g3p4y3x7s2pv587fw0zm6nx +nomic1ugde2zyg7eusa8xzz94l43r8afhykhlz0kflyd +nomic15tjvcxjuzmtkd5cpk78gsmne8gkuz8v7ezwufk +nomic1shtyrqmd8trk5utwr2xznnz583uer28vfqarh8 +nomic1x47rcwukde03fah62jhu237yqauwmsjpd7wxt0 +nomic1rwg299eggxxwdnpjvg4h05rkxxdm0mpchy3wr3 +nomic1mmdafzv75ymfvjl6raj96aqkg5cyrhltjztrvn +nomic1r4tlmxdv2c42r0z73ndga5ay7h8ut4exennh79 +nomic1skkza5kn9p8dxykd785q64nwr3f778tql3ze7p +nomic1cx0d4c4c0mmdpfxlqhx9vk94echz3jvwyjnyar +nomic14gyczg4q209tfv3qzudrs2ales0aseap5dm25s +nomic1phvddcjw2ng6ma6e46xk6k645wa52d6ajzmm2k +nomic100fjd4fgvavlevh44wqtfl8e46ryyzmhw9ch5y +nomic14jayw662dsn2u050lmhpysqu64dz02cvy7s5q3 +nomic1ll9yn0a8vaykxf7upq6v95dlk6eg0wrupuapag +nomic17x2ry75hddumjswr2gr7hwfle7hdtned5ync3k +nomic1g850f3cyrtrapsa7e5wm8upmnk8adt45gq2y4e +nomic14xqhp6z2f0dd3058tereffchy5gxx8dw7a0kvr +nomic1zgdgxc99vkt0q0dnznnruyce2exg448n2cjejh +nomic14cajwg99cyyp6jj7rwvapr3upjedk67qrk7t24 +nomic1hyhzlnpwplwn0msk599e042wwatr5clvlkxnpy +nomic1akce8drf4gdh20rt6yrg3wa4dza0nkzs4glmcl +nomic1qttmfljc3qcerypthjtxw4a8675xcf9hrtezns +nomic1kfflnrwq0p882clrcfr0s4f7ra4mw5ae290lvp +nomic19t7k5wxtc9pvmxku34ltj030czt906e5hjuenn +nomic190yklca66sqhfljdpc4mmqkmjmg95y3anpftp7 +nomic1lj6h5mznygghykje06eh8jus5u9qq524fprtcd +nomic1zny08hytla5a2cngc4wl8kannwdhv7me4yg84y +nomic1w4nsxsu54d0fdc5zkqkj0sj9v095fqjkhcmta5 +nomic1t2e0jgt78saqdzn845l95c8kpyz36ye6wzw5ar +nomic1fceypmsnz7gq9eyjm7ducer88j67ptgkeelru0 +nomic1ksjcaas536pfnz0ugnnrk5x2k7n7xtele0ctwf +nomic1xyg6scf4t8qq8karduxhump89hyrvl3vph69h5 +nomic1xus0kvfkav7h85ahmnxuxz7ujyyfrmknleh5u5 +nomic150q6ppu366x468pkhm7zcw7jk5jegg0su9gskc +nomic1dfqxqksjhun28yek7recpqv00u00mdpxdt8325 +nomic1cnzse0r2let7yr65u885e7ehueq4mfn2wzjlv0 +nomic19g48nzz2xtwn2p8cskarqsypvx5jw8nchyxyc3 +nomic1h62d2ymq7ym4snzxk84uel5t4dntpcl6ncze3z +nomic1ja0uke5s63vw2umrk3vpjjwd8m5a9zcark4e7u +nomic1gm4jceunfw78eee8a0n2wa5cq6q5sf8pwg57xz +nomic1p2fsp3ux7kuvldvp6khxqv7ds4ly22q0qda4d5 +nomic17u2jm3yx67mg5udl9keh5nq6gddpfjn5a8dvzl +nomic1sclt9dyygqfd4szgj9l6ygt5nrhd7g8tu5v4s5 +nomic17jycpgrstaj5ahlqdwm740se2z4k7kgq7rc8nk +nomic1y946vr3nxmxp4ueuunt4hazmvf5srdk9xxdkj3 +nomic1ns0qvqyst4jq3vk532ersjs33jfamwd5wksqxd +nomic10usxwzd4jrtrkyu7cw4p39z0ajg2rfmu9lxqh7 +nomic1x46ff45ctkak6rjqka9uqvwqt4vhdr45hzc5vf +nomic19kd6f0yn50qh80xw54jtr7aeesch0kshwfh6de +nomic1xs5lxpalxqkyv8hnmg0n63gwmdt72mgr5l0v5q +nomic1x7km6v5hltx9hywkq6fctq0v326y9lv6cnrd0v +nomic19jc885m0n9kdqk9smnzwx97kcnsmgwnxjvhskx +nomic1qr6gggq8953qetshu7l03m85cmdlet8lk9m9tp +nomic1eh6ukje0t7n00cf3q0gfhvxnrgxc98wuu7sled +nomic1gdurpulxwxc4ev077dtkvjlvvzq787ac9x760g +nomic1p2wm8jtxdtyqa4dfda3suh5wrpjkr2cklcexz4 +nomic1aw9r2mrvsh9v7re4sx5pq7e2fgzrvcuaamfx27 +nomic1nffxrer06tgkzlhzdxtz7efrqf0ykufraaxnj0 +nomic1afgkpa33glu2nu4hrzzzuaeyguzx6rcwdhykdp +nomic166f7qetvlesa82zd85kxe77mtnem9u54yljy07 +nomic1cawhs2t43pvp9rstva6fceg6nzgr6g8m4rsgqe +nomic14e2nkug4xg3spcfuhpldap24erruak5qfgmml0 +nomic14zuqtexs7gyurtspw9ztxdlcmql890hjg33k8m +nomic14wpavs5ndsmmzzw2fqd3xp6h7eppw9gjs5kfka +nomic147zw46lceqvcez2jclaxvgtp9eszpvhe8e2cmk +nomic1xvkrdmtj0qw6htydtlzj88qvpqk8h96mk86q9j +nomic1tff5zpw5nnswjstemvr52krcmryvdhc0ax4h6r +nomic1k0g7hacqf25ahx75x3p0dqsch73xk4mexwqmnz +nomic1r277pfc6tce8v3s4jl3k4jfntt44w56axaym90 +nomic1jl82qy8645dpmrcxe64wfxtq8rygyxlrj74z62 +nomic1kzz8l4wx8ltgt5krj34d3lf6fyhx98ysq63ujp +nomic1nfja85y9xta9634uxm0r0w6x00hgy22kp3z7ud +nomic1sc24mq7czjlyh2trym83kmyeam2jadqtyr9lkd +nomic1yaw8t3m93afsk995a3x9c3fuduuqg6xg4lmyek +nomic17qy5dh52emhdxj9jsrggz5e2aq8rcyefayqu8z +nomic108rqwjaffph0lvdyd7fc7tpnrx4n8h4rdyvntj +nomic1sg8r7u5ddqkpha7qv52c6lu82ude88lyafrnsz +nomic1xvssg39qa7ah9muq50fsmm6h4smzgjfqkp5tvp +nomic198mp2nyzwshjrytzw6g6tuyulkvqngtwu94qpp +nomic10vkkjh7fhhmzgc44cfmj6pwzk5z6ummwr0yf76 +nomic1tcahu5ye35chj809jtnavf86lva4gwkzqm0jpk +nomic1xp5jvw76yh3ac8fs9lqn0gq2leav4se82dpads +nomic1vvln3gz58r3nexrm76msfp9rhr3dzclchytvka +nomic14vv4xlk5nwcpq4r8pkqdupsc0qk52x3tkcr8xp +nomic1zvjt8xpc9q3rycppu06quqwuy6280fh45fgdtc +nomic17eckvmlaj256k5vmxsprxvewverakdk3jsmkre +nomic124ysmvvr8rprzhq8ksec5mjnkf56hujgmhd4jl +nomic1d9p7wh9nq53uq0z0tdfpakp439zwznm27zn2ed +nomic1svkdprfr5ct7dytvnczfjxcxu29k4znf7rumxy +nomic1vmnszddr75huvt7fcvx7nuvk7vje4qmx9a3zuk +nomic1gzkve0ajwv8kymfffz0mru9zfg3nwjvqekkwdl +nomic1zekppcu735ltlpr4la8gmasn7pt7ajylsgdrc4 +nomic195u7ldqrg4esrfp0qc87ek4uze98dmnugx6m4s +nomic1julguuht6dkx9e272freehg0dd9gj7wvgzudgs +nomic1p6y3x9zy0d05mnptm6sef0y9ly6xmgxffus2xn +nomic1xlperzrmq9yz2ktg7jrhcskkht4yf6xwq66ewr +nomic173k74w7c3pd9yfjg0mervs6kmcmelyr86sd4lc +nomic12088f4cr8lxrlyqmgynt68mj57ejgg58vl3tcx +nomic1qcaugnrkmzm9gkcp46kh4fge8v33542as338gn +nomic1d0egu5ge0n6m8yk8fm2ev37xhrfqel7qh3ld7x +nomic1ue8h6392q97gt8hfm4n8ge6lws7796hx9zrtw8 +nomic1rdrrdvhxqsmrljzp656csvz6hvh9620l7je0rp +nomic1cw0ytqhfdzlslcfcl9p77upe5hkjrc4wla9m4h +nomic1fnanhpzzuad5mfmfe22yk4492zt4yh3sdrgwdc +nomic1szxk36ftugmy2hux5cdgj3dr4ze8h9a0tngeas +nomic12qahcc7m5axx55mdeqhulwdxha983z76nucpgj +nomic1rpjqknsyak6h40pktntjgmpalfz4lr4wya52ce +nomic1w7gyemhymkkwz6tyvzrfyw34axuvta5vcsdyuj +nomic1sfecgc5rsddpgz9v2drajqdv8vsl69wkmcqc46 +nomic13ve4n5ak0xydf0943lhlw6f4t4n8ueshuces3h +nomic1z7d3q0znrfyljm0fpzsjlxyeqvwpxu28lhgw0v +nomic1ajl8ga754hmems6c33ljxerxvpw9detpxd39lm +nomic1pe70udrxekg4asdxwdzljp7pspttxdrvh7acjd +nomic1ahsgwdj3g8ca6dn7kwhtu029spg9jgx8nnfylg +nomic13n05lm84xnmf7f44fne8dt994lsajmzpgagy5h +nomic16meymakpr0cfcjeu20fh2s6dtvul4kpwh6play +nomic19zt3lept54w38pr9qxq6j6fhy5rcew604luapk +nomic10mkczsrf8snhdhazkf7lav2hjdctyupv0ywapg +nomic1m0nrf6hwu2x6va7uvxa4897f2ugr0hlvqhawhy +nomic1ld5p7hn43yuh8ht28gm9pfjgj2fctujpqpc0cl +nomic1zch695nea92jqn94sdd0nqjhnvpgfffwdsstz6 +nomic17ew29tzgtlunm4j0mqpj3vt2ewncdqp6nhhz7d +nomic1z8nrmgcz0qelhxv7hftdu64dq4hl2pn0eye6xg +nomic1cqct99d8lnwrp4fqemjuld60qfnmt43mhzm9q5 +nomic1ruzff99wnlky2vx02dwdncr42rq0z2n6vnre7k +nomic1uy5hzhmdxky4l76afes2szhdj3zlt8tu72v0nh +nomic1m8yf3g2m9p7danjvt4ga6vzewy380pk54al4g0 +nomic1jsadfu3nfj83sxqc8at4ppmnkdsm03glfrx9d0 +nomic1c3uhgyvzurgezzs3kc0dc2k43jw32cjr9gh0wd +nomic1fya67xh7e0ug0mkw0hc4v4heja6f30txjv0nmh +nomic1w85z6fss8lugus9awd925hu39jrujrlw0rkv25 +nomic12t252tyzuxrnupcepeany3epsnprs25ag09ymr +nomic108p4g2t6cprdl438gyhhnsdses3j97vvk6rj69 +nomic1meywllrujslm9xq80vhna7647kkm0t4hj3dz58 +nomic1tcaw75s8r4ukj0g6qztscqssd5vrpka9zmjwp7 +nomic1pgau0y96k6y2j2493rmq0f290vwj8ekxswnyf2 +nomic1mmm6ua0v2zvp7k4fw5dww5v050ddscl9p5psan +nomic1j4ht7ph4qldtx46jm2vqj3hj7x970nje404tx0 +nomic1pxleugd5xzduj2tjd7n9cxfayjhams2r38qkdr +nomic1hetx9a3q9cujy3h5x8zk43lu8krreup73l4t5j +nomic1laxjhvkftdx4nsj3yk7jhkqwus4ye22ellxz3w +nomic1vpmex66h7ylz8cg2jgy4t62xg4m2tla9mcc4cv +nomic1y4wzfnvak6fwdm934stksjt9g0gz8klmg24fsz +nomic1purja9dkex682z3j2xxhz4d9hxrpmlltvky273 +nomic1tlaea2had6dyw3z6xyj7sjkgfsqhszh57p5mv5 +nomic1jaq6rn09s4y8r4dmhwgtztecyd5w7tctnj7xed +nomic12sczd7vmheqat355txqducgm6fk86ye4d6lm53 +nomic13zpcmzffesteq4pwvtnr7r259pntuvz4q8k4sz +nomic1qak3fa94ltmuwd0sjyz0sq5te9tnv6xtg07laf +nomic1lvm3fw9sstz07w2xqselqu5tucu74mh096nfu6 +nomic1um0j8mskacs58whj3zd3fx6nrytsw8w2qjrvhm +nomic14dmelcmvwq8sefu5tr4atv98u6ur9c20pyyp3r +nomic147tm60zcvkv6j9n52uxxezjuv8k72xvf9jctd5 +nomic1985t3fwh8aw7kd2m78mj0v9fe7z2473j8dvswq +nomic1052lct3krg9yagysaelvg38t65hwyn89xz2xmv +nomic10srftzzf8wc2geclaxjxxc6gdfmeallc7m7f4c +nomic1jjal9zgepms9nk533nya6frzyeu3je2vh7vn3r +nomic13sc66ae36a8m6zcqyg8h63t9syjeg5a7y5zflk +nomic1cu9asccxghup3f7ee0akzqtrga3wusuunhpkek +nomic1ygla0anwp772yfl82ptmyv5vkl2uwxaxvkyp6j +nomic1sm0huqu76wjug6cwkf3szft00v9v7jmgh0vzng +nomic14wnuhpgkzgnh7z908dsukskn7yujmr8l30fsqe +nomic1lyzvryks0pst8678rct6nctkxxezua08gdmymu +nomic1g4rnl25cnl4upu6at88xpnqz7a7rfq52vu8jkh +nomic1sfqqq4dcdjw7fvdysstzmnmq4ua3xcfspxxltt +nomic1aa6mrfgneuseyjq8rr3vllsjcpammajuahpztv +nomic1law0330gjt83tslcv6ykkr3dz88dc0wf78ye8q +nomic1tusvcyxg89f7xl7jy64tmpvx2yukxj74fm8x83 +nomic1gv23034suxwklhr4q7fsw9dygph55ykmn7jlkp +nomic17e4xmtdg9tz4z2uaw2ul2rf7te2m9cc0tklwy8 +nomic1an9wl53ngnsmjmxlmpsqtrp7e7y84raquvn8ks +nomic1qxauw8pvg5fej2lhstdwh96ska708nm63pxuez +nomic1e9u2s9msfetm0f30vvaeemechpmkf5vhpghltz +nomic1z7w0x22dj48h66her49mcrjaf9wuu3h7qkcqnn +nomic102dsxewzf8egvxr3els5tjqmvp5ql367p8dcm0 +nomic1ys7s8x49xev0t62mu5hw5khyv07l7p4fjuyfj4 +nomic1nze42jgkycjwqvuzzyh5nq6uha2v6lrfmqw8zw +nomic1hef2emuf6x04uyck8lmpq93lzzd89wav6vt8dd +nomic10xgz33mrrlj07kc8hlz0r436a4ejzkte8rr57a +nomic1s7n0khuh558gf7uzgd6tar9ch34pdh6upyrna7 +nomic10lul8yphh4tvq4frfw6zejvrd2gyhtl7m3s0me +nomic1cpuae23pr36qxfpqqmv7nvc7ehr6rl49aw0f7p +nomic1hmqcnuadgeel9f697hnfzery0lxpkdanjqjz92 +nomic10zs8jsstx6smrns7jvhc6n7tj3tqcz8dtnt6qa +nomic1ar4jjfqfm3090msyqzh2ymsrpsrettz2ylp667 +nomic13ru2tdm2pr5r6n32jw738a8m9lkwlcdwap0xas +nomic1u7qk0xjnqd2yvw4ccspsrvpa6rlm3j29v7jukt +nomic1zy8lt3n0et4n6xu6a9kl27e45m45f2ke8pffa3 +nomic13exwxhzkvjqs525ep8t4wkss5svelyana9jpp3 +nomic1n770stec6366ttw2pqhhe6vug2saka8n9edfm0 +nomic19fxt5vqy9j2yt9uu99l6yw0hruh5wxaer074df +nomic1wgdegtthkx0n5fmyt2l2xn9jchywffac2j8ns6 +nomic1detqf79grm03sv6ryaat8n5kt745y3fgxvgpln +nomic18r72flynzn768us36dygfn6c6dn7gtmfe939wq +nomic17h4fe4qdt0dtcfkuc2cmk43ktan5u064t6dyeu +nomic1gxsmetwlkn2c2p9cp9d0s4gepqnj7pd6cdvp8j +nomic1dek6e9c9p00usgxgkl5759lh7gw5uyqyq5m9z5 +nomic168mmzne3a0e6qapfl2etczz6x7d85fhymxrzer +nomic17yz0at89xnt2zy8lpfy7ultwh9nl7cplyc9hq4 +nomic1gsntsyym25rc5kgqeuydutlpuqhgs54vfzhree +nomic1k4drxydzq8vz4x6wy5vk4je573tca0w9k37x00 +nomic1h0gnlq6ac6jlsgyysx5shwvhju5jeyz9f3txlp +nomic1qe0exmrlvv6mwg9jaqdyzx00pdulv0ysuqnwne +nomic1ra7dmu2lqshkdnkx5l0kra38ftw3qenku845du +nomic1yhppklazvehhap0je5lerlpuwzq9jhzvvxrkmk +nomic1q4ug8tl7ghz5j0q23dhuszv98he392h2esxd25 +nomic1kquk63vg0c7ugpd4n9l2hfemys9kgywwrzdkjr +nomic1e2fyddrp9mxng9lk8kpqs38hcusrsnwerht692 +nomic1v83dnztej6fhhp2hy9tkqzeng7flr9nx6kq7f3 +nomic1sa8mc9jdhll20ed343zraksc3h5j9d02udk3wx +nomic1zjwnvwlz6nq5qtna8feeur6hcjj3d2hg9k39kd +nomic18y53njs6qp3ex0k724sd9mfsjftxet9rxfmcwj +nomic1rygf6l3swgyuy9apuuspwleqj4g0sq264t5v65 +nomic1s43l7s99hx627scn2ldd3ey50qpj9frvma3vhx +nomic1z2qgaj3flw2r2gdn7yq22623p7adykwgl05tfw +nomic1447ffn7mtr53trn4egr73qg08fxr9tle7qr0z7 +nomic14zzjec8la569ruld9vqqt6nvrc85f20lanknsq +nomic1csv2mv8w7kqtp5z7eu86pfsz8qwja8uyfrf9su +nomic18hvxeurh47qudv5qmrg88tewrs53razk7sfelh +nomic10v970v5e4juafq6cfw370ug9xzgntntgkpkhjm +nomic1z0p2u7k4rxuqrj9hn2qetmrykz6yat367kjj3k +nomic19aan9pu2vnuja7u8nf7kdh4d86afhj0r5zksp5 +nomic1fm2h9mp4xrrumdrjk2w97hltnrt2u2twmjjtfl +nomic1frc266qg9vdyyfegekxqfmvlxpkq9thh76pu9q +nomic1dza5jnmznme24q94gt7q4uagcu056zy4lsfw5m +nomic1vcdhr936f7tw5a6fn9jc0axws5ylulu69p2g22 +nomic1s0aywgc6rucfscng07fnw0fj836mhz6mmmlu7p +nomic16mf0f2tzxs67rdyd4uc34sqjzs9gk4wajw3pj2 +nomic1jjwf2052uy7fvl8tl65lgxnyr7mggc7vk9rz0u +nomic1xzfxvm6g36urvjs3xdaht9flz4gch0zh9ylpug +nomic1sx6jfq55kjlyvm6ae53x07n8gcu4s56xnqyeh7 +nomic1vrum3rl49lxeetta5vd2zwmwvkw4kdq94qk5hh +nomic1vudtpjyplxrau4822u4uu9kfkavdfxg456g2dh +nomic1f353yj9st8kzxhkfyxrw44uncxvpekpflldpk4 +nomic1d9zu8dpk2dha29pjx7vlpqz2dslxqzn6rlu2v2 +nomic1fjzc695xqr48y4l4gq674cxxq5d2hqez2gm8wy +nomic1qs3pca5yuv8t8qfy70ylkuzqu8428uxahsm2h5 +nomic1smrhd9c9rfafzuv30t5uakhlxah6dcg89leg3y +nomic12yc58lmcnctards59ep8ujme8c725a8vms73mj +nomic1wcx3h2cev0j6xj3jud2xhlp7r8tnzm4uf93nam +nomic1hake9gt024lmpagdx50knuztcyssuqdk335m7d +nomic1s4tkwhj46hp9d4p05lymzcg2lrqcvd0kmmy7ws +nomic1prjkdylugnqfknhdhksu8dwfyd2zyhd2zt5q09 +nomic1hn38ncjta6qhnurnv9v4zf56v9atsx0dxw2v52 +nomic10rdut36lnhsrudd3t4zqqgpvrmxam4le4qs68s +nomic1rxug3etjd7dd740f0j3h0yql7j7zyvxdtzk0th +nomic1nrc069kemdy6t224t4hkrcm0vwffjv9f872lv9 +nomic1wtvzsrcsq5rpeahn885tk3dlg9qpaufp9pftyr +nomic1kzuguxevc6kexrwhm6xj3vanl4cmawk5vfah9u +nomic1p06guptkql3eannp5cl5qeqh27xwhzjqkpf57f +nomic1vf7la07q3n8cdc236mp3g0shatdqxdp8525ssp +nomic1nm50zycnm9yf33rv8n6lpks24usxzahktu6g5d +nomic1gwua5gcrm6ypayh6h9crfkj8q6dw9qvknjgd8l +nomic1g5435cjhlm4s2nlmwln6ess9x4lc4qgd4pjsvs +nomic17n8yp00k3ml0ykpzqtmglc8eatcpshgdx0hrux +nomic1dz4k4hd64rvn0dkn5a8gdjdaj936jyxd590avz +nomic1ax32rmtyraxnf76w3tcx6pmt7psdfgfdlr9mq8 +nomic1v2xh06d7jywnnrhu0shyfejn7uff7l4nhut2zy +nomic1r2gphsxrxr8kxul58taqgmzn7n4yqdugq87zh6 +nomic19f7nq7cs5lxgartse9u3jutaz98w20lc9z0cqv +nomic15qshvgxzyda5tmxl7fs6x0080dfm39d40qrrak +nomic1cttw5h56pq2g4z4nedv4wqhvcrh4yfq350kd03 +nomic18j249nuqwey5dvsrdg3ynjrytr0qpx5jy5a5wc +nomic1vr3p4yyk0vkjekrvhmjvnj4g5ypl8exa53cdfr +nomic1e2ylwns00w9krm4cz5pc062jqpamjlmy0zhggk +nomic1eg2fxj2pkm3cez8fd6wlqreqtf39mtsyg2208p +nomic10mj5vs3w0t8nghpvl7lzqsrezzt6dxyhpegz04 +nomic1r2nujddqfxvw3nuvdfgsnskxgrdhpfz7g9qx4w +nomic1z92n47uyeyxwtmfsw44nawy5plxfdxpng33z7d +nomic1fs67g6a7jdf4u6lkhyuwwlyyf9dw8ljtkcmtcr +nomic1amhkfh70dphzhm7vda4auv05wh0alp8v8gfnxg +nomic1y83nga220nfjt9zz0mmqc90cd705az95vllqrl +nomic1yxpl8dgfm2w77wkr9dl70zfa2vyrrrkwjh6d7t +nomic1e5pfa582fyypuh9c8quasdh3f40a6yt758vl83 +nomic17dn6khagllfhgtnhpa3uf3gpsnfr7nurd8x38y +nomic12hyv6qsvd5ts3pe08l8euccrunmp5ry2w4858c +nomic1xrrrxwmpeuzf6edvmylch3rnrn8f567qgmpwd5 +nomic1jdkd57kyj0ps6y8ev2sktxzteavsqzm8v9z44y +nomic1qgcrc6lgfycffdre09fwp4t35lkcags6av5dx9 +nomic1ga8tq2jv9cks6scpmrjfhst55dqvtmhqhxjjmf +nomic18jj8eq7xpyqdv9cdxpyxn0ulspmhx424lg69f9 +nomic10jcdyzrdu5w0xh23r0ve8ftmmw0n4pj28x0wgl +nomic1da68qsg9l5vuaclcks7af86kvmvvp0gs7nnadl +nomic17pz7rlzlgsne9luslvxpchn5m3p5fgrq93m45v +nomic144spjf44ewzfwf6qvrv6evhwq9s0rxlzapsv9s +nomic1vmjmcp77zjv8usfvaqca02vrecgpc68qjy25uu +nomic1syk509stjkvfn3qwhuuzjse03cr4xwrfy40xj0 +nomic1fsclv2hq9vf2jw8dv5wrffprh5ga623mjq5tau +nomic15sdehu0qksljngzjvtjav2uh8s45ugm773rulm +nomic1l07ht975euv8lycv2q3hymqwmsnzy5l3sku4qj +nomic1y282cakk53q8ryuxxcg5fkczzulp6wy6ghplzv +nomic1vsgse6335r9dae85nlh2ps0hu84hlremg76wfu +nomic1hn5lw538tvdvmn3afs3s2k4ws22jc0ft3flzxc +nomic1gk6py8fukt8dnaad00atemjqjlhjlwv9lsaqng +nomic1z9ny5l2md8t5jl8vzwk07epk6lad2ktvjh0v53 +nomic1uh36v8655ngav2kmyp8p3nhks79sgfvuk4t7wr +nomic1v63q6ckkym7znwmey36gzc0tzzrapckma4z3pq +nomic1my5xxs2pq0ecwnel5pc9w37qyh83azpxeeyyqh +nomic1e0zm9l8dz9z94xskvd7wgmv0e8qst6700gwplj +nomic137uqhz0u6h0zpn3w5rmhtr98d4m80hf9xrdm02 +nomic1mptn4sw4z0d0874usn4qpk4e49zectxx6shx5q +nomic1gdwcxmnuaxgze3daxc798jxzayt2h7vyzyp0u9 +nomic1xzp8m73fctzu0lk3jtdefhvhej8u4hmvrnjpqe +nomic1qd432aem98lvzpjcq78gvzqputgcs090xnv32r +nomic17vqcum09r9a3tqhjhzd9x595g7u5ytq3jp5xs3 +nomic1e7lgh54xt3dsljwkcdg89k5fqexrc6sagfrlke +nomic12d425eddl7nql8zydt8ep6xy02sujjmwhruwwz +nomic1hlxsavlny5ax6uwggr49qaw57cxnhcld6qznmq +nomic1ngl93ejfmq43ws8w4sxzy7gecg3v9d50s0jkyu +nomic1d3957x4h9g4h54v900vcsyfwlf5qnrca206c7s +nomic1uqp2gwghwq3ygy4x7wsaeyggtgrpzkt7gz8hrv +nomic1l3ny5jf5g69rdlz37pkkayvs5yypaavjpv4gar +nomic1hj9edlk53xmp8t63vy8wcu75f2j3huz672ye7d +nomic15hyr8az8yg0jk2f00y97zryz27q9wax62cmpa7 +nomic1ze3qzejss6tcfdnshl6gkd9f3uwjmuap3l360d +nomic1mk8kvqsnge6e3edpx38dqnpn39zmqlswfz6zln +nomic1n52duyxq5tlrr2yx42p4ctgakkn3exau70yncu +nomic1q2yj0vdmdanmdsh6qztu3cn7y9deqx7lxak4qp +nomic1nvawlzsgytetv8hk409qarhf97fqhuh0xfxljc +nomic1rk9vpxq2ux2u6u384veu7psxztslwhscastxhl +nomic19avcwh4q70ugvjpp24qu0kcdqkvgzlvehkv8eq +nomic1fy6n0tg7s7rxaduw09h4wyuu2fp7ldy9hlj4jr +nomic1ncmcp96glmf5cnsxez8lvplumg98zqz85z8v3p +nomic1vqp3s0muqq0045j6tudnsm6sx7lsr5x6n8ckyr +nomic1gtlrpw0atvc3ydn2s2fpcja0n2stw4djn40pyu +nomic1m8hax6c4tc02uq3ldmgw6yrejtd5grg92dc7np +nomic1rd457dzds27ltcjzfkxqkqs4qw0a2mtjumhd6m +nomic1d8xtuav36xg7hp6lv6u69gexpd8sunae2n3rm3 +nomic1zvj80m9ckmtp5cglwt6wn0dcs0y9ceddsdqkt7 +nomic1pdsepwmf42mw53tcq70fe2xjfshgkrgn7fsw2e +nomic10wzd0drgcpudme039j22h70dnayra75akcw34x +nomic1smfzt25ax563c0s2wgmcmt3g67d09t4mf692jv +nomic1w6ha70ghjp4rg57cvtws6k5jnz8t85a0xzzs9z +nomic1sd2hkpjqevmqva6jvsrrc52kmdshplgyu52nqw +nomic1hdu7ddht7v6a5h9ewhhu3td964v999mf9w68af +nomic1jlthkvj72j4a6aysus8hw5fe4609kth3g69n5m +nomic1fnukum7q4q8y939v90vhuzheeeudh954fe3lnj +nomic1pl4zwv4mmzkmqc3ac42jpn2u7xche7n0rf92rg +nomic16as2ednuwdng0255eazchgf6u9ys53s6md8plz +nomic1rdsavmql2xx9m67a8a6pp739cktkynz49m3qun +nomic1mx4zxmq9l3an7a2mgzs0cvcdernz633n6zqw29 +nomic1c6mgxkjepquve9ryq5pmq5lcjgywhm7s4qsh8c +nomic1rqrck8d5u34l8p6zvanh9zn4kkd4v6shpza48p +nomic1t3gsdl2uux0rmt3acn8qursc9sarhtm6fmzt0m +nomic14eflcqm6rzlvauwdvw29gg2vqjmddn099aj8lu +nomic14fqtpynvp6vcn4hwu5k6fw3rtxzp5yd5gkelmf +nomic1u8p5gz4cht0n889ecazyg5u776pe73fn2lj9de +nomic1zqqj40n9vuve4hl84a0rhdzqkxzk42ttj90rs7 +nomic166jxmsf24hgdn9xcjanemwvkf3d6e0gmyt4ns3 +nomic136d9g5f284ka432eh50gpr6rs3d8qcrlssj5el +nomic1984xcee3ejd65w9zmjr2stawy7a2nqzq4m0zdd +nomic1fghgwhgtxtcshj4a9alp7u2qv6n2wffqwdphv0 +nomic10qey6aqjf5wlkglp0ljjg3v6h8ws26pm4tn3th +nomic1dmmaf7wvw4ldcr7sg5xxh497l26h7nxvalltes +nomic1hxma8texfslkkhan00vm6vkzxl8t6rumlh8ved +nomic1z0ssgfj0khzf8fc6x2j28mysgalug8aeuznf2r +nomic1nul93xq4es683ee03rctw6vqhmhd7aggc7g6kp +nomic1cnch842gndmzw25yduvxjk540mnfrask37r52x +nomic192ul5fw3u0d7rn2t96ssjjffx9qdexf83est8n +nomic1vsfteyxefcr30dj9exl5j0fvscvusvstzgglda +nomic1yjcddkk7xfz2hg7srs2q23u2hne02xwwupxcds +nomic1vrx73w2st2nxzrz5ee9rpgqevhqs6n6m228k0y +nomic1gdv7kzg2lvx6k5w6nxq84q8r9z2ujpvenwsd93 +nomic1vjdwjuxxtn3n5g532l6tkzmrv6xpyux0d3qkpp +nomic18pkjl97qfech33dusdhsh65tfj3p3jnsj56nc2 +nomic1lwxcn8a3ntqpdtx0vd4wx3harnx08enqp40j0e +nomic1pqnarwhqk229ac79wcakh57gtzwzqwxrqk42f7 +nomic1djqpcjyy2rcphlestk64l3c8pt48udh3aex5h9 +nomic1jds98a8qcvhvnd8anguj0xnqgyawzh662tsgdd +nomic1qr5dttjyacpzv9jadtljxumqfxt3n2xzkdq9gq +nomic1smqr5tp684g07aekcn0w852wqlme5mn6jsh6fu +nomic17q8qj64kj5gv7d7xdna784xylhqa3qug44r2hd +nomic13alpkca5fmxk3x5ruluzczgc3k2vramt2gheg7 +nomic1f48dwj5fptfdhxud687yt99ew4n0nyqrsd36kx +nomic14ap5vza5jyy9kqkvxm5763mfnszd9vum05vgej +nomic1gzlz4dqudpye5xqfrcccp9st0yxhqudzn4fyeg +nomic1gynfd0g657rdnx9ve7netv3nxws9h78ccvlvk5 +nomic1tyyqm3agxuncfznrv4z6ff489rx0vq7clqnfp3 +nomic144w0jcruskyhtgx4ezavd7pqlc46jg4vjry6nc +nomic1zywrc64u67y8r556tc9qar29g7vyeen0alvdg9 +nomic1cnxdkwta80f4jxw7ddexvlh2uss2ag9t0fjdcl +nomic1c9r0dhtre0afhvvquj05e5608yhkzeatgaa9at +nomic1mksc5x458dqknzu39s9g82u55w0t6944fy8a62 +nomic1y03trwazguex20fw3ckxg0jd8gmpjh3xwkejpk +nomic13ze97zcysvwxmpu0zpeq7fr5wx44advdmdskez +nomic13qny7y3msjr5lyngqt28hjgz33xhtd24yftka5 +nomic1qrzg3eyjnp3y2hxawwdcjkcv4kydy3a3l6pve8 +nomic1wupm8er407z5f8rwwfr0knc7v79a35pv5y3rfm +nomic14gwg2qaghttmmsm8a998kkv4sav0mke0mfwfz3 +nomic1a5kaehuk3zhkjrtx2uq30dgxj35a3evv53uz8d +nomic1v97agk4gkyytpphhymqxhh3aqvvra3vv340yya +nomic1umlfm6vfcmku3jktf4a44cf4nv4fe6hqn6xvy5 +nomic1aqr9jwwlr487w0rqqwznnky49xz4c2jphcynen +nomic1j5l0tg7nxjj84hnkyyywph2avulyzyshne0zsw +nomic1e2q9zjl88qsefg8fxdcsvuqxydvcgzkss2clqp +nomic1gfwqwjsw8ny8298d6lvx0g6um4x6q8qncmzmj4 +nomic1jjj7yh9ch0qgxmhh0hexy9ajdflwxu3n49eqg5 +nomic1l6x296xzmj3xxf4sxcsxzhlmk9aguqzz2f2z9p +nomic126kv4x70s75mrkvmpvmq5p4prhd9ep6w9jqwtj +nomic15f46k58ca87cj7844rgz4z47axpksq96y52zcm +nomic12z9k00k7dje9vnpfkkqsr0e7fy795dqjj308k2 +nomic1uc7f4dt04pe07rwmv9q6yggghynzevmwmz8ltf +nomic1s49d0qgengsj6xwaqvhnsfrep3czs5v3dzzz9t +nomic1cf89v2eu9mdnekd6unusxyntyqh208qsneqllw +nomic15pdycya5fgxfmymfdrfdnsd874sh8w009ar60r +nomic1ssanfu7czpyw64ypruj6aqmmw666qfku64hqq3 +nomic1lwkpyc07zta670uuz750xet787czp6uc53a4le +nomic1j725ypfqc83ewlndjp0qjk07mnvn6z2ul4vgye +nomic1a4klfgf2z2ka4u8599p57aqxdlhwf2p78n0k79 +nomic12pacz5tyulvluu0tl6kld3txhdu70dxgp3jqyx +nomic1pazpywju5mrfgrshkyzs3zxemf0fgwpksmfz5s +nomic1pzunc9mys4lkr02nncdsg40we93qhj7n79yggf +nomic1958ex963n93nhmvcrtlwwtr0c9qmvewhcqec64 +nomic1s0lxr229rpysrkeukugq4ue9sa2c05sx7qxmk9 +nomic199gxe69xgw8qxpnld7ya8eh92ajdaqzw8d5hnk +nomic1duad60aqqyhzfnha5srhpsw3eegg6phmwlyd0m +nomic1gp957czryfgyvxwn3tfnyy2f0t9g2p4pe475e7 +nomic1gru9dpat50hn4gzhvlh3vwnyc9q3q7d4w9gcvt +nomic12rnu5pl8rd0nvjym6qx45dddv85y5sanny7gsm +nomic1np9qurvpurwls32a2csfec992txm5wlxdse47z +nomic13h9whxjw9vujgz7tlagrxa577zsfe0qs980mga +nomic1e3r37jr5pwhfa8690psfmly7rjnh8pcwumfecl +nomic1ammx459meute6x7lsp6wds7e69gggzys8uvwwf +nomic1vxurf7gcsrn6unggcez7agvdnjyvpxq7dyr3rg +nomic1saz2nvwyr87aqu60qc4gmnfl3s4s0qquf7cl4c +nomic1h5kqk49qply5mzr9lh0er377k0rtxdpskr5rj8 +nomic1wv8s3cflrukukpe8wt0t246ewamshqlnty6qat +nomic1636skayudk5wmz2dp65rzs3wrlzyaw4xfkgmrz +nomic1lxptmy60dpjn2wck7lrseg90krh30drssmdz2v +nomic1w8f79untsjwrdlzl7tfy046gh2suz96zz6zt97 +nomic1tcashe2jcwu4mlwql08ayrmv72dwanpzz898kv +nomic1sfc34ujkys84eeqmegm7lle955y3edytuvdj72 +nomic1etfksyl75gjvf4s2ah4cvtwev62c0zhng2e22z +nomic1q2t96wltse9s8ygl2a4e92tccmahrve6m34q5g +nomic10lgdszxem58cy6nvh4nkffd4t3f8vaa9vm9c7w +nomic124u9z0jp0l05krrke9ncny22g5znfkzvmdtt50 +nomic1tc04s3qm00fyhllzrm4e3lrdrhzx798xg9zum5 +nomic1s2v9s9uhgqcdnqex8mcslrvehaphv3emeh585n +nomic1zlsrllgaxgxahp43ur33dtdg0qs9ga45zr90kh +nomic1quvm9qndnqakcrv4n4sp08k2tn0jyu3ta4dvf0 +nomic1p4ks5aktxq48yqmpzh8e90z6suan8zwyfzz7jk +nomic1gkqqcg8qhl2h0re4cmz3mqqnm8e6999jd6wsjs +nomic1g6hp8n8mefwmg8x3fhg4zc33d68rgfp8fg3kyv +nomic1tjajx9c75kguhdl65masvyfrm8z2d48thrxszy +nomic1v7y8ma66z72pa82gxt30tkqqpx3dkwqgwgagjt +nomic1h4zvy6wupk9lf4v2yj87v8006yzuf0syf0awj2 +nomic15ncsssyks98mg4dpnv6wc7ljqqa74rxq23hv5y +nomic1we8y6ndpclggm4q8fxm4xe97ssjmuvtux457qj +nomic19q2mc4ajvaah2dv7zssusywggheyuhhszdvsjl +nomic1es4qps3rfeana39vtjxq4kcg0hwf8ezg77vnax +nomic10ulx4m2s2c6ddpdwpd2676frjfq9hcplnxfe7y +nomic1h4v8jxrwzex5yj6d49jm92a827sempjtzgz9uf +nomic17xns6wc65n37mdf6k8mqxunkc2exq6qx44klx2 +nomic1vasunpy8eyx29fd4pk9kvkl8je2hpfvyaez0zv +nomic1ckxphvpgsg5lf86e028dqmgxamn0m8lvcev2mq +nomic1tg9f7xd9e4fw66y2y8srzzxys940ys2xlkwnua +nomic1z9zyhgk59af064gaemclnf396gj9uep0r3trnl +nomic19mfm9aa5shp59agt675nwrl9lf8n3ldspswf5z +nomic1gkyaffl4t63lafgmquvygsanh9xh8d6jmt8gyq +nomic1lpku3pkrg0nwwv3u5p7dljn5tyg7x3ggr3ks2s +nomic16zs53whzuydl50pptd9cx8w5f22tfqa3ar78gs +nomic1477zhjwcyfezy3tye8qsd7x5yvywygn4npp606 +nomic1umgn2ytauy5kaxnyd84730rra3nuhl0jzne86v +nomic1d7ncx0jzh9wq3m9hkw44j5jf9fxl6xvywlyrxv +nomic1shxgw7dcm9grykl5cws9ekqr6qvas5v49274l4 +nomic1ssmeg0jhyr57kwjlt508lgz8jeqsfx8552wjpe +nomic14wumm87mhsckl6cagyppjpd0c2wgfxpcaajhvz +nomic1tp6fa7pfkpc6m8dyhwm8rx64h0ef8xmvjz0zne +nomic1t3ecu6khpws8jz4wuu770yqahvwnfrydczp43n +nomic1kyjhauz86gnqz93gvx82wwqruafqnsee90nha8 +nomic1w84t5g9wwhk00c7ut74tl9adzztqw64mh4gkfk +nomic145vxusnjvg5w3wclx4g8jnvpjy7sqy5xdmh2ke +nomic1yzpmk937nwum02dkpyr0wk3u8jdm9yw8hadkfs +nomic1sn2hpzc7d3jq74d5ctsp402qeqvjs4qxv2f0p4 +nomic1emaa7mwgpnpmc7yptm728ytp9quamsvu7aeu8k +nomic1ns2s5yppam6j7l5aezu9ns927g278tfvv6kg3z +nomic1fsdpx8k5kaktxhcx47gdgcnnslv3r9xkhe2rqf +nomic1pjv7c0vtjmyvqtfvq05qw3z3paepv7hldel3yf +nomic1y0t5g650jcn49v66ta4ueumkd6qwxp4qnerskz +nomic1xkc49nyne66dktdhzj46vkza4n5w2yalaaf5er +nomic10evcqqf458k9d7y9aw65xv3cpgqgadw7fqa7hd +nomic13s0hlxhp584rtl4kx3reshsjq9u42r8f0ync39 +nomic1s8nmy3khrydsuc2fr68dn9wfh0pf3x5yxvltc6 +nomic129fhjcakchhv8d4f6g5hs3vae0m4z3h3qa4yku +nomic1xajyrrg5jndz8gqhn6cvkkndhluzjpr4y7ftxr +nomic1ej5l4zz79shdxeklga6f7pf38lxvwtllwrh86z +nomic1uyum2hplfn9fauwaewnlyvqsk5asqge58nzjzh +nomic1myqxl874yh9dfpzmwzkrp394un4pzzgqq5lmv5 +nomic1xwm26sgjh66hjsq8c9py6wucl5re6mdz8cykx8 +nomic1e6zdjcj3wry34hns4pw9hvse7xcv9mmt6cp9ul +nomic1z5sq7suwta4xyztp6f0h42dtexajjdysy4k7qc +nomic1rcp29q3hpd246n6qak7jluqep4v006cdf5defx +nomic148r8afj23qx2ahd00hw503vjcf847q4kutjpag +nomic1xlykrvmztj07nkvw6aulkwahc2vyfqjrrx0swu +nomic180ua4mvj4serkttaas4skc3fcucpd7h3mg3n95 +nomic1dn4ksttedez0lzk9842un0v24xx04ppde87nkj +nomic13h4vazvsjkm0jzh7jtpf36f6kssg9mrhfswpcr +nomic1nhfc04w08j8fmd0rwu8hc6f92g7qq9zl0sxjgq +nomic1eqhexdtptfsgyz0m9efg8s8v5vcmsknxy8a5zy +nomic1mvc7vrpqctf8ezw4dylrmmy8d09fvlm2x8z2qc +nomic14h59xe0y8y8fgg3r9aycdfml043kksrmczuguf +nomic13ulcudmvpuuu0cpzcuz3ecvmg3r3q7hd9h5r7x +nomic14lsul82j5rtac70pn3emxu8sfrtjlfxevey8c5 +nomic177t27fsph9rejywmdh4d9s8eqlmv86hdd5gm22 +nomic1rcnqs00jrvzk6sgvn4xyar7c5dcmtct0c3s0zr +nomic16l78jd88t6phup7324wlcl0kgvvc9c8cjckkqt +nomic1vg984t5t4exemdwrka2sef2fskuwyx7u65nxa3 +nomic1zfcj782j2fydqjfagdnl0v7p95vm52wgx7r9qn +nomic1f4n4a3xyun8ntgk9skh50t2l884vfyejm5erls +nomic1ye0kh9z36dn0esfps070h6acg8s27kmqv07a03 +nomic1wtt690w8zryfljyncd4rpdavlajrmdxwks4738 +nomic16v25qy0suml5v2s5swvmj7pycd76dxmgqew3hm +nomic1fhzyvpkhnaxau2lza92476wdvpjz6jy8mfdefp +nomic16cttawml87zvpspfhh0zr5d4dyfpgd5arugs5x +nomic13xus6jynf067mc2req6z4gg7yupkxkfxlncl82 +nomic1nawucrwkqqwevn4nyllfk0r6csw0mkywtnl926 +nomic1r0mjrsjfprau9rwwxe04hkzfud696n3xuzz03x +nomic198avvj8r7dx5lp6gesuhhx5py99apc9kgmvgtn +nomic1zmk6sh6ahvg6wt0ckqvdxuszm77jdpk63fu96r +nomic1lfg492xhnde2dpxxmmaa23x52d8yywpgprvpek +nomic1xd7msw457czev06cawsm5h8hma8w5wrq87nl3v +nomic109kwf05m25zslkc442re3krjuhjhjcq85pw6y4 +nomic16l5jk2m9mkfhe862wyfx5dyz57vrf056s0kkr2 +nomic1e0kyfl3re078qzsjqugdpnc4lkdq4zvj0sntx2 +nomic17lqckr45zv3x6ajsfh98al76a963sz25cc0h0m +nomic18xhs7tmx833m36y7gvq9y4pqtymuu9xa534nzl +nomic15hz2v3mj08jhgjyxc3t0dzrv3k937nvfj8zrqu +nomic12tdulmvjmsmpaqrpshz0emu0h9sqz5x5cutch5 +nomic1kfngrld93jtymlrjftuh9zxk2h2vjcxn2j9l8p +nomic1jzqfg3rq8hdav6wfcmrdk5l47y8wdwxxazd8vn +nomic1dxy5vd2xe3s48hlwrpy9xeepqzn3jg9hed4zml +nomic1kugd5v2yeyufpr0s33nm86xe76ryjhzpf5p6k7 +nomic10j9a6a65alsu0c9h83l6l39kllkq84mze9edvd +nomic1fp37ep4m3eaa887zxt5z6wfg8nrm2td3jpk5kg +nomic1mcyg745pznjuwey33rpfw67fa40z5227nsunmr +nomic1slksud3yr6emzjwlf5hzdr5tqmc7y2pvp5ur0x +nomic1rg7xdsvszrh4nqpd7vs9hs2x9cs2xgq83qmnx5 +nomic1xtjnzwmf6gadsmw555tyl8dz05pcp9frgkcut6 +nomic1jth7dgcu9xk2stwg6l66lqd588lqqem2qe9zs8 +nomic1xueyy0ta7any5tmw9zntlgg8z50x95zw2f5sw8 +nomic1dv62904dr25e54k32unylyr7d4np3qy308ds53 +nomic1qf0kxkk60qrcj5qa7v7t439249qfkcd45evltq +nomic1w3vdm29dwgts66tx72cduvku2slhdytfhwpzcj +nomic1yup79md6y57k54vdmgsj4jcwmezufyc2ryarx7 +nomic1k3gu4prsv6uzk2alt8f8w3uhyayqem20e9lf92 +nomic1wgq590ngcfnc8vh78ufstsj3hc888zexqw3fnf +nomic1vuafuq42sh7xgjw6y2500yjlm58m3jrje9txta +nomic13k4p55ls5m6srku3z24njhcqj550hjpkx4crgl +nomic1w2thvet5hp3rssqts0kg4sjnk2kydrsr377hhd +nomic1uj2ny4pycvg6aj42fppmt7l6tkcpad8z9n0hmy +nomic1vd6nak22s0cs3nc3qpnkvr3m9gv96xnnph8xj0 +nomic1gnfqundmu8pzxh52g6ula38pdmghn6mmnyptwh +nomic1dc0333tdv650d5mgucfesm8z0rtdtc0kw7ad3a +nomic1rf5n4qh5ulmyhw02uuwlkptg90ucrmpzd0k6yz +nomic1kntuen5xjnhhtky9umnu5azy5emed7d8ydvyr6 +nomic1wke9k02smhpsa2mtaml6lr5hy27rgwzz22l0r6 +nomic16l5w8y5ch6jykxy8k2q6c90jt8pcn06g3ey853 +nomic1hzgn9g4anff68xlmkv6n22su56x20g7n2g948y +nomic1t9nd2wcgjxkw7mvgzm7z70vl6jf408u7ug73qv +nomic1gptyq7pqhvm2ws5zzlpvfrlulnypz2gdj2nh4z +nomic1qr20et89w8z85fjkelakvfx0d3t0nvqkcsull0 +nomic1pu0q2fq6s823u7kt3ljtgs8vt58kkrwgu6zh2z +nomic12pd6h5xd5gputhctkdxy9zatlpwuej0l270hdt +nomic1wt4rq0gcchm8ued9yzlrar59kfsmgr9gm2jd4x +nomic1vesgn48a8l7enm892pc4hqngtrl7ygx7dd3z4y +nomic148045k6x9f4wmmg84zqumckk5rs34rqar32t55 +nomic1ep2umj6kn34g2ttjalsc5r9w8pt7sv4xe6u6es +nomic1dlgurq4mnm96kdsnf66gmfd883ms056kv53p0q +nomic1yfqswayzce28rzqrw9z6gctv4nzwwkts4rzgp4 +nomic1uvqdyc8cs985r8qdkamz8df94lmrrahlxlsx52 +nomic1khc4837d2kcmrgta8hrcv2jymzgmt2l20l8a7g +nomic1r79uqglmvz6vqjhe65f0p3lhna4fc5k3fc5p8k +nomic1984ucd9z0k0920qzfznqaaktt4rajhx63ahh3w +nomic1ff78n2kt88m465enu080lnnqcg5x8c3zvqduhd +nomic1d4t34uad005mutw8c5klq5ktg9vxd8dmxsy3wy +nomic1a9l4dq6s44k7dk4lx0us6g7xsunartz8lgtf4m +nomic12juuftkgx92h38q4jr4xhpwka62luzh0hftps8 +nomic1dx32vuehztxu7a8zy29eruc6yd6xf69lnesj03 +nomic1lp43mmjg97gcg7n5a2tynd0q4hq5f5v9se4dw4 +nomic1vprfyt0vp9axdwrfd9p2570vxmg6rzuj7tgh5g +nomic17vv33gl7esrnulrhz943rrchs623g0aayjgy8s +nomic1ewrlwrchdhp05x98v7q8x2k83huuvgg8paqskt +nomic1mx26py964dy0rraylx9pz2wu3p7lv9j54x2gf3 +nomic1s9qddt4kgfzdt23zd30r0tg20wggeydr35jukn +nomic1vxvmljtx0eyt4uk8ywuasvx8j3l2e8llny2hwd +nomic1k25emq087mh24neaem4lksa36qn3cdg2e7870t +nomic1u8kdllz9p2ntk76shunsj7f46tuvnz8rxs5zlf +nomic18r457ws54pkrvurcakxufawxp3eedhffppcdpn +nomic1nllnffudccy2f6wrfv4djaadsvqsr2lay5xw4w +nomic1cr2m7cyeewszeu0mjgtsek0hpd04gzkxnfqud8 +nomic1tjwgngtl3ljpfg38n535a6akgtdyjanmmp559t +nomic12dhdxqkmegdfjku0zxkj32yt765jpf0kmvdfse +nomic146l37udxpsph626spp5cdz4fnnttyyqgseld2u +nomic1qwqe792ag6p0fg44nk3f2qcredn4lu6972nmrv +nomic1yxt425jn7rxgzagxlhv9l2yajkv6n5htyjkeg4 +nomic1erarlz2yk2wk74sm8v2x4cewuj8njwlaqjjjdj +nomic1qc60ztmn89hzn9w8zxd77m7lcpygcjdc7wshfe +nomic1f05udu6hhp59mj3e0lt2rnhyr0dmkkxlrthec8 +nomic1vz73yxk594xlxeveu7muafzkynejjcgr9smgla +nomic1gnx6wfuzrh8tgu29dwml03fda76fc2juhj8uz9 +nomic1mg9cn5cyrm440qmz58f2l85yt87eah5wpuwman +nomic1r5f9ruu0tc2tpdt2y6qfegkhtxdv4k2ugd380y +nomic1nkp5vkek6ses8ljqvqa0rxmzzer684fvcrysh3 +nomic196vjhefllcdvmpeyjezvctmve58ahenl5g9ms8 +nomic1jfrs6r5q9shj0w27ydm3gn86pa44fh9ar7j6vp +nomic14pseemx4yarq6lh67ew2mtp57ayqwj7t338qql +nomic13fq7e69punt6ju05f5wwr39udcmlvrlqzreru2 +nomic13jsv0utt6dl4fc7kypkm8hp7k3lc0q597genmh +nomic1fgwaqndwpl2hmk6vv98vt07fkefvx46w3xq7n9 +nomic15kzyw7at85juqlfc04pxfd02tj8y3aagdqslg7 +nomic1s9xp57kdmu7t54m7uf4wc4rx5hd5dwjx40mdzj +nomic1a8gx9m553deeajj8jcdlp37tgwqyy2c0s7wx5l +nomic19hyeze8tnvwx2tcd49g340zz8y0453fnr8d8er +nomic1sdpfga9e073kwx603fwpcnxjsg97knkpwnvvet +nomic18tye7mqdkz6cmfk6tcf6trzjexjvdjtn8g98sr +nomic1q429fu7xwrjy9uk78r9f96rh2qaqrjtgzw6gyw +nomic1urcmv4ge6n64f9xydw2crjjyml8ezzu63jvaas +nomic1p77ruksa0f954k46788vrrj02lqmavwt3udscx +nomic1whm46gnq5kcgytjx45tfuwh5pdart422lv24r9 +nomic18yk9lyud9vfckgzywfnsnvdajfsqaulvutgze0 +nomic1e9gyenmtlrusl9af67mfd9tpplckzmslk69prg +nomic1uqnlhtz3h6ppe6d0xcqsvgg2e7xjjn7ewc4nf8 +nomic18vygp7wghlwqqcctsldl9d7qd38nn5d7hm9jx6 +nomic1ytagpftcttkjt9y5g0e5e4eln03kjaglxylefu +nomic1v60nl7wzelzush0c0vqata60pjffc0rx9x4v6c +nomic150f75zqu82n7w785emdzz4xkngzlq4d0yv8vwg +nomic1pm47fmktjxgt2puwppn7tzfefk86cfursgk30n +nomic1gwwz25r3r2ve6eppdhlyj2dex6j28su7fu3lhg +nomic1e8g6555vsgsjrlyls057ut89d2n5lj97vj5s5a +nomic1l0r6vucw0yfsdqw2pv6hzwky2hzhwrdd3r0ts0 +nomic16qzy98c0kaenaduxrgkhvlrwv0uglv6dykn30r +nomic10vvtht8ycyup5sj2tz3m80dnet8hge6lvfa643 +nomic13snvtmj26n6jyt79etf4vejezuqk8v0dr7eef0 +nomic1ggcxyngdy2zk5ef3spxkyk0lavfxx4yhvtngdv +nomic1j75fm3w9rhsgsyllz3c0k34k8fpkamp89420l8 +nomic15d6q4u635cct3acu0t6wqenz4r9k2459jetyef +nomic1auaffqw8enc5ru9arlqxj6c8ceksvq20ffa6nr +nomic1qj7nm3gxxypwqp5lvrjg27jc7tlhlys7cfp032 +nomic19jkrdeqz03vvnz6q0xdan0ss8drvsxj58zs6gk +nomic1x65ng38pytnkkjnqpz7y052cpfplzuazngm24m +nomic1s5f9ezcqj6euemwxt2d66cefj2yrl76gj2l24y +nomic1x70x96vvtcl0zqauujhgzq3xwpukpexwkntm4u +nomic172tzm9vrwk4x7ux49qfj9ratczy3gxmt4gp0zc +nomic12rt6naat9m4g7lr8y6lhv229uk5jpvttehwj0q +nomic1r09gkqcv7957tztarzel87765ku280nvz5jqec +nomic15lql6fqv5kl2lc2rdnc94432yjgpwdgquw5uad +nomic127t0x9gsceejkuam4k8wm39q6mrz2yqx70jcpv +nomic1ud7vjhjwl03ytfamqz56q4sqh22yqd7qp6u8lp +nomic1dd3xne5h4tup838wun6tra4ezq92rncpu0k3tc +nomic1axfdqs9ppn7xe6jutt327pwxguqvzpyjrv75ht +nomic1jatwu3s7aahwyneklzn04rej5spr50ypf77nc2 +nomic17gttancyft8fzvdm2rywcnehvnllj6xsxfr6pu +nomic1hasj5mqt2qf2q79397h73mzdtgg6n6968ly792 +nomic1e69n6znf95ru98ydn8f5qm3qw3n7kljtcj9p59 +nomic1vu7v4k459550rmynqjlf9wvhj95989j8qjj3kg +nomic1vcs68xf2tnqes5tg0khr0vyevm40ff6z8vd24z +nomic1ztdzqrhuv945xxjqa6af27shdaehzr2rwdeatd +nomic1hkthq04278pj5cqt7tsle4shs2hhlee4valze3 +nomic13z4p8e65ptz2k5kj7v8jxnhl3j0jx4xh9zxvrg +nomic158ddh954pzt3etjh0yqe8lp7ax0pz6pcqt3jnw +nomic1kj4efnuuse7mgqfunxs7lfu49uggvjn4ccrkrm +nomic1d0hk2gflp7hsejy4t2a750g34w2m9nelu60kll +nomic17vz8hvg96lddwawdfygvu89ua4v7qgd64jm0xu +nomic143tw0kj2gtffwgmkr489kwh3fw4pkud0lwrmsg +nomic1f9r4xgc5xpwq654hrm9jf5q7uj589mltueflzx +nomic18ucy57v5afeugpp8as4yve3sckel2gv70tx66w +nomic15jc2hdsyc4glj3kaet3k40lhrqxe7gqx4rqula +nomic1q4fxpajzfz64lm93vr7tg5g0752hhmgefq8rlp +nomic1gq6pd9q8px97720arytdngc7zhyrxp4xfmmful +nomic1834glp9yf9f6sd5rk0hvtryjj0uj6cgc0ur4ht +nomic1v2wmsgvu3c7ss3altqqrxhsen8lwenttuwukm6 +nomic1ykqfsmrw0uk4fcnycpp60a0cdg0xlsmcn82ens +nomic1xgp5cuqjyrdtrysfsqzu0ektndha72pup6rcj3 +nomic1tg95ja5ahtsf6dzpwzahxuj2gkfgllms878g04 +nomic1k49luuv6a09542hxyz7e964zz46ka5jtm7tdgj +nomic13gjhk3pmmusvdrsgqwdc74fcafdmvex0rk7w5c +nomic1njusvz6kcg2844cpuetke5yghjrp57uy7hlzgz +nomic160sa9dv06t8nvaw9gnq4h54dq93l90vv3yhrds +nomic1n8gqw8jdh73r7w6nuvr0wy6javsjgwt32sht0m +nomic14ghs6hs8xkl9racufmqnvmg4l0n7unhpv4q8cp +nomic1uqc6lydtafdvujp55crljygndxgl573z3nsn4j +nomic1y573wwtlw47tj0flkwhphhgrpufgptxfvgyy3q +nomic18ycy3jwflq8g3zkmsmw9nx5jjth0uhwcdr8n03 +nomic1temvcezkp2f5u42u2f69ra8k85c5p8n35nh5g6 +nomic13u5y9vkaplwzl4qyj9y855wjwp4krta99wqkl4 +nomic1y7tc6g66ewgkux44u5htnyje59p4mnj2xutg4d +nomic1wnnq8zw5s4elhnl6znyza82q73x7w8g3mu9xd3 +nomic17um7sz9ap29vtkn0xz8ll38qcq8jhrufz5wffm +nomic1laqefwck8mkxt44jfn7fnpynfv9f2utyjv82yw +nomic1hv9zsqrezf7pwu7pnx3vkl2etud5np7hpqywvg +nomic1mmfl8uz5ff008rr7v76nts8wunsw0nu20eezkg +nomic1xwkfpa23rvjjqv993pcezrepgyta235yc82gg6 +nomic16facdx50eramsgdkd2h8eywjqyllmp6qvxdcz9 +nomic1suvlzxf5057p5tlu9636ysy02t6v38e2lg4qwh +nomic1wx33kqfj0zs3kpsu90resx5e7zn9v5kh555y44 +nomic1n8j9xve22sh5arf2kfdtdde46udztadatcr5aj +nomic1aq4j6gz0tcj039nn74pdfefgksnqlld0dhvvyr +nomic1m8rwaup0774h3pj0wrlk53cwd44jrx6nyqpkm7 +nomic1f62zgjhla097yc4e9sf5zm64antugnjh5vhsnp +nomic1226q9glnrx4vvkk68050l82dazcpk4uvgsm9t9 +nomic1vm7zakramzn96h6zrtr3z7cuhus5e0lj9f3nzg +nomic1eduu6rk03m7tqthj4weuvwqmwjxmh52wchqumm +nomic189n8jcs42t56rzs7cur9wtz9pfz3sxacvv6zn0 +nomic15sxd33p67wyn37zz5yn0jpheeq8kkdnvxkusru +nomic1zh3atlxnu9q0nvsz6yldjl3n76j7wha74dzvj8 +nomic1gwtqpgfvyx8kz9a9zqmrze0tyt8ls5a0x57h8j +nomic12pgtk90nlrzqftdl2w9kewe6rrkzaszk7m9k7r +nomic1ryu2zpqjyf6zd6cxhlcszrg4ykt5lk2aupx3gz +nomic18wg80p26wzjwdggclux0mzeetdapfhjctw37em +nomic1q5r883azzh0n7v377h6ehv87y7xm5yldl0xn5y +nomic1wz69rcq9qdnksdryma0caxsktt272hlguqvrqf +nomic1qfucy7548g479yzuf5j3qkge20az6t4q8c0psg +nomic1kxykphkk82x4pk5nzq2kq5f2r6n69k73x6egwu +nomic1yp95ns7exf4l9jgh4rm58lmk3s6j80zyj7nkgq +nomic1fnckkce3e5ddwz5nw52sk5k8q33x8rvx3fqs3d +nomic1mm8huzhpk5tx5vgj877zse37c2zdymzlls635p +nomic15n4sgr79uddm6r98hes4ah767h62satgqunngm +nomic1nphed9yccwkpaqzn2ra8r7pvaws8zd9twe9ezg +nomic19qc25l2nwztml9nvhqpg7y55420uvg59cys0ex +nomic1hd2evedvt9tggmalwfj3emvd67ln7u5pppuazm +nomic1efsj9hrsuhcu6lmamm544n7syfn58kd6nw39nd +nomic1jxajys5atelv6afuxrjw8afxtyhyducz47nyta +nomic12dnv539p9umh6ze2jpn8n57frlsads3dxu0g39 +nomic14tdg37jf4x0vkdwjszs5npd0gxndew5mafpfev +nomic1c2w7sxnp423935c47zwv32rgmk2zmgt807syk7 +nomic1vmmlphwck04khtwj69ghuewux5hrmvwwjsnru3 +nomic1epmlgyve8nu6ag4xldnegj3gaqpa6tw7eew7mj +nomic1treczrfhsjdvlfvcgldt7d94wj4vhk3r7f8r05 +nomic1s24ht39ea9pquwa2ry3zwd4ahlq5zlj5aswv3f +nomic1fgnfg2gnxhkmcc8tgpph6jm6xvn236jellq23k +nomic1xt77j9lkg63zxr4wk70paaf3gghwsu4r5ls2e4 +nomic13cpt0uc3qy8da9shcl8u4sm9v0ggmn6uxzmtqr +nomic1z7qvrdv3dym46rdz52gyzeygqemjwc68ue9tyc +nomic1e9jlmhjnhv0z5wj64gz0dwn6q523xyxe6t2l72 +nomic1w0n9kqgxqcqxv7yv49tkp3e8ujrzrlmgguclfk +nomic1xppn98w0gg6wl0q2g2nasmkqlf2elwpkrx6z8w +nomic1cy7jye9jkg6k4h9wcurdcx7q4ld03m48gfg7zk +nomic1dwzxaessw2fpvfzyh4wp7kgmgcfgeqthw9jpr0 +nomic1pvwussxtdv2m2cutv8atgpy40e7g947un94ls7 +nomic1u2wpyuem4tuj22tajan9cjn5npcq8syvzv5k05 +nomic1pjmngrwcsatsuyy8m3qrunaun67sr9x7mcy9lf +nomic1wqx8gt8tsn05eanmwfl6qjr4np2mgeyhg3008a +nomic1wtx87w2c8pf965t67e8wxzherzap2d55rytuf8 +nomic1z2uecn5khjexks0reldjjfm5a9ssj6zvewy8nz +nomic1r88z055j3m73r545tq8mjsjqs9znzyp8fr48u6 +nomic1f40g9lqmxlm90nwtwdlmvk2x0vl00z8q96xmc6 +nomic1t0wc9j6jsut6g4chhzxp5ledqd3wx53tde2lh2 +nomic1apvsay7qcqx6mrh7d4acva0y3chf445rctfrjl +nomic174yq7s0u59wjwsrvv428cwa2cp8ygdu9nllwjs +nomic1vuseuysmdmvfwcngkk489jypugwtcq0n0npae6 +nomic1grdda4v6n5wddmcrea2mm0vl4f3wvpxjca8543 +nomic1msga35xat6cxa3ajfpurq0slcng0pxws8rxau5 +nomic1xwdjn7tjjp29l05w0lzjpdfp5m3m3hfuel77w5 +nomic1nxd64cd6nujsnhkms7v9rahu97c2rd36azeqy8 +nomic1hq8tlgq0kqz9e56532zghdhz7g8gtjymeut2um +nomic19vqjj6a4wcsnd82v50y9payde726f5kea0j3dd +nomic1utn6ut2adkyxy2mx5mknmwf87tm3k02srzq63v +nomic14x8f347h4jvl9574fzl4v7z8etys4jsjrmthtt +nomic1cn7fqru45dejr696jxutys997nlxk6909wphee +nomic1xlcjd5vhgnvr9xmn8kqsut966zt0a5p87ahn0s +nomic1yg93sten48lv682wkqg3jlhzee5wxwft55c0ht +nomic1m9dwd037y7ma059xsnzwey92xk3v8jmyq5xfaz +nomic168w4jva5kfrqngu63ev0tmx6wg5k5y9tn93e7g +nomic17y6m4vrtj7xn5f6eh8d350xkwhuymak8nuas63 +nomic1f4wluqxm0rk3hudga7s360eg5dtsgaczh8zkps +nomic1rp2flwax08v7cdy5wxmth8yjagfctsfwl6amrl +nomic12f8l3ll04rt643aw4ddnned67h5yga5tvcdv2z +nomic1200zz4f9r8dqsqtuuhew3u2xwtmaca9fenc7rq +nomic1lgu66ly24wz0x95hkhuzny754hfm9pkuvrhvnq +nomic1df7x3xg4ynhlz6xtx40g0mhvnr2l0sjse887x6 +nomic1qkzqdx4l2r6gf0nmw3n0jmv2dust2kc4hs8ewj +nomic1vxt2ljvquqjw3g34ttnjzl746rqkktfwdlhs8g +nomic19gk75r4pd0e6hzz60nqgg3nps5xh980nskewcg +nomic13zs0yntzdswanglzutk89zad74dwc4v8tdcq29 +nomic1phekwx93vtlk8yjqvvnppzgkfd9tt7e82re4gs +nomic1tx5fu2d7vdyjn9jt7ppm9447n5xzj7m02cfv4h +nomic1mergdp6r8c0xe49fz5k2ekyuvqrjzxyljzhjl5 +nomic13gu73wcxa084n74fhxdgxfv3z8qe5h6e0vccm2 +nomic1v3um4h8ljp26frtjczzd0jse8gqhr82vjdv3xr +nomic18nl28k25u5qtwga7qzgd03ee8nqfzqypvwq2fw +nomic1dk7wguun50stqv7t86t5urat0r7cv9qtvx6awn +nomic1lcvgw8s9uqvtjnem8h4txqhpvj5evdgdz6ythy +nomic1usp9zktlfkqlalyf90evhnnqqwec6dlq6jxv2l +nomic1sn9q36shl7zlyw4q7q8cvs88pc4v3trvh49us0 +nomic1493he8w6gp6ku6mgkj9ujx95653n9uytjvz0zn +nomic1z35x9dzrsgc0fzg2j3dp35jtjr0ytd445w3p7j +nomic10hc0ylp6t0fmwpyga2zc6zj5qcf3ed0ng9vkf9 +nomic17lz2jzhfrzmk62u44p3rr6dgd2ayfuc09z0g0h +nomic1qnfppzd4hjvyge0h740ftwvugjkakwafpv6qjt +nomic1uhryuw296lqgaz3j22mhc8aym0vegrev25gqtx +nomic1t8cdk3gx6nrq0tn7r5e55ry9mdmgcm4vyg0jhx +nomic1psut3wswfp0ft683g78u2ymea4w9kcne737e9f +nomic1d6tz0gxxqjj2kvff58sa9cs0c3uuuay99rhte5 +nomic14c4zp75ywy3c988d9djuxevd2ajsyk0sd0cms6 +nomic1pvcm3nx4qtuljps2uu6c7teaqmzr9jvl3ez7ma +nomic12rxqu8kjg6j294537a6jw7tgvcv7m07qajwv72 +nomic1kvh6nggq5uyz85qvf92hftstl96dxfmue8z4fa +nomic1smy3rgl47tdveps0c52ecj3e58j09ukgusexrg +nomic15rzj3pas9rmsnr9zevxq845s3cyh2j3yeennng +nomic17p4dcxd8lverdp3kx2ejy8asntkcc00j37x27a +nomic1p43srkxlpaqa6nn3udr43r5a34cuj5vfxpzzh4 +nomic1zzq5fulfm6k88x42g4fqncxurqk36qlcqfl55r +nomic1vgy0nv3rx5l0z5ggn09yffkzc9fhm2haqdw90r +nomic1hrfxk25qfuq6a8e9h3hs07m7g2zjhsf3c23mzx +nomic1f5dq8sdeey47wvwl6kycwrcmw8fx347s726gda +nomic1m37dqvw9atrfxv5t8y6pjldypn2mr7dpyydgvf +nomic1zs25dsdjel37rlw66lqxwmq4ntcwd65mf4wdg7 +nomic1u9ftquz3vqacz68pjp9qcmqzse5s8n84vrvm0a +nomic14pg68dky8ry0qfrg8vkmdvz8zyhxvctrm3hkz6 +nomic1nd7t7xmgk99y0we7semezataneuxz0mdasuwfp +nomic12e92d84r0nrpzr3wpqnd3kce7lnqdwtx7xkt64 +nomic1qrgnl5w0ll3apm2txlnj34eyfs2256t5z4g0rj +nomic1sgcsksdehak35fqtmypz0fzfkyuryq7fl9dfk2 +nomic1qkhk6n7k2kapkl298rqq0m7n6k6fl3yrky5wwv +nomic1tvm9ls2ynxykfffqgh9ppefc06qshaean4m6g9 +nomic1d5n325zrf4elfu0heqd59gna5j6xyunhev23cj +nomic1h22vm6ggnwha77mradt5aagzngq62zsjyzst2l +nomic1xlwdqt84cnarutlw2kzr7pmutamza3cxcyjcta +nomic1qk9kqrz209chxf86yjy6emhvrvqzxn8vtgulhc +nomic1lxynnpg873fx3ftp5zn3ues98zrwgwndesadtl +nomic186xfxt5u9paadc58825s5dsh6u9v6hjr5we5p7 +nomic1wyc5tqkk92hpg6paut0w2tdad4ychv6fhz0wdy +nomic18x5yhxzjwqspsyvc9dhnpude7e2r8res9p258r +nomic14z79y3yrghqx493mwgcj0qd2udy6lm26lmduah diff --git a/tests/bitcoin.rs b/tests/bitcoin.rs index 37ccdd6c..75dc84d7 100644 --- a/tests/bitcoin.rs +++ b/tests/bitcoin.rs @@ -21,7 +21,7 @@ use nomic::bitcoin::header_queue::Config as HeaderQueueConfig; use nomic::bitcoin::relayer::DepositAddress; use nomic::bitcoin::relayer::Relayer; use nomic::bitcoin::signer::Signer; -use nomic::bitcoin::threshold_sig::VersionedPubkey; +use nomic::bitcoin::threshold_sig::Pubkey; use nomic::bitcoin::Config as BitcoinConfig; use nomic::error::{Error, Result}; use nomic::utils::*; @@ -298,6 +298,7 @@ async fn bitcoin_test() { vec![slashable_signer_xpriv], 0.1, 1.0, + 0, None, || { let wallet = DerivedKey::from_secret_key(privkey); @@ -465,6 +466,14 @@ async fn bitcoin_test() { .await .unwrap(); + app_client() + .with_wallet(funded_accounts[0].wallet.clone()) + .call( + move |app| build_call!(app.accounts.take_as_funding((MIN_FEE).into())), + move |app| build_call!(app.bitcoin.transfer_to_fee_pool(8000000000.into())), + ) + .await?; + btc_client .generate_to_address(4, &async_wallet_address) .await @@ -485,7 +494,7 @@ async fn bitcoin_test() { .unwrap(); assert!(signer_jailed); - let expected_balance = 989989871600000; + let expected_balance = 989981871600000; let balance = poll_for_updated_balance(funded_accounts[0].address, expected_balance).await; assert_eq!(balance, Amount::from(expected_balance)); @@ -532,7 +541,7 @@ async fn bitcoin_test() { } } } - assert_eq!(signatory_balance, 49986239); + assert_eq!(signatory_balance, 49994239); let funded_account_balances: Vec<_> = funded_accounts .iter() @@ -547,7 +556,7 @@ async fn bitcoin_test() { }) .collect(); - let expected_account_balances: Vec = vec![989988029, 0, 0, 0]; + let expected_account_balances: Vec = vec![989980029, 0, 0, 0]; assert_eq!(funded_account_balances, expected_account_balances); for (i, account) in funded_accounts[0..1].iter().enumerate() { @@ -744,6 +753,7 @@ async fn signing_completed_checkpoint_test() { vec![xpriv], 0.1, 1.0, + 0, None, || { let wallet = DerivedKey::from_secret_key(privkey); @@ -771,6 +781,7 @@ async fn signing_completed_checkpoint_test() { vec![xpriv], 0.1, 1.0, + 0, None, move || { let wallet = DerivedKey::from_secret_key(privkey); @@ -1214,6 +1225,7 @@ async fn signer_key_updating() { vec![xpriv], 0.1, 1.0, + 0, None, client_provider, None, @@ -1297,7 +1309,7 @@ async fn signer_key_updating() { assert_eq!( completed_checkpoint_0_pubkey, - VersionedPubkey::from(derived_public_key_0) + Pubkey::from(derived_public_key_0) ); let building_checkpoint_1_pubkey = app_client() @@ -1319,7 +1331,7 @@ async fn signer_key_updating() { assert_eq!( building_checkpoint_1_pubkey, - VersionedPubkey::from(derived_public_key_1) + Pubkey::from(derived_public_key_1) ); tx.send(Some(())).await.unwrap(); @@ -1351,6 +1363,7 @@ async fn signer_key_updating() { vec![new_xpriv, xpriv], 0.1, 1.0, + 0, None, client_provider, None, @@ -1389,7 +1402,7 @@ async fn signer_key_updating() { assert_eq!( completed_checkpoint_1_pubkey, - VersionedPubkey::from(derived_public_key_1) + Pubkey::from(derived_public_key_1) ); let building_checkpoint_2_pubkey = app_client() @@ -1411,7 +1424,7 @@ async fn signer_key_updating() { assert_eq!( building_checkpoint_2_pubkey, - VersionedPubkey::from(derived_public_key_2) + Pubkey::from(derived_public_key_2) ); deposit_bitcoin( @@ -1442,7 +1455,7 @@ async fn signer_key_updating() { assert_eq!( completed_checkpoint_2_pubkey, - VersionedPubkey::from(derived_public_key_2) + Pubkey::from(derived_public_key_2) ); Err::<(), Error>(Error::Test("Test completed successfully".to_string()))