@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,734 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var should = require('chai').should();
|
|
4
|
+
var opcat = require('../../');
|
|
5
|
+
var Interpreter = opcat.Script.Interpreter;
|
|
6
|
+
var Transaction = opcat.Transaction;
|
|
7
|
+
var PrivateKey = opcat.PrivateKey;
|
|
8
|
+
var Script = opcat.Script;
|
|
9
|
+
var BN = opcat.crypto.BN;
|
|
10
|
+
var BufferWriter = opcat.encoding.BufferWriter;
|
|
11
|
+
var Opcode = opcat.Opcode;
|
|
12
|
+
var _ = require('../../lib/util/_');
|
|
13
|
+
|
|
14
|
+
var scriptTests = require('../data/bitcoind/script_tests');
|
|
15
|
+
var txValid = require('../data/bitcoind/tx_valid');
|
|
16
|
+
var txInvalid = require('../data/bitcoind/tx_invalid');
|
|
17
|
+
|
|
18
|
+
// the script string format used in bitcoind data tests
|
|
19
|
+
Script.fromBitcoindString = function (str) {
|
|
20
|
+
var bw = new BufferWriter();
|
|
21
|
+
var tokens = str.split(' ');
|
|
22
|
+
for (var i = 0; i < tokens.length; i++) {
|
|
23
|
+
var token = tokens[i];
|
|
24
|
+
if (token === '') {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var opstr;
|
|
29
|
+
var opcodenum;
|
|
30
|
+
var tbuf;
|
|
31
|
+
if (token[0] === '0' && token[1] === 'x') {
|
|
32
|
+
var hex = token.slice(2);
|
|
33
|
+
bw.write(Buffer.from(hex, 'hex'));
|
|
34
|
+
} else if (token[0] === "'") {
|
|
35
|
+
var tstr = token.slice(1, token.length - 1);
|
|
36
|
+
var cbuf = Buffer.from(tstr);
|
|
37
|
+
tbuf = Script().add(cbuf).toBuffer();
|
|
38
|
+
bw.write(tbuf);
|
|
39
|
+
} else if (typeof Opcode['OP_' + token] !== 'undefined') {
|
|
40
|
+
opstr = 'OP_' + token;
|
|
41
|
+
opcodenum = Opcode[opstr];
|
|
42
|
+
bw.writeUInt8(opcodenum);
|
|
43
|
+
} else if (typeof Opcode[token] === 'number') {
|
|
44
|
+
opstr = token;
|
|
45
|
+
opcodenum = Opcode[opstr];
|
|
46
|
+
bw.writeUInt8(opcodenum);
|
|
47
|
+
} else if (!isNaN(parseInt(token))) {
|
|
48
|
+
var script = Script().add(new BN(token).toScriptNumBuffer());
|
|
49
|
+
tbuf = script.toBuffer();
|
|
50
|
+
bw.write(tbuf);
|
|
51
|
+
} else {
|
|
52
|
+
throw new Error('Could not determine type of script value');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
var buf = bw.concat();
|
|
56
|
+
return this.fromBuffer(buf);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
describe('Interpreter', function () {
|
|
60
|
+
it('should make a new interp', function () {
|
|
61
|
+
var interp = new Interpreter();
|
|
62
|
+
(interp instanceof Interpreter).should.equal(true);
|
|
63
|
+
interp.stack.length.should.equal(0);
|
|
64
|
+
interp.altstack.length.should.equal(0);
|
|
65
|
+
interp.pc.should.equal(0);
|
|
66
|
+
interp.pbegincodehash.should.equal(0);
|
|
67
|
+
interp.nOpCount.should.equal(0);
|
|
68
|
+
interp.vfExec.length.should.equal(0);
|
|
69
|
+
interp.errstr.should.equal('');
|
|
70
|
+
interp.flags.should.equal(0);
|
|
71
|
+
});
|
|
72
|
+
it('interpreter can set new values for stacks', function () {
|
|
73
|
+
const interp = new Interpreter();
|
|
74
|
+
interp.stack.push(Buffer.from(['stack']));
|
|
75
|
+
interp.stack.length.should.equal(1);
|
|
76
|
+
interp.altstack.push(Buffer.from(['altstack']));
|
|
77
|
+
interp.altstack.length.should.equal(1);
|
|
78
|
+
interp.set({ stack: [], altstack: [] });
|
|
79
|
+
interp.stack.length.should.equal(0);
|
|
80
|
+
interp.altstack.length.should.equal(0);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe('@castToBool', function () {
|
|
84
|
+
it('should cast these bufs to bool correctly', function () {
|
|
85
|
+
Interpreter.castToBool(
|
|
86
|
+
new BN(0).toSM({
|
|
87
|
+
endian: 'little',
|
|
88
|
+
}),
|
|
89
|
+
).should.equal(false);
|
|
90
|
+
Interpreter.castToBool(Buffer.from('0080', 'hex')).should.equal(false); // negative 0
|
|
91
|
+
Interpreter.castToBool(
|
|
92
|
+
new BN(1).toSM({
|
|
93
|
+
endian: 'little',
|
|
94
|
+
}),
|
|
95
|
+
).should.equal(true);
|
|
96
|
+
Interpreter.castToBool(
|
|
97
|
+
new BN(-1).toSM({
|
|
98
|
+
endian: 'little',
|
|
99
|
+
}),
|
|
100
|
+
).should.equal(true);
|
|
101
|
+
|
|
102
|
+
var buf = Buffer.from('00', 'hex');
|
|
103
|
+
var bool =
|
|
104
|
+
BN.fromSM(buf, {
|
|
105
|
+
endian: 'little',
|
|
106
|
+
}).cmp(BN.Zero) !== 0;
|
|
107
|
+
Interpreter.castToBool(buf).should.equal(bool);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('#verify', function () {
|
|
112
|
+
it('should verify these trivial scripts', function () {
|
|
113
|
+
var verified;
|
|
114
|
+
var si = Interpreter();
|
|
115
|
+
verified = si.verify(Script('OP_1'), Script('OP_1'));
|
|
116
|
+
verified.should.equal(true);
|
|
117
|
+
verified = Interpreter().verify(Script('OP_1'), Script('OP_0'));
|
|
118
|
+
verified.should.equal(false);
|
|
119
|
+
verified = Interpreter().verify(Script('OP_0'), Script('OP_1'));
|
|
120
|
+
verified.should.equal(true);
|
|
121
|
+
verified = Interpreter().verify(Script('OP_CODESEPARATOR'), Script('OP_1'));
|
|
122
|
+
verified.should.equal(true);
|
|
123
|
+
verified = Interpreter().verify(Script(''), Script('OP_DEPTH OP_0 OP_EQUAL'));
|
|
124
|
+
verified.should.equal(true);
|
|
125
|
+
verified = Interpreter().verify(
|
|
126
|
+
Script('OP_1 OP_2'),
|
|
127
|
+
Script('OP_2 OP_EQUALVERIFY OP_1 OP_EQUAL'),
|
|
128
|
+
);
|
|
129
|
+
verified.should.equal(true);
|
|
130
|
+
verified = Interpreter().verify(Script('9 0x000000000000000010'), Script(''));
|
|
131
|
+
verified.should.equal(true);
|
|
132
|
+
verified = Interpreter().verify(Script('OP_1'), Script('OP_15 OP_ADD OP_16 OP_EQUAL'));
|
|
133
|
+
verified.should.equal(true);
|
|
134
|
+
verified = Interpreter().verify(Script('OP_0'), Script('OP_IF OP_VER OP_ELSE OP_1 OP_ENDIF'));
|
|
135
|
+
verified.should.equal(true);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should verify these simple transaction', function () {
|
|
139
|
+
// first we create a transaction
|
|
140
|
+
var privateKey = new PrivateKey('cSBnVM4xvxarwGQuAfQFwqDg9k5tErHUHzgWsEfD4zdwUasvqRVY');
|
|
141
|
+
var publicKey = privateKey.publicKey;
|
|
142
|
+
var fromAddress = publicKey.toAddress();
|
|
143
|
+
var toAddress = 'mrU9pEmAx26HcbKVrABvgL7AwA5fjNFoDc';
|
|
144
|
+
var scriptPubkey = Script.buildPublicKeyHashOut(fromAddress);
|
|
145
|
+
var utxo = {
|
|
146
|
+
address: fromAddress,
|
|
147
|
+
txId: 'a477af6b2667c29670467e4e0728b685ee07b240235771862318e29ddbe58458',
|
|
148
|
+
outputIndex: 0,
|
|
149
|
+
script: scriptPubkey,
|
|
150
|
+
satoshis: 100000,
|
|
151
|
+
};
|
|
152
|
+
var tx = new Transaction().from(utxo).to(toAddress, 100000).sign(privateKey, 1);
|
|
153
|
+
|
|
154
|
+
// we then extract the signature from the first input
|
|
155
|
+
var inputIndex = 0;
|
|
156
|
+
var signature = tx.getSignatures(privateKey, 1)[inputIndex].signature;
|
|
157
|
+
|
|
158
|
+
var scriptSig = Script.buildPublicKeyHashIn(publicKey, signature);
|
|
159
|
+
var flags = Interpreter.SCRIPT_VERIFY_STRICTENC;
|
|
160
|
+
var verified = Interpreter().verify(scriptSig, scriptPubkey, tx, inputIndex, flags);
|
|
161
|
+
verified.should.equal(true);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('#script debugger', function () {
|
|
166
|
+
it('debugger should fire while executing script', function () {
|
|
167
|
+
var si = Interpreter();
|
|
168
|
+
let debugCount = 0;
|
|
169
|
+
si.stepListener = function (step) {
|
|
170
|
+
debugCount += 1;
|
|
171
|
+
};
|
|
172
|
+
si.verify(Script('OP_1 OP_2 OP_ADD'), Script('OP_3 OP_EQUAL'));
|
|
173
|
+
si.errstr.should.equal('');
|
|
174
|
+
// two scripts. first one has 3 instructions. second one has 2 instructions
|
|
175
|
+
debugCount.should.equal(3 + 2);
|
|
176
|
+
});
|
|
177
|
+
it('debugger error in callback should not kill executing script', function () {
|
|
178
|
+
var si = Interpreter();
|
|
179
|
+
si.stepListener = function (step) {
|
|
180
|
+
throw new Error('This error is expected.');
|
|
181
|
+
};
|
|
182
|
+
si.verify(Script('OP_1 OP_2 OP_ADD'), Script(''));
|
|
183
|
+
const result = [...si.stack.pop()];
|
|
184
|
+
result.should.to.deep.equal([3]);
|
|
185
|
+
si.errstr.should.equal('');
|
|
186
|
+
si.stack.length.should.equal(0);
|
|
187
|
+
});
|
|
188
|
+
it('script debugger should fire and not cause an error', function () {
|
|
189
|
+
var si = Interpreter();
|
|
190
|
+
si.stepListener = debugScript;
|
|
191
|
+
si.verify(Script('OP_1 OP_2 OP_ADD'), Script('OP_3 OP_EQUAL'));
|
|
192
|
+
si.errstr.should.equal('');
|
|
193
|
+
});
|
|
194
|
+
it('script debugger should make copies of stack: no more make copies bcoz memory used', function () {
|
|
195
|
+
/*
|
|
196
|
+
var si = Interpreter()
|
|
197
|
+
let stk, stkval, altstk, altstkval
|
|
198
|
+
si.stepListener = function (step, stack, altstack) {
|
|
199
|
+
// stack is an array of buffers, interpreter must give us copies of stack so we can't mess it up
|
|
200
|
+
console.log(step)
|
|
201
|
+
console.log(stack)
|
|
202
|
+
console.log(altstack)
|
|
203
|
+
// these values will get overwritten each step but we only care about that final values
|
|
204
|
+
stk = (stack === si.stack)
|
|
205
|
+
stkval = (stack[0] === si.stack.stacktop(-si.stack.length))
|
|
206
|
+
altstk = (altstack === si.altstack)
|
|
207
|
+
altstkval = (altstack[0] === si.altstack.stacktop(-si.altstack.length))
|
|
208
|
+
}
|
|
209
|
+
// alt stack is not copied to second script execution so just do everything in second script
|
|
210
|
+
si.verify(Script(''), Script('OP_2 OP_TOALTSTACK OP_1'))
|
|
211
|
+
console.log(si.stack)
|
|
212
|
+
console.log(si.altstack)
|
|
213
|
+
si.errstr.should.equal('')
|
|
214
|
+
si.stack.length.should.equal(1)
|
|
215
|
+
si.altstack.length.should.equal(1)
|
|
216
|
+
stk.should.equal(false)
|
|
217
|
+
stkval.should.equal(false)
|
|
218
|
+
altstk.should.equal(false)
|
|
219
|
+
altstkval.should.equal(false)
|
|
220
|
+
*/
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
var getFlags = function getFlags(flagstr) {
|
|
225
|
+
var flags = 0;
|
|
226
|
+
if (flagstr.indexOf('NONE') !== -1) {
|
|
227
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_NONE;
|
|
228
|
+
}
|
|
229
|
+
if (flagstr.indexOf('STRICTENC') !== -1) {
|
|
230
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_STRICTENC;
|
|
231
|
+
}
|
|
232
|
+
if (flagstr.indexOf('DERSIG') !== -1) {
|
|
233
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_DERSIG;
|
|
234
|
+
}
|
|
235
|
+
if (flagstr.indexOf('LOW_S') !== -1) {
|
|
236
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_LOW_S;
|
|
237
|
+
}
|
|
238
|
+
if (flagstr.indexOf('NULLDUMMY') !== -1) {
|
|
239
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_NULLDUMMY;
|
|
240
|
+
}
|
|
241
|
+
if (flagstr.indexOf('SIGPUSHONLY') !== -1) {
|
|
242
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_SIGPUSHONLY;
|
|
243
|
+
}
|
|
244
|
+
if (flagstr.indexOf('MINIMALDATA') !== -1) {
|
|
245
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_MINIMALDATA;
|
|
246
|
+
}
|
|
247
|
+
if (flagstr.indexOf('DISCOURAGE_UPGRADABLE_NOPS') !== -1) {
|
|
248
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS;
|
|
249
|
+
}
|
|
250
|
+
if (flagstr.indexOf('CHECKLOCKTIMEVERIFY') !== -1) {
|
|
251
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
|
|
252
|
+
}
|
|
253
|
+
if (flagstr.indexOf('CHECKSEQUENCEVERIFY') !== -1) {
|
|
254
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
|
|
255
|
+
}
|
|
256
|
+
if (flagstr.indexOf('NULLFAIL') !== -1) {
|
|
257
|
+
flags = flags | Interpreter.SCRIPT_VERIFY_NULLFAIL;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (flagstr.indexOf('MONOLITH') !== -1) {
|
|
261
|
+
flags = flags | Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (flagstr.indexOf('MAGNETIC') !== -1) {
|
|
265
|
+
flags = flags | Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return flags;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
var testFixture = function (vector, expected, extraData) {
|
|
272
|
+
var scriptSig = Script.fromBitcoindString(vector[0]);
|
|
273
|
+
var scriptPubkey = Script.fromBitcoindString(vector[1]);
|
|
274
|
+
var flags = getFlags(vector[2]);
|
|
275
|
+
var inputAmount = 0;
|
|
276
|
+
if (extraData) {
|
|
277
|
+
inputAmount = extraData[0] * 1e8;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
var hashbuf = Buffer.alloc(32);
|
|
281
|
+
hashbuf.fill(0);
|
|
282
|
+
var credtx = new Transaction();
|
|
283
|
+
credtx.uncheckedAddInput(
|
|
284
|
+
new Transaction.Input({
|
|
285
|
+
prevTxId: '0000000000000000000000000000000000000000000000000000000000000000',
|
|
286
|
+
outputIndex: 0xffffffff,
|
|
287
|
+
sequenceNumber: 0xffffffff,
|
|
288
|
+
script: Script('OP_0 OP_0'),
|
|
289
|
+
}),
|
|
290
|
+
);
|
|
291
|
+
credtx.addOutput(
|
|
292
|
+
new Transaction.Output({
|
|
293
|
+
script: scriptPubkey,
|
|
294
|
+
satoshis: inputAmount,
|
|
295
|
+
}),
|
|
296
|
+
);
|
|
297
|
+
var idbuf = credtx.id;
|
|
298
|
+
|
|
299
|
+
var spendtx = new Transaction();
|
|
300
|
+
spendtx.uncheckedAddInput(
|
|
301
|
+
new Transaction.Input({
|
|
302
|
+
prevTxId: idbuf.toString('hex'),
|
|
303
|
+
outputIndex: 0,
|
|
304
|
+
sequenceNumber: 0xffffffff,
|
|
305
|
+
script: scriptSig,
|
|
306
|
+
output: credtx.outputs[0],
|
|
307
|
+
}),
|
|
308
|
+
);
|
|
309
|
+
spendtx.addOutput(
|
|
310
|
+
new Transaction.Output({
|
|
311
|
+
script: new Script(),
|
|
312
|
+
satoshis: inputAmount,
|
|
313
|
+
}),
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
//spendtx.sign(opcat.PrivateKey.fromWIF(""))
|
|
318
|
+
Interpreter.MAX_OPCODE_COUNT = 201;
|
|
319
|
+
Interpreter.MAX_SCRIPT_SIZE = 10000;
|
|
320
|
+
var interp = new Interpreter();
|
|
321
|
+
var verified = interp.verify(scriptSig, scriptPubkey, spendtx, 0, flags, new BN(inputAmount));
|
|
322
|
+
verified.should.equal(expected, interp.errstr);
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const CheckMul = function (a, b, expected) {
|
|
326
|
+
// Negative values for multiplication
|
|
327
|
+
CheckBinaryOpMagnetic(a, b, Opcode.OP_MUL, expected);
|
|
328
|
+
CheckBinaryOpMagnetic(a, NegativeValtype(b), Opcode.OP_MUL, NegativeValtype(expected));
|
|
329
|
+
CheckBinaryOpMagnetic(NegativeValtype(a), b, Opcode.OP_MUL, NegativeValtype(expected));
|
|
330
|
+
CheckBinaryOpMagnetic(NegativeValtype(a), NegativeValtype(b), Opcode.OP_MUL, expected);
|
|
331
|
+
|
|
332
|
+
// Commutativity
|
|
333
|
+
CheckBinaryOpMagnetic(b, a, Opcode.OP_MUL, expected);
|
|
334
|
+
CheckBinaryOpMagnetic(b, NegativeValtype(a), Opcode.OP_MUL, NegativeValtype(expected));
|
|
335
|
+
CheckBinaryOpMagnetic(NegativeValtype(b), a, Opcode.OP_MUL, NegativeValtype(expected));
|
|
336
|
+
CheckBinaryOpMagnetic(NegativeValtype(b), NegativeValtype(a), Opcode.OP_MUL, expected);
|
|
337
|
+
|
|
338
|
+
// Multiplication identities
|
|
339
|
+
CheckBinaryOpMagnetic(a, [0x01], Opcode.OP_MUL, a);
|
|
340
|
+
CheckBinaryOpMagnetic(a, [0x81], Opcode.OP_MUL, NegativeValtype(a));
|
|
341
|
+
CheckBinaryOpMagnetic(a, [], Opcode.OP_MUL, []);
|
|
342
|
+
|
|
343
|
+
CheckBinaryOpMagnetic([0x01], b, Opcode.OP_MUL, b);
|
|
344
|
+
CheckBinaryOpMagnetic([0x81], b, Opcode.OP_MUL, NegativeValtype(b));
|
|
345
|
+
CheckBinaryOpMagnetic([], b, Opcode.OP_MUL, []);
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
const CheckBinaryOpMagnetic = function (a, b, op, expected) {
|
|
349
|
+
const interp = evaluateScript(a, b, op);
|
|
350
|
+
const result = [...interp.stack.pop()];
|
|
351
|
+
result.should.to.deep.equal(expected);
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
const NegativeValtype = function (v) {
|
|
355
|
+
let copy = v.slice();
|
|
356
|
+
if (copy.length) {
|
|
357
|
+
copy[copy.length - 1] ^= 0x80;
|
|
358
|
+
}
|
|
359
|
+
// TODO: expose minimally encode as public method?
|
|
360
|
+
return Interpreter._minimallyEncode(copy);
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
const evaluateScript = function (arraySig, arrayPubKey, op, funcDebug) {
|
|
364
|
+
const interp = new Interpreter();
|
|
365
|
+
interp.stepListener = funcDebug;
|
|
366
|
+
interp.script = new Script().add(Buffer.from(arraySig)).add(Buffer.from(arrayPubKey));
|
|
367
|
+
interp.script.add(op);
|
|
368
|
+
interp.flags =
|
|
369
|
+
Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES |
|
|
370
|
+
Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES;
|
|
371
|
+
interp.evaluate();
|
|
372
|
+
return interp;
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
const debugScript = function (step, stack, altstack) {
|
|
376
|
+
const script = new Script().add(step.opcode);
|
|
377
|
+
// stack is array of buffers
|
|
378
|
+
let stackTop = '>';
|
|
379
|
+
for (let item in stack.reverse()) {
|
|
380
|
+
console.log(`Step ${step.pc}: ${script}:${stackTop}${stack[item].toString('hex')}`);
|
|
381
|
+
stackTop = ' ';
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
const toBitpattern = function (binaryString) {
|
|
386
|
+
return parseInt(binaryString, 2).toString(16).padStart(8, '0');
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
describe('#Empty and null script', function () {
|
|
390
|
+
it('Empty buffer should have value 0x00 in script', function () {
|
|
391
|
+
const s = new Script().add(Buffer.from([]));
|
|
392
|
+
// script does not render anything so it appears invisible
|
|
393
|
+
s.toString().should.equal('OP_0');
|
|
394
|
+
// yet there is a script chunk there
|
|
395
|
+
s.chunks.length.should.equal(1);
|
|
396
|
+
s.chunks[0].opcodenum.should.equal(0);
|
|
397
|
+
});
|
|
398
|
+
it('Zero value (0x00) buffer should have value 0x01 0x00 in script', function () {
|
|
399
|
+
const s = new Script().add(Buffer.from([0x00]));
|
|
400
|
+
s.toString().should.equal('1 0x00');
|
|
401
|
+
s.chunks.length.should.equal(1);
|
|
402
|
+
s.chunks[0].opcodenum.should.equal(1);
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
describe('#NegativeValType', function () {
|
|
407
|
+
it('should pass all tests', function () {
|
|
408
|
+
// Test zero values
|
|
409
|
+
new Script()
|
|
410
|
+
.add(Buffer.from(NegativeValtype([])))
|
|
411
|
+
.should.to.deep.equal(new Script().add(Buffer.from([])));
|
|
412
|
+
new Script()
|
|
413
|
+
.add(Buffer.from(NegativeValtype([0x00])))
|
|
414
|
+
.should.to.deep.equal(new Script().add(Buffer.from([])));
|
|
415
|
+
new Script()
|
|
416
|
+
.add(Buffer.from(NegativeValtype([0x80])))
|
|
417
|
+
.should.to.deep.equal(new Script().add(Buffer.from([])));
|
|
418
|
+
new Script()
|
|
419
|
+
.add(Buffer.from(NegativeValtype([0x00, 0x00])))
|
|
420
|
+
.should.to.deep.equal(new Script().add(Buffer.from([])));
|
|
421
|
+
new Script()
|
|
422
|
+
.add(Buffer.from(NegativeValtype([0x00, 0x80])))
|
|
423
|
+
.should.to.deep.equal(new Script().add(Buffer.from([])));
|
|
424
|
+
|
|
425
|
+
// Non-zero values
|
|
426
|
+
NegativeValtype([0x01]).should.to.deep.equal([0x81]);
|
|
427
|
+
NegativeValtype([0x81]).should.to.deep.equal([0x01]);
|
|
428
|
+
NegativeValtype([0x02, 0x01]).should.to.deep.equal([0x02, 0x81]);
|
|
429
|
+
NegativeValtype([0x02, 0x81]).should.to.deep.equal([0x02, 0x01]);
|
|
430
|
+
NegativeValtype([0xff, 0x02, 0x01]).should.to.deep.equal([0xff, 0x02, 0x81]);
|
|
431
|
+
NegativeValtype([0xff, 0x02, 0x81]).should.to.deep.equal([0xff, 0x02, 0x01]);
|
|
432
|
+
NegativeValtype([0xff, 0xff, 0x02, 0x01]).should.to.deep.equal([0xff, 0xff, 0x02, 0x81]);
|
|
433
|
+
NegativeValtype([0xff, 0xff, 0x02, 0x81]).should.to.deep.equal([0xff, 0xff, 0x02, 0x01]);
|
|
434
|
+
|
|
435
|
+
// Should not be overly-minimized
|
|
436
|
+
NegativeValtype([0xff, 0x80]).should.to.deep.equal([0xff, 0x00]);
|
|
437
|
+
NegativeValtype([0xff, 0x00]).should.to.deep.equal([0xff, 0x80]);
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
describe('#OP_LSHIFT tests from bitcoind', function () {
|
|
442
|
+
it('should not shift when no n value', function () {
|
|
443
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [], Opcode.OP_LSHIFT);
|
|
444
|
+
console.log(interp.script);
|
|
445
|
+
const result = interp.stack.pop();
|
|
446
|
+
result.toString('hex').should.equal(toBitpattern('10011111000100011111010101010101'));
|
|
447
|
+
});
|
|
448
|
+
it('should shift left 1', function () {
|
|
449
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x01], Opcode.OP_LSHIFT);
|
|
450
|
+
const result = interp.stack.pop();
|
|
451
|
+
result.toString('hex').should.equal(toBitpattern('00111110001000111110101010101010'));
|
|
452
|
+
});
|
|
453
|
+
it('should shift left 2', function () {
|
|
454
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x02], Opcode.OP_LSHIFT);
|
|
455
|
+
const result = interp.stack.pop();
|
|
456
|
+
result.toString('hex').should.equal(toBitpattern('01111100010001111101010101010100'));
|
|
457
|
+
});
|
|
458
|
+
it('should shift left 3', function () {
|
|
459
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x03], Opcode.OP_LSHIFT);
|
|
460
|
+
const result = interp.stack.pop();
|
|
461
|
+
result.toString('hex').should.equal(toBitpattern('11111000100011111010101010101000'));
|
|
462
|
+
});
|
|
463
|
+
it('should shift left 4', function () {
|
|
464
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x04], Opcode.OP_LSHIFT);
|
|
465
|
+
const result = interp.stack.pop();
|
|
466
|
+
result.toString('hex').should.equal(toBitpattern('11110001000111110101010101010000'));
|
|
467
|
+
});
|
|
468
|
+
it('should shift left 5', function () {
|
|
469
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x05], Opcode.OP_LSHIFT);
|
|
470
|
+
const result = interp.stack.pop();
|
|
471
|
+
result.toString('hex').should.equal(toBitpattern('11100010001111101010101010100000'));
|
|
472
|
+
});
|
|
473
|
+
it('should shift left 6', function () {
|
|
474
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x06], Opcode.OP_LSHIFT);
|
|
475
|
+
const result = interp.stack.pop();
|
|
476
|
+
result.toString('hex').should.equal(toBitpattern('11000100011111010101010101000000'));
|
|
477
|
+
});
|
|
478
|
+
it('should shift left 7', function () {
|
|
479
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x07], Opcode.OP_LSHIFT);
|
|
480
|
+
const result = interp.stack.pop();
|
|
481
|
+
result.toString('hex').should.equal(toBitpattern('10001000111110101010101010000000'));
|
|
482
|
+
});
|
|
483
|
+
it('should shift left 08', function () {
|
|
484
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x08], Opcode.OP_LSHIFT);
|
|
485
|
+
const result = interp.stack.pop();
|
|
486
|
+
result.toString('hex').should.equal(toBitpattern('00010001111101010101010100000000'));
|
|
487
|
+
});
|
|
488
|
+
it('should shift left 9', function () {
|
|
489
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x09], Opcode.OP_LSHIFT);
|
|
490
|
+
const result = interp.stack.pop();
|
|
491
|
+
result.toString('hex').should.equal(toBitpattern('00100011111010101010101000000000'));
|
|
492
|
+
});
|
|
493
|
+
it('should shift left 0A', function () {
|
|
494
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0a], Opcode.OP_LSHIFT);
|
|
495
|
+
const result = interp.stack.pop();
|
|
496
|
+
result.toString('hex').should.equal(toBitpattern('01000111110101010101010000000000'));
|
|
497
|
+
});
|
|
498
|
+
it('should shift left 0B', function () {
|
|
499
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0b], Opcode.OP_LSHIFT);
|
|
500
|
+
const result = interp.stack.pop();
|
|
501
|
+
result.toString('hex').should.equal(toBitpattern('10001111101010101010100000000000'));
|
|
502
|
+
});
|
|
503
|
+
it('should shift left 0C', function () {
|
|
504
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0c], Opcode.OP_LSHIFT);
|
|
505
|
+
const result = interp.stack.pop();
|
|
506
|
+
result.toString('hex').should.equal(toBitpattern('00011111010101010101000000000000'));
|
|
507
|
+
});
|
|
508
|
+
it('should shift left 0D', function () {
|
|
509
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0d], Opcode.OP_LSHIFT);
|
|
510
|
+
const result = interp.stack.pop();
|
|
511
|
+
result.toString('hex').should.equal(toBitpattern('00111110101010101010000000000000'));
|
|
512
|
+
});
|
|
513
|
+
it('should shift left 0E', function () {
|
|
514
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0e], Opcode.OP_LSHIFT);
|
|
515
|
+
const result = interp.stack.pop();
|
|
516
|
+
result.toString('hex').should.equal(toBitpattern('01111101010101010100000000000000'));
|
|
517
|
+
});
|
|
518
|
+
it('should shift left 0F', function () {
|
|
519
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0f], Opcode.OP_LSHIFT);
|
|
520
|
+
const result = interp.stack.pop();
|
|
521
|
+
result.toString('hex').should.equal(toBitpattern('11111010101010101000000000000000'));
|
|
522
|
+
});
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
describe('#OP_RSHIFT tests from bitcoind', function () {
|
|
526
|
+
it('should not shift when no n value', function () {
|
|
527
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [], Opcode.OP_RSHIFT);
|
|
528
|
+
const result = interp.stack.pop();
|
|
529
|
+
result.toString('hex').should.equal(toBitpattern('10011111000100011111010101010101'));
|
|
530
|
+
});
|
|
531
|
+
it('should shift right 1', function () {
|
|
532
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x01], Opcode.OP_RSHIFT);
|
|
533
|
+
const result = interp.stack.pop();
|
|
534
|
+
result.toString('hex').should.equal(toBitpattern('01001111100010001111101010101010'));
|
|
535
|
+
});
|
|
536
|
+
it('should shift right 2', function () {
|
|
537
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x02], Opcode.OP_RSHIFT);
|
|
538
|
+
const result = interp.stack.pop();
|
|
539
|
+
result.toString('hex').should.equal(toBitpattern('00100111110001000111110101010101'));
|
|
540
|
+
});
|
|
541
|
+
it('should shift right 3', function () {
|
|
542
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x03], Opcode.OP_RSHIFT);
|
|
543
|
+
const result = interp.stack.pop();
|
|
544
|
+
result.toString('hex').should.equal(toBitpattern('00010011111000100011111010101010'));
|
|
545
|
+
});
|
|
546
|
+
it('should shift right 4', function () {
|
|
547
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x04], Opcode.OP_RSHIFT);
|
|
548
|
+
const result = interp.stack.pop();
|
|
549
|
+
result.toString('hex').should.equal(toBitpattern('00001001111100010001111101010101'));
|
|
550
|
+
});
|
|
551
|
+
it('should shift right 5', function () {
|
|
552
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x05], Opcode.OP_RSHIFT);
|
|
553
|
+
const result = interp.stack.pop();
|
|
554
|
+
result.toString('hex').should.equal(toBitpattern('00000100111110001000111110101010'));
|
|
555
|
+
});
|
|
556
|
+
it('should shift right 6', function () {
|
|
557
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x06], Opcode.OP_RSHIFT);
|
|
558
|
+
const result = interp.stack.pop();
|
|
559
|
+
result.toString('hex').should.equal(toBitpattern('00000010011111000100011111010101'));
|
|
560
|
+
});
|
|
561
|
+
it('should shift right 7', function () {
|
|
562
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x07], Opcode.OP_RSHIFT);
|
|
563
|
+
const result = interp.stack.pop();
|
|
564
|
+
result.toString('hex').should.equal(toBitpattern('00000001001111100010001111101010'));
|
|
565
|
+
});
|
|
566
|
+
it('should shift right 08', function () {
|
|
567
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x08], Opcode.OP_RSHIFT);
|
|
568
|
+
const result = interp.stack.pop();
|
|
569
|
+
result.toString('hex').should.equal(toBitpattern('00000000100111110001000111110101'));
|
|
570
|
+
});
|
|
571
|
+
it('should shift right 9', function () {
|
|
572
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x09], Opcode.OP_RSHIFT);
|
|
573
|
+
const result = interp.stack.pop();
|
|
574
|
+
result.toString('hex').should.equal(toBitpattern('00000000010011111000100011111010'));
|
|
575
|
+
});
|
|
576
|
+
it('should shift right 0A', function () {
|
|
577
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0a], Opcode.OP_RSHIFT);
|
|
578
|
+
const result = interp.stack.pop();
|
|
579
|
+
result.toString('hex').should.equal(toBitpattern('00000000001001111100010001111101'));
|
|
580
|
+
});
|
|
581
|
+
it('should shift right 0B', function () {
|
|
582
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0b], Opcode.OP_RSHIFT);
|
|
583
|
+
const result = interp.stack.pop();
|
|
584
|
+
result.toString('hex').should.equal(toBitpattern('00000000000100111110001000111110'));
|
|
585
|
+
});
|
|
586
|
+
it('should shift right 0C', function () {
|
|
587
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0c], Opcode.OP_RSHIFT);
|
|
588
|
+
const result = interp.stack.pop();
|
|
589
|
+
result.toString('hex').should.equal(toBitpattern('00000000000010011111000100011111'));
|
|
590
|
+
});
|
|
591
|
+
it('should shift right 0D', function () {
|
|
592
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0d], Opcode.OP_RSHIFT);
|
|
593
|
+
const result = interp.stack.pop();
|
|
594
|
+
result.toString('hex').should.equal(toBitpattern('00000000000001001111100010001111'));
|
|
595
|
+
});
|
|
596
|
+
it('should shift right 0E', function () {
|
|
597
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0e], Opcode.OP_RSHIFT);
|
|
598
|
+
const result = interp.stack.pop();
|
|
599
|
+
result.toString('hex').should.equal(toBitpattern('00000000000000100111110001000111'));
|
|
600
|
+
});
|
|
601
|
+
it('should shift right 0F', function () {
|
|
602
|
+
const interp = evaluateScript([0x9f, 0x11, 0xf5, 0x55], [0x0f], Opcode.OP_RSHIFT);
|
|
603
|
+
const result = interp.stack.pop();
|
|
604
|
+
result.toString('hex').should.equal(toBitpattern('00000000000000010011111000100011'));
|
|
605
|
+
});
|
|
606
|
+
});
|
|
607
|
+
describe('#OP_MUL tests from bitcoind', function () {
|
|
608
|
+
it('OP_MUL tests', function () {
|
|
609
|
+
CheckMul([0x05], [0x06], [0x1e]);
|
|
610
|
+
CheckMul([0x05], [0x26], [0xbe, 0x00]);
|
|
611
|
+
CheckMul([0x45], [0x26], [0x3e, 0x0a]);
|
|
612
|
+
CheckMul([0x02], [0x56, 0x24], [0xac, 0x48]);
|
|
613
|
+
CheckMul([0x05], [0x26, 0x03, 0x32], [0xbe, 0x0f, 0xfa, 0x00]);
|
|
614
|
+
CheckMul([0x06], [0x26, 0x03, 0x32, 0x04], [0xe4, 0x12, 0x2c, 0x19]);
|
|
615
|
+
CheckMul([0xa0, 0xa0], [0xf5, 0xe4], [0x20, 0xb9, 0xdd, 0x0c]); // -20A0*-64F5=0CDDB920
|
|
616
|
+
CheckMul([0x05, 0x26], [0x26, 0x03, 0x32], [0xbe, 0xb3, 0x71, 0x6d, 0x07]);
|
|
617
|
+
CheckMul([0x06, 0x26], [0x26, 0x03, 0x32, 0x04], [0xe4, 0xb6, 0xa3, 0x85, 0x9f, 0x00]);
|
|
618
|
+
CheckMul([0x05, 0x26, 0x09], [0x26, 0x03, 0x32], [0xbe, 0xb3, 0xc7, 0x89, 0xc9, 0x01]);
|
|
619
|
+
CheckMul([0x06, 0x26, 0x09], [0x26, 0x03, 0x32, 0x04], [0xe4, 0xb6, 0xf9, 0xa1, 0x61, 0x26]);
|
|
620
|
+
CheckMul(
|
|
621
|
+
[0x06, 0x26, 0x09, 0x34],
|
|
622
|
+
[0x26, 0x03, 0x32, 0x04],
|
|
623
|
+
[0xe4, 0xb6, 0xf9, 0x59, 0x05, 0x4f, 0xda, 0x00],
|
|
624
|
+
);
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
describe('bitcoind script evaluation fixtures', function () {
|
|
629
|
+
var testAllFixtures = function (set) {
|
|
630
|
+
var c = 0;
|
|
631
|
+
var l = set.length;
|
|
632
|
+
set.forEach(function (vector) {
|
|
633
|
+
if (vector.length === 1) {
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
var extraData;
|
|
638
|
+
if (_.isArray(vector[0])) {
|
|
639
|
+
extraData = vector.shift();
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
c++;
|
|
643
|
+
|
|
644
|
+
var fullScriptString = `${vector[0]} ${vector[1]}`;
|
|
645
|
+
var expected = vector[3] === 'OK';
|
|
646
|
+
var descstr = vector[4];
|
|
647
|
+
var comment = descstr ? ` (${descstr})` : '';
|
|
648
|
+
var txt = `should ${vector[3]} script_tests vector #${c}/${l}: ${fullScriptString}${comment}`;
|
|
649
|
+
|
|
650
|
+
it(txt, function () {
|
|
651
|
+
testFixture(vector, expected, extraData);
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
};
|
|
655
|
+
testAllFixtures(scriptTests);
|
|
656
|
+
});
|
|
657
|
+
describe('bitcoind transaction evaluation fixtures', function () {
|
|
658
|
+
var testTxs = function (set, expected) {
|
|
659
|
+
var c = 0;
|
|
660
|
+
set.forEach(function (vector) {
|
|
661
|
+
if (vector.length === 1) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
c++;
|
|
665
|
+
var cc = c; // copy to local
|
|
666
|
+
it('should pass tx_' + (expected ? '' : 'in') + 'valid vector ' + cc, function () {
|
|
667
|
+
var inputs = vector[0];
|
|
668
|
+
var txhex = vector[1];
|
|
669
|
+
|
|
670
|
+
var flags = getFlags(vector[2]);
|
|
671
|
+
|
|
672
|
+
if (vector[2].indexOf('P2SH') !== -1) {
|
|
673
|
+
return; // skip P2SH tests
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
var map = {};
|
|
677
|
+
var satoshisMap = {};
|
|
678
|
+
var dataMap = {};
|
|
679
|
+
inputs.forEach(function (input) {
|
|
680
|
+
var txid = input[0];
|
|
681
|
+
var txoutnum = input[1];
|
|
682
|
+
var scriptPubKeyStr = input[2];
|
|
683
|
+
var satoshis = input[3];
|
|
684
|
+
var dataStr = input[4];
|
|
685
|
+
if (txoutnum === -1) {
|
|
686
|
+
txoutnum = 0xffffffff; // bitcoind casts -1 to an unsigned int
|
|
687
|
+
}
|
|
688
|
+
map[txid + ':' + txoutnum] = Script.fromBitcoindString(scriptPubKeyStr);
|
|
689
|
+
satoshisMap[txid + ':' + txoutnum] = satoshis
|
|
690
|
+
dataMap[txid + ':' + txoutnum] = dataStr ? Buffer.from(dataStr, 'hex') : Buffer.from([])
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
var tx = new Transaction(txhex);
|
|
694
|
+
var allInputsVerified = true;
|
|
695
|
+
tx.inputs.forEach(function (txin, j) {
|
|
696
|
+
if (txin.isNull()) {
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
var scriptSig = txin.script;
|
|
701
|
+
var txidhex = txin.prevTxId.toString('hex');
|
|
702
|
+
var txoutnum = txin.outputIndex;
|
|
703
|
+
var scriptPubkey = map[txidhex + ':' + txoutnum];
|
|
704
|
+
var data = dataMap[txidhex + ':' + txoutnum];
|
|
705
|
+
var satoshis = satoshisMap[txidhex + ':' + txoutnum]
|
|
706
|
+
should.exist(scriptPubkey);
|
|
707
|
+
should.exist(data);
|
|
708
|
+
should.exist(satoshis);
|
|
709
|
+
(scriptSig !== undefined).should.equal(true);
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
txin.output = new Transaction.Output({
|
|
713
|
+
satoshis,
|
|
714
|
+
script: scriptPubkey,
|
|
715
|
+
data,
|
|
716
|
+
})
|
|
717
|
+
|
|
718
|
+
var interp = new Interpreter();
|
|
719
|
+
var verified = interp.verify(scriptSig, scriptPubkey, tx, j, flags);
|
|
720
|
+
if (!verified) {
|
|
721
|
+
allInputsVerified = false;
|
|
722
|
+
}
|
|
723
|
+
});
|
|
724
|
+
var txVerified = tx.verify(true);
|
|
725
|
+
txVerified = txVerified === true;
|
|
726
|
+
allInputsVerified = allInputsVerified && txVerified;
|
|
727
|
+
allInputsVerified.should.equal(expected);
|
|
728
|
+
});
|
|
729
|
+
});
|
|
730
|
+
};
|
|
731
|
+
testTxs(txValid, true);
|
|
732
|
+
//testTxs(txInvalid, false);
|
|
733
|
+
});
|
|
734
|
+
});
|