Completed
Pull Request — master (#77)
by thomas
02:43
created

test/size_estimation.test.js   F

Complexity

Total Complexity 95
Complexity/F 1.3

Size

Lines of Code 807
Function Count 73

Duplication

Duplicated Lines 40
Ratio 4.96 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 0
wmc 95
c 3
b 0
f 0
nc 1
mnd 2
bc 97
fnc 73
dl 40
loc 807
rs 2.1818
bpm 1.3287
cpm 1.3012
noi 11

35 Functions

Rating   Name   Duplication   Size   Complexity  
A size_estimation.test.js ➔ makeUtxo 0 13 3
A describe(ꞌSizeEstimation.estimateOutputsꞌ) 0 16 1
A size_estimation.test.js ➔ multisigScriptSizes 0 20 1
A size_estimation.test.js ➔ describe(ꞌestimateMultisigStackSizeꞌ) 0 53 1
A size_estimation.test.js ➔ describe(ꞌestimateP2PKStackSizeꞌ) 0 48 1
A u.map 0 3 1
B describe(ꞌSizeEstimation.getLengthForScriptPushꞌ) 0 24 1
B multisigUtxoFixtures.constructor 0 40 1
A p2pkhFormFixtures.constructor 0 7 1
A data.map 0 7 1
A c.map 0 3 1
B p2pkUtxoFixtures.constructor 0 27 1
A size_estimation.test.js ➔ p2pkhMakeScript 5 5 1
A size_estimation.test.js ➔ p2pkScriptSizes 16 20 1
A size_estimation.test.js ➔ p2pkMakeScript 3 5 1
A describe(ꞌSizeEstimation.estimateInputFromScriptsꞌ) 0 14 1
A size_estimation.test.js ➔ describe(ꞌestimateWitnessPubKeyHashꞌ) 0 22 1
A size_estimation.test.js ➔ multisigMakeScript 2 7 1
A size_estimation.test.js ➔ makeFormFixtures 0 16 4
A size_estimation.test.js ➔ describe(ꞌestimateP2PKHStackSizeꞌ) 0 51 1
A size_estimation.test.js ➔ scriptUtxos 0 22 1
A size_estimation.test.js ➔ p2pkhScriptSizes 0 20 3
B describe(ꞌSizeEstimation.getLengthForVarIntꞌ) 0 24 1
A describe(ꞌSizeEstimation.estimateTxWeightꞌ) 0 60 1
B multisigStackFixtures.constructor 0 32 4
A p2pkhUtxoFixtures.constructor 0 20 1
A p2pkhStackFixtures.constructor 0 10 1
A p2pkFormFixtures.constructor 0 5 1
B describe(ꞌSizeEstimation.estimateUtxoꞌ) 0 76 1
A multisigFormFixtures.constructor 0 11 1
B describe(ꞌSizeEstimation.estimateInputsSizeꞌ) 0 28 1
A p2pkStackFixtures.constructor 0 11 1
A size_estimation.test.js ➔ makeUtxoFixtures 0 17 4
A size_estimation.test.js ➔ p2pkMakeFormFixtures 5 5 1
A size_estimation.test.js ➔ p2pkhFormFixture 6 6 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like test/size_estimation.test.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/* jshint -W101, -W098 */
2
/* global window */
3
var assert = require('assert');
4
var bitcoin = require('bitcoinjs-lib');
5
var SizeEstimation = require("../lib/size_estimation");
6
7
function makeUtxo(script, rs, ws) {
8
    var utxo = {
9
        scriptpubkey_hex: script.toString('hex'),
10
        value: 100000000
11
    };
12
    if (rs instanceof Buffer) {
0 ignored issues
show
Bug introduced by
The variable Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
13
        utxo.redeem_script = rs.toString('hex');
14
    }
15
    if (ws instanceof Buffer) {
16
        utxo.witness_script = ws.toString('hex');
17
    }
18
    return utxo;
19
}
20
21
function scriptUtxos(script) {
22
    var hash160 = bitcoin.crypto.hash160(script);
23
    var p2shSPK = bitcoin.script.scriptHash.output.encode(hash160);
24
25
    var sha256 = bitcoin.crypto.sha256(script);
26
    var p2wshSPK = bitcoin.script.witnessScriptHash.output.encode(sha256);
27
28
    var p2wshHash160 = bitcoin.crypto.hash160(p2wshSPK);
29
    var p2wshP2sh = bitcoin.script.scriptHash.output.encode(p2wshHash160);
30
31
    var bareUtxo = makeUtxo(script, null, null);
32
    var p2shUtxo = makeUtxo(p2shSPK, script, null);
33
    var p2wshUtxo = makeUtxo(p2wshSPK, null, script);
34
    var p2shP2wshUtxo = makeUtxo(p2wshP2sh, p2wshSPK, script);
35
36
    return {
37
        bareUtxo: bareUtxo,
38
        p2shUtxo: p2shUtxo,
39
        p2wshUtxo: p2wshUtxo,
40
        p2shP2wshUtxo: p2shP2wshUtxo
41
    };
42
}
43
44
function makeUtxoFixtures(script, scriptSizes, extra) {
45
    var utxos = scriptUtxos(script);
46
    var result = [
47
        [utxos.bareUtxo, scriptSizes.bareSig, 0],
48
        [utxos.p2shUtxo, scriptSizes.p2shSig, 0],
49
        [utxos.p2wshUtxo, 1, scriptSizes.nestedWit],
50
        [utxos.p2shP2wshUtxo, scriptSizes.nestedSig, scriptSizes.nestedWit]
51
    ];
52
53
    if (Array.isArray(extra) && extra.length > 0) {
54
        for (var i = 0; i < result.length; i++) {
55
            result[i] = result[i].concat(extra);
56
        }
57
    }
58
59
    return result;
60
}
61
62
function makeFormFixtures(script, scriptSizes, extra) {
63
    var result = [
64
        [script, false, null, null, scriptSizes.bareSig, 0],
65
        [script, false, script, null, scriptSizes.p2shSig, 0],
66
        [script, true, null, script, 1, scriptSizes.nestedWit],
67
        [script, true, scriptSizes.p2wshScript, script, scriptSizes.nestedSig, scriptSizes.nestedWit]
68
    ];
69
70
    if (Array.isArray(extra) && extra.length > 0) {
71
        for (var i = 0; i < result.length; i++) {
72
            result[i] = result[i].concat(extra);
73
        }
74
    }
75
76
    return result;
77
}
78
79
function p2pkScriptSizes(script) {
80
    var bareSize = (1 + SizeEstimation.SIZE_DER_SIGNATURE);
81
    var bareSig = 1 + bareSize;
82
    var p2shSig = 1 + bareSize + 1 + script.length;
83 View Code Duplication
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
84
    var p2wshHash = bitcoin.crypto.sha256(script);
85
    var p2wshScript = bitcoin.script.witnessScriptHash.output.encode(p2wshHash);
86
87
    var nestedSig = 1 + 1 + p2wshScript.length;
88
    var witSize = (1 + SizeEstimation.SIZE_DER_SIGNATURE);
89
    var nestedWit = witSize + 1 + 1 + script.length;
90
91
    return {
92
        bareSig: bareSig,
93
        p2shSig: p2shSig,
94
        p2wshScript: p2wshScript,
95
        nestedSig: nestedSig,
96
        nestedWit: nestedWit
97
    };
98
}
99
100
function p2pkMakeScript(wif, network) {
101
    var uncompressed = bitcoin.ECPair.fromWIF(wif, network);
102
    var keyu = uncompressed.getPublicKeyBuffer();
103
    return bitcoin.script.pubKey.output.encode(keyu);
104
}
105
106
function p2pkhScriptSizes(script, compressed) {
107
    var bareSize = (1 + SizeEstimation.SIZE_DER_SIGNATURE) + (1 + (compressed ? 33 : 65));
108
    var bareSig = 1 + bareSize;
109
    var p2shSig = 1 + bareSize + 1 + script.length;
110
111
    var p2wshHash = bitcoin.crypto.sha256(script);
112
    var p2wshScript = bitcoin.script.witnessScriptHash.output.encode(p2wshHash);
113
114
    var nestedSig = 1 + 1 + p2wshScript.length;
115
    var witSize = (1 + SizeEstimation.SIZE_DER_SIGNATURE) + (1 + (compressed ? 33 : 65));
116
    var nestedWit = witSize + 1 + 1 + script.length;
117
118
    return {
119
        bareSig: bareSig,
120
        p2shSig: p2shSig,
121
        p2wshScript: p2wshScript,
122
        nestedSig: nestedSig,
123
        nestedWit: nestedWit
124
    };
125
}
126
127 View Code Duplication
function p2pkhMakeScript(wif, network) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
128
    var eckey = bitcoin.ECPair.fromWIF(wif, network);
129
    var hash160 = bitcoin.crypto.hash160(eckey.getPublicKeyBuffer());
130
    return bitcoin.script.pubKeyHash.output.encode(hash160);
131
}
132
133
function p2pkhFormFixture(wif, network) {
134
    var keyHash = p2pkhMakeScript(wif, network);
135
    var compressed = bitcoin.ECPair.fromWIF(wif, network).compressed;
136
    var scriptSizes = p2pkhScriptSizes(keyHash, compressed);
137
    return makeFormFixtures(keyHash, scriptSizes, [compressed]);
138
}
139
140
function p2pkMakeFormFixtures(wif, network) {
141
    var script = p2pkMakeScript(wif, network);
142
    var scriptSizes = p2pkScriptSizes(script);
143
    return makeFormFixtures(script, scriptSizes);
144
}
145
function multisigMakeScript(m, wifs, network) {
146
    var keys = wifs.map(function(wif) {
147
        return bitcoin.ECPair.fromWIF(wif, network).getPublicKeyBuffer();
148
    });
149
150
    return bitcoin.script.multisig.output.encode(m, keys);
151
}
152
function multisigScriptSizes(m, script) {
153
    var bareSize = 1/*op0*/ + m * (1 + SizeEstimation.SIZE_DER_SIGNATURE);
154
    var bareSig = 1 + bareSize;
155
    var p2shSig = bareSize + SizeEstimation.getLengthForScriptPush(script.length) + script.length;
156
157
    var p2wshHash = bitcoin.crypto.sha256(script);
158
    var p2wshScript = bitcoin.script.witnessScriptHash.output.encode(p2wshHash);
159
160
    var nestedSig = 1 + 1 + p2wshScript.length;
161
    var witSize = 1 + m * (1 + SizeEstimation.SIZE_DER_SIGNATURE);
162
    var nestedWit = witSize + 1 + 1 + script.length;
163
164
    return {
165
        bareSig: bareSig,
166
        p2shSig: SizeEstimation.getLengthForVarInt(p2shSig) + p2shSig,
167
        p2wshScript: p2wshScript,
168
        nestedSig: nestedSig,
169
        nestedWit: nestedWit
170
    };
171
}
172
173
var varIntFixtures = [
174
    [0, 1],
175
    [1, 1],
176
    [252, 1],
177
    [253, 3],
178
    [254, 3],
179
    [65534, 3],
180
    [65535, 5],
181
    [65536, 5],
182
    [Math.pow(2, 31), 5],
183
    [Math.pow(2, 32) - 2, 5],
184
    [Math.pow(2, 32) - 1, 9],
185
    [Math.pow(2, 32), 9],
186
187
    // don't go above this, is signed int territory, PHP complains
188
    // nodejs?
189
    [0x7fffffffffffffff, 9]
190
];
191
192
var scriptDataLenFixtures =  [
193
    [0, 1],
194
    [1, 1],
195
    [74, 1],
196
    [75, 2],
197
    [76, 2],
198
    [254, 2],
199
    [255, 2],
200
    [256, 3],
201
    [65534, 3],
202
    [65535, 3],
203
    [65536, 5]
204
];
205
206
var p2pkStackFixtures = (function() {
207
    var u = '5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp';
208
    var c = 'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd';
209
210
    var fixtures = [];
211
212
    fixtures.push([p2pkMakeScript(u, bitcoin.networks.bitcoin)]);
213
    fixtures.push([p2pkMakeScript(c, bitcoin.networks.bitcoin)]);
214
215
    return fixtures;
216
})();
217
218
// test fixtures of every possible representation of multisig
219
var p2pkFormFixtures = (function() {
220
    return []
221
        .concat(p2pkMakeFormFixtures('5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp', bitcoin.networks.bitcoin))
222
        .concat(p2pkMakeFormFixtures('L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd', bitcoin.networks.bitcoin));
223
})();
224
225
var p2pkhStackFixtures = (function() {
226
    var u = '5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp';
227
    var c = 'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd';
228
229
    var fixtures = [];
230
    fixtures.push([p2pkhMakeScript(u, bitcoin.networks.bitcoin)]);
231
    fixtures.push([p2pkhMakeScript(c, bitcoin.networks.bitcoin)]);
232
233
    return fixtures;
234
})();
235
236
// test fixtures of every possible representation of multisig
237
var p2pkhFormFixtures = (function() {
238
239
    return []
240
        .concat(p2pkhFormFixture('L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd', bitcoin.networks.bitcoin))
241
        .concat(p2pkhFormFixture('5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp', bitcoin.networks.bitcoin))
242
    ;
243
})();
244
245
var multisigStackFixtures = (function() {
246
    var u = ['5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp',
247
        '5KCV94YBsrJWTdk6cQWJxEd25sH8h1cGTpJnCN6kLMLe4c3QZVr',
248
        '5JUxGateMWVBsBQkAwSRQLxyaQXhsch4EStfC62cqdEf2zUheVT'
249
    ];
250
    var c = ['L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
251
        'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
252
        'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
253
    ];
254
    var uncompressed = u.map(function(wif) {
255
        return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
256
    });
257
    var compressed = c.map(function(wif) {
258
        return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
259
    });
260
261
    var fixtures = [];
262
    for (var i = 0; i < 3; i++) {
263
        var keys = [];
264
        var j;
265
        for (j = 0; j < i; j++) {
266
            keys.push(uncompressed[j].getPublicKeyBuffer());
267
        }
268
        for (j = i; j < 3; j++) {
269
            keys.push(compressed[j].getPublicKeyBuffer());
270
        }
271
272
        fixtures.push([bitcoin.script.multisig.output.encode(2, keys)]);
273
    }
274
275
    return fixtures;
276
})();
277
278
// test fixtures of every possible representation of multisig
279
var multisigFormFixtures = (function() {
280
    var multisig = multisigMakeScript(2, ['L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
281
        'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
282
        'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
283
    ], bitcoin.networks.bitcoin);
284
285
    var msDetail = multisigScriptSizes(2, multisig);
286
287
    return []
288
        .concat(makeFormFixtures(multisig, msDetail));
289
})();
290
291
// test fixtures of every possible representation of multisig
292
var multisigUtxoFixtures = (function() {
293
    var data = [
294
        [
295
            2,
296
            [
297
                'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
298
                'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
299
                'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
300
            ],
301
            bitcoin.networks.bitcoin
302
        ],
303
        [
304
            3,
305
            [
306
                'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
307
                'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
308
                'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
309
            ],
310
            bitcoin.networks.bitcoin
311
        ],
312
        [
313
            1,
314
            [
315
                'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd'
316
            ],
317
            bitcoin.networks.bitcoin
318
        ]
319
    ];
320
321
    var fixtures = [];
322
    data.map(function(fixture) {
323
        var script = multisigMakeScript(fixture[0], fixture[1], fixture[2]);
324
        var msDetail = multisigScriptSizes(fixture[0], script);
325
        makeUtxoFixtures(script, msDetail).map(function(fixture) {
326
            fixtures.push(fixture);
327
        });
328
    });
329
330
    return fixtures;
331
})();
332
333
// test fixtures of every possible representation of multisig
334
var p2pkUtxoFixtures = (function() {
335
    var data = [
336
        [
337
            'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
338
            bitcoin.networks.bitcoin
339
        ],
340
        [
341
            'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
342
            bitcoin.networks.bitcoin
343
        ],
344
        [
345
            'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW',
346
            bitcoin.networks.bitcoin
347
        ]
348
    ];
349
350
    var fixtures = [];
351
    data.map(function(fixture) {
352
        var script = p2pkMakeScript(fixture[0], fixture[1]);
353
        var msDetail = p2pkScriptSizes(script);
354
        makeUtxoFixtures(script, msDetail).map(function(fixture) {
355
            fixtures.push(fixture);
356
        });
357
    });
358
359
    return fixtures;
360
})();
361
362
// test fixtures of every possible representation of multisig
363
var p2pkhUtxoFixtures = (function() {
364
    var data = [
365
        [
366
            'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
367
            bitcoin.networks.bitcoin
368
        ]
369
    ];
370
371
    var fixtures = [];
372
    data.map(function(fixture) {
373
        var script = p2pkhMakeScript(fixture[0], fixture[1]);
374
        var compressed = bitcoin.ECPair.fromWIF(fixture[0], fixture[1]).compressed;
375
        var msDetail = p2pkhScriptSizes(script, compressed);
376
        makeUtxoFixtures(script, msDetail, [compressed]).map(function(fixture) {
377
            fixtures.push(fixture);
378
        });
379
    });
380
381
    return fixtures;
382
})();
383
384
describe('SizeEstimation.getLengthForVarInt', function() {
385
    varIntFixtures.map(function(fixture) {
386
        var inputLen = fixture[0];
387
        var expectSize = fixture[1];
388
        it('works for `' + inputLen + '` (equals ' + expectSize + ')', function(cb) {
389
            var result = SizeEstimation.getLengthForVarInt(inputLen);
390
            assert.equal(expectSize, result);
391
            cb();
392
        });
393
    });
394
395
    it('throws when too large an input is provided', function(cb) {
396
        var err;
397
        try {
398
            SizeEstimation.getLengthForVarInt(0xffffffffffffffff + 1);
399
        } catch (e) {
400
            err = e;
401
        }
402
403
        assert.ok(typeof err === "object");
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths.
Loading history...
404
        assert.equal(err.message, "Size of varint too large");
405
        cb();
406
    });
407
});
408
409
describe('SizeEstimation.getLengthForScriptPush', function() {
410
    scriptDataLenFixtures.map(function(fixture) {
411
        var inputLen = fixture[0];
412
        var expectSize = fixture[1];
413
        it(' works for ' + inputLen + '` (equals ' + expectSize + ')', function(cb) {
414
            var result = SizeEstimation.getLengthForScriptPush(inputLen);
415
            assert.equal(expectSize, result);
416
            cb();
417
        });
418
    });
419
420
    it('throws when too large an input is provided', function(cb) {
421
        var err;
422
        try {
423
            SizeEstimation.getLengthForScriptPush(0xffffffff + 1);
424
        } catch (e) {
425
            err = e;
426
        }
427
428
        assert.ok(typeof err === "object");
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths.
Loading history...
429
        assert.equal(err.message, "Size of pushdata too large");
430
        cb();
431
    });
432
});
433
434
describe('estimateP2PKStackSize', function() {
435
    p2pkStackFixtures.map(function(fixture) {
436
        it("works for p2pk scripts with the keys", function(cb) {
437
            var script = fixture[0];
438
            assert.ok(bitcoin.script.pubKey.output.check(script));
439
            var decoded = bitcoin.script.pubKey.output.decode(script);
440
441
            var estimation = SizeEstimation.estimateP2PKStackSize(decoded);
442
            assert.equal("object", typeof estimation);
443
            assert.equal(2, estimation.length);
444
445
            var scriptSize = estimation[1];
446
            assert.equal(script.length, scriptSize);
447
448
            var stackSizes = estimation[0];
449
            assert.equal(1, stackSizes.length);
450
            assert.equal(SizeEstimation.SIZE_DER_SIGNATURE, stackSizes[0]);
451
            cb();
452
        });
453
    });
454
455
    p2pkFormFixtures.map(function(fixture) {
456
        it("deals with different representations", function(cb) {
457
            var script = fixture[0];
458
            var isWit = fixture[1];
459
            var rs = fixture[2];
460
            var ws = fixture[3];
461
            var expectSig = fixture[4];
462
            var expectWit = fixture[5];
463
464
            assert.ok(bitcoin.script.pubKey.output.check(script));
465
            var decoded = bitcoin.script.pubKey.output.decode(script);
466
            var stackEst = SizeEstimation.estimateP2PKStackSize(decoded);
467
            var stackSizes = stackEst[0];
468
469
            var est = SizeEstimation.estimateStackSignatureSize(stackSizes, isWit, rs, ws);
470
            assert.equal("object", typeof est);
471
            assert.equal(2, est.length);
472
473
            var foundSigSize = est[0];
474
            var foundWitSize = est[1];
475
476
            assert.equal(foundSigSize, expectSig);
477
            assert.equal(foundWitSize, expectWit);
478
            cb();
479
        });
480
    });
481
});
482
483
describe('estimateP2PKHStackSize', function() {
484
    p2pkhStackFixtures.map(function(fixture) {
485
        it("works for p2pkh scripts with the keys", function(cb) {
486
            var script = fixture[0];
487
            assert.ok(bitcoin.script.pubKeyHash.output.check(script));
488
            var decoded = bitcoin.script.pubKeyHash.output.decode(script);
489
490
            var estimation = SizeEstimation.estimateP2PKHStackSize(decoded);
491
            assert.equal("object", typeof estimation);
492
            assert.equal(2, estimation.length);
493
494
            var scriptSize = estimation[1];
495
            assert.equal(scriptSize, script.length);
496
497
            var stackSizes = estimation[0];
498
            assert.equal(2, stackSizes.length);
499
500
            assert.equal(stackSizes[0], SizeEstimation.SIZE_DER_SIGNATURE);
501
            assert.equal(stackSizes[1], 33);
502
            cb();
503
        });
504
    });
505
506
    p2pkhFormFixtures.map(function(fixture) {
507
        it("deals with different representations", function(cb) {
508
            var script = fixture[0];
509
            var isWit = fixture[1];
510
            var rs = fixture[2];
511
            var ws = fixture[3];
512
            var expectSig = fixture[4];
513
            var expectWit = fixture[5];
514
            var compressed = fixture[6];
515
516
            assert.ok(bitcoin.script.pubKeyHash.output.check(script));
517
518
            var stackEst = SizeEstimation.estimateP2PKHStackSize(compressed);
519
            var stackSizes = stackEst[0];
520
521
            var est = SizeEstimation.estimateStackSignatureSize(stackSizes, isWit, rs, ws);
522
            assert.equal("object", typeof est);
523
            assert.equal(2, est.length);
524
525
            var foundSigSize = est[0];
526
            var foundWitSize = est[1];
527
528
            assert.equal(foundSigSize, expectSig);
529
            assert.equal(foundWitSize, expectWit);
530
            cb();
531
        });
532
    });
533
});
534
535
describe("estimateMultisigStackSize", function() {
536
    multisigStackFixtures.map(function(fixture) {
537
        it("works for multisig scripts with the keys", function(cb) {
538
            var script = fixture[0];
539
            assert.ok(bitcoin.script.multisig.output.check(script));
540
            var decoded = bitcoin.script.multisig.output.decode(script);
541
            var estimation = SizeEstimation.estimateMultisigStackSize(decoded.m, decoded.pubKeys);
542
543
            assert.equal("object", typeof estimation);
544
            assert.equal(2, estimation.length);
545
546
            var scriptSize = estimation[1];
547
            assert.equal(script.length, scriptSize);
548
549
            var stackSizes = estimation[0];
550
            assert.equal(1 + decoded.m, stackSizes.length);
551
            assert.equal(0, stackSizes[0]);
552
            for (var i = 0; i < decoded.m; i++) {
553
                assert.equal(SizeEstimation.SIZE_DER_SIGNATURE, stackSizes[1 + i]);
554
            }
555
            cb();
556
        });
557
    });
558
559
    multisigFormFixtures.map(function(fixture) {
560
        it("deals with different representations", function(cb) {
561
            var script = fixture[0];
562
            var isWit = fixture[1];
563
            var rs = fixture[2];
564
            var ws = fixture[3];
565
            var expectSig = fixture[4];
566
            var expectWit = fixture[5];
567
568
            assert.ok(bitcoin.script.multisig.output.check(script));
569
            var multisig = bitcoin.script.multisig.output.decode(script);
570
571
            var stackEst = SizeEstimation.estimateMultisigStackSize(multisig.m, multisig.pubKeys);
572
            var stackSizes = stackEst[0];
573
574
            var est = SizeEstimation.estimateStackSignatureSize(stackSizes, isWit, rs, ws);
575
            assert.equal("object", typeof est);
576
            assert.equal(2, est.length);
577
578
            var foundSigSize = est[0];
579
            var foundWitSize = est[1];
580
581
            assert.equal(foundSigSize, expectSig);
582
            assert.equal(foundWitSize, expectWit);
583
            cb();
584
        });
585
    });
586
587
});
588
589
describe("SizeEstimation.estimateInputFromScripts", function() {
590
    it('throws on invalid script type', function(cb) {
591
        var err;
592
        try {
593
            SizeEstimation.estimateInputFromScripts(Buffer.from('', 'hex'), null, null);
0 ignored issues
show
Bug introduced by
The variable Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
594
        } catch (e) {
595
            err = e;
596
        }
597
598
        assert.ok(typeof err === "object");
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths.
Loading history...
599
        assert.equal(err.message, "Unsupported script type");
600
        cb();
601
    });
602
});
603
describe("SizeEstimation.estimateOutputs", function() {
604
    [0, 1, 5, 9].map(function(size) {
605
        it("estimates single output, for script size " + size, function(cb) {
606
            var script = '';
607
            for (var i = 0; i < size; i++) {
608
                script = script + '6a';
609
            }
610
            var outputsSize = SizeEstimation.calculateOutputsSize([{
611
                value: 1234,
612
                script: script
613
            }]);
614
            assert.equal(outputsSize, 8 + 1 + size);
615
            cb();
616
        });
617
    });
618
});
619
620
describe("SizeEstimation.estimateTxWeight", function() {
621
    var wif = "5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp";
622
    var key = bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
623
624
    var hash160 = bitcoin.crypto.hash160(key.getPublicKeyBuffer());
625
    var p2wpkh = bitcoin.script.witnessPubKeyHash.output.encode(hash160);
626
    var p2pkh = bitcoin.script.pubKeyHash.output.encode(hash160);
627
628
    it("estimates p2wpkh weight", function(cb) {
629
        var utxos = [
630
            {
631
                txid: "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234",
632
                vout: 0,
633
                scriptpubkey_hex: p2wpkh
634
            }
635
        ];
636
637
        var txb = new bitcoin.TransactionBuilder();
638
        utxos.map(function(utxo) {
639
            txb.addInput(utxo.txid, utxo.vout);
640
        });
641
642
        txb.addOutput(p2wpkh, 1234);
643
        var tx = txb.buildIncomplete();
644
645
        var size = SizeEstimation.estimateTxWeight(tx, utxos);
646
        var vsize = SizeEstimation.estimateTxVsize(tx, utxos);
647
648
        assert.equal(Math.ceil(size / 4), vsize);
649
        cb();
650
    });
651
652
    it("weight for non-witness is 4x size", function(cb) {
653
        var utxos = [
654
            {
655
                txid: "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234",
656
                vout: 0,
657
                scriptpubkey_hex: p2pkh
658
            }
659
        ];
660
661
        var txb = new bitcoin.TransactionBuilder();
662
        utxos.map(function(utxo) {
663
            txb.addInput(utxo.txid, utxo.vout);
664
        });
665
666
        txb.addOutput(p2wpkh, 1234);
667
        var tx = txb.buildIncomplete();
668
669
        var os = SizeEstimation.calculateOutputsSize(tx.outs);
670
        var bs = 4 + 4 + SizeEstimation.estimateInputsSize(utxos, false) + 4 + os + 4;
671
672
        var size = SizeEstimation.estimateTxWeight(tx, utxos);
673
        assert.equal(size, bs * 4);
674
675
        var vsize = SizeEstimation.estimateTxVsize(tx, utxos);
676
        assert.equal(Math.ceil(size / 4), vsize);
677
        cb();
678
    });
679
});
680
681
describe("SizeEstimation.estimateInputsSize", function() {
682
    var wif = "5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp";
683
    var key = bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
684
685
    var hash160 = bitcoin.crypto.hash160(key.getPublicKeyBuffer());
686
    var p2wpkh = bitcoin.script.witnessPubKeyHash.output.encode(hash160);
687
688
    it("drops witness based on parameter", function(cb) {
689
        var withWitness = SizeEstimation.estimateInputsSize([{
690
            value: 1234,
691
            scriptpubkey_hex: p2wpkh
692
        }], true);
693
694
        var noWitness = SizeEstimation.estimateInputsSize([{
695
            value: 1234,
696
            scriptpubkey_hex: p2wpkh
697
        }], false);
698
699
        assert.equal(noWitness, 32 + 4 + 4 + 1);
700
        /*witness flags + witness vector*/
701
702
        var assumeSize = noWitness + 2 + (1 + 1 + SizeEstimation.SIZE_DER_SIGNATURE + 1 + 33);
703
704
        assert.ok(assumeSize === withWitness);
705
706
        cb();
707
    });
708
});
709
710
describe("SizeEstimation.estimateUtxo", function() {
711
    it("throws if P2SH and redeemScript not provided", function(cb) {
712
        var err;
713
        try {
714
            var hash160 = bitcoin.crypto.hash160(Buffer.from("42", "hex"));
0 ignored issues
show
Bug introduced by
The variable Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
715
            var spk = bitcoin.script.scriptHash.output.encode(hash160);
716
            SizeEstimation.estimateUtxo({
717
                scriptpubkey_hex: spk,
718
                redeem_script: null
719
            });
720
        } catch (e) {
721
            err = e;
722
        }
723
724
        assert.ok(typeof err === "object");
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths.
Loading history...
725
        assert.equal(err.message, "Cant estimate, missing redeem script");
726
        cb();
727
    });
728
729
    it("throws if P2WSH and witnessScript not provided", function(cb) {
730
        var err;
731
        try {
732
            var hash160 = bitcoin.crypto.sha256(Buffer.from("42", "hex"));
0 ignored issues
show
Bug introduced by
The variable Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
733
            var spk = bitcoin.script.witnessScriptHash.output.encode(hash160);
734
            SizeEstimation.estimateUtxo({
735
                scriptpubkey_hex: spk,
736
                witness_script: null
737
            });
738
        } catch (e) {
739
            err = e;
740
        }
741
742
        assert.ok(typeof err === "object");
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths.
Loading history...
743
        assert.equal(err.message, "Can't estimate, missing witness script");
744
        cb();
745
    });
746
747
    it("throws if unsupported script type", function(cb) {
748
        var err;
749
        try {
750
            var spk = Buffer.from('6a', 'hex');
0 ignored issues
show
Bug introduced by
The variable Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
751
            SizeEstimation.estimateUtxo({
752
                scriptpubkey_hex: spk,
753
                witness_script: null
754
            });
755
        } catch (e) {
756
            err = e;
757
        }
758
759
        assert.ok(typeof err === "object");
0 ignored issues
show
Bug introduced by
The variable err seems to not be initialized for all possible execution paths.
Loading history...
760
        assert.equal(err.message, "Unsupported script type");
761
        cb();
762
    });
763
764
    []
765
        .concat(multisigUtxoFixtures)
766
        .concat(p2pkUtxoFixtures)
767
        .concat(p2pkhUtxoFixtures)
768
        .map(function(fixture) {
769
            it("deals with different representations", function(cb) {
770
                var utxo = fixture[0];
771
                var expectSig = fixture[1];
772
                var expectWit = fixture[2];
773
                var compressed = false;
774
                if (typeof fixture[3] === "boolean") {
775
                    compressed = fixture[3];
776
                }
777
778
                var estimate = SizeEstimation.estimateUtxo(utxo, compressed);
779
780
                assert.equal(estimate.scriptSig, expectSig);
781
                assert.equal(estimate.witness, expectWit);
782
                cb();
783
            });
784
        });
785
});
786
787
788
describe("estimateWitnessPubKeyHash", function() {
789
    it('should work', function(cb) {
790
        var utxo = { hash: '4141414141414141414141414141414141414141414141414141414141414141',
791
            idx: 2,
792
            scriptpubkey_hex: '00140102030401020304010203040102030401020304',
793
            value: 1,
794
            confirmations: 1,
795
            sign_mode: 'dont_sign',
796
            address: '2N245vnpchbFYWm5hZ6hqF2zC8QbVpoHeSU',
797
            path: null,
798
            redeem_script: null,
799
            witness_script: null,
800
            green: null };
801
802
        var estimation = SizeEstimation.estimateUtxo(utxo);
803
804
        assert.equal(1, estimation.scriptSig);
805
        assert.equal(108, estimation.witness);
806
807
        cb();
808
    });
809
});
810