depolymerization

wire gateway for Bitcoin/Ethereum
Log | Files | Refs | Submodules | README | LICENSE

commit 44779a35dd9872847e32ad31f0143787ae02bbce
parent 2885b53d08fabeaaf594c55a67a5c3f9596088b1
Author: Antoine A <>
Date:   Fri,  4 Jul 2025 11:43:01 +0200

nexus: update to geth 1.14

Diffstat:
MCargo.lock | 59++++-------------------------------------------------------
Mdepolymerizer-bitcoin/src/api.rs | 13++++++++++---
Mdepolymerizer-ethereum/src/api.rs | 16+++++++++++-----
Mdepolymerizer-ethereum/src/lib.rs | 18+++++++++++++-----
Mdepolymerizer-ethereum/src/loops/worker.rs | 4++--
Mdepolymerizer-ethereum/src/rpc.rs | 26++------------------------
Minstrumentation/Cargo.toml | 9+--------
Minstrumentation/src/btc.rs | 5++++-
Minstrumentation/src/eth.rs | 341++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Minstrumentation/src/main.rs | 14++++----------
Minstrumentation/src/utils.rs | 2+-
Mscript/prepare.sh | 2+-
12 files changed, 251 insertions(+), 258 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -402,26 +402,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] -name = "clap_mangen" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc33c849748320656a90832f54a5eeecaa598e92557fb5dedebc3355746d31e4" -dependencies = [ - "clap", - "roff", -] - -[[package]] -name = "color-backtrace" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2123a5984bd52ca861c66f66a9ab9883b27115c607f801f86c1bc2a84eb69f0f" -dependencies = [ - "backtrace", - "termcolor", -] - -[[package]] name = "colorchoice" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1475,9 +1455,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.12" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4adb2ee6ad319a912210a36e56e3623555817bcc877a7e6e8802d1d69c4d8056" +checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd" dependencies = [ "console", "portable-atomic", @@ -1493,8 +1473,6 @@ dependencies = [ "anyhow", "bitcoin", "clap", - "clap_mangen", - "color-backtrace", "common", "const-hex", "depolymerizer-bitcoin", @@ -1504,7 +1482,6 @@ dependencies = [ "indicatif", "owo-colors", "rust-ini", - "signal-child", "taler-api", "taler-common", "tempfile", @@ -2267,12 +2244,6 @@ dependencies = [ ] [[package]] -name = "roff" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" - -[[package]] name = "rsa" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2294,13 +2265,12 @@ dependencies = [ [[package]] name = "rust-ini" -version = "0.21.1" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f" +checksum = "e7295b7ce3bf4806b419dc3420745998b447178b7005e2011947b38fc5aa6791" dependencies = [ "cfg-if", "ordered-multimap", - "trim-in-place", ] [[package]] @@ -2560,12 +2530,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] -name = "signal-child" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3184fa464a0128cbcc353100ae752a848bc0067dd5715a50550f31570051150" - -[[package]] name = "signal-hook-registry" version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2971,15 +2935,6 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] name = "thiserror" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -3256,12 +3211,6 @@ dependencies = [ ] [[package]] -name = "trim-in-place" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" - -[[package]] name = "typenum" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/depolymerizer-bitcoin/src/api.rs b/depolymerizer-bitcoin/src/api.rs @@ -29,6 +29,7 @@ use axum::{ response::{IntoResponse as _, Response}, }; use bitcoin::address::NetworkUnchecked; +use common::reconnect::client_jitter; use sqlx::{ PgPool, QueryBuilder, Row, postgres::{PgListener, PgRow}, @@ -39,6 +40,7 @@ use taler_api::{ error::{ApiResult, failure, failure_status, not_implemented}, }; use taler_common::{ + ExpoBackoffDecorr, api_params::{History, Page}, api_wire::{ AddIncomingRequest, AddIncomingResponse, AddKycauthRequest, AddKycauthResponse, @@ -382,7 +384,11 @@ pub async fn status_middleware( /// Listen to backend status change async fn status_watcher(state: Arc<ServerState>) { - async fn inner(state: &ServerState) -> Result<(), sqlx::error::Error> { + let mut jitter = client_jitter(); + async fn inner( + state: &ServerState, + jitter: &mut ExpoBackoffDecorr, + ) -> Result<(), sqlx::error::Error> { let mut listener = PgListener::connect_with(&state.pool).await?; listener.listen("status").await?; loop { @@ -395,14 +401,15 @@ async fn status_watcher(state: Arc<ServerState>) { state.status.store(status[0] == 1, Ordering::SeqCst); // Wait for next notification listener.recv().await?; + jitter.reset(); } } loop { - if let Err(err) = inner(&state).await { + if let Err(err) = inner(&state, &mut jitter).await { error!("status-watcher: {}", err); // TODO better sleep - sleep(Duration::from_secs(5)).await; + sleep(Duration::from_secs(jitter.next() as u64)).await; } } } diff --git a/depolymerizer-ethereum/src/api.rs b/depolymerizer-ethereum/src/api.rs @@ -28,6 +28,7 @@ use axum::{ middleware::Next, response::{IntoResponse as _, Response}, }; +use common::reconnect::client_jitter; use sqlx::{ PgPool, QueryBuilder, Row, postgres::{PgListener, PgRow}, @@ -38,6 +39,7 @@ use taler_api::{ error::{ApiResult, failure, failure_status, not_implemented}, }; use taler_common::{ + ExpoBackoffDecorr, api_params::{History, Page}, api_wire::{ AddIncomingRequest, AddIncomingResponse, AddKycauthRequest, AddKycauthResponse, @@ -145,7 +147,6 @@ impl WireGateway for ServerState { wtid: r.try_get_base32("wtid")?, credit_account: sql_payto(&r, "credit_acc", "credit_name")?, }; - dbg!(&prev.credit_account, &req.credit_account); if prev == req { // Idempotence return Ok(TransferResponse { @@ -350,7 +351,7 @@ impl WireGateway for ServerState { async fn add_incoming_kyc(&self, _req: AddKycauthRequest) -> ApiResult<AddKycauthResponse> { Err(not_implemented( - "depolymerizer-bitcoin does not supports KYC", + "depolymerizer-ethereum does not supports KYC", )) } @@ -378,7 +379,11 @@ pub async fn status_middleware( /// Listen to backend status change async fn status_watcher(state: Arc<ServerState>) { - async fn inner(state: &ServerState) -> Result<(), sqlx::error::Error> { + let mut jitter = client_jitter(); + async fn inner( + state: &ServerState, + jitter: &mut ExpoBackoffDecorr, + ) -> Result<(), sqlx::error::Error> { let mut listener = PgListener::connect_with(&state.pool).await?; listener.listen("status").await?; loop { @@ -391,14 +396,15 @@ async fn status_watcher(state: Arc<ServerState>) { state.status.store(status[0] == 1, Ordering::SeqCst); // Wait for next notification listener.recv().await?; + jitter.reset(); } } loop { - if let Err(err) = inner(&state).await { + if let Err(err) = inner(&state, &mut jitter).await { error!("status-watcher: {}", err); // TODO better sleep - sleep(Duration::from_secs(5)).await; + sleep(Duration::from_secs(jitter.next() as u64)).await; } } } diff --git a/depolymerizer-ethereum/src/lib.rs b/depolymerizer-ethereum/src/lib.rs @@ -136,19 +136,25 @@ pub trait RpcExtended: RpcClient { // Move until tip height while chain_cursor.number.unwrap() != state.tip_height { txs.extend(match_tx(chain_cursor.transactions, confirmation)); - chain_cursor = self.block(&chain_cursor.parent_hash)?.unwrap(); + chain_cursor = self + .block(&chain_cursor.parent_hash)? + .expect("broken blockchain"); confirmation += 1; } // Check if fork if chain_cursor.hash.unwrap() != state.tip_hash { - let mut fork_cursor = self.block(&state.tip_hash)?.unwrap(); + let mut fork_cursor = self.block(&state.tip_hash)?.expect("broken blockchain"); // Move until found common parent while fork_cursor.hash != chain_cursor.hash { txs.extend(match_tx(chain_cursor.transactions, confirmation)); removed.extend(match_tx(fork_cursor.transactions, confirmation)); - chain_cursor = self.block(&chain_cursor.parent_hash)?.unwrap(); - fork_cursor = self.block(&fork_cursor.parent_hash)?.unwrap(); + chain_cursor = self + .block(&chain_cursor.parent_hash)? + .expect("broken blockchain"); + fork_cursor = self + .block(&fork_cursor.parent_hash)? + .expect("broken blockchain"); confirmation += 1; fork_len += 1; } @@ -157,7 +163,9 @@ pub trait RpcExtended: RpcClient { // Move until last conf while chain_cursor.number.unwrap() > state.conf_height { txs.extend(match_tx(chain_cursor.transactions, confirmation)); - chain_cursor = self.block(&chain_cursor.parent_hash)?.unwrap(); + chain_cursor = self + .block(&chain_cursor.parent_hash)? + .expect("broken blockchain"); confirmation += 1; } diff --git a/depolymerizer-ethereum/src/loops/worker.rs b/depolymerizer-ethereum/src/loops/worker.rs @@ -189,7 +189,7 @@ fn sync_chain( Ok(true) } -/// Sync database with removed transactions, return false if bitcoin backing is compromised +/// Sync database with removed transactions, return false if ethereum backing is compromised fn sync_chain_removed( txs: &[SyncTransaction], removed: &[SyncTransaction], @@ -200,7 +200,7 @@ fn sync_chain_removed( // A removed incoming transaction is a correctness issues in only two cases: // - it is a confirmed credit registered in the database // - it is an invalid transactions already bounced - // Those two cases can compromise bitcoin backing + // Those two cases can compromise ethereum backing // Removed outgoing transactions will be retried automatically by the node let mut blocking_credit = Vec::new(); diff --git a/depolymerizer-ethereum/src/rpc.rs b/depolymerizer-ethereum/src/rpc.rs @@ -20,7 +20,7 @@ //! make our code more compatible with future deprecation use common::url::Url; -use ethereum_types::{Address, H160, H256, U64, U256}; +use ethereum_types::{Address, H256, U64, U256}; use serde::de::DeserializeOwned; use std::{ fmt::Debug, @@ -359,7 +359,7 @@ pub trait RpcClient { self.call("eth_getBalance", &(addr, "pending")) } - /// Get pending account balance + /// Get current chain height fn height(&mut self) -> Result<U64> { self.call("eth_blockNumber", &EMPTY) } @@ -381,28 +381,6 @@ pub trait RpcClient { self.call("eth_sendTransaction", &[req]) } - /* ----- Miner ----- */ - - fn miner_set_etherbase(&mut self, addr: &H160) -> Result<bool> { - self.call("miner_setEtherbase", &[addr]) - } - - /// Start mining - fn miner_start(&mut self) -> Result<()> { - match self.call("miner_start", &EMPTY) { - Err(Error::Null) => Ok(()), - i => i, - } - } - - /// Stop mining - fn miner_stop(&mut self) -> Result<()> { - match self.call("miner_stop", &EMPTY) { - Err(Error::Null) => Ok(()), - i => i, - } - } - /* ----- Peer management ----- */ fn export_chain(&mut self, path: &str) -> Result<bool> { diff --git a/instrumentation/Cargo.toml b/instrumentation/Cargo.toml @@ -26,18 +26,11 @@ tempfile = "3.3.0" fastrand = "2.0.1" # terminal color owo-colors = "4.0.0" -# Better backtrace -color-backtrace = "0.7.0" -# Send signal to child processes -signal-child = "1.0.5" # Edit toml files rust-ini = "0.21.0" # Progress reporting -indicatif = "0.17.7" +indicatif = "0.18.0" thread-local-panic-hook = "0.1.0" taler-common.workspace = true taler-api.workspace = true anyhow.workspace = true - -[build-dependencies] -clap_mangen = "0.2.14" diff --git a/instrumentation/src/btc.rs b/instrumentation/src/btc.rs @@ -670,7 +670,10 @@ pub fn lifetime(ctx: TestCtx) { ctx.next_block(); } // End down - retry(|| !ctx.gateway_running(), "server not running"); + retry( + || !ctx.wire_running() && !ctx.gateway_running(), + "both down", + ); } /// Check the capacity of wire-gateway and btc-wire to recover from database and node loss diff --git a/instrumentation/src/eth.rs b/instrumentation/src/eth.rs @@ -16,8 +16,8 @@ use std::{ ops::{Deref, DerefMut}, - path::Path, - thread::sleep, + path::{Path, PathBuf}, + sync::LazyLock, time::Duration, }; @@ -40,9 +40,11 @@ use taler_common::config::Config; use crate::utils::{ ChildGuard, TalerCtx, TestCtx, check_incoming, check_outgoing, cmd_out, cmd_redirect, - cmd_redirect_ok, patch_config, print_now, retry, retry_opt, transfer, unused_port, + cmd_redirect_ok, patch_config, print_now, retry, retry_opt, transfer, }; +const NETWORK_FEE: LazyLock<U256> = LazyLock::new(|| U256::from(166u32)); + fn wait_for_pending(rpc: &mut Rpc) { print_now("Wait for pending transactions mining:"); let mut rpc = rpc.subscribe_new_head().unwrap(); @@ -221,6 +223,7 @@ struct EthCtx { serve_cfg: ServeCfg, ctx: TalerCtx, passwd: String, + pswd_path: PathBuf, } impl Deref for EthCtx { @@ -279,41 +282,91 @@ impl EthCtx { addrs.next().unwrap(), addrs.next().unwrap(), ); - let genesis = format!( - "{{ - \"config\": {{ - \"chainId\": 42, - \"homesteadBlock\": 0, - \"eip150Block\": 0, - \"eip155Block\": 0, - \"eip158Block\": 0, - \"byzantiumBlock\": 0, - \"constantinopleBlock\": 0, - \"petersburgBlock\": 0, - \"istanbulBlock\": 0, - \"berlinBlock\": 0, - \"londonBlock:\": 0, - \"clique\": {{ - \"period\": 1 - }} - }}, - \"difficulty\": \"1\", - \"gasLimit\": \"0\", - \"baseFeePerGas\": null, - \"extraData\": \"0x0000000000000000000000000000000000000000000000000000000000000000{reserve}0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", - \"alloc\": {{ - \"{client}\": {{ \"balance\": \"10000000000000000000\" }} - }} - }}" - ); + let genesis = r#" + { + "config": { + "chainId": 1337, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "muirGlacierBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "arrowGlacierBlock": 0, + "grayGlacierBlock": 0, + "shanghaiTime": 0, + "cancunTime": 0, + "terminalTotalDifficulty": 0, + "terminalTotalDifficultyPassed": true, + "depositContractAddress": "0x0000000000000000000000000000000000000000" + }, + "nonce": "0x0", + "timestamp": "0x0", + "extraData": "0x", + "gasLimit": "0x0", + "difficulty": "0x0", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "coinbase": "0x0000000000000000000000000000000000000000", + "alloc": { + "0000000000000000000000000000000000000001": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000002": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000003": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000004": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000005": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000006": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000007": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000008": { + "balance": "0x1" + }, + "0000000000000000000000000000000000000009": { + "balance": "0x1" + }, + "CLIENT": { + "balance": "0x100000000000000000" + }, + "RESERVE": { + "balance": "0x100000000000000000" + } + }, + "number": "0x0", + "gasUsed": "0x0", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "baseFeePerGas": "0x0", + "excessBlobGas": null, + "blobGasUsed": null + } + "# + .replace("CLIENT", client) + .replace("RESERVE", reserve); std::fs::write(ctx.wire_dir.join("genesis.json"), genesis.as_bytes()).unwrap(); cmd_redirect_ok( "geth", &[ + "--dev", "--datadir", ctx.wire_dir.to_str().unwrap(), - "--lightkdf", + "--password", + pswd_path.to_str().unwrap(), "init", ctx.wire_dir.join("genesis.json").to_str().unwrap(), ], @@ -323,9 +376,11 @@ impl EthCtx { cmd_redirect_ok( "geth", &[ + "--dev", "--datadir", ctx.wire2_dir.to_str().unwrap(), - "--lightkdf", + "--password", + pswd_path.to_str().unwrap(), "init", ctx.wire_dir.join("genesis.json").to_str().unwrap(), ], @@ -339,15 +394,13 @@ impl EthCtx { ctx.wire_dir.to_str().unwrap(), "--cache", "16", - "--nodiscover", "--lightkdf", - "--miner.gasprice", - "10", - "--authrpc.port", - &unused_port().to_string(), - "--port", - &unused_port().to_string(), "--rpc.enabledeprecatedpersonal", + "--dev", + "--miner.gasprice", + "1", + "--password", + pswd_path.to_str().unwrap(), ], ctx.log("geth"), ); @@ -379,7 +432,7 @@ impl EthCtx { rpc.unlock_account(addr, &passwd).unwrap(); } - Self { + let mut tmp = Self { node, rpc, reserve_addr, @@ -389,7 +442,10 @@ impl EthCtx { serve_cfg, ctx, passwd, - } + pswd_path, + }; + tmp.mine(0); + tmp } pub fn reset_db(&mut self) { @@ -431,7 +487,11 @@ impl EthCtx { self.ctx.wire2_dir.to_str().unwrap(), "--keystore", self.ctx.wire_dir.join("keystore").to_str().unwrap(), + "--cache", + "16", "--lightkdf", + "--password", + self.pswd_path.to_str().unwrap(), "import", path, ], @@ -444,21 +504,17 @@ impl EthCtx { let node2 = cmd_redirect( "geth", &[ + "--dev", "--datadir", self.ctx.wire2_dir.to_str().unwrap(), "--keystore", self.ctx.wire_dir.join("keystore").to_str().unwrap(), "--cache", "16", - "--nodiscover", "--lightkdf", - "--miner.gasprice", - "10", - "--authrpc.port", - &unused_port().to_string(), - "--port", - &unused_port().to_string(), "--rpc.enabledeprecatedpersonal", + "--password", + self.pswd_path.to_str().unwrap(), ], self.ctx.log("geth2"), ); @@ -466,12 +522,7 @@ impl EthCtx { let node1_height = self.rpc.height().unwrap(); let node2_height = rpc.height().unwrap(); let diff = node1_height - node2_height; - Self::_mine( - &mut rpc, - &self.reserve_addr, - diff.as_u32() as u16 + 10, - &self.passwd, - ); + self._mine(Some(&mut rpc), diff.as_u32() as u16 + 10); let path = self.ctx.dir.path().join("chain"); let path = path.to_str().unwrap(); Self::export(&mut rpc, path); @@ -483,6 +534,8 @@ impl EthCtx { "--datadir", self.ctx.wire_dir.to_str().unwrap(), "--lightkdf", + "--password", + self.pswd_path.to_str().unwrap(), "import", path, ], @@ -498,16 +551,16 @@ impl EthCtx { } pub fn resume_node(&mut self, additional_args: &[&str]) { - let (pa, pb) = (unused_port().to_string(), unused_port().to_string()); let mut args = vec![ "--datadir", self.ctx.wire_dir.to_str().unwrap(), "--lightkdf", - "--authrpc.port", - &pa, - "--port", - &pb, + "--dev", + "--cache", + "16", "--rpc.enabledeprecatedpersonal", + "--password", + self.pswd_path.to_str().unwrap(), ]; args.extend_from_slice(additional_args); self.node = cmd_redirect("geth", &args, self.ctx.log("geth")); @@ -542,7 +595,7 @@ impl EthCtx { .as_payto() .as_full_payto("Anonymous"), &eth_to_taler(&amount, &self.worker_cfg.currency), - ) + ); } pub fn malformed_credit(&mut self, amount: U256) { @@ -580,32 +633,49 @@ impl EthCtx { /* ----- Mining ----- */ - fn _mine(rpc: &mut Rpc, addr: &H160, mut amount: u16, passwd: &str) { - rpc.unlock_account(addr, passwd).ok(); - rpc.miner_set_etherbase(addr).ok(); - let mut rpc = rpc.subscribe_new_head().unwrap(); + fn dummy_tx(&self) -> TransactionRequest { + TransactionRequest { + from: self.reserve_addr, + to: self.reserve_addr, + value: U256::zero(), + gas_price: None, + data: Hex::default(), + nonce: None, + } + } - rpc.miner_start().unwrap(); + fn resume_miner(&mut self) { + self.rpc.send_transaction(&self.dummy_tx()).unwrap(); + self.mine(10); + } + + fn _mine(&mut self, custom: Option<&mut Rpc>, mut nb: u16) { + let dummy_tx = self.dummy_tx(); + let mut rpc = custom + .unwrap_or(&mut self.rpc) + .subscribe_new_head() + .unwrap(); while !rpc.pending_transactions().unwrap().is_empty() { rpc.next().unwrap(); - amount = amount.saturating_sub(1); + nb = nb.saturating_sub(1); } - for _ in 0..amount { + for _ in 0..nb { + rpc.send_transaction(&dummy_tx).unwrap(); rpc.next().unwrap(); } - rpc.miner_stop().unwrap(); } fn mine(&mut self, nb: u16) { - Self::_mine(&mut self.rpc, &self.reserve_addr, nb, &self.passwd) + self._mine(None, nb); } pub fn next_conf(&mut self) { + self.mine(0); self.mine(self.worker_cfg.confirmation as u16) } - pub fn next_block(&mut self) { - self.mine(1) + pub fn mine_pending(&mut self) { + self.mine(0) } /* ----- Balances ----- */ @@ -622,25 +692,25 @@ impl EthCtx { self.rpc.get_balance_pending(&self.wire_addr).unwrap() } - fn expect_balance(&mut self, balance: U256, mine: bool, lambda: fn(&mut Self) -> U256) { + fn expect_balance(&mut self, balance: U256, lambda: fn(&mut Self) -> U256) { retry( || { - let check = balance == lambda(self); - if !check && mine { - self.next_block(); + let current = lambda(self); + if current != balance { + // dbg!(current.abs_diff(balance), current.abs_diff(balance) / 30); } - check + balance == current }, "balance", ); } - pub fn expect_client_balance(&mut self, balance: U256, mine: bool) { - self.expect_balance(balance, mine, Self::client_balance) + pub fn expect_client_balance(&mut self, balance: U256) { + self.expect_balance(balance, Self::client_balance) } - pub fn expect_wire_balance(&mut self, balance: U256, mine: bool) { - self.expect_balance(balance, mine, Self::wire_balance) + pub fn expect_wire_balance(&mut self, balance: U256) { + self.expect_balance(balance, Self::wire_balance) } /* ----- Wire Gateway ----- */ @@ -691,7 +761,7 @@ pub fn wire(ctx: TestCtx) { } ctx.next_conf(); ctx.expect_credits(&txs); - ctx.expect_wire_balance(balance, true); + ctx.expect_wire_balance(balance); }; ctx.step("Debit"); @@ -705,21 +775,22 @@ pub fn wire(ctx: TestCtx) { ctx.debit(amount, &metadata); txs.push((metadata, amount)); } - ctx.next_block(); ctx.expect_debits(&txs); - ctx.expect_client_balance(balance, true); + ctx.expect_client_balance(balance); } ctx.step("Bounce"); { // Send bad transactions - let mut balance = ctx.wire_balance(); + let mut wire_balance = ctx.wire_balance(); for n in 10..40 { - ctx.malformed_credit(ctx.amount(n * 1000)); - balance += ctx.worker_cfg.bounce_fee; + let amount = ctx.amount(n * 101); + ctx.malformed_credit(amount); + wire_balance += ctx.worker_cfg.bounce_fee + *NETWORK_FEE; } + ctx.next_conf(); - ctx.expect_wire_balance(balance, true); + ctx.expect_wire_balance(wire_balance); } } @@ -736,7 +807,7 @@ pub fn lifetime(ctx: TestCtx) { // Consume lifetime for n in 0..=ctx.worker_cfg.lifetime.unwrap() { ctx.credit(ctx.amount(n * 1000), &Base32::rand()); - ctx.next_block(); + ctx.mine_pending(); } for n in 0..=ctx.serve_cfg.lifetime.unwrap() { ctx.debit(ctx.amount(n * 1000), &Base32::rand()); @@ -762,7 +833,6 @@ pub fn reconnect(ctx: TestCtx) { let amount = ctx.amount(42000); ctx.credit(amount, &metadata); credits.push((metadata, amount)); - ctx.next_block(); ctx.next_conf(); ctx.expect_credits(&credits); }; @@ -787,27 +857,18 @@ pub fn reconnect(ctx: TestCtx) { let amount = ctx.amount(2000); ctx.debit(amount, &metadata); debits.push((metadata, amount)); - ctx.next_block(); - sleep(Duration::from_secs(3)); - ctx.next_block(); - sleep(Duration::from_secs(3)); - ctx.next_block(); + ctx.next_conf(); ctx.expect_debits(&debits); ctx.expect_credits(&credits); } ctx.step("Recover DB"); { - ctx.next_block(); - sleep(Duration::from_secs(3)); - ctx.next_block(); - sleep(Duration::from_secs(3)); let balance = ctx.wire_balance(); ctx.reset_db(); - ctx.next_block(); ctx.expect_debits(&debits); ctx.expect_credits(&credits); - ctx.expect_wire_balance(balance, true); + ctx.expect_wire_balance(balance); } } @@ -831,7 +892,7 @@ pub fn stress(ctx: TestCtx) { } ctx.next_conf(); ctx.expect_credits(&credits); - ctx.expect_wire_balance(balance, true); + ctx.expect_wire_balance(balance); }; ctx.step("Debit"); @@ -844,30 +905,28 @@ pub fn stress(ctx: TestCtx) { ctx.debit(amount, &metadata); debits.push((metadata, amount)); } - ctx.next_block(); ctx.expect_debits(&debits); - ctx.expect_client_balance(balance, true); + ctx.expect_client_balance(balance); } ctx.step("Bounce"); { - let mut balance = ctx.wire_balance(); + let mut wire_balance = ctx.wire_balance(); for n in 10..30 { - ctx.malformed_credit(ctx.amount(n * 1000)); - balance += ctx.worker_cfg.bounce_fee; + ctx.malformed_credit(ctx.amount(n * 101)); + wire_balance += ctx.worker_cfg.bounce_fee + *NETWORK_FEE; } ctx.next_conf(); - ctx.expect_wire_balance(balance, true); + ctx.expect_wire_balance(wire_balance); } ctx.step("Recover DB"); { let balance = ctx.wire_balance(); ctx.reset_db(); - ctx.next_block(); ctx.expect_debits(&debits); ctx.expect_credits(&credits); - ctx.expect_wire_balance(balance, true); + ctx.expect_wire_balance(balance); } } @@ -892,12 +951,13 @@ pub fn reorg(ctx: TestCtx) { // Perform fork and check eth-wire hard error ctx.expect_gateway_up(); ctx.cluster_fork(); - ctx.expect_wire_balance(before, false); + ctx.expect_wire_balance(before); ctx.expect_gateway_down(); // Recover orphaned transaction + ctx.resume_miner(); ctx.next_conf(); - ctx.expect_wire_balance(after, false); + ctx.expect_wire_balance(after); ctx.expect_gateway_up(); } @@ -914,18 +974,19 @@ pub fn reorg(ctx: TestCtx) { ctx.debit(amount, &Base32::rand()); after += amount; } - ctx.next_block(); - ctx.expect_client_balance(after, true); + ctx.mine_pending(); + ctx.expect_client_balance(after); // Perform fork and check eth-wire still up ctx.expect_gateway_up(); ctx.cluster_fork(); - ctx.expect_client_balance(before, false); + ctx.expect_client_balance(before); ctx.expect_gateway_up(); // Recover orphaned transaction + ctx.resume_miner(); ctx.next_conf(); - ctx.expect_client_balance(after, false); + ctx.expect_client_balance(after); } ctx.step("Handle reorg bounce"); @@ -938,22 +999,20 @@ pub fn reorg(ctx: TestCtx) { let mut after = ctx.wire_balance(); for n in 10..21 { ctx.malformed_credit(ctx.amount(n * 1000)); - after += ctx.worker_cfg.bounce_fee; + after += ctx.worker_cfg.bounce_fee + *NETWORK_FEE; } ctx.next_conf(); - ctx.expect_wire_balance(after, true); + ctx.expect_wire_balance(after); // Perform fork and check eth-wire hard error ctx.expect_gateway_up(); ctx.cluster_fork(); - ctx.expect_wire_balance(before, false); + ctx.expect_wire_balance(before); ctx.expect_gateway_down(); // Recover orphaned transaction - ctx.mine(10); - sleep(Duration::from_secs(3)); - ctx.next_block(); - ctx.expect_wire_balance(after, false); + ctx.resume_miner(); + ctx.expect_wire_balance(after); ctx.expect_gateway_up(); } } @@ -979,15 +1038,16 @@ pub fn hell(ctx: TestCtx) { // Generate conflict ctx.restart_node(&["--miner.gasprice", "1000"]); ctx.abandon(); + ctx.resume_miner(); let amount = ctx.amount(54000); ctx.credit(amount, &Base32::rand()); - ctx.expect_wire_balance(amount, true); + ctx.expect_wire_balance(amount); // Check eth-wire suspend operation let bounce_amount = ctx.amount(34000); ctx.malformed_credit(bounce_amount); ctx.next_conf(); - ctx.expect_wire_balance(amount + bounce_amount, true); + ctx.expect_wire_balance(amount + bounce_amount); ctx.expect_gateway_down(); } @@ -995,17 +1055,15 @@ pub fn hell(ctx: TestCtx) { let amount = ctx.amount(420000); ctx.credit(amount, &Base32::rand()); ctx.next_conf(); - ctx.expect_wire_balance(amount, true); + ctx.expect_wire_balance(amount); }); step(&ctx, "Handle reorg conflicting incoming bounce", |ctx| { + let wire_balance = ctx.wire_balance(); let amount = ctx.amount(420000); ctx.malformed_credit(amount); ctx.next_conf(); - retry( - || ctx.wire_balance_pending() == ctx.worker_cfg.bounce_fee, - "balance", - ); + ctx.expect_wire_balance(wire_balance + ctx.worker_cfg.bounce_fee + *NETWORK_FEE); }); } @@ -1028,12 +1086,12 @@ pub fn analysis(ctx: TestCtx) { // Perform fork and check eth-wire hard error ctx.expect_gateway_up(); ctx.cluster_fork(); - ctx.expect_wire_balance(before, false); + ctx.expect_wire_balance(before); ctx.expect_gateway_down(); // Recover orphaned transaction ctx.mine(6); - ctx.expect_wire_balance(after, false); + ctx.expect_wire_balance(after); ctx.expect_gateway_up(); // Loose second node @@ -1047,8 +1105,7 @@ pub fn analysis(ctx: TestCtx) { // Perform fork and check eth-wire learned from previous attack ctx.expect_gateway_up(); ctx.cluster_fork(); - ctx.expect_wire_balance(before, false); - std::thread::sleep(Duration::from_secs(3)); + ctx.expect_wire_balance(before); ctx.expect_gateway_up(); } @@ -1071,11 +1128,10 @@ pub fn bumpfee(tctx: TestCtx) { retry(|| ctx.wire_balance_pending() < wire, "balance"); // Bump min relay fee making the previous debit stuck - ctx.restart_node(&["--miner.gasprice", "1000"]); + ctx.restart_node(&["--miner.gasprice", "100"]); // Check bump happen - client += amount; - ctx.expect_client_balance(client, true); + ctx.expect_client_balance(client); } ctx.step("Bump fee reorg"); @@ -1092,11 +1148,11 @@ pub fn bumpfee(tctx: TestCtx) { // Bump min relay fee and fork making the previous debit stuck and problematic ctx.cluster_fork(); - ctx.restart_node(&["--miner.gasprice", "2000"]); + ctx.restart_node(&["--miner.gasprice", "200"]); // Check bump happen client += amount; - ctx.expect_client_balance(client, true); + ctx.expect_client_balance(client); } ctx.step("Setup"); @@ -1130,7 +1186,7 @@ pub fn bumpfee(tctx: TestCtx) { ctx.restart_node(&["--miner.gasprice", "1000"]); // Check bump happen - ctx.expect_client_balance(client + total_amount, true); + ctx.expect_client_balance(client + total_amount); } } @@ -1158,11 +1214,10 @@ pub fn maxfee(ctx: TestCtx) { total_amount += amount; ctx.debit(amount, &Base32::rand()); } - sleep(Duration::from_secs(3)); // Check no transaction happen - ctx.expect_wire_balance(wire, true); - ctx.expect_client_balance(client, true); + ctx.expect_wire_balance(wire); + ctx.expect_client_balance(client); } ctx.step("Good feed"); @@ -1171,6 +1226,6 @@ pub fn maxfee(ctx: TestCtx) { ctx.restart_node(&[""]); // Check transaction now have been made - ctx.expect_client_balance(client + total_amount, true); + ctx.expect_client_balance(client + total_amount); } } diff --git a/instrumentation/src/main.rs b/instrumentation/src/main.rs @@ -22,7 +22,6 @@ use std::{ }; use clap::Parser; -use color_backtrace::termcolor::NoColor; use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; use owo_colors::OwoColorize; use thread_local_panic_hook::set_hook; @@ -58,8 +57,6 @@ enum Cmd { } pub fn main() { - color_backtrace::install(); - let args = Args::parse(); match args.cmd { Cmd::Online { config } => { @@ -117,13 +114,10 @@ pub fn main() { let ctx: TestCtx = TestCtx::new(name, pb.clone(), db); let out = Arc::new(Mutex::new(String::new())); let tmp = out.clone(); - set_hook(Box::new(move |info| { - let mut buf = Vec::new(); - color_backtrace::BacktracePrinter::new() - .print_panic_info(info, &mut NoColor::new(&mut buf)) - .ok(); - let str = String::from_utf8(buf).unwrap_or_default(); - tmp.lock().unwrap().push_str(&str); + set_hook(Box::new(move |_| { + let backtrace = + std::backtrace::Backtrace::force_capture().to_string(); + tmp.lock().unwrap().push_str(&backtrace); })); let tmp = ctx.clone(); let result = catch_unwind(|| { diff --git a/instrumentation/src/utils.rs b/instrumentation/src/utils.rs @@ -207,7 +207,7 @@ pub fn retry_opt<T, E: Debug>(mut lambda: impl FnMut() -> Result<T, E>) -> T { let start = Instant::now(); loop { let result = lambda(); - if result.is_err() && start.elapsed() < Duration::from_secs(30) { + if result.is_err() && start.elapsed() < Duration::from_secs(20) { sleep(Duration::from_millis(500)); } else { return result.unwrap(); diff --git a/script/prepare.sh b/script/prepare.sh @@ -17,7 +17,7 @@ function cleanup() { trap cleanup EXIT BTC_VER="29.0" -ETH_VER="1.13.5-916d6a44" +ETH_VER="1.14.11-f3c696fa" echo "Ⅰ - Find installed postgres version" PG_VER=`pg_config --version | egrep -o '[0-9]{1,}' | head -1`