@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.
Files changed (138) hide show
  1. package/.mocharc.yaml +3 -0
  2. package/index.d.ts +1541 -0
  3. package/index.js +74 -0
  4. package/lib/address.js +478 -0
  5. package/lib/block/block.js +277 -0
  6. package/lib/block/blockheader.js +295 -0
  7. package/lib/block/index.js +4 -0
  8. package/lib/block/merkleblock.js +323 -0
  9. package/lib/bn.js +3423 -0
  10. package/lib/crypto/bn.js +278 -0
  11. package/lib/crypto/ecdsa.js +339 -0
  12. package/lib/crypto/hash.browser.js +171 -0
  13. package/lib/crypto/hash.js +2 -0
  14. package/lib/crypto/hash.node.js +171 -0
  15. package/lib/crypto/point.js +221 -0
  16. package/lib/crypto/random.browser.js +28 -0
  17. package/lib/crypto/random.js +2 -0
  18. package/lib/crypto/random.node.js +11 -0
  19. package/lib/crypto/signature.js +325 -0
  20. package/lib/encoding/base58.js +111 -0
  21. package/lib/encoding/base58check.js +121 -0
  22. package/lib/encoding/bufferreader.js +212 -0
  23. package/lib/encoding/bufferwriter.js +140 -0
  24. package/lib/encoding/decode-asm.js +24 -0
  25. package/lib/encoding/decode-hex.js +32 -0
  26. package/lib/encoding/decode-script-chunks.js +43 -0
  27. package/lib/encoding/encode-hex.js +284 -0
  28. package/lib/encoding/is-hex.js +7 -0
  29. package/lib/encoding/varint.js +75 -0
  30. package/lib/errors/index.js +54 -0
  31. package/lib/errors/spec.js +314 -0
  32. package/lib/hash-cache.js +50 -0
  33. package/lib/hdprivatekey.js +678 -0
  34. package/lib/hdpublickey.js +525 -0
  35. package/lib/message/message.js +191 -0
  36. package/lib/mnemonic/mnemonic.js +303 -0
  37. package/lib/mnemonic/pbkdf2.browser.js +68 -0
  38. package/lib/mnemonic/pbkdf2.js +2 -0
  39. package/lib/mnemonic/pbkdf2.node.js +68 -0
  40. package/lib/mnemonic/words/chinese.js +2054 -0
  41. package/lib/mnemonic/words/english.js +2054 -0
  42. package/lib/mnemonic/words/french.js +2054 -0
  43. package/lib/mnemonic/words/index.js +8 -0
  44. package/lib/mnemonic/words/italian.js +2054 -0
  45. package/lib/mnemonic/words/japanese.js +2054 -0
  46. package/lib/mnemonic/words/spanish.js +2054 -0
  47. package/lib/networks.js +379 -0
  48. package/lib/opcode.js +255 -0
  49. package/lib/privatekey.js +374 -0
  50. package/lib/publickey.js +386 -0
  51. package/lib/script/index.js +5 -0
  52. package/lib/script/interpreter.js +1834 -0
  53. package/lib/script/script.js +1074 -0
  54. package/lib/script/stack.js +109 -0
  55. package/lib/script/write-i32-le.js +17 -0
  56. package/lib/script/write-push-data.js +35 -0
  57. package/lib/script/write-u16-le.js +12 -0
  58. package/lib/script/write-u32-le.js +16 -0
  59. package/lib/script/write-u64-le.js +24 -0
  60. package/lib/script/write-u8-le.js +8 -0
  61. package/lib/script/write-varint.js +46 -0
  62. package/lib/transaction/index.js +7 -0
  63. package/lib/transaction/input/index.js +5 -0
  64. package/lib/transaction/input/input.js +354 -0
  65. package/lib/transaction/input/multisig.js +242 -0
  66. package/lib/transaction/input/publickey.js +100 -0
  67. package/lib/transaction/input/publickeyhash.js +118 -0
  68. package/lib/transaction/output.js +231 -0
  69. package/lib/transaction/sighash.js +167 -0
  70. package/lib/transaction/signature.js +97 -0
  71. package/lib/transaction/transaction.js +1639 -0
  72. package/lib/transaction/unspentoutput.js +113 -0
  73. package/lib/util/_.js +47 -0
  74. package/lib/util/js.js +90 -0
  75. package/lib/util/preconditions.js +33 -0
  76. package/package.json +26 -0
  77. package/test/address.js +509 -0
  78. package/test/block/block.js +251 -0
  79. package/test/block/blockheader.js +275 -0
  80. package/test/block/merklebloack.js +211 -0
  81. package/test/crypto/bn.js +177 -0
  82. package/test/crypto/ecdsa.js +391 -0
  83. package/test/crypto/hash.browser.js +135 -0
  84. package/test/crypto/hash.js +136 -0
  85. package/test/crypto/point.js +224 -0
  86. package/test/crypto/random.js +32 -0
  87. package/test/crypto/signature.js +409 -0
  88. package/test/data/bip69.json +215 -0
  89. package/test/data/bitcoind/base58_keys_invalid.json +52 -0
  90. package/test/data/bitcoind/base58_keys_valid.json +335 -0
  91. package/test/data/bitcoind/blocks.json +22 -0
  92. package/test/data/bitcoind/script_tests.json +3822 -0
  93. package/test/data/bitcoind/sig_canonical.json +7 -0
  94. package/test/data/bitcoind/sig_noncanonical.json +36 -0
  95. package/test/data/bitcoind/tx_invalid.json +445 -0
  96. package/test/data/bitcoind/tx_valid.json +44 -0
  97. package/test/data/blk86756-testnet.dat +0 -0
  98. package/test/data/blk86756-testnet.js +14 -0
  99. package/test/data/blk86756-testnet.json +684 -0
  100. package/test/data/block.hex +1 -0
  101. package/test/data/ecdsa.json +230 -0
  102. package/test/data/merkleblocks.js +488 -0
  103. package/test/data/messages.json +22 -0
  104. package/test/data/sighash.json +12 -0
  105. package/test/data/tx_creation.json +95 -0
  106. package/test/encoding/base58.js +131 -0
  107. package/test/encoding/base58check.js +136 -0
  108. package/test/encoding/bufferreader.js +337 -0
  109. package/test/encoding/bufferwriter.js +172 -0
  110. package/test/encoding/varint.js +104 -0
  111. package/test/hashCache.js +67 -0
  112. package/test/hdkeys.js +445 -0
  113. package/test/hdprivatekey.js +332 -0
  114. package/test/hdpublickey.js +304 -0
  115. package/test/index.js +16 -0
  116. package/test/message/message.js +204 -0
  117. package/test/mnemonic/data/fixtures.json +300 -0
  118. package/test/mnemonic/mnemonic.js +259 -0
  119. package/test/mnemonic/mocha.opts +1 -0
  120. package/test/mnemonic/pbkdf2.test.js +59 -0
  121. package/test/networks.js +159 -0
  122. package/test/opcode.js +161 -0
  123. package/test/privatekey.js +439 -0
  124. package/test/publickey.js +554 -0
  125. package/test/script/interpreter.js +734 -0
  126. package/test/script/script.js +1437 -0
  127. package/test/transaction/deserialize.js +34 -0
  128. package/test/transaction/input/input.js +90 -0
  129. package/test/transaction/input/multisig.js +90 -0
  130. package/test/transaction/input/publickey.js +68 -0
  131. package/test/transaction/input/publickeyhash.js +51 -0
  132. package/test/transaction/output.js +185 -0
  133. package/test/transaction/sighash.js +65 -0
  134. package/test/transaction/signature.js +114 -0
  135. package/test/transaction/transaction.js +1109 -0
  136. package/test/transaction/unspentoutput.js +110 -0
  137. package/test/util/js.js +76 -0
  138. 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,8 @@
1
+ function writeU8LE(writer, n) {
2
+ if (n > 0xff) throw new Error('number too large');
3
+ const buffer = new Uint8Array(1);
4
+ buffer[0] = n;
5
+ return writer.write(buffer);
6
+ }
7
+
8
+ module.exports = writeU8LE;
@@ -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,5 @@
1
+ module.exports = require('./input.js');
2
+
3
+ module.exports.PublicKey = require('./publickey.js');
4
+ module.exports.PublicKeyHash = require('./publickeyhash.js');
5
+ module.exports.MultiSig = require('./multisig.js');
@@ -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;