summaryrefslogtreecommitdiff
path: root/btc-wire/src/bin/segwit-demo.rs
blob: ca9cc6d48ba8644fe84abfe8f017d1ce0f5a3870 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::str::FromStr;

use bech32::Hrp;
use bitcoin::{Address, Amount, Network};
use btc_wire::segwit::decode_segwit_msg;
use btc_wire::{rpc_utils, segwit::encode_segwit_addr};
use common::{
    base32::{self, Alphabet},
    rand_slice,
};

pub fn main() {
    let address = Address::from_str("tb1qhxrhccqexg0dv4nltgkuw4fg2ce7muplmjsn0v")
        .unwrap()
        .assume_checked();
    let amount = Amount::from_sat(5000000);
    let reserve_pub = "54ZN9AMVN1R0YZ68ZPVHHQA4KZE1V037M05FNMYH4JQ596YAKJEG";
    let btc = amount.to_btc();

    println!("Ⅰ - Parse payto uri");
    println!(
        "Got payto uri: payto://bitcoin/{}?amount=BTC:{}&subject={}",
        address, btc, reserve_pub
    );
    println!(
        "Send {} BTC to {} with reserve public key {}",
        btc, address, 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 prefix: [u8; 4] = rand_slice();
    println!("Generate random prefix 0x{}", hex::encode(prefix));
    println!(
        "Split reserve public key in two:\n0x{}\n0x{}",
        hex::encode(&decoded[..16]),
        hex::encode(&decoded[16..])
    );
    let mut first_half = [&prefix, &decoded[..16]].concat();
    let mut second_half = [&prefix, &decoded[16..]].concat();
    println!(
        "Concatenate random prefix 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 hrp = match address.network() {
        Network::Bitcoin => "bc",
        Network::Testnet | Network::Signet => "tb",
        Network::Regtest => "bcrt",
        _ => unimplemented!(),
    };
    let hrp = Hrp::parse(hrp).unwrap();
    let first = encode_segwit_addr(hrp, first_half[..].try_into().unwrap());
    let second = encode_segwit_addr(hrp, 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().to_btc();
    println!("Send a single bitcoin transaction with the three addresses as recipient as follow:");
    println!("\nIn bitcoincore wallet use 'Add Recipient' button to add two additional recipient and copy adresses and amounts");
    let first = Address::from_str(&first).unwrap().assume_checked();
    let second = Address::from_str(&second).unwrap().assume_checked();
    for (address, amount) in [(&address, btc), (&first, minimum), (&second, minimum)] {
        println!("{} {:.8} BTC", address, amount);
    }
    println!("\nIn Electrum wallet paste the following three lines in 'Pay to' field :");
    for (address, amount) in [(&address, btc), (&first, minimum), (&second, minimum)] {
        println!("{},{:.8}", address, amount);
    }
    println!(
        "Make sure the amount show 0.10000588 BTC, else you have to change the base unit to BTC"
    );

    let key1 = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4";
    let key2 = "tb1qzxwu2p7urkqx0gq2ltfazf9w2jdu48ya8qwlm0";
    let key3 = "tb1qzxwu2pef8a224xagwq8hej8akuvd63yluu3wrh";
    let addresses = vec![key1, key2, key3];
    let dec = decode_segwit_msg(&addresses);

    println!(
        "Decode reserve public key: 0x{}",
        hex::encode(&dec.unwrap()[..])
    );
}