forked from satindergrewal/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
permute_tx.c
143 lines (117 loc) · 2.9 KB
/
permute_tx.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
#include "permute_tx.h"
#include <stdbool.h>
#include <string.h>
static bool input_better(const struct bitcoin_tx_input *a,
const struct bitcoin_tx_input *b)
{
int cmp;
cmp = memcmp(&a->txid, &b->txid, sizeof(a->txid));
if (cmp != 0)
return cmp < 0;
if (a->index != b->index)
return a->index < b->index;
/* These shouldn't happen, but let's get a canonical order anyway. */
if (tal_len(a->script) != tal_len(b->script))
return tal_len(a->script) < tal_len(b->script);
cmp = memcmp(a->script, b->script, tal_len(a->script));
if (cmp != 0)
return cmp < 0;
return a->sequence_number < b->sequence_number;
}
static size_t find_best_in(struct bitcoin_tx_input *inputs, size_t num)
{
size_t i, best = 0;
for (i = 1; i < num; i++) {
if (input_better(&inputs[i], &inputs[best]))
best = i;
}
return best;
}
static void swap_inputs(struct bitcoin_tx_input *inputs,
const void **map,
size_t i1, size_t i2)
{
struct bitcoin_tx_input tmpinput;
const void *tmp;
if (i1 == i2)
return;
tmpinput = inputs[i1];
inputs[i1] = inputs[i2];
inputs[i2] = tmpinput;
if (map) {
tmp = map[i1];
map[i1] = map[i2];
map[i2] = tmp;
}
}
void permute_inputs(struct bitcoin_tx_input *inputs, size_t num_inputs,
const void **map)
{
size_t i;
/* We can't permute nothing! */
if (num_inputs == 0)
return;
/* Now do a dumb sort (num_inputs is small). */
for (i = 0; i < num_inputs-1; i++) {
/* Swap best into first place. */
swap_inputs(inputs, map,
i, i + find_best_in(inputs + i, num_inputs - i));
}
}
static void swap_outputs(struct bitcoin_tx_output *outputs,
const void **map,
size_t i1, size_t i2)
{
struct bitcoin_tx_output tmpoutput;
const void *tmp;
if (i1 == i2)
return;
tmpoutput = outputs[i1];
outputs[i1] = outputs[i2];
outputs[i2] = tmpoutput;
if (map) {
tmp = map[i1];
map[i1] = map[i2];
map[i2] = tmp;
}
}
static bool output_better(const struct bitcoin_tx_output *a,
const struct bitcoin_tx_output *b)
{
size_t len;
int ret;
if (a->amount != b->amount)
return a->amount < b->amount;
/* Lexicographical sort. */
if (tal_len(a->script) < tal_len(b->script))
len = tal_len(a->script);
else
len = tal_len(b->script);
ret = memcmp(a->script, b->script, len);
if (ret != 0)
return ret < 0;
return tal_len(a->script) < tal_len(b->script);
}
static size_t find_best_out(struct bitcoin_tx_output *outputs, size_t num)
{
size_t i, best = 0;
for (i = 1; i < num; i++) {
if (output_better(&outputs[i], &outputs[best]))
best = i;
}
return best;
}
void permute_outputs(struct bitcoin_tx_output *outputs, size_t num_outputs,
const void **map)
{
size_t i;
/* We can't permute nothing! */
if (num_outputs == 0)
return;
/* Now do a dumb sort (num_outputs is small). */
for (i = 0; i < num_outputs-1; i++) {
/* Swap best into first place. */
swap_outputs(outputs, map,
i, i + find_best_out(outputs + i, num_outputs - i));
}
}