depolymerization

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

commit 1864e66bb6fe34de7e9777dc7c9e6cf2854c7f6b
parent 641d31b40b5e6bd9552bd34e3202303f70fdf7eb
Author: Antoine A <>
Date:   Tue, 18 Jan 2022 19:19:47 +0100

Improve bootstrap cli

Diffstat:
MCargo.lock | 18+++++++++---------
Mbtc-wire/Cargo.toml | 2+-
Mbtc-wire/src/bin/btc-wire-cli.rs | 66+++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mbtc-wire/src/rpc.rs | 11+++++++++++
Mtaler-common/Cargo.toml | 2+-
Mwire-gateway/Cargo.toml | 6+++---
6 files changed, 74 insertions(+), 31 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -805,9 +805,9 @@ checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "listenfd" -version = "0.3.5" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e514e2cb8a9624701346ea3e694c1766d76778e343e537d873c1c366e79a7" +checksum = "fe05ca4da1db151e4cfed8dfd45438047aee112e43656c0963b6579e443bf22a" dependencies = [ "libc", "uuid", @@ -1345,9 +1345,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.74" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" +checksum = "c059c05b48c5c0067d4b4b2b4f0732dd65feb52daf7e0ea09cd87e7dadc1af79" dependencies = [ "itoa 1.0.1", "ryu", @@ -1367,12 +1367,12 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 0.4.8", + "itoa 1.0.1", "ryu", "serde", ] @@ -1413,9 +1413,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" +checksum = "a86232ab60fa71287d7f2ddae4a7073f6b7aac33631c3015abb556f08c6d0a3e" [[package]] name = "slab" diff --git a/btc-wire/Cargo.toml b/btc-wire/Cargo.toml @@ -23,7 +23,7 @@ rand = { version = "0.8.4", features = ["getrandom"] } fastrand = "1.6.0" # Serialization library serde = { version = "1.0.133", features = ["derive"] } -serde_json = "1.0.74" +serde_json = "1.0.75" serde_repr = "0.1.7" # Error macros thiserror = "1.0.30" diff --git a/btc-wire/src/bin/btc-wire-cli.rs b/btc-wire/src/bin/btc-wire-cli.rs @@ -10,29 +10,46 @@ fn main() { // Parse taler config let config = taler_common::config::InitConfig::load_from_file(&args[2]); // Connect to database - let mut client = Client::connect(&config.db_url, NoTls).unwrap(); + let mut db = Client::connect(&config.db_url, NoTls).expect("Failed to connect to database"); match args[1].as_str() { "initdb" => { // Load schema - client - .batch_execute(include_str!("../../../db/btc.sql")) - .unwrap(); + db.batch_execute(include_str!("../../../db/btc.sql")) + .expect("Failed to load database schema"); // Init status to true - client + db .execute( - "INSERT INTO state (name, value) VALUES ('status', $1)", + "INSERT INTO state (name, value) VALUES ('status', $1) ON CONFLICT (name) DO NOTHING", &[&[1u8].as_ref()], ) - .unwrap(); + .expect("Failed to initialise database state"); println!("Database initialised"); } "initwallet" => { // Parse bitcoin config let btc_conf = - BitcoinConfig::load(config.btc_data_dir.unwrap_or_else(default_data_dir)).unwrap(); + BitcoinConfig::load(config.btc_data_dir.unwrap_or_else(default_data_dir)) + .expect("Failed to load bitcoin configuration"); // Connect to bitcoin node - let mut rpc = BtcRpc::common(&btc_conf).unwrap(); + let mut rpc = + BtcRpc::common(&btc_conf).expect("Failed to connect to bitcoin RPC server"); + + // Skip previous blocks + let info = rpc + .get_blockchain_info() + .expect("Failed to get blockchain info"); + let nb_row = db + .execute( + "INSERT INTO state (name, value) VALUES ('last_hash', $1) ON CONFLICT (name) DO NOTHING", + &[&info.best_block_hash.as_ref()], + ) + .expect("Failed to update database state"); + if nb_row > 0 { + println!("Skip previous block until now"); + } + + // Create wallet let created = match rpc.create_wallet(WIRE_WALLET_NAME) { Err(Error::RPC { code, .. }) if code == ErrorCode::RpcWalletError => false, Err(e) => panic!("{}", e), @@ -40,22 +57,37 @@ fn main() { }; rpc.load_wallet(WIRE_WALLET_NAME).ok(); - // TODO idempotent (store address in database ?) - // TODO init last_hash to skip previous database sync - let address = BtcRpc::wallet(&btc_conf, WIRE_WALLET_NAME) - .unwrap() - .get_new_address() - .unwrap(); + + // Load previous address + let prev_addr = db + .query_opt("SELECT value FROM state WHERE name = 'addr'", &[]) + .expect("Failed to query database state"); + let addr = if let Some(row) = prev_addr { + String::from_utf8(row.get(0)).expect("Stored address is not a valid string") + } else { + // Or generate a new one + let new = BtcRpc::wallet(&btc_conf, WIRE_WALLET_NAME) + .expect("Failed to connect to wallet bitcoin RPC server") + .get_new_address() + .expect("Failed to generate new address") + .to_string(); + db.execute( + "INSERT INTO state (name, value) VALUES ('addr', $1)", + &[&new.as_bytes()], + ) + .expect("Failed to update database state"); + new + }; if created { println!("Created new wallet"); } else { println!("Found already existing wallet") } - println!("Address is {}", &address); + println!("Address is {}", &addr); println!("Add the following line into taler.conf:"); println!("[depolymerizer-bitcoin]"); - println!("PAYTO = payto://bitcoin/{}", address); + println!("PAYTO = payto://bitcoin/{}", addr); } cmd => panic!("Unknown command {}", cmd), } diff --git a/btc-wire/src/rpc.rs b/btc-wire/src/rpc.rs @@ -194,6 +194,10 @@ impl BtcRpc { Ok(Amount::from_btc(btc).unwrap()) } + pub fn get_blockchain_info(&mut self) -> Result<BlockchainInfo> { + self.call("getblockchaininfo", &EMPTY) + } + pub fn send(&mut self, address: &Address, amount: &Amount, subtract_fee: bool) -> Result<Txid> { let btc = amount.as_btc(); self.call("sendtoaddress", &(address, btc, (), (), subtract_fee)) @@ -313,6 +317,13 @@ pub struct Vout { pub script_pub_key: VoutScriptPubKey, } +#[derive(Clone, Debug, serde::Deserialize)] +pub struct BlockchainInfo { + pub blocks: u64, + #[serde(rename = "bestblockhash")] + pub best_block_hash: BlockHash, +} + #[derive(Debug, serde::Deserialize)] pub struct Vin { pub sequence: u32, diff --git a/taler-common/Cargo.toml b/taler-common/Cargo.toml @@ -11,7 +11,7 @@ serde = { version = "1.0.133", features = ["derive"] } # Serialization helper serde_with = "1.11.0" # JSON serialization -serde_json = "1.0.74" +serde_json = "1.0.75" # Url format url = { version = "2.2.2", features = ["serde"] } # Crockford’s base32 diff --git a/wire-gateway/Cargo.toml b/wire-gateway/Cargo.toml @@ -19,9 +19,9 @@ serde = { version = "1.0.133", features = ["derive"] } # Serialization helper serde_with = "1.11.0" # JSON serialization -serde_json = "1.0.74" +serde_json = "1.0.75" # Url query serialization -serde_urlencoded = "0.7.0" +serde_urlencoded = "0.7.1" # Error macros thiserror = "1.0.30" # Deflate compression @@ -33,7 +33,7 @@ tokio-postgres = { version = "0.7.5" } postgres = { version = "0.19.2" } deadpool-postgres = "0.10.1" # Socket activation -listenfd = "0.3.5" +listenfd = "0.4.0" # Taler libs taler-common = { path = "../taler-common" }