A simple example how to use libwally - from generation of the recovery phrase to signing of the psbt transaction
main.cpp@3:3d6e031ab07b, 2019-09-19 (annotated)
- Committer:
- diybitcoinhardware
- Date:
- Thu Sep 19 09:21:23 2019 +0000
- Revision:
- 3:3d6e031ab07b
- Parent:
- 0:3729443d0bf8
alloc the keys
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
diybitcoinhardware | 0:3729443d0bf8 | 1 | #include "mbed.h" |
diybitcoinhardware | 0:3729443d0bf8 | 2 | |
diybitcoinhardware | 0:3729443d0bf8 | 3 | #include "wally_core.h" |
diybitcoinhardware | 0:3729443d0bf8 | 4 | #include "wally_bip32.h" |
diybitcoinhardware | 0:3729443d0bf8 | 5 | #include "wally_bip39.h" |
diybitcoinhardware | 0:3729443d0bf8 | 6 | #include "wally_address.h" |
diybitcoinhardware | 0:3729443d0bf8 | 7 | |
diybitcoinhardware | 0:3729443d0bf8 | 8 | #include "wally_psbt.h" |
diybitcoinhardware | 0:3729443d0bf8 | 9 | #include "wally_script.h" |
diybitcoinhardware | 0:3729443d0bf8 | 10 | |
diybitcoinhardware | 0:3729443d0bf8 | 11 | RawSerial pc(SERIAL_TX, SERIAL_RX, 115200); |
diybitcoinhardware | 0:3729443d0bf8 | 12 | |
diybitcoinhardware | 0:3729443d0bf8 | 13 | // small helper functions that prints |
diybitcoinhardware | 0:3729443d0bf8 | 14 | // data in hex to the serial port |
diybitcoinhardware | 0:3729443d0bf8 | 15 | void print_hex(const uint8_t * data, size_t data_len){ |
diybitcoinhardware | 0:3729443d0bf8 | 16 | for(int i=0; i<data_len; i++){ |
diybitcoinhardware | 0:3729443d0bf8 | 17 | printf("%02x", data[i]); |
diybitcoinhardware | 0:3729443d0bf8 | 18 | } |
diybitcoinhardware | 0:3729443d0bf8 | 19 | } |
diybitcoinhardware | 0:3729443d0bf8 | 20 | // just adds a new line to the end of the data |
diybitcoinhardware | 0:3729443d0bf8 | 21 | void println_hex(const uint8_t * data, size_t data_len){ |
diybitcoinhardware | 0:3729443d0bf8 | 22 | print_hex(data, data_len); |
diybitcoinhardware | 0:3729443d0bf8 | 23 | printf("\r\n"); |
diybitcoinhardware | 0:3729443d0bf8 | 24 | } |
diybitcoinhardware | 0:3729443d0bf8 | 25 | // prints error and hangs forever |
diybitcoinhardware | 0:3729443d0bf8 | 26 | void err(const char * message, void * data = NULL){ |
diybitcoinhardware | 0:3729443d0bf8 | 27 | printf("ERROR: %s\r\n", message); |
diybitcoinhardware | 0:3729443d0bf8 | 28 | while(1){ |
diybitcoinhardware | 0:3729443d0bf8 | 29 | wait(1); |
diybitcoinhardware | 0:3729443d0bf8 | 30 | } |
diybitcoinhardware | 0:3729443d0bf8 | 31 | } |
diybitcoinhardware | 0:3729443d0bf8 | 32 | |
diybitcoinhardware | 0:3729443d0bf8 | 33 | void print_psbt(const wally_psbt * psbt); |
diybitcoinhardware | 0:3729443d0bf8 | 34 | |
diybitcoinhardware | 0:3729443d0bf8 | 35 | void libwally_example(){ |
diybitcoinhardware | 0:3729443d0bf8 | 36 | size_t len; // to store length of serialization etc |
diybitcoinhardware | 0:3729443d0bf8 | 37 | int res; // to store wally's results |
diybitcoinhardware | 0:3729443d0bf8 | 38 | |
diybitcoinhardware | 0:3729443d0bf8 | 39 | // we need to initialize libwally first |
diybitcoinhardware | 0:3729443d0bf8 | 40 | res = wally_init(0); |
diybitcoinhardware | 0:3729443d0bf8 | 41 | |
diybitcoinhardware | 0:3729443d0bf8 | 42 | /**************** BIP-39 recovery phrase ******************/ |
diybitcoinhardware | 0:3729443d0bf8 | 43 | |
diybitcoinhardware | 0:3729443d0bf8 | 44 | // random buffer should be generated by TRNG or somehow else |
diybitcoinhardware | 0:3729443d0bf8 | 45 | // but we will use predefined one for demo purposes |
diybitcoinhardware | 0:3729443d0bf8 | 46 | // 16 bytes will generate a 12-word recovery phrase |
diybitcoinhardware | 0:3729443d0bf8 | 47 | uint8_t rnd[] = { |
diybitcoinhardware | 0:3729443d0bf8 | 48 | 0xbd, 0xb5, 0x1a, 0x16, 0xeb, 0x64, 0x60, 0xec, |
diybitcoinhardware | 0:3729443d0bf8 | 49 | 0x16, 0xf8, 0x4d, 0x7b, 0x6f, 0x19, 0xe2, 0x0d |
diybitcoinhardware | 0:3729443d0bf8 | 50 | }; |
diybitcoinhardware | 0:3729443d0bf8 | 51 | |
diybitcoinhardware | 0:3729443d0bf8 | 52 | // creating a recovery phrase |
diybitcoinhardware | 0:3729443d0bf8 | 53 | char *phrase = NULL; |
diybitcoinhardware | 0:3729443d0bf8 | 54 | res = bip39_mnemonic_from_bytes(NULL, rnd, sizeof(rnd), &phrase); |
diybitcoinhardware | 0:3729443d0bf8 | 55 | printf("Recovery phrase: %s\r\n", phrase); |
diybitcoinhardware | 0:3729443d0bf8 | 56 | |
diybitcoinhardware | 0:3729443d0bf8 | 57 | // converting recovery phrase to seed |
diybitcoinhardware | 0:3729443d0bf8 | 58 | uint8_t seed[BIP39_SEED_LEN_512]; |
diybitcoinhardware | 0:3729443d0bf8 | 59 | res = bip39_mnemonic_to_seed(phrase, "my password", seed, sizeof(seed), &len); |
diybitcoinhardware | 0:3729443d0bf8 | 60 | |
diybitcoinhardware | 0:3729443d0bf8 | 61 | // don't forget to securely clean up the string when done |
diybitcoinhardware | 0:3729443d0bf8 | 62 | wally_free_string(phrase); |
diybitcoinhardware | 0:3729443d0bf8 | 63 | |
diybitcoinhardware | 0:3729443d0bf8 | 64 | printf("Seed: "); |
diybitcoinhardware | 0:3729443d0bf8 | 65 | println_hex(seed, sizeof(seed)); |
diybitcoinhardware | 0:3729443d0bf8 | 66 | |
diybitcoinhardware | 0:3729443d0bf8 | 67 | /**************** BIP-32 HD keys ******************/ |
diybitcoinhardware | 0:3729443d0bf8 | 68 | |
diybitcoinhardware | 0:3729443d0bf8 | 69 | // root HD key |
diybitcoinhardware | 3:3d6e031ab07b | 70 | ext_key * root = NULL; |
diybitcoinhardware | 3:3d6e031ab07b | 71 | res = bip32_key_from_seed_alloc(seed, sizeof(seed), BIP32_VER_TEST_PRIVATE, 0, &root); |
diybitcoinhardware | 0:3729443d0bf8 | 72 | // get base58 xprv string |
diybitcoinhardware | 0:3729443d0bf8 | 73 | char *xprv = NULL; |
diybitcoinhardware | 3:3d6e031ab07b | 74 | res = bip32_key_to_base58(root, BIP32_FLAG_KEY_PRIVATE, &xprv); |
diybitcoinhardware | 0:3729443d0bf8 | 75 | printf("Root key: %s\r\n", xprv); |
diybitcoinhardware | 0:3729443d0bf8 | 76 | // don't forget to securely clean up the string when done |
diybitcoinhardware | 0:3729443d0bf8 | 77 | wally_free_string(xprv); |
diybitcoinhardware | 0:3729443d0bf8 | 78 | |
diybitcoinhardware | 0:3729443d0bf8 | 79 | // deriving account key for native segwit, testnet: m/84h/1h/0h |
diybitcoinhardware | 3:3d6e031ab07b | 80 | ext_key * account = NULL; |
diybitcoinhardware | 0:3729443d0bf8 | 81 | uint32_t path[] = { |
diybitcoinhardware | 0:3729443d0bf8 | 82 | BIP32_INITIAL_HARDENED_CHILD+84, // 84h |
diybitcoinhardware | 0:3729443d0bf8 | 83 | BIP32_INITIAL_HARDENED_CHILD+1, // 1h |
diybitcoinhardware | 0:3729443d0bf8 | 84 | BIP32_INITIAL_HARDENED_CHILD // 0h |
diybitcoinhardware | 0:3729443d0bf8 | 85 | }; |
diybitcoinhardware | 3:3d6e031ab07b | 86 | res = bip32_key_from_parent_path_alloc(root, path, 3, BIP32_FLAG_KEY_PRIVATE, &account); |
diybitcoinhardware | 0:3729443d0bf8 | 87 | |
diybitcoinhardware | 3:3d6e031ab07b | 88 | res = bip32_key_to_base58(account, BIP32_FLAG_KEY_PRIVATE, &xprv); |
diybitcoinhardware | 0:3729443d0bf8 | 89 | printf("Account private key: %s\r\n", xprv); |
diybitcoinhardware | 0:3729443d0bf8 | 90 | // don't forget to securely clean up the string when done |
diybitcoinhardware | 0:3729443d0bf8 | 91 | wally_free_string(xprv); |
diybitcoinhardware | 0:3729443d0bf8 | 92 | |
diybitcoinhardware | 0:3729443d0bf8 | 93 | char *xpub = NULL; |
diybitcoinhardware | 3:3d6e031ab07b | 94 | res = bip32_key_to_base58(account, BIP32_FLAG_KEY_PUBLIC, &xpub); |
diybitcoinhardware | 0:3729443d0bf8 | 95 | printf("Account public key: %s\r\n", xpub); |
diybitcoinhardware | 0:3729443d0bf8 | 96 | |
diybitcoinhardware | 0:3729443d0bf8 | 97 | // fingerprint |
diybitcoinhardware | 0:3729443d0bf8 | 98 | printf("Derivation information: ["); |
diybitcoinhardware | 3:3d6e031ab07b | 99 | print_hex(root->hash160, 4); |
diybitcoinhardware | 0:3729443d0bf8 | 100 | printf("/84h/1h/0h]%s\r\n", xpub); |
diybitcoinhardware | 0:3729443d0bf8 | 101 | |
diybitcoinhardware | 0:3729443d0bf8 | 102 | // don't forget to securely clean up the string when done |
diybitcoinhardware | 0:3729443d0bf8 | 103 | wally_free_string(xpub); |
diybitcoinhardware | 0:3729443d0bf8 | 104 | |
diybitcoinhardware | 0:3729443d0bf8 | 105 | /**************** Addresses ******************/ |
diybitcoinhardware | 0:3729443d0bf8 | 106 | |
diybitcoinhardware | 0:3729443d0bf8 | 107 | // key for the first address |
diybitcoinhardware | 3:3d6e031ab07b | 108 | ext_key * first_recv = NULL; |
diybitcoinhardware | 0:3729443d0bf8 | 109 | uint32_t recv_path[] = {0, 0}; |
diybitcoinhardware | 0:3729443d0bf8 | 110 | // we only need public key here, no need in private key |
diybitcoinhardware | 3:3d6e031ab07b | 111 | res = bip32_key_from_parent_path_alloc(account, recv_path, 2, BIP32_FLAG_KEY_PUBLIC, &first_recv); |
diybitcoinhardware | 0:3729443d0bf8 | 112 | char * addr = NULL; |
diybitcoinhardware | 0:3729443d0bf8 | 113 | |
diybitcoinhardware | 0:3729443d0bf8 | 114 | // native segwit address |
diybitcoinhardware | 3:3d6e031ab07b | 115 | res = wally_bip32_key_to_addr_segwit(first_recv, "tb", 0, &addr); |
diybitcoinhardware | 0:3729443d0bf8 | 116 | printf("Segwit address: %s\r\n", addr); |
diybitcoinhardware | 0:3729443d0bf8 | 117 | wally_free_string(addr); |
diybitcoinhardware | 0:3729443d0bf8 | 118 | |
diybitcoinhardware | 0:3729443d0bf8 | 119 | // nested segwit address |
diybitcoinhardware | 3:3d6e031ab07b | 120 | res = wally_bip32_key_to_address(first_recv, WALLY_ADDRESS_TYPE_P2SH_P2WPKH, WALLY_ADDRESS_VERSION_P2SH_TESTNET, &addr); |
diybitcoinhardware | 0:3729443d0bf8 | 121 | printf("Nested segwit address: %s\r\n", addr); |
diybitcoinhardware | 0:3729443d0bf8 | 122 | wally_free_string(addr); |
diybitcoinhardware | 0:3729443d0bf8 | 123 | |
diybitcoinhardware | 0:3729443d0bf8 | 124 | // legacy address |
diybitcoinhardware | 3:3d6e031ab07b | 125 | res = wally_bip32_key_to_address(first_recv, WALLY_ADDRESS_TYPE_P2PKH, WALLY_ADDRESS_VERSION_P2PKH_TESTNET, &addr); |
diybitcoinhardware | 0:3729443d0bf8 | 126 | printf("Legacy address: %s\r\n", addr); |
diybitcoinhardware | 0:3729443d0bf8 | 127 | wally_free_string(addr); |
diybitcoinhardware | 0:3729443d0bf8 | 128 | |
diybitcoinhardware | 0:3729443d0bf8 | 129 | /**************** PSBT ******************/ |
diybitcoinhardware | 0:3729443d0bf8 | 130 | |
diybitcoinhardware | 3:3d6e031ab07b | 131 | char b64_psbt[] = "cHNidP8BAHICAAAAAX7U8W8nyYJcYzFjoHa5UH5j0Ug43ej/q2bf" |
diybitcoinhardware | 3:3d6e031ab07b | 132 | "IPq8XnjeAAAAAAD/////AihATAAAAAAAFgAUPE9Ix5e2qWWcDW78" |
diybitcoinhardware | 3:3d6e031ab07b | 133 | "DM+uqX09ANNAS0wAAAAAABepFPPNvp1TAyho+Kys4wwejY8iakgQ" |
diybitcoinhardware | 3:3d6e031ab07b | 134 | "hwAAAAAAAQEfgJaYAAAAAAAWABRy2Nt/+F2j9EYd2bcI5CfSqeey" |
diybitcoinhardware | 3:3d6e031ab07b | 135 | "MSIGAmijc35Kh8Nfa9oC0jGb2I1UfzkS0MqAfHw0BKA6JRwuGCbd" |
diybitcoinhardware | 3:3d6e031ab07b | 136 | "2XhUAACAAQAAgAAAAIAAAAAAAAAAAAAiAgOTSWH+F+K8DsY9lzWM" |
diybitcoinhardware | 3:3d6e031ab07b | 137 | "QZJptjBUmMVgdE+1814LZMwVFRgm3dl4VAAAgAEAAIAAAACAAQAAAAAAAAAAAA=="; |
diybitcoinhardware | 0:3729443d0bf8 | 138 | wally_psbt * psbt = NULL; |
diybitcoinhardware | 0:3729443d0bf8 | 139 | res = wally_psbt_from_base64(b64_psbt, &psbt); |
diybitcoinhardware | 0:3729443d0bf8 | 140 | |
diybitcoinhardware | 0:3729443d0bf8 | 141 | print_psbt(psbt); |
diybitcoinhardware | 0:3729443d0bf8 | 142 | |
diybitcoinhardware | 0:3729443d0bf8 | 143 | for(int i = 0; i < psbt->num_inputs; i++){ |
diybitcoinhardware | 0:3729443d0bf8 | 144 | if(!psbt->inputs[i].witness_utxo){ |
diybitcoinhardware | 0:3729443d0bf8 | 145 | printf("Too lazy for legacy"); |
diybitcoinhardware | 0:3729443d0bf8 | 146 | return; |
diybitcoinhardware | 0:3729443d0bf8 | 147 | } |
diybitcoinhardware | 0:3729443d0bf8 | 148 | uint8_t hash[32]; |
diybitcoinhardware | 0:3729443d0bf8 | 149 | uint8_t script[25]; |
diybitcoinhardware | 0:3729443d0bf8 | 150 | printf("scriptpubkey: "); |
diybitcoinhardware | 0:3729443d0bf8 | 151 | println_hex(psbt->inputs[i].witness_utxo->script, psbt->inputs[i].witness_utxo->script_len); |
diybitcoinhardware | 0:3729443d0bf8 | 152 | wally_scriptpubkey_p2pkh_from_bytes( |
diybitcoinhardware | 0:3729443d0bf8 | 153 | psbt->inputs[i].witness_utxo->script+2, 20, |
diybitcoinhardware | 0:3729443d0bf8 | 154 | 0, |
diybitcoinhardware | 0:3729443d0bf8 | 155 | script, 25, &len); |
diybitcoinhardware | 0:3729443d0bf8 | 156 | printf("scriptpubkey: "); |
diybitcoinhardware | 0:3729443d0bf8 | 157 | println_hex(script, len); |
diybitcoinhardware | 0:3729443d0bf8 | 158 | wally_tx_get_btc_signature_hash(psbt->tx, i, |
diybitcoinhardware | 0:3729443d0bf8 | 159 | script, len, |
diybitcoinhardware | 0:3729443d0bf8 | 160 | psbt->inputs[i].witness_utxo->satoshi, |
diybitcoinhardware | 0:3729443d0bf8 | 161 | WALLY_SIGHASH_ALL, |
diybitcoinhardware | 0:3729443d0bf8 | 162 | WALLY_TX_FLAG_USE_WITNESS, |
diybitcoinhardware | 0:3729443d0bf8 | 163 | hash, 32 |
diybitcoinhardware | 0:3729443d0bf8 | 164 | ); |
diybitcoinhardware | 0:3729443d0bf8 | 165 | printf("Input %d. Hash to sign: ", i); |
diybitcoinhardware | 0:3729443d0bf8 | 166 | println_hex(hash, 32); |
diybitcoinhardware | 3:3d6e031ab07b | 167 | ext_key * pk = NULL; |
diybitcoinhardware | 3:3d6e031ab07b | 168 | bip32_key_from_parent_path_alloc(root, |
diybitcoinhardware | 0:3729443d0bf8 | 169 | psbt->inputs[i].keypaths->items[0].origin.path, |
diybitcoinhardware | 0:3729443d0bf8 | 170 | psbt->inputs[i].keypaths->items[0].origin.path_len, |
diybitcoinhardware | 0:3729443d0bf8 | 171 | BIP32_FLAG_KEY_PRIVATE, &pk); |
diybitcoinhardware | 0:3729443d0bf8 | 172 | |
diybitcoinhardware | 0:3729443d0bf8 | 173 | uint8_t sig[EC_SIGNATURE_LEN]; |
diybitcoinhardware | 0:3729443d0bf8 | 174 | wally_ec_sig_from_bytes( |
diybitcoinhardware | 3:3d6e031ab07b | 175 | pk->priv_key+1, 32, // first byte of ext_key.priv_key is 0x00 |
diybitcoinhardware | 0:3729443d0bf8 | 176 | hash, 32, |
diybitcoinhardware | 0:3729443d0bf8 | 177 | EC_FLAG_ECDSA, |
diybitcoinhardware | 0:3729443d0bf8 | 178 | sig, EC_SIGNATURE_LEN |
diybitcoinhardware | 0:3729443d0bf8 | 179 | ); |
diybitcoinhardware | 3:3d6e031ab07b | 180 | bip32_key_free(pk); |
diybitcoinhardware | 0:3729443d0bf8 | 181 | uint8_t der[EC_SIGNATURE_DER_MAX_LEN+1]; |
diybitcoinhardware | 0:3729443d0bf8 | 182 | wally_ec_sig_to_der( |
diybitcoinhardware | 0:3729443d0bf8 | 183 | sig, EC_SIGNATURE_LEN, |
diybitcoinhardware | 0:3729443d0bf8 | 184 | der, EC_SIGNATURE_DER_MAX_LEN, |
diybitcoinhardware | 0:3729443d0bf8 | 185 | &len |
diybitcoinhardware | 0:3729443d0bf8 | 186 | ); |
diybitcoinhardware | 0:3729443d0bf8 | 187 | der[len] = WALLY_SIGHASH_ALL; |
diybitcoinhardware | 0:3729443d0bf8 | 188 | if(!psbt->inputs[i].partial_sigs){ |
diybitcoinhardware | 0:3729443d0bf8 | 189 | partial_sigs_map_init_alloc(1, &psbt->inputs[i].partial_sigs); |
diybitcoinhardware | 0:3729443d0bf8 | 190 | } |
diybitcoinhardware | 0:3729443d0bf8 | 191 | add_new_partial_sig(psbt->inputs[i].partial_sigs, |
diybitcoinhardware | 3:3d6e031ab07b | 192 | pk->pub_key, |
diybitcoinhardware | 0:3729443d0bf8 | 193 | der, len+1 |
diybitcoinhardware | 0:3729443d0bf8 | 194 | ); |
diybitcoinhardware | 0:3729443d0bf8 | 195 | } |
diybitcoinhardware | 0:3729443d0bf8 | 196 | |
diybitcoinhardware | 0:3729443d0bf8 | 197 | char * output; |
diybitcoinhardware | 0:3729443d0bf8 | 198 | wally_psbt_to_base64(psbt, &output); |
diybitcoinhardware | 0:3729443d0bf8 | 199 | wally_psbt_free(psbt); |
diybitcoinhardware | 0:3729443d0bf8 | 200 | |
diybitcoinhardware | 0:3729443d0bf8 | 201 | printf("PSBT: %s\r\n", output); |
diybitcoinhardware | 0:3729443d0bf8 | 202 | wally_free_string(output); |
diybitcoinhardware | 0:3729443d0bf8 | 203 | |
diybitcoinhardware | 3:3d6e031ab07b | 204 | bip32_key_free(root); |
diybitcoinhardware | 3:3d6e031ab07b | 205 | bip32_key_free(account); |
diybitcoinhardware | 0:3729443d0bf8 | 206 | wally_cleanup(0); |
diybitcoinhardware | 0:3729443d0bf8 | 207 | } |
diybitcoinhardware | 0:3729443d0bf8 | 208 | |
diybitcoinhardware | 0:3729443d0bf8 | 209 | void print_psbt(const wally_psbt * psbt){ |
diybitcoinhardware | 0:3729443d0bf8 | 210 | printf("PSBT:\r\n" |
diybitcoinhardware | 0:3729443d0bf8 | 211 | "Inputs: %d\r\n", psbt->num_inputs); |
diybitcoinhardware | 0:3729443d0bf8 | 212 | uint64_t in_amount = 0; |
diybitcoinhardware | 0:3729443d0bf8 | 213 | for(int i = 0; i < psbt->num_inputs; i++){ |
diybitcoinhardware | 0:3729443d0bf8 | 214 | if(!psbt->inputs[i].witness_utxo){ |
diybitcoinhardware | 0:3729443d0bf8 | 215 | printf("Non-segwit input or prev output is missing! It's bad..."); |
diybitcoinhardware | 0:3729443d0bf8 | 216 | return; |
diybitcoinhardware | 0:3729443d0bf8 | 217 | } |
diybitcoinhardware | 0:3729443d0bf8 | 218 | in_amount += psbt->inputs[i].witness_utxo->satoshi; |
diybitcoinhardware | 0:3729443d0bf8 | 219 | } |
diybitcoinhardware | 0:3729443d0bf8 | 220 | printf("Spending %llu satoshi\r\n", in_amount); |
diybitcoinhardware | 0:3729443d0bf8 | 221 | printf("Outputs: %d\r\n", psbt->tx->num_outputs); |
diybitcoinhardware | 0:3729443d0bf8 | 222 | uint64_t out_amount = 0; |
diybitcoinhardware | 0:3729443d0bf8 | 223 | for(int i=0; i < psbt->tx->num_outputs; i++){ |
diybitcoinhardware | 0:3729443d0bf8 | 224 | size_t script_type; |
diybitcoinhardware | 0:3729443d0bf8 | 225 | wally_scriptpubkey_get_type(psbt->tx->outputs[i].script, psbt->tx->outputs[i].script_len, &script_type); |
diybitcoinhardware | 0:3729443d0bf8 | 226 | char * addr = NULL; |
diybitcoinhardware | 0:3729443d0bf8 | 227 | uint8_t bytes[21]; |
diybitcoinhardware | 0:3729443d0bf8 | 228 | // should deal with all script types, only P2WPKH for now |
diybitcoinhardware | 0:3729443d0bf8 | 229 | switch(script_type){ |
diybitcoinhardware | 0:3729443d0bf8 | 230 | case WALLY_SCRIPT_TYPE_P2WPKH: |
diybitcoinhardware | 0:3729443d0bf8 | 231 | case WALLY_SCRIPT_TYPE_P2WSH: |
diybitcoinhardware | 0:3729443d0bf8 | 232 | wally_addr_segwit_from_bytes(psbt->tx->outputs[i].script, psbt->tx->outputs[i].script_len, "tb", 0, &addr); |
diybitcoinhardware | 0:3729443d0bf8 | 233 | break; |
diybitcoinhardware | 0:3729443d0bf8 | 234 | case WALLY_SCRIPT_TYPE_P2SH: |
diybitcoinhardware | 0:3729443d0bf8 | 235 | bytes[0] = WALLY_ADDRESS_VERSION_P2SH_TESTNET; |
diybitcoinhardware | 0:3729443d0bf8 | 236 | memcpy(bytes+1, psbt->tx->outputs[i].script+2, 20); |
diybitcoinhardware | 0:3729443d0bf8 | 237 | wally_base58_from_bytes(bytes, 21, BASE58_FLAG_CHECKSUM, &addr); |
diybitcoinhardware | 0:3729443d0bf8 | 238 | break; |
diybitcoinhardware | 0:3729443d0bf8 | 239 | case WALLY_SCRIPT_TYPE_P2PKH: |
diybitcoinhardware | 0:3729443d0bf8 | 240 | bytes[0] = WALLY_ADDRESS_VERSION_P2PKH_TESTNET; |
diybitcoinhardware | 0:3729443d0bf8 | 241 | memcpy(bytes+1, psbt->tx->outputs[i].script+3, 20); |
diybitcoinhardware | 0:3729443d0bf8 | 242 | wally_base58_from_bytes(bytes, 21, BASE58_FLAG_CHECKSUM, &addr); |
diybitcoinhardware | 0:3729443d0bf8 | 243 | break; |
diybitcoinhardware | 0:3729443d0bf8 | 244 | } |
diybitcoinhardware | 0:3729443d0bf8 | 245 | // TODO: also verify if it is a change address |
diybitcoinhardware | 0:3729443d0bf8 | 246 | if(addr){ |
diybitcoinhardware | 0:3729443d0bf8 | 247 | printf("- Out %d: %llu sat to %s\r\n", i+1, psbt->tx->outputs[i].satoshi, addr); |
diybitcoinhardware | 0:3729443d0bf8 | 248 | wally_free_string(addr); |
diybitcoinhardware | 0:3729443d0bf8 | 249 | }else{ |
diybitcoinhardware | 0:3729443d0bf8 | 250 | printf("- Out %d: %llu sat to %s\r\n", i+1, psbt->tx->outputs[i].satoshi, "...custom script..."); |
diybitcoinhardware | 0:3729443d0bf8 | 251 | } |
diybitcoinhardware | 0:3729443d0bf8 | 252 | out_amount += psbt->tx->outputs[i].satoshi; |
diybitcoinhardware | 0:3729443d0bf8 | 253 | } |
diybitcoinhardware | 0:3729443d0bf8 | 254 | printf("Fee: %llu sat\r\n", in_amount-out_amount); |
diybitcoinhardware | 0:3729443d0bf8 | 255 | } |
diybitcoinhardware | 0:3729443d0bf8 | 256 | |
diybitcoinhardware | 0:3729443d0bf8 | 257 | int main(){ |
diybitcoinhardware | 0:3729443d0bf8 | 258 | printf("Press any key to continue\r\n"); |
diybitcoinhardware | 0:3729443d0bf8 | 259 | pc.getc(); |
diybitcoinhardware | 0:3729443d0bf8 | 260 | printf("Ready to go!\r\n"); |
diybitcoinhardware | 0:3729443d0bf8 | 261 | |
diybitcoinhardware | 0:3729443d0bf8 | 262 | printf("=== Running example for libwally ===\r\n"); |
diybitcoinhardware | 0:3729443d0bf8 | 263 | libwally_example(); |
diybitcoinhardware | 0:3729443d0bf8 | 264 | |
diybitcoinhardware | 0:3729443d0bf8 | 265 | printf("\r\n=== Done ===\r\n"); |
diybitcoinhardware | 0:3729443d0bf8 | 266 | |
diybitcoinhardware | 0:3729443d0bf8 | 267 | } |