forked from dhruvbansal/bitcoin-iterate
-
Notifications
You must be signed in to change notification settings - Fork 1
/
cli.c
201 lines (194 loc) · 7.47 KB
/
cli.c
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*******************************************************************************
*
* = cli.c
*
* Entry point for the 'bitcoin-iterate' command-line program.
*
* Format strings are set by command-line flags. These format
* strings are then used by data-structure-appropriate functions
* which delegate to the `print_format` function.
*
* UTXOs are only collected if certain format codes were specified.
*
*/
#include <ccan/err/err.h>
#include <ccan/opt/opt.h>
#include "iterate.h"
#include "utils.h"
#include "format.h"
static char *blockfmt = NULL, *txfmt = NULL, *inputfmt = NULL, *outputfmt = NULL, *utxofmt = NULL;
static void print_block(const struct utxo_map *utxo_map, struct block *b)
{
if (blockfmt) {
print_format(blockfmt, utxo_map, b, NULL, 0, NULL, NULL, NULL, NULL);
}
}
static void print_transaction(const struct utxo_map *utxo_map, struct block *b, struct transaction *t, size_t txnum)
{
if (txfmt) {
print_format(txfmt, utxo_map, b, t, txnum, NULL, NULL, NULL, NULL);
}
}
static void print_input(const struct utxo_map *utxo_map, struct block *b, struct transaction *t, size_t txnum, struct input *i)
{
if (inputfmt) {
print_format(inputfmt, utxo_map, b, t, txnum, i, NULL, NULL, NULL);
}
}
static void print_output(const struct utxo_map *utxo_map, struct block *b, struct transaction *t, size_t txnum, struct output *o)
{
if (outputfmt) {
print_format(outputfmt, utxo_map, b, t, txnum, NULL, o, NULL, NULL);
}
}
static void print_utxo(const struct utxo_map *utxo_map, struct block *current_block, struct block *last_utxo_block, struct utxo *u)
{
if (utxofmt) {
print_format(utxofmt, utxo_map, current_block, NULL, 0, NULL, NULL, u, last_utxo_block);
}
}
int main(int argc, char *argv[])
{
char *blockdir = NULL, *cachedir = NULL;
bool use_testnet = false;
unsigned long block_start = 0, block_end = -1UL;
u8 tip[SHA256_DIGEST_LENGTH] = { 0 }, start_hash[SHA256_DIGEST_LENGTH] = { 0 };
bool needs_utxo = false;
unsigned int utxo_period = 144;
bool use_mmap = true;
unsigned progress_marks = 0;
bool quiet = false;
err_set_progname(argv[0]);
opt_register_noarg("-h|--help", opt_usage_and_exit,
"\nValid block, transaction, input, output, and utxo format:\n"
" <literal>: unquoted\n"
" %bl: block length\n"
" %bv: block version\n"
" %bp: block prev hash (big-endian)\n"
" %bm: block merkle hash\n"
" %bs: block timestamp\n"
" %bt: block target\n"
" %bn: block nonce\n"
" %bc: block transaction count\n"
" %bh: block hash (big-endian)\n"
" %bN: block height\n"
" %bH: block header (hex string)\n"
"Valid transaction, input or output format:\n"
" %tS: transaction is segwit\n"
" %th: transaction txid (big endian)\n"
" %tH: transaction wtxid (big endian)\n"
" %tv: transaction version\n"
" %ti: transaction input count\n"
" %to: transaction output count\n"
" %tt: transaction locktime\n"
" %tL: transaction total length (bytes)\n"
" %tl: transaction virtual length (vbytes)\n"
" %tn: transaction length (non-segwit) (bytes)\n"
" %tw: transaction weight (in sipa)\n"
" %tN: transaction number\n"
" %tF: transaction fee paid\n"
" %tD: transaction bitcoin days destroyed\n"
" %tX: transaction in hex\n"
"Valid input format:\n"
" %ia: input amount\n"
" %ih: input hash\n"
" %ii: input index\n"
" %il: input script length\n"
" %is: input script as a hex string\n"
" %iq: input nSequence\n"
" %iN: input number\n"
" %iX: input in hex\n"
" %iB: input UTXO block number (0 for coinbase)\n"
" %iT: input UTXO transaction number (-1 for coinbase)\n"
" %ip: input payment guess: same ("
stringify(CHANGE_OUTPUT) ") or different ("
stringify(PAYMENT_OUTPUT) ") owner, or ("
stringify(UNKNOWN_OUTPUT) ") unknown\n"
"Valid output format:\n"
" %oa: output amount\n"
" %ol: output script length\n"
" %os: output script as a hex string\n"
" %oN: output number\n"
" %oU: output is unspendable (0 if spendable)\n"
" %oX: output in hex\n"
"Valid utxo format:\n"
" %uh: utxo transaction hash\n"
" %un: utxo output index\n"
" %ut: utxo timestamp\n"
" %uN: utxo height\n"
" %ua: utxo amount\n"
" %ul: output script length\n"
" %us: output script as a hex string\n"
" %uC: utxo bitcoin days created\n",
"Display help message");
opt_register_arg("--block", opt_set_charp, NULL, &blockfmt,
"Format to print for each block");
opt_register_arg("--tx|--transaction", opt_set_charp, NULL, &txfmt,
"Format to print for each transaction");
opt_register_arg("--input", opt_set_charp, NULL, &inputfmt,
"Format to print for each transaction input");
opt_register_arg("--output", opt_set_charp, NULL, &outputfmt,
"Format to print for each transaction output");
opt_register_arg("--utxo", opt_set_charp, NULL, &utxofmt,
"Format to print for each UTXO");
opt_register_arg("--utxo-period", opt_set_uintval, NULL,
&utxo_period, "Loop over UTXOs every this many blocks");
opt_register_arg("--progress", opt_set_uintval, NULL,
&progress_marks, "Print . to stderr this many times");
opt_register_noarg("--no-mmap", opt_set_invbool, &use_mmap,
"Don't mmap the block files");
opt_register_noarg("--quiet|-q", opt_set_bool, &quiet,
"Don't output progress information");
opt_register_noarg("--testnet|-t", opt_set_bool, &use_testnet,
"Look for testnet3 blocks");
opt_register_arg("--blockdir", opt_set_charp, NULL, &blockdir,
"Block directory instead of ~/.bitcoin/[testnet3/]blocks");
opt_register_arg("--end-hash", opt_set_hash, NULL, tip,
"Best blockhash to use instead of longest chain.");
opt_register_arg("--start-hash", opt_set_hash, NULL, start_hash,
"Blockhash to start at instead of genesis.");
opt_register_arg("--start", opt_set_ulongval, NULL, &block_start,
"Block number to start instead of genesis.");
opt_register_arg("--end", opt_set_ulongval, NULL, &block_end,
"Block number to end at instead of longest chain.");
opt_register_arg("--cache", opt_set_charp, NULL, &cachedir,
"Cache for multiple runs.");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc != 1)
opt_usage_and_exit(NULL);
if (txfmt && strstr(txfmt, "%tF"))
needs_utxo = true;
if (txfmt && strstr(txfmt, "%tD"))
needs_utxo = true;
if (inputfmt && strstr(inputfmt, "%tF"))
needs_utxo = true;
if (inputfmt && strstr(inputfmt, "%tD"))
needs_utxo = true;
if (inputfmt && strstr(inputfmt, "%iB"))
needs_utxo = true;
if (inputfmt && strstr(inputfmt, "%iT"))
needs_utxo = true;
if (inputfmt && strstr(inputfmt, "%ia"))
needs_utxo = true;
if (inputfmt && strstr(inputfmt, "%ip"))
needs_utxo = true;
if (outputfmt && strstr(outputfmt, "%tF"))
needs_utxo = true;
if (outputfmt && strstr(outputfmt, "%tD"))
needs_utxo = true;
if (utxofmt)
needs_utxo = true;
iterate(blockdir, cachedir,
use_testnet,
block_start, block_end, start_hash, tip,
needs_utxo, utxo_period,
use_mmap,
progress_marks, quiet,
(blockfmt ? print_block : NULL),
(txfmt ? print_transaction : NULL),
(inputfmt ? print_input : NULL),
(outputfmt ? print_output : NULL),
(utxofmt ? print_utxo : NULL)
);
return 0;
}