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
|
use std::str::FromStr;
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 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()[..])
);
}
|