1 #include "config.h"
2 
3 #include <wally_transaction.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdbool.h>
8 
9 static const char *p2pkh_hex =
10     "0100000001be66e10da854e7aea9338c1f91cd489768d1d6d7189f586d7a3613f2a24d5396000000008b483045022100da43201760bda697222002f56266bf65023fef2094519e13077f777baed553b102205ce35d05eabda58cd50a67977a65706347cc25ef43153e309ff210a134722e9e0141042daa93315eebbe2cb9b5c3505df4c6fb6caca8b756786098567550d4820c09db988fe9997d049d687292f815ccd6e7fb5c1b1a91137999818d17c73d0f80aef9ffffffff0123ce0100000000001976a9142bc89c2702e0e618db7d59eb5ce2f0f147b4075488ac00000000";
11 
12 static const char *wit_hex = "020000000001012f94ddd965758445be2dfac132c5e75c517edf5ea04b745a953d0bc04c32829901000000006aedc98002a8c500000000000022002009246bbe3beb48cf1f6f2954f90d648eb04d68570b797e104fead9e6c3c87fd40544020000000000160014c221cdfc1b867d82f19d761d4e09f3b6216d8a8304004830450221008aaa56e4f0efa1f7b7ed690944ac1b59f046a59306fcd1d09924936bd500046d02202b22e13a2ad7e16a0390d726c56dfc9f07647f7abcfac651e35e5dc9d830fc8a01483045022100e096ad0acdc9e8261d1cdad973f7f234ee84a6ee68e0b89ff0c1370896e63fe102202ec36d7554d1feac8bc297279f89830da98953664b73d38767e81ee0763b9988014752210390134e68561872313ba59e56700732483f4a43c2de24559cb8c7039f25f7faf821039eb59b267a78f1020f27a83dc5e3b1e4157e4a517774040a196e9f43f08ad17d52ae89a3b720";
13 
14 static const char *coinbase_hex = "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff4b03464d0804c97bb35b642f4254432e434f4d2ffabe6d6d1a6db4ee2dab39db5d871f8ddf5eaf687a3d3f94996a328fe67e89971f80c64e01000000000000006675aeb700000000bd920000ffffffff03aeef224e0000000016001497cfc76442fe717f2a3f0cc9c175f7561b6619970000000000000000266a24aa21a9ed742e7ee7bf189ccc148c8d4e32d39fc1d3ea1340c7473094e5f8a5077716db8200000000000000002952534b424c4f434b3afe833adaeb81adc753269cdd3e4225c199637e7921996cadd94803adbe87f79c0120000000000000000000000000000000000000000000000000000000000000000000000000";
15 
16 #define check_ret(r) if (r != WALLY_OK) return false
17 
tx_roundtrip(const char * tx_hex)18 static bool tx_roundtrip(const char *tx_hex)
19 {
20     struct wally_tx *tx;
21     struct wally_tx_input *in, *new_in;
22     struct wally_tx_output *out, *new_out;
23     char *new_hex;
24     size_t i;
25     int ret;
26 
27     /* Unserialize and serialize the tx and verify they match */
28     ret = wally_tx_from_hex(tx_hex, WALLY_TX_FLAG_USE_WITNESS, &tx);
29     check_ret(ret);
30 
31     ret = wally_tx_to_hex(tx, WALLY_TX_FLAG_USE_WITNESS, &new_hex);
32     if (ret != WALLY_OK || strcmp(tx_hex, new_hex))
33         return false;
34 
35     ret = wally_free_string(new_hex);
36     check_ret(ret);
37 
38     /* Test adding and removing inputs */
39     in = &tx->inputs[0];
40     ret = wally_tx_input_init_alloc(in->txhash, sizeof(in->txhash),
41                                     in->index, in->sequence,
42                                     in->script, in->script_len, in->witness,
43                                     &new_in);
44     check_ret(ret);
45 
46     for (i = 0; i < 5; ++i) {
47         ret = wally_tx_add_input(tx, new_in);
48         check_ret(ret);
49     }
50     ret = wally_tx_remove_input(tx, 5); /* Remove last */
51     check_ret(ret);
52     ret = wally_tx_add_raw_input(tx, new_in->txhash, WALLY_TXHASH_LEN,
53                                  new_in->index, new_in->sequence,
54                                  new_in->script, new_in->script_len,
55                                  new_in->witness, 0);
56     check_ret(ret);
57     ret = wally_tx_remove_input(tx, 3); /* Remove middle */
58     check_ret(ret);
59     ret = wally_tx_remove_input(tx, 2); /* Remove middle */
60     check_ret(ret);
61     ret = wally_tx_remove_input(tx, 0); /* Remove first */
62     check_ret(ret);
63 
64     /* Test adding and removing outputs */
65     out = &tx->outputs[0];
66     ret = wally_tx_output_init_alloc(out->satoshi,
67                                      out->script, out->script_len, &new_out);
68     check_ret(ret);
69 
70     for (i = 0; i < 5; ++i) {
71         ret = wally_tx_add_output(tx, new_out);
72         check_ret(ret);
73     }
74 
75     ret = wally_tx_remove_output(tx, 5); /* Remove last */
76     check_ret(ret);
77     ret = wally_tx_add_raw_output(tx, new_out->satoshi, new_out->script, new_out->script_len, 0);
78     check_ret(ret);
79     ret = wally_tx_remove_output(tx, 3); /* Remove middle */
80     check_ret(ret);
81     ret = wally_tx_remove_output(tx, 2); /* Remove middle */
82     check_ret(ret);
83     ret = wally_tx_remove_output(tx, 0); /* Remove first */
84     check_ret(ret);
85 
86     /* Clean up (for valgrind heap checking) */
87     ret = wally_tx_free(tx);
88     check_ret(ret);
89     ret = wally_tx_input_free(new_in);
90     check_ret(ret);
91     ret = wally_tx_output_free(new_out);
92     check_ret(ret);
93     return true;
94 }
95 
tx_coinbase(const char * tx_hex)96 static bool tx_coinbase(const char *tx_hex)
97 {
98     struct wally_tx *tx;
99     char *new_hex;
100     const uint32_t flags = WALLY_TX_FLAG_USE_WITNESS;
101     size_t is_coinbase;
102     int ret;
103 
104     /* Unserialize and serialize the tx and verify they match */
105     ret = wally_tx_from_hex(tx_hex, flags, &tx);
106     check_ret(ret);
107 
108     ret = wally_tx_to_hex(tx, flags, &new_hex);
109     if (ret != WALLY_OK || strcmp(tx_hex, new_hex))
110         return false;
111 
112     ret = wally_free_string(new_hex);
113     check_ret(ret);
114 
115     ret = wally_tx_is_coinbase(tx, &is_coinbase);
116     if (ret != WALLY_OK || !is_coinbase)
117         return false;
118 
119     /* Clean up (for valgrind heap checking) */
120     ret = wally_tx_free(tx);
121     check_ret(ret);
122 
123     return true;
124 }
125 
test_tx_parse(void)126 static bool test_tx_parse(void)
127 {
128     return tx_roundtrip(p2pkh_hex) &&
129            tx_roundtrip(wit_hex) &&
130            tx_coinbase(coinbase_hex);
131 }
132 
main(void)133 int main(void)
134 {
135     bool tests_ok = true;
136 
137 #define RUN(t) if (!t()) { printf(#t " test_tx() test failed!\n"); tests_ok = false; }
138 
139     RUN(test_tx_parse);
140 
141     return tests_ok ? 0 : 1;
142 }
143