segwit-demo.rs (3722B)
1 use std::str::FromStr; 2 3 use bech32::Hrp; 4 use bitcoin::{Address, Amount, Network}; 5 use depolymerizer_bitcoin::{ 6 guess_network, rpc_utils, 7 segwit::{decode_segwit_msg, encode_segwit_addr}, 8 }; 9 use depolymerizer_common::rand_slice; 10 use taler_common::types::base32; 11 12 pub fn main() { 13 let address = Address::from_str("tb1qhxrhccqexg0dv4nltgkuw4fg2ce7muplmjsn0v") 14 .unwrap() 15 .assume_checked(); 16 let amount = Amount::from_sat(5000000); 17 let reserve_pub = "54ZN9AMVN1R0YZ68ZPVHHQA4KZE1V037M05FNMYH4JQ596YAKJEG"; 18 let btc = amount.to_btc(); 19 20 println!("Ⅰ - Parse payto uri"); 21 println!("Got payto uri: payto://bitcoin/{address}?amount=BTC:{btc}&subject={reserve_pub}"); 22 println!("Send {btc} BTC to {address} with reserve public key {reserve_pub}"); 23 24 println!("\nⅡ - Generate fake segwit addresses"); 25 let decoded: [u8; 32] = base32::decode(reserve_pub.as_bytes()).unwrap(); 26 println!("Decode reserve public key: 0x{}", hex::encode(&decoded[..])); 27 let prefix: [u8; 4] = rand_slice(); 28 println!("Generate random prefix 0x{}", hex::encode(prefix)); 29 println!( 30 "Split reserve public key in two:\n0x{}\n0x{}", 31 hex::encode(&decoded[..16]), 32 hex::encode(&decoded[16..]) 33 ); 34 let mut first_half = [&prefix, &decoded[..16]].concat(); 35 let mut second_half = [&prefix, &decoded[16..]].concat(); 36 println!( 37 "Concatenate random prefix with each reserve public key half:\n0x{}\n0x{}", 38 hex::encode(&first_half), 39 hex::encode(&second_half) 40 ); 41 first_half[0] &= 0b0111_1111; 42 second_half[0] |= 0b1000_0000; 43 println!( 44 "Set first bit of the first half:\n0x{}\nUnset first bit of the second half:\n0x{}", 45 hex::encode(&first_half), 46 hex::encode(&second_half) 47 ); 48 // bech32: https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki 49 let hrp = match guess_network(&address) { 50 Network::Bitcoin => "bc", 51 Network::Testnet | Network::Signet => "tb", 52 Network::Regtest => "bcrt", 53 _ => unimplemented!(), 54 }; 55 let hrp = Hrp::parse(hrp).unwrap(); 56 let first = encode_segwit_addr(hrp, first_half[..].try_into().unwrap()); 57 let second = encode_segwit_addr(hrp, second_half[..].try_into().unwrap()); 58 println!("Encode each half using bech32 to generate a segwit address:\n{first}\n{second}"); 59 60 println!("\nⅢ - Send to many"); 61 let minimum = rpc_utils::segwit_min_amount().to_btc(); 62 println!("Send a single bitcoin transaction with the three addresses as recipient as follow:"); 63 println!( 64 "\nIn bitcoincore wallet use 'Add Recipient' button to add two additional recipient and copy addresses and amounts" 65 ); 66 let first = Address::from_str(&first).unwrap().assume_checked(); 67 let second = Address::from_str(&second).unwrap().assume_checked(); 68 for (address, amount) in [(&address, btc), (&first, minimum), (&second, minimum)] { 69 println!("{address} {amount:.8} BTC"); 70 } 71 println!("\nIn Electrum wallet paste the following three lines in 'Pay to' field :"); 72 for (address, amount) in [(&address, btc), (&first, minimum), (&second, minimum)] { 73 println!("{address},{amount:.8}"); 74 } 75 println!( 76 "Make sure the amount show 0.10000588 BTC, else you have to change the base unit to BTC" 77 ); 78 79 let key1 = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"; 80 let key2 = "tb1qzxwu2p7urkqx0gq2ltfazf9w2jdu48ya8qwlm0"; 81 let key3 = "tb1qzxwu2pef8a224xagwq8hej8akuvd63yluu3wrh"; 82 let addresses = vec![key1, key2, key3]; 83 let dec = decode_segwit_msg(&addresses); 84 85 println!( 86 "Decode reserve public key: 0x{}", 87 hex::encode(&dec.unwrap()[..]) 88 ); 89 }