depolymerization

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

commit d08e314ea5f1f97690d13726ce3d6b46c5f27da3
parent 076dc90710086f24aa72fa0a9f84fb82a7491b8f
Author: Antoine A <>
Date:   Tue, 16 Nov 2021 13:30:50 +0100

Improbe binary command to test future transaction listener

Diffstat:
Msrc/main.rs | 276+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 214 insertions(+), 62 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -1,4 +1,4 @@ -use std::{collections::HashSet, path::PathBuf, str::FromStr}; +use std::{collections::HashSet, path::PathBuf, str::FromStr, time::Duration}; use bitcoincore_rpc::{ bitcoin::{Amount, Txid}, @@ -54,13 +54,99 @@ fn network_dir_path(network: Network) -> PathBuf { #[derive(argh::FromArgs)] /// Bitcoin metadata tester struct Args { - /// start as a sender - #[argh(switch, short = 'c')] - client: bool, + #[argh(subcommand)] + cmd: Cmd, +} + +#[derive(argh::FromArgs)] +/// Test library +#[argh(subcommand, name = "test")] +struct TestCmd {} + +#[derive(argh::FromArgs)] +/// Mine block for the given wallet +#[argh(subcommand, name = "mine")] +struct MineCmd { + #[argh(option, short = 'r')] + /// repeat every ? ms + repeat: Option<u64>, + + #[argh(positional)] + /// the wallet name + wallet: String, + + #[argh(positional, default = "1")] + /// repeat every ? ms + amount: u64, +} + +#[derive(argh::FromArgs)] + +/// Send message +#[argh(subcommand, name = "send")] +struct SendRole { + #[argh(switch, short = 'm')] + /// mine on send + mine: bool, +} + +#[derive(argh::FromArgs)] + +/// Receive message +#[argh(subcommand, name = "receive")] +struct ReceiveRole {} - /// start as a receiver - #[argh(switch, short = 'w')] - wire: bool, +#[derive(argh::FromArgs)] +#[argh(subcommand)] +enum Role { + Send(SendRole), + Receive(ReceiveRole), +} + +enum Metadata { + SegWit, + OpReturn, +} + +impl ToString for Metadata { + fn to_string(&self) -> String { + match self { + Metadata::SegWit => "SegWit", + Metadata::OpReturn => "OpReturn", + } + .to_string() + } +} + +impl FromStr for Metadata { + type Err = String; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "SegWit" | "Segwit" | "segwit" | "seg" | "s" => Ok(Self::SegWit), + "OpReturn" | "Opreturn" | "opreturn" | "op" | "o" => Ok(Self::OpReturn), + _ => Err(format!("Unknown")), + } + } +} + +#[derive(argh::FromArgs)] +/// Msg exchange msg using metadata +#[argh(subcommand, name = "msg")] +struct MsgCmd { + #[argh(subcommand)] + role: Role, + + #[argh(positional)] + method: Option<Metadata>, +} + +#[derive(argh::FromArgs)] +#[argh(subcommand)] +enum Cmd { + Mine(MineCmd), + Test(TestCmd), + Msg(MsgCmd), } fn common_rpc(network: Network) -> bitcoincore_rpc::Result<Client> { @@ -136,68 +222,134 @@ fn main() { } } - println!("Initial state:"); - let client_rpc = wallet_rpc(network, CLIENT); - let wire_rpc = wallet_rpc(network, WIRE); - let client_addr = client_rpc.get_new_address(None, None).unwrap(); - let wire_addr = wire_rpc.get_new_address(None, None).unwrap(); - println!( - "{} {} {}", - WIRE, - wire_addr, - wire_rpc.get_balance(None, None).unwrap() - ); - println!( - "{} {} {}", - CLIENT, - client_addr, - client_rpc.get_balance(None, None).unwrap() - ); - let args: Args = argh::from_env(); - if args.client { - println!("Start client"); - let mut rl = rustyline::Editor::<()>::new(); - loop { - let rl = rl.readline(">> "); - match rl { - Ok(line) => { - client_rpc - .send_op_return(&wire_addr, Amount::from_sat(4200), line.as_bytes()) - .unwrap(); - client_rpc.generate_to_address(1, &client_addr).unwrap(); + match args.cmd { + Cmd::Mine(MineCmd { + repeat, + wallet, + amount, + }) => { + let rpc = wallet_rpc(network, &wallet); + let balance = rpc.get_balance(None, None).unwrap(); + let addr = rpc.get_new_address(None, None).unwrap(); + println!("{} {}", wallet, balance); + if amount == 0 { + return; + } + loop { + println!("Mine {} block", amount); + rpc.generate_to_address(amount, &addr).unwrap(); + + let balance = rpc.get_balance(None, None).unwrap(); + println!("{} {}", wallet, balance); + + if let Some(wait) = repeat { + std::thread::sleep(Duration::from_millis(wait)) + } else { + return; } - Err(_) => break, } } - } else if args.wire { - println!("Start wire"); - loop { - wire_rpc.wait_for_new_block(60 * 60 * 1000).ok(); + Cmd::Test(_) => { + let client_rpc = wallet_rpc(network, CLIENT); + let wire_rpc = wallet_rpc(network, WIRE); + let client_addr = client_rpc.get_new_address(None, None).unwrap(); + let wire_addr = wire_rpc.get_new_address(None, None).unwrap(); + // OP RETURN test + let msg = "J'aime le chocolat".as_bytes(); + client_rpc + .send_op_return(&wire_addr, Amount::from_sat(4200), msg) + .unwrap(); + client_rpc.generate_to_address(1, &client_addr).unwrap(); let last = last_transaction(&wire_rpc).unwrap(); let (_, decoded) = wire_rpc.get_tx_op_return(&last).unwrap(); - println!(">> {}", String::from_utf8_lossy(&decoded)); + assert_eq!(&msg, &decoded.as_slice()); + + // Segwit test + let key = rand_key(); + client_rpc + .send_segwit_key(&wire_addr, Amount::from_sat(4200), &key) + .unwrap(); + client_rpc.generate_to_address(1, &client_addr).unwrap(); + let last = last_transaction(&wire_rpc).unwrap(); + let (_, decoded) = wire_rpc.get_tx_segwit_key(&last).unwrap(); + assert_eq!(key, decoded); + + println!("Test ok"); + } + Cmd::Msg(MsgCmd { role, method }) => { + println!("Initial state:"); + let client_rpc = wallet_rpc(network, CLIENT); + let wire_rpc = wallet_rpc(network, WIRE); + let client_addr = client_rpc.get_new_address(None, None).unwrap(); + let wire_addr = wire_rpc.get_new_address(None, None).unwrap(); + println!("{} {}", WIRE, wire_rpc.get_balance(None, None).unwrap()); + println!("{} {}", CLIENT, client_rpc.get_balance(None, None).unwrap()); + let method = method.unwrap_or(Metadata::SegWit); + match role { + Role::Send(SendRole { mine }) => { + println!("Send message using {}", method.to_string()); + let mut rl = rustyline::Editor::<()>::new(); + loop { + let rl = rl.readline(">> "); + match rl { + Ok(line) => { + match method { + Metadata::SegWit => { + for chunk in line.as_bytes().chunks(32) { + let mut key = [0; 32]; + key[..chunk.len()].copy_from_slice(&chunk); + client_rpc + .send_segwit_key( + &wire_addr, + Amount::from_sat(4200), + &key, + ) + .unwrap(); + } + } + Metadata::OpReturn => { + for chunk in line.as_bytes().chunks(80) { + client_rpc + .send_op_return( + &wire_addr, + Amount::from_sat(4200), + chunk, + ) + .unwrap(); + } + } + } + + if mine { + client_rpc.generate_to_address(1, &client_addr).unwrap(); + } + } + Err(_) => break, + } + } + } + Role::Receive(_) => { + println!("Receive message using {}", method.to_string()); + loop { + wire_rpc.wait_for_new_block(60 * 60 * 1000).ok(); + println!("new block"); + let last = last_transaction(&wire_rpc).unwrap(); + let msg: String = match method { + Metadata::SegWit => { + let (_, decoded) = wire_rpc.get_tx_segwit_key(&last).unwrap(); + String::from_utf8_lossy(&decoded).to_string() + } + Metadata::OpReturn => { + let (_, decoded) = wire_rpc.get_tx_op_return(&last).unwrap(); + String::from_utf8_lossy(&decoded).to_string() + } + }; + println!("> {}", msg); + } + } + } } - } else { - // OP RETURN test - let msg = "J'aime le chocolat".as_bytes(); - client_rpc - .send_op_return(&wire_addr, Amount::from_sat(4200), msg) - .unwrap(); - client_rpc.generate_to_address(1, &client_addr).unwrap(); - let last = last_transaction(&wire_rpc).unwrap(); - let (_, decoded) = wire_rpc.get_tx_op_return(&last).unwrap(); - assert_eq!(&msg, &decoded.as_slice()); - - // Segwit test - let key = rand_key(); - client_rpc - .send_segwit_key(&wire_addr, Amount::from_sat(4200), &key) - .unwrap(); - client_rpc.generate_to_address(1, &client_addr).unwrap(); - let last = last_transaction(&wire_rpc).unwrap(); - let (_, decoded) = wire_rpc.get_tx_segwit_key(&last).unwrap(); - assert_eq!(key, decoded); } }