1 | 'use strict';
|
2 | Object.defineProperty(exports, '__esModule', { value: true });
|
3 | exports.Transaction = void 0;
|
4 | const bufferutils_1 = require('./bufferutils');
|
5 | const bcrypto = require('./crypto');
|
6 | const bscript = require('./script');
|
7 | const script_1 = require('./script');
|
8 | const types = require('./types');
|
9 | const { typeforce } = types;
|
10 | function varSliceSize(someScript) {
|
11 | const length = someScript.length;
|
12 | return bufferutils_1.varuint.encodingLength(length) + length;
|
13 | }
|
14 | function vectorSize(someVector) {
|
15 | const length = someVector.length;
|
16 | return (
|
17 | bufferutils_1.varuint.encodingLength(length) +
|
18 | someVector.reduce((sum, witness) => {
|
19 | return sum + varSliceSize(witness);
|
20 | }, 0)
|
21 | );
|
22 | }
|
23 | const EMPTY_BUFFER = Buffer.allocUnsafe(0);
|
24 | const EMPTY_WITNESS = [];
|
25 | const ZERO = Buffer.from(
|
26 | '0000000000000000000000000000000000000000000000000000000000000000',
|
27 | 'hex',
|
28 | );
|
29 | const ONE = Buffer.from(
|
30 | '0000000000000000000000000000000000000000000000000000000000000001',
|
31 | 'hex',
|
32 | );
|
33 | const VALUE_UINT64_MAX = Buffer.from('ffffffffffffffff', 'hex');
|
34 | const BLANK_OUTPUT = {
|
35 | script: EMPTY_BUFFER,
|
36 | valueBuffer: VALUE_UINT64_MAX,
|
37 | };
|
38 | function isOutput(out) {
|
39 | return out.value !== undefined;
|
40 | }
|
41 | class Transaction {
|
42 | constructor() {
|
43 | this.version = 1;
|
44 | this.locktime = 0;
|
45 | this.ins = [];
|
46 | this.outs = [];
|
47 | }
|
48 | static fromBuffer(buffer, _NO_STRICT) {
|
49 | const bufferReader = new bufferutils_1.BufferReader(buffer);
|
50 | const tx = new Transaction();
|
51 | tx.version = bufferReader.readInt32();
|
52 | const marker = bufferReader.readUInt8();
|
53 | const flag = bufferReader.readUInt8();
|
54 | let hasWitnesses = false;
|
55 | if (
|
56 | marker === Transaction.ADVANCED_TRANSACTION_MARKER &&
|
57 | flag === Transaction.ADVANCED_TRANSACTION_FLAG
|
58 | ) {
|
59 | hasWitnesses = true;
|
60 | } else {
|
61 | bufferReader.offset -= 2;
|
62 | }
|
63 | const vinLen = bufferReader.readVarInt();
|
64 | for (let i = 0; i < vinLen; ++i) {
|
65 | tx.ins.push({
|
66 | hash: bufferReader.readSlice(32),
|
67 | index: bufferReader.readUInt32(),
|
68 | script: bufferReader.readVarSlice(),
|
69 | sequence: bufferReader.readUInt32(),
|
70 | witness: EMPTY_WITNESS,
|
71 | });
|
72 | }
|
73 | const voutLen = bufferReader.readVarInt();
|
74 | for (let i = 0; i < voutLen; ++i) {
|
75 | tx.outs.push({
|
76 | value: bufferReader.readUInt64(),
|
77 | script: bufferReader.readVarSlice(),
|
78 | });
|
79 | }
|
80 | if (hasWitnesses) {
|
81 | for (let i = 0; i < vinLen; ++i) {
|
82 | tx.ins[i].witness = bufferReader.readVector();
|
83 | }
|
84 |
|
85 | if (!tx.hasWitnesses())
|
86 | throw new Error('Transaction has superfluous witness data');
|
87 | }
|
88 | tx.locktime = bufferReader.readUInt32();
|
89 | if (_NO_STRICT) return tx;
|
90 | if (bufferReader.offset !== buffer.length)
|
91 | throw new Error('Transaction has unexpected data');
|
92 | return tx;
|
93 | }
|
94 | static fromHex(hex) {
|
95 | return Transaction.fromBuffer(Buffer.from(hex, 'hex'), false);
|
96 | }
|
97 | static isCoinbaseHash(buffer) {
|
98 | typeforce(types.Hash256bit, buffer);
|
99 | for (let i = 0; i < 32; ++i) {
|
100 | if (buffer[i] !== 0) return false;
|
101 | }
|
102 | return true;
|
103 | }
|
104 | isCoinbase() {
|
105 | return (
|
106 | this.ins.length === 1 && Transaction.isCoinbaseHash(this.ins[0].hash)
|
107 | );
|
108 | }
|
109 | addInput(hash, index, sequence, scriptSig) {
|
110 | typeforce(
|
111 | types.tuple(
|
112 | types.Hash256bit,
|
113 | types.UInt32,
|
114 | types.maybe(types.UInt32),
|
115 | types.maybe(types.Buffer),
|
116 | ),
|
117 | arguments,
|
118 | );
|
119 | if (types.Null(sequence)) {
|
120 | sequence = Transaction.DEFAULT_SEQUENCE;
|
121 | }
|
122 |
|
123 | return (
|
124 | this.ins.push({
|
125 | hash,
|
126 | index,
|
127 | script: scriptSig || EMPTY_BUFFER,
|
128 | sequence: sequence,
|
129 | witness: EMPTY_WITNESS,
|
130 | }) - 1
|
131 | );
|
132 | }
|
133 | addOutput(scriptPubKey, value) {
|
134 | typeforce(types.tuple(types.Buffer, types.Satoshi), arguments);
|
135 |
|
136 | return (
|
137 | this.outs.push({
|
138 | script: scriptPubKey,
|
139 | value,
|
140 | }) - 1
|
141 | );
|
142 | }
|
143 | hasWitnesses() {
|
144 | return this.ins.some(x => {
|
145 | return x.witness.length !== 0;
|
146 | });
|
147 | }
|
148 | weight() {
|
149 | const base = this.byteLength(false);
|
150 | const total = this.byteLength(true);
|
151 | return base * 3 + total;
|
152 | }
|
153 | virtualSize() {
|
154 | return Math.ceil(this.weight() / 4);
|
155 | }
|
156 | byteLength(_ALLOW_WITNESS = true) {
|
157 | const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();
|
158 | return (
|
159 | (hasWitnesses ? 10 : 8) +
|
160 | bufferutils_1.varuint.encodingLength(this.ins.length) +
|
161 | bufferutils_1.varuint.encodingLength(this.outs.length) +
|
162 | this.ins.reduce((sum, input) => {
|
163 | return sum + 40 + varSliceSize(input.script);
|
164 | }, 0) +
|
165 | this.outs.reduce((sum, output) => {
|
166 | return sum + 8 + varSliceSize(output.script);
|
167 | }, 0) +
|
168 | (hasWitnesses
|
169 | ? this.ins.reduce((sum, input) => {
|
170 | return sum + vectorSize(input.witness);
|
171 | }, 0)
|
172 | : 0)
|
173 | );
|
174 | }
|
175 | clone() {
|
176 | const newTx = new Transaction();
|
177 | newTx.version = this.version;
|
178 | newTx.locktime = this.locktime;
|
179 | newTx.ins = this.ins.map(txIn => {
|
180 | return {
|
181 | hash: txIn.hash,
|
182 | index: txIn.index,
|
183 | script: txIn.script,
|
184 | sequence: txIn.sequence,
|
185 | witness: txIn.witness,
|
186 | };
|
187 | });
|
188 | newTx.outs = this.outs.map(txOut => {
|
189 | return {
|
190 | script: txOut.script,
|
191 | value: txOut.value,
|
192 | };
|
193 | });
|
194 | return newTx;
|
195 | }
|
196 | |
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 | hashForSignature(inIndex, prevOutScript, hashType) {
|
205 | typeforce(
|
206 | types.tuple(types.UInt32, types.Buffer, types.Number),
|
207 | arguments,
|
208 | );
|
209 |
|
210 | if (inIndex >= this.ins.length) return ONE;
|
211 |
|
212 | const ourScript = bscript.compile(
|
213 | bscript.decompile(prevOutScript).filter(x => {
|
214 | return x !== script_1.OPS.OP_CODESEPARATOR;
|
215 | }),
|
216 | );
|
217 | const txTmp = this.clone();
|
218 |
|
219 | if ((hashType & 0x1f) === Transaction.SIGHASH_NONE) {
|
220 | txTmp.outs = [];
|
221 |
|
222 | txTmp.ins.forEach((input, i) => {
|
223 | if (i === inIndex) return;
|
224 | input.sequence = 0;
|
225 | });
|
226 |
|
227 | } else if ((hashType & 0x1f) === Transaction.SIGHASH_SINGLE) {
|
228 |
|
229 | if (inIndex >= this.outs.length) return ONE;
|
230 |
|
231 | txTmp.outs.length = inIndex + 1;
|
232 |
|
233 | for (let i = 0; i < inIndex; i++) {
|
234 | txTmp.outs[i] = BLANK_OUTPUT;
|
235 | }
|
236 |
|
237 | txTmp.ins.forEach((input, y) => {
|
238 | if (y === inIndex) return;
|
239 | input.sequence = 0;
|
240 | });
|
241 | }
|
242 |
|
243 | if (hashType & Transaction.SIGHASH_ANYONECANPAY) {
|
244 | txTmp.ins = [txTmp.ins[inIndex]];
|
245 | txTmp.ins[0].script = ourScript;
|
246 |
|
247 | } else {
|
248 |
|
249 | txTmp.ins.forEach(input => {
|
250 | input.script = EMPTY_BUFFER;
|
251 | });
|
252 | txTmp.ins[inIndex].script = ourScript;
|
253 | }
|
254 |
|
255 | const buffer = Buffer.allocUnsafe(txTmp.byteLength(false) + 4);
|
256 | buffer.writeInt32LE(hashType, buffer.length - 4);
|
257 | txTmp.__toBuffer(buffer, 0, false);
|
258 | return bcrypto.hash256(buffer);
|
259 | }
|
260 | hashForWitnessV1(inIndex, prevOutScripts, values, hashType, leafHash, annex) {
|
261 |
|
262 | typeforce(
|
263 | types.tuple(
|
264 | types.UInt32,
|
265 | typeforce.arrayOf(types.Buffer),
|
266 | typeforce.arrayOf(types.Satoshi),
|
267 | types.UInt32,
|
268 | ),
|
269 | arguments,
|
270 | );
|
271 | if (
|
272 | values.length !== this.ins.length ||
|
273 | prevOutScripts.length !== this.ins.length
|
274 | ) {
|
275 | throw new Error('Must supply prevout script and value for all inputs');
|
276 | }
|
277 | const outputType =
|
278 | hashType === Transaction.SIGHASH_DEFAULT
|
279 | ? Transaction.SIGHASH_ALL
|
280 | : hashType & Transaction.SIGHASH_OUTPUT_MASK;
|
281 | const inputType = hashType & Transaction.SIGHASH_INPUT_MASK;
|
282 | const isAnyoneCanPay = inputType === Transaction.SIGHASH_ANYONECANPAY;
|
283 | const isNone = outputType === Transaction.SIGHASH_NONE;
|
284 | const isSingle = outputType === Transaction.SIGHASH_SINGLE;
|
285 | let hashPrevouts = EMPTY_BUFFER;
|
286 | let hashAmounts = EMPTY_BUFFER;
|
287 | let hashScriptPubKeys = EMPTY_BUFFER;
|
288 | let hashSequences = EMPTY_BUFFER;
|
289 | let hashOutputs = EMPTY_BUFFER;
|
290 | if (!isAnyoneCanPay) {
|
291 | let bufferWriter = bufferutils_1.BufferWriter.withCapacity(
|
292 | 36 * this.ins.length,
|
293 | );
|
294 | this.ins.forEach(txIn => {
|
295 | bufferWriter.writeSlice(txIn.hash);
|
296 | bufferWriter.writeUInt32(txIn.index);
|
297 | });
|
298 | hashPrevouts = bcrypto.sha256(bufferWriter.end());
|
299 | bufferWriter = bufferutils_1.BufferWriter.withCapacity(
|
300 | 8 * this.ins.length,
|
301 | );
|
302 | values.forEach(value => bufferWriter.writeUInt64(value));
|
303 | hashAmounts = bcrypto.sha256(bufferWriter.end());
|
304 | bufferWriter = bufferutils_1.BufferWriter.withCapacity(
|
305 | prevOutScripts.map(varSliceSize).reduce((a, b) => a + b),
|
306 | );
|
307 | prevOutScripts.forEach(prevOutScript =>
|
308 | bufferWriter.writeVarSlice(prevOutScript),
|
309 | );
|
310 | hashScriptPubKeys = bcrypto.sha256(bufferWriter.end());
|
311 | bufferWriter = bufferutils_1.BufferWriter.withCapacity(
|
312 | 4 * this.ins.length,
|
313 | );
|
314 | this.ins.forEach(txIn => bufferWriter.writeUInt32(txIn.sequence));
|
315 | hashSequences = bcrypto.sha256(bufferWriter.end());
|
316 | }
|
317 | if (!(isNone || isSingle)) {
|
318 | const txOutsSize = this.outs
|
319 | .map(output => 8 + varSliceSize(output.script))
|
320 | .reduce((a, b) => a + b);
|
321 | const bufferWriter = bufferutils_1.BufferWriter.withCapacity(txOutsSize);
|
322 | this.outs.forEach(out => {
|
323 | bufferWriter.writeUInt64(out.value);
|
324 | bufferWriter.writeVarSlice(out.script);
|
325 | });
|
326 | hashOutputs = bcrypto.sha256(bufferWriter.end());
|
327 | } else if (isSingle && inIndex < this.outs.length) {
|
328 | const output = this.outs[inIndex];
|
329 | const bufferWriter = bufferutils_1.BufferWriter.withCapacity(
|
330 | 8 + varSliceSize(output.script),
|
331 | );
|
332 | bufferWriter.writeUInt64(output.value);
|
333 | bufferWriter.writeVarSlice(output.script);
|
334 | hashOutputs = bcrypto.sha256(bufferWriter.end());
|
335 | }
|
336 | const spendType = (leafHash ? 2 : 0) + (annex ? 1 : 0);
|
337 |
|
338 |
|
339 |
|
340 |
|
341 | const sigMsgSize =
|
342 | 174 -
|
343 | (isAnyoneCanPay ? 49 : 0) -
|
344 | (isNone ? 32 : 0) +
|
345 | (annex ? 32 : 0) +
|
346 | (leafHash ? 37 : 0);
|
347 | const sigMsgWriter = bufferutils_1.BufferWriter.withCapacity(sigMsgSize);
|
348 | sigMsgWriter.writeUInt8(hashType);
|
349 |
|
350 | sigMsgWriter.writeInt32(this.version);
|
351 | sigMsgWriter.writeUInt32(this.locktime);
|
352 | sigMsgWriter.writeSlice(hashPrevouts);
|
353 | sigMsgWriter.writeSlice(hashAmounts);
|
354 | sigMsgWriter.writeSlice(hashScriptPubKeys);
|
355 | sigMsgWriter.writeSlice(hashSequences);
|
356 | if (!(isNone || isSingle)) {
|
357 | sigMsgWriter.writeSlice(hashOutputs);
|
358 | }
|
359 |
|
360 | sigMsgWriter.writeUInt8(spendType);
|
361 | if (isAnyoneCanPay) {
|
362 | const input = this.ins[inIndex];
|
363 | sigMsgWriter.writeSlice(input.hash);
|
364 | sigMsgWriter.writeUInt32(input.index);
|
365 | sigMsgWriter.writeUInt64(values[inIndex]);
|
366 | sigMsgWriter.writeVarSlice(prevOutScripts[inIndex]);
|
367 | sigMsgWriter.writeUInt32(input.sequence);
|
368 | } else {
|
369 | sigMsgWriter.writeUInt32(inIndex);
|
370 | }
|
371 | if (annex) {
|
372 | const bufferWriter = bufferutils_1.BufferWriter.withCapacity(
|
373 | varSliceSize(annex),
|
374 | );
|
375 | bufferWriter.writeVarSlice(annex);
|
376 | sigMsgWriter.writeSlice(bcrypto.sha256(bufferWriter.end()));
|
377 | }
|
378 |
|
379 | if (isSingle) {
|
380 | sigMsgWriter.writeSlice(hashOutputs);
|
381 | }
|
382 |
|
383 | if (leafHash) {
|
384 | sigMsgWriter.writeSlice(leafHash);
|
385 | sigMsgWriter.writeUInt8(0);
|
386 | sigMsgWriter.writeUInt32(0xffffffff);
|
387 | }
|
388 |
|
389 |
|
390 | return bcrypto.taggedHash(
|
391 | 'TapSighash',
|
392 | Buffer.concat([Buffer.from([0x00]), sigMsgWriter.end()]),
|
393 | );
|
394 | }
|
395 | hashForWitnessV0(inIndex, prevOutScript, value, hashType) {
|
396 | typeforce(
|
397 | types.tuple(types.UInt32, types.Buffer, types.Satoshi, types.UInt32),
|
398 | arguments,
|
399 | );
|
400 | let tbuffer = Buffer.from([]);
|
401 | let bufferWriter;
|
402 | let hashOutputs = ZERO;
|
403 | let hashPrevouts = ZERO;
|
404 | let hashSequence = ZERO;
|
405 | if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) {
|
406 | tbuffer = Buffer.allocUnsafe(36 * this.ins.length);
|
407 | bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
|
408 | this.ins.forEach(txIn => {
|
409 | bufferWriter.writeSlice(txIn.hash);
|
410 | bufferWriter.writeUInt32(txIn.index);
|
411 | });
|
412 | hashPrevouts = bcrypto.hash256(tbuffer);
|
413 | }
|
414 | if (
|
415 | !(hashType & Transaction.SIGHASH_ANYONECANPAY) &&
|
416 | (hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
|
417 | (hashType & 0x1f) !== Transaction.SIGHASH_NONE
|
418 | ) {
|
419 | tbuffer = Buffer.allocUnsafe(4 * this.ins.length);
|
420 | bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
|
421 | this.ins.forEach(txIn => {
|
422 | bufferWriter.writeUInt32(txIn.sequence);
|
423 | });
|
424 | hashSequence = bcrypto.hash256(tbuffer);
|
425 | }
|
426 | if (
|
427 | (hashType & 0x1f) !== Transaction.SIGHASH_SINGLE &&
|
428 | (hashType & 0x1f) !== Transaction.SIGHASH_NONE
|
429 | ) {
|
430 | const txOutsSize = this.outs.reduce((sum, output) => {
|
431 | return sum + 8 + varSliceSize(output.script);
|
432 | }, 0);
|
433 | tbuffer = Buffer.allocUnsafe(txOutsSize);
|
434 | bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
|
435 | this.outs.forEach(out => {
|
436 | bufferWriter.writeUInt64(out.value);
|
437 | bufferWriter.writeVarSlice(out.script);
|
438 | });
|
439 | hashOutputs = bcrypto.hash256(tbuffer);
|
440 | } else if (
|
441 | (hashType & 0x1f) === Transaction.SIGHASH_SINGLE &&
|
442 | inIndex < this.outs.length
|
443 | ) {
|
444 | const output = this.outs[inIndex];
|
445 | tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script));
|
446 | bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
|
447 | bufferWriter.writeUInt64(output.value);
|
448 | bufferWriter.writeVarSlice(output.script);
|
449 | hashOutputs = bcrypto.hash256(tbuffer);
|
450 | }
|
451 | tbuffer = Buffer.allocUnsafe(156 + varSliceSize(prevOutScript));
|
452 | bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
|
453 | const input = this.ins[inIndex];
|
454 | bufferWriter.writeInt32(this.version);
|
455 | bufferWriter.writeSlice(hashPrevouts);
|
456 | bufferWriter.writeSlice(hashSequence);
|
457 | bufferWriter.writeSlice(input.hash);
|
458 | bufferWriter.writeUInt32(input.index);
|
459 | bufferWriter.writeVarSlice(prevOutScript);
|
460 | bufferWriter.writeUInt64(value);
|
461 | bufferWriter.writeUInt32(input.sequence);
|
462 | bufferWriter.writeSlice(hashOutputs);
|
463 | bufferWriter.writeUInt32(this.locktime);
|
464 | bufferWriter.writeUInt32(hashType);
|
465 | return bcrypto.hash256(tbuffer);
|
466 | }
|
467 | getHash(forWitness) {
|
468 |
|
469 | if (forWitness && this.isCoinbase()) return Buffer.alloc(32, 0);
|
470 | return bcrypto.hash256(this.__toBuffer(undefined, undefined, forWitness));
|
471 | }
|
472 | getId() {
|
473 |
|
474 | return (0, bufferutils_1.reverseBuffer)(this.getHash(false)).toString(
|
475 | 'hex',
|
476 | );
|
477 | }
|
478 | toBuffer(buffer, initialOffset) {
|
479 | return this.__toBuffer(buffer, initialOffset, true);
|
480 | }
|
481 | toHex() {
|
482 | return this.toBuffer(undefined, undefined).toString('hex');
|
483 | }
|
484 | setInputScript(index, scriptSig) {
|
485 | typeforce(types.tuple(types.Number, types.Buffer), arguments);
|
486 | this.ins[index].script = scriptSig;
|
487 | }
|
488 | setWitness(index, witness) {
|
489 | typeforce(types.tuple(types.Number, [types.Buffer]), arguments);
|
490 | this.ins[index].witness = witness;
|
491 | }
|
492 | __toBuffer(buffer, initialOffset, _ALLOW_WITNESS = false) {
|
493 | if (!buffer) buffer = Buffer.allocUnsafe(this.byteLength(_ALLOW_WITNESS));
|
494 | const bufferWriter = new bufferutils_1.BufferWriter(
|
495 | buffer,
|
496 | initialOffset || 0,
|
497 | );
|
498 | bufferWriter.writeInt32(this.version);
|
499 | const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses();
|
500 | if (hasWitnesses) {
|
501 | bufferWriter.writeUInt8(Transaction.ADVANCED_TRANSACTION_MARKER);
|
502 | bufferWriter.writeUInt8(Transaction.ADVANCED_TRANSACTION_FLAG);
|
503 | }
|
504 | bufferWriter.writeVarInt(this.ins.length);
|
505 | this.ins.forEach(txIn => {
|
506 | bufferWriter.writeSlice(txIn.hash);
|
507 | bufferWriter.writeUInt32(txIn.index);
|
508 | bufferWriter.writeVarSlice(txIn.script);
|
509 | bufferWriter.writeUInt32(txIn.sequence);
|
510 | });
|
511 | bufferWriter.writeVarInt(this.outs.length);
|
512 | this.outs.forEach(txOut => {
|
513 | if (isOutput(txOut)) {
|
514 | bufferWriter.writeUInt64(txOut.value);
|
515 | } else {
|
516 | bufferWriter.writeSlice(txOut.valueBuffer);
|
517 | }
|
518 | bufferWriter.writeVarSlice(txOut.script);
|
519 | });
|
520 | if (hasWitnesses) {
|
521 | this.ins.forEach(input => {
|
522 | bufferWriter.writeVector(input.witness);
|
523 | });
|
524 | }
|
525 | bufferWriter.writeUInt32(this.locktime);
|
526 |
|
527 | if (initialOffset !== undefined)
|
528 | return buffer.slice(initialOffset, bufferWriter.offset);
|
529 | return buffer;
|
530 | }
|
531 | }
|
532 | exports.Transaction = Transaction;
|
533 | Transaction.DEFAULT_SEQUENCE = 0xffffffff;
|
534 | Transaction.SIGHASH_DEFAULT = 0x00;
|
535 | Transaction.SIGHASH_ALL = 0x01;
|
536 | Transaction.SIGHASH_NONE = 0x02;
|
537 | Transaction.SIGHASH_SINGLE = 0x03;
|
538 | Transaction.SIGHASH_ANYONECANPAY = 0x80;
|
539 | Transaction.SIGHASH_OUTPUT_MASK = 0x03;
|
540 | Transaction.SIGHASH_INPUT_MASK = 0x80;
|
541 | Transaction.ADVANCED_TRANSACTION_MARKER = 0x00;
|
542 | Transaction.ADVANCED_TRANSACTION_FLAG = 0x01;
|