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:
| M | src/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);
}
}