A simple example how to use libwally - from generation of the recovery phrase to signing of the psbt transaction

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?

UserRevisionLine numberNew 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 }