@opcat-labs/opcat 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mocharc.yaml +3 -0
- package/index.d.ts +1541 -0
- package/index.js +74 -0
- package/lib/address.js +478 -0
- package/lib/block/block.js +277 -0
- package/lib/block/blockheader.js +295 -0
- package/lib/block/index.js +4 -0
- package/lib/block/merkleblock.js +323 -0
- package/lib/bn.js +3423 -0
- package/lib/crypto/bn.js +278 -0
- package/lib/crypto/ecdsa.js +339 -0
- package/lib/crypto/hash.browser.js +171 -0
- package/lib/crypto/hash.js +2 -0
- package/lib/crypto/hash.node.js +171 -0
- package/lib/crypto/point.js +221 -0
- package/lib/crypto/random.browser.js +28 -0
- package/lib/crypto/random.js +2 -0
- package/lib/crypto/random.node.js +11 -0
- package/lib/crypto/signature.js +325 -0
- package/lib/encoding/base58.js +111 -0
- package/lib/encoding/base58check.js +121 -0
- package/lib/encoding/bufferreader.js +212 -0
- package/lib/encoding/bufferwriter.js +140 -0
- package/lib/encoding/decode-asm.js +24 -0
- package/lib/encoding/decode-hex.js +32 -0
- package/lib/encoding/decode-script-chunks.js +43 -0
- package/lib/encoding/encode-hex.js +284 -0
- package/lib/encoding/is-hex.js +7 -0
- package/lib/encoding/varint.js +75 -0
- package/lib/errors/index.js +54 -0
- package/lib/errors/spec.js +314 -0
- package/lib/hash-cache.js +50 -0
- package/lib/hdprivatekey.js +678 -0
- package/lib/hdpublickey.js +525 -0
- package/lib/message/message.js +191 -0
- package/lib/mnemonic/mnemonic.js +303 -0
- package/lib/mnemonic/pbkdf2.browser.js +68 -0
- package/lib/mnemonic/pbkdf2.js +2 -0
- package/lib/mnemonic/pbkdf2.node.js +68 -0
- package/lib/mnemonic/words/chinese.js +2054 -0
- package/lib/mnemonic/words/english.js +2054 -0
- package/lib/mnemonic/words/french.js +2054 -0
- package/lib/mnemonic/words/index.js +8 -0
- package/lib/mnemonic/words/italian.js +2054 -0
- package/lib/mnemonic/words/japanese.js +2054 -0
- package/lib/mnemonic/words/spanish.js +2054 -0
- package/lib/networks.js +379 -0
- package/lib/opcode.js +255 -0
- package/lib/privatekey.js +374 -0
- package/lib/publickey.js +386 -0
- package/lib/script/index.js +5 -0
- package/lib/script/interpreter.js +1834 -0
- package/lib/script/script.js +1074 -0
- package/lib/script/stack.js +109 -0
- package/lib/script/write-i32-le.js +17 -0
- package/lib/script/write-push-data.js +35 -0
- package/lib/script/write-u16-le.js +12 -0
- package/lib/script/write-u32-le.js +16 -0
- package/lib/script/write-u64-le.js +24 -0
- package/lib/script/write-u8-le.js +8 -0
- package/lib/script/write-varint.js +46 -0
- package/lib/transaction/index.js +7 -0
- package/lib/transaction/input/index.js +5 -0
- package/lib/transaction/input/input.js +354 -0
- package/lib/transaction/input/multisig.js +242 -0
- package/lib/transaction/input/publickey.js +100 -0
- package/lib/transaction/input/publickeyhash.js +118 -0
- package/lib/transaction/output.js +231 -0
- package/lib/transaction/sighash.js +167 -0
- package/lib/transaction/signature.js +97 -0
- package/lib/transaction/transaction.js +1639 -0
- package/lib/transaction/unspentoutput.js +113 -0
- package/lib/util/_.js +47 -0
- package/lib/util/js.js +90 -0
- package/lib/util/preconditions.js +33 -0
- package/package.json +26 -0
- package/test/address.js +509 -0
- package/test/block/block.js +251 -0
- package/test/block/blockheader.js +275 -0
- package/test/block/merklebloack.js +211 -0
- package/test/crypto/bn.js +177 -0
- package/test/crypto/ecdsa.js +391 -0
- package/test/crypto/hash.browser.js +135 -0
- package/test/crypto/hash.js +136 -0
- package/test/crypto/point.js +224 -0
- package/test/crypto/random.js +32 -0
- package/test/crypto/signature.js +409 -0
- package/test/data/bip69.json +215 -0
- package/test/data/bitcoind/base58_keys_invalid.json +52 -0
- package/test/data/bitcoind/base58_keys_valid.json +335 -0
- package/test/data/bitcoind/blocks.json +22 -0
- package/test/data/bitcoind/script_tests.json +3822 -0
- package/test/data/bitcoind/sig_canonical.json +7 -0
- package/test/data/bitcoind/sig_noncanonical.json +36 -0
- package/test/data/bitcoind/tx_invalid.json +445 -0
- package/test/data/bitcoind/tx_valid.json +44 -0
- package/test/data/blk86756-testnet.dat +0 -0
- package/test/data/blk86756-testnet.js +14 -0
- package/test/data/blk86756-testnet.json +684 -0
- package/test/data/block.hex +1 -0
- package/test/data/ecdsa.json +230 -0
- package/test/data/merkleblocks.js +488 -0
- package/test/data/messages.json +22 -0
- package/test/data/sighash.json +12 -0
- package/test/data/tx_creation.json +95 -0
- package/test/encoding/base58.js +131 -0
- package/test/encoding/base58check.js +136 -0
- package/test/encoding/bufferreader.js +337 -0
- package/test/encoding/bufferwriter.js +172 -0
- package/test/encoding/varint.js +104 -0
- package/test/hashCache.js +67 -0
- package/test/hdkeys.js +445 -0
- package/test/hdprivatekey.js +332 -0
- package/test/hdpublickey.js +304 -0
- package/test/index.js +16 -0
- package/test/message/message.js +204 -0
- package/test/mnemonic/data/fixtures.json +300 -0
- package/test/mnemonic/mnemonic.js +259 -0
- package/test/mnemonic/mocha.opts +1 -0
- package/test/mnemonic/pbkdf2.test.js +59 -0
- package/test/networks.js +159 -0
- package/test/opcode.js +161 -0
- package/test/privatekey.js +439 -0
- package/test/publickey.js +554 -0
- package/test/script/interpreter.js +734 -0
- package/test/script/script.js +1437 -0
- package/test/transaction/deserialize.js +34 -0
- package/test/transaction/input/input.js +90 -0
- package/test/transaction/input/multisig.js +90 -0
- package/test/transaction/input/publickey.js +68 -0
- package/test/transaction/input/publickeyhash.js +51 -0
- package/test/transaction/output.js +185 -0
- package/test/transaction/sighash.js +65 -0
- package/test/transaction/signature.js +114 -0
- package/test/transaction/transaction.js +1109 -0
- package/test/transaction/unspentoutput.js +110 -0
- package/test/util/js.js +76 -0
- package/test/util/preconditions.js +79 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var should = require('chai').should();
|
|
4
|
+
var opcat = require('../..');
|
|
5
|
+
var Point = opcat.crypto.Point;
|
|
6
|
+
var BN = opcat.crypto.BN;
|
|
7
|
+
|
|
8
|
+
describe('Point', function () {
|
|
9
|
+
var valid = {
|
|
10
|
+
x: 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2',
|
|
11
|
+
y: '4836ab292c105a711ed10fcfd30999c31ff7c02456147747e03e739ad527c380',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
it('should create a point', function () {
|
|
15
|
+
var p = Point(valid.x, valid.y);
|
|
16
|
+
should.exist(p);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should create a point when called with "new"', function () {
|
|
20
|
+
var p = new Point(valid.x, valid.y);
|
|
21
|
+
should.exist(p);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('#getX', function () {
|
|
25
|
+
it('should return x', function () {
|
|
26
|
+
var p = Point(valid.x, valid.y);
|
|
27
|
+
var x = p.getX();
|
|
28
|
+
x.toString('hex', 64).should.equal(valid.x);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should be convertable to a buffer', function () {
|
|
32
|
+
var p = Point(valid.x, valid.y);
|
|
33
|
+
var a = p.getX().toBuffer({ size: 32 });
|
|
34
|
+
a.length.should.equal(32);
|
|
35
|
+
a.should.deep.equal(Buffer.from(valid.x, 'hex'));
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('#getY', function () {
|
|
40
|
+
it('should return y', function () {
|
|
41
|
+
var p = Point(valid.x, valid.y);
|
|
42
|
+
p.getY().toString('hex', 64).should.equal(valid.y);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should be convertable to a buffer', function () {
|
|
46
|
+
var p = Point(valid.x, valid.y);
|
|
47
|
+
var a = p.getY().toBuffer({ size: 32 });
|
|
48
|
+
a.length.should.equal(32);
|
|
49
|
+
a.should.deep.equal(Buffer.from(valid.y, 'hex'));
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('#add', function () {
|
|
54
|
+
it('should accurately add g to itself', function () {
|
|
55
|
+
var p1 = Point.getG();
|
|
56
|
+
var p2 = Point.getG();
|
|
57
|
+
var p3 = p1.add(p2);
|
|
58
|
+
p3.getX()
|
|
59
|
+
.toString()
|
|
60
|
+
.should.equal(
|
|
61
|
+
'89565891926547004231252920425935692360644145829622209' + '833684329913297188986597',
|
|
62
|
+
);
|
|
63
|
+
p3.getY()
|
|
64
|
+
.toString()
|
|
65
|
+
.should.equal(
|
|
66
|
+
'12158399299693830322967808612713398636155367887041628' + '176798871954788371653930',
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe('#mul', function () {
|
|
72
|
+
it('should accurately multiply g by 2', function () {
|
|
73
|
+
var g = Point.getG();
|
|
74
|
+
var b = g.mul(new BN(2));
|
|
75
|
+
b.getX()
|
|
76
|
+
.toString()
|
|
77
|
+
.should.equal(
|
|
78
|
+
'8956589192654700423125292042593569236064414582962220983' + '3684329913297188986597',
|
|
79
|
+
);
|
|
80
|
+
b.getY()
|
|
81
|
+
.toString()
|
|
82
|
+
.should.equal(
|
|
83
|
+
'1215839929969383032296780861271339863615536788704162817' + '6798871954788371653930',
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should accurately multiply g by n-1', function () {
|
|
88
|
+
var g = Point.getG();
|
|
89
|
+
var n = Point.getN();
|
|
90
|
+
var b = g.mul(n.sub(new BN(1)));
|
|
91
|
+
b.getX()
|
|
92
|
+
.toString()
|
|
93
|
+
.should.equal(
|
|
94
|
+
'55066263022277343669578718895168534326250603453777594175' + '500187360389116729240',
|
|
95
|
+
);
|
|
96
|
+
b.getY()
|
|
97
|
+
.toString()
|
|
98
|
+
.should.equal(
|
|
99
|
+
'83121579216557378445487899878180864668798711284981320763' + '518679672151497189239',
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// not sure if this is technically accurate or not...
|
|
104
|
+
// normally, you should always multiply g by something less than n
|
|
105
|
+
// but it is the same result in OpenSSL
|
|
106
|
+
it('should accurately multiply g by n+1', function () {
|
|
107
|
+
var g = Point.getG();
|
|
108
|
+
var n = Point.getN();
|
|
109
|
+
var b = g.mul(n.add(new BN(1)));
|
|
110
|
+
b.getX()
|
|
111
|
+
.toString()
|
|
112
|
+
.should.equal(
|
|
113
|
+
'550662630222773436695787188951685343262506034537775941755' + '00187360389116729240',
|
|
114
|
+
);
|
|
115
|
+
b.getY()
|
|
116
|
+
.toString()
|
|
117
|
+
.should.equal(
|
|
118
|
+
'326705100207588169780830851305070431844712733806592432759' + '38904335757337482424',
|
|
119
|
+
);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('@fromX', function () {
|
|
124
|
+
it('should return g', function () {
|
|
125
|
+
var g = Point.getG();
|
|
126
|
+
var p = Point.fromX(false, g.getX());
|
|
127
|
+
g.eq(p).should.equal(true);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
describe('@pointToCompressed', function () {
|
|
132
|
+
it('should return g', function () {
|
|
133
|
+
let g = Point.getG();
|
|
134
|
+
let pbuf = Point.pointToCompressed(g);
|
|
135
|
+
pbuf.length.should.equal(33);
|
|
136
|
+
pbuf
|
|
137
|
+
.toString('hex')
|
|
138
|
+
.should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
describe('#toBuffer', function () {
|
|
143
|
+
it('should return g', function () {
|
|
144
|
+
let g = Point.getG();
|
|
145
|
+
let pbuf = g.toBuffer();
|
|
146
|
+
pbuf.length.should.equal(33);
|
|
147
|
+
pbuf
|
|
148
|
+
.toString('hex')
|
|
149
|
+
.should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe('@fromBuffer', function () {
|
|
154
|
+
it('should return g', function () {
|
|
155
|
+
let buf = Buffer.from(
|
|
156
|
+
'0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798',
|
|
157
|
+
'hex',
|
|
158
|
+
);
|
|
159
|
+
let p = Point.fromBuffer(buf);
|
|
160
|
+
p.toBuffer().toString('hex').should.equal(buf.toString('hex'));
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
describe('#toHex', function () {
|
|
165
|
+
it('should return g', function () {
|
|
166
|
+
let g = Point.getG();
|
|
167
|
+
let phex = g.toHex();
|
|
168
|
+
phex.length.should.equal(33 * 2);
|
|
169
|
+
phex.should.equal('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('@fromHex', function () {
|
|
174
|
+
it('should return g', function () {
|
|
175
|
+
let hex = '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798';
|
|
176
|
+
let p = Point.fromHex(hex);
|
|
177
|
+
p.toHex().should.equal(hex);
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe('#validate', function () {
|
|
182
|
+
it('should describe this point as valid', function () {
|
|
183
|
+
var p = Point(valid.x, valid.y);
|
|
184
|
+
should.exist(p.validate());
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('should describe this point as invalid because of zero y', function () {
|
|
188
|
+
var x = 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2';
|
|
189
|
+
var y = '0000000000000000000000000000000000000000000000000000000000000000';
|
|
190
|
+
(function () {
|
|
191
|
+
Point(x, y);
|
|
192
|
+
}).should.throw('Invalid y value for curve.');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should describe this point as invalid because of invalid y', function () {
|
|
196
|
+
var x = 'ac242d242d23be966085a2b2b893d989f824e06c9ad0395a8a52f055ba39abb2';
|
|
197
|
+
var y = '00000000000000000000000000000000000000000000000000000000000000FF';
|
|
198
|
+
(function () {
|
|
199
|
+
Point(x, y);
|
|
200
|
+
}).should.throw('Invalid y value for curve.');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should describe this point as invalid because out of curve bounds', function () {
|
|
204
|
+
// point larger than max
|
|
205
|
+
var x = 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEDCE6AF48A03BBFD25E8CD0364141';
|
|
206
|
+
// calculated y of x
|
|
207
|
+
var y = 'ed3970f129bc2ca7c7c6cf92fa7da4de6a1dfc9c14da4bf056aa868d3dd74034';
|
|
208
|
+
|
|
209
|
+
(function () {
|
|
210
|
+
// set the point
|
|
211
|
+
Point(x, y);
|
|
212
|
+
}).should.throw('Point does not lie on the curve');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should describe this point as invalid because out of curve bounds', function () {
|
|
216
|
+
var x = '0000000000000000000000000000000000000000000000000000000000000000';
|
|
217
|
+
|
|
218
|
+
(function () {
|
|
219
|
+
// set the point
|
|
220
|
+
Point.fromX(false, x);
|
|
221
|
+
}).should.throw('Invalid X');
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var opcat = require('../..');
|
|
4
|
+
var Random = opcat.crypto.Random;
|
|
5
|
+
|
|
6
|
+
describe('Random', function () {
|
|
7
|
+
describe('@getRandomBuffer', function () {
|
|
8
|
+
it('should return a buffer', function () {
|
|
9
|
+
var bytes = Random.getRandomBuffer(8);
|
|
10
|
+
bytes.length.should.equal(8);
|
|
11
|
+
Buffer.isBuffer(bytes).should.equal(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should not equate two 256 bit random buffers', function () {
|
|
15
|
+
var bytes1 = Random.getRandomBuffer(32);
|
|
16
|
+
var bytes2 = Random.getRandomBuffer(32);
|
|
17
|
+
bytes1.toString('hex').should.not.equal(bytes2.toString('hex'));
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should generate 100 8 byte buffers in a row that are not equal', function () {
|
|
21
|
+
var hexs = [];
|
|
22
|
+
for (var i = 0; i < 100; i++) {
|
|
23
|
+
hexs[i] = Random.getRandomBuffer(8).toString('hex');
|
|
24
|
+
}
|
|
25
|
+
for (i = 0; i < 100; i++) {
|
|
26
|
+
for (var j = i + 1; j < 100; j++) {
|
|
27
|
+
hexs[i].should.not.equal(hexs[j]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
});
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _ = require('../../lib/util/_');
|
|
4
|
+
var should = require('chai').should();
|
|
5
|
+
var opcat = require('../..');
|
|
6
|
+
var BN = opcat.crypto.BN;
|
|
7
|
+
var Signature = opcat.crypto.Signature;
|
|
8
|
+
var JSUtil = opcat.util.js;
|
|
9
|
+
var Interpreter = opcat.Script.Interpreter;
|
|
10
|
+
|
|
11
|
+
var sigCanonical = require('../data/bitcoind/sig_canonical');
|
|
12
|
+
var sigNonCanonical = require('../data/bitcoind/sig_noncanonical');
|
|
13
|
+
|
|
14
|
+
describe('Signature', function () {
|
|
15
|
+
it('should make a blank signature', function () {
|
|
16
|
+
var sig = new Signature();
|
|
17
|
+
should.exist(sig);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should work with conveniently setting r, s', function () {
|
|
21
|
+
var r = new BN();
|
|
22
|
+
var s = new BN();
|
|
23
|
+
var sig = new Signature(r, s);
|
|
24
|
+
should.exist(sig);
|
|
25
|
+
sig.r.toString().should.equal(r.toString());
|
|
26
|
+
sig.s.toString().should.equal(s.toString());
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
describe('#set', function () {
|
|
30
|
+
it('should set compressed', function () {
|
|
31
|
+
should.exist(
|
|
32
|
+
Signature().set({
|
|
33
|
+
compressed: true,
|
|
34
|
+
}),
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should set nhashtype', function () {
|
|
39
|
+
var sig = Signature().set({
|
|
40
|
+
nhashtype: Signature.SIGHASH_ALL,
|
|
41
|
+
});
|
|
42
|
+
sig.nhashtype.should.equal(Signature.SIGHASH_ALL);
|
|
43
|
+
sig.set({
|
|
44
|
+
nhashtype: Signature.SIGHASH_ALL | Signature.SIGHASH_ANYONECANPAY,
|
|
45
|
+
});
|
|
46
|
+
sig.nhashtype.should.equal(Signature.SIGHASH_ALL | Signature.SIGHASH_ANYONECANPAY);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('#fromCompact', function () {
|
|
51
|
+
it('should create a signature from a compressed signature', function () {
|
|
52
|
+
var blank = Buffer.alloc(32);
|
|
53
|
+
blank.fill(0);
|
|
54
|
+
var compressed = Buffer.concat([Buffer.from([0 + 27 + 4]), blank, blank]);
|
|
55
|
+
var sig = Signature.fromCompact(compressed);
|
|
56
|
+
sig.r.cmp(BN.Zero).should.equal(0);
|
|
57
|
+
sig.s.cmp(BN.Zero).should.equal(0);
|
|
58
|
+
sig.compressed.should.equal(true);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('should create a signature from an uncompressed signature', function () {
|
|
62
|
+
var sigHexaStr =
|
|
63
|
+
'1cd5e61ab5bfd0d1450997894cb1a53e917f89d82eb43f06fa96f32c96e061aec12fc1188e8b' +
|
|
64
|
+
'0dc553a2588be2b5b68dbbd7f092894aa3397786e9c769c5348dc6';
|
|
65
|
+
var sig = Signature.fromCompact(Buffer.from(sigHexaStr, 'hex'));
|
|
66
|
+
var r = 'd5e61ab5bfd0d1450997894cb1a53e917f89d82eb43f06fa96f32c96e061aec1';
|
|
67
|
+
var s = '2fc1188e8b0dc553a2588be2b5b68dbbd7f092894aa3397786e9c769c5348dc6';
|
|
68
|
+
sig.r.toString('hex').should.equal(r);
|
|
69
|
+
sig.s.toString('hex').should.equal(s);
|
|
70
|
+
sig.compressed.should.equal(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('#fromDER', function () {
|
|
75
|
+
var buf = Buffer.from(
|
|
76
|
+
'3044022075fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e62770220729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2',
|
|
77
|
+
'hex',
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
it('should parse this DER format signature', function () {
|
|
81
|
+
var sig = Signature.fromDER(buf);
|
|
82
|
+
sig.r
|
|
83
|
+
.toBuffer({
|
|
84
|
+
size: 32,
|
|
85
|
+
})
|
|
86
|
+
.toString('hex')
|
|
87
|
+
.should.equal('75fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e6277');
|
|
88
|
+
sig.s
|
|
89
|
+
.toBuffer({
|
|
90
|
+
size: 32,
|
|
91
|
+
})
|
|
92
|
+
.toString('hex')
|
|
93
|
+
.should.equal('729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2');
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('#fromString', function () {
|
|
98
|
+
var buf = Buffer.from(
|
|
99
|
+
'3044022075fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e62770220729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2',
|
|
100
|
+
'hex',
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
it('should parse this DER format signature in hex', function () {
|
|
104
|
+
var sig = Signature.fromString(buf.toString('hex'));
|
|
105
|
+
sig.r
|
|
106
|
+
.toBuffer({
|
|
107
|
+
size: 32,
|
|
108
|
+
})
|
|
109
|
+
.toString('hex')
|
|
110
|
+
.should.equal('75fc517e541bd54769c080b64397e32161c850f6c1b2b67a5c433affbb3e6277');
|
|
111
|
+
sig.s
|
|
112
|
+
.toBuffer({
|
|
113
|
+
size: 32,
|
|
114
|
+
})
|
|
115
|
+
.toString('hex')
|
|
116
|
+
.should.equal('729e85cc46ffab881065ec07694220e71d4df9b2b8c8fd12c3122cf3a5efbcf2');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('#toTxFormat', function () {
|
|
121
|
+
it('should parse this known signature and rebuild it with updated zero-padded sighash types', function () {
|
|
122
|
+
var original =
|
|
123
|
+
'30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e7201';
|
|
124
|
+
var buf = Buffer.from(original, 'hex');
|
|
125
|
+
var sig = Signature.fromTxFormat(buf);
|
|
126
|
+
sig.nhashtype.should.equal(Signature.SIGHASH_ALL);
|
|
127
|
+
sig.set({
|
|
128
|
+
nhashtype: Signature.SIGHASH_ALL | Signature.SIGHASH_ANYONECANPAY,
|
|
129
|
+
});
|
|
130
|
+
sig
|
|
131
|
+
.toTxFormat()
|
|
132
|
+
.toString('hex')
|
|
133
|
+
.should.equal(original.slice(0, -2) + '81');
|
|
134
|
+
sig.set({
|
|
135
|
+
nhashtype: Signature.SIGHASH_SINGLE,
|
|
136
|
+
});
|
|
137
|
+
sig
|
|
138
|
+
.toTxFormat()
|
|
139
|
+
.toString('hex')
|
|
140
|
+
.should.equal(original.slice(0, -2) + '03');
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe('#fromTxFormat', function () {
|
|
145
|
+
it('should convert from this known tx-format buffer', function () {
|
|
146
|
+
var buf = Buffer.from(
|
|
147
|
+
'30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e7201',
|
|
148
|
+
'hex',
|
|
149
|
+
);
|
|
150
|
+
var sig = Signature.fromTxFormat(buf);
|
|
151
|
+
sig.r
|
|
152
|
+
.toString()
|
|
153
|
+
.should.equal(
|
|
154
|
+
'63173831029936981022572627018246571655303050627048489594159321588908385378810',
|
|
155
|
+
);
|
|
156
|
+
sig.s
|
|
157
|
+
.toString()
|
|
158
|
+
.should.equal(
|
|
159
|
+
'4331694221846364448463828256391194279133231453999942381442030409253074198130',
|
|
160
|
+
);
|
|
161
|
+
sig.nhashtype.should.equal(Signature.SIGHASH_ALL);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should parse this known signature and rebuild it', function () {
|
|
165
|
+
var hex =
|
|
166
|
+
'3044022007415aa37ce7eaa6146001ac8bdefca0ddcba0e37c5dc08c4ac99392124ebac802207d382307fd53f65778b07b9c63b6e196edeadf0be719130c5db21ff1e700d67501';
|
|
167
|
+
var buf = Buffer.from(hex, 'hex');
|
|
168
|
+
var sig = Signature.fromTxFormat(buf);
|
|
169
|
+
sig.toTxFormat().toString('hex').should.equal(hex);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
describe('#parseDER', function () {
|
|
174
|
+
it('should parse this signature generated in node', function () {
|
|
175
|
+
var sighex =
|
|
176
|
+
'30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e72';
|
|
177
|
+
var sig = Buffer.from(sighex, 'hex');
|
|
178
|
+
var parsed = Signature.parseDER(sig);
|
|
179
|
+
parsed.header.should.equal(0x30);
|
|
180
|
+
parsed.length.should.equal(69);
|
|
181
|
+
parsed.rlength.should.equal(33);
|
|
182
|
+
parsed.rneg.should.equal(true);
|
|
183
|
+
parsed.rbuf
|
|
184
|
+
.toString('hex')
|
|
185
|
+
.should.equal('008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa');
|
|
186
|
+
parsed.r
|
|
187
|
+
.toString()
|
|
188
|
+
.should.equal(
|
|
189
|
+
'63173831029936981022572627018246571655303050627048489594159321588908385378810',
|
|
190
|
+
);
|
|
191
|
+
parsed.slength.should.equal(32);
|
|
192
|
+
parsed.sneg.should.equal(false);
|
|
193
|
+
parsed.sbuf
|
|
194
|
+
.toString('hex')
|
|
195
|
+
.should.equal('0993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e72');
|
|
196
|
+
parsed.s
|
|
197
|
+
.toString()
|
|
198
|
+
.should.equal(
|
|
199
|
+
'4331694221846364448463828256391194279133231453999942381442030409253074198130',
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should parse this 69 byte signature', function () {
|
|
204
|
+
var sighex =
|
|
205
|
+
'3043021f59e4705959cc78acbfcf8bd0114e9cc1b389a4287fb33152b73a38c319b50302202f7428a27284c757e409bf41506183e9e49dfb54d5063796dfa0d403a4deccfa';
|
|
206
|
+
var sig = Buffer.from(sighex, 'hex');
|
|
207
|
+
var parsed = Signature.parseDER(sig);
|
|
208
|
+
parsed.header.should.equal(0x30);
|
|
209
|
+
parsed.length.should.equal(67);
|
|
210
|
+
parsed.rlength.should.equal(31);
|
|
211
|
+
parsed.rneg.should.equal(false);
|
|
212
|
+
parsed.rbuf
|
|
213
|
+
.toString('hex')
|
|
214
|
+
.should.equal('59e4705959cc78acbfcf8bd0114e9cc1b389a4287fb33152b73a38c319b503');
|
|
215
|
+
parsed.r
|
|
216
|
+
.toString()
|
|
217
|
+
.should.equal(
|
|
218
|
+
'158826015856106182499128681792325160381907915189052224498209222621383996675',
|
|
219
|
+
);
|
|
220
|
+
parsed.slength.should.equal(32);
|
|
221
|
+
parsed.sneg.should.equal(false);
|
|
222
|
+
parsed.sbuf
|
|
223
|
+
.toString('hex')
|
|
224
|
+
.should.equal('2f7428a27284c757e409bf41506183e9e49dfb54d5063796dfa0d403a4deccfa');
|
|
225
|
+
parsed.s
|
|
226
|
+
.toString()
|
|
227
|
+
.should.equal(
|
|
228
|
+
'21463938592353267769710297084836796652964571266930856168996063301532842380538',
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should parse this 68 byte signature', function () {
|
|
233
|
+
var sighex =
|
|
234
|
+
'3042021e17cfe77536c3fb0526bd1a72d7a8e0973f463add210be14063c8a9c37632022061bfa677f825ded82ba0863fb0c46ca1388dd3e647f6a93c038168b59d131a51';
|
|
235
|
+
var sig = Buffer.from(sighex, 'hex');
|
|
236
|
+
var parsed = Signature.parseDER(sig);
|
|
237
|
+
parsed.header.should.equal(0x30);
|
|
238
|
+
parsed.length.should.equal(66);
|
|
239
|
+
parsed.rlength.should.equal(30);
|
|
240
|
+
parsed.rneg.should.equal(false);
|
|
241
|
+
parsed.rbuf
|
|
242
|
+
.toString('hex')
|
|
243
|
+
.should.equal('17cfe77536c3fb0526bd1a72d7a8e0973f463add210be14063c8a9c37632');
|
|
244
|
+
parsed.r
|
|
245
|
+
.toString()
|
|
246
|
+
.should.equal('164345250294671732127776123343329699648286106708464198588053542748255794');
|
|
247
|
+
parsed.slength.should.equal(32);
|
|
248
|
+
parsed.sneg.should.equal(false);
|
|
249
|
+
parsed.sbuf
|
|
250
|
+
.toString('hex')
|
|
251
|
+
.should.equal('61bfa677f825ded82ba0863fb0c46ca1388dd3e647f6a93c038168b59d131a51');
|
|
252
|
+
parsed.s
|
|
253
|
+
.toString()
|
|
254
|
+
.should.equal(
|
|
255
|
+
'44212963026209759051804639008236126356702363229859210154760104982946304432721',
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
it('should parse this signature from script_valid.json', function () {
|
|
260
|
+
var sighex =
|
|
261
|
+
'304502203e4516da7253cf068effec6b95c41221c0cf3a8e6ccb8cbf1725b562e9afde2c022100ab1e3da73d67e32045a20e0b999e049978ea8d6ee5480d485fcf2ce0d03b2ef051';
|
|
262
|
+
var sig = Buffer.from(sighex, 'hex');
|
|
263
|
+
var parsed = Signature.parseDER(sig, false);
|
|
264
|
+
should.exist(parsed);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
describe('#toDER', function () {
|
|
269
|
+
it('should convert these known r and s values into a known signature', function () {
|
|
270
|
+
var r = new BN(
|
|
271
|
+
'63173831029936981022572627018246571655303050627048489594159321588908385378810',
|
|
272
|
+
);
|
|
273
|
+
var s = new BN(
|
|
274
|
+
'4331694221846364448463828256391194279133231453999942381442030409253074198130',
|
|
275
|
+
);
|
|
276
|
+
var sig = new Signature({
|
|
277
|
+
r: r,
|
|
278
|
+
s: s,
|
|
279
|
+
});
|
|
280
|
+
var der = sig.toDER(r, s);
|
|
281
|
+
der
|
|
282
|
+
.toString('hex')
|
|
283
|
+
.should.equal(
|
|
284
|
+
'30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e72',
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
describe('#toString', function () {
|
|
290
|
+
it('should convert this signature in to hex DER', function () {
|
|
291
|
+
var r = new BN(
|
|
292
|
+
'63173831029936981022572627018246571655303050627048489594159321588908385378810',
|
|
293
|
+
);
|
|
294
|
+
var s = new BN(
|
|
295
|
+
'4331694221846364448463828256391194279133231453999942381442030409253074198130',
|
|
296
|
+
);
|
|
297
|
+
var sig = new Signature({
|
|
298
|
+
r: r,
|
|
299
|
+
s: s,
|
|
300
|
+
});
|
|
301
|
+
var hex = sig.toString();
|
|
302
|
+
hex.should.equal(
|
|
303
|
+
'30450221008bab1f0a2ff2f9cb8992173d8ad73c229d31ea8e10b0f4d4ae1a0d8ed76021fa02200993a6ec81755b9111762fc2cf8e3ede73047515622792110867d12654275e72',
|
|
304
|
+
);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
describe('@isTxDER', function () {
|
|
309
|
+
it('should know this is a DER signature', function () {
|
|
310
|
+
var sighex =
|
|
311
|
+
'3042021e17cfe77536c3fb0526bd1a72d7a8e0973f463add210be14063c8a9c37632022061bfa677f825ded82ba0863fb0c46ca1388dd3e647f6a93c038168b59d131a5101';
|
|
312
|
+
var sigbuf = Buffer.from(sighex, 'hex');
|
|
313
|
+
Signature.isTxDER(sigbuf).should.equal(true);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it('should know this is not a DER signature', function () {
|
|
317
|
+
// for more extensive tests, see the script interpreter
|
|
318
|
+
var sighex =
|
|
319
|
+
'3042021e17cfe77536c3fb0526bd1a72d7a8e0973f463add210be14063c8a9c37632022061bfa677f825ded82ba0863fb0c46ca1388dd3e647f6a93c038168b59d131a5101';
|
|
320
|
+
var sigbuf = Buffer.from(sighex, 'hex');
|
|
321
|
+
sigbuf[0] = 0x31;
|
|
322
|
+
Signature.isTxDER(sigbuf).should.equal(false);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('bitcoind fixtures', function () {
|
|
326
|
+
var testSigs = function (set, expected) {
|
|
327
|
+
var i = 0;
|
|
328
|
+
set.forEach(function (vector) {
|
|
329
|
+
if (!JSUtil.isHexa(vector)) {
|
|
330
|
+
// non-hex strings are ignored
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
it('should be ' + (expected ? '' : 'in') + 'valid for fixture #' + i, function () {
|
|
334
|
+
var sighex = vector;
|
|
335
|
+
var interp = Interpreter();
|
|
336
|
+
interp.flags = Interpreter.SCRIPT_VERIFY_DERSIG | Interpreter.SCRIPT_VERIFY_STRICTENC;
|
|
337
|
+
var result = interp.checkSignatureEncoding(Buffer.from(sighex, 'hex'));
|
|
338
|
+
result.should.equal(expected);
|
|
339
|
+
});
|
|
340
|
+
i++;
|
|
341
|
+
});
|
|
342
|
+
};
|
|
343
|
+
testSigs(sigCanonical, true);
|
|
344
|
+
testSigs(sigNonCanonical, false);
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
describe('#hasLowS', function () {
|
|
348
|
+
it('should detect high and low S', function () {
|
|
349
|
+
var r = new BN(
|
|
350
|
+
'63173831029936981022572627018246571655303050627048489594159321588908385378810',
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
var sig = new Signature({
|
|
354
|
+
r: r,
|
|
355
|
+
s: new BN('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A1', 'hex'),
|
|
356
|
+
});
|
|
357
|
+
sig.hasLowS().should.equal(false);
|
|
358
|
+
|
|
359
|
+
var sig2 = new Signature({
|
|
360
|
+
r: r,
|
|
361
|
+
s: new BN('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex'),
|
|
362
|
+
});
|
|
363
|
+
sig2.hasLowS().should.equal(true);
|
|
364
|
+
|
|
365
|
+
var sig3 = new Signature({
|
|
366
|
+
r: r,
|
|
367
|
+
s: new BN(1),
|
|
368
|
+
});
|
|
369
|
+
sig3.hasLowS().should.equal(true);
|
|
370
|
+
|
|
371
|
+
var sig4 = new Signature({
|
|
372
|
+
r: r,
|
|
373
|
+
s: new BN(0),
|
|
374
|
+
});
|
|
375
|
+
sig4.hasLowS().should.equal(false);
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
describe('#hasDefinedHashtype', function () {
|
|
380
|
+
it('should reject invalid sighash types and accept valid ones', function () {
|
|
381
|
+
var sig = new Signature();
|
|
382
|
+
sig.hasDefinedHashtype().should.equal(false);
|
|
383
|
+
var testCases = [
|
|
384
|
+
[undefined, false],
|
|
385
|
+
[null, false],
|
|
386
|
+
[0, false],
|
|
387
|
+
[1.1, false],
|
|
388
|
+
[-1, false],
|
|
389
|
+
[-1.1, false],
|
|
390
|
+
['', false],
|
|
391
|
+
['1', false],
|
|
392
|
+
[Signature.SIGHASH_ANYONECANPAY, false],
|
|
393
|
+
[Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_ALL, true],
|
|
394
|
+
[Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_NONE, true],
|
|
395
|
+
[Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_SINGLE, true],
|
|
396
|
+
[Signature.SIGHASH_ALL, true],
|
|
397
|
+
[Signature.SIGHASH_NONE, true],
|
|
398
|
+
[Signature.SIGHASH_SINGLE, true],
|
|
399
|
+
[Signature.SIGHASH_SINGLE + 1, false],
|
|
400
|
+
[(Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_SINGLE) + 1, false],
|
|
401
|
+
[(Signature.SIGHASH_ANYONECANPAY | Signature.SIGHASH_ALL) - 1, false],
|
|
402
|
+
];
|
|
403
|
+
_.each(testCases, function (testCase) {
|
|
404
|
+
sig.nhashtype = testCase[0];
|
|
405
|
+
sig.hasDefinedHashtype().should.equal(testCase[1]);
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
});
|
|
409
|
+
});
|