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

test/size_estimation.test.js   F

Complexity

Total Complexity 95
Complexity/F 1.3

Size

Lines of Code 806
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 806
rs 2.1818
bpm 1.3287
cpm 1.3012
noi 11

35 Functions

Rating   Name   Duplication   Size   Complexity  
A describe(ꞌSizeEstimation.estimateOutputsꞌ) 0 16 1
A size_estimation.test.js ➔ multisigScriptSizes 20 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 0 5 1
A size_estimation.test.js ➔ p2pkScriptSizes 0 20 1
A size_estimation.test.js ➔ p2pkMakeScript 0 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 0 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 20 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 29 1
A p2pkStackFixtures.constructor 0 11 1
A size_estimation.test.js ➔ makeUtxoFixtures 0 17 4
A size_estimation.test.js ➔ makeUtxo 0 13 3
A size_estimation.test.js ➔ p2pkMakeFormFixtures 0 5 1
A size_estimation.test.js ➔ p2pkhFormFixture 0 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 makeUtxoFixtures(script, scriptSizes, extra) {
22
    var utxos = scriptUtxos(script);
23
    var result = [
24
        [utxos.bareUtxo, scriptSizes.bareSig, 0],
25
        [utxos.p2shUtxo, scriptSizes.p2shSig, 0],
26
        [utxos.p2wshUtxo, 1, scriptSizes.nestedWit],
27
        [utxos.p2shP2wshUtxo, scriptSizes.nestedSig, scriptSizes.nestedWit]
28
    ];
29
30
    if (Array.isArray(extra) && extra.length > 0) {
31
        for (var i = 0; i < result.length; i++) {
32
            result[i] = result[i].concat(extra);
33
        }
34
    }
35
36
    return result;
37
}
38
39
function makeFormFixtures(script, scriptSizes, extra) {
40
    var result = [
41
        [script, false, null, null, scriptSizes.bareSig, 0],
42
        [script, false, script, null, scriptSizes.p2shSig, 0],
43
        [script, true, null, script, 1, scriptSizes.nestedWit],
44
        [script, true, scriptSizes.p2wshScript, script, scriptSizes.nestedSig, scriptSizes.nestedWit]
45
    ];
46
47
    if (Array.isArray(extra) && extra.length > 0) {
48
        for (var i = 0; i < result.length; i++) {
49
            result[i] = result[i].concat(extra);
50
        }
51
    }
52
53
    return result;
54
}
55
56
function p2pkScriptSizes(script) {
57
    var bareSize = (1 + SizeEstimation.SIZE_DER_SIGNATURE);
58
    var bareSig = 1 + bareSize;
59
    var p2shSig = 1 + bareSize + 1 + script.length;
60
61
    var p2wshHash = bitcoin.crypto.sha256(script);
62
    var p2wshScript = bitcoin.script.witnessScriptHash.output.encode(p2wshHash);
63
64
    var nestedSig = 1 + 1 + p2wshScript.length;
65
    var witSize = (1 + SizeEstimation.SIZE_DER_SIGNATURE);
66
    var nestedWit = witSize + 1 + 1 + script.length;
67
68
    return {
69
        bareSig: bareSig,
70
        p2shSig: p2shSig,
71
        p2wshScript: p2wshScript,
72
        nestedSig: nestedSig,
73
        nestedWit: nestedWit
74
    }
75
}
76
77
function p2pkMakeScript(wif, network) {
78
    var uncompressed = bitcoin.ECPair.fromWIF(wif, network);
79
    var keyu = uncompressed.getPublicKeyBuffer();
80
    return bitcoin.script.pubKey.output.encode(keyu);
81
}
82
83 View Code Duplication
function p2pkhScriptSizes(script, compressed) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
84
    var bareSize = (1 + SizeEstimation.SIZE_DER_SIGNATURE) + (1 + (compressed ? 33 : 65));
85
    var bareSig = 1 + bareSize;
86
    var p2shSig = 1 + bareSize + 1 + script.length;
87
88
    var p2wshHash = bitcoin.crypto.sha256(script);
89
    var p2wshScript = bitcoin.script.witnessScriptHash.output.encode(p2wshHash);
90
91
    var nestedSig = 1 + 1 + p2wshScript.length;
92
    var witSize = (1 + SizeEstimation.SIZE_DER_SIGNATURE) + (1 + (compressed ? 33 : 65));
93
    var nestedWit = witSize + 1 + 1 + script.length;
94
95
    return {
96
        bareSig: bareSig,
97
        p2shSig: p2shSig,
98
        p2wshScript: p2wshScript,
99
        nestedSig: nestedSig,
100
        nestedWit: nestedWit
101
    }
102
}
103
function p2pkhFormFixture(wif, network) {
104
    var keyHash = p2pkhMakeScript(wif, network);
105
    var compressed = bitcoin.ECPair.fromWIF(wif, network).compressed;
106
    var scriptSizes = p2pkhScriptSizes(keyHash, compressed);
107
    return makeFormFixtures(keyHash, scriptSizes, [compressed]);
108
}
109
function p2pkhMakeScript(wif, network) {
110
    var eckey = bitcoin.ECPair.fromWIF(wif, network);
111
    var hash160 = bitcoin.crypto.hash160(eckey.getPublicKeyBuffer());
112
    return bitcoin.script.pubKeyHash.output.encode(hash160)
113
}
114
115
function p2pkMakeFormFixtures(wif, network) {
116
    var script = p2pkMakeScript(wif, network);
117
    var scriptSizes = p2pkScriptSizes(script);
118
    return makeFormFixtures(script, scriptSizes)
119
}
120
function multisigMakeScript(m, wifs, network) {
121
    var keys = wifs.map(function(wif) {
122
        return bitcoin.ECPair.fromWIF(wif, network).getPublicKeyBuffer();
123
    });
124
125
    return bitcoin.script.multisig.output.encode(m, keys);
126
}
127 View Code Duplication
function multisigScriptSizes(m, script) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
128
    var bareSize = 1/*op0*/ + m * (1 + SizeEstimation.SIZE_DER_SIGNATURE);
129
    var bareSig = 1 + bareSize;
130
    var p2shSig = bareSize + SizeEstimation.getLengthForScriptPush(script.length) + script.length;
131
132
    var p2wshHash = bitcoin.crypto.sha256(script);
133
    var p2wshScript = bitcoin.script.witnessScriptHash.output.encode(p2wshHash);
134
135
    var nestedSig = 1 + 1 + p2wshScript.length;
136
    var witSize = 1 + m * (1 + SizeEstimation.SIZE_DER_SIGNATURE);
137
    var nestedWit = witSize + 1 + 1 + script.length;
138
139
    return {
140
        bareSig: bareSig,
141
        p2shSig: SizeEstimation.getLengthForVarInt(p2shSig) + p2shSig,
142
        p2wshScript: p2wshScript,
143
        nestedSig: nestedSig,
144
        nestedWit: nestedWit
145
    }
146
}
147
148
function scriptUtxos(script) {
149
    var hash160 = bitcoin.crypto.hash160(script);
150
    var p2shSPK = bitcoin.script.scriptHash.output.encode(hash160);
151
152
    var sha256 = bitcoin.crypto.sha256(script);
153
    var p2wshSPK = bitcoin.script.witnessScriptHash.output.encode(sha256);
154
155
    var p2wshHash160 = bitcoin.crypto.hash160(p2wshSPK);
156
    var p2wshP2sh = bitcoin.script.scriptHash.output.encode(p2wshHash160);
157
158
    var bareUtxo = makeUtxo(script, null, null);
159
    var p2shUtxo = makeUtxo(p2shSPK, script, null);
160
    var p2wshUtxo = makeUtxo(p2wshSPK, null, script);
161
    var p2shP2wshUtxo = makeUtxo(p2wshP2sh, p2wshSPK, script);
162
163
    return {
164
        bareUtxo: bareUtxo,
165
        p2shUtxo: p2shUtxo,
166
        p2wshUtxo: p2wshUtxo,
167
        p2shP2wshUtxo: p2shP2wshUtxo
168
    }
169
}
170
171
var varIntFixtures = [
172
    [0, 1],
173
    [1, 1],
174
    [252, 1],
175
    [253, 3],
176
    [254, 3],
177
    [65534, 3],
178
    [65535, 5],
179
    [65536, 5],
180
    [Math.pow(2, 31), 5],
181
    [Math.pow(2, 32) - 2, 5],
182
    [Math.pow(2, 32) - 1, 9],
183
    [Math.pow(2, 32), 9],
184
185
    // don't go above this, is signed int territory, PHP complains
186
    // nodejs?
187
    [0x7fffffffffffffff, 9]
188
];
189
190
var scriptDataLenFixtures =  [
191
    [0, 1],
192
    [1, 1],
193
    [74, 1],
194
    [75, 2],
195
    [76, 2],
196
    [254, 2],
197
    [255, 2],
198
    [256, 3],
199
    [65534, 3],
200
    [65535, 3],
201
    [65536, 5]
202
];
203
204
var p2pkStackFixtures = (function() {
205
    var u = '5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp';
206
    var c = 'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd';
207
208
    var fixtures = [];
209
210
    fixtures.push([p2pkMakeScript(u, bitcoin.networks.bitcoin)]);
211
    fixtures.push([p2pkMakeScript(c, bitcoin.networks.bitcoin)]);
212
213
    return fixtures;
214
})();
215
216
// test fixtures of every possible representation of multisig
217
var p2pkFormFixtures = (function() {
218
    return []
219
        .concat(p2pkMakeFormFixtures('5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp', bitcoin.networks.bitcoin))
220
        .concat(p2pkMakeFormFixtures('L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd', bitcoin.networks.bitcoin));
221
})();
222
223
var p2pkhStackFixtures = (function() {
224
    var u = '5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp';
225
    var c = 'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd';
226
227
    var fixtures = [];
228
    fixtures.push([p2pkhMakeScript(u, bitcoin.networks.bitcoin)]);
229
    fixtures.push([p2pkhMakeScript(c, bitcoin.networks.bitcoin)]);
230
231
    return fixtures;
232
})();
233
234
// test fixtures of every possible representation of multisig
235
var p2pkhFormFixtures = (function() {
236
237
    return []
238
        .concat(p2pkhFormFixture('L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd', bitcoin.networks.bitcoin))
239
        .concat(p2pkhFormFixture('5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp', bitcoin.networks.bitcoin))
240
    ;
241
})();
242
243
var multisigStackFixtures = (function() {
244
    var u = ['5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp',
245
        '5KCV94YBsrJWTdk6cQWJxEd25sH8h1cGTpJnCN6kLMLe4c3QZVr',
246
        '5JUxGateMWVBsBQkAwSRQLxyaQXhsch4EStfC62cqdEf2zUheVT'
247
    ];
248
    var c = ['L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
249
        'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
250
        'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
251
    ];
252
    var uncompressed = u.map(function(wif) {
253
        return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
254
    });
255
    var compressed = c.map(function(wif) {
256
        return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
257
    });
258
259
    var fixtures = [];
260
    for (var i = 0; i < 3; i++) {
261
        var keys = [];
262
        var j;
263
        for (j = 0; j < i; j++) {
264
            keys.push(uncompressed[j].getPublicKeyBuffer());
265
        }
266
        for (j = i; j < 3; j++) {
267
            keys.push(compressed[j].getPublicKeyBuffer());
268
        }
269
270
        fixtures.push([bitcoin.script.multisig.output.encode(2, keys)]);
271
    }
272
273
    return fixtures;
274
})();
275
276
// test fixtures of every possible representation of multisig
277
var multisigFormFixtures = (function() {
278
    var multisig = multisigMakeScript(2, ['L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
279
        'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
280
        'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
281
    ], bitcoin.networks.bitcoin);
282
283
    var msDetail = multisigScriptSizes(2, multisig);
284
285
    return []
286
        .concat(makeFormFixtures(multisig, msDetail));
287
})();
288
289
// test fixtures of every possible representation of multisig
290
var multisigUtxoFixtures = (function() {
291
    var data = [
292
        [
293
            2,
294
            [
295
                'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
296
                'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
297
                'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
298
            ],
299
            bitcoin.networks.bitcoin
300
        ],
301
        [
302
            3,
303
            [
304
                'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
305
                'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
306
                'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
307
            ],
308
            bitcoin.networks.bitcoin
309
        ],
310
        [
311
            1,
312
            [
313
                'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
314
            ],
315
            bitcoin.networks.bitcoin
316
        ]
317
    ];
318
319
    var fixtures = [];
320
    data.map(function (fixture) {
321
        var script = multisigMakeScript(fixture[0], fixture[1], fixture[2]);
322
        var msDetail = multisigScriptSizes(fixture[0], script);
323
        makeUtxoFixtures(script, msDetail).map(function (fixture) {
324
            fixtures.push(fixture);
325
        });
326
    });
327
328
    return fixtures;
329
})();
330
331
// test fixtures of every possible representation of multisig
332
var p2pkUtxoFixtures = (function() {
333
    var data = [
334
        [
335
            'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
336
            bitcoin.networks.bitcoin
337
        ],
338
        [
339
            'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
340
            bitcoin.networks.bitcoin
341
        ],
342
        [
343
            'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW',
344
            bitcoin.networks.bitcoin
345
        ]
346
    ];
347
348
    var fixtures = [];
349
    data.map(function (fixture) {
350
        var script = p2pkMakeScript(fixture[0], fixture[1]);
351
        var msDetail = p2pkScriptSizes(script);
352
        makeUtxoFixtures(script, msDetail).map(function (fixture) {
353
            fixtures.push(fixture);
354
        });
355
    });
356
357
    return fixtures;
358
})();
359
360
// test fixtures of every possible representation of multisig
361
var p2pkhUtxoFixtures = (function() {
362
    var data = [
363
        [
364
            'L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
365
            bitcoin.networks.bitcoin
366
        ],
367
    ];
368
369
    var fixtures = [];
370
    data.map(function (fixture) {
371
        var script = p2pkhMakeScript(fixture[0], fixture[1]);
372
        var compressed = bitcoin.ECPair.fromWIF(fixture[0], fixture[1]).compressed;
373
        var msDetail = p2pkhScriptSizes(script, compressed);
374
        makeUtxoFixtures(script, msDetail, [compressed]).map(function (fixture) {
375
            fixtures.push(fixture);
376
        });
377
    });
378
379
    return fixtures;
380
})();
381
382
describe('SizeEstimation.getLengthForVarInt', function() {
383
    varIntFixtures.map(function(fixture) {
384
        var inputLen = fixture[0];
385
        var expectSize = fixture[1];
386
        it('works for `' + inputLen + '` (equals ' + expectSize + ')', function(cb) {
387
            var result = SizeEstimation.getLengthForVarInt(inputLen);
388
            assert.equal(expectSize, result);
389
            cb();
390
        });
391
    });
392
393
    it('throws when too large an input is provided', function(cb) {
394
        var err;
395
        try {
396
            SizeEstimation.getLengthForVarInt(0xffffffffffffffff + 1);
397
        } catch (e) {
398
            err = e
399
        }
400
401
        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...
402
        assert.equal(err.message, "Size of varint too large");
403
        cb();
404
    });
405
});
406
407
describe('SizeEstimation.getLengthForScriptPush', function() {
408
    scriptDataLenFixtures.map(function(fixture) {
409
        var inputLen = fixture[0];
410
        var expectSize = fixture[1];
411
        it(' works for ' + inputLen + '` (equals ' + expectSize + ')', function(cb) {
412
            var result = SizeEstimation.getLengthForScriptPush(inputLen);
413
            assert.equal(expectSize, result);
414
            cb();
415
        });
416
    });
417
418
    it('throws when too large an input is provided', function(cb) {
419
        var err;
420
        try {
421
            SizeEstimation.getLengthForScriptPush(0xffffffff + 1);
422
        } catch (e) {
423
            err = e
424
        }
425
426
        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...
427
        assert.equal(err.message, "Size of pushdata too large");
428
        cb();
429
    });
430
});
431
432
describe('estimateP2PKStackSize', function() {
433
    p2pkStackFixtures.map(function(fixture) {
434
        it("works for p2pk scripts with the keys", function(cb) {
435
            var script = fixture[0];
436
            assert.ok(bitcoin.script.pubKey.output.check(script));
437
            var decoded = bitcoin.script.pubKey.output.decode(script);
438
439
            var estimation = SizeEstimation.estimateP2PKStackSize(decoded);
440
            assert.equal("object", typeof estimation);
441
            assert.equal(2, estimation.length);
442
443
            var scriptSize = estimation[1];
444
            assert.equal(script.length, scriptSize);
445
446
            var stackSizes = estimation[0];
447
            assert.equal(1, stackSizes.length);
448
            assert.equal(SizeEstimation.SIZE_DER_SIGNATURE, stackSizes[0]);
449
            cb()
450
        });
451
    });
452
453
    p2pkFormFixtures.map(function(fixture) {
454
        it("deals with different representations", function(cb) {
455
            var script = fixture[0];
456
            var isWit = fixture[1];
457
            var rs = fixture[2];
458
            var ws = fixture[3];
459
            var expectSig = fixture[4];
460
            var expectWit = fixture[5];
461
462
            assert.ok(bitcoin.script.pubKey.output.check(script));
463
            var decoded = bitcoin.script.pubKey.output.decode(script);
464
            var stackEst = SizeEstimation.estimateP2PKStackSize(decoded);
465
            var stackSizes = stackEst[0];
466
467
            var est = SizeEstimation.estimateStackSignatureSize(stackSizes, isWit, rs, ws);
468
            assert.equal("object", typeof est);
469
            assert.equal(2, est.length);
470
471
            var foundSigSize = est[0];
472
            var foundWitSize = est[1];
473
474
            assert.equal(foundSigSize, expectSig);
475
            assert.equal(foundWitSize, expectWit);
476
            cb();
477
        });
478
    });
479
});
480
481
describe('estimateP2PKHStackSize', function() {
482
    p2pkhStackFixtures.map(function(fixture) {
483
        it("works for p2pkh scripts with the keys", function(cb) {
484
            var script = fixture[0];
485
            assert.ok(bitcoin.script.pubKeyHash.output.check(script));
486
            var decoded = bitcoin.script.pubKeyHash.output.decode(script);
487
488
            var estimation = SizeEstimation.estimateP2PKHStackSize(decoded);
489
            assert.equal("object", typeof estimation);
490
            assert.equal(2, estimation.length);
491
492
            var scriptSize = estimation[1];
493
            assert.equal(scriptSize, script.length);
494
495
            var stackSizes = estimation[0];
496
            assert.equal(2, stackSizes.length);
497
498
            assert.equal(stackSizes[0], SizeEstimation.SIZE_DER_SIGNATURE);
499
            assert.equal(stackSizes[1], 33);
500
            cb()
501
        });
502
    });
503
504
    p2pkhFormFixtures.map(function(fixture) {
505
        it("deals with different representations", function(cb) {
506
            var script = fixture[0];
507
            var isWit = fixture[1];
508
            var rs = fixture[2];
509
            var ws = fixture[3];
510
            var expectSig = fixture[4];
511
            var expectWit = fixture[5];
512
            var compressed = fixture[6];
513
514
            assert.ok(bitcoin.script.pubKeyHash.output.check(script));
515
516
            var stackEst = SizeEstimation.estimateP2PKHStackSize(compressed);
517
            var stackSizes = stackEst[0];
518
519
            var est = SizeEstimation.estimateStackSignatureSize(stackSizes, isWit, rs, ws);
520
            assert.equal("object", typeof est);
521
            assert.equal(2, est.length);
522
523
            var foundSigSize = est[0];
524
            var foundWitSize = est[1];
525
526
            assert.equal(foundSigSize, expectSig);
527
            assert.equal(foundWitSize, expectWit);
528
            cb();
529
        });
530
    });
531
});
532
533
describe("estimateMultisigStackSize", function() {
534
    multisigStackFixtures.map(function(fixture) {
535
        it("works for multisig scripts with the keys", function(cb) {
536
            var script = fixture[0];
537
            assert.ok(bitcoin.script.multisig.output.check(script));
538
            var decoded = bitcoin.script.multisig.output.decode(script);
539
            var estimation = SizeEstimation.estimateMultisigStackSize(decoded.m, decoded.pubKeys);
540
541
            assert.equal("object", typeof estimation);
542
            assert.equal(2, estimation.length);
543
544
            var scriptSize = estimation[1];
545
            assert.equal(script.length, scriptSize);
546
547
            var stackSizes = estimation[0];
548
            assert.equal(1 + decoded.m, stackSizes.length);
549
            assert.equal(0, stackSizes[0]);
550
            for (var i = 0; i < decoded.m; i++) {
551
                assert.equal(SizeEstimation.SIZE_DER_SIGNATURE, stackSizes[1 + i]);
552
            }
553
            cb();
554
        });
555
    });
556
557
    multisigFormFixtures.map(function(fixture) {
558
        it("deals with different representations", function(cb) {
559
            var script = fixture[0];
560
            var isWit = fixture[1];
561
            var rs = fixture[2];
562
            var ws = fixture[3];
563
            var expectSig = fixture[4];
564
            var expectWit = fixture[5];
565
566
            assert.ok(bitcoin.script.multisig.output.check(script));
567
            var multisig = bitcoin.script.multisig.output.decode(script);
568
569
            var stackEst = SizeEstimation.estimateMultisigStackSize(multisig.m, multisig.pubKeys);
570
            var stackSizes = stackEst[0];
571
572
            var est = SizeEstimation.estimateStackSignatureSize(stackSizes, isWit, rs, ws);
573
            assert.equal("object", typeof est);
574
            assert.equal(2, est.length);
575
576
            var foundSigSize = est[0];
577
            var foundWitSize = est[1];
578
579
            assert.equal(foundSigSize, expectSig);
580
            assert.equal(foundWitSize, expectWit);
581
            cb();
582
        });
583
    });
584
585
});
586
587
describe("SizeEstimation.estimateInputFromScripts", function() {
588
    it('throws on invalid script type', function(cb) {
589
        var err;
590
        try {
591
            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...
592
        } catch (e) {
593
            err = e
594
        }
595
596
        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...
597
        assert.equal(err.message, "Unsupported script type");
598
        cb();
599
    });
600
});
601
describe("SizeEstimation.estimateOutputs", function() {
602
    [0, 1, 5, 9].map(function(size) {
603
        it("estimates single output, for script size " + size, function(cb) {
604
            var script = '';
605
            for (var i = 0; i < size; i++) {
606
                script = script + '6a';
607
            }
608
            var outputsSize = SizeEstimation.calculateOutputsSize([{
609
                value: 1234,
610
                script: script
611
            }]);
612
            assert.equal(outputsSize, 8 + 1 + size);
613
            cb();
614
        });
615
    });
616
});
617
618
describe("SizeEstimation.estimateTxWeight", function() {
619
    var wif = "5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp";
620
    var key = bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
621
622
    var hash160 = bitcoin.crypto.hash160(key.getPublicKeyBuffer());
623
    var p2wpkh = bitcoin.script.witnessPubKeyHash.output.encode(hash160);
624
    var p2pkh = bitcoin.script.pubKeyHash.output.encode(hash160);
625
626
    it("estimates p2wpkh weight", function(cb) {
627
        var utxos = [
628
            {
629
                txid: "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234",
630
                vout: 0,
631
                scriptpubkey_hex: p2wpkh
632
            }
633
        ];
634
635
        var txb = new bitcoin.TransactionBuilder();
636
        utxos.map(function(utxo) {
637
            txb.addInput(utxo.txid, utxo.vout);
638
        });
639
640
        txb.addOutput(p2wpkh, 1234);
641
        var tx = txb.buildIncomplete();
642
643
        var size = SizeEstimation.estimateTxWeight(tx, utxos);
644
        var vsize = SizeEstimation.estimateTxVsize(tx, utxos);
645
646
        assert.equal(Math.ceil(size / 4), vsize);
647
        cb();
648
    });
649
650
    it("weight for non-witness is 4x size", function(cb) {
651
        var utxos = [
652
            {
653
                txid: "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234",
654
                vout: 0,
655
                scriptpubkey_hex: p2pkh
656
            }
657
        ];
658
659
        var txb = new bitcoin.TransactionBuilder();
660
        utxos.map(function(utxo) {
661
            txb.addInput(utxo.txid, utxo.vout);
662
        });
663
664
        txb.addOutput(p2wpkh, 1234);
665
        var tx = txb.buildIncomplete();
666
667
        var os = SizeEstimation.calculateOutputsSize(tx.outs);
668
        var bs = 4 + 4 + SizeEstimation.estimateInputsSize(utxos, false) + 4 + os + 4;
669
670
        var size = SizeEstimation.estimateTxWeight(tx, utxos);
671
        assert.equal(size, bs * 4);
672
673
        var vsize = SizeEstimation.estimateTxVsize(tx, utxos);
674
        assert.equal(Math.ceil(size / 4), vsize);
675
        cb();
676
    });
677
});
678
679
describe("SizeEstimation.estimateInputsSize", function() {
680
    var wif = "5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp";
681
    var key = bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
682
683
    var hash160 = bitcoin.crypto.hash160(key.getPublicKeyBuffer());
684
    var p2wpkh = bitcoin.script.witnessPubKeyHash.output.encode(hash160);
685
686
    it("drops witness based on parameter", function(cb) {
687
        var withWitness = SizeEstimation.estimateInputsSize([{
688
            value: 1234,
689
            scriptpubkey_hex: p2wpkh
690
        }], true);
691
692
        var noWitness = SizeEstimation.estimateInputsSize([{
693
            value: 1234,
694
            scriptpubkey_hex: p2wpkh
695
        }], false);
696
697
        assert.equal(noWitness, 32+4+4+1);
698
699
        var assumeSize = noWitness +
700
            /*witness flags*/2 +
701
            /*witness vector with one input*/(1+1+SizeEstimation.SIZE_DER_SIGNATURE+1+33);
702
703
        assert.ok(assumeSize  === withWitness);
704
705
        cb();
706
    });
707
});
708
709
describe("SizeEstimation.estimateUtxo", function() {
710
    it("throws if P2SH and redeemScript not provided", function(cb) {
711
        var err;
712
        try {
713
            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...
714
            var spk = bitcoin.script.scriptHash.output.encode(hash160);
715
            SizeEstimation.estimateUtxo({
716
                scriptpubkey_hex: spk,
717
                redeem_script: null
718
            });
719
        } catch (e) {
720
            err = e
721
        }
722
723
        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...
724
        assert.equal(err.message, "Cant estimate, missing redeem script");
725
        cb();
726
    });
727
728
    it("throws if P2WSH and witnessScript not provided", function(cb) {
729
        var err;
730
        try {
731
            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...
732
            var spk = bitcoin.script.witnessScriptHash.output.encode(hash160);
733
            SizeEstimation.estimateUtxo({
734
                scriptpubkey_hex: spk,
735
                witness_script: null
736
            });
737
        } catch (e) {
738
            err = e
739
        }
740
741
        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...
742
        assert.equal(err.message, "Can't estimate, missing witness script");
743
        cb();
744
    });
745
746
    it("throws if unsupported script type", function(cb) {
747
        var err;
748
        try {
749
            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...
750
            SizeEstimation.estimateUtxo({
751
                scriptpubkey_hex: spk,
752
                witness_script: null
753
            });
754
        } catch (e) {
755
            err = e
756
        }
757
758
        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...
759
        assert.equal(err.message, "Unsupported script type");
760
        cb();
761
    });
762
763
    []
764
        .concat(multisigUtxoFixtures)
765
        .concat(p2pkUtxoFixtures)
766
        .concat(p2pkhUtxoFixtures)
767
        .map(function(fixture) {
768
            it("deals with different representations", function(cb) {
769
                var utxo = fixture[0];
770
                var expectSig = fixture[1];
771
                var expectWit = fixture[2];
772
                var compressed = false;
773
                if (typeof fixture[3] === "boolean") {
774
                    compressed = fixture[3];
775
                }
776
777
                var estimate = SizeEstimation.estimateUtxo(utxo, compressed);
778
779
                assert.equal(estimate.scriptSig, expectSig);
780
                assert.equal(estimate.witness, expectWit);
781
                cb();
782
            });
783
        });
784
});
785
786
787
describe("estimateWitnessPubKeyHash", function() {
788
    it('should work', function(cb) {
789
        var utxo = { hash: '4141414141414141414141414141414141414141414141414141414141414141',
790
            idx: 2,
791
            scriptpubkey_hex: '00140102030401020304010203040102030401020304',
792
            value: 1,
793
            confirmations: 1,
794
            sign_mode: 'dont_sign',
795
            address: '2N245vnpchbFYWm5hZ6hqF2zC8QbVpoHeSU',
796
            path: null,
797
            redeem_script: null,
798
            witness_script: null,
799
            green: null };
800
801
        var estimation = SizeEstimation.estimateUtxo(utxo);
802
803
        assert.equal(1, estimation.scriptSig);
804
        assert.equal(108, estimation.witness);
805
806
        cb();
807
    });
808
});
809