depolymerization

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

commit 171993db6cc36166d98b940354a960c287ef6895
parent d576e6948658a54ef2612846ab2f39d094fd9ae2
Author: Antoine A <>
Date:   Tue, 16 Nov 2021 11:10:52 +0100

Improve network agnosticism

Diffstat:
Mbenches/metadata.rs | 5++---
Msrc/lib.rs | 74+++++++++++++++++++++++++++++---------------------------------------------
Msrc/main.rs | 24++++++++++++++++++++++--
3 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/benches/metadata.rs b/benches/metadata.rs @@ -2,7 +2,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; use depolymerization::{ decode_segwit_msg, encode_segwit_key, utils::{rand_addresses, rand_key}, - Network, }; fn criterion_benchmark(c: &mut Criterion) { @@ -10,13 +9,13 @@ fn criterion_benchmark(c: &mut Criterion) { group.bench_function("encode", |b| { b.iter_batched( rand_key, - |key| encode_segwit_key(Network::MainNet, &key), + |key| encode_segwit_key("bench", &key), criterion::BatchSize::SmallInput, ); }); group.bench_function("decode", |b| { b.iter_batched( - || rand_addresses(Network::MainNet, &rand_key()), + || rand_addresses("bench", &rand_key()), |addrs| decode_segwit_msg(&addrs), criterion::BatchSize::SmallInput, ); diff --git a/src/lib.rs b/src/lib.rs @@ -1,36 +1,18 @@ use bech32::{u5, FromBase32, ToBase32, Variant}; -use bitcoincore_rpc::{Client, RpcApi, bitcoin::{Address, Amount, Txid, hashes::hex::{FromHex, ToHex}}, json::ScriptPubkeyType, jsonrpc::serde_json::{json, Value}}; +use bitcoincore_rpc::{ + bitcoin::{ + hashes::hex::{FromHex, ToHex}, + Address, Amount, Network, Txid, + }, + json::ScriptPubkeyType, + jsonrpc::serde_json::{json, Value}, + Client, RpcApi, +}; use rand::{rngs::OsRng, RngCore}; use rpc_patch::{ClientPatched, GetTransactionFull}; mod rpc_patch; -/// Bitcoin networks -#[derive(Debug, Clone, Copy)] -pub enum Network { - MainNet, - TestNet, - RegTest, -} - -impl Network { - pub fn segwit_hrp(&self) -> &'static str { - match self { - Network::MainNet => "bc", - Network::TestNet => "tb", - Network::RegTest => "bcrt", - } - } - - pub fn dir(&self) -> &'static str { - match self { - Network::MainNet => "mainnet", - Network::TestNet => "testnet", - Network::RegTest => "regtest", - } - } -} - /// Minimum dust amount to perform a transaction to a segwit address fn segwit_min_amount() -> Amount { // https://github.com/bitcoin/bitcoin/blob/master/src/policy/policy.cpp @@ -38,16 +20,16 @@ fn segwit_min_amount() -> Amount { } /// Encode metadata into a segwit address -fn encode_segwit_addr(network: Network, metada: &[u8; 20]) -> String { +fn encode_segwit_addr(hrp: &str, metada: &[u8; 20]) -> String { // We use the version 0 with bech32 encoding let mut buf = vec![u5::try_from_u8(0).unwrap()]; buf.extend_from_slice(&metada.to_base32()); - bech32::encode(network.segwit_hrp(), buf, Variant::Bech32).unwrap() + bech32::encode(hrp, buf, Variant::Bech32).unwrap() } /// Encode half of a 32B key into a segwit address fn encode_segwit_key_half( - network: Network, + hrp: &str, is_first: bool, magic_id: &[u8; 4], key_half: &[u8; 16], @@ -63,11 +45,11 @@ fn encode_segwit_key_half( buf[0] |= 0b1000_0000 // Set first bit } // Encode into an fake segwit address - encode_segwit_addr(network, &buf) + encode_segwit_addr(hrp, &buf) } /// Encode a 32B key into two segwit adresses -pub fn encode_segwit_key(network: Network, msg: &[u8; 32]) -> [String; 2] { +pub fn encode_segwit_key(hrp: &str, msg: &[u8; 32]) -> [String; 2] { // Generate a random magic identifier let mut magic_id = [0; 4]; OsRng.fill_bytes(&mut magic_id); @@ -76,8 +58,8 @@ pub fn encode_segwit_key(network: Network, msg: &[u8; 32]) -> [String; 2] { split.0.copy_from_slice(&msg[..16]); split.1.copy_from_slice(&msg[16..]); [ - encode_segwit_key_half(network, true, &magic_id, &split.0), - encode_segwit_key_half(network, false, &magic_id, &split.1), + encode_segwit_key_half(hrp, true, &magic_id, &split.0), + encode_segwit_key_half(hrp, false, &magic_id, &split.1), ] } @@ -113,7 +95,6 @@ pub trait ClientExtended { /// Send a transaction with a 32B key as metadata encoded using fake segwit addresses fn send_segwit_key( &self, - network: Network, to: &Address, amount: Amount, metadata: &[u8; 32], @@ -141,12 +122,16 @@ pub trait ClientExtended { impl ClientExtended for Client { fn send_segwit_key( &self, - network: Network, to: &Address, amount: Amount, metadata: &[u8; 32], ) -> bitcoincore_rpc::Result<Txid> { - let addresses = encode_segwit_key(network, metadata); + let hrp = match to.network { + Network::Bitcoin => "bc", + Network::Testnet | Network::Signet => "tb", + Network::Regtest => "bcrt", + }; + let addresses = encode_segwit_key(hrp, metadata); let mut recipients = vec![(to.to_string(), amount)]; recipients.extend( addresses @@ -222,7 +207,7 @@ impl ClientExtended for Client { // TODO error handling .unwrap(); let hex = op_return_out.script_pub_key.asm.split_once(' ').unwrap().1; - let metadata= Vec::from_hex(hex).unwrap(); + let metadata = Vec::from_hex(hex).unwrap(); Ok((full, metadata)) } @@ -289,7 +274,7 @@ pub fn decode_segwit_msg(segwit_addrs: &[impl AsRef<str>]) -> Result<[u8; 32], D } pub mod utils { - use crate::{encode_segwit_addr, encode_segwit_key, Network}; + use crate::{encode_segwit_addr, encode_segwit_key}; pub fn rand_key() -> [u8; 32] { let mut key = [0; 32]; @@ -303,13 +288,13 @@ pub mod utils { key } - pub fn rand_addresses(network: Network, key: &[u8; 32]) -> Vec<String> { + pub fn rand_addresses(hrp: &str, key: &[u8; 32]) -> Vec<String> { let mut rng_address: Vec<String> = - std::iter::repeat_with(|| encode_segwit_addr(network, &rand_data())) + std::iter::repeat_with(|| encode_segwit_addr(hrp, &rand_data())) .take(2) .collect(); - let mut addresses = encode_segwit_key(network, &key).to_vec(); + let mut addresses = encode_segwit_key(hrp, &key).to_vec(); addresses.append(&mut rng_address); fastrand::shuffle(&mut addresses); addresses @@ -321,14 +306,13 @@ mod test { use crate::{ decode_segwit_msg, encode_segwit_key, utils::{rand_addresses, rand_key}, - Network, }; #[test] fn test_shuffle() { for _ in 0..1000 { let key = rand_key(); - let mut addresses = encode_segwit_key(Network::RegTest, &key); + let mut addresses = encode_segwit_key("test", &key); fastrand::shuffle(&mut addresses); let decoded = decode_segwit_msg(&addresses.iter().map(|s| s.as_str()).collect::<Vec<&str>>()) @@ -341,7 +325,7 @@ mod test { fn test_shuffle_many() { for _ in 0..1000 { let key = rand_key(); - let addresses = rand_addresses(Network::TestNet, &key); + let addresses = rand_addresses("test", &key); let decoded = decode_segwit_msg(&addresses.iter().map(|s| s.as_str()).collect::<Vec<&str>>()) .unwrap(); diff --git a/src/main.rs b/src/main.rs @@ -4,12 +4,30 @@ use bitcoincore_rpc::{ bitcoin::{Amount, Txid}, Auth, Client, RpcApi, }; -use depolymerization::{utils::rand_key, ClientExtended, Network}; +use depolymerization::{utils::rand_key, ClientExtended}; const CLIENT: &str = "client"; const WIRE: &str = "wire"; const RPC_URL: &str = "http://localhost:18443"; +/// Bitcoin networks +#[derive(Debug, Clone, Copy)] +pub enum Network { + MainNet, + TestNet, + RegTest, +} + +impl Network { + pub fn dir(&self) -> &'static str { + match self { + Network::MainNet => "mainnet", + Network::TestNet => "testnet", + Network::RegTest => "regtest", + } + } +} + fn data_dir_path() -> PathBuf { // https://github.com/bitcoin/bitcoin/blob/master/doc/bitcoin-conf.md#:~:text=By%20default%2C%20the%20configuration%20file,file%3E%20option%20in%20the%20bitcoin. if cfg!(target_os = "windows") { @@ -44,6 +62,7 @@ struct Args { #[argh(switch, short = 'w')] wire: bool, } + fn common_rpc(network: Network) -> Client { Client::new( RPC_URL, @@ -51,6 +70,7 @@ fn common_rpc(network: Network) -> Client { ) .expect("Failed to open common client") } + fn wallet_rpc(network: Network, wallet: &str) -> Client { Client::new( &format!("{}/wallet/{}", RPC_URL, wallet), @@ -152,7 +172,7 @@ fn main() { // Segwit test let key = rand_key(); client_rpc - .send_segwit_key(network, &wire_addr, Amount::from_sat(4200), &key) + .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();