@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,109 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var Stack = function Stack(rawstack, varStack) {
|
|
4
|
+
this.stack = rawstack;
|
|
5
|
+
this.varStack = varStack || [];
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
module.exports = Stack;
|
|
9
|
+
|
|
10
|
+
Stack.prototype.pushVar = function (varName) {
|
|
11
|
+
this.varStack.push(varName || '$tmp');
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
Stack.prototype.popVar = function () {
|
|
15
|
+
this.varStack.pop();
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
Stack.prototype.push = function (n, varName) {
|
|
19
|
+
this.pushVar(varName);
|
|
20
|
+
this.stack.push(n);
|
|
21
|
+
this.checkConsistency();
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
Stack.prototype.pop = function () {
|
|
25
|
+
this.popVar();
|
|
26
|
+
let top = this.stack.pop();
|
|
27
|
+
this.checkConsistency();
|
|
28
|
+
return top;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
Stack.prototype.updateTopVars = function (vars) {
|
|
32
|
+
if (vars.length > this.varStack.length) {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`updateTopVars fail, stack: ${this.stack.length}, varStack: ${this.varStack.length}, vars:${vars.length}`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
vars = vars.reverse();
|
|
38
|
+
this.varStack.splice(this.varStack.length - vars.length, vars.length, ...vars);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
Stack.prototype.stacktop = function (i) {
|
|
42
|
+
return this.stack[this.stack.length + i];
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
Stack.prototype.vartop = function (i) {
|
|
46
|
+
return this.varStack[this.varStack.length + i];
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
Stack.prototype.slice = function (start, end) {
|
|
50
|
+
return this.stack.slice(start, end);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
Stack.prototype.splice = function (start, deleteCount, ...items) {
|
|
54
|
+
this.varStack.splice(start, deleteCount, ...items);
|
|
55
|
+
return this.stack.splice(start, deleteCount, ...items);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
Stack.prototype.write = function (i, value) {
|
|
59
|
+
this.stack[this.stack.length + i] = value;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
Stack.prototype.copy = function () {
|
|
63
|
+
return new Stack(this.stack.slice() || [], this.varStack.slice() || []);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
function bytesToHexString(bytearray) {
|
|
67
|
+
return bytearray.reduce(function (o, c) {
|
|
68
|
+
o += ('0' + (c & 0xff).toString(16)).slice(-2);
|
|
69
|
+
return o;
|
|
70
|
+
}, '');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
Stack.prototype.printVarStack = function () {
|
|
74
|
+
let array = this.varStack.map((v, i) => ({
|
|
75
|
+
name: v,
|
|
76
|
+
value: bytesToHexString(this.rawstack[i].data),
|
|
77
|
+
}));
|
|
78
|
+
console.log(JSON.stringify(array, null, 4));
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
Stack.prototype.checkConsistency = function () {
|
|
82
|
+
if (this.stack.length !== this.varStack.length) {
|
|
83
|
+
this.printVarStack();
|
|
84
|
+
throw new Error(
|
|
85
|
+
`checkConsistency fail, stack: ${this.stack.length}, varStack:${this.varStack.length}`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
Stack.prototype.checkConsistencyWithVars = function (varStack) {
|
|
91
|
+
if (this.stack.length < varStack.length) {
|
|
92
|
+
this.printVarStack();
|
|
93
|
+
throw new Error(
|
|
94
|
+
`checkConsistencyWithVars fail, stack: ${this.stack.length}, varStack:${varStack.length}`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
Object.defineProperty(Stack.prototype, 'length', {
|
|
100
|
+
get: function () {
|
|
101
|
+
return this.stack.length;
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
Object.defineProperty(Stack.prototype, 'rawstack', {
|
|
106
|
+
get: function () {
|
|
107
|
+
return this.stack;
|
|
108
|
+
},
|
|
109
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
function writeI32LE(writer, n) {
|
|
2
|
+
if (n < -2147483648 || n > 2147483647)
|
|
3
|
+
throw new Error('Out of range. It must be >= -2147483648 and <= 2147483647.');
|
|
4
|
+
|
|
5
|
+
const buffer = new Uint8Array(4);
|
|
6
|
+
buffer[0] = n % 256;
|
|
7
|
+
n = Math.floor(n / 256);
|
|
8
|
+
buffer[1] = n % 256;
|
|
9
|
+
n = n >> 8;
|
|
10
|
+
buffer[2] = n % 256;
|
|
11
|
+
n = n >> 8;
|
|
12
|
+
buffer[3] = n;
|
|
13
|
+
|
|
14
|
+
return writer.write(buffer);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = writeI32LE;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
function writePushData(writer, buffer) {
|
|
2
|
+
// It is possible to optimize buffers that only store numbers 1-16, or -1, by using the OP_N opcodes.
|
|
3
|
+
// But we say "push data" is always stored using OP_0 or OP_PUSH(N) so that it's easy to identify and
|
|
4
|
+
// extract, and also because there is some ambiguity around OP_0 if we don't do this.
|
|
5
|
+
if (buffer.length === 0) {
|
|
6
|
+
writer.write([0]);
|
|
7
|
+
} else if (buffer.length <= 75) {
|
|
8
|
+
writer.write([buffer.length]); // OP_PUSH(buffer.length)
|
|
9
|
+
writer.write(buffer);
|
|
10
|
+
} else if (buffer.length <= 0xff) {
|
|
11
|
+
writer.write([76, buffer.length]); // OP_PUSHDATA1
|
|
12
|
+
writer.write(buffer);
|
|
13
|
+
} else if (buffer.length <= 0xffff) {
|
|
14
|
+
writer.write([77, buffer.length % 256, buffer.length >> 8]); // OP_PUSHDATA2
|
|
15
|
+
writer.write(buffer);
|
|
16
|
+
} else if (buffer.length <= 0xffffffff) {
|
|
17
|
+
const prefix = new Uint8Array(5);
|
|
18
|
+
prefix[0] = 78; // OP_PUSHDATA4
|
|
19
|
+
let n = buffer.length;
|
|
20
|
+
prefix[1] = n % 256;
|
|
21
|
+
n = Math.floor(n / 256);
|
|
22
|
+
prefix[2] = n % 256;
|
|
23
|
+
n = Math.floor(n / 256);
|
|
24
|
+
prefix[3] = n % 256;
|
|
25
|
+
n = Math.floor(n / 256);
|
|
26
|
+
prefix[4] = n;
|
|
27
|
+
writer.write(prefix);
|
|
28
|
+
writer.write(buffer);
|
|
29
|
+
} else {
|
|
30
|
+
throw new Error('data too large');
|
|
31
|
+
}
|
|
32
|
+
return writer;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = writePushData;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
function writeU16LE(writer, n) {
|
|
2
|
+
if (n > 0xffff) throw new Error('number too large');
|
|
3
|
+
|
|
4
|
+
const buffer = new Uint8Array(2);
|
|
5
|
+
buffer[0] = n % 256;
|
|
6
|
+
n = n >> 8;
|
|
7
|
+
buffer[1] = n % 256;
|
|
8
|
+
|
|
9
|
+
return writer.write(buffer);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = writeU16LE;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
function writeU32LE(writer, n) {
|
|
2
|
+
if (n > 0xffffffff) throw new Error('number too large');
|
|
3
|
+
|
|
4
|
+
const buffer = new Uint8Array(4);
|
|
5
|
+
buffer[0] = n % 256;
|
|
6
|
+
n = Math.floor(n / 256);
|
|
7
|
+
buffer[1] = n % 256;
|
|
8
|
+
n = n >> 8;
|
|
9
|
+
buffer[2] = n % 256;
|
|
10
|
+
n = n >> 8;
|
|
11
|
+
buffer[3] = n;
|
|
12
|
+
|
|
13
|
+
return writer.write(buffer);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
module.exports = writeU32LE;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function writeU64LE(writer, n) {
|
|
2
|
+
if (n > Number.MAX_SAFE_INTEGER) throw new Error('number too large');
|
|
3
|
+
|
|
4
|
+
const buffer = new Uint8Array(8);
|
|
5
|
+
buffer[0] = n % 256;
|
|
6
|
+
n = Math.floor(n / 256);
|
|
7
|
+
buffer[1] = n % 256;
|
|
8
|
+
n = Math.floor(n / 256);
|
|
9
|
+
buffer[2] = n % 256;
|
|
10
|
+
n = Math.floor(n / 256);
|
|
11
|
+
buffer[3] = n % 256;
|
|
12
|
+
n = Math.floor(n / 256);
|
|
13
|
+
buffer[4] = n % 256;
|
|
14
|
+
n = Math.floor(n / 256);
|
|
15
|
+
buffer[5] = n % 256;
|
|
16
|
+
n = n >> 8;
|
|
17
|
+
buffer[6] = n % 256;
|
|
18
|
+
n = n >> 8;
|
|
19
|
+
buffer[7] = n;
|
|
20
|
+
|
|
21
|
+
return writer.write(buffer);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = writeU64LE;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function writeVarint(writer, n) {
|
|
2
|
+
if (n > Number.MAX_SAFE_INTEGER) throw new Error('varint too large');
|
|
3
|
+
|
|
4
|
+
if (n <= 0xfc) {
|
|
5
|
+
return writer.write([n]);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (n <= 0xffff) {
|
|
9
|
+
return writer.write([0xfd, n % 256, Math.floor(n / 256)]);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (n <= 0xffffffff) {
|
|
13
|
+
const buffer = new Uint8Array(5);
|
|
14
|
+
buffer[0] = 0xfe;
|
|
15
|
+
buffer[1] = n % 256;
|
|
16
|
+
n = Math.floor(n / 256);
|
|
17
|
+
buffer[2] = n % 256;
|
|
18
|
+
n = Math.floor(n / 256);
|
|
19
|
+
buffer[3] = n % 256;
|
|
20
|
+
n = Math.floor(n / 256);
|
|
21
|
+
buffer[4] = n;
|
|
22
|
+
return writer.write(buffer);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// n <= 0xffffffffffffffff
|
|
26
|
+
const buffer = new Uint8Array(9);
|
|
27
|
+
buffer[0] = 0xff;
|
|
28
|
+
buffer[1] = n % 256;
|
|
29
|
+
n = Math.floor(n / 256);
|
|
30
|
+
buffer[2] = n % 256;
|
|
31
|
+
n = Math.floor(n / 256);
|
|
32
|
+
buffer[3] = n % 256;
|
|
33
|
+
n = Math.floor(n / 256);
|
|
34
|
+
buffer[4] = n % 256;
|
|
35
|
+
n = Math.floor(n / 256);
|
|
36
|
+
buffer[5] = n % 256;
|
|
37
|
+
n = Math.floor(n / 256);
|
|
38
|
+
buffer[6] = n % 256;
|
|
39
|
+
n = Math.floor(n / 256);
|
|
40
|
+
buffer[7] = n % 256;
|
|
41
|
+
n = Math.floor(n / 256);
|
|
42
|
+
buffer[8] = n;
|
|
43
|
+
return writer.write(buffer);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = writeVarint;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
module.exports = require('./transaction');
|
|
2
|
+
|
|
3
|
+
module.exports.Input = require('./input');
|
|
4
|
+
module.exports.Output = require('./output');
|
|
5
|
+
module.exports.UnspentOutput = require('./unspentoutput');
|
|
6
|
+
module.exports.Signature = require('./signature');
|
|
7
|
+
module.exports.Sighash = require('./sighash');
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var _ = require('../../util/_');
|
|
4
|
+
var $ = require('../../util/preconditions');
|
|
5
|
+
var errors = require('../../errors');
|
|
6
|
+
var BufferWriter = require('../../encoding/bufferwriter');
|
|
7
|
+
var JSUtil = require('../../util/js');
|
|
8
|
+
var Script = require('../../script');
|
|
9
|
+
var Sighash = require('../sighash');
|
|
10
|
+
var Output = require('../output');
|
|
11
|
+
var Signature = require('../../crypto/signature');
|
|
12
|
+
var TransactionSignature = require('../signature');
|
|
13
|
+
var Hash = require('../../crypto/hash');
|
|
14
|
+
var Interpreter = require('../../script/interpreter');
|
|
15
|
+
var Opcode = require('../../opcode');
|
|
16
|
+
const PrivateKey = require('../../privatekey');
|
|
17
|
+
|
|
18
|
+
var MAXINT = 0xffffffff; // Math.pow(2, 32) - 1;
|
|
19
|
+
var DEFAULT_RBF_SEQNUMBER = MAXINT - 2;
|
|
20
|
+
var DEFAULT_SEQNUMBER = MAXINT;
|
|
21
|
+
var DEFAULT_LOCKTIME_SEQNUMBER = MAXINT - 1;
|
|
22
|
+
|
|
23
|
+
function getLowSPreimage(tx, sigtype, inputIndex, subscript, inputAmount) {
|
|
24
|
+
var i = 0;
|
|
25
|
+
do {
|
|
26
|
+
var preimage = Sighash.sighashPreimage(tx, sigtype, inputIndex, subscript, inputAmount);
|
|
27
|
+
|
|
28
|
+
var sighash = Hash.sha256sha256(preimage);
|
|
29
|
+
|
|
30
|
+
if (_.isPositiveNumber(sighash.readUInt8()) && _.isPositiveNumber(sighash.readUInt8(31))) {
|
|
31
|
+
return preimage;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
tx.nLockTime++;
|
|
35
|
+
} while (i < Number.MAX_SAFE_INTEGER);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function Input(params) {
|
|
39
|
+
if (!(this instanceof Input)) {
|
|
40
|
+
return new Input(params);
|
|
41
|
+
}
|
|
42
|
+
if (params) {
|
|
43
|
+
return this._fromObject(params);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
Input.MAXINT = MAXINT;
|
|
48
|
+
Input.DEFAULT_SEQNUMBER = DEFAULT_SEQNUMBER;
|
|
49
|
+
Input.DEFAULT_LOCKTIME_SEQNUMBER = DEFAULT_LOCKTIME_SEQNUMBER;
|
|
50
|
+
Input.DEFAULT_RBF_SEQNUMBER = DEFAULT_RBF_SEQNUMBER;
|
|
51
|
+
// txid + output index + sequence number
|
|
52
|
+
Input.BASE_SIZE = 32 + 4 + 4;
|
|
53
|
+
|
|
54
|
+
Object.defineProperty(Input.prototype, 'script', {
|
|
55
|
+
configurable: false,
|
|
56
|
+
enumerable: true,
|
|
57
|
+
get: function () {
|
|
58
|
+
if (this.isNull()) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
if (!this._script) {
|
|
62
|
+
this._script = new Script(this._scriptBuffer);
|
|
63
|
+
this._script._isInput = true;
|
|
64
|
+
}
|
|
65
|
+
return this._script;
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
Input.fromObject = function (obj) {
|
|
70
|
+
$.checkArgument(_.isObject(obj));
|
|
71
|
+
var input = new Input();
|
|
72
|
+
return input._fromObject(obj);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
Input.prototype._fromObject = function (params) {
|
|
76
|
+
|
|
77
|
+
if(_.isUndefined(params.prevTxId)
|
|
78
|
+
|| _.isUndefined(params.outputIndex)) {
|
|
79
|
+
throw new errors.Transaction.Input.InvalidParams('require prevTxId and outputIndex');
|
|
80
|
+
}
|
|
81
|
+
var prevTxId;
|
|
82
|
+
if (_.isString(params.prevTxId) && JSUtil.isHexa(params.prevTxId)) {
|
|
83
|
+
prevTxId = Buffer.from(params.prevTxId, 'hex');
|
|
84
|
+
} else {
|
|
85
|
+
prevTxId = params.prevTxId;
|
|
86
|
+
}
|
|
87
|
+
this.output = params.output
|
|
88
|
+
? params.output instanceof Output
|
|
89
|
+
? params.output
|
|
90
|
+
: new Output(params.output)
|
|
91
|
+
: undefined;
|
|
92
|
+
this.prevTxId = prevTxId || params.txidbuf;
|
|
93
|
+
this.outputIndex = _.isUndefined(params.outputIndex) ? params.txoutnum : params.outputIndex;
|
|
94
|
+
this.sequenceNumber = _.isUndefined(params.sequenceNumber)
|
|
95
|
+
? _.isUndefined(params.seqnum)
|
|
96
|
+
? DEFAULT_SEQNUMBER
|
|
97
|
+
: params.seqnum
|
|
98
|
+
: params.sequenceNumber;
|
|
99
|
+
this.setScript(params.scriptBuffer || params.script || Script.empty());
|
|
100
|
+
return this;
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
Input.prototype.toObject = Input.prototype.toJSON = function toObject() {
|
|
104
|
+
var obj = {
|
|
105
|
+
prevTxId: this.prevTxId.toString('hex'),
|
|
106
|
+
outputIndex: this.outputIndex,
|
|
107
|
+
sequenceNumber: this.sequenceNumber,
|
|
108
|
+
script: this._scriptBuffer.toString('hex'),
|
|
109
|
+
};
|
|
110
|
+
// add human readable form if input contains valid script
|
|
111
|
+
if (this.script) {
|
|
112
|
+
obj.scriptString = this.script.toString();
|
|
113
|
+
}
|
|
114
|
+
if (this.output) {
|
|
115
|
+
obj.output = this.output.toObject();
|
|
116
|
+
}
|
|
117
|
+
return obj;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
Input.fromBufferReader = function (br) {
|
|
121
|
+
var input = new Input();
|
|
122
|
+
input.prevTxId = br.readReverse(32);
|
|
123
|
+
input.outputIndex = br.readUInt32LE();
|
|
124
|
+
input._scriptBuffer = br.readVarLengthBuffer();
|
|
125
|
+
input.sequenceNumber = br.readUInt32LE();
|
|
126
|
+
// TODO: return different classes according to which input it is
|
|
127
|
+
// e.g: CoinbaseInput, PublicKeyHashInput, etc.
|
|
128
|
+
return input;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
Input.prototype.toBufferWriter = function (hashScriptSig, writer) {
|
|
132
|
+
$.checkArgument(typeof hashScriptSig === 'boolean', 'hashScriptSig should be boolean')
|
|
133
|
+
if (!writer) {
|
|
134
|
+
writer = new BufferWriter()
|
|
135
|
+
}
|
|
136
|
+
writer.writeReverse(this.prevTxId)
|
|
137
|
+
writer.writeUInt32LE(this.outputIndex)
|
|
138
|
+
var script = this._scriptBuffer
|
|
139
|
+
if(hashScriptSig) {
|
|
140
|
+
writer.write(Hash.sha256(script))
|
|
141
|
+
} else {
|
|
142
|
+
writer.writeVarintNum(script.length)
|
|
143
|
+
writer.write(script)
|
|
144
|
+
}
|
|
145
|
+
writer.writeUInt32LE(this.sequenceNumber)
|
|
146
|
+
return writer
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
Input.prototype.toPrevout = function () {
|
|
151
|
+
let writer = new BufferWriter()
|
|
152
|
+
writer.writeReverse(this.prevTxId)
|
|
153
|
+
writer.writeUInt32LE(this.outputIndex)
|
|
154
|
+
return writer.toBuffer()
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
Input.prototype.setScript = function (script) {
|
|
159
|
+
this._script = null;
|
|
160
|
+
if (script instanceof Script) {
|
|
161
|
+
this._script = script;
|
|
162
|
+
this._script._isInput = true;
|
|
163
|
+
this._scriptBuffer = script.toBuffer();
|
|
164
|
+
} else if (script === null) {
|
|
165
|
+
this._script = Script.empty();
|
|
166
|
+
this._script._isInput = true;
|
|
167
|
+
this._scriptBuffer = this._script.toBuffer();
|
|
168
|
+
} else if (JSUtil.isHexa(script)) {
|
|
169
|
+
// hex string script
|
|
170
|
+
this._scriptBuffer = Buffer.from(script, 'hex');
|
|
171
|
+
} else if (_.isString(script)) {
|
|
172
|
+
// human readable string script
|
|
173
|
+
this._script = new Script(script);
|
|
174
|
+
this._script._isInput = true;
|
|
175
|
+
this._scriptBuffer = this._script.toBuffer();
|
|
176
|
+
} else if (Buffer.isBuffer(script)) {
|
|
177
|
+
// buffer script
|
|
178
|
+
this._scriptBuffer = Buffer.from(script);
|
|
179
|
+
} else {
|
|
180
|
+
throw new TypeError('Invalid argument type: script');
|
|
181
|
+
}
|
|
182
|
+
return this;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Retrieve signatures for the provided PrivateKey.
|
|
187
|
+
*
|
|
188
|
+
* @param {Transaction} transaction - the transaction to be signed
|
|
189
|
+
* @param {PrivateKey | Array} privateKeys - the private key to use when signing
|
|
190
|
+
* @param {number} inputIndex - the index of this input in the provided transaction
|
|
191
|
+
* @param {number} sigType - defaults to Signature.SIGHASH_ALL
|
|
192
|
+
* @abstract
|
|
193
|
+
*/
|
|
194
|
+
Input.prototype.getSignatures = function (transaction, privateKeys, inputIndex, sigtype) {
|
|
195
|
+
$.checkState(this.output instanceof Output);
|
|
196
|
+
sigtype = sigtype || Signature.SIGHASH_ALL;
|
|
197
|
+
var results = [];
|
|
198
|
+
if (privateKeys instanceof PrivateKey) {
|
|
199
|
+
results.push(
|
|
200
|
+
new TransactionSignature({
|
|
201
|
+
publicKey: privateKeys.publicKey,
|
|
202
|
+
prevTxId: this.prevTxId,
|
|
203
|
+
outputIndex: this.outputIndex,
|
|
204
|
+
inputIndex: inputIndex,
|
|
205
|
+
signature: Sighash.sign(
|
|
206
|
+
transaction,
|
|
207
|
+
privateKeys,
|
|
208
|
+
sigtype,
|
|
209
|
+
inputIndex,
|
|
210
|
+
),
|
|
211
|
+
sigtype: sigtype,
|
|
212
|
+
}),
|
|
213
|
+
);
|
|
214
|
+
} else if (_.isArray(privateKeys)) {
|
|
215
|
+
var self = this;
|
|
216
|
+
|
|
217
|
+
_.each(privateKeys, function (privateKey, index) {
|
|
218
|
+
var sigtype_ = sigtype;
|
|
219
|
+
if (_.isArray(sigtype)) {
|
|
220
|
+
sigtype_ = sigtype[index] || Signature.SIGHASH_ALL;
|
|
221
|
+
}
|
|
222
|
+
results.push(
|
|
223
|
+
new TransactionSignature({
|
|
224
|
+
publicKey: privateKey.publicKey,
|
|
225
|
+
prevTxId: self.prevTxId,
|
|
226
|
+
outputIndex: self.outputIndex,
|
|
227
|
+
inputIndex: inputIndex,
|
|
228
|
+
signature: Sighash.sign(
|
|
229
|
+
transaction,
|
|
230
|
+
privateKey,
|
|
231
|
+
sigtype_,
|
|
232
|
+
inputIndex,
|
|
233
|
+
),
|
|
234
|
+
sigtype: sigtype_,
|
|
235
|
+
}),
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
return results;
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Retrieve preimage for the Input.
|
|
244
|
+
*
|
|
245
|
+
* @param {Transaction} transaction - the transaction to be signed
|
|
246
|
+
* @param {number} inputIndex - the index of this input in the provided transaction
|
|
247
|
+
* @param {number} sigType - defaults to Signature.SIGHASH_ALL
|
|
248
|
+
* @param {boolean} isLowS - true if the sig hash is safe for low s.
|
|
249
|
+
* @abstract
|
|
250
|
+
*/
|
|
251
|
+
Input.prototype.getPreimage = function (transaction, inputIndex, sigtype, isLowS) {
|
|
252
|
+
$.checkState(this.output instanceof Output);
|
|
253
|
+
sigtype = sigtype || Signature.SIGHASH_ALL;
|
|
254
|
+
isLowS = isLowS || false;
|
|
255
|
+
return isLowS
|
|
256
|
+
? getLowSPreimage(transaction, sigtype, inputIndex)
|
|
257
|
+
: Sighash.sighashPreimage(transaction, sigtype, inputIndex);
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
Input.prototype.isFullySigned = function () {
|
|
261
|
+
throw new errors.AbstractMethodInvoked('Input#isFullySigned');
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
Input.prototype.isFinal = function () {
|
|
265
|
+
return this.sequenceNumber === Input.MAXINT;
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
Input.prototype.addSignature = function (transaction, signature) {
|
|
269
|
+
const s = Script.buildPublicKeyIn(signature.signature.toDER(), signature.sigtype)
|
|
270
|
+
console.log("s:", s.toHex())
|
|
271
|
+
// throw new errors.AbstractMethodInvoked('Input#addSignature')
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
Input.prototype.clearSignatures = function () {
|
|
275
|
+
// throw new errors.AbstractMethodInvoked('Input#clearSignatures')
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
Input.prototype.isValidSignature = function (transaction, signature) {
|
|
279
|
+
// FIXME: Refactor signature so this is not necessary
|
|
280
|
+
signature.signature.nhashtype = signature.sigtype;
|
|
281
|
+
return Sighash.verify(
|
|
282
|
+
transaction,
|
|
283
|
+
signature.signature,
|
|
284
|
+
signature.publicKey,
|
|
285
|
+
signature.inputIndex,
|
|
286
|
+
this.output.script,
|
|
287
|
+
this.output.satoshisBN,
|
|
288
|
+
);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* @returns true if this is a coinbase input (represents no input)
|
|
293
|
+
*/
|
|
294
|
+
Input.prototype.isNull = function () {
|
|
295
|
+
return (
|
|
296
|
+
this.prevTxId.toString('hex') ===
|
|
297
|
+
'0000000000000000000000000000000000000000000000000000000000000000' &&
|
|
298
|
+
this.outputIndex === 0xffffffff
|
|
299
|
+
);
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
Input.prototype._estimateSize = function () {
|
|
303
|
+
return this.toBufferWriter(false).toBuffer().length;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
Input.prototype.verify = function (transaction, inputIndex) {
|
|
307
|
+
$.checkState(this.output instanceof Output);
|
|
308
|
+
$.checkState(this.script instanceof Script);
|
|
309
|
+
$.checkState(this.output.script instanceof Script);
|
|
310
|
+
|
|
311
|
+
var us = this.script;
|
|
312
|
+
var ls = this.output.script;
|
|
313
|
+
var inputSatoshis = this.output.satoshisBN;
|
|
314
|
+
|
|
315
|
+
Interpreter.MAX_SCRIPT_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER;
|
|
316
|
+
Interpreter.MAXIMUM_ELEMENT_SIZE = Number.MAX_SAFE_INTEGER;
|
|
317
|
+
|
|
318
|
+
const bsi = new Interpreter();
|
|
319
|
+
|
|
320
|
+
let failedAt = {};
|
|
321
|
+
|
|
322
|
+
bsi.stepListener = function (step) {
|
|
323
|
+
if (
|
|
324
|
+
step.fExec ||
|
|
325
|
+
(Opcode.OP_IF <= step.opcode.toNumber() && step.opcode.toNumber() <= Opcode.OP_ENDIF)
|
|
326
|
+
) {
|
|
327
|
+
if (
|
|
328
|
+
(Opcode.OP_IF <= step.opcode.toNumber() && step.opcode.toNumber() <= Opcode.OP_ENDIF) ||
|
|
329
|
+
step.opcode.toNumber() === Opcode.OP_RETURN
|
|
330
|
+
) {
|
|
331
|
+
/** Opreturn */ failedAt.opcode = step.opcode;
|
|
332
|
+
} else {
|
|
333
|
+
failedAt = step;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
var success = bsi.verify(
|
|
339
|
+
us,
|
|
340
|
+
ls,
|
|
341
|
+
transaction,
|
|
342
|
+
inputIndex,
|
|
343
|
+
Interpreter.DEFAULT_FLAGS,
|
|
344
|
+
inputSatoshis,
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
if (failedAt.opcode) {
|
|
348
|
+
failedAt.opcode = failedAt.opcode.toNumber();
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return { success, error: bsi.errstr, failedAt: success ? {} : failedAt };
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
module.exports = Input;
|