depolymerization

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

commit 187f435336d86935a92b4d55a5a17cd5e24b9aab
parent 3e080b281767c1d9623cf97091d2e4e1c01b450c
Author: Antoine A <>
Date:   Tue, 15 Feb 2022 11:24:23 +0100

btc-wire: metadata doc draft

Diffstat:
MCargo.lock | 1+
Mbtc-wire/Cargo.toml | 2++
Mbtc-wire/README.md | 19+++++++++++++++++++
Abtc-wire/src/bin/segwit-demo.rs | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbtc-wire/src/segwit.rs | 2+-
Mcommon/src/lib.rs | 1+
Mmakefile | 7+++++--
Mscript/prepare.sh | 4++--
Mtest/conf/taler_btc_lifetime.conf | 1-
9 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -156,6 +156,7 @@ dependencies = [ "bitcoin", "common", "criterion", + "hex", "rust-ini", "serde", "serde_json", diff --git a/btc-wire/Cargo.toml b/btc-wire/Cargo.toml @@ -32,6 +32,8 @@ base64 = "0.13.0" common = { path = "../common" } # Ini parser rust-ini = "0.17.0" +# Hexadecimal encoding +hex = "0.4.3" [dev-dependencies] # statistics-driven micro-benchmarks diff --git a/btc-wire/README.md b/btc-wire/README.md @@ -40,6 +40,25 @@ the RPC server, `txindex=1` and `maxtxfee` are mandatory. 7. Run wire-gateway `wire-gateway` 8. Run btc-wire `btc-wire` +## Deposit metadata format + +Starting from a bitcoin payto URI you will have to generate fake segwit +addresses to encode the reserve public key as metadata into a common bitcoin +transaction. + +A single segwit address can contain 20B of chosen data and the reserve pub key +is 32B. We use two fake adresses consisting of the two key half prepended +with the same random pattern, at the exception of the first bit with must be 0 +for the first half and 1 for the second one. You must then send a single +transaction with the three addresses as recipients. + +As a few lines of code can carry more meaning that many words you can find a +[simple rust example](src/bin/segwit-demo.rs) in this project and run it with +`make segwit_demo`. + +Segwit addresses are encoded using a bitcoin specific format: [bech32]( +[bech32](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)) + ## Implementation details ### Stuck transaction diff --git a/btc-wire/src/bin/segwit-demo.rs b/btc-wire/src/bin/segwit-demo.rs @@ -0,0 +1,56 @@ +use bitcoin::Amount; +use btc_wire::{rpc_utils, segwit::encode_segwit_addr}; +use common::{ + base32::{self, Alphabet}, + rand_slice, +}; + +pub fn main() { + let address = "bc1qgkgxkjj27g3f7s87mcvjjsghay7gh34cx39prj"; + let amount = Amount::from_sat(10000000); + let reserve_pub = "0ZSX8SH0M30KHX8K3Y1DAMVGDQV82XEF9DG1HC4QMQ3QWYT4AF00"; + let btc = amount.as_btc(); + + println!("Ⅰ - Parse payto uri"); + println!("Got payto uri: payto://bitcoin/{address}?amount=BTC:{btc}&subject={reserve_pub}"); + println!("Send {btc} BTC to {address} with reserve public key {reserve_pub}"); + + println!("\nⅡ - Generate fake segwit addresses"); + let decoded: [u8; 32] = base32::decode(Alphabet::Crockford, reserve_pub) + .unwrap() + .try_into() + .unwrap(); + println!("Decode reserve public key: 0x{}", hex::encode(&decoded[..])); + let magic_id: [u8; 4] = rand_slice(); + println!("Generate magic id: 0x{}", hex::encode(&magic_id)); + println!( + "Split reserve public key in two:\n0x{}\n0x{}", + hex::encode(&decoded[..16]), + hex::encode(&decoded[16..]) + ); + let mut first_half = [&magic_id, &decoded[..16]].concat(); + let mut second_half = [&magic_id, &decoded[16..]].concat(); + println!( + "Concatenate magic id with each reserve public key half:\n0x{}\n0x{}", + hex::encode(&first_half), + hex::encode(&second_half) + ); + first_half[0] &= 0b0111_1111; + second_half[0] |= 0b1000_0000; + println!( + "Set first bit of the first half:\n0x{}\nUnset first bit of the second half:\n0x{}", + hex::encode(&first_half), + hex::encode(&second_half) + ); + // bech32: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki + let first = encode_segwit_addr("bc", first_half[..].try_into().unwrap()); + let second = encode_segwit_addr("bc", second_half[..].try_into().unwrap()); + println!( + "Encode each half using bech32 to generate a segwit address:\n{}\n{}", + first, second + ); + + println!("\nⅢ - Send to many"); + let minimum = rpc_utils::segwit_min_amount().as_btc(); + println!("Send a single bitcoin transaction with the three addresses as recipient as follow:\n{address} {btc}BTC\n{first} {minimum}BTC\n{second} {minimum}BTC"); +} diff --git a/btc-wire/src/segwit.rs b/btc-wire/src/segwit.rs @@ -17,7 +17,7 @@ use bech32::{u5, FromBase32, ToBase32, Variant}; use common::rand::{rngs::OsRng, RngCore}; /// Encode metadata into a segwit address -fn encode_segwit_addr(hrp: &str, metada: &[u8; 20]) -> String { +pub 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()); diff --git a/common/src/lib.rs b/common/src/lib.rs @@ -20,6 +20,7 @@ use rand::{rngs::OsRng, RngCore}; pub use postgres; pub use rand; pub use url; +pub use base32; pub mod api_common; pub mod api_wire; diff --git a/makefile b/makefile @@ -28,4 +28,7 @@ test_eth: install test/eth/hell.sh test/eth/analysis.sh -test: install test_gateway test_eth test_btc -\ No newline at end of file +test: install test_gateway test_eth test_btc + +segwit_demo: + cargo run --release --bin segwit-demo +\ No newline at end of file diff --git a/script/prepare.sh b/script/prepare.sh @@ -33,7 +33,7 @@ tar xvzf btc.tar.gz mv -v bitcoin-22.0/* ~/bitcoin -echo "Ⅳ - Install Go Ethereum (Geth) v1.10.15 " +echo "Ⅲ - Install Go Ethereum (Geth) v1.10.15 " cd $DIR curl -L https://gethstore.blob.core.windows.net/builds/geth-alltools-linux-amd64-1.10.15-8be800ff.tar.gz -o geth.tar.gz rm -rfv ~/geth @@ -41,7 +41,7 @@ mkdir -pv ~/geth tar xvzf geth.tar.gz mv -v geth-alltools-linux-amd64-1.10.15-8be800ff/* ~/geth -echo "Ⅲ - Config" +echo "Ⅳ - Config" echo "Add ~/postgresql/bin to your path" echo "Add ~/bitcoin/bin to your path" diff --git a/test/conf/taler_btc_lifetime.conf b/test/conf/taler_btc_lifetime.conf @@ -9,6 +9,5 @@ DB_URL = postgres://localhost:5454/postgres?user=postgres&password=passwo PORT = 8060 PAYTO = payto://bitcoin/bcrt1qgkgxkjj27g3f7s87mcvjjsghay7gh34cx39prj CONFIRMATION = 3 -BOUNCE_FEE = 1000 HTTP_LIFETIME = 10 WIRE_LIFETIME = 10 \ No newline at end of file