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