UNPKG

255 kBJavaScriptView Raw
1import _Aes from 'aes';
2import _Bn from 'bn.js';
3import bs58 from 'bs58';
4import elliptic from 'bitcoin-elliptic';
5import hashjs from 'hash.js';
6import pbkdf2 from 'pbkdf2';
7import isHex from 'is-hex';
8import randomBytes from 'randombytes';
9
10var version = "2.0.3";
11
12function Bn(n, base, ...rest) {
13 if (!(this instanceof Bn)) {
14 return new Bn(n, base, ...rest);
15 }
16
17 _Bn.call(this, n, base, ...rest);
18}
19
20Object.keys(_Bn).forEach(function (key) {
21 Bn[key] = _Bn[key];
22});
23Bn.prototype = Object.create(_Bn.prototype);
24Bn.prototype.constructor = Bn;
25
26function reverseBuf(buf) {
27 const buf2 = Buffer.alloc(buf.length);
28
29 for (let i = 0; i < buf.length; i++) {
30 buf2[i] = buf[buf.length - 1 - i];
31 }
32
33 return buf2;
34}
35
36Bn.prototype.fromHex = function (hex, opts) {
37 return this.fromBuffer(Buffer.from(hex, 'hex'), opts);
38};
39
40Bn.prototype.toHex = function (opts) {
41 return this.toBuffer(opts).toString('hex');
42};
43
44Bn.prototype.toJSON = function () {
45 return this.toString();
46};
47
48Bn.prototype.fromJSON = function (str) {
49 const bn = Bn(str);
50 bn.copy(this);
51 return this;
52};
53
54Bn.prototype.fromNumber = function (n) {
55 const bn = Bn(n);
56 bn.copy(this);
57 return this;
58};
59
60Bn.prototype.toNumber = function () {
61 return parseInt(this.toString(10), 10);
62};
63
64Bn.prototype.fromString = function (str, base) {
65 const bn = Bn(str, base);
66 bn.copy(this);
67 return this;
68};
69
70Bn.fromBuffer = function (buf, opts = {
71 endian: 'big'
72}) {
73 if (opts.endian === 'little') {
74 buf = reverseBuf(buf);
75 }
76
77 const hex = buf.toString('hex');
78 const bn = new Bn(hex, 16);
79 return bn;
80};
81
82Bn.prototype.fromBuffer = function (buf, opts) {
83 const bn = Bn.fromBuffer(buf, opts);
84 bn.copy(this);
85 return this;
86};
87
88Bn.prototype.toBuffer = function (opts = {
89 size: undefined,
90 endian: 'big'
91}) {
92 let buf;
93
94 if (opts.size) {
95 const hex = this.toString(16, 2);
96 const natlen = hex.length / 2;
97 buf = Buffer.from(hex, 'hex');
98
99 if (natlen === opts.size) ; else if (natlen > opts.size) {
100 buf = buf.slice(natlen - buf.length, buf.length);
101 } else if (natlen < opts.size) {
102 const rbuf = Buffer.alloc(opts.size);
103
104 for (let i = 0; i < buf.length; i++) {
105 rbuf[rbuf.length - 1 - i] = buf[buf.length - 1 - i];
106 }
107
108 for (let i = 0; i < opts.size - natlen; i++) {
109 rbuf[i] = 0;
110 }
111
112 buf = rbuf;
113 }
114 } else {
115 const hex = this.toString(16, 2);
116 buf = Buffer.from(hex, 'hex');
117 }
118
119 if (opts.endian === 'little') {
120 buf = reverseBuf(buf);
121 }
122
123 const longzero = Buffer.from([0]);
124
125 if (Buffer.compare(buf, longzero) === 0) {
126 return Buffer.from([]);
127 }
128
129 return buf;
130};
131
132Bn.prototype.toFastBuffer = Bn.prototype.toBuffer;
133Bn.fromFastBuffer = Bn.fromBuffer;
134Bn.prototype.fromFastBuffer = Bn.prototype.fromBuffer;
135
136Bn.prototype.fromSm = function (buf, opts = {
137 endian: 'big'
138}) {
139 if (buf.length === 0) {
140 this.fromBuffer(Buffer.from([0]));
141 }
142
143 const endian = opts.endian;
144
145 if (endian === 'little') {
146 buf = reverseBuf(buf);
147 }
148
149 if (buf[0] & 0x80) {
150 buf[0] = buf[0] & 0x7f;
151 this.fromBuffer(buf);
152 this.neg().copy(this);
153 } else {
154 this.fromBuffer(buf);
155 }
156
157 return this;
158};
159
160Bn.prototype.toSm = function (opts = {
161 endian: 'big'
162}) {
163 const endian = opts.endian;
164 let buf;
165
166 if (this.cmp(0) === -1) {
167 buf = this.neg().toBuffer();
168
169 if (buf[0] & 0x80) {
170 buf = Buffer.concat([Buffer.from([0x80]), buf]);
171 } else {
172 buf[0] = buf[0] | 0x80;
173 }
174 } else {
175 buf = this.toBuffer();
176
177 if (buf[0] & 0x80) {
178 buf = Buffer.concat([Buffer.from([0x00]), buf]);
179 }
180 }
181
182 if (buf.length === 1 & buf[0] === 0) {
183 buf = Buffer.from([]);
184 }
185
186 if (endian === 'little') {
187 buf = reverseBuf(buf);
188 }
189
190 return buf;
191};
192
193Bn.prototype.fromBits = function (bits, opts = {
194 strict: false
195}) {
196 let buf = Buffer.alloc(4);
197 buf.writeUInt32BE(bits, 0);
198 bits = buf.readInt32BE(0);
199
200 if (opts.strict && bits & 0x00800000) {
201 throw new Error('negative bit set');
202 }
203
204 const nsize = bits >> 24;
205 const nword = bits & 0x007fffff;
206 buf = Buffer.alloc(4);
207 buf.writeInt32BE(nword);
208
209 if (nsize <= 3) {
210 buf = buf.slice(1, nsize + 1);
211 } else {
212 const fill = Buffer.alloc(nsize - 3);
213 fill.fill(0);
214 buf = Buffer.concat([buf, fill]);
215 }
216
217 this.fromBuffer(buf);
218
219 if (bits & 0x00800000) {
220 Bn(0).sub(this).copy(this);
221 }
222
223 return this;
224};
225
226Bn.prototype.toBits = function () {
227 let buf;
228
229 if (this.lt(0)) {
230 buf = this.neg().toBuffer();
231 } else {
232 buf = this.toBuffer();
233 }
234
235 let nsize = buf.length;
236 let nword;
237
238 if (nsize > 3) {
239 nword = Buffer.concat([Buffer.from([0]), buf.slice(0, 3)]).readUInt32BE(0);
240 } else if (nsize <= 3) {
241 const blank = Buffer.alloc(3 - nsize + 1);
242 blank.fill(0);
243 nword = Buffer.concat([blank, buf.slice(0, nsize)]).readUInt32BE(0);
244 }
245
246 if (nword & 0x00800000) {
247 nword >>= 8;
248 nsize++;
249 }
250
251 if (this.lt(0)) {
252 nword |= 0x00800000;
253 }
254
255 const bits = nsize << 24 | nword;
256 buf = Buffer.alloc(4);
257 buf.writeInt32BE(bits, 0);
258 return buf.readUInt32BE(0);
259};
260
261Bn.prototype.fromScriptNumBuffer = function (buf, fRequireMinimal, nMaxNumSize) {
262 if (nMaxNumSize === undefined) {
263 nMaxNumSize = 4;
264 }
265
266 if (buf.length > nMaxNumSize) {
267 throw new Error('script number overflow');
268 }
269
270 if (fRequireMinimal && buf.length > 0) {
271 if ((buf[buf.length - 1] & 0x7f) === 0) {
272 if (buf.length <= 1 || (buf[buf.length - 2] & 0x80) === 0) {
273 throw new Error('non-minimally encoded script number');
274 }
275 }
276 }
277
278 return this.fromSm(buf, {
279 endian: 'little'
280 });
281};
282
283Bn.prototype.toScriptNumBuffer = function (buf) {
284 return this.toSm({
285 endian: 'little'
286 });
287};
288
289Bn.prototype.neg = function () {
290 const _neg = _Bn.prototype.neg.call(this);
291
292 const neg = Object.create(Bn.prototype);
293
294 _neg.copy(neg);
295
296 return neg;
297};
298
299Bn.prototype.add = function (bn) {
300 const _bn = _Bn.prototype.add.call(this, bn);
301
302 bn = Object.create(Bn.prototype);
303
304 _bn.copy(bn);
305
306 return bn;
307};
308
309Bn.prototype.sub = function (bn) {
310 const _bn = _Bn.prototype.sub.call(this, bn);
311
312 bn = Object.create(Bn.prototype);
313
314 _bn.copy(bn);
315
316 return bn;
317};
318
319Bn.prototype.mul = function (bn) {
320 const _bn = _Bn.prototype.mul.call(this, bn);
321
322 bn = Object.create(Bn.prototype);
323
324 _bn.copy(bn);
325
326 return bn;
327};
328
329Bn.prototype.mod = function (bn) {
330 const _bn = _Bn.prototype.mod.call(this, bn);
331
332 bn = Object.create(Bn.prototype);
333
334 _bn.copy(bn);
335
336 return bn;
337};
338
339Bn.prototype.umod = function (bn) {
340 const _bn = _Bn.prototype.umod.call(this, bn);
341
342 bn = Object.create(Bn.prototype);
343
344 _bn.copy(bn);
345
346 return bn;
347};
348
349Bn.prototype.invm = function (bn) {
350 const _bn = _Bn.prototype.invm.call(this, bn);
351
352 bn = Object.create(Bn.prototype);
353
354 _bn.copy(bn);
355
356 return bn;
357};
358
359Bn.prototype.div = function (bn) {
360 const _bn = _Bn.prototype.div.call(this, bn);
361
362 bn = Object.create(Bn.prototype);
363
364 _bn.copy(bn);
365
366 return bn;
367};
368
369Bn.prototype.ushln = function (bits) {
370 const _bn = _Bn.prototype.ushln.call(this, bits);
371
372 const bn = Object.create(Bn.prototype);
373
374 _bn.copy(bn);
375
376 return bn;
377};
378
379Bn.prototype.ushrn = function (bits) {
380 const _bn = _Bn.prototype.ushrn.call(this, bits);
381
382 const bn = Object.create(Bn.prototype);
383
384 _bn.copy(bn);
385
386 return bn;
387};
388
389Bn.prototype.cmp = function (bn) {
390 return _Bn.prototype.cmp.call(this, bn);
391};
392
393function decorate(name) {
394 Bn.prototype['_' + name] = Bn.prototype[name];
395
396 const f = function (b) {
397 if (typeof b === 'string') {
398 b = new Bn(b);
399 } else if (typeof b === 'number') {
400 b = new Bn(b.toString());
401 }
402
403 return this['_' + name](b);
404 };
405
406 Bn.prototype[name] = f;
407}
408
409Bn.prototype.eq = function (b) {
410 return this.cmp(b) === 0;
411};
412
413Bn.prototype.neq = function (b) {
414 return this.cmp(b) !== 0;
415};
416
417Bn.prototype.gt = function (b) {
418 return this.cmp(b) > 0;
419};
420
421Bn.prototype.geq = function (b) {
422 return this.cmp(b) >= 0;
423};
424
425Bn.prototype.lt = function (b) {
426 return this.cmp(b) < 0;
427};
428
429Bn.prototype.leq = function (b) {
430 return this.cmp(b) <= 0;
431};
432
433decorate('add');
434decorate('sub');
435decorate('mul');
436decorate('mod');
437decorate('invm');
438decorate('div');
439decorate('cmp');
440decorate('gt');
441decorate('geq');
442decorate('lt');
443decorate('leq');
444
445class Br {
446 constructor(buf) {
447 this.fromObject({
448 buf
449 });
450 }
451
452 fromObject(obj) {
453 this.buf = obj.buf || this.buf || undefined;
454 this.pos = obj.pos || this.pos || 0;
455 return this;
456 }
457
458 eof() {
459 return this.pos >= this.buf.length;
460 }
461
462 read(len = this.buf.length) {
463 const buf = this.buf.slice(this.pos, this.pos + len);
464 this.pos = this.pos + len;
465 return buf;
466 }
467
468 readReverse(len = this.buf.length) {
469 const buf = this.buf.slice(this.pos, this.pos + len);
470 this.pos = this.pos + len;
471 const buf2 = Buffer.alloc(buf.length);
472
473 for (let i = 0; i < buf2.length; i++) {
474 buf2[i] = buf[buf.length - 1 - i];
475 }
476
477 return buf2;
478 }
479
480 readUInt8() {
481 const val = this.buf.readUInt8(this.pos);
482 this.pos = this.pos + 1;
483 return val;
484 }
485
486 readInt8() {
487 const val = this.buf.readInt8(this.pos);
488 this.pos = this.pos + 1;
489 return val;
490 }
491
492 readUInt16BE() {
493 const val = this.buf.readUInt16BE(this.pos);
494 this.pos = this.pos + 2;
495 return val;
496 }
497
498 readInt16BE() {
499 const val = this.buf.readInt16BE(this.pos);
500 this.pos = this.pos + 2;
501 return val;
502 }
503
504 readUInt16LE() {
505 const val = this.buf.readUInt16LE(this.pos);
506 this.pos = this.pos + 2;
507 return val;
508 }
509
510 readInt16LE() {
511 const val = this.buf.readInt16LE(this.pos);
512 this.pos = this.pos + 2;
513 return val;
514 }
515
516 readUInt32BE() {
517 const val = this.buf.readUInt32BE(this.pos);
518 this.pos = this.pos + 4;
519 return val;
520 }
521
522 readInt32BE() {
523 const val = this.buf.readInt32BE(this.pos);
524 this.pos = this.pos + 4;
525 return val;
526 }
527
528 readUInt32LE() {
529 const val = this.buf.readUInt32LE(this.pos);
530 this.pos = this.pos + 4;
531 return val;
532 }
533
534 readInt32LE() {
535 const val = this.buf.readInt32LE(this.pos);
536 this.pos = this.pos + 4;
537 return val;
538 }
539
540 readUInt64BEBn() {
541 const buf = this.buf.slice(this.pos, this.pos + 8);
542 const bn = new Bn().fromBuffer(buf);
543 this.pos = this.pos + 8;
544 return bn;
545 }
546
547 readUInt64LEBn() {
548 const buf = this.readReverse(8);
549 const bn = new Bn().fromBuffer(buf);
550 return bn;
551 }
552
553 readVarIntNum() {
554 const first = this.readUInt8();
555 let bn, n;
556
557 switch (first) {
558 case 0xfd:
559 return this.readUInt16LE();
560
561 case 0xfe:
562 return this.readUInt32LE();
563
564 case 0xff:
565 bn = this.readUInt64LEBn();
566 n = bn.toNumber();
567
568 if (n <= Math.pow(2, 53)) {
569 return n;
570 } else {
571 throw new Error('number too large to retain precision - use readVarIntBn');
572 }
573
574 default:
575 return first;
576 }
577 }
578
579 readVarIntBuf() {
580 const first = this.buf.readUInt8(this.pos);
581
582 switch (first) {
583 case 0xfd:
584 return this.read(1 + 2);
585
586 case 0xfe:
587 return this.read(1 + 4);
588
589 case 0xff:
590 return this.read(1 + 8);
591
592 default:
593 return this.read(1);
594 }
595 }
596
597 readVarIntBn() {
598 const first = this.readUInt8();
599
600 switch (first) {
601 case 0xfd:
602 return new Bn(this.readUInt16LE());
603
604 case 0xfe:
605 return new Bn(this.readUInt32LE());
606
607 case 0xff:
608 return this.readUInt64LEBn();
609
610 default:
611 return new Bn(first);
612 }
613 }
614
615}
616
617class Bw {
618 constructor(bufs) {
619 this.fromObject({
620 bufs
621 });
622 }
623
624 fromObject(obj) {
625 this.bufs = obj.bufs || this.bufs || [];
626 return this;
627 }
628
629 getLength() {
630 let len = 0;
631
632 for (const i in this.bufs) {
633 const buf = this.bufs[i];
634 len = len + buf.length;
635 }
636
637 return len;
638 }
639
640 toBuffer() {
641 return Buffer.concat(this.bufs);
642 }
643
644 write(buf) {
645 this.bufs.push(buf);
646 return this;
647 }
648
649 writeReverse(buf) {
650 const buf2 = Buffer.alloc(buf.length);
651
652 for (let i = 0; i < buf2.length; i++) {
653 buf2[i] = buf[buf.length - 1 - i];
654 }
655
656 this.bufs.push(buf2);
657 return this;
658 }
659
660 writeUInt8(n) {
661 const buf = Buffer.alloc(1);
662 buf.writeUInt8(n, 0);
663 this.write(buf);
664 return this;
665 }
666
667 writeInt8(n) {
668 const buf = Buffer.alloc(1);
669 buf.writeInt8(n, 0);
670 this.write(buf);
671 return this;
672 }
673
674 writeUInt16BE(n) {
675 const buf = Buffer.alloc(2);
676 buf.writeUInt16BE(n, 0);
677 this.write(buf);
678 return this;
679 }
680
681 writeInt16BE(n) {
682 const buf = Buffer.alloc(2);
683 buf.writeInt16BE(n, 0);
684 this.write(buf);
685 return this;
686 }
687
688 writeUInt16LE(n) {
689 const buf = Buffer.alloc(2);
690 buf.writeUInt16LE(n, 0);
691 this.write(buf);
692 return this;
693 }
694
695 writeInt16LE(n) {
696 const buf = Buffer.alloc(2);
697 buf.writeInt16LE(n, 0);
698 this.write(buf);
699 return this;
700 }
701
702 writeUInt32BE(n) {
703 const buf = Buffer.alloc(4);
704 buf.writeUInt32BE(n, 0);
705 this.write(buf);
706 return this;
707 }
708
709 writeInt32BE(n) {
710 const buf = Buffer.alloc(4);
711 buf.writeInt32BE(n, 0);
712 this.write(buf);
713 return this;
714 }
715
716 writeUInt32LE(n) {
717 const buf = Buffer.alloc(4);
718 buf.writeUInt32LE(n, 0);
719 this.write(buf);
720 return this;
721 }
722
723 writeInt32LE(n) {
724 const buf = Buffer.alloc(4);
725 buf.writeInt32LE(n, 0);
726 this.write(buf);
727 return this;
728 }
729
730 writeUInt64BEBn(bn) {
731 const buf = bn.toBuffer({
732 size: 8
733 });
734 this.write(buf);
735 return this;
736 }
737
738 writeUInt64LEBn(bn) {
739 const buf = bn.toBuffer({
740 size: 8
741 });
742 this.writeReverse(buf);
743 return this;
744 }
745
746 writeVarIntNum(n) {
747 const buf = Bw.varIntBufNum(n);
748 this.write(buf);
749 return this;
750 }
751
752 writeVarIntBn(bn) {
753 const buf = Bw.varIntBufBn(bn);
754 this.write(buf);
755 return this;
756 }
757
758 static varIntBufNum(n) {
759 let buf;
760
761 if (n < 253) {
762 buf = Buffer.alloc(1);
763 buf.writeUInt8(n, 0);
764 } else if (n < 0x10000) {
765 buf = Buffer.alloc(1 + 2);
766 buf.writeUInt8(253, 0);
767 buf.writeUInt16LE(n, 1);
768 } else if (n < 0x100000000) {
769 buf = Buffer.alloc(1 + 4);
770 buf.writeUInt8(254, 0);
771 buf.writeUInt32LE(n, 1);
772 } else {
773 buf = Buffer.alloc(1 + 8);
774 buf.writeUInt8(255, 0);
775 buf.writeInt32LE(n & -1, 1);
776 buf.writeUInt32LE(Math.floor(n / 0x100000000), 5);
777 }
778
779 return buf;
780 }
781
782 static varIntBufBn(bn) {
783 let buf;
784 const n = bn.toNumber();
785
786 if (n < 253) {
787 buf = Buffer.alloc(1);
788 buf.writeUInt8(n, 0);
789 } else if (n < 0x10000) {
790 buf = Buffer.alloc(1 + 2);
791 buf.writeUInt8(253, 0);
792 buf.writeUInt16LE(n, 1);
793 } else if (n < 0x100000000) {
794 buf = Buffer.alloc(1 + 4);
795 buf.writeUInt8(254, 0);
796 buf.writeUInt32LE(n, 1);
797 } else {
798 const bw = new Bw();
799 bw.writeUInt8(255);
800 bw.writeUInt64LEBn(bn);
801 buf = bw.toBuffer();
802 }
803
804 return buf;
805 }
806
807}
808
809class Struct {
810 constructor(obj) {
811 this.fromObject(obj);
812 }
813
814 fromObject(obj) {
815 if (!obj) {
816 return this;
817 }
818
819 for (const key of Object.keys(obj)) {
820 if (obj[key] !== undefined) {
821 this[key] = obj[key];
822 }
823 }
824
825 return this;
826 }
827
828 static fromObject(obj) {
829 return new this().fromObject(obj);
830 }
831
832 fromBr(br) {
833 if (!(br instanceof Br)) {
834 throw new Error('br must be a buffer reader');
835 }
836
837 throw new Error('not implemented');
838 }
839
840 static fromBr(br) {
841 return new this().fromBr(br);
842 }
843
844 asyncFromBr(br) {
845 if (!(br instanceof Br)) {
846 throw new Error('br must be a buffer reader');
847 }
848
849 throw new Error('not implemented');
850 }
851
852 static asyncFromBr(br) {
853 return new this().asyncFromBr(br);
854 }
855
856 toBw(bw) {
857 throw new Error('not implemented');
858 }
859
860 asyncToBw(bw) {
861 throw new Error('not implemented');
862 }
863
864 *genFromBuffers() {
865 throw new Error('not implemented');
866 }
867
868 *expect(len, startbuf) {
869 let buf = startbuf;
870 const bw = new Bw();
871 let gotlen = 0;
872
873 if (startbuf) {
874 bw.write(startbuf);
875 gotlen += startbuf.length;
876 }
877
878 while (gotlen < len) {
879 const remainderlen = len - gotlen;
880 buf = yield remainderlen;
881
882 if (!buf) {
883 continue;
884 }
885
886 bw.write(buf);
887 gotlen += buf.length;
888 }
889
890 buf = bw.toBuffer();
891 const overlen = gotlen - len;
892 const remainderbuf = buf.slice(buf.length - overlen, buf.length);
893 buf = buf.slice(0, buf.length - overlen);
894 return {
895 buf: buf,
896 remainderbuf: remainderbuf
897 };
898 }
899
900 fromBuffer(buf, ...rest) {
901 if (!Buffer.isBuffer(buf)) {
902 throw new Error('buf must be a buffer');
903 }
904
905 const br = new Br(buf);
906 return this.fromBr(br, ...rest);
907 }
908
909 static fromBuffer(...rest) {
910 return new this().fromBuffer(...rest);
911 }
912
913 asyncFromBuffer(buf, ...rest) {
914 if (!Buffer.isBuffer(buf)) {
915 throw new Error('buf must be a buffer');
916 }
917
918 const br = new Br(buf);
919 return this.asyncFromBr(br, ...rest);
920 }
921
922 static asyncFromBuffer(buf, ...rest) {
923 return new this().asyncFromBuffer(buf, ...rest);
924 }
925
926 fromFastBuffer(buf, ...rest) {
927 if (buf.length === 0) {
928 return this;
929 } else {
930 return this.fromBuffer(buf, ...rest);
931 }
932 }
933
934 static fromFastBuffer(...rest) {
935 return new this().fromFastBuffer(...rest);
936 }
937
938 toBuffer(...rest) {
939 return this.toBw(...rest).toBuffer();
940 }
941
942 asyncToBuffer(...rest) {
943 return this.asyncToBw(...rest).then(bw => bw.toBuffer());
944 }
945
946 toFastBuffer(...rest) {
947 if (Object.keys(this).length === 0) {
948 return Buffer.alloc(0);
949 } else {
950 return this.toBuffer(...rest);
951 }
952 }
953
954 fromHex(hex, ...rest) {
955 if (!isHex(hex)) {
956 throw new Error('invalid hex string');
957 }
958
959 const buf = Buffer.from(hex, 'hex');
960 return this.fromBuffer(buf, ...rest);
961 }
962
963 static fromHex(hex, ...rest) {
964 return new this().fromHex(hex, ...rest);
965 }
966
967 asyncFromHex(hex, ...rest) {
968 if (!isHex(hex)) {
969 throw new Error('invalid hex string');
970 }
971
972 const buf = Buffer.from(hex, 'hex');
973 return this.asyncFromBuffer(buf, ...rest);
974 }
975
976 static asyncFromHex(hex, ...rest) {
977 return new this().asyncFromHex(hex, ...rest);
978 }
979
980 fromFastHex(hex, ...rest) {
981 if (!isHex(hex)) {
982 throw new Error('invalid hex string');
983 }
984
985 const buf = Buffer.from(hex, 'hex');
986 return this.fromFastBuffer(buf, ...rest);
987 }
988
989 static fromFastHex(hex, ...rest) {
990 return new this().fromFastHex(hex, ...rest);
991 }
992
993 toHex(...rest) {
994 return this.toBuffer(...rest).toString('hex');
995 }
996
997 asyncToHex(...rest) {
998 return this.asyncToBuffer(...rest).then(buf => buf.toString('hex'));
999 }
1000
1001 toFastHex(...rest) {
1002 return this.toFastBuffer(...rest).toString('hex');
1003 }
1004
1005 fromString(str, ...rest) {
1006 if (typeof str !== 'string') {
1007 throw new Error('str must be a string');
1008 }
1009
1010 return this.fromHex(str, ...rest);
1011 }
1012
1013 static fromString(str, ...rest) {
1014 return new this().fromString(str, ...rest);
1015 }
1016
1017 asyncFromString(str, ...rest) {
1018 if (typeof str !== 'string') {
1019 throw new Error('str must be a string');
1020 }
1021
1022 return this.asyncFromHex(str, ...rest);
1023 }
1024
1025 static asyncFromString(str, ...rest) {
1026 return new this().asyncFromString(str, ...rest);
1027 }
1028
1029 toString(...rest) {
1030 return this.toHex(...rest);
1031 }
1032
1033 asyncToString(...rest) {
1034 return this.asyncToHex(...rest);
1035 }
1036
1037 fromJSON(json) {
1038 throw new Error('not implemented');
1039 }
1040
1041 static fromJSON(json, ...rest) {
1042 return new this().fromJSON(json, ...rest);
1043 }
1044
1045 asyncFromJSON(json, ...rest) {
1046 throw new Error('not implemented');
1047 }
1048
1049 static asyncFromJSON(json, ...rest) {
1050 return new this().asyncFromJSON(json, ...rest);
1051 }
1052
1053 toJSON() {
1054 var json = {};
1055
1056 for (var val in this) {
1057 if (Array.isArray(this[val])) {
1058 const arr = [];
1059
1060 for (var i in this[val]) {
1061 if (typeof this[val][i].toJSON === 'function') {
1062 arr.push(this[val][i].toJSON());
1063 } else {
1064 arr.push(JSON.stringify(this[val][i]));
1065 }
1066 }
1067
1068 json[val] = arr;
1069 } else if (this[val] === null) {
1070 json[val] = this[val];
1071 } else if (typeof this[val] === 'object' && typeof this[val].toJSON === 'function') {
1072 json[val] = this[val].toJSON();
1073 } else if (typeof this[val] === 'boolean' || typeof this[val] === 'number' || typeof this[val] === 'string') {
1074 json[val] = this[val];
1075 } else if (Buffer.isBuffer(this[val])) {
1076 json[val] = this[val].toString('hex');
1077 } else if (this[val] instanceof Map) {
1078 json[val] = JSON.stringify(this[val]);
1079 } else if (typeof this[val] === 'object') {
1080 throw new Error('not implemented');
1081 }
1082 }
1083
1084 return json;
1085 }
1086
1087 asyncToJSON() {
1088 throw new Error('not implemented');
1089 }
1090
1091 clone() {
1092 return this.cloneByJSON();
1093 }
1094
1095 cloneByBuffer() {
1096 return new this.constructor().fromBuffer(this.toBuffer());
1097 }
1098
1099 cloneByFastBuffer() {
1100 return new this.constructor().fromFastBuffer(this.toFastBuffer());
1101 }
1102
1103 cloneByHex() {
1104 return new this.constructor().fromHex(this.toHex());
1105 }
1106
1107 cloneByString() {
1108 return new this.constructor().fromString(this.toString());
1109 }
1110
1111 cloneByJSON() {
1112 return new this.constructor().fromJSON(this.toJSON());
1113 }
1114
1115}
1116
1117class Base58 extends Struct {
1118 constructor(buf) {
1119 super({
1120 buf
1121 });
1122 }
1123
1124 fromHex(hex) {
1125 return this.fromBuffer(Buffer.from(hex, 'hex'));
1126 }
1127
1128 toHex() {
1129 return this.toBuffer().toString('hex');
1130 }
1131
1132 static encode(buf) {
1133 if (!Buffer.isBuffer(buf)) {
1134 throw new Error('Input should be a buffer');
1135 }
1136
1137 return bs58.encode(buf);
1138 }
1139
1140 static decode(str) {
1141 if (typeof str !== 'string') {
1142 throw new Error('Input should be a string');
1143 }
1144
1145 return Buffer.from(bs58.decode(str));
1146 }
1147
1148 fromBuffer(buf) {
1149 this.buf = buf;
1150 return this;
1151 }
1152
1153 fromString(str) {
1154 const buf = Base58.decode(str);
1155 this.buf = buf;
1156 return this;
1157 }
1158
1159 toBuffer() {
1160 return this.buf;
1161 }
1162
1163 toString() {
1164 return Base58.encode(this.buf);
1165 }
1166
1167}
1168
1169const cmp = (buf1, buf2) => {
1170 if (!Buffer.isBuffer(buf1) || !Buffer.isBuffer(buf2)) {
1171 throw new Error('buf1 and buf2 must be buffers');
1172 }
1173
1174 if (buf1.length !== buf2.length) {
1175 return false;
1176 }
1177
1178 let d = 0;
1179
1180 for (let i = 0; i < buf1.length; i++) {
1181 const x = buf1[i];
1182 const y = buf2[i];
1183 d |= x ^ y;
1184 }
1185
1186 return d === 0;
1187};
1188
1189class WorkersResult extends Struct {
1190 constructor(resbuf, isError, id) {
1191 super({
1192 resbuf,
1193 isError,
1194 id
1195 });
1196 }
1197
1198 fromResult(result, id) {
1199 if (result.toFastBuffer) {
1200 this.resbuf = result.toFastBuffer();
1201 } else if (Buffer.isBuffer(result)) {
1202 this.resbuf = result;
1203 } else {
1204 this.resbuf = Buffer.from(JSON.stringify(result));
1205 }
1206
1207 this.isError = false;
1208 this.id = id;
1209 return this;
1210 }
1211
1212 static fromResult(result, id) {
1213 return new this().fromResult(result, id);
1214 }
1215
1216 fromError(error, id) {
1217 this.resbuf = Buffer.from(JSON.stringify(error.message));
1218 this.isError = true;
1219 this.id = id;
1220 return this;
1221 }
1222
1223 toBw(bw) {
1224 if (!bw) {
1225 bw = new Bw();
1226 }
1227
1228 bw.writeVarIntNum(this.resbuf.length);
1229 bw.write(this.resbuf);
1230 bw.writeUInt8(Number(this.isError));
1231 bw.writeVarIntNum(this.id);
1232 return bw;
1233 }
1234
1235 fromBr(br) {
1236 const resbuflen = br.readVarIntNum();
1237 this.resbuf = br.read(resbuflen);
1238 this.isError = Boolean(br.readUInt8());
1239 this.id = br.readVarIntNum();
1240 return this;
1241 }
1242
1243}
1244
1245let globalWorkers;
1246
1247class Workers {
1248 constructor(nativeWorkers = [], lastid = 0, incompconsteRes = [], promisemap = new Map()) {
1249 this.nativeWorkers = nativeWorkers;
1250 this.lastid = lastid;
1251 this.incompconsteRes = incompconsteRes;
1252 this.promisemap = promisemap;
1253 }
1254
1255 asyncObjectMethod(obj, methodname, args, id = this.lastid + 1) {
1256 if (!args) {
1257 throw new Error('must specify args');
1258 }
1259
1260 const result = obj[methodname](...args);
1261 const workersResult = new WorkersResult().fromResult(result, id);
1262 return workersResult;
1263 }
1264
1265 static asyncObjectMethod(obj, methodname, args, id) {
1266 if (!globalWorkers) {
1267 globalWorkers = new Workers();
1268 }
1269
1270 return globalWorkers.asyncObjectMethod(obj, methodname, args, id);
1271 }
1272
1273 asyncClassMethod(classObj, methodname, args, id = this.lastid + 1) {
1274 if (!args) {
1275 throw new Error('must specify args');
1276 }
1277
1278 const result = classObj[methodname](...args);
1279 const workersResult = new WorkersResult().fromResult(result, id);
1280 return workersResult;
1281 }
1282
1283 static asyncClassMethod(classObj, methodname, args, id) {
1284 if (!globalWorkers) {
1285 globalWorkers = new Workers();
1286 }
1287
1288 return globalWorkers.asyncClassMethod(classObj, methodname, args, id);
1289 }
1290
1291 static endGlobalWorkers() {
1292 if (globalWorkers && !process.browser) {
1293 globalWorkers = undefined;
1294 }
1295 }
1296
1297}
1298
1299class Hash {}
1300
1301Hash.sha1 = function (buf) {
1302 if (!Buffer.isBuffer(buf)) {
1303 throw new Error('sha1 hash must be of a buffer');
1304 }
1305
1306 const Sha1 = hashjs.sha1;
1307 const hash = new Sha1().update(buf).digest();
1308 return Buffer.from(hash);
1309};
1310
1311Hash.sha1.blockSize = 512;
1312
1313Hash.asyncSha1 = async function (buf) {
1314 const args = [buf];
1315 const workersResult = await Workers.asyncClassMethod(Hash, 'sha1', args);
1316 return workersResult.resbuf;
1317};
1318
1319Hash.sha256 = function (buf) {
1320 if (!Buffer.isBuffer(buf)) {
1321 throw new Error('sha256 hash must be of a buffer');
1322 }
1323
1324 const Sha256 = hashjs.sha256;
1325 const hash = new Sha256().update(buf).digest();
1326 return Buffer.from(hash);
1327};
1328
1329Hash.sha256.blockSize = 512;
1330
1331Hash.asyncSha256 = async function (buf) {
1332 const args = [buf];
1333 const workersResult = await Workers.asyncClassMethod(Hash, 'sha256', args);
1334 return workersResult.resbuf;
1335};
1336
1337Hash.sha256Sha256 = function (buf) {
1338 try {
1339 return Hash.sha256(Hash.sha256(buf));
1340 } catch (e) {
1341 throw new Error('sha256Sha256 hash must be of a buffer: ' + e);
1342 }
1343};
1344
1345Hash.asyncSha256Sha256 = async function (buf) {
1346 const args = [buf];
1347 const workersResult = await Workers.asyncClassMethod(Hash, 'sha256Sha256', args);
1348 return workersResult.resbuf;
1349};
1350
1351Hash.ripemd160 = function (buf) {
1352 if (!Buffer.isBuffer(buf)) {
1353 throw new Error('ripemd160 hash must be of a buffer');
1354 }
1355
1356 const Ripemd160 = hashjs.ripemd160;
1357 const hash = new Ripemd160().update(buf).digest();
1358 return Buffer.from(hash);
1359};
1360
1361Hash.asyncRipemd160 = async function (buf) {
1362 const args = [buf];
1363 const workersResult = await Workers.asyncClassMethod(Hash, 'ripemd160', args);
1364 return workersResult.resbuf;
1365};
1366
1367Hash.sha256Ripemd160 = function (buf) {
1368 try {
1369 return Hash.ripemd160(Hash.sha256(buf));
1370 } catch (e) {
1371 throw new Error('sha256Ripemd160 hash must be of a buffer: ' + e);
1372 }
1373};
1374
1375Hash.asyncSha256Ripemd160 = async function (buf) {
1376 const args = [buf];
1377 const workersResult = await Workers.asyncClassMethod(Hash, 'sha256Ripemd160', args);
1378 return workersResult.resbuf;
1379};
1380
1381Hash.sha512 = function (buf) {
1382 if (!Buffer.isBuffer(buf)) {
1383 throw new Error('sha512 hash must be of a buffer');
1384 }
1385
1386 const Sha512 = hashjs.sha512;
1387 const hash = new Sha512().update(buf).digest();
1388 return Buffer.from(hash);
1389};
1390
1391Hash.asyncSha512 = async function (buf) {
1392 const args = [buf];
1393 const workersResult = await Workers.asyncClassMethod(Hash, 'sha512', args);
1394 return workersResult.resbuf;
1395};
1396
1397Hash.sha512.blockSize = 1024;
1398
1399Hash.hmac = function (hashFStr, data, key) {
1400 if (hashFStr !== 'sha1' && hashFStr !== 'sha256' && hashFStr !== 'sha512') {
1401 throw new Error('invalid choice of hash function');
1402 }
1403
1404 const hashf = Hash[hashFStr];
1405
1406 if (!Buffer.isBuffer(data) || !Buffer.isBuffer(key)) {
1407 throw new Error('data and key must be buffers');
1408 }
1409
1410 const blockSize = hashf.blockSize / 8;
1411
1412 if (key.length > blockSize) {
1413 key = hashf(key);
1414 }
1415
1416 if (key.length < blockSize) {
1417 const fill = Buffer.alloc(blockSize);
1418 fill.fill(0, key.length);
1419 key.copy(fill);
1420 key = fill;
1421 }
1422
1423 const oKeyPad = Buffer.alloc(blockSize);
1424 const iKeyPad = Buffer.alloc(blockSize);
1425
1426 for (let i = 0; i < blockSize; i++) {
1427 oKeyPad[i] = 0x5c ^ key[i];
1428 iKeyPad[i] = 0x36 ^ key[i];
1429 }
1430
1431 return hashf(Buffer.concat([oKeyPad, hashf(Buffer.concat([iKeyPad, data]))]));
1432};
1433
1434Hash.sha1Hmac = function (data, key) {
1435 return Hash.hmac('sha1', data, key);
1436};
1437
1438Hash.asyncSha1Hmac = async function (data, key) {
1439 const args = [data, key];
1440 const workersResult = await Workers.asyncClassMethod(Hash, 'sha1Hmac', args);
1441 return workersResult.resbuf;
1442};
1443
1444Hash.sha1Hmac.bitsize = 160;
1445
1446Hash.sha256Hmac = function (data, key) {
1447 return Hash.hmac('sha256', data, key);
1448};
1449
1450Hash.asyncSha256Hmac = async function (data, key) {
1451 const args = [data, key];
1452 const workersResult = await Workers.asyncClassMethod(Hash, 'sha256Hmac', args);
1453 return workersResult.resbuf;
1454};
1455
1456Hash.sha256Hmac.bitsize = 256;
1457
1458Hash.sha512Hmac = function (data, key) {
1459 return Hash.hmac('sha512', data, key);
1460};
1461
1462Hash.asyncSha512Hmac = async function (data, key) {
1463 const args = [data, key];
1464 const workersResult = await Workers.asyncClassMethod(Hash, 'sha512Hmac', args);
1465 return workersResult.resbuf;
1466};
1467
1468Hash.sha512Hmac.bitsize = 512;
1469
1470class Base58Check extends Struct {
1471 constructor(buf) {
1472 super({
1473 buf
1474 });
1475 }
1476
1477 fromHex(hex) {
1478 return this.fromBuffer(Buffer.from(hex, 'hex'));
1479 }
1480
1481 toHex() {
1482 return this.toBuffer().toString('hex');
1483 }
1484
1485 static decode(s) {
1486 if (typeof s !== 'string') {
1487 throw new Error('Input must be a string');
1488 }
1489
1490 const buf = Base58.decode(s);
1491
1492 if (buf.length < 4) {
1493 throw new Error('Input string too short');
1494 }
1495
1496 const data = buf.slice(0, -4);
1497 const csum = buf.slice(-4);
1498 const hash = Hash.sha256Sha256(data);
1499 const hash4 = hash.slice(0, 4);
1500
1501 if (!cmp(csum, hash4)) {
1502 throw new Error('Checksum mismatch');
1503 }
1504
1505 return data;
1506 }
1507
1508 static encode(buf) {
1509 if (!Buffer.isBuffer(buf)) {
1510 throw new Error('Input must be a buffer');
1511 }
1512
1513 const checkedBuf = Buffer.alloc(buf.length + 4);
1514 const hash = Hash.sha256Sha256(buf);
1515 buf.copy(checkedBuf);
1516 hash.copy(checkedBuf, buf.length);
1517 return Base58.encode(checkedBuf);
1518 }
1519
1520 fromBuffer(buf) {
1521 this.buf = buf;
1522 return this;
1523 }
1524
1525 fromString(str) {
1526 const buf = Base58Check.decode(str);
1527 this.buf = buf;
1528 return this;
1529 }
1530
1531 toBuffer() {
1532 return this.buf;
1533 }
1534
1535 toString() {
1536 return Base58Check.encode(this.buf);
1537 }
1538
1539}
1540
1541class Config {
1542 constructor(values) {
1543 this.keyDefined = key => key in values;
1544
1545 this.getValue = key => values[key];
1546 }
1547
1548 get(key) {
1549 if (this.keyDefined(key)) {
1550 return this.getValue(key);
1551 } else {
1552 throw new Error(`Unknown configuration: ${key}`);
1553 }
1554 }
1555
1556}
1557
1558class ConfigBuilder {
1559 constructor() {
1560 this.variables = {};
1561 }
1562
1563 build() {
1564 return new Config(this.variables);
1565 }
1566
1567 addValue(key, value) {
1568 if (value === undefined) {
1569 throw new Error(`Failed to add "${key}" property. The value cannot be undefined`);
1570 }
1571
1572 if (key in this.variables) {
1573 throw new Error(`"${key}" already has a value defined.`);
1574 }
1575
1576 this.variables[key] = value;
1577 return this;
1578 }
1579
1580 addValueWithDefault(key, value, defaultValue) {
1581 if (defaultValue === undefined) {
1582 throw new Error(`Failed to add "${key}" property. Default value cannot be undefined`);
1583 }
1584
1585 return this.addValue(key, value === undefined ? defaultValue : value);
1586 }
1587
1588}
1589
1590const config = new ConfigBuilder().addValue('NETWORK', process.env.NETWORK || 'mainnet').build();
1591
1592const Constants = {};
1593Constants.Mainnet = {
1594 MaxSize: 0x02000000,
1595 Port: 8333,
1596 Address: {
1597 pubKeyHash: 0x00,
1598 payToScriptHash: 0x05
1599 },
1600 Bip32: {
1601 pubKey: 0x0488b21e,
1602 privKey: 0x0488ade4
1603 },
1604 Block: {
1605 maxNBits: 0x1d00ffff,
1606 magicNum: 0xe3e1f3e8
1607 },
1608 Msg: {
1609 magicNum: 0xe3e1f3e8,
1610 versionBytesNum: 70015
1611 },
1612 PrivKey: {
1613 versionByteNum: 0x80
1614 },
1615 TxBuilder: {
1616 dust: 546,
1617 feePerKbNum: 0.00000500e8
1618 },
1619 Workers: {
1620 timeout: 60000
1621 }
1622};
1623Constants.Testnet = Object.assign({}, Constants.Mainnet, {
1624 Port: 18333,
1625 Address: {
1626 pubKeyHash: 0x6f,
1627 payToScriptHash: 0xc4
1628 },
1629 Bip32: {
1630 pubKey: 0x043587cf,
1631 privKey: 0x04358394
1632 },
1633 Block: {
1634 maxNBits: 0x1d00ffff,
1635 magicNum: 0xf4e5f3f4
1636 },
1637 Msg: {
1638 magicNum: 0xf4e5f3f4,
1639 versionBytesNum: 70015
1640 },
1641 PrivKey: {
1642 versionByteNum: 0xef
1643 }
1644});
1645Constants.Regtest = Object.assign({}, Constants.Mainnet, {
1646 Port: 18444,
1647 Address: {
1648 pubKeyHash: 0x6f,
1649 payToScriptHash: 0xc4
1650 },
1651 Bip32: {
1652 pubKey: 0x043587cf,
1653 privKey: 0x04358394
1654 },
1655 Block: {
1656 maxNBits: 0x1d00ffff,
1657 magicNum: 0xdab5bffa
1658 },
1659 Msg: {
1660 magicNum: 0xdab5bffa,
1661 versionBytesNum: 70015
1662 },
1663 PrivKey: {
1664 versionByteNum: 0xef
1665 }
1666});
1667Constants.STN = Object.assign({}, Constants.Mainnet, {
1668 Port: 9333,
1669 Address: {
1670 pubKeyHash: 0x6f,
1671 payToScriptHash: 0xc4
1672 },
1673 Bip32: {
1674 pubKey: 0x043587cf,
1675 privKey: 0x04358394
1676 },
1677 Block: {
1678 maxNBits: 0x1d00ffff,
1679 magicNum: 0xfbcec4f9
1680 },
1681 Msg: {
1682 magicNum: 0xfbcec4f9,
1683 versionBytesNum: 70015
1684 },
1685 PrivKey: {
1686 versionByteNum: 0xef
1687 }
1688});
1689
1690if (config.get('NETWORK') === 'testnet') {
1691 Constants.Default = Object.assign({}, Constants.Testnet);
1692} else if (config.get('NETWORK') === 'mainnet') {
1693 Constants.Default = Object.assign({}, Constants.Mainnet);
1694} else if (config.get('NETWORK') === 'regtest') {
1695 Constants.Default = Object.assign({}, Constants.Regtest);
1696} else if (config.get('NETWORK') === 'stn') {
1697 Constants.Default = Object.assign({}, Constants.STN);
1698} else {
1699 throw new Error(`must set network in environment variable - mainnet, testnet, regtest or stn?, received ${config.get('NETWORK')}`);
1700}
1701
1702const getConstants = magicNum => {
1703 if (Constants.Mainnet.Msg.magicNum === magicNum) {
1704 return Constants.Mainnet;
1705 } else if (Constants.Testnet.Msg.magicNum === magicNum) {
1706 return Constants.Testnet;
1707 } else if (Constants.Regtest.Msg.magicNum === magicNum) {
1708 return Constants.Regtest;
1709 } else if (Constants.STN.Msg.magicNum === magicNum) {
1710 return Constants.STN;
1711 } else {
1712 return Constants.Default;
1713 }
1714};
1715
1716const map = {
1717 OP_FALSE: 0x00,
1718 OP_0: 0x00,
1719 OP_PUSHDATA1: 0x4c,
1720 OP_PUSHDATA2: 0x4d,
1721 OP_PUSHDATA4: 0x4e,
1722 OP_1NEGATE: 0x4f,
1723 OP_RESERVED: 0x50,
1724 OP_TRUE: 0x51,
1725 OP_1: 0x51,
1726 OP_2: 0x52,
1727 OP_3: 0x53,
1728 OP_4: 0x54,
1729 OP_5: 0x55,
1730 OP_6: 0x56,
1731 OP_7: 0x57,
1732 OP_8: 0x58,
1733 OP_9: 0x59,
1734 OP_10: 0x5a,
1735 OP_11: 0x5b,
1736 OP_12: 0x5c,
1737 OP_13: 0x5d,
1738 OP_14: 0x5e,
1739 OP_15: 0x5f,
1740 OP_16: 0x60,
1741 OP_NOP: 0x61,
1742 OP_VER: 0x62,
1743 OP_IF: 0x63,
1744 OP_NOTIF: 0x64,
1745 OP_VERIF: 0x65,
1746 OP_VERNOTIF: 0x66,
1747 OP_ELSE: 0x67,
1748 OP_ENDIF: 0x68,
1749 OP_VERIFY: 0x69,
1750 OP_RETURN: 0x6a,
1751 OP_TOALTSTACK: 0x6b,
1752 OP_FROMALTSTACK: 0x6c,
1753 OP_2DROP: 0x6d,
1754 OP_2DUP: 0x6e,
1755 OP_3DUP: 0x6f,
1756 OP_2OVER: 0x70,
1757 OP_2ROT: 0x71,
1758 OP_2SWAP: 0x72,
1759 OP_IFDUP: 0x73,
1760 OP_DEPTH: 0x74,
1761 OP_DROP: 0x75,
1762 OP_DUP: 0x76,
1763 OP_NIP: 0x77,
1764 OP_OVER: 0x78,
1765 OP_PICK: 0x79,
1766 OP_ROLL: 0x7a,
1767 OP_ROT: 0x7b,
1768 OP_SWAP: 0x7c,
1769 OP_TUCK: 0x7d,
1770 OP_CAT: 0x7e,
1771 OP_SUBSTR: 0x7f,
1772 OP_SPLIT: 0x7f,
1773 OP_LEFT: 0x80,
1774 OP_NUM2BIN: 0x80,
1775 OP_RIGHT: 0x81,
1776 OP_BIN2NUM: 0x81,
1777 OP_SIZE: 0x82,
1778 OP_INVERT: 0x83,
1779 OP_AND: 0x84,
1780 OP_OR: 0x85,
1781 OP_XOR: 0x86,
1782 OP_EQUAL: 0x87,
1783 OP_EQUALVERIFY: 0x88,
1784 OP_RESERVED1: 0x89,
1785 OP_RESERVED2: 0x8a,
1786 OP_1ADD: 0x8b,
1787 OP_1SUB: 0x8c,
1788 OP_2MUL: 0x8d,
1789 OP_2DIV: 0x8e,
1790 OP_NEGATE: 0x8f,
1791 OP_ABS: 0x90,
1792 OP_NOT: 0x91,
1793 OP_0NOTEQUAL: 0x92,
1794 OP_ADD: 0x93,
1795 OP_SUB: 0x94,
1796 OP_MUL: 0x95,
1797 OP_DIV: 0x96,
1798 OP_MOD: 0x97,
1799 OP_LSHIFT: 0x98,
1800 OP_RSHIFT: 0x99,
1801 OP_BOOLAND: 0x9a,
1802 OP_BOOLOR: 0x9b,
1803 OP_NUMEQUAL: 0x9c,
1804 OP_NUMEQUALVERIFY: 0x9d,
1805 OP_NUMNOTEQUAL: 0x9e,
1806 OP_LESSTHAN: 0x9f,
1807 OP_GREATERTHAN: 0xa0,
1808 OP_LESSTHANOREQUAL: 0xa1,
1809 OP_GREATERTHANOREQUAL: 0xa2,
1810 OP_MIN: 0xa3,
1811 OP_MAX: 0xa4,
1812 OP_WITHIN: 0xa5,
1813 OP_RIPEMD160: 0xa6,
1814 OP_SHA1: 0xa7,
1815 OP_SHA256: 0xa8,
1816 OP_HASH160: 0xa9,
1817 OP_HASH256: 0xaa,
1818 OP_CODESEPARATOR: 0xab,
1819 OP_CHECKSIG: 0xac,
1820 OP_CHECKSIGVERIFY: 0xad,
1821 OP_CHECKMULTISIG: 0xae,
1822 OP_CHECKMULTISIGVERIFY: 0xaf,
1823 OP_NOP1: 0xb0,
1824 OP_NOP2: 0xb1,
1825 OP_CHECKLOCKTIMEVERIFY: 0xb1,
1826 OP_NOP3: 0xb2,
1827 OP_CHECKSEQUENCEVERIFY: 0xb2,
1828 OP_NOP4: 0xb3,
1829 OP_NOP5: 0xb4,
1830 OP_NOP6: 0xb5,
1831 OP_NOP7: 0xb6,
1832 OP_NOP8: 0xb7,
1833 OP_NOP9: 0xb8,
1834 OP_NOP10: 0xb9,
1835 OP_SMALLDATA: 0xf9,
1836 OP_SMALLINTEGER: 0xfa,
1837 OP_PUBKEYS: 0xfb,
1838 OP_PUBKEYHASH: 0xfd,
1839 OP_PUBKEY: 0xfe,
1840 OP_INVALIDOPCODE: 0xff
1841};
1842
1843class OpCode extends Struct {
1844 constructor(num) {
1845 super({
1846 num
1847 });
1848 }
1849
1850 fromNumber(num) {
1851 this.num = num;
1852 return this;
1853 }
1854
1855 static fromNumber(num) {
1856 return new this().fromNumber(num);
1857 }
1858
1859 toNumber() {
1860 return this.num;
1861 }
1862
1863 fromString(str) {
1864 const num = map[str];
1865
1866 if (num === undefined) {
1867 throw new Error('Invalid opCodeStr');
1868 }
1869
1870 this.num = num;
1871 return this;
1872 }
1873
1874 static fromString(str) {
1875 return new this().fromString(str);
1876 }
1877
1878 toString() {
1879 const str = OpCode.str[this.num];
1880
1881 if (str === undefined) {
1882 if (this.num > 0 && this.num < OpCode.OP_PUSHDATA1) {
1883 return this.num.toString();
1884 }
1885
1886 throw new Error('OpCode does not have a string representation');
1887 }
1888
1889 return str;
1890 }
1891
1892}
1893
1894OpCode.str = {};
1895
1896for (const opCodeStr in map) {
1897 OpCode[opCodeStr] = map[opCodeStr];
1898
1899 if (Object.prototype.hasOwnProperty.call(map, opCodeStr)) {
1900 OpCode.str[map[opCodeStr]] = opCodeStr;
1901 }
1902}
1903
1904const ec = elliptic.curves.secp256k1;
1905
1906const _point = ec.curve.point();
1907
1908const _Point = _point.constructor;
1909
1910class Point extends _Point {
1911 constructor(x, y, isRed) {
1912 super(ec.curve, x, y, isRed);
1913 }
1914
1915 static fromX(isOdd, x) {
1916 const _point = ec.curve.pointFromX(x, isOdd);
1917
1918 const point = Object.create(Point.prototype);
1919 return point.copyFrom(_point);
1920 }
1921
1922 copyFrom(point) {
1923 if (!(point instanceof _Point)) {
1924 throw new Error('point should be an external point');
1925 }
1926
1927 Object.keys(point).forEach(function (key) {
1928 this[key] = point[key];
1929 }.bind(this));
1930 return this;
1931 }
1932
1933 add(p) {
1934 p = _Point.prototype.add.call(this, p);
1935 const point = Object.create(Point.prototype);
1936 return point.copyFrom(p);
1937 }
1938
1939 mul(bn) {
1940 if (!bn.lt(Point.getN())) {
1941 throw new Error('point mul out of range');
1942 }
1943
1944 const p = _Point.prototype.mul.call(this, bn);
1945
1946 const point = Object.create(Point.prototype);
1947 return point.copyFrom(p);
1948 }
1949
1950 mulAdd(bn1, point, bn2) {
1951 const p = _Point.prototype.mulAdd.call(this, bn1, point, bn2);
1952
1953 point = Object.create(Point.prototype);
1954 return point.copyFrom(p);
1955 }
1956
1957 getX() {
1958 const _x = _Point.prototype.getX.call(this);
1959
1960 const x = Object.create(Bn.prototype);
1961
1962 _x.copy(x);
1963
1964 return x;
1965 }
1966
1967 getY() {
1968 const _y = _Point.prototype.getY.call(this);
1969
1970 const y = Object.create(Bn.prototype);
1971
1972 _y.copy(y);
1973
1974 return y;
1975 }
1976
1977 fromX(isOdd, x) {
1978 const point = Point.fromX(isOdd, x);
1979 return this.copyFrom(point);
1980 }
1981
1982 toJSON() {
1983 return {
1984 x: this.getX().toString(),
1985 y: this.getY().toString()
1986 };
1987 }
1988
1989 fromJSON(json) {
1990 const x = new Bn().fromString(json.x);
1991 const y = new Bn().fromString(json.y);
1992 const point = new Point(x, y);
1993 return this.copyFrom(point);
1994 }
1995
1996 toString() {
1997 return JSON.stringify(this.toJSON());
1998 }
1999
2000 fromString(str) {
2001 const json = JSON.parse(str);
2002 const p = new Point().fromJSON(json);
2003 return this.copyFrom(p);
2004 }
2005
2006 static getG() {
2007 const _g = ec.curve.g;
2008 const g = Object.create(Point.prototype);
2009 return g.copyFrom(_g);
2010 }
2011
2012 static getN() {
2013 return new Bn(ec.curve.n.toArray());
2014 }
2015
2016 validate() {
2017 const p2 = Point.fromX(this.getY().isOdd(), this.getX());
2018
2019 if (!(p2.getY().cmp(this.getY()) === 0)) {
2020 throw new Error('Invalid y value of public key');
2021 }
2022
2023 if (!(this.getX().gt(-1) && this.getX().lt(Point.getN())) || !(this.getY().gt(-1) && this.getY().lt(Point.getN()))) {
2024 throw new Error('Point does not lie on the curve');
2025 }
2026
2027 return this;
2028 }
2029
2030}
2031
2032class PubKey extends Struct {
2033 constructor(point, compressed) {
2034 super({
2035 point,
2036 compressed
2037 });
2038 }
2039
2040 fromJSON(json) {
2041 this.fromFastHex(json);
2042 return this;
2043 }
2044
2045 toJSON() {
2046 return this.toFastHex();
2047 }
2048
2049 fromPrivKey(privKey) {
2050 this.fromObject({
2051 point: Point.getG().mul(privKey.bn),
2052 compressed: privKey.compressed
2053 });
2054 return this;
2055 }
2056
2057 static fromPrivKey(privKey) {
2058 return new this().fromPrivKey(privKey);
2059 }
2060
2061 async asyncFromPrivKey(privKey) {
2062 const workersResult = await Workers.asyncObjectMethod(this, 'fromPrivKey', [privKey]);
2063 return this.fromFastBuffer(workersResult.resbuf);
2064 }
2065
2066 static asyncFromPrivKey(privKey) {
2067 return new this().asyncFromPrivKey(privKey);
2068 }
2069
2070 fromBuffer(buf, strict) {
2071 return this.fromDer(buf, strict);
2072 }
2073
2074 async asyncFromBuffer(buf, strict) {
2075 const args = [buf, strict];
2076 const workersResult = await Workers.asyncObjectMethod(this, 'fromBuffer', args);
2077 return this.fromFastBuffer(workersResult.resbuf);
2078 }
2079
2080 fromFastBuffer(buf) {
2081 if (buf.length === 0) {
2082 return this;
2083 }
2084
2085 const compressed = Boolean(buf[0]);
2086 buf = buf.slice(1);
2087 this.fromDer(buf);
2088 this.compressed = compressed;
2089 return this;
2090 }
2091
2092 fromDer(buf, strict) {
2093 if (strict === undefined) {
2094 strict = true;
2095 } else {
2096 strict = false;
2097 }
2098
2099 if (buf[0] === 0x04 || !strict && (buf[0] === 0x06 || buf[0] === 0x07)) {
2100 const xbuf = buf.slice(1, 33);
2101 const ybuf = buf.slice(33, 65);
2102
2103 if (xbuf.length !== 32 || ybuf.length !== 32 || buf.length !== 65) {
2104 throw new Error('LEngth of x and y must be 32 bytes');
2105 }
2106
2107 const x = new Bn(xbuf);
2108 const y = new Bn(ybuf);
2109 this.point = new Point(x, y);
2110 this.compressed = false;
2111 } else if (buf[0] === 0x03) {
2112 const xbuf = buf.slice(1);
2113 const x = new Bn(xbuf);
2114 this.fromX(true, x);
2115 this.compressed = true;
2116 } else if (buf[0] === 0x02) {
2117 const xbuf = buf.slice(1);
2118 const x = new Bn(xbuf);
2119 this.fromX(false, x);
2120 this.compressed = true;
2121 } else {
2122 throw new Error('Invalid DER format pubKey');
2123 }
2124
2125 return this;
2126 }
2127
2128 static fromDer(buf, strict) {
2129 return new this().fromDer(buf, strict);
2130 }
2131
2132 fromString(str) {
2133 this.fromDer(Buffer.from(str, 'hex'));
2134 return this;
2135 }
2136
2137 fromX(odd, x) {
2138 if (typeof odd !== 'boolean') {
2139 throw new Error('Must specify whether y is odd or not (true or false)');
2140 }
2141
2142 this.point = Point.fromX(odd, x);
2143 return this;
2144 }
2145
2146 static fromX(odd, x) {
2147 return new this().fromX(odd, x);
2148 }
2149
2150 toBuffer() {
2151 const compressed = this.compressed === undefined ? true : this.compressed;
2152 return this.toDer(compressed);
2153 }
2154
2155 toFastBuffer() {
2156 if (!this.point) {
2157 return Buffer.alloc(0);
2158 }
2159
2160 const bw = new Bw();
2161 const compressed = this.compressed === undefined ? true : Boolean(this.compressed);
2162 bw.writeUInt8(Number(compressed));
2163 bw.write(this.toDer(false));
2164 return bw.toBuffer();
2165 }
2166
2167 toDer(compressed) {
2168 compressed = compressed === undefined ? this.compressed : compressed;
2169
2170 if (typeof compressed !== 'boolean') {
2171 throw new Error('Must specify whether the public key is compressed or not (true or false)');
2172 }
2173
2174 const x = this.point.getX();
2175 const y = this.point.getY();
2176 const xbuf = x.toBuffer({
2177 size: 32
2178 });
2179 const ybuf = y.toBuffer({
2180 size: 32
2181 });
2182 let prefix;
2183
2184 if (!compressed) {
2185 prefix = Buffer.from([0x04]);
2186 return Buffer.concat([prefix, xbuf, ybuf]);
2187 } else {
2188 const odd = ybuf[ybuf.length - 1] % 2;
2189
2190 if (odd) {
2191 prefix = Buffer.from([0x03]);
2192 } else {
2193 prefix = Buffer.from([0x02]);
2194 }
2195
2196 return Buffer.concat([prefix, xbuf]);
2197 }
2198 }
2199
2200 toString() {
2201 const compressed = this.compressed === undefined ? true : this.compressed;
2202 return this.toDer(compressed).toString('hex');
2203 }
2204
2205 static isCompressedOrUncompressed(buf) {
2206 if (buf.length < 33) {
2207 return false;
2208 }
2209
2210 if (buf[0] === 0x04) {
2211 if (buf.length !== 65) {
2212 return false;
2213 }
2214 } else if (buf[0] === 0x02 || buf[0] === 0x03) {
2215 if (buf.length !== 33) {
2216 return false;
2217 }
2218 } else {
2219 return false;
2220 }
2221
2222 return true;
2223 }
2224
2225 validate() {
2226 if (this.point.isInfinity()) {
2227 throw new Error('point: Point cannot be equal to Infinity');
2228 }
2229
2230 if (this.point.eq(new Point(new Bn(0), new Bn(0)))) {
2231 throw new Error('point: Point cannot be equal to 0, 0');
2232 }
2233
2234 this.point.validate();
2235 return this;
2236 }
2237
2238}
2239
2240class Random {}
2241
2242Random.getRandomBuffer = function (size) {
2243 return randomBytes(size);
2244};
2245
2246class PrivKey extends Struct {
2247 constructor(bn, compressed, constants = null) {
2248 super({
2249 bn,
2250 compressed
2251 });
2252 constants = constants || Constants.Default.PrivKey;
2253 this.Constants = constants;
2254 }
2255
2256 fromJSON(json) {
2257 this.fromHex(json);
2258 return this;
2259 }
2260
2261 toJSON() {
2262 return this.toHex();
2263 }
2264
2265 fromRandom() {
2266 let privBuf, bn, condition;
2267
2268 do {
2269 privBuf = Random.getRandomBuffer(32);
2270 bn = new Bn().fromBuffer(privBuf);
2271 condition = bn.lt(Point.getN());
2272 } while (!condition);
2273
2274 this.fromObject({
2275 bn: bn,
2276 compressed: true
2277 });
2278 return this;
2279 }
2280
2281 static fromRandom() {
2282 return new this().fromRandom();
2283 }
2284
2285 toBuffer() {
2286 let compressed = this.compressed;
2287
2288 if (compressed === undefined) {
2289 compressed = true;
2290 }
2291
2292 const privBuf = this.bn.toBuffer({
2293 size: 32
2294 });
2295 let buf;
2296
2297 if (compressed) {
2298 buf = Buffer.concat([Buffer.from([this.Constants.versionByteNum]), privBuf, Buffer.from([0x01])]);
2299 } else {
2300 buf = Buffer.concat([Buffer.from([this.Constants.versionByteNum]), privBuf]);
2301 }
2302
2303 return buf;
2304 }
2305
2306 fromBuffer(buf) {
2307 if (buf.length === 1 + 32 + 1 && buf[1 + 32 + 1 - 1] === 1) {
2308 this.compressed = true;
2309 } else if (buf.length === 1 + 32) {
2310 this.compressed = false;
2311 } else {
2312 throw new Error('Length of privKey buffer must be 33 (uncompressed pubKey) or 34 (compressed pubKey)');
2313 }
2314
2315 if (buf[0] !== this.Constants.versionByteNum) {
2316 throw new Error('Invalid versionByteNum byte');
2317 }
2318
2319 return this.fromBn(new Bn().fromBuffer(buf.slice(1, 1 + 32)));
2320 }
2321
2322 toBn() {
2323 return this.bn;
2324 }
2325
2326 fromBn(bn) {
2327 this.bn = bn;
2328 return this;
2329 }
2330
2331 static fromBn(bn) {
2332 return new this().fromBn(bn);
2333 }
2334
2335 validate() {
2336 if (!this.bn.lt(Point.getN())) {
2337 throw new Error('Number must be less than N');
2338 }
2339
2340 if (typeof this.compressed !== 'boolean') {
2341 throw new Error('Must specify whether the corresponding public key is compressed or not (true or false)');
2342 }
2343
2344 return this;
2345 }
2346
2347 toWif() {
2348 return Base58Check.encode(this.toBuffer());
2349 }
2350
2351 fromWif(str) {
2352 return this.fromBuffer(Base58Check.decode(str));
2353 }
2354
2355 static fromWif(str) {
2356 return new this().fromWif(str);
2357 }
2358
2359 toString() {
2360 return this.toWif();
2361 }
2362
2363 fromString(str) {
2364 return this.fromWif(str);
2365 }
2366
2367}
2368
2369PrivKey.Mainnet = class extends PrivKey {
2370 constructor(bn, compressed) {
2371 super(bn, compressed, Constants.Mainnet.PrivKey);
2372 }
2373
2374};
2375PrivKey.Testnet = class extends PrivKey {
2376 constructor(bn, compressed) {
2377 super(bn, compressed, Constants.Testnet.PrivKey);
2378 }
2379
2380};
2381
2382class Sig extends Struct {
2383 constructor(r, s, nHashType, recovery, compressed) {
2384 super({
2385 r,
2386 s,
2387 nHashType,
2388 recovery,
2389 compressed
2390 });
2391 }
2392
2393 fromBuffer(buf) {
2394 try {
2395 return this.fromDer(buf, true);
2396 } catch (e) {}
2397
2398 try {
2399 return this.fromCompact(buf);
2400 } catch (e) {}
2401
2402 return this.fromTxFormat(buf);
2403 }
2404
2405 toBuffer() {
2406 if (this.nHashType !== undefined) {
2407 return this.toTxFormat();
2408 } else if (this.recovery !== undefined) {
2409 return this.toCompact();
2410 }
2411
2412 return this.toDer();
2413 }
2414
2415 fromCompact(buf) {
2416 let compressed = true;
2417 let recovery = buf.slice(0, 1)[0] - 27 - 4;
2418
2419 if (recovery < 0) {
2420 compressed = false;
2421 recovery = recovery + 4;
2422 }
2423
2424 if (!(recovery === 0 || recovery === 1 || recovery === 2 || recovery === 3)) {
2425 throw new Error('i must be 0, 1, 2, or 3');
2426 }
2427
2428 this.compressed = compressed;
2429 this.recovery = recovery;
2430 const rsbuf = buf.slice(1);
2431 this.fromRS(rsbuf);
2432 return this;
2433 }
2434
2435 static fromCompact(buf) {
2436 return new this().fromCompact(buf);
2437 }
2438
2439 fromRS(rsbuf) {
2440 const b2 = rsbuf.slice(0, 32);
2441 const b3 = rsbuf.slice(32, 64);
2442
2443 if (b2.length !== 32) {
2444 throw new Error('r must be 32 bytes');
2445 }
2446
2447 if (b3.length !== 32 || rsbuf.length > 64) {
2448 throw new Error('s must be 32 bytes');
2449 }
2450
2451 this.r = new Bn().fromBuffer(b2);
2452 this.s = new Bn().fromBuffer(b3);
2453 return this;
2454 }
2455
2456 static fromRS(rsbuf) {
2457 return new this().fromRS(rsbuf);
2458 }
2459
2460 fromDer(buf, strict) {
2461 const obj = Sig.parseDer(buf, strict);
2462 this.r = obj.r;
2463 this.s = obj.s;
2464 return this;
2465 }
2466
2467 static fromDer(buf, strict) {
2468 return new this().fromDer(buf, strict);
2469 }
2470
2471 fromTxFormat(buf) {
2472 if (buf.length === 0) {
2473 this.r = new Bn(1);
2474 this.s = new Bn(1);
2475 this.nHashType = 1;
2476 return this;
2477 }
2478
2479 const nHashType = buf.readUInt8(buf.length - 1);
2480 const derbuf = buf.slice(0, buf.length - 1);
2481 this.fromDer(derbuf, false);
2482 this.nHashType = nHashType;
2483 return this;
2484 }
2485
2486 static fromTxFormat(buf) {
2487 return new this().fromTxFormat(buf);
2488 }
2489
2490 fromString(str) {
2491 return this.fromHex(str);
2492 }
2493
2494 static parseDer(buf, strict) {
2495 if (strict === undefined) {
2496 strict = true;
2497 }
2498
2499 if (!Buffer.isBuffer(buf)) {
2500 throw new Error('DER formatted signature should be a buffer');
2501 }
2502
2503 const header = buf[0];
2504
2505 if (header !== 0x30) {
2506 throw new Error('Header byte should be 0x30');
2507 }
2508
2509 let length = buf[1];
2510 const buflength = buf.slice(2).length;
2511
2512 if (strict && length !== buflength) {
2513 throw new Error('LEngth byte should length of what follows');
2514 } else {
2515 length = length < buflength ? length : buflength;
2516 }
2517
2518 const rheader = buf[2 + 0];
2519
2520 if (rheader !== 0x02) {
2521 throw new Error('Integer byte for r should be 0x02');
2522 }
2523
2524 const rlength = buf[2 + 1];
2525 const rbuf = buf.slice(2 + 2, 2 + 2 + rlength);
2526 const r = new Bn().fromBuffer(rbuf);
2527 const rneg = buf[2 + 1 + 1] === 0x00;
2528
2529 if (rlength !== rbuf.length) {
2530 throw new Error('LEngth of r incorrect');
2531 }
2532
2533 const sheader = buf[2 + 2 + rlength + 0];
2534
2535 if (sheader !== 0x02) {
2536 throw new Error('Integer byte for s should be 0x02');
2537 }
2538
2539 const slength = buf[2 + 2 + rlength + 1];
2540 const sbuf = buf.slice(2 + 2 + rlength + 2, 2 + 2 + rlength + 2 + slength);
2541 const s = new Bn().fromBuffer(sbuf);
2542 const sneg = buf[2 + 2 + rlength + 2 + 2] === 0x00;
2543
2544 if (slength !== sbuf.length) {
2545 throw new Error('LEngth of s incorrect');
2546 }
2547
2548 const sumlength = 2 + 2 + rlength + 2 + slength;
2549
2550 if (length !== sumlength - 2) {
2551 throw new Error('LEngth of signature incorrect');
2552 }
2553
2554 const obj = {
2555 header: header,
2556 length: length,
2557 rheader: rheader,
2558 rlength: rlength,
2559 rneg: rneg,
2560 rbuf: rbuf,
2561 r: r,
2562 sheader: sheader,
2563 slength: slength,
2564 sneg: sneg,
2565 sbuf: sbuf,
2566 s: s
2567 };
2568 return obj;
2569 }
2570
2571 static IsTxDer(buf) {
2572 if (buf.length < 9) {
2573 return false;
2574 }
2575
2576 if (buf.length > 73) {
2577 return false;
2578 }
2579
2580 if (buf[0] !== 0x30) {
2581 return false;
2582 }
2583
2584 if (buf[1] !== buf.length - 3) {
2585 return false;
2586 }
2587
2588 const nLEnR = buf[3];
2589
2590 if (5 + nLEnR >= buf.length) {
2591 return false;
2592 }
2593
2594 const nLEnS = buf[5 + nLEnR];
2595
2596 if (nLEnR + nLEnS + 7 !== buf.length) {
2597 return false;
2598 }
2599
2600 const R = buf.slice(4);
2601
2602 if (buf[4 - 2] !== 0x02) {
2603 return false;
2604 }
2605
2606 if (nLEnR === 0) {
2607 return false;
2608 }
2609
2610 if (R[0] & 0x80) {
2611 return false;
2612 }
2613
2614 if (nLEnR > 1 && R[0] === 0x00 && !(R[1] & 0x80)) {
2615 return false;
2616 }
2617
2618 const S = buf.slice(6 + nLEnR);
2619
2620 if (buf[6 + nLEnR - 2] !== 0x02) {
2621 return false;
2622 }
2623
2624 if (nLEnS === 0) {
2625 return false;
2626 }
2627
2628 if (S[0] & 0x80) {
2629 return false;
2630 }
2631
2632 if (nLEnS > 1 && S[0] === 0x00 && !(S[1] & 0x80)) {
2633 return false;
2634 }
2635
2636 return true;
2637 }
2638
2639 hasLowS() {
2640 if (this.s.lt(1) || this.s.gt(Bn.fromBuffer(Buffer.from('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')))) {
2641 return false;
2642 }
2643
2644 return true;
2645 }
2646
2647 hasDefinedHashType() {
2648 if (this.nHashType < Sig.SIGHASH_ALL || this.nHashType > Sig.SIGHASH_SINGLE) {
2649 return false;
2650 }
2651
2652 return true;
2653 }
2654
2655 toCompact(recovery, compressed) {
2656 recovery = typeof recovery === 'number' ? recovery : this.recovery;
2657 compressed = typeof compressed === 'boolean' ? compressed : this.compressed;
2658
2659 if (!(recovery === 0 || recovery === 1 || recovery === 2 || recovery === 3)) {
2660 throw new Error('recovery must be equal to 0, 1, 2, or 3');
2661 }
2662
2663 let val = recovery + 27 + 4;
2664
2665 if (compressed === false) {
2666 val = val - 4;
2667 }
2668
2669 const b1 = Buffer.from([val]);
2670 const b2 = this.r.toBuffer({
2671 size: 32
2672 });
2673 const b3 = this.s.toBuffer({
2674 size: 32
2675 });
2676 return Buffer.concat([b1, b2, b3]);
2677 }
2678
2679 toRS() {
2680 return Buffer.concat([this.r.toBuffer({
2681 size: 32
2682 }), this.s.toBuffer({
2683 size: 32
2684 })]);
2685 }
2686
2687 toDer() {
2688 const rnbuf = this.r.toBuffer();
2689 const snbuf = this.s.toBuffer();
2690 const rneg = rnbuf[0] & 0x80;
2691 const sneg = snbuf[0] & 0x80;
2692 const rbuf = rneg ? Buffer.concat([Buffer.from([0x00]), rnbuf]) : rnbuf;
2693 const sbuf = sneg ? Buffer.concat([Buffer.from([0x00]), snbuf]) : snbuf;
2694 const length = 2 + rbuf.length + 2 + sbuf.length;
2695 const rlength = rbuf.length;
2696 const slength = sbuf.length;
2697 const rheader = 0x02;
2698 const sheader = 0x02;
2699 const header = 0x30;
2700 const der = Buffer.concat([Buffer.from([header, length, rheader, rlength]), rbuf, Buffer.from([sheader, slength]), sbuf]);
2701 return der;
2702 }
2703
2704 toTxFormat() {
2705 const derbuf = this.toDer();
2706 const buf = Buffer.alloc(1);
2707 buf.writeUInt8(this.nHashType, 0);
2708 return Buffer.concat([derbuf, buf]);
2709 }
2710
2711 toString() {
2712 return this.toHex();
2713 }
2714
2715}
2716
2717Sig.SIGHASH_ALL = 0x00000001;
2718Sig.SIGHASH_NONE = 0x00000002;
2719Sig.SIGHASH_SINGLE = 0x00000003;
2720Sig.SIGHASH_FORKID = 0x00000040;
2721Sig.SIGHASH_ANYONECANPAY = 0x00000080;
2722
2723class Script extends Struct {
2724 constructor(chunks = []) {
2725 super({
2726 chunks
2727 });
2728 }
2729
2730 fromJSON(json) {
2731 return this.fromString(json);
2732 }
2733
2734 toJSON() {
2735 return this.toString();
2736 }
2737
2738 fromBuffer(buf) {
2739 this.chunks = [];
2740 const br = new Br(buf);
2741
2742 while (!br.eof()) {
2743 const opCodeNum = br.readUInt8();
2744 let len = 0;
2745
2746 let _buf = Buffer.from([]);
2747
2748 if (opCodeNum > 0 && opCodeNum < OpCode.OP_PUSHDATA1) {
2749 len = opCodeNum;
2750 this.chunks.push({
2751 buf: br.read(len),
2752 len: len,
2753 opCodeNum: opCodeNum
2754 });
2755 } else if (opCodeNum === OpCode.OP_PUSHDATA1) {
2756 try {
2757 len = br.readUInt8();
2758 _buf = br.read(len);
2759 } catch (err) {
2760 br.read();
2761 }
2762
2763 this.chunks.push({
2764 buf: _buf,
2765 len: len,
2766 opCodeNum: opCodeNum
2767 });
2768 } else if (opCodeNum === OpCode.OP_PUSHDATA2) {
2769 try {
2770 len = br.readUInt16LE();
2771 _buf = br.read(len);
2772 } catch (err) {
2773 br.read();
2774 }
2775
2776 this.chunks.push({
2777 buf: _buf,
2778 len: len,
2779 opCodeNum: opCodeNum
2780 });
2781 } else if (opCodeNum === OpCode.OP_PUSHDATA4) {
2782 try {
2783 len = br.readUInt32LE();
2784 _buf = br.read(len);
2785 } catch (err) {
2786 br.read();
2787 }
2788
2789 this.chunks.push({
2790 buf: _buf,
2791 len: len,
2792 opCodeNum: opCodeNum
2793 });
2794 } else {
2795 this.chunks.push({
2796 opCodeNum: opCodeNum
2797 });
2798 }
2799 }
2800
2801 return this;
2802 }
2803
2804 toBuffer() {
2805 const bw = new Bw();
2806
2807 for (let i = 0; i < this.chunks.length; i++) {
2808 const chunk = this.chunks[i];
2809 const opCodeNum = chunk.opCodeNum;
2810 bw.writeUInt8(opCodeNum);
2811
2812 if (chunk.buf) {
2813 if (opCodeNum < OpCode.OP_PUSHDATA1) {
2814 bw.write(chunk.buf);
2815 } else if (opCodeNum === OpCode.OP_PUSHDATA1) {
2816 bw.writeUInt8(chunk.len);
2817 bw.write(chunk.buf);
2818 } else if (opCodeNum === OpCode.OP_PUSHDATA2) {
2819 bw.writeUInt16LE(chunk.len);
2820 bw.write(chunk.buf);
2821 } else if (opCodeNum === OpCode.OP_PUSHDATA4) {
2822 bw.writeUInt32LE(chunk.len);
2823 bw.write(chunk.buf);
2824 }
2825 }
2826 }
2827
2828 return bw.toBuffer();
2829 }
2830
2831 fromString(str) {
2832 this.chunks = [];
2833
2834 if (str === '' || str === undefined) {
2835 return this;
2836 }
2837
2838 const tokens = str.split(' ');
2839 let i = 0;
2840
2841 while (i < tokens.length) {
2842 const token = tokens[i];
2843 let opCodeNum;
2844
2845 try {
2846 const opCode = new OpCode().fromString(token);
2847 opCodeNum = opCode.toNumber();
2848 } catch (err) {}
2849
2850 if (opCodeNum === undefined) {
2851 opCodeNum = parseInt(token, 10);
2852
2853 if (opCodeNum > 0 && opCodeNum < OpCode.OP_PUSHDATA1) {
2854 this.chunks.push({
2855 buf: Buffer.from(tokens[i + 1].slice(2), 'hex'),
2856 len: opCodeNum,
2857 opCodeNum: opCodeNum
2858 });
2859 i = i + 2;
2860 } else if (opCodeNum === 0) {
2861 this.chunks.push({
2862 opCodeNum: 0
2863 });
2864 i = i + 1;
2865 } else {
2866 throw new Error('Invalid script');
2867 }
2868 } else if (opCodeNum === OpCode.OP_PUSHDATA1 || opCodeNum === OpCode.OP_PUSHDATA2 || opCodeNum === OpCode.OP_PUSHDATA4) {
2869 if (tokens[i + 2].slice(0, 2) !== '0x') {
2870 throw new Error('Pushdata data must start with 0x');
2871 }
2872
2873 this.chunks.push({
2874 buf: Buffer.from(tokens[i + 2].slice(2), 'hex'),
2875 len: parseInt(tokens[i + 1], 10),
2876 opCodeNum: opCodeNum
2877 });
2878 i = i + 3;
2879 } else {
2880 this.chunks.push({
2881 opCodeNum: opCodeNum
2882 });
2883 i = i + 1;
2884 }
2885 }
2886
2887 return this;
2888 }
2889
2890 toString() {
2891 let str = '';
2892
2893 for (let i = 0; i < this.chunks.length; i++) {
2894 const chunk = this.chunks[i];
2895 const opCodeNum = chunk.opCodeNum;
2896
2897 if (!chunk.buf) {
2898 if (OpCode.str[opCodeNum] !== undefined) {
2899 str = str + ' ' + new OpCode(opCodeNum).toString();
2900 } else {
2901 str = str + ' ' + '0x' + opCodeNum.toString(16);
2902 }
2903 } else {
2904 if (opCodeNum === OpCode.OP_PUSHDATA1 || opCodeNum === OpCode.OP_PUSHDATA2 || opCodeNum === OpCode.OP_PUSHDATA4) {
2905 str = str + ' ' + new OpCode(opCodeNum).toString();
2906 }
2907
2908 str = str + ' ' + chunk.len;
2909 str = str + ' ' + '0x' + chunk.buf.toString('hex');
2910 }
2911 }
2912
2913 return str.substr(1);
2914 }
2915
2916 fromBitcoindString(str) {
2917 const bw = new Bw();
2918 const tokens = str.split(' ');
2919 let i;
2920
2921 for (i = 0; i < tokens.length; i++) {
2922 const token = tokens[i];
2923
2924 if (token === '') {
2925 continue;
2926 }
2927
2928 if (token[0] === '0' && token[1] === 'x') {
2929 const hex = token.slice(2);
2930 bw.write(Buffer.from(hex, 'hex'));
2931 } else if (token[0] === "'") {
2932 const tstr = token.slice(1, token.length - 1);
2933 const cbuf = Buffer.from(tstr);
2934 const tbuf = new Script().writeBuffer(cbuf).toBuffer();
2935 bw.write(tbuf);
2936 } else if (OpCode['OP_' + token] !== undefined) {
2937 const opstr = 'OP_' + token;
2938 const opCodeNum = OpCode[opstr];
2939 bw.writeUInt8(opCodeNum);
2940 } else if (typeof OpCode[token] === 'number') {
2941 const opstr = token;
2942 const opCodeNum = OpCode[opstr];
2943 bw.writeUInt8(opCodeNum);
2944 } else if (!isNaN(parseInt(token, 10))) {
2945 const bn = new Bn(token);
2946 const script = new Script().writeBn(bn);
2947 const tbuf = script.toBuffer();
2948 bw.write(tbuf);
2949 } else {
2950 throw new Error('Could not determine type of script value');
2951 }
2952 }
2953
2954 const buf = bw.toBuffer();
2955 return this.fromBuffer(buf);
2956 }
2957
2958 static fromBitcoindString(str) {
2959 return new this().fromBitcoindString(str);
2960 }
2961
2962 toBitcoindString() {
2963 let str = '';
2964
2965 for (let i = 0; i < this.chunks.length; i++) {
2966 const chunk = this.chunks[i];
2967
2968 if (chunk.buf) {
2969 const buf = new Script([chunk]).toBuffer();
2970 const hex = buf.toString('hex');
2971 str = str + ' ' + '0x' + hex;
2972 } else if (OpCode.str[chunk.opCodeNum] !== undefined) {
2973 const ostr = new OpCode(chunk.opCodeNum).toString();
2974 str = str + ' ' + ostr.slice(3);
2975 } else {
2976 str = str + ' ' + '0x' + chunk.opCodeNum.toString(16);
2977 }
2978 }
2979
2980 return str.substr(1);
2981 }
2982
2983 fromAsmString(str) {
2984 this.chunks = [];
2985 const tokens = str.split(' ');
2986 let i = 0;
2987
2988 while (i < tokens.length) {
2989 const token = tokens[i];
2990 let opCode, opCodeNum;
2991
2992 try {
2993 opCode = OpCode.fromString(token);
2994 opCodeNum = opCode.toNumber();
2995 } catch (err) {
2996 opCode = undefined;
2997 opCodeNum = undefined;
2998 }
2999
3000 if (token === '0') {
3001 opCodeNum = 0;
3002 this.chunks.push({
3003 opCodeNum: opCodeNum
3004 });
3005 i = i + 1;
3006 } else if (token === '-1') {
3007 opCodeNum = OpCode.OP_1NEGATE;
3008 this.chunks.push({
3009 opCodeNum: opCodeNum
3010 });
3011 i = i + 1;
3012 } else if (opCode === undefined) {
3013 const hex = tokens[i];
3014 const buf = Buffer.from(hex, 'hex');
3015
3016 if (buf.toString('hex') !== hex) {
3017 throw new Error('invalid hex string in script');
3018 }
3019
3020 const len = buf.length;
3021
3022 if (len >= 0 && len < OpCode.OP_PUSHDATA1) {
3023 opCodeNum = len;
3024 } else if (len < Math.pow(2, 8)) {
3025 opCodeNum = OpCode.OP_PUSHDATA1;
3026 } else if (len < Math.pow(2, 16)) {
3027 opCodeNum = OpCode.OP_PUSHDATA2;
3028 } else if (len < Math.pow(2, 32)) {
3029 opCodeNum = OpCode.OP_PUSHDATA4;
3030 }
3031
3032 this.chunks.push({
3033 buf: buf,
3034 len: buf.length,
3035 opCodeNum: opCodeNum
3036 });
3037 i = i + 1;
3038 } else {
3039 this.chunks.push({
3040 opCodeNum: opCodeNum
3041 });
3042 i = i + 1;
3043 }
3044 }
3045
3046 return this;
3047 }
3048
3049 static fromAsmString(str) {
3050 return new this().fromAsmString(str);
3051 }
3052
3053 toAsmString() {
3054 var str = '';
3055
3056 for (var i = 0; i < this.chunks.length; i++) {
3057 var chunk = this.chunks[i];
3058 str += this._chunkToString(chunk);
3059 }
3060
3061 return str.substr(1);
3062 }
3063
3064 _chunkToString(chunk, type) {
3065 var opCodeNum = chunk.opCodeNum;
3066 var str = '';
3067
3068 if (!chunk.buf) {
3069 if (typeof OpCode.str[opCodeNum] !== 'undefined') {
3070 if (opCodeNum === 0) {
3071 str = str + ' 0';
3072 } else if (opCodeNum === 79) {
3073 str = str + ' -1';
3074 } else {
3075 str = str + ' ' + new OpCode(opCodeNum).toString();
3076 }
3077 } else {
3078 var numstr = opCodeNum.toString(16);
3079
3080 if (numstr.length % 2 !== 0) {
3081 numstr = '0' + numstr;
3082 }
3083
3084 str = str + ' ' + numstr;
3085 }
3086 } else {
3087 if (chunk.len > 0) {
3088 str = str + ' ' + chunk.buf.toString('hex');
3089 }
3090 }
3091
3092 return str;
3093 }
3094
3095 fromOpReturnData(dataBuf) {
3096 this.writeOpCode(OpCode.OP_RETURN);
3097 this.writeBuffer(dataBuf);
3098 return this;
3099 }
3100
3101 static fromOpReturnData(dataBuf) {
3102 return new this().fromOpReturnData(dataBuf);
3103 }
3104
3105 fromSafeData(dataBuf) {
3106 this.writeOpCode(OpCode.OP_FALSE);
3107 this.writeOpCode(OpCode.OP_RETURN);
3108 this.writeBuffer(dataBuf);
3109 return this;
3110 }
3111
3112 static fromSafeData(dataBuf) {
3113 return new this().fromSafeData(dataBuf);
3114 }
3115
3116 fromSafeDataArray(dataBufs) {
3117 this.writeOpCode(OpCode.OP_FALSE);
3118 this.writeOpCode(OpCode.OP_RETURN);
3119
3120 for (const i in dataBufs) {
3121 const dataBuf = dataBufs[i];
3122 this.writeBuffer(dataBuf);
3123 }
3124
3125 return this;
3126 }
3127
3128 static fromSafeDataArray(dataBufs) {
3129 return new this().fromSafeDataArray(dataBufs);
3130 }
3131
3132 getData() {
3133 if (this.isSafeDataOut()) {
3134 const chunks = this.chunks.slice(2);
3135 const buffers = chunks.map(chunk => chunk.buf);
3136 return buffers;
3137 }
3138
3139 if (this.isOpReturn()) {
3140 const chunks = this.chunks.slice(1);
3141 const buffers = chunks.map(chunk => chunk.buf);
3142 return buffers;
3143 }
3144
3145 throw new Error('Unrecognized script type to get data from');
3146 }
3147
3148 fromPubKeyHash(hashBuf) {
3149 if (hashBuf.length !== 20) {
3150 throw new Error('hashBuf must be a 20 byte buffer');
3151 }
3152
3153 this.writeOpCode(OpCode.OP_DUP);
3154 this.writeOpCode(OpCode.OP_HASH160);
3155 this.writeBuffer(hashBuf);
3156 this.writeOpCode(OpCode.OP_EQUALVERIFY);
3157 this.writeOpCode(OpCode.OP_CHECKSIG);
3158 return this;
3159 }
3160
3161 static fromPubKeyHash(hashBuf) {
3162 return new this().fromPubKeyHash(hashBuf);
3163 }
3164
3165 static sortPubKeys(pubKeys) {
3166 return pubKeys.slice().sort((pubKey1, pubKey2) => {
3167 const buf1 = pubKey1.toBuffer();
3168 const buf2 = pubKey2.toBuffer();
3169 const len = Math.max(buf1.length, buf2.length);
3170
3171 for (let i = 0; i <= len; i++) {
3172 if (buf1[i] === undefined) {
3173 return -1;
3174 }
3175
3176 if (buf2[i] === undefined) {
3177 return 1;
3178 }
3179
3180 if (buf1[i] < buf2[i]) {
3181 return -1;
3182 }
3183
3184 if (buf1[i] > buf2[i]) {
3185 return 1;
3186 } else {
3187 continue;
3188 }
3189 }
3190 });
3191 }
3192
3193 fromPubKeys(m, pubKeys, sort = true) {
3194 if (typeof m !== 'number') {
3195 throw new Error('m must be a number');
3196 }
3197
3198 if (sort === true) {
3199 pubKeys = Script.sortPubKeys(pubKeys);
3200 }
3201
3202 this.writeOpCode(m + OpCode.OP_1 - 1);
3203
3204 for (const i in pubKeys) {
3205 this.writeBuffer(pubKeys[i].toBuffer());
3206 }
3207
3208 this.writeOpCode(pubKeys.length + OpCode.OP_1 - 1);
3209 this.writeOpCode(OpCode.OP_CHECKMULTISIG);
3210 return this;
3211 }
3212
3213 static fromPubKeys(m, pubKeys, sort) {
3214 return new this().fromPubKeys(m, pubKeys, sort);
3215 }
3216
3217 removeCodeseparators() {
3218 const chunks = [];
3219
3220 for (let i = 0; i < this.chunks.length; i++) {
3221 if (this.chunks[i].opCodeNum !== OpCode.OP_CODESEPARATOR) {
3222 chunks.push(this.chunks[i]);
3223 }
3224 }
3225
3226 this.chunks = chunks;
3227 return this;
3228 }
3229
3230 isPushOnly() {
3231 for (let i = 0; i < this.chunks.length; i++) {
3232 const chunk = this.chunks[i];
3233 const opCodeNum = chunk.opCodeNum;
3234
3235 if (opCodeNum > OpCode.OP_16) {
3236 return false;
3237 }
3238 }
3239
3240 return true;
3241 }
3242
3243 isOpReturn() {
3244 if (this.chunks[0].opCodeNum === OpCode.OP_RETURN && this.chunks.filter(chunk => Buffer.isBuffer(chunk.buf)).length === this.chunks.slice(1).length) {
3245 return true;
3246 } else {
3247 return false;
3248 }
3249 }
3250
3251 isSafeDataOut() {
3252 if (this.chunks.length < 2) {
3253 return false;
3254 }
3255
3256 if (this.chunks[0].opCodeNum !== OpCode.OP_FALSE) {
3257 return false;
3258 }
3259
3260 var chunks = this.chunks.slice(1);
3261 var script2 = new Script(chunks);
3262 return script2.isOpReturn();
3263 }
3264
3265 isPubKeyHashOut() {
3266 if (this.chunks[0] && this.chunks[0].opCodeNum === OpCode.OP_DUP && this.chunks[1] && this.chunks[1].opCodeNum === OpCode.OP_HASH160 && this.chunks[2].buf && this.chunks[3] && this.chunks[3].opCodeNum === OpCode.OP_EQUALVERIFY && this.chunks[4] && this.chunks[4].opCodeNum === OpCode.OP_CHECKSIG) {
3267 return true;
3268 } else {
3269 return false;
3270 }
3271 }
3272
3273 isPubKeyHashIn() {
3274 if (this.chunks.length === 2 && (this.chunks[0].buf || this.chunks[0].opCodeNum === OpCode.OP_0) && (this.chunks[1].buf || this.chunks[0].opCodeNum === OpCode.OP_0)) {
3275 return true;
3276 } else {
3277 return false;
3278 }
3279 }
3280
3281 isScriptHashOut() {
3282 const buf = this.toBuffer();
3283 return buf.length === 23 && buf[0] === OpCode.OP_HASH160 && buf[1] === 0x14 && buf[22] === OpCode.OP_EQUAL;
3284 }
3285
3286 isScriptHashIn() {
3287 if (!this.isPushOnly()) {
3288 return false;
3289 }
3290
3291 try {
3292 new Script().fromBuffer(this.chunks[this.chunks.length - 1].buf);
3293 } catch (err) {
3294 return false;
3295 }
3296
3297 return true;
3298 }
3299
3300 isMultiSigOut() {
3301 const m = this.chunks[0].opCodeNum - OpCode.OP_1 + 1;
3302
3303 if (!(m >= 1 && m <= 16)) {
3304 return false;
3305 }
3306
3307 const pubKeychunks = this.chunks.slice(1, this.chunks.length - 2);
3308
3309 if (!pubKeychunks.every(chunk => {
3310 try {
3311 const buf = chunk.buf;
3312 const pubKey = new PubKey().fromDer(buf);
3313 pubKey.validate();
3314 return true;
3315 } catch (err) {
3316 return false;
3317 }
3318 })) {
3319 return false;
3320 }
3321
3322 const n = this.chunks[this.chunks.length - 2].opCodeNum - OpCode.OP_1 + 1;
3323
3324 if (!(n >= m && n <= 16)) {
3325 return false;
3326 }
3327
3328 if (this.chunks[1 + n + 1].opCodeNum !== OpCode.OP_CHECKMULTISIG) {
3329 return false;
3330 }
3331
3332 return true;
3333 }
3334
3335 isMultiSigIn() {
3336 if (this.chunks[0].opCodeNum !== OpCode.OP_0) {
3337 return false;
3338 }
3339
3340 const remaining = this.chunks.slice(1);
3341
3342 if (remaining.length < 1) {
3343 return false;
3344 }
3345
3346 return remaining.every(chunk => Buffer.isBuffer(chunk.buf) && Sig.IsTxDer(chunk.buf));
3347 }
3348
3349 findAndDelete(script) {
3350 const buf = script.toBuffer();
3351
3352 for (let i = 0; i < this.chunks.length; i++) {
3353 const script2 = new Script([this.chunks[i]]);
3354 const buf2 = script2.toBuffer();
3355
3356 if (cmp(buf, buf2)) {
3357 this.chunks.splice(i, 1);
3358 }
3359 }
3360
3361 return this;
3362 }
3363
3364 writeScript(script) {
3365 this.chunks = this.chunks.concat(script.chunks);
3366 return this;
3367 }
3368
3369 static writeScript(script) {
3370 return new this().writeScript(script);
3371 }
3372
3373 writeString(str) {
3374 const script = new Script().fromString(str);
3375 this.chunks = this.chunks.concat(script.chunks);
3376 return this;
3377 }
3378
3379 static writeString(str) {
3380 return new this().writeString(str);
3381 }
3382
3383 writeOpCode(opCodeNum) {
3384 this.chunks.push({
3385 opCodeNum
3386 });
3387 return this;
3388 }
3389
3390 static writeOpCode(opCodeNum) {
3391 return new this().writeOpCode(opCodeNum);
3392 }
3393
3394 setChunkOpCode(i, opCodeNum) {
3395 this.chunks[i] = {
3396 opCodeNum
3397 };
3398 return this;
3399 }
3400
3401 writeBn(bn) {
3402 if (bn.cmp(0) === OpCode.OP_0) {
3403 this.chunks.push({
3404 opCodeNum: OpCode.OP_0
3405 });
3406 } else if (bn.cmp(-1) === 0) {
3407 this.chunks.push({
3408 opCodeNum: OpCode.OP_1NEGATE
3409 });
3410 } else if (bn.cmp(1) >= 0 && bn.cmp(16) <= 0) {
3411 this.chunks.push({
3412 opCodeNum: bn.toNumber() + OpCode.OP_1 - 1
3413 });
3414 } else {
3415 const buf = bn.toSm({
3416 endian: 'little'
3417 });
3418 this.writeBuffer(buf);
3419 }
3420
3421 return this;
3422 }
3423
3424 static writeBn(bn) {
3425 return new this().writeBn(bn);
3426 }
3427
3428 writeNumber(number) {
3429 this.writeBn(new Bn().fromNumber(number));
3430 return this;
3431 }
3432
3433 static writeNumber(number) {
3434 return new this().writeNumber(number);
3435 }
3436
3437 setChunkBn(i, bn) {
3438 this.chunks[i] = new Script().writeBn(bn).chunks[0];
3439 return this;
3440 }
3441
3442 writeBuffer(buf) {
3443 let opCodeNum;
3444 const len = buf.length;
3445
3446 if (buf.length > 0 && buf.length < OpCode.OP_PUSHDATA1) {
3447 opCodeNum = buf.length;
3448 } else if (buf.length === 0) {
3449 opCodeNum = OpCode.OP_0;
3450 } else if (buf.length < Math.pow(2, 8)) {
3451 opCodeNum = OpCode.OP_PUSHDATA1;
3452 } else if (buf.length < Math.pow(2, 16)) {
3453 opCodeNum = OpCode.OP_PUSHDATA2;
3454 } else if (buf.length < Math.pow(2, 32)) {
3455 opCodeNum = OpCode.OP_PUSHDATA4;
3456 } else {
3457 throw new Error("You can't push that much data");
3458 }
3459
3460 this.chunks.push({
3461 buf: buf,
3462 len: len,
3463 opCodeNum: opCodeNum
3464 });
3465 return this;
3466 }
3467
3468 static writeBuffer(buf) {
3469 return new this().writeBuffer(buf);
3470 }
3471
3472 setChunkBuffer(i, buf) {
3473 this.chunks[i] = new Script().writeBuffer(buf).chunks[0];
3474 return this;
3475 }
3476
3477 checkMinimalPush(i) {
3478 const chunk = this.chunks[i];
3479 const buf = chunk.buf;
3480 const opCodeNum = chunk.opCodeNum;
3481
3482 if (!buf) {
3483 return true;
3484 }
3485
3486 if (buf.length === 0) {
3487 return opCodeNum === OpCode.OP_0;
3488 } else if (buf.length === 1 && buf[0] >= 1 && buf[0] <= 16) {
3489 return opCodeNum === OpCode.OP_1 + (buf[0] - 1);
3490 } else if (buf.length === 1 && buf[0] === 0x81) {
3491 return opCodeNum === OpCode.OP_1NEGATE;
3492 } else if (buf.length <= 75) {
3493 return opCodeNum === buf.length;
3494 } else if (buf.length <= 255) {
3495 return opCodeNum === OpCode.OP_PUSHDATA1;
3496 } else if (buf.length <= 65535) {
3497 return opCodeNum === OpCode.OP_PUSHDATA2;
3498 }
3499
3500 return true;
3501 }
3502
3503}
3504
3505class Address extends Struct {
3506 constructor(versionByteNum, hashBuf, constants = null) {
3507 super({
3508 versionByteNum,
3509 hashBuf
3510 });
3511 constants = constants || Constants.Default.Address;
3512 this.Constants = constants;
3513 }
3514
3515 fromBuffer(buf) {
3516 if (buf.length !== 1 + 20) {
3517 throw new Error('address buffers must be exactly 21 bytes');
3518 }
3519
3520 if (buf[0] !== this.Constants.pubKeyHash) {
3521 throw new Error('address: invalid versionByteNum byte');
3522 }
3523
3524 this.versionByteNum = buf[0];
3525 this.hashBuf = buf.slice(1);
3526 return this;
3527 }
3528
3529 fromPubKeyHashBuf(hashBuf) {
3530 this.hashBuf = hashBuf;
3531 this.versionByteNum = this.Constants.pubKeyHash;
3532 return this;
3533 }
3534
3535 static fromPubKeyHashBuf(hashBuf) {
3536 return new this().fromPubKeyHashBuf(hashBuf);
3537 }
3538
3539 fromPubKey(pubKey) {
3540 const hashBuf = Hash.sha256Ripemd160(pubKey.toBuffer());
3541 return this.fromPubKeyHashBuf(hashBuf);
3542 }
3543
3544 static fromPubKey(pubKey) {
3545 return new this().fromPubKey(pubKey);
3546 }
3547
3548 async asyncFromPubKey(pubKey) {
3549 const args = [pubKey];
3550 const workersResult = await Workers.asyncObjectMethod(this, 'fromPubKey', args);
3551 return this.fromFastBuffer(workersResult.resbuf);
3552 }
3553
3554 static asyncFromPubKey(pubKey) {
3555 return new this().asyncFromPubKey(pubKey);
3556 }
3557
3558 fromPrivKey(privKey) {
3559 const pubKey = new PubKey().fromPrivKey(privKey);
3560 const hashBuf = Hash.sha256Ripemd160(pubKey.toBuffer());
3561 return this.fromPubKeyHashBuf(hashBuf);
3562 }
3563
3564 static fromPrivKey(privKey) {
3565 return new this().fromPrivKey(privKey);
3566 }
3567
3568 async asyncFromPrivKey(privKey) {
3569 const args = [privKey];
3570 const workersResult = await Workers.asyncObjectMethod(this, 'fromPrivKey', args);
3571 return this.fromFastBuffer(workersResult.resbuf);
3572 }
3573
3574 static asyncFromPrivKey(privKey) {
3575 return new this().fromPrivKey(privKey);
3576 }
3577
3578 fromRandom() {
3579 const randomPrivKey = new PrivKey().fromRandom();
3580 return this.fromPrivKey(randomPrivKey);
3581 }
3582
3583 static fromRandom() {
3584 return new this().fromRandom();
3585 }
3586
3587 async asyncFromRandom() {
3588 const args = [];
3589 const workersResult = await Workers.asyncObjectMethod(this, 'fromRandom', args);
3590 return this.fromFastBuffer(workersResult.resbuf);
3591 }
3592
3593 static asyncFromRandom() {
3594 return new this().fromRandom();
3595 }
3596
3597 fromString(str) {
3598 const buf = Base58Check.decode(str);
3599 return this.fromBuffer(buf);
3600 }
3601
3602 async asyncFromString(str) {
3603 const args = [str];
3604 const workersResult = await Workers.asyncObjectMethod(this, 'fromString', args);
3605 return this.fromFastBuffer(workersResult.resbuf);
3606 }
3607
3608 static asyncFromString(str) {
3609 return new this().asyncFromString(str);
3610 }
3611
3612 static isValid(addrstr) {
3613 let address;
3614
3615 try {
3616 address = new Address().fromString(addrstr);
3617 } catch (e) {
3618 return false;
3619 }
3620
3621 return address.isValid();
3622 }
3623
3624 isValid() {
3625 try {
3626 this.validate();
3627 return true;
3628 } catch (e) {
3629 return false;
3630 }
3631 }
3632
3633 toTxOutScript() {
3634 const script = new Script();
3635 script.writeOpCode(OpCode.OP_DUP);
3636 script.writeOpCode(OpCode.OP_HASH160);
3637 script.writeBuffer(this.hashBuf);
3638 script.writeOpCode(OpCode.OP_EQUALVERIFY);
3639 script.writeOpCode(OpCode.OP_CHECKSIG);
3640 return script;
3641 }
3642
3643 fromTxInScript(script) {
3644 const pubKeyHashBuf = Hash.sha256Ripemd160(script.chunks[1].buf || Buffer.from('00'.repeat(32), 'hex'));
3645 return this.fromPubKeyHashBuf(pubKeyHashBuf);
3646 }
3647
3648 static fromTxInScript(script) {
3649 return new this().fromTxInScript(script);
3650 }
3651
3652 fromTxOutScript(script) {
3653 return this.fromPubKeyHashBuf(script.chunks[2].buf);
3654 }
3655
3656 static fromTxOutScript(script) {
3657 return new this().fromTxOutScript(script);
3658 }
3659
3660 toBuffer() {
3661 const versionByteBuf = Buffer.from([this.versionByteNum]);
3662 const buf = Buffer.concat([versionByteBuf, this.hashBuf]);
3663 return buf;
3664 }
3665
3666 toJSON() {
3667 const json = {};
3668
3669 if (this.hashBuf) {
3670 json.hashBuf = this.hashBuf.toString('hex');
3671 }
3672
3673 if (typeof this.versionByteNum !== 'undefined') {
3674 json.versionByteNum = this.versionByteNum;
3675 }
3676
3677 return json;
3678 }
3679
3680 fromJSON(json) {
3681 if (json.hashBuf) {
3682 this.hashBuf = Buffer.from(json.hashBuf, 'hex');
3683 }
3684
3685 if (typeof json.versionByteNum !== 'undefined') {
3686 this.versionByteNum = json.versionByteNum;
3687 }
3688
3689 return this;
3690 }
3691
3692 toString() {
3693 return Base58Check.encode(this.toBuffer());
3694 }
3695
3696 async asyncToString() {
3697 const args = [];
3698 const workersResult = await Workers.asyncObjectMethod(this, 'toString', args);
3699 return JSON.parse(workersResult.resbuf.toString());
3700 }
3701
3702 validate() {
3703 if (!Buffer.isBuffer(this.hashBuf) || this.hashBuf.length !== 20) {
3704 throw new Error('hashBuf must be a buffer of 20 bytes');
3705 }
3706
3707 if (this.versionByteNum !== this.Constants.pubKeyHash) {
3708 throw new Error('invalid versionByteNum');
3709 }
3710
3711 return this;
3712 }
3713
3714}
3715
3716Address.Mainnet = class extends Address {
3717 constructor(versionByteNum, hashBuf) {
3718 super(versionByteNum, hashBuf, Constants.Mainnet.Address);
3719 }
3720
3721};
3722Address.Testnet = class extends Address {
3723 constructor(versionByteNum, hashBuf) {
3724 super(versionByteNum, hashBuf, Constants.Testnet.Address);
3725 }
3726
3727};
3728
3729class Bip32 extends Struct {
3730 constructor(versionBytesNum, depth, parentFingerPrint, childIndex, chainCode, privKey, pubKey, constants = null, PrivKey$1 = PrivKey) {
3731 super({
3732 versionBytesNum,
3733 depth,
3734 parentFingerPrint,
3735 childIndex,
3736 chainCode,
3737 privKey,
3738 pubKey
3739 });
3740 constants = constants || Constants.Default.Bip32;
3741 this.Constants = constants;
3742 this.PrivKey = PrivKey$1;
3743 }
3744
3745 fromRandom() {
3746 this.versionBytesNum = this.Constants.privKey;
3747 this.depth = 0x00;
3748 this.parentFingerPrint = Buffer.from([0, 0, 0, 0]);
3749 this.childIndex = 0;
3750 this.chainCode = Random.getRandomBuffer(32);
3751 this.privKey = new this.PrivKey().fromRandom();
3752 this.pubKey = new PubKey().fromPrivKey(this.privKey);
3753 return this;
3754 }
3755
3756 static fromRandom() {
3757 return new this().fromRandom();
3758 }
3759
3760 fromString(str) {
3761 return this.fromBuffer(Base58Check.decode(str));
3762 }
3763
3764 async asyncFromString(str) {
3765 const args = [str];
3766 const workersResult = await Workers.asyncObjectMethod(this, 'fromString', args);
3767 return this.fromFastBuffer(workersResult.resbuf);
3768 }
3769
3770 fromSeed(bytes) {
3771 if (!Buffer.isBuffer(bytes)) {
3772 throw new Error('bytes must be a buffer');
3773 }
3774
3775 if (bytes.length < 128 / 8) {
3776 throw new Error('Need more than 128 bits of entropy');
3777 }
3778
3779 if (bytes.length > 512 / 8) {
3780 throw new Error('More than 512 bits of entropy is nonstandard');
3781 }
3782
3783 const hash = Hash.sha512Hmac(bytes, Buffer.from('Bitcoin seed'));
3784 this.depth = 0x00;
3785 this.parentFingerPrint = Buffer.from([0, 0, 0, 0]);
3786 this.childIndex = 0;
3787 this.chainCode = hash.slice(32, 64);
3788 this.versionBytesNum = this.Constants.privKey;
3789 this.privKey = new this.PrivKey().fromBn(Bn().fromBuffer(hash.slice(0, 32)));
3790 this.pubKey = new PubKey().fromPrivKey(this.privKey);
3791 return this;
3792 }
3793
3794 static fromSeed(bytes) {
3795 return new this().fromSeed(bytes);
3796 }
3797
3798 async asyncFromSeed(bytes) {
3799 const workersResult = await Workers.asyncObjectMethod(this, 'fromSeed', [bytes]);
3800 return this.fromFastBuffer(workersResult.resbuf);
3801 }
3802
3803 static asyncFromSeed(bytes) {
3804 return new this().asyncFromSeed(bytes);
3805 }
3806
3807 fromBuffer(buf) {
3808 if (buf.length !== 78) {
3809 throw new Error('incorrect bip32 data length');
3810 }
3811
3812 this.versionBytesNum = buf.slice(0, 4).readUInt32BE(0);
3813 this.depth = buf.slice(4, 5).readUInt8(0);
3814 this.parentFingerPrint = buf.slice(5, 9);
3815 this.childIndex = buf.slice(9, 13).readUInt32BE(0);
3816 this.chainCode = buf.slice(13, 45);
3817 const keyBytes = buf.slice(45, 78);
3818 const isPrivate = this.versionBytesNum === this.Constants.privKey;
3819 const isPublic = this.versionBytesNum === this.Constants.pubKey;
3820
3821 if (isPrivate && keyBytes[0] === 0) {
3822 this.privKey = new this.PrivKey().fromBn(Bn().fromBuffer(keyBytes.slice(1, 33)));
3823 this.pubKey = new PubKey().fromPrivKey(this.privKey);
3824 } else if (isPublic && (keyBytes[0] === 0x02 || keyBytes[0] === 0x03)) {
3825 this.pubKey = new PubKey().fromDer(keyBytes);
3826 } else {
3827 throw new Error('Invalid key');
3828 }
3829
3830 return this;
3831 }
3832
3833 fromFastBuffer(buf) {
3834 if (buf.length === 0) {
3835 return this;
3836 }
3837
3838 if (buf.length !== 78 && buf.length !== 78 + 33) {
3839 throw new Error('incorrect bip32 fastBuffer data length: ' + buf.length);
3840 }
3841
3842 this.versionBytesNum = buf.slice(0, 4).readUInt32BE(0);
3843 this.depth = buf.slice(4, 5).readUInt8(0);
3844 this.parentFingerPrint = buf.slice(5, 9);
3845 this.childIndex = buf.slice(9, 13).readUInt32BE(0);
3846 this.chainCode = buf.slice(13, 45);
3847 const keyBytes = buf.slice(45, buf.length);
3848 const isPrivate = this.versionBytesNum === this.Constants.privKey;
3849 const isPublic = this.versionBytesNum === this.Constants.pubKey;
3850
3851 if (isPrivate && keyBytes[0] === 0 && buf.length === 78) {
3852 this.privKey = new this.PrivKey().fromBn(Bn().fromBuffer(keyBytes.slice(1, 33)));
3853 this.pubKey = new PubKey().fromPrivKey(this.privKey);
3854 } else if (isPublic && buf.length === 78 + 33) {
3855 this.pubKey = new PubKey().fromFastBuffer(keyBytes);
3856 this.pubKey.compressed = true;
3857 } else {
3858 throw new Error('Invalid key');
3859 }
3860
3861 return this;
3862 }
3863
3864 derive(path) {
3865 const e = path.split('/');
3866
3867 if (path === 'm') {
3868 return this;
3869 }
3870
3871 let bip32 = this;
3872
3873 for (const i in e) {
3874 const c = e[i];
3875
3876 if (i === '0') {
3877 if (c !== 'm') throw new Error('invalid path');
3878 continue;
3879 }
3880
3881 if (parseInt(c.replace("'", ''), 10).toString() !== c.replace("'", '')) {
3882 throw new Error('invalid path');
3883 }
3884
3885 const usePrivate = c.length > 1 && c[c.length - 1] === "'";
3886 let childIndex = parseInt(usePrivate ? c.slice(0, c.length - 1) : c, 10) & 0x7fffffff;
3887
3888 if (usePrivate) {
3889 childIndex += 0x80000000;
3890 }
3891
3892 bip32 = bip32.deriveChild(childIndex);
3893 }
3894
3895 return bip32;
3896 }
3897
3898 async asyncDerive(path) {
3899 const workersResult = await Workers.asyncObjectMethod(this, 'derive', [path]);
3900 return new this.constructor().fromFastBuffer(workersResult.resbuf);
3901 }
3902
3903 deriveChild(i) {
3904 if (typeof i !== 'number') {
3905 throw new Error('i must be a number');
3906 }
3907
3908 let ib = [];
3909 ib.push(i >> 24 & 0xff);
3910 ib.push(i >> 16 & 0xff);
3911 ib.push(i >> 8 & 0xff);
3912 ib.push(i & 0xff);
3913 ib = Buffer.from(ib);
3914 const usePrivate = (i & 0x80000000) !== 0;
3915 const isPrivate = this.versionBytesNum === this.Constants.privKey;
3916
3917 if (usePrivate && (!this.privKey || !isPrivate)) {
3918 throw new Error('Cannot do private key derivation without private key');
3919 }
3920
3921 let ret = null;
3922
3923 if (this.privKey) {
3924 let data = null;
3925
3926 if (usePrivate) {
3927 data = Buffer.concat([Buffer.from([0]), this.privKey.bn.toBuffer({
3928 size: 32
3929 }), ib]);
3930 } else {
3931 data = Buffer.concat([this.pubKey.toBuffer({
3932 size: 32
3933 }), ib]);
3934 }
3935
3936 const hash = Hash.sha512Hmac(data, this.chainCode);
3937 const il = Bn().fromBuffer(hash.slice(0, 32), {
3938 size: 32
3939 });
3940 const ir = hash.slice(32, 64);
3941 const k = il.add(this.privKey.bn).mod(Point.getN());
3942 ret = new this.constructor();
3943 ret.chainCode = ir;
3944 ret.privKey = new this.PrivKey().fromBn(k);
3945 ret.pubKey = new PubKey().fromPrivKey(ret.privKey);
3946 } else {
3947 const data = Buffer.concat([this.pubKey.toBuffer(), ib]);
3948 const hash = Hash.sha512Hmac(data, this.chainCode);
3949 const il = Bn().fromBuffer(hash.slice(0, 32));
3950 const ir = hash.slice(32, 64);
3951 const ilG = Point.getG().mul(il);
3952 const Kpar = this.pubKey.point;
3953 const Ki = ilG.add(Kpar);
3954 const newpub = new PubKey();
3955 newpub.point = Ki;
3956 ret = new this.constructor();
3957 ret.chainCode = ir;
3958 ret.pubKey = newpub;
3959 }
3960
3961 ret.childIndex = i;
3962 const pubKeyhash = Hash.sha256Ripemd160(this.pubKey.toBuffer());
3963 ret.parentFingerPrint = pubKeyhash.slice(0, 4);
3964 ret.versionBytesNum = this.versionBytesNum;
3965 ret.depth = this.depth + 1;
3966 return ret;
3967 }
3968
3969 toPublic() {
3970 const bip32 = new this.constructor().fromObject(this);
3971 bip32.versionBytesNum = this.Constants.pubKey;
3972 bip32.privKey = undefined;
3973 return bip32;
3974 }
3975
3976 toBuffer() {
3977 const isPrivate = this.versionBytesNum === this.Constants.privKey;
3978 const isPublic = this.versionBytesNum === this.Constants.pubKey;
3979
3980 if (isPrivate) {
3981 return new Bw().writeUInt32BE(this.versionBytesNum).writeUInt8(this.depth).write(this.parentFingerPrint).writeUInt32BE(this.childIndex).write(this.chainCode).writeUInt8(0).write(this.privKey.bn.toBuffer({
3982 size: 32
3983 })).toBuffer();
3984 } else if (isPublic) {
3985 if (this.pubKey.compressed === false) {
3986 throw new Error('cannot convert bip32 to buffer if pubKey is not compressed');
3987 }
3988
3989 return new Bw().writeUInt32BE(this.versionBytesNum).writeUInt8(this.depth).write(this.parentFingerPrint).writeUInt32BE(this.childIndex).write(this.chainCode).write(this.pubKey.toBuffer()).toBuffer();
3990 } else {
3991 throw new Error('bip32: invalid versionBytesNum byte');
3992 }
3993 }
3994
3995 toFastBuffer() {
3996 if (!this.versionBytesNum) {
3997 return Buffer.alloc(0);
3998 }
3999
4000 const isPrivate = this.versionBytesNum === this.Constants.privKey;
4001 const isPublic = this.versionBytesNum === this.Constants.pubKey;
4002
4003 if (isPrivate) {
4004 return new Bw().writeUInt32BE(this.versionBytesNum).writeUInt8(this.depth).write(this.parentFingerPrint).writeUInt32BE(this.childIndex).write(this.chainCode).writeUInt8(0).write(this.privKey.bn.toBuffer({
4005 size: 32
4006 })).toBuffer();
4007 } else if (isPublic) {
4008 return new Bw().writeUInt32BE(this.versionBytesNum).writeUInt8(this.depth).write(this.parentFingerPrint).writeUInt32BE(this.childIndex).write(this.chainCode).write(this.pubKey.toFastBuffer()).toBuffer();
4009 } else {
4010 throw new Error('bip32: invalid versionBytesNum byte');
4011 }
4012 }
4013
4014 toString() {
4015 return Base58Check.encode(this.toBuffer());
4016 }
4017
4018 async asyncToString() {
4019 const workersResult = await Workers.asyncObjectMethod(this, 'toString', []);
4020 return JSON.parse(workersResult.resbuf.toString());
4021 }
4022
4023 toJSON() {
4024 return this.toFastHex();
4025 }
4026
4027 fromJSON(json) {
4028 return this.fromFastHex(json);
4029 }
4030
4031 isPrivate() {
4032 return this.versionBytesNum === this.Constants.privKey;
4033 }
4034
4035}
4036
4037Bip32.Mainnet = class extends Bip32 {
4038 constructor(versionBytesNum, depth, parentFingerPrint, childIndex, chainCode, privKey, pubKey) {
4039 super(versionBytesNum, depth, parentFingerPrint, childIndex, chainCode, privKey, pubKey, Constants.Mainnet.Bip32, PrivKey.Mainnet);
4040 }
4041
4042};
4043Bip32.Testnet = class extends Bip32 {
4044 constructor(versionBytesNum, depth, parentFingerPrint, childIndex, chainCode, privKey, pubKey) {
4045 super(versionBytesNum, depth, parentFingerPrint, childIndex, chainCode, privKey, pubKey, Constants.Testnet.Bip32, PrivKey.Testnet);
4046 }
4047
4048};
4049
4050const wordList = ['abandon', 'ability', 'able', 'about', 'above', 'absent', 'absorb', 'abstract', 'absurd', 'abuse', 'access', 'accident', 'account', 'accuse', 'achieve', 'acid', 'acoustic', 'acquire', 'across', 'act', 'action', 'actor', 'actress', 'actual', 'adapt', 'add', 'addict', 'address', 'adjust', 'admit', 'adult', 'advance', 'advice', 'aerobic', 'affair', 'afford', 'afraid', 'again', 'age', 'agent', 'agree', 'ahead', 'aim', 'air', 'airport', 'aisle', 'alarm', 'album', 'alcohol', 'alert', 'alien', 'all', 'alley', 'allow', 'almost', 'alone', 'alpha', 'already', 'also', 'alter', 'always', 'amateur', 'amazing', 'among', 'amount', 'amused', 'analyst', 'anchor', 'ancient', 'anger', 'angle', 'angry', 'animal', 'ankle', 'announce', 'annual', 'another', 'answer', 'antenna', 'antique', 'anxiety', 'any', 'apart', 'apology', 'appear', 'apple', 'approve', 'april', 'arch', 'arctic', 'area', 'arena', 'argue', 'arm', 'armed', 'armor', 'army', 'around', 'arrange', 'arrest', 'arrive', 'arrow', 'art', 'artefact', 'artist', 'artwork', 'ask', 'aspect', 'assault', 'asset', 'assist', 'assume', 'asthma', 'athlete', 'atom', 'attack', 'attend', 'attitude', 'attract', 'auction', 'audit', 'august', 'aunt', 'author', 'auto', 'autumn', 'average', 'avocado', 'avoid', 'awake', 'aware', 'away', 'awesome', 'awful', 'awkward', 'axis', 'baby', 'bachelor', 'bacon', 'badge', 'bag', 'balance', 'balcony', 'ball', 'bamboo', 'banana', 'banner', 'bar', 'barely', 'bargain', 'barrel', 'base', 'basic', 'basket', 'battle', 'beach', 'bean', 'beauty', 'because', 'become', 'beef', 'before', 'begin', 'behave', 'behind', 'believe', 'below', 'belt', 'bench', 'benefit', 'best', 'betray', 'better', 'between', 'beyond', 'bicycle', 'bid', 'bike', 'bind', 'biology', 'bird', 'birth', 'bitter', 'black', 'blade', 'blame', 'blanket', 'blast', 'bleak', 'bless', 'blind', 'blood', 'blossom', 'blouse', 'blue', 'blur', 'blush', 'board', 'boat', 'body', 'boil', 'bomb', 'bone', 'bonus', 'book', 'boost', 'border', 'boring', 'borrow', 'boss', 'bottom', 'bounce', 'box', 'boy', 'bracket', 'brain', 'brand', 'brass', 'brave', 'bread', 'breeze', 'brick', 'bridge', 'brief', 'bright', 'bring', 'brisk', 'broccoli', 'broken', 'bronze', 'broom', 'brother', 'brown', 'brush', 'bubble', 'buddy', 'budget', 'buffalo', 'build', 'bulb', 'bulk', 'bullet', 'bundle', 'bunker', 'burden', 'burger', 'burst', 'bus', 'business', 'busy', 'butter', 'buyer', 'buzz', 'cabbage', 'cabin', 'cable', 'cactus', 'cage', 'cake', 'call', 'calm', 'camera', 'camp', 'can', 'canal', 'cancel', 'candy', 'cannon', 'canoe', 'canvas', 'canyon', 'capable', 'capital', 'captain', 'car', 'carbon', 'card', 'cargo', 'carpet', 'carry', 'cart', 'case', 'cash', 'casino', 'castle', 'casual', 'cat', 'catalog', 'catch', 'category', 'cattle', 'caught', 'cause', 'caution', 'cave', 'ceiling', 'celery', 'cement', 'census', 'century', 'cereal', 'certain', 'chair', 'chalk', 'champion', 'change', 'chaos', 'chapter', 'charge', 'chase', 'chat', 'cheap', 'check', 'cheese', 'chef', 'cherry', 'chest', 'chicken', 'chief', 'child', 'chimney', 'choice', 'choose', 'chronic', 'chuckle', 'chunk', 'churn', 'cigar', 'cinnamon', 'circle', 'citizen', 'city', 'civil', 'claim', 'clap', 'clarify', 'claw', 'clay', 'clean', 'clerk', 'clever', 'click', 'client', 'cliff', 'climb', 'clinic', 'clip', 'clock', 'clog', 'close', 'cloth', 'cloud', 'clown', 'club', 'clump', 'cluster', 'clutch', 'coach', 'coast', 'coconut', 'code', 'coffee', 'coil', 'coin', 'collect', 'color', 'column', 'combine', 'come', 'comfort', 'comic', 'common', 'company', 'concert', 'conduct', 'confirm', 'congress', 'connect', 'consider', 'control', 'convince', 'cook', 'cool', 'copper', 'copy', 'coral', 'core', 'corn', 'correct', 'cost', 'cotton', 'couch', 'country', 'couple', 'course', 'cousin', 'cover', 'coyote', 'crack', 'cradle', 'craft', 'cram', 'crane', 'crash', 'crater', 'crawl', 'crazy', 'cream', 'credit', 'creek', 'crew', 'cricket', 'crime', 'crisp', 'critic', 'crop', 'cross', 'crouch', 'crowd', 'crucial', 'cruel', 'cruise', 'crumble', 'crunch', 'crush', 'cry', 'crystal', 'cube', 'culture', 'cup', 'cupboard', 'curious', 'current', 'curtain', 'curve', 'cushion', 'custom', 'cute', 'cycle', 'dad', 'damage', 'damp', 'dance', 'danger', 'daring', 'dash', 'daughter', 'dawn', 'day', 'deal', 'debate', 'debris', 'decade', 'december', 'decide', 'decline', 'decorate', 'decrease', 'deer', 'defense', 'define', 'defy', 'degree', 'delay', 'deliver', 'demand', 'demise', 'denial', 'dentist', 'deny', 'depart', 'depend', 'deposit', 'depth', 'deputy', 'derive', 'describe', 'desert', 'design', 'desk', 'despair', 'destroy', 'detail', 'detect', 'develop', 'device', 'devote', 'diagram', 'dial', 'diamond', 'diary', 'dice', 'diesel', 'diet', 'differ', 'digital', 'dignity', 'dilemma', 'dinner', 'dinosaur', 'direct', 'dirt', 'disagree', 'discover', 'disease', 'dish', 'dismiss', 'disorder', 'display', 'distance', 'divert', 'divide', 'divorce', 'dizzy', 'doctor', 'document', 'dog', 'doll', 'dolphin', 'domain', 'donate', 'donkey', 'donor', 'door', 'dose', 'double', 'dove', 'draft', 'dragon', 'drama', 'drastic', 'draw', 'dream', 'dress', 'drift', 'drill', 'drink', 'drip', 'drive', 'drop', 'drum', 'dry', 'duck', 'dumb', 'dune', 'during', 'dust', 'dutch', 'duty', 'dwarf', 'dynamic', 'eager', 'eagle', 'early', 'earn', 'earth', 'easily', 'east', 'easy', 'echo', 'ecology', 'economy', 'edge', 'edit', 'educate', 'effort', 'egg', 'eight', 'either', 'elbow', 'elder', 'electric', 'elegant', 'element', 'elephant', 'elevator', 'elite', 'else', 'embark', 'embody', 'embrace', 'emerge', 'emotion', 'employ', 'empower', 'empty', 'enable', 'enact', 'end', 'endless', 'endorse', 'enemy', 'energy', 'enforce', 'engage', 'engine', 'enhance', 'enjoy', 'enlist', 'enough', 'enrich', 'enroll', 'ensure', 'enter', 'entire', 'entry', 'envelope', 'episode', 'equal', 'equip', 'era', 'erase', 'erode', 'erosion', 'error', 'erupt', 'escape', 'essay', 'essence', 'estate', 'eternal', 'ethics', 'evidence', 'evil', 'evoke', 'evolve', 'exact', 'example', 'excess', 'exchange', 'excite', 'exclude', 'excuse', 'execute', 'exercise', 'exhaust', 'exhibit', 'exile', 'exist', 'exit', 'exotic', 'expand', 'expect', 'expire', 'explain', 'expose', 'express', 'extend', 'extra', 'eye', 'eyebrow', 'fabric', 'face', 'faculty', 'fade', 'faint', 'faith', 'fall', 'false', 'fame', 'family', 'famous', 'fan', 'fancy', 'fantasy', 'farm', 'fashion', 'fat', 'fatal', 'father', 'fatigue', 'fault', 'favorite', 'feature', 'february', 'federal', 'fee', 'feed', 'feel', 'female', 'fence', 'festival', 'fetch', 'fever', 'few', 'fiber', 'fiction', 'field', 'figure', 'file', 'film', 'filter', 'final', 'find', 'fine', 'finger', 'finish', 'fire', 'firm', 'first', 'fiscal', 'fish', 'fit', 'fitness', 'fix', 'flag', 'flame', 'flash', 'flat', 'flavor', 'flee', 'flight', 'flip', 'float', 'flock', 'floor', 'flower', 'fluid', 'flush', 'fly', 'foam', 'focus', 'fog', 'foil', 'fold', 'follow', 'food', 'foot', 'force', 'forest', 'forget', 'fork', 'fortune', 'forum', 'forward', 'fossil', 'foster', 'found', 'fox', 'fragile', 'frame', 'frequent', 'fresh', 'friend', 'fringe', 'frog', 'front', 'frost', 'frown', 'frozen', 'fruit', 'fuel', 'fun', 'funny', 'furnace', 'fury', 'future', 'gadget', 'gain', 'galaxy', 'gallery', 'game', 'gap', 'garage', 'garbage', 'garden', 'garlic', 'garment', 'gas', 'gasp', 'gate', 'gather', 'gauge', 'gaze', 'general', 'genius', 'genre', 'gentle', 'genuine', 'gesture', 'ghost', 'giant', 'gift', 'giggle', 'ginger', 'giraffe', 'girl', 'give', 'glad', 'glance', 'glare', 'glass', 'glide', 'glimpse', 'globe', 'gloom', 'glory', 'glove', 'glow', 'glue', 'goat', 'goddess', 'gold', 'good', 'goose', 'gorilla', 'gospel', 'gossip', 'govern', 'gown', 'grab', 'grace', 'grain', 'grant', 'grape', 'grass', 'gravity', 'great', 'green', 'grid', 'grief', 'grit', 'grocery', 'group', 'grow', 'grunt', 'guard', 'guess', 'guide', 'guilt', 'guitar', 'gun', 'gym', 'habit', 'hair', 'half', 'hammer', 'hamster', 'hand', 'happy', 'harbor', 'hard', 'harsh', 'harvest', 'hat', 'have', 'hawk', 'hazard', 'head', 'health', 'heart', 'heavy', 'hedgehog', 'height', 'hello', 'helmet', 'help', 'hen', 'hero', 'hidden', 'high', 'hill', 'hint', 'hip', 'hire', 'history', 'hobby', 'hockey', 'hold', 'hole', 'holiday', 'hollow', 'home', 'honey', 'hood', 'hope', 'horn', 'horror', 'horse', 'hospital', 'host', 'hotel', 'hour', 'hover', 'hub', 'huge', 'human', 'humble', 'humor', 'hundred', 'hungry', 'hunt', 'hurdle', 'hurry', 'hurt', 'husband', 'hybrid', 'ice', 'icon', 'idea', 'identify', 'idle', 'ignore', 'ill', 'illegal', 'illness', 'image', 'imitate', 'immense', 'immune', 'impact', 'impose', 'improve', 'impulse', 'inch', 'include', 'income', 'increase', 'index', 'indicate', 'indoor', 'industry', 'infant', 'inflict', 'inform', 'inhale', 'inherit', 'initial', 'inject', 'injury', 'inmate', 'inner', 'innocent', 'input', 'inquiry', 'insane', 'insect', 'inside', 'inspire', 'install', 'intact', 'interest', 'into', 'invest', 'invite', 'involve', 'iron', 'island', 'isolate', 'issue', 'item', 'ivory', 'jacket', 'jaguar', 'jar', 'jazz', 'jealous', 'jeans', 'jelly', 'jewel', 'job', 'join', 'joke', 'journey', 'joy', 'judge', 'juice', 'jump', 'jungle', 'junior', 'junk', 'just', 'kangaroo', 'keen', 'keep', 'ketchup', 'key', 'kick', 'kid', 'kidney', 'kind', 'kingdom', 'kiss', 'kit', 'kitchen', 'kite', 'kitten', 'kiwi', 'knee', 'knife', 'knock', 'know', 'lab', 'label', 'labor', 'ladder', 'lady', 'lake', 'lamp', 'language', 'laptop', 'large', 'later', 'latin', 'laugh', 'laundry', 'lava', 'law', 'lawn', 'lawsuit', 'layer', 'lazy', 'leader', 'leaf', 'learn', 'leave', 'lecture', 'left', 'leg', 'legal', 'legend', 'leisure', 'lemon', 'lend', 'length', 'lens', 'leopard', 'lesson', 'letter', 'level', 'liar', 'liberty', 'library', 'license', 'life', 'lift', 'light', 'like', 'limb', 'limit', 'link', 'lion', 'liquid', 'list', 'little', 'live', 'lizard', 'load', 'loan', 'lobster', 'local', 'lock', 'logic', 'lonely', 'long', 'loop', 'lottery', 'loud', 'lounge', 'love', 'loyal', 'lucky', 'luggage', 'lumber', 'lunar', 'lunch', 'luxury', 'lyrics', 'machine', 'mad', 'magic', 'magnet', 'maid', 'mail', 'main', 'major', 'make', 'mammal', 'man', 'manage', 'mandate', 'mango', 'mansion', 'manual', 'maple', 'marble', 'march', 'margin', 'marine', 'market', 'marriage', 'mask', 'mass', 'master', 'match', 'material', 'math', 'matrix', 'matter', 'maximum', 'maze', 'meadow', 'mean', 'measure', 'meat', 'mechanic', 'medal', 'media', 'melody', 'melt', 'member', 'memory', 'mention', 'menu', 'mercy', 'merge', 'merit', 'merry', 'mesh', 'message', 'metal', 'method', 'middle', 'midnight', 'milk', 'million', 'mimic', 'mind', 'minimum', 'minor', 'minute', 'miracle', 'mirror', 'misery', 'miss', 'mistake', 'mix', 'mixed', 'mixture', 'mobile', 'model', 'modify', 'mom', 'moment', 'monitor', 'monkey', 'monster', 'month', 'moon', 'moral', 'more', 'morning', 'mosquito', 'mother', 'motion', 'motor', 'mountain', 'mouse', 'move', 'movie', 'much', 'muffin', 'mule', 'multiply', 'muscle', 'museum', 'mushroom', 'music', 'must', 'mutual', 'myself', 'mystery', 'myth', 'naive', 'name', 'napkin', 'narrow', 'nasty', 'nation', 'nature', 'near', 'neck', 'need', 'negative', 'neglect', 'neither', 'nephew', 'nerve', 'nest', 'net', 'network', 'neutral', 'never', 'news', 'next', 'nice', 'night', 'noble', 'noise', 'nominee', 'noodle', 'normal', 'north', 'nose', 'notable', 'note', 'nothing', 'notice', 'novel', 'now', 'nuclear', 'number', 'nurse', 'nut', 'oak', 'obey', 'object', 'oblige', 'obscure', 'observe', 'obtain', 'obvious', 'occur', 'ocean', 'october', 'odor', 'off', 'offer', 'office', 'often', 'oil', 'okay', 'old', 'olive', 'olympic', 'omit', 'once', 'one', 'onion', 'online', 'only', 'open', 'opera', 'opinion', 'oppose', 'option', 'orange', 'orbit', 'orchard', 'order', 'ordinary', 'organ', 'orient', 'original', 'orphan', 'ostrich', 'other', 'outdoor', 'outer', 'output', 'outside', 'oval', 'oven', 'over', 'own', 'owner', 'oxygen', 'oyster', 'ozone', 'pact', 'paddle', 'page', 'pair', 'palace', 'palm', 'panda', 'panel', 'panic', 'panther', 'paper', 'parade', 'parent', 'park', 'parrot', 'party', 'pass', 'patch', 'path', 'patient', 'patrol', 'pattern', 'pause', 'pave', 'payment', 'peace', 'peanut', 'pear', 'peasant', 'pelican', 'pen', 'penalty', 'pencil', 'people', 'pepper', 'perfect', 'permit', 'person', 'pet', 'phone', 'photo', 'phrase', 'physical', 'piano', 'picnic', 'picture', 'piece', 'pig', 'pigeon', 'pill', 'pilot', 'pink', 'pioneer', 'pipe', 'pistol', 'pitch', 'pizza', 'place', 'planet', 'plastic', 'plate', 'play', 'please', 'pledge', 'pluck', 'plug', 'plunge', 'poem', 'poet', 'point', 'polar', 'pole', 'police', 'pond', 'pony', 'pool', 'popular', 'portion', 'position', 'possible', 'post', 'potato', 'pottery', 'poverty', 'powder', 'power', 'practice', 'praise', 'predict', 'prefer', 'prepare', 'present', 'pretty', 'prevent', 'price', 'pride', 'primary', 'print', 'priority', 'prison', 'private', 'prize', 'problem', 'process', 'produce', 'profit', 'program', 'project', 'promote', 'proof', 'property', 'prosper', 'protect', 'proud', 'provide', 'public', 'pudding', 'pull', 'pulp', 'pulse', 'pumpkin', 'punch', 'pupil', 'puppy', 'purchase', 'purity', 'purpose', 'purse', 'push', 'put', 'puzzle', 'pyramid', 'quality', 'quantum', 'quarter', 'question', 'quick', 'quit', 'quiz', 'quote', 'rabbit', 'raccoon', 'race', 'rack', 'radar', 'radio', 'rail', 'rain', 'raise', 'rally', 'ramp', 'ranch', 'random', 'range', 'rapid', 'rare', 'rate', 'rather', 'raven', 'raw', 'razor', 'ready', 'real', 'reason', 'rebel', 'rebuild', 'recall', 'receive', 'recipe', 'record', 'recycle', 'reduce', 'reflect', 'reform', 'refuse', 'region', 'regret', 'regular', 'reject', 'relax', 'release', 'relief', 'rely', 'remain', 'remember', 'remind', 'remove', 'render', 'renew', 'rent', 'reopen', 'repair', 'repeat', 'replace', 'report', 'require', 'rescue', 'resemble', 'resist', 'resource', 'response', 'result', 'retire', 'retreat', 'return', 'reunion', 'reveal', 'review', 'reward', 'rhythm', 'rib', 'ribbon', 'rice', 'rich', 'ride', 'ridge', 'rifle', 'right', 'rigid', 'ring', 'riot', 'ripple', 'risk', 'ritual', 'rival', 'river', 'road', 'roast', 'robot', 'robust', 'rocket', 'romance', 'roof', 'rookie', 'room', 'rose', 'rotate', 'rough', 'round', 'route', 'royal', 'rubber', 'rude', 'rug', 'rule', 'run', 'runway', 'rural', 'sad', 'saddle', 'sadness', 'safe', 'sail', 'salad', 'salmon', 'salon', 'salt', 'salute', 'same', 'sample', 'sand', 'satisfy', 'satoshi', 'sauce', 'sausage', 'save', 'say', 'scale', 'scan', 'scare', 'scatter', 'scene', 'scheme', 'school', 'science', 'scissors', 'scorpion', 'scout', 'scrap', 'screen', 'script', 'scrub', 'sea', 'search', 'season', 'seat', 'second', 'secret', 'section', 'security', 'seed', 'seek', 'segment', 'select', 'sell', 'seminar', 'senior', 'sense', 'sentence', 'series', 'service', 'session', 'settle', 'setup', 'seven', 'shadow', 'shaft', 'shallow', 'share', 'shed', 'shell', 'sheriff', 'shield', 'shift', 'shine', 'ship', 'shiver', 'shock', 'shoe', 'shoot', 'shop', 'short', 'shoulder', 'shove', 'shrimp', 'shrug', 'shuffle', 'shy', 'sibling', 'sick', 'side', 'siege', 'sight', 'sign', 'silent', 'silk', 'silly', 'silver', 'similar', 'simple', 'since', 'sing', 'siren', 'sister', 'situate', 'six', 'size', 'skate', 'sketch', 'ski', 'skill', 'skin', 'skirt', 'skull', 'slab', 'slam', 'sleep', 'slender', 'slice', 'slide', 'slight', 'slim', 'slogan', 'slot', 'slow', 'slush', 'small', 'smart', 'smile', 'smoke', 'smooth', 'snack', 'snake', 'snap', 'sniff', 'snow', 'soap', 'soccer', 'social', 'sock', 'soda', 'soft', 'solar', 'soldier', 'solid', 'solution', 'solve', 'someone', 'song', 'soon', 'sorry', 'sort', 'soul', 'sound', 'soup', 'source', 'south', 'space', 'spare', 'spatial', 'spawn', 'speak', 'special', 'speed', 'spell', 'spend', 'sphere', 'spice', 'spider', 'spike', 'spin', 'spirit', 'split', 'spoil', 'sponsor', 'spoon', 'sport', 'spot', 'spray', 'spread', 'spring', 'spy', 'square', 'squeeze', 'squirrel', 'stable', 'stadium', 'staff', 'stage', 'stairs', 'stamp', 'stand', 'start', 'state', 'stay', 'steak', 'steel', 'stem', 'step', 'stereo', 'stick', 'still', 'sting', 'stock', 'stomach', 'stone', 'stool', 'story', 'stove', 'strategy', 'street', 'strike', 'strong', 'struggle', 'student', 'stuff', 'stumble', 'style', 'subject', 'submit', 'subway', 'success', 'such', 'sudden', 'suffer', 'sugar', 'suggest', 'suit', 'summer', 'sun', 'sunny', 'sunset', 'super', 'supply', 'supreme', 'sure', 'surface', 'surge', 'surprise', 'surround', 'survey', 'suspect', 'sustain', 'swallow', 'swamp', 'swap', 'swarm', 'swear', 'sweet', 'swift', 'swim', 'swing', 'switch', 'sword', 'symbol', 'symptom', 'syrup', 'system', 'table', 'tackle', 'tag', 'tail', 'talent', 'talk', 'tank', 'tape', 'target', 'task', 'taste', 'tattoo', 'taxi', 'teach', 'team', 'tell', 'ten', 'tenant', 'tennis', 'tent', 'term', 'test', 'text', 'thank', 'that', 'theme', 'then', 'theory', 'there', 'they', 'thing', 'this', 'thought', 'three', 'thrive', 'throw', 'thumb', 'thunder', 'ticket', 'tide', 'tiger', 'tilt', 'timber', 'time', 'tiny', 'tip', 'tired', 'tissue', 'title', 'toast', 'tobacco', 'today', 'toddler', 'toe', 'together', 'toilet', 'token', 'tomato', 'tomorrow', 'tone', 'tongue', 'tonight', 'tool', 'tooth', 'top', 'topic', 'topple', 'torch', 'tornado', 'tortoise', 'toss', 'total', 'tourist', 'toward', 'tower', 'town', 'toy', 'track', 'trade', 'traffic', 'tragic', 'train', 'transfer', 'trap', 'trash', 'travel', 'tray', 'treat', 'tree', 'trend', 'trial', 'tribe', 'trick', 'trigger', 'trim', 'trip', 'trophy', 'trouble', 'truck', 'true', 'truly', 'trumpet', 'trust', 'truth', 'try', 'tube', 'tuition', 'tumble', 'tuna', 'tunnel', 'turkey', 'turn', 'turtle', 'twelve', 'twenty', 'twice', 'twin', 'twist', 'two', 'type', 'typical', 'ugly', 'umbrella', 'unable', 'unaware', 'uncle', 'uncover', 'under', 'undo', 'unfair', 'unfold', 'unhappy', 'uniform', 'unique', 'unit', 'universe', 'unknown', 'unlock', 'until', 'unusual', 'unveil', 'update', 'upgrade', 'uphold', 'upon', 'upper', 'upset', 'urban', 'urge', 'usage', 'use', 'used', 'useful', 'useless', 'usual', 'utility', 'vacant', 'vacuum', 'vague', 'valid', 'valley', 'valve', 'van', 'vanish', 'vapor', 'various', 'vast', 'vault', 'vehicle', 'velvet', 'vendor', 'venture', 'venue', 'verb', 'verify', 'version', 'very', 'vessel', 'veteran', 'viable', 'vibrant', 'vicious', 'victory', 'video', 'view', 'village', 'vintage', 'violin', 'virtual', 'virus', 'visa', 'visit', 'visual', 'vital', 'vivid', 'vocal', 'voice', 'void', 'volcano', 'volume', 'vote', 'voyage', 'wage', 'wagon', 'wait', 'walk', 'wall', 'walnut', 'want', 'warfare', 'warm', 'warrior', 'wash', 'wasp', 'waste', 'water', 'wave', 'way', 'wealth', 'weapon', 'wear', 'weasel', 'weather', 'web', 'wedding', 'weekend', 'weird', 'welcome', 'west', 'wet', 'whale', 'what', 'wheat', 'wheel', 'when', 'where', 'whip', 'whisper', 'wide', 'width', 'wife', 'wild', 'will', 'win', 'window', 'wine', 'wing', 'wink', 'winner', 'winter', 'wire', 'wisdom', 'wise', 'wish', 'witness', 'wolf', 'woman', 'wonder', 'wood', 'wool', 'word', 'work', 'world', 'worry', 'worth', 'wrap', 'wreck', 'wrestle', 'wrist', 'write', 'wrong', 'yard', 'year', 'yellow', 'you', 'young', 'youth', 'zebra', 'zero', 'zone', 'zoo'];
4051wordList.space = ' ';
4052
4053class Bip39 extends Struct {
4054 constructor(mnemonic, seed, wordlist = wordList) {
4055 super({
4056 mnemonic,
4057 seed
4058 });
4059 this.Wordlist = wordlist;
4060 }
4061
4062 toBw(bw) {
4063 if (!bw) {
4064 bw = new Bw();
4065 }
4066
4067 if (this.mnemonic) {
4068 const buf = Buffer.from(this.mnemonic);
4069 bw.writeVarIntNum(buf.length);
4070 bw.write(buf);
4071 } else {
4072 bw.writeVarIntNum(0);
4073 }
4074
4075 if (this.seed) {
4076 bw.writeVarIntNum(this.seed.length);
4077 bw.write(this.seed);
4078 } else {
4079 bw.writeVarIntNum(0);
4080 }
4081
4082 return bw;
4083 }
4084
4085 fromBr(br) {
4086 const mnemoniclen = br.readVarIntNum();
4087
4088 if (mnemoniclen > 0) {
4089 this.mnemonic = br.read(mnemoniclen).toString();
4090 }
4091
4092 const seedlen = br.readVarIntNum();
4093
4094 if (seedlen > 0) {
4095 this.seed = br.read(seedlen);
4096 }
4097
4098 return this;
4099 }
4100
4101 fromRandom(bits) {
4102 if (!bits) {
4103 bits = 128;
4104 }
4105
4106 if (bits % 32 !== 0) {
4107 throw new Error('bits must be multiple of 32');
4108 }
4109
4110 if (bits < 128) {
4111 throw new Error('bits must be at least 128');
4112 }
4113
4114 const buf = Random.getRandomBuffer(bits / 8);
4115 this.entropy2Mnemonic(buf);
4116 this.mnemonic2Seed();
4117 return this;
4118 }
4119
4120 static fromRandom(bits) {
4121 return new this().fromRandom(bits);
4122 }
4123
4124 async asyncFromRandom(bits) {
4125 if (!bits) {
4126 bits = 128;
4127 }
4128
4129 const buf = Random.getRandomBuffer(bits / 8);
4130 let workersResult = await Workers.asyncObjectMethod(this, 'entropy2Mnemonic', [buf]);
4131 const bip39 = new Bip39().fromFastBuffer(workersResult.resbuf);
4132 workersResult = await Workers.asyncObjectMethod(bip39, 'mnemonic2Seed', []);
4133 return this.fromFastBuffer(workersResult.resbuf);
4134 }
4135
4136 static asyncFromRandom(bits) {
4137 return new this().asyncFromRandom(bits);
4138 }
4139
4140 fromEntropy(buf) {
4141 this.entropy2Mnemonic(buf);
4142 return this;
4143 }
4144
4145 static fromEntropy(buf) {
4146 return new this().fromEntropy(buf);
4147 }
4148
4149 async asyncFromEntropy(buf) {
4150 const workersResult = await Workers.asyncObjectMethod(this, 'fromEntropy', [buf]);
4151 return this.fromFastBuffer(workersResult.resbuf);
4152 }
4153
4154 static asyncFromEntropy(buf) {
4155 return new this().asyncFromEntropy(buf);
4156 }
4157
4158 fromString(mnemonic) {
4159 this.mnemonic = mnemonic;
4160 return this;
4161 }
4162
4163 toString() {
4164 return this.mnemonic;
4165 }
4166
4167 toSeed(passphrase) {
4168 this.mnemonic2Seed(passphrase);
4169 return this.seed;
4170 }
4171
4172 async asyncToSeed(passphrase) {
4173 if (passphrase === undefined) {
4174 passphrase = '';
4175 }
4176
4177 const args = [passphrase];
4178 const workersResult = await Workers.asyncObjectMethod(this, 'toSeed', args);
4179 return workersResult.resbuf;
4180 }
4181
4182 entropy2Mnemonic(buf) {
4183 if (!Buffer.isBuffer(buf) || buf.length < 128 / 8) {
4184 throw new Error('Entropy is less than 128 bits. It must be 128 bits or more.');
4185 }
4186
4187 const hash = Hash.sha256(buf);
4188 let bin = '';
4189 const bits = buf.length * 8;
4190
4191 for (let i = 0; i < buf.length; i++) {
4192 bin = bin + ('00000000' + buf[i].toString(2)).slice(-8);
4193 }
4194
4195 let hashbits = hash[0].toString(2);
4196 hashbits = ('00000000' + hashbits).slice(-8).slice(0, bits / 32);
4197 bin = bin + hashbits;
4198
4199 if (bin.length % 11 !== 0) {
4200 throw new Error('internal error - entropy not an even multiple of 11 bits - ' + bin.length);
4201 }
4202
4203 let mnemonic = '';
4204
4205 for (let i = 0; i < bin.length / 11; i++) {
4206 if (mnemonic !== '') {
4207 mnemonic = mnemonic + this.Wordlist.space;
4208 }
4209
4210 const wi = parseInt(bin.slice(i * 11, (i + 1) * 11), 2);
4211 mnemonic = mnemonic + this.Wordlist[wi];
4212 }
4213
4214 this.mnemonic = mnemonic;
4215 return this;
4216 }
4217
4218 check() {
4219 const mnemonic = this.mnemonic;
4220 const words = mnemonic.split(this.Wordlist.space);
4221 let bin = '';
4222
4223 for (let i = 0; i < words.length; i++) {
4224 const ind = this.Wordlist.indexOf(words[i]);
4225
4226 if (ind < 0) {
4227 return false;
4228 }
4229
4230 bin = bin + ('00000000000' + ind.toString(2)).slice(-11);
4231 }
4232
4233 if (bin.length % 11 !== 0) {
4234 throw new Error('internal error - entropy not an even multiple of 11 bits - ' + bin.length);
4235 }
4236
4237 const cs = bin.length / 33;
4238 const hashBits = bin.slice(-cs);
4239 const nonhashBits = bin.slice(0, bin.length - cs);
4240 const buf = Buffer.alloc(nonhashBits.length / 8);
4241
4242 for (let i = 0; i < nonhashBits.length / 8; i++) {
4243 buf.writeUInt8(parseInt(bin.slice(i * 8, (i + 1) * 8), 2), i);
4244 }
4245
4246 const hash = Hash.sha256(buf);
4247 let expectedHashBits = hash[0].toString(2);
4248 expectedHashBits = ('00000000' + expectedHashBits).slice(-8).slice(0, cs);
4249 return expectedHashBits === hashBits;
4250 }
4251
4252 mnemonic2Seed(passphrase = '') {
4253 let mnemonic = this.mnemonic;
4254
4255 if (!this.check()) {
4256 throw new Error('Mnemonic does not pass the check - was the mnemonic typed incorrectly? Are there extra spaces?');
4257 }
4258
4259 if (typeof passphrase !== 'string') {
4260 throw new Error('passphrase must be a string or undefined');
4261 }
4262
4263 mnemonic = mnemonic.normalize('NFKD');
4264 passphrase = passphrase.normalize('NFKD');
4265 const mbuf = Buffer.from(mnemonic);
4266 const pbuf = Buffer.concat([Buffer.from('mnemonic'), Buffer.from(passphrase)]);
4267 this.seed = pbkdf2.pbkdf2Sync(mbuf, pbuf, 2048, 64, 'sha512');
4268 return this;
4269 }
4270
4271 isValid(passphrase = '') {
4272 let isValid;
4273
4274 try {
4275 isValid = !!this.mnemonic2Seed(passphrase);
4276 } catch (err) {
4277 isValid = false;
4278 }
4279
4280 return isValid;
4281 }
4282
4283 static isValid(mnemonic, passphrase = '') {
4284 return new Bip39(mnemonic).isValid(passphrase);
4285 }
4286
4287}
4288
4289const wordList$1 = ['あいこくしん', 'あいさつ', 'あいだ', 'あおぞら', 'あかちゃん', 'あきる', 'あけがた', 'あける', 'あこがれる', 'あさい', 'あさひ', 'あしあと', 'あじわう', 'あずかる', 'あずき', 'あそぶ', 'あたえる', 'あたためる', 'あたりまえ', 'あたる', 'あつい', 'あつかう', 'あっしゅく', 'あつまり', 'あつめる', 'あてな', 'あてはまる', 'あひる', 'あぶら', 'あぶる', 'あふれる', 'あまい', 'あまど', 'あまやかす', 'あまり', 'あみもの', 'あめりか', 'あやまる', 'あゆむ', 'あらいぐま', 'あらし', 'あらすじ', 'あらためる', 'あらゆる', 'あらわす', 'ありがとう', 'あわせる', 'あわてる', 'あんい', 'あんがい', 'あんこ', 'あんぜん', 'あんてい', 'あんない', 'あんまり', 'いいだす', 'いおん', 'いがい', 'いがく', 'いきおい', 'いきなり', 'いきもの', 'いきる', 'いくじ', 'いくぶん', 'いけばな', 'いけん', 'いこう', 'いこく', 'いこつ', 'いさましい', 'いさん', 'いしき', 'いじゅう', 'いじょう', 'いじわる', 'いずみ', 'いずれ', 'いせい', 'いせえび', 'いせかい', 'いせき', 'いぜん', 'いそうろう', 'いそがしい', 'いだい', 'いだく', 'いたずら', 'いたみ', 'いたりあ', 'いちおう', 'いちじ', 'いちど', 'いちば', 'いちぶ', 'いちりゅう', 'いつか', 'いっしゅん', 'いっせい', 'いっそう', 'いったん', 'いっち', 'いってい', 'いっぽう', 'いてざ', 'いてん', 'いどう', 'いとこ', 'いない', 'いなか', 'いねむり', 'いのち', 'いのる', 'いはつ', 'いばる', 'いはん', 'いびき', 'いひん', 'いふく', 'いへん', 'いほう', 'いみん', 'いもうと', 'いもたれ', 'いもり', 'いやがる', 'いやす', 'いよかん', 'いよく', 'いらい', 'いらすと', 'いりぐち', 'いりょう', 'いれい', 'いれもの', 'いれる', 'いろえんぴつ', 'いわい', 'いわう', 'いわかん', 'いわば', 'いわゆる', 'いんげんまめ', 'いんさつ', 'いんしょう', 'いんよう', 'うえき', 'うえる', 'うおざ', 'うがい', 'うかぶ', 'うかべる', 'うきわ', 'うくらいな', 'うくれれ', 'うけたまわる', 'うけつけ', 'うけとる', 'うけもつ', 'うける', 'うごかす', 'うごく', 'うこん', 'うさぎ', 'うしなう', 'うしろがみ', 'うすい', 'うすぎ', 'うすぐらい', 'うすめる', 'うせつ', 'うちあわせ', 'うちがわ', 'うちき', 'うちゅう', 'うっかり', 'うつくしい', 'うったえる', 'うつる', 'うどん', 'うなぎ', 'うなじ', 'うなずく', 'うなる', 'うねる', 'うのう', 'うぶげ', 'うぶごえ', 'うまれる', 'うめる', 'うもう', 'うやまう', 'うよく', 'うらがえす', 'うらぐち', 'うらない', 'うりあげ', 'うりきれ', 'うるさい', 'うれしい', 'うれゆき', 'うれる', 'うろこ', 'うわき', 'うわさ', 'うんこう', 'うんちん', 'うんてん', 'うんどう', 'えいえん', 'えいが', 'えいきょう', 'えいご', 'えいせい', 'えいぶん', 'えいよう', 'えいわ', 'えおり', 'えがお', 'えがく', 'えきたい', 'えくせる', 'えしゃく', 'えすて', 'えつらん', 'えのぐ', 'えほうまき', 'えほん', 'えまき', 'えもじ', 'えもの', 'えらい', 'えらぶ', 'えりあ', 'えんえん', 'えんかい', 'えんぎ', 'えんげき', 'えんしゅう', 'えんぜつ', 'えんそく', 'えんちょう', 'えんとつ', 'おいかける', 'おいこす', 'おいしい', 'おいつく', 'おうえん', 'おうさま', 'おうじ', 'おうせつ', 'おうたい', 'おうふく', 'おうべい', 'おうよう', 'おえる', 'おおい', 'おおう', 'おおどおり', 'おおや', 'おおよそ', 'おかえり', 'おかず', 'おがむ', 'おかわり', 'おぎなう', 'おきる', 'おくさま', 'おくじょう', 'おくりがな', 'おくる', 'おくれる', 'おこす', 'おこなう', 'おこる', 'おさえる', 'おさない', 'おさめる', 'おしいれ', 'おしえる', 'おじぎ', 'おじさん', 'おしゃれ', 'おそらく', 'おそわる', 'おたがい', 'おたく', 'おだやか', 'おちつく', 'おっと', 'おつり', 'おでかけ', 'おとしもの', 'おとなしい', 'おどり', 'おどろかす', 'おばさん', 'おまいり', 'おめでとう', 'おもいで', 'おもう', 'おもたい', 'おもちゃ', 'おやつ', 'おやゆび', 'およぼす', 'おらんだ', 'おろす', 'おんがく', 'おんけい', 'おんしゃ', 'おんせん', 'おんだん', 'おんちゅう', 'おんどけい', 'かあつ', 'かいが', 'がいき', 'がいけん', 'がいこう', 'かいさつ', 'かいしゃ', 'かいすいよく', 'かいぜん', 'かいぞうど', 'かいつう', 'かいてん', 'かいとう', 'かいふく', 'がいへき', 'かいほう', 'かいよう', 'がいらい', 'かいわ', 'かえる', 'かおり', 'かかえる', 'かがく', 'かがし', 'かがみ', 'かくご', 'かくとく', 'かざる', 'がぞう', 'かたい', 'かたち', 'がちょう', 'がっきゅう', 'がっこう', 'がっさん', 'がっしょう', 'かなざわし', 'かのう', 'がはく', 'かぶか', 'かほう', 'かほご', 'かまう', 'かまぼこ', 'かめれおん', 'かゆい', 'かようび', 'からい', 'かるい', 'かろう', 'かわく', 'かわら', 'がんか', 'かんけい', 'かんこう', 'かんしゃ', 'かんそう', 'かんたん', 'かんち', 'がんばる', 'きあい', 'きあつ', 'きいろ', 'ぎいん', 'きうい', 'きうん', 'きえる', 'きおう', 'きおく', 'きおち', 'きおん', 'きかい', 'きかく', 'きかんしゃ', 'ききて', 'きくばり', 'きくらげ', 'きけんせい', 'きこう', 'きこえる', 'きこく', 'きさい', 'きさく', 'きさま', 'きさらぎ', 'ぎじかがく', 'ぎしき', 'ぎじたいけん', 'ぎじにってい', 'ぎじゅつしゃ', 'きすう', 'きせい', 'きせき', 'きせつ', 'きそう', 'きぞく', 'きぞん', 'きたえる', 'きちょう', 'きつえん', 'ぎっちり', 'きつつき', 'きつね', 'きてい', 'きどう', 'きどく', 'きない', 'きなが', 'きなこ', 'きぬごし', 'きねん', 'きのう', 'きのした', 'きはく', 'きびしい', 'きひん', 'きふく', 'きぶん', 'きぼう', 'きほん', 'きまる', 'きみつ', 'きむずかしい', 'きめる', 'きもだめし', 'きもち', 'きもの', 'きゃく', 'きやく', 'ぎゅうにく', 'きよう', 'きょうりゅう', 'きらい', 'きらく', 'きりん', 'きれい', 'きれつ', 'きろく', 'ぎろん', 'きわめる', 'ぎんいろ', 'きんかくじ', 'きんじょ', 'きんようび', 'ぐあい', 'くいず', 'くうかん', 'くうき', 'くうぐん', 'くうこう', 'ぐうせい', 'くうそう', 'ぐうたら', 'くうふく', 'くうぼ', 'くかん', 'くきょう', 'くげん', 'ぐこう', 'くさい', 'くさき', 'くさばな', 'くさる', 'くしゃみ', 'くしょう', 'くすのき', 'くすりゆび', 'くせげ', 'くせん', 'ぐたいてき', 'くださる', 'くたびれる', 'くちこみ', 'くちさき', 'くつした', 'ぐっすり', 'くつろぐ', 'くとうてん', 'くどく', 'くなん', 'くねくね', 'くのう', 'くふう', 'くみあわせ', 'くみたてる', 'くめる', 'くやくしょ', 'くらす', 'くらべる', 'くるま', 'くれる', 'くろう', 'くわしい', 'ぐんかん', 'ぐんしょく', 'ぐんたい', 'ぐんて', 'けあな', 'けいかく', 'けいけん', 'けいこ', 'けいさつ', 'げいじゅつ', 'けいたい', 'げいのうじん', 'けいれき', 'けいろ', 'けおとす', 'けおりもの', 'げきか', 'げきげん', 'げきだん', 'げきちん', 'げきとつ', 'げきは', 'げきやく', 'げこう', 'げこくじょう', 'げざい', 'けさき', 'げざん', 'けしき', 'けしごむ', 'けしょう', 'げすと', 'けたば', 'けちゃっぷ', 'けちらす', 'けつあつ', 'けつい', 'けつえき', 'けっこん', 'けつじょ', 'けっせき', 'けってい', 'けつまつ', 'げつようび', 'げつれい', 'けつろん', 'げどく', 'けとばす', 'けとる', 'けなげ', 'けなす', 'けなみ', 'けぬき', 'げねつ', 'けねん', 'けはい', 'げひん', 'けぶかい', 'げぼく', 'けまり', 'けみかる', 'けむし', 'けむり', 'けもの', 'けらい', 'けろけろ', 'けわしい', 'けんい', 'けんえつ', 'けんお', 'けんか', 'げんき', 'けんげん', 'けんこう', 'けんさく', 'けんしゅう', 'けんすう', 'げんそう', 'けんちく', 'けんてい', 'けんとう', 'けんない', 'けんにん', 'げんぶつ', 'けんま', 'けんみん', 'けんめい', 'けんらん', 'けんり', 'こあくま', 'こいぬ', 'こいびと', 'ごうい', 'こうえん', 'こうおん', 'こうかん', 'ごうきゅう', 'ごうけい', 'こうこう', 'こうさい', 'こうじ', 'こうすい', 'ごうせい', 'こうそく', 'こうたい', 'こうちゃ', 'こうつう', 'こうてい', 'こうどう', 'こうない', 'こうはい', 'ごうほう', 'ごうまん', 'こうもく', 'こうりつ', 'こえる', 'こおり', 'ごかい', 'ごがつ', 'ごかん', 'こくご', 'こくさい', 'こくとう', 'こくない', 'こくはく', 'こぐま', 'こけい', 'こける', 'ここのか', 'こころ', 'こさめ', 'こしつ', 'こすう', 'こせい', 'こせき', 'こぜん', 'こそだて', 'こたい', 'こたえる', 'こたつ', 'こちょう', 'こっか', 'こつこつ', 'こつばん', 'こつぶ', 'こてい', 'こてん', 'ことがら', 'ことし', 'ことば', 'ことり', 'こなごな', 'こねこね', 'このまま', 'このみ', 'このよ', 'ごはん', 'こひつじ', 'こふう', 'こふん', 'こぼれる', 'ごまあぶら', 'こまかい', 'ごますり', 'こまつな', 'こまる', 'こむぎこ', 'こもじ', 'こもち', 'こもの', 'こもん', 'こやく', 'こやま', 'こゆう', 'こゆび', 'こよい', 'こよう', 'こりる', 'これくしょん', 'ころっけ', 'こわもて', 'こわれる', 'こんいん', 'こんかい', 'こんき', 'こんしゅう', 'こんすい', 'こんだて', 'こんとん', 'こんなん', 'こんびに', 'こんぽん', 'こんまけ', 'こんや', 'こんれい', 'こんわく', 'ざいえき', 'さいかい', 'さいきん', 'ざいげん', 'ざいこ', 'さいしょ', 'さいせい', 'ざいたく', 'ざいちゅう', 'さいてき', 'ざいりょう', 'さうな', 'さかいし', 'さがす', 'さかな', 'さかみち', 'さがる', 'さぎょう', 'さくし', 'さくひん', 'さくら', 'さこく', 'さこつ', 'さずかる', 'ざせき', 'さたん', 'さつえい', 'ざつおん', 'ざっか', 'ざつがく', 'さっきょく', 'ざっし', 'さつじん', 'ざっそう', 'さつたば', 'さつまいも', 'さてい', 'さといも', 'さとう', 'さとおや', 'さとし', 'さとる', 'さのう', 'さばく', 'さびしい', 'さべつ', 'さほう', 'さほど', 'さます', 'さみしい', 'さみだれ', 'さむけ', 'さめる', 'さやえんどう', 'さゆう', 'さよう', 'さよく', 'さらだ', 'ざるそば', 'さわやか', 'さわる', 'さんいん', 'さんか', 'さんきゃく', 'さんこう', 'さんさい', 'ざんしょ', 'さんすう', 'さんせい', 'さんそ', 'さんち', 'さんま', 'さんみ', 'さんらん', 'しあい', 'しあげ', 'しあさって', 'しあわせ', 'しいく', 'しいん', 'しうち', 'しえい', 'しおけ', 'しかい', 'しかく', 'じかん', 'しごと', 'しすう', 'じだい', 'したうけ', 'したぎ', 'したて', 'したみ', 'しちょう', 'しちりん', 'しっかり', 'しつじ', 'しつもん', 'してい', 'してき', 'してつ', 'じてん', 'じどう', 'しなぎれ', 'しなもの', 'しなん', 'しねま', 'しねん', 'しのぐ', 'しのぶ', 'しはい', 'しばかり', 'しはつ', 'しはらい', 'しはん', 'しひょう', 'しふく', 'じぶん', 'しへい', 'しほう', 'しほん', 'しまう', 'しまる', 'しみん', 'しむける', 'じむしょ', 'しめい', 'しめる', 'しもん', 'しゃいん', 'しゃうん', 'しゃおん', 'じゃがいも', 'しやくしょ', 'しゃくほう', 'しゃけん', 'しゃこ', 'しゃざい', 'しゃしん', 'しゃせん', 'しゃそう', 'しゃたい', 'しゃちょう', 'しゃっきん', 'じゃま', 'しゃりん', 'しゃれい', 'じゆう', 'じゅうしょ', 'しゅくはく', 'じゅしん', 'しゅっせき', 'しゅみ', 'しゅらば', 'じゅんばん', 'しょうかい', 'しょくたく', 'しょっけん', 'しょどう', 'しょもつ', 'しらせる', 'しらべる', 'しんか', 'しんこう', 'じんじゃ', 'しんせいじ', 'しんちく', 'しんりん', 'すあげ', 'すあし', 'すあな', 'ずあん', 'すいえい', 'すいか', 'すいとう', 'ずいぶん', 'すいようび', 'すうがく', 'すうじつ', 'すうせん', 'すおどり', 'すきま', 'すくう', 'すくない', 'すける', 'すごい', 'すこし', 'ずさん', 'すずしい', 'すすむ', 'すすめる', 'すっかり', 'ずっしり', 'ずっと', 'すてき', 'すてる', 'すねる', 'すのこ', 'すはだ', 'すばらしい', 'ずひょう', 'ずぶぬれ', 'すぶり', 'すふれ', 'すべて', 'すべる', 'ずほう', 'すぼん', 'すまい', 'すめし', 'すもう', 'すやき', 'すらすら', 'するめ', 'すれちがう', 'すろっと', 'すわる', 'すんぜん', 'すんぽう', 'せあぶら', 'せいかつ', 'せいげん', 'せいじ', 'せいよう', 'せおう', 'せかいかん', 'せきにん', 'せきむ', 'せきゆ', 'せきらんうん', 'せけん', 'せこう', 'せすじ', 'せたい', 'せたけ', 'せっかく', 'せっきゃく', 'ぜっく', 'せっけん', 'せっこつ', 'せっさたくま', 'せつぞく', 'せつだん', 'せつでん', 'せっぱん', 'せつび', 'せつぶん', 'せつめい', 'せつりつ', 'せなか', 'せのび', 'せはば', 'せびろ', 'せぼね', 'せまい', 'せまる', 'せめる', 'せもたれ', 'せりふ', 'ぜんあく', 'せんい', 'せんえい', 'せんか', 'せんきょ', 'せんく', 'せんげん', 'ぜんご', 'せんさい', 'せんしゅ', 'せんすい', 'せんせい', 'せんぞ', 'せんたく', 'せんちょう', 'せんてい', 'せんとう', 'せんぬき', 'せんねん', 'せんぱい', 'ぜんぶ', 'ぜんぽう', 'せんむ', 'せんめんじょ', 'せんもん', 'せんやく', 'せんゆう', 'せんよう', 'ぜんら', 'ぜんりゃく', 'せんれい', 'せんろ', 'そあく', 'そいとげる', 'そいね', 'そうがんきょう', 'そうき', 'そうご', 'そうしん', 'そうだん', 'そうなん', 'そうび', 'そうめん', 'そうり', 'そえもの', 'そえん', 'そがい', 'そげき', 'そこう', 'そこそこ', 'そざい', 'そしな', 'そせい', 'そせん', 'そそぐ', 'そだてる', 'そつう', 'そつえん', 'そっかん', 'そつぎょう', 'そっけつ', 'そっこう', 'そっせん', 'そっと', 'そとがわ', 'そとづら', 'そなえる', 'そなた', 'そふぼ', 'そぼく', 'そぼろ', 'そまつ', 'そまる', 'そむく', 'そむりえ', 'そめる', 'そもそも', 'そよかぜ', 'そらまめ', 'そろう', 'そんかい', 'そんけい', 'そんざい', 'そんしつ', 'そんぞく', 'そんちょう', 'ぞんび', 'ぞんぶん', 'そんみん', 'たあい', 'たいいん', 'たいうん', 'たいえき', 'たいおう', 'だいがく', 'たいき', 'たいぐう', 'たいけん', 'たいこ', 'たいざい', 'だいじょうぶ', 'だいすき', 'たいせつ', 'たいそう', 'だいたい', 'たいちょう', 'たいてい', 'だいどころ', 'たいない', 'たいねつ', 'たいのう', 'たいはん', 'だいひょう', 'たいふう', 'たいへん', 'たいほ', 'たいまつばな', 'たいみんぐ', 'たいむ', 'たいめん', 'たいやき', 'たいよう', 'たいら', 'たいりょく', 'たいる', 'たいわん', 'たうえ', 'たえる', 'たおす', 'たおる', 'たおれる', 'たかい', 'たかね', 'たきび', 'たくさん', 'たこく', 'たこやき', 'たさい', 'たしざん', 'だじゃれ', 'たすける', 'たずさわる', 'たそがれ', 'たたかう', 'たたく', 'ただしい', 'たたみ', 'たちばな', 'だっかい', 'だっきゃく', 'だっこ', 'だっしゅつ', 'だったい', 'たてる', 'たとえる', 'たなばた', 'たにん', 'たぬき', 'たのしみ', 'たはつ', 'たぶん', 'たべる', 'たぼう', 'たまご', 'たまる', 'だむる', 'ためいき', 'ためす', 'ためる', 'たもつ', 'たやすい', 'たよる', 'たらす', 'たりきほんがん', 'たりょう', 'たりる', 'たると', 'たれる', 'たれんと', 'たろっと', 'たわむれる', 'だんあつ', 'たんい', 'たんおん', 'たんか', 'たんき', 'たんけん', 'たんご', 'たんさん', 'たんじょうび', 'だんせい', 'たんそく', 'たんたい', 'だんち', 'たんてい', 'たんとう', 'だんな', 'たんにん', 'だんねつ', 'たんのう', 'たんぴん', 'だんぼう', 'たんまつ', 'たんめい', 'だんれつ', 'だんろ', 'だんわ', 'ちあい', 'ちあん', 'ちいき', 'ちいさい', 'ちえん', 'ちかい', 'ちから', 'ちきゅう', 'ちきん', 'ちけいず', 'ちけん', 'ちこく', 'ちさい', 'ちしき', 'ちしりょう', 'ちせい', 'ちそう', 'ちたい', 'ちたん', 'ちちおや', 'ちつじょ', 'ちてき', 'ちてん', 'ちぬき', 'ちぬり', 'ちのう', 'ちひょう', 'ちへいせん', 'ちほう', 'ちまた', 'ちみつ', 'ちみどろ', 'ちめいど', 'ちゃんこなべ', 'ちゅうい', 'ちゆりょく', 'ちょうし', 'ちょさくけん', 'ちらし', 'ちらみ', 'ちりがみ', 'ちりょう', 'ちるど', 'ちわわ', 'ちんたい', 'ちんもく', 'ついか', 'ついたち', 'つうか', 'つうじょう', 'つうはん', 'つうわ', 'つかう', 'つかれる', 'つくね', 'つくる', 'つけね', 'つける', 'つごう', 'つたえる', 'つづく', 'つつじ', 'つつむ', 'つとめる', 'つながる', 'つなみ', 'つねづね', 'つのる', 'つぶす', 'つまらない', 'つまる', 'つみき', 'つめたい', 'つもり', 'つもる', 'つよい', 'つるぼ', 'つるみく', 'つわもの', 'つわり', 'てあし', 'てあて', 'てあみ', 'ていおん', 'ていか', 'ていき', 'ていけい', 'ていこく', 'ていさつ', 'ていし', 'ていせい', 'ていたい', 'ていど', 'ていねい', 'ていひょう', 'ていへん', 'ていぼう', 'てうち', 'ておくれ', 'てきとう', 'てくび', 'でこぼこ', 'てさぎょう', 'てさげ', 'てすり', 'てそう', 'てちがい', 'てちょう', 'てつがく', 'てつづき', 'でっぱ', 'てつぼう', 'てつや', 'でぬかえ', 'てぬき', 'てぬぐい', 'てのひら', 'てはい', 'てぶくろ', 'てふだ', 'てほどき', 'てほん', 'てまえ', 'てまきずし', 'てみじか', 'てみやげ', 'てらす', 'てれび', 'てわけ', 'てわたし', 'でんあつ', 'てんいん', 'てんかい', 'てんき', 'てんぐ', 'てんけん', 'てんごく', 'てんさい', 'てんし', 'てんすう', 'でんち', 'てんてき', 'てんとう', 'てんない', 'てんぷら', 'てんぼうだい', 'てんめつ', 'てんらんかい', 'でんりょく', 'でんわ', 'どあい', 'といれ', 'どうかん', 'とうきゅう', 'どうぐ', 'とうし', 'とうむぎ', 'とおい', 'とおか', 'とおく', 'とおす', 'とおる', 'とかい', 'とかす', 'ときおり', 'ときどき', 'とくい', 'とくしゅう', 'とくてん', 'とくに', 'とくべつ', 'とけい', 'とける', 'とこや', 'とさか', 'としょかん', 'とそう', 'とたん', 'とちゅう', 'とっきゅう', 'とっくん', 'とつぜん', 'とつにゅう', 'とどける', 'ととのえる', 'とない', 'となえる', 'となり', 'とのさま', 'とばす', 'どぶがわ', 'とほう', 'とまる', 'とめる', 'ともだち', 'ともる', 'どようび', 'とらえる', 'とんかつ', 'どんぶり', 'ないかく', 'ないこう', 'ないしょ', 'ないす', 'ないせん', 'ないそう', 'なおす', 'ながい', 'なくす', 'なげる', 'なこうど', 'なさけ', 'なたでここ', 'なっとう', 'なつやすみ', 'ななおし', 'なにごと', 'なにもの', 'なにわ', 'なのか', 'なふだ', 'なまいき', 'なまえ', 'なまみ', 'なみだ', 'なめらか', 'なめる', 'なやむ', 'ならう', 'ならび', 'ならぶ', 'なれる', 'なわとび', 'なわばり', 'にあう', 'にいがた', 'にうけ', 'におい', 'にかい', 'にがて', 'にきび', 'にくしみ', 'にくまん', 'にげる', 'にさんかたんそ', 'にしき', 'にせもの', 'にちじょう', 'にちようび', 'にっか', 'にっき', 'にっけい', 'にっこう', 'にっさん', 'にっしょく', 'にっすう', 'にっせき', 'にってい', 'になう', 'にほん', 'にまめ', 'にもつ', 'にやり', 'にゅういん', 'にりんしゃ', 'にわとり', 'にんい', 'にんか', 'にんき', 'にんげん', 'にんしき', 'にんずう', 'にんそう', 'にんたい', 'にんち', 'にんてい', 'にんにく', 'にんぷ', 'にんまり', 'にんむ', 'にんめい', 'にんよう', 'ぬいくぎ', 'ぬかす', 'ぬぐいとる', 'ぬぐう', 'ぬくもり', 'ぬすむ', 'ぬまえび', 'ぬめり', 'ぬらす', 'ぬんちゃく', 'ねあげ', 'ねいき', 'ねいる', 'ねいろ', 'ねぐせ', 'ねくたい', 'ねくら', 'ねこぜ', 'ねこむ', 'ねさげ', 'ねすごす', 'ねそべる', 'ねだん', 'ねつい', 'ねっしん', 'ねつぞう', 'ねったいぎょ', 'ねぶそく', 'ねふだ', 'ねぼう', 'ねほりはほり', 'ねまき', 'ねまわし', 'ねみみ', 'ねむい', 'ねむたい', 'ねもと', 'ねらう', 'ねわざ', 'ねんいり', 'ねんおし', 'ねんかん', 'ねんきん', 'ねんぐ', 'ねんざ', 'ねんし', 'ねんちゃく', 'ねんど', 'ねんぴ', 'ねんぶつ', 'ねんまつ', 'ねんりょう', 'ねんれい', 'のいず', 'のおづま', 'のがす', 'のきなみ', 'のこぎり', 'のこす', 'のこる', 'のせる', 'のぞく', 'のぞむ', 'のたまう', 'のちほど', 'のっく', 'のばす', 'のはら', 'のべる', 'のぼる', 'のみもの', 'のやま', 'のらいぬ', 'のらねこ', 'のりもの', 'のりゆき', 'のれん', 'のんき', 'ばあい', 'はあく', 'ばあさん', 'ばいか', 'ばいく', 'はいけん', 'はいご', 'はいしん', 'はいすい', 'はいせん', 'はいそう', 'はいち', 'ばいばい', 'はいれつ', 'はえる', 'はおる', 'はかい', 'ばかり', 'はかる', 'はくしゅ', 'はけん', 'はこぶ', 'はさみ', 'はさん', 'はしご', 'ばしょ', 'はしる', 'はせる', 'ぱそこん', 'はそん', 'はたん', 'はちみつ', 'はつおん', 'はっかく', 'はづき', 'はっきり', 'はっくつ', 'はっけん', 'はっこう', 'はっさん', 'はっしん', 'はったつ', 'はっちゅう', 'はってん', 'はっぴょう', 'はっぽう', 'はなす', 'はなび', 'はにかむ', 'はぶらし', 'はみがき', 'はむかう', 'はめつ', 'はやい', 'はやし', 'はらう', 'はろうぃん', 'はわい', 'はんい', 'はんえい', 'はんおん', 'はんかく', 'はんきょう', 'ばんぐみ', 'はんこ', 'はんしゃ', 'はんすう', 'はんだん', 'ぱんち', 'ぱんつ', 'はんてい', 'はんとし', 'はんのう', 'はんぱ', 'はんぶん', 'はんぺん', 'はんぼうき', 'はんめい', 'はんらん', 'はんろん', 'ひいき', 'ひうん', 'ひえる', 'ひかく', 'ひかり', 'ひかる', 'ひかん', 'ひくい', 'ひけつ', 'ひこうき', 'ひこく', 'ひさい', 'ひさしぶり', 'ひさん', 'びじゅつかん', 'ひしょ', 'ひそか', 'ひそむ', 'ひたむき', 'ひだり', 'ひたる', 'ひつぎ', 'ひっこし', 'ひっし', 'ひつじゅひん', 'ひっす', 'ひつぜん', 'ぴったり', 'ぴっちり', 'ひつよう', 'ひてい', 'ひとごみ', 'ひなまつり', 'ひなん', 'ひねる', 'ひはん', 'ひびく', 'ひひょう', 'ひほう', 'ひまわり', 'ひまん', 'ひみつ', 'ひめい', 'ひめじし', 'ひやけ', 'ひやす', 'ひよう', 'びょうき', 'ひらがな', 'ひらく', 'ひりつ', 'ひりょう', 'ひるま', 'ひるやすみ', 'ひれい', 'ひろい', 'ひろう', 'ひろき', 'ひろゆき', 'ひんかく', 'ひんけつ', 'ひんこん', 'ひんしゅ', 'ひんそう', 'ぴんち', 'ひんぱん', 'びんぼう', 'ふあん', 'ふいうち', 'ふうけい', 'ふうせん', 'ぷうたろう', 'ふうとう', 'ふうふ', 'ふえる', 'ふおん', 'ふかい', 'ふきん', 'ふくざつ', 'ふくぶくろ', 'ふこう', 'ふさい', 'ふしぎ', 'ふじみ', 'ふすま', 'ふせい', 'ふせぐ', 'ふそく', 'ぶたにく', 'ふたん', 'ふちょう', 'ふつう', 'ふつか', 'ふっかつ', 'ふっき', 'ふっこく', 'ぶどう', 'ふとる', 'ふとん', 'ふのう', 'ふはい', 'ふひょう', 'ふへん', 'ふまん', 'ふみん', 'ふめつ', 'ふめん', 'ふよう', 'ふりこ', 'ふりる', 'ふるい', 'ふんいき', 'ぶんがく', 'ぶんぐ', 'ふんしつ', 'ぶんせき', 'ふんそう', 'ぶんぽう', 'へいあん', 'へいおん', 'へいがい', 'へいき', 'へいげん', 'へいこう', 'へいさ', 'へいしゃ', 'へいせつ', 'へいそ', 'へいたく', 'へいてん', 'へいねつ', 'へいわ', 'へきが', 'へこむ', 'べにいろ', 'べにしょうが', 'へらす', 'へんかん', 'べんきょう', 'べんごし', 'へんさい', 'へんたい', 'べんり', 'ほあん', 'ほいく', 'ぼうぎょ', 'ほうこく', 'ほうそう', 'ほうほう', 'ほうもん', 'ほうりつ', 'ほえる', 'ほおん', 'ほかん', 'ほきょう', 'ぼきん', 'ほくろ', 'ほけつ', 'ほけん', 'ほこう', 'ほこる', 'ほしい', 'ほしつ', 'ほしゅ', 'ほしょう', 'ほせい', 'ほそい', 'ほそく', 'ほたて', 'ほたる', 'ぽちぶくろ', 'ほっきょく', 'ほっさ', 'ほったん', 'ほとんど', 'ほめる', 'ほんい', 'ほんき', 'ほんけ', 'ほんしつ', 'ほんやく', 'まいにち', 'まかい', 'まかせる', 'まがる', 'まける', 'まこと', 'まさつ', 'まじめ', 'ますく', 'まぜる', 'まつり', 'まとめ', 'まなぶ', 'まぬけ', 'まねく', 'まほう', 'まもる', 'まゆげ', 'まよう', 'まろやか', 'まわす', 'まわり', 'まわる', 'まんが', 'まんきつ', 'まんぞく', 'まんなか', 'みいら', 'みうち', 'みえる', 'みがく', 'みかた', 'みかん', 'みけん', 'みこん', 'みじかい', 'みすい', 'みすえる', 'みせる', 'みっか', 'みつかる', 'みつける', 'みてい', 'みとめる', 'みなと', 'みなみかさい', 'みねらる', 'みのう', 'みのがす', 'みほん', 'みもと', 'みやげ', 'みらい', 'みりょく', 'みわく', 'みんか', 'みんぞく', 'むいか', 'むえき', 'むえん', 'むかい', 'むかう', 'むかえ', 'むかし', 'むぎちゃ', 'むける', 'むげん', 'むさぼる', 'むしあつい', 'むしば', 'むじゅん', 'むしろ', 'むすう', 'むすこ', 'むすぶ', 'むすめ', 'むせる', 'むせん', 'むちゅう', 'むなしい', 'むのう', 'むやみ', 'むよう', 'むらさき', 'むりょう', 'むろん', 'めいあん', 'めいうん', 'めいえん', 'めいかく', 'めいきょく', 'めいさい', 'めいし', 'めいそう', 'めいぶつ', 'めいれい', 'めいわく', 'めぐまれる', 'めざす', 'めした', 'めずらしい', 'めだつ', 'めまい', 'めやす', 'めんきょ', 'めんせき', 'めんどう', 'もうしあげる', 'もうどうけん', 'もえる', 'もくし', 'もくてき', 'もくようび', 'もちろん', 'もどる', 'もらう', 'もんく', 'もんだい', 'やおや', 'やける', 'やさい', 'やさしい', 'やすい', 'やすたろう', 'やすみ', 'やせる', 'やそう', 'やたい', 'やちん', 'やっと', 'やっぱり', 'やぶる', 'やめる', 'ややこしい', 'やよい', 'やわらかい', 'ゆうき', 'ゆうびんきょく', 'ゆうべ', 'ゆうめい', 'ゆけつ', 'ゆしゅつ', 'ゆせん', 'ゆそう', 'ゆたか', 'ゆちゃく', 'ゆでる', 'ゆにゅう', 'ゆびわ', 'ゆらい', 'ゆれる', 'ようい', 'ようか', 'ようきゅう', 'ようじ', 'ようす', 'ようちえん', 'よかぜ', 'よかん', 'よきん', 'よくせい', 'よくぼう', 'よけい', 'よごれる', 'よさん', 'よしゅう', 'よそう', 'よそく', 'よっか', 'よてい', 'よどがわく', 'よねつ', 'よやく', 'よゆう', 'よろこぶ', 'よろしい', 'らいう', 'らくがき', 'らくご', 'らくさつ', 'らくだ', 'らしんばん', 'らせん', 'らぞく', 'らたい', 'らっか', 'られつ', 'りえき', 'りかい', 'りきさく', 'りきせつ', 'りくぐん', 'りくつ', 'りけん', 'りこう', 'りせい', 'りそう', 'りそく', 'りてん', 'りねん', 'りゆう', 'りゅうがく', 'りよう', 'りょうり', 'りょかん', 'りょくちゃ', 'りょこう', 'りりく', 'りれき', 'りろん', 'りんご', 'るいけい', 'るいさい', 'るいじ', 'るいせき', 'るすばん', 'るりがわら', 'れいかん', 'れいぎ', 'れいせい', 'れいぞうこ', 'れいとう', 'れいぼう', 'れきし', 'れきだい', 'れんあい', 'れんけい', 'れんこん', 'れんさい', 'れんしゅう', 'れんぞく', 'れんらく', 'ろうか', 'ろうご', 'ろうじん', 'ろうそく', 'ろくが', 'ろこつ', 'ろじうら', 'ろしゅつ', 'ろせん', 'ろてん', 'ろめん', 'ろれつ', 'ろんぎ', 'ろんぱ', 'ろんぶん', 'ろんり', 'わかす', 'わかめ', 'わかやま', 'わかれる', 'わしつ', 'わじまし', 'わすれもの', 'わらう', 'われる'];
4290wordList$1.space = ' ';
4291
4292class KeyPair extends Struct {
4293 constructor(privKey, pubKey, PrivKey$1 = PrivKey) {
4294 super({
4295 privKey,
4296 pubKey
4297 });
4298 this.PrivKey = PrivKey$1;
4299 }
4300
4301 fromJSON(json) {
4302 if (json.privKey) {
4303 this.privKey = this.PrivKey.fromJSON(json.privKey);
4304 }
4305
4306 if (json.pubKey) {
4307 this.pubKey = PubKey.fromJSON(json.pubKey);
4308 }
4309
4310 return this;
4311 }
4312
4313 fromBr(br) {
4314 const buflen1 = br.readUInt8();
4315
4316 if (buflen1 > 0) {
4317 this.privKey = new this.PrivKey().fromFastBuffer(br.read(buflen1));
4318 }
4319
4320 const buflen2 = br.readUInt8();
4321
4322 if (buflen2 > 0) {
4323 this.pubKey = new PubKey().fromFastBuffer(br.read(buflen2));
4324 }
4325
4326 return this;
4327 }
4328
4329 toBw(bw) {
4330 if (!bw) {
4331 bw = new Bw();
4332 }
4333
4334 if (this.privKey) {
4335 const privKeybuf = this.privKey.toFastBuffer();
4336 bw.writeUInt8(privKeybuf.length);
4337 bw.write(privKeybuf);
4338 } else {
4339 bw.writeUInt8(0);
4340 }
4341
4342 if (this.pubKey) {
4343 const pubKeybuf = this.pubKey.toFastBuffer();
4344 bw.writeUInt8(pubKeybuf.length);
4345 bw.write(pubKeybuf);
4346 } else {
4347 bw.writeUInt8(0);
4348 }
4349
4350 return bw;
4351 }
4352
4353 fromString(str) {
4354 return this.fromJSON(JSON.parse(str));
4355 }
4356
4357 toString() {
4358 return JSON.stringify(this.toJSON());
4359 }
4360
4361 toPublic() {
4362 const keyPair = new KeyPair().fromObject(this);
4363 keyPair.privKey = undefined;
4364 return keyPair;
4365 }
4366
4367 fromPrivKey(privKey) {
4368 this.privKey = privKey;
4369 this.pubKey = new PubKey().fromPrivKey(privKey);
4370 return this;
4371 }
4372
4373 static fromPrivKey(privKey) {
4374 return new this().fromPrivKey(privKey);
4375 }
4376
4377 async asyncFromPrivKey(privKey) {
4378 this.privKey = privKey;
4379 this.pubKey = await new PubKey().asyncFromPrivKey(privKey);
4380 return this;
4381 }
4382
4383 static asyncFromPrivKey(privKey) {
4384 return new this().asyncFromPrivKey(privKey);
4385 }
4386
4387 fromRandom() {
4388 this.privKey = new this.PrivKey().fromRandom();
4389 this.pubKey = new PubKey().fromPrivKey(this.privKey);
4390 return this;
4391 }
4392
4393 static fromRandom() {
4394 return new this().fromRandom();
4395 }
4396
4397 async asyncFromRandom() {
4398 this.privKey = new this.PrivKey().fromRandom();
4399 return this.asyncFromPrivKey(this.privKey);
4400 }
4401
4402 static asyncFromRandom() {
4403 return new this().asyncFromRandom();
4404 }
4405
4406}
4407
4408KeyPair.Mainnet = class extends KeyPair {
4409 constructor(privKey, pubKey) {
4410 super(privKey, pubKey, PrivKey.Mainnet);
4411 }
4412
4413};
4414KeyPair.Testnet = class extends KeyPair {
4415 constructor(privKey, pubKey) {
4416 super(privKey, pubKey, PrivKey.Testnet);
4417 }
4418
4419};
4420
4421class Ecdsa extends Struct {
4422 constructor(sig, keyPair, hashBuf, k, endian, verified) {
4423 super({
4424 sig,
4425 keyPair,
4426 hashBuf,
4427 k,
4428 endian,
4429 verified
4430 });
4431 }
4432
4433 toJSON() {
4434 return {
4435 sig: this.sig ? this.sig.toString() : undefined,
4436 keyPair: this.keyPair ? this.keyPair.toBuffer().toString('hex') : undefined,
4437 hashBuf: this.hashBuf ? this.hashBuf.toString('hex') : undefined,
4438 k: this.k ? this.k.toString() : undefined,
4439 endian: this.endian,
4440 verified: this.verified
4441 };
4442 }
4443
4444 fromJSON(json) {
4445 this.sig = json.sig ? new Sig().fromString(json.sig) : undefined;
4446 this.keyPair = json.keyPair ? new KeyPair().fromBuffer(Buffer.from(json.keyPair, 'hex')) : undefined;
4447 this.hashBuf = json.hashBuf ? Buffer.from(json.hashBuf, 'hex') : undefined;
4448 this.k = json.k ? new Bn().fromString(json.k) : undefined;
4449 this.endian = json.endian;
4450 this.verified = json.verified;
4451 return this;
4452 }
4453
4454 toBuffer() {
4455 const str = JSON.stringify(this.toJSON());
4456 return Buffer.from(str);
4457 }
4458
4459 fromBuffer(buf) {
4460 const json = JSON.parse(buf.toString());
4461 return this.fromJSON(json);
4462 }
4463
4464 calcrecovery() {
4465 for (let recovery = 0; recovery < 4; recovery++) {
4466 let Qprime;
4467 this.sig.recovery = recovery;
4468
4469 try {
4470 Qprime = this.sig2PubKey();
4471 } catch (e) {
4472 continue;
4473 }
4474
4475 if (Qprime.point.eq(this.keyPair.pubKey.point)) {
4476 const compressed = this.keyPair.pubKey.compressed;
4477 this.sig.compressed = this.keyPair.pubKey.compressed === undefined ? true : compressed;
4478 return this;
4479 }
4480 }
4481
4482 this.sig.recovery = undefined;
4483 throw new Error('Unable to find valid recovery factor');
4484 }
4485
4486 async asyncCalcrecovery() {
4487 const workersResult = await Workers.asyncObjectMethod(this, 'calcrecovery', []);
4488 return this.fromFastBuffer(workersResult.resbuf);
4489 }
4490
4491 static calcrecovery(sig, pubKey, hashBuf) {
4492 const ecdsa = new Ecdsa().fromObject({
4493 sig: sig,
4494 keyPair: new KeyPair().fromObject({
4495 pubKey: pubKey
4496 }),
4497 hashBuf: hashBuf
4498 });
4499 return ecdsa.calcrecovery().sig;
4500 }
4501
4502 static async asyncCalcrecovery(sig, pubKey, hashBuf) {
4503 const workersResult = await Workers.asyncClassMethod(Ecdsa, 'calcrecovery', [sig, pubKey, hashBuf]);
4504 return new Sig().fromFastBuffer(workersResult.resbuf);
4505 }
4506
4507 fromString(str) {
4508 const obj = JSON.parse(str);
4509
4510 if (obj.hashBuf) {
4511 this.hashBuf = Buffer.from(obj.hashBuf, 'hex');
4512 }
4513
4514 if (obj.keyPair) {
4515 this.keyPair = new KeyPair().fromString(obj.keyPair);
4516 }
4517
4518 if (obj.sig) {
4519 this.sig = new Sig().fromString(obj.sig);
4520 }
4521
4522 if (obj.k) {
4523 this.k = new Bn(obj.k, 10);
4524 }
4525
4526 return this;
4527 }
4528
4529 randomK() {
4530 const N = Point.getN();
4531 let k;
4532
4533 do {
4534 k = new Bn().fromBuffer(Random.getRandomBuffer(32));
4535 } while (!(k.lt(N) && k.gt(0)));
4536
4537 this.k = k;
4538 return this;
4539 }
4540
4541 deterministicK(badrs) {
4542 let v = Buffer.alloc(32);
4543 v.fill(0x01);
4544 let k = Buffer.alloc(32);
4545 k.fill(0x00);
4546 const x = this.keyPair.privKey.bn.toBuffer({
4547 size: 32
4548 });
4549 k = Hash.sha256Hmac(Buffer.concat([v, Buffer.from([0x00]), x, this.hashBuf]), k);
4550 v = Hash.sha256Hmac(v, k);
4551 k = Hash.sha256Hmac(Buffer.concat([v, Buffer.from([0x01]), x, this.hashBuf]), k);
4552 v = Hash.sha256Hmac(v, k);
4553 v = Hash.sha256Hmac(v, k);
4554 let T = new Bn().fromBuffer(v);
4555 const N = Point.getN();
4556
4557 if (badrs === undefined) {
4558 badrs = 0;
4559 }
4560
4561 for (let i = 0; i < badrs || !(T.lt(N) && T.gt(0)); i++) {
4562 k = Hash.sha256Hmac(Buffer.concat([v, Buffer.from([0x00])]), k);
4563 v = Hash.sha256Hmac(v, k);
4564 v = Hash.sha256Hmac(v, k);
4565 T = new Bn().fromBuffer(v);
4566 }
4567
4568 this.k = T;
4569 return this;
4570 }
4571
4572 sig2PubKey() {
4573 const recovery = this.sig.recovery;
4574
4575 if (!(recovery === 0 || recovery === 1 || recovery === 2 || recovery === 3)) {
4576 throw new Error('i must be equal to 0, 1, 2, or 3');
4577 }
4578
4579 const e = new Bn().fromBuffer(this.hashBuf);
4580 const r = this.sig.r;
4581 const s = this.sig.s;
4582 const isYOdd = recovery & 1;
4583 const isSecondKey = recovery >> 1;
4584 const n = Point.getN();
4585 const G = Point.getG();
4586 const x = isSecondKey ? r.add(n) : r;
4587 const R = Point.fromX(isYOdd, x);
4588 let errm = '';
4589
4590 try {
4591 R.mul(n);
4592 } catch (err) {
4593 errm = err.message;
4594 }
4595
4596 if (errm !== 'point mul out of range') {
4597 throw new Error('nR is not a valid curve point');
4598 }
4599
4600 const eNeg = e.neg().umod(n);
4601 const rInv = r.invm(n);
4602 const Q = R.mul(s).add(G.mul(eNeg)).mul(rInv);
4603 const pubKey = new PubKey(Q);
4604 pubKey.compressed = this.sig.compressed;
4605 pubKey.validate();
4606 return pubKey;
4607 }
4608
4609 async asyncSig2PubKey() {
4610 const workersResult = await Workers.asyncObjectMethod(this, 'sig2PubKey', []);
4611 return PubKey.fromFastBuffer(workersResult.resbuf);
4612 }
4613
4614 static sig2PubKey(sig, hashBuf) {
4615 const ecdsa = new Ecdsa().fromObject({
4616 sig: sig,
4617 hashBuf: hashBuf
4618 });
4619 return ecdsa.sig2PubKey();
4620 }
4621
4622 static async asyncSig2PubKey(sig, hashBuf) {
4623 const ecdsa = new Ecdsa().fromObject({
4624 sig: sig,
4625 hashBuf: hashBuf
4626 });
4627 const pubKey = await ecdsa.asyncSig2PubKey();
4628 return pubKey;
4629 }
4630
4631 verifyStr(enforceLowS = true) {
4632 if (!Buffer.isBuffer(this.hashBuf) || this.hashBuf.length !== 32) {
4633 return 'hashBuf must be a 32 byte buffer';
4634 }
4635
4636 try {
4637 this.keyPair.pubKey.validate();
4638 } catch (e) {
4639 return 'Invalid pubKey: ' + e;
4640 }
4641
4642 const r = this.sig.r;
4643 const s = this.sig.s;
4644
4645 if (!(r.gt(0) && r.lt(Point.getN())) || !(s.gt(0) && s.lt(Point.getN()))) {
4646 return 'r and s not in range';
4647 }
4648
4649 if (enforceLowS) {
4650 if (!this.sig.hasLowS()) {
4651 return 's is too high and does not satisfy low s contraint - see bip 62';
4652 }
4653 }
4654
4655 const e = new Bn().fromBuffer(this.hashBuf, this.endian ? {
4656 endian: this.endian
4657 } : undefined);
4658 const n = Point.getN();
4659 const sinv = s.invm(n);
4660 const u1 = sinv.mul(e).mod(n);
4661 const u2 = sinv.mul(r).mod(n);
4662 const p = Point.getG().mulAdd(u1, this.keyPair.pubKey.point, u2);
4663
4664 if (p.isInfinity()) {
4665 return 'p is infinity';
4666 }
4667
4668 if (!(p.getX().mod(n).cmp(r) === 0)) {
4669 return 'Invalid signature';
4670 } else {
4671 return false;
4672 }
4673 }
4674
4675 sign() {
4676 const hashBuf = this.endian === 'little' ? new Br(this.hashBuf).readReverse() : this.hashBuf;
4677 const privKey = this.keyPair.privKey;
4678 const d = privKey.bn;
4679
4680 if (!hashBuf || !privKey || !d) {
4681 throw new Error('invalid parameters');
4682 }
4683
4684 if (!Buffer.isBuffer(hashBuf) || hashBuf.length !== 32) {
4685 throw new Error('hashBuf must be a 32 byte buffer');
4686 }
4687
4688 const N = Point.getN();
4689 const G = Point.getG();
4690 const e = new Bn().fromBuffer(hashBuf);
4691 let badrs = 0;
4692 let k, Q, r, s;
4693
4694 do {
4695 if (!this.k || badrs > 0) {
4696 this.deterministicK(badrs);
4697 }
4698
4699 badrs++;
4700 k = this.k;
4701 Q = G.mul(k);
4702 r = Q.getX().mod(N);
4703 s = k.invm(N).mul(e.add(d.mul(r))).mod(N);
4704 } while (r.cmp(0) <= 0 || s.cmp(0) <= 0);
4705
4706 if (s.gt(new Bn().fromBuffer(Buffer.from('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0', 'hex')))) {
4707 s = Point.getN().sub(s);
4708 }
4709
4710 this.sig = Sig.fromObject({
4711 r: r,
4712 s: s,
4713 compressed: this.keyPair.pubKey.compressed
4714 });
4715 return this;
4716 }
4717
4718 async asyncSign() {
4719 const workersResult = await Workers.asyncObjectMethod(this, 'sign', []);
4720 return this.fromFastBuffer(workersResult.resbuf);
4721 }
4722
4723 signRandomK() {
4724 this.randomK();
4725 return this.sign();
4726 }
4727
4728 toString() {
4729 const obj = {};
4730
4731 if (this.hashBuf) {
4732 obj.hashBuf = this.hashBuf.toString('hex');
4733 }
4734
4735 if (this.keyPair) {
4736 obj.keyPair = this.keyPair.toString();
4737 }
4738
4739 if (this.sig) {
4740 obj.sig = this.sig.toString();
4741 }
4742
4743 if (this.k) {
4744 obj.k = this.k.toString();
4745 }
4746
4747 return JSON.stringify(obj);
4748 }
4749
4750 verify(enforceLowS = true) {
4751 if (!this.verifyStr(enforceLowS)) {
4752 this.verified = true;
4753 } else {
4754 this.verified = false;
4755 }
4756
4757 return this;
4758 }
4759
4760 async asyncVerify(enforceLowS = true) {
4761 const workersResult = await Workers.asyncObjectMethod(this, 'verify', [enforceLowS]);
4762 return this.fromFastBuffer(workersResult.resbuf);
4763 }
4764
4765 static sign(hashBuf, keyPair, endian) {
4766 return new Ecdsa().fromObject({
4767 hashBuf: hashBuf,
4768 endian: endian,
4769 keyPair: keyPair
4770 }).sign().sig;
4771 }
4772
4773 static async asyncSign(hashBuf, keyPair, endian) {
4774 const ecdsa = new Ecdsa().fromObject({
4775 hashBuf: hashBuf,
4776 endian: endian,
4777 keyPair: keyPair
4778 });
4779 await ecdsa.asyncSign();
4780 return ecdsa.sig;
4781 }
4782
4783 static verify(hashBuf, sig, pubKey, endian, enforceLowS = true) {
4784 return new Ecdsa().fromObject({
4785 hashBuf: hashBuf,
4786 endian: endian,
4787 sig: sig,
4788 keyPair: new KeyPair().fromObject({
4789 pubKey: pubKey
4790 })
4791 }).verify(enforceLowS).verified;
4792 }
4793
4794 static async asyncVerify(hashBuf, sig, pubKey, endian, enforceLowS = true) {
4795 const ecdsa = new Ecdsa().fromObject({
4796 hashBuf: hashBuf,
4797 endian: endian,
4798 sig: sig,
4799 keyPair: new KeyPair().fromObject({
4800 pubKey: pubKey
4801 })
4802 });
4803 await ecdsa.asyncVerify(enforceLowS);
4804 return ecdsa.verified;
4805 }
4806
4807}
4808
4809class Bsm extends Struct {
4810 constructor(messageBuf, keyPair, sig, address, verified) {
4811 super({
4812 messageBuf,
4813 keyPair,
4814 sig,
4815 address,
4816 verified
4817 });
4818 }
4819
4820 static magicHash(messageBuf) {
4821 if (!Buffer.isBuffer(messageBuf)) {
4822 throw new Error('messageBuf must be a buffer');
4823 }
4824
4825 const bw = new Bw();
4826 bw.writeVarIntNum(Bsm.magicBytes.length);
4827 bw.write(Bsm.magicBytes);
4828 bw.writeVarIntNum(messageBuf.length);
4829 bw.write(messageBuf);
4830 const buf = bw.toBuffer();
4831 const hashBuf = Hash.sha256Sha256(buf);
4832 return hashBuf;
4833 }
4834
4835 static async asyncMagicHash(messageBuf) {
4836 const args = [messageBuf];
4837 const workersResult = await Workers.asyncClassMethod(Bsm, 'magicHash', args);
4838 return workersResult.resbuf;
4839 }
4840
4841 static sign(messageBuf, keyPair) {
4842 const m = new Bsm(messageBuf, keyPair);
4843 m.sign();
4844 const sigbuf = m.sig.toCompact();
4845 const sigstr = sigbuf.toString('base64');
4846 return sigstr;
4847 }
4848
4849 static async asyncSign(messageBuf, keyPair) {
4850 const args = [messageBuf, keyPair];
4851 const workersResult = await Workers.asyncClassMethod(Bsm, 'sign', args);
4852 const sigstr = JSON.parse(workersResult.resbuf.toString());
4853 return sigstr;
4854 }
4855
4856 static verify(messageBuf, sigstr, address) {
4857 const sigbuf = Buffer.from(sigstr, 'base64');
4858 const message = new Bsm();
4859 message.messageBuf = messageBuf;
4860 message.sig = new Sig().fromCompact(sigbuf);
4861 message.address = address;
4862 return message.verify().verified;
4863 }
4864
4865 static async asyncVerify(messageBuf, sigstr, address) {
4866 const args = [messageBuf, sigstr, address];
4867 const workersResult = await Workers.asyncClassMethod(Bsm, 'verify', args);
4868 const res = JSON.parse(workersResult.resbuf.toString());
4869 return res;
4870 }
4871
4872 sign() {
4873 const hashBuf = Bsm.magicHash(this.messageBuf);
4874 const ecdsa = new Ecdsa().fromObject({
4875 hashBuf: hashBuf,
4876 keyPair: this.keyPair
4877 });
4878 ecdsa.sign();
4879 ecdsa.calcrecovery();
4880 this.sig = ecdsa.sig;
4881 return this;
4882 }
4883
4884 verify() {
4885 const hashBuf = Bsm.magicHash(this.messageBuf);
4886 const ecdsa = new Ecdsa();
4887 ecdsa.hashBuf = hashBuf;
4888 ecdsa.sig = this.sig;
4889 ecdsa.keyPair = new KeyPair();
4890 ecdsa.keyPair.pubKey = ecdsa.sig2PubKey();
4891
4892 if (!ecdsa.verify()) {
4893 this.verified = false;
4894 return this;
4895 }
4896
4897 const address = new Address().fromPubKey(ecdsa.keyPair.pubKey, undefined, this.sig.compressed);
4898
4899 if (cmp(address.hashBuf, this.address.hashBuf)) {
4900 this.verified = true;
4901 } else {
4902 this.verified = false;
4903 }
4904
4905 return this;
4906 }
4907
4908}
4909
4910Bsm.magicBytes = Buffer.from('Bitcoin Signed Message:\n');
4911
4912class BlockHeader extends Struct {
4913 constructor(versionBytesNum, prevBlockHashBuf, merkleRootBuf, time, bits, nonce) {
4914 super({
4915 versionBytesNum,
4916 prevBlockHashBuf,
4917 merkleRootBuf,
4918 time,
4919 bits,
4920 nonce
4921 });
4922 }
4923
4924 fromJSON(json) {
4925 this.fromObject({
4926 versionBytesNum: json.versionBytesNum,
4927 prevBlockHashBuf: Buffer.from(json.prevBlockHashBuf, 'hex'),
4928 merkleRootBuf: Buffer.from(json.merkleRootBuf, 'hex'),
4929 time: json.time,
4930 bits: json.bits,
4931 nonce: json.nonce
4932 });
4933 return this;
4934 }
4935
4936 toJSON() {
4937 return {
4938 versionBytesNum: this.versionBytesNum,
4939 prevBlockHashBuf: this.prevBlockHashBuf.toString('hex'),
4940 merkleRootBuf: this.merkleRootBuf.toString('hex'),
4941 time: this.time,
4942 bits: this.bits,
4943 nonce: this.nonce
4944 };
4945 }
4946
4947 fromBr(br) {
4948 this.versionBytesNum = br.readUInt32LE();
4949 this.prevBlockHashBuf = br.read(32);
4950 this.merkleRootBuf = br.read(32);
4951 this.time = br.readUInt32LE();
4952 this.bits = br.readUInt32LE();
4953 this.nonce = br.readUInt32LE();
4954 return this;
4955 }
4956
4957 toBw(bw) {
4958 if (!bw) {
4959 bw = new Bw();
4960 }
4961
4962 bw.writeUInt32LE(this.versionBytesNum);
4963 bw.write(this.prevBlockHashBuf);
4964 bw.write(this.merkleRootBuf);
4965 bw.writeUInt32LE(this.time);
4966 bw.writeUInt32LE(this.bits);
4967 bw.writeUInt32LE(this.nonce);
4968 return bw;
4969 }
4970
4971}
4972
4973class Merkle extends Struct {
4974 constructor(hashBuf, buf, merkle1, merkle2) {
4975 super({
4976 hashBuf,
4977 buf,
4978 merkle1,
4979 merkle2
4980 });
4981 }
4982
4983 hash() {
4984 if (this.hashBuf) {
4985 return this.hashBuf;
4986 }
4987
4988 if (this.buf) {
4989 return Hash.sha256Sha256(this.buf);
4990 }
4991
4992 const hashBuf1 = this.merkle1.hash();
4993 const hashBuf2 = this.merkle2.hash();
4994 this.buf = Buffer.concat([hashBuf1, hashBuf2]);
4995 return Hash.sha256Sha256(this.buf);
4996 }
4997
4998 fromBuffers(bufs) {
4999 if (bufs.length < 1) {
5000 throw new Error('buffers must have a length');
5001 }
5002
5003 bufs = bufs.slice();
5004 const log = Math.log2(bufs.length);
5005
5006 if (!Number.isInteger(log)) {
5007 const lastval = bufs[bufs.length - 1];
5008 var len = Math.pow(2, Math.ceil(log));
5009
5010 for (let i = bufs.length; i < len; i++) {
5011 bufs.push(lastval);
5012 }
5013 }
5014
5015 const bufs1 = bufs.slice(0, bufs.length / 2);
5016 const bufs2 = bufs.slice(bufs.length / 2);
5017 this.fromBufferArrays(bufs1, bufs2);
5018 return this;
5019 }
5020
5021 static fromBuffers(bufs) {
5022 return new this().fromBuffers(bufs);
5023 }
5024
5025 fromBufferArrays(bufs1, bufs2) {
5026 if (bufs1.length === 1) {
5027 this.merkle1 = new Merkle(undefined, bufs1[0]);
5028 this.merkle2 = new Merkle(undefined, bufs2[0]);
5029 return this;
5030 }
5031
5032 const bufs11 = bufs1.slice(0, bufs1.length / 2);
5033 const bufs12 = bufs1.slice(bufs1.length / 2);
5034 this.merkle1 = new Merkle().fromBufferArrays(bufs11, bufs12);
5035 const bufs21 = bufs2.slice(0, bufs2.length / 2);
5036 const bufs22 = bufs2.slice(bufs2.length / 2);
5037 this.merkle2 = new Merkle().fromBufferArrays(bufs21, bufs22);
5038 return this;
5039 }
5040
5041 static fromBufferArrays(bufs1, bufs2) {
5042 return new this().fromBufferArrays(bufs1, bufs2);
5043 }
5044
5045 leavesNum() {
5046 if (this.merkle1) {
5047 return this.merkle1.leavesNum() + this.merkle2.leavesNum();
5048 }
5049
5050 if (this.buf) {
5051 return 1;
5052 }
5053
5054 throw new Error('invalid number of leaves');
5055 }
5056
5057}
5058
5059class HashCache extends Struct {
5060 constructor(prevoutsHashBuf, sequenceHashBuf, outputsHashBuf) {
5061 super();
5062 this.fromObject({
5063 prevoutsHashBuf,
5064 sequenceHashBuf,
5065 outputsHashBuf
5066 });
5067 }
5068
5069 fromBuffer(buf) {
5070 return this.fromJSON(JSON.parse(buf.toString()));
5071 }
5072
5073 toBuffer() {
5074 return Buffer.from(JSON.stringify(this.toJSON()));
5075 }
5076
5077 fromJSON(json) {
5078 this.prevoutsHashBuf = json.prevoutsHashBuf ? Buffer.from(json.prevoutsHashBuf, 'hex') : undefined;
5079 this.sequenceHashBuf = json.sequenceHashBuf ? Buffer.from(json.sequenceHashBuf, 'hex') : undefined;
5080 this.outputsHashBuf = json.outputsHashBuf ? Buffer.from(json.outputsHashBuf, 'hex') : undefined;
5081 return this;
5082 }
5083
5084 toJSON() {
5085 return {
5086 prevoutsHashBuf: this.prevoutsHashBuf ? this.prevoutsHashBuf.toString('hex') : undefined,
5087 sequenceHashBuf: this.sequenceHashBuf ? this.sequenceHashBuf.toString('hex') : undefined,
5088 outputsHashBuf: this.outputsHashBuf ? this.outputsHashBuf.toString('hex') : undefined
5089 };
5090 }
5091
5092}
5093
5094class VarInt extends Struct {
5095 constructor(buf) {
5096 super({
5097 buf
5098 });
5099 }
5100
5101 fromJSON(json) {
5102 this.fromObject({
5103 buf: Buffer.from(json, 'hex')
5104 });
5105 return this;
5106 }
5107
5108 toJSON() {
5109 return this.buf.toString('hex');
5110 }
5111
5112 fromBuffer(buf) {
5113 this.buf = buf;
5114 return this;
5115 }
5116
5117 fromBr(br) {
5118 this.buf = br.readVarIntBuf();
5119 return this;
5120 }
5121
5122 fromBn(bn) {
5123 this.buf = new Bw().writeVarIntBn(bn).toBuffer();
5124 return this;
5125 }
5126
5127 static fromBn(bn) {
5128 return new this().fromBn(bn);
5129 }
5130
5131 fromNumber(num) {
5132 this.buf = new Bw().writeVarIntNum(num).toBuffer();
5133 return this;
5134 }
5135
5136 static fromNumber(num) {
5137 return new this().fromNumber(num);
5138 }
5139
5140 toBuffer() {
5141 return this.buf;
5142 }
5143
5144 toBn() {
5145 return new Br(this.buf).readVarIntBn();
5146 }
5147
5148 toNumber() {
5149 return new Br(this.buf).readVarIntNum();
5150 }
5151
5152}
5153
5154class TxIn extends Struct {
5155 constructor(txHashBuf, txOutNum, scriptVi, script, nSequence = 0xffffffff) {
5156 super({
5157 txHashBuf,
5158 txOutNum,
5159 scriptVi,
5160 script,
5161 nSequence
5162 });
5163 }
5164
5165 setScript(script) {
5166 this.scriptVi = VarInt.fromNumber(script.toBuffer().length);
5167 this.script = script;
5168 return this;
5169 }
5170
5171 fromProperties(txHashBuf, txOutNum, script, nSequence) {
5172 this.fromObject({
5173 txHashBuf,
5174 txOutNum,
5175 nSequence
5176 });
5177 this.setScript(script);
5178 return this;
5179 }
5180
5181 static fromProperties(txHashBuf, txOutNum, script, nSequence) {
5182 return new this().fromProperties(txHashBuf, txOutNum, script, nSequence);
5183 }
5184
5185 fromJSON(json) {
5186 this.fromObject({
5187 txHashBuf: typeof json.txHashBuf !== 'undefined' ? Buffer.from(json.txHashBuf, 'hex') : undefined,
5188 txOutNum: json.txOutNum,
5189 scriptVi: typeof json.scriptVi !== 'undefined' ? VarInt.fromJSON(json.scriptVi) : undefined,
5190 script: typeof json.script !== 'undefined' ? Script.fromJSON(json.script) : undefined,
5191 nSequence: json.nSequence
5192 });
5193 return this;
5194 }
5195
5196 toJSON() {
5197 return {
5198 txHashBuf: typeof this.txHashBuf !== 'undefined' ? this.txHashBuf.toString('hex') : undefined,
5199 txOutNum: this.txOutNum,
5200 scriptVi: typeof this.scriptVi !== 'undefined' ? this.scriptVi.toJSON() : undefined,
5201 script: typeof this.script !== 'undefined' ? this.script.toJSON() : undefined,
5202 nSequence: this.nSequence
5203 };
5204 }
5205
5206 fromBr(br) {
5207 this.txHashBuf = br.read(32);
5208 this.txOutNum = br.readUInt32LE();
5209 this.scriptVi = VarInt.fromBuffer(br.readVarIntBuf());
5210 this.script = Script.fromBuffer(br.read(this.scriptVi.toNumber()));
5211 this.nSequence = br.readUInt32LE();
5212 return this;
5213 }
5214
5215 toBw(bw) {
5216 if (!bw) {
5217 bw = new Bw();
5218 }
5219
5220 bw.write(this.txHashBuf);
5221 bw.writeUInt32LE(this.txOutNum);
5222 bw.write(this.scriptVi.buf);
5223 bw.write(this.script.toBuffer());
5224 bw.writeUInt32LE(this.nSequence);
5225 return bw;
5226 }
5227
5228 fromPubKeyHashTxOut(txHashBuf, txOutNum, txOut, pubKey) {
5229 const script = new Script();
5230
5231 if (txOut.script.isPubKeyHashOut()) {
5232 script.writeOpCode(OpCode.OP_0);
5233
5234 if (pubKey) {
5235 script.writeBuffer(pubKey.toBuffer());
5236 } else {
5237 script.writeOpCode(OpCode.OP_0);
5238 }
5239 } else {
5240 throw new Error('txOut must be of type pubKeyHash');
5241 }
5242
5243 this.txHashBuf = txHashBuf;
5244 this.txOutNum = txOutNum;
5245 this.setScript(script);
5246 return this;
5247 }
5248
5249 hasNullInput() {
5250 const hex = this.txHashBuf.toString('hex');
5251
5252 if (hex === '0000000000000000000000000000000000000000000000000000000000000000' && this.txOutNum === 0xffffffff) {
5253 return true;
5254 }
5255
5256 return false;
5257 }
5258
5259 setNullInput() {
5260 this.txHashBuf = Buffer.alloc(32);
5261 this.txHashBuf.fill(0);
5262 this.txOutNum = 0xffffffff;
5263 }
5264
5265}
5266
5267TxIn.LOCKTIME_VERIFY_SEQUENCE = 1 << 0;
5268TxIn.SEQUENCE_FINAL = 0xffffffff;
5269TxIn.SEQUENCE_LOCKTIME_DISABLE_FLAG = 1 << 31;
5270TxIn.SEQUENCE_LOCKTIME_TYPE_FLAG = 1 << 22;
5271TxIn.SEQUENCE_LOCKTIME_MASK = 0x0000ffff;
5272TxIn.SEQUENCE_LOCKTIME_GRANULARITY = 9;
5273
5274class TxOut extends Struct {
5275 constructor(valueBn, scriptVi, script) {
5276 super({
5277 valueBn,
5278 scriptVi,
5279 script
5280 });
5281 }
5282
5283 setScript(script) {
5284 this.scriptVi = VarInt.fromNumber(script.toBuffer().length);
5285 this.script = script;
5286 return this;
5287 }
5288
5289 fromProperties(valueBn, script) {
5290 this.fromObject({
5291 valueBn
5292 });
5293 this.setScript(script);
5294 return this;
5295 }
5296
5297 static fromProperties(valueBn, script) {
5298 return new this().fromProperties(valueBn, script);
5299 }
5300
5301 fromJSON(json) {
5302 this.fromObject({
5303 valueBn: new Bn().fromJSON(json.valueBn),
5304 scriptVi: new VarInt().fromJSON(json.scriptVi),
5305 script: new Script().fromJSON(json.script)
5306 });
5307 return this;
5308 }
5309
5310 toJSON() {
5311 return {
5312 valueBn: this.valueBn.toJSON(),
5313 scriptVi: this.scriptVi.toJSON(),
5314 script: this.script.toJSON()
5315 };
5316 }
5317
5318 fromBr(br) {
5319 this.valueBn = br.readUInt64LEBn();
5320 this.scriptVi = VarInt.fromNumber(br.readVarIntNum());
5321 this.script = new Script().fromBuffer(br.read(this.scriptVi.toNumber()));
5322 return this;
5323 }
5324
5325 toBw(bw) {
5326 if (!bw) {
5327 bw = new Bw();
5328 }
5329
5330 bw.writeUInt64LEBn(this.valueBn);
5331 bw.write(this.scriptVi.buf);
5332 bw.write(this.script.toBuffer());
5333 return bw;
5334 }
5335
5336}
5337
5338class Tx extends Struct {
5339 constructor(versionBytesNum = 1, txInsVi = VarInt.fromNumber(0), txIns = [], txOutsVi = VarInt.fromNumber(0), txOuts = [], nLockTime = 0) {
5340 super({
5341 versionBytesNum,
5342 txInsVi,
5343 txIns,
5344 txOutsVi,
5345 txOuts,
5346 nLockTime
5347 });
5348 }
5349
5350 fromJSON(json) {
5351 const txIns = [];
5352 json.txIns.forEach(function (txIn) {
5353 txIns.push(new TxIn().fromJSON(txIn));
5354 });
5355 const txOuts = [];
5356 json.txOuts.forEach(function (txOut) {
5357 txOuts.push(new TxOut().fromJSON(txOut));
5358 });
5359 this.fromObject({
5360 versionBytesNum: json.versionBytesNum,
5361 txInsVi: new VarInt().fromJSON(json.txInsVi),
5362 txIns: txIns,
5363 txOutsVi: new VarInt().fromJSON(json.txOutsVi),
5364 txOuts: txOuts,
5365 nLockTime: json.nLockTime
5366 });
5367 return this;
5368 }
5369
5370 toJSON() {
5371 const txIns = [];
5372 this.txIns.forEach(function (txIn) {
5373 txIns.push(txIn.toJSON());
5374 });
5375 const txOuts = [];
5376 this.txOuts.forEach(function (txOut) {
5377 txOuts.push(txOut.toJSON());
5378 });
5379 return {
5380 versionBytesNum: this.versionBytesNum,
5381 txInsVi: this.txInsVi.toJSON(),
5382 txIns: txIns,
5383 txOutsVi: this.txOutsVi.toJSON(),
5384 txOuts: txOuts,
5385 nLockTime: this.nLockTime
5386 };
5387 }
5388
5389 fromBr(br) {
5390 this.versionBytesNum = br.readUInt32LE();
5391 this.txInsVi = new VarInt(br.readVarIntBuf());
5392 const txInsNum = this.txInsVi.toNumber();
5393 this.txIns = [];
5394
5395 for (let i = 0; i < txInsNum; i++) {
5396 this.txIns.push(new TxIn().fromBr(br));
5397 }
5398
5399 this.txOutsVi = new VarInt(br.readVarIntBuf());
5400 const txOutsNum = this.txOutsVi.toNumber();
5401 this.txOuts = [];
5402
5403 for (let i = 0; i < txOutsNum; i++) {
5404 this.txOuts.push(new TxOut().fromBr(br));
5405 }
5406
5407 this.nLockTime = br.readUInt32LE();
5408 return this;
5409 }
5410
5411 toBw(bw) {
5412 if (!bw) {
5413 bw = new Bw();
5414 }
5415
5416 bw.writeUInt32LE(this.versionBytesNum);
5417 bw.write(this.txInsVi.buf);
5418
5419 for (let i = 0; i < this.txIns.length; i++) {
5420 this.txIns[i].toBw(bw);
5421 }
5422
5423 bw.write(this.txOutsVi.buf);
5424
5425 for (let i = 0; i < this.txOuts.length; i++) {
5426 this.txOuts[i].toBw(bw);
5427 }
5428
5429 bw.writeUInt32LE(this.nLockTime);
5430 return bw;
5431 }
5432
5433 hashPrevouts() {
5434 const bw = new Bw();
5435
5436 for (const i in this.txIns) {
5437 const txIn = this.txIns[i];
5438 bw.write(txIn.txHashBuf);
5439 bw.writeUInt32LE(txIn.txOutNum);
5440 }
5441
5442 return Hash.sha256Sha256(bw.toBuffer());
5443 }
5444
5445 hashSequence() {
5446 const bw = new Bw();
5447
5448 for (const i in this.txIns) {
5449 const txIn = this.txIns[i];
5450 bw.writeUInt32LE(txIn.nSequence);
5451 }
5452
5453 return Hash.sha256Sha256(bw.toBuffer());
5454 }
5455
5456 hashOutputs() {
5457 const bw = new Bw();
5458
5459 for (const i in this.txOuts) {
5460 const txOut = this.txOuts[i];
5461 bw.write(txOut.toBuffer());
5462 }
5463
5464 return Hash.sha256Sha256(bw.toBuffer());
5465 }
5466
5467 sighash(nHashType, nIn, subScript, valueBn, flags = 0, hashCache = new HashCache()) {
5468 if (nHashType & Sig.SIGHASH_FORKID && flags & Tx.SCRIPT_ENABLE_SIGHASH_FORKID) {
5469 let hashPrevouts = Buffer.alloc(32, 0);
5470 let hashSequence = Buffer.alloc(32, 0);
5471 let hashOutputs = Buffer.alloc(32, 0);
5472
5473 if (!(nHashType & Sig.SIGHASH_ANYONECANPAY)) {
5474 hashPrevouts = hashCache.prevoutsHashBuf ? hashCache.prevoutsHashBuf : hashCache.prevoutsHashBuf = this.hashPrevouts();
5475 }
5476
5477 if (!(nHashType & Sig.SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) !== Sig.SIGHASH_SINGLE && (nHashType & 0x1f) !== Sig.SIGHASH_NONE) {
5478 hashSequence = hashCache.sequenceHashBuf ? hashCache.sequenceHashBuf : hashCache.sequenceHashBuf = this.hashSequence();
5479 }
5480
5481 if ((nHashType & 0x1f) !== Sig.SIGHASH_SINGLE && (nHashType & 0x1f) !== Sig.SIGHASH_NONE) {
5482 hashOutputs = hashCache.outputsHashBuf ? hashCache.outputsHashBuf : hashCache.outputsHashBuf = this.hashOutputs();
5483 } else if ((nHashType & 0x1f) === Sig.SIGHASH_SINGLE && nIn < this.txOuts.length) {
5484 hashOutputs = Hash.sha256Sha256(this.txOuts[nIn].toBuffer());
5485 }
5486
5487 const bw = new Bw();
5488 bw.writeUInt32LE(this.versionBytesNum);
5489 bw.write(hashPrevouts);
5490 bw.write(hashSequence);
5491 bw.write(this.txIns[nIn].txHashBuf);
5492 bw.writeUInt32LE(this.txIns[nIn].txOutNum);
5493 bw.writeVarIntNum(subScript.toBuffer().length);
5494 bw.write(subScript.toBuffer());
5495 bw.writeUInt64LEBn(valueBn);
5496 bw.writeUInt32LE(this.txIns[nIn].nSequence);
5497 bw.write(hashOutputs);
5498 bw.writeUInt32LE(this.nLockTime);
5499 bw.writeUInt32LE(nHashType >>> 0);
5500 return new Br(Hash.sha256Sha256(bw.toBuffer())).readReverse();
5501 }
5502
5503 const txcopy = this.cloneByBuffer();
5504 subScript = new Script().fromBuffer(subScript.toBuffer());
5505 subScript.removeCodeseparators();
5506
5507 for (let i = 0; i < txcopy.txIns.length; i++) {
5508 txcopy.txIns[i] = TxIn.fromBuffer(txcopy.txIns[i].toBuffer()).setScript(new Script());
5509 }
5510
5511 txcopy.txIns[nIn] = TxIn.fromBuffer(txcopy.txIns[nIn].toBuffer()).setScript(subScript);
5512
5513 if ((nHashType & 31) === Sig.SIGHASH_NONE) {
5514 txcopy.txOuts.length = 0;
5515 txcopy.txOutsVi = VarInt.fromNumber(0);
5516
5517 for (let i = 0; i < txcopy.txIns.length; i++) {
5518 if (i !== nIn) {
5519 txcopy.txIns[i].nSequence = 0;
5520 }
5521 }
5522 } else if ((nHashType & 31) === Sig.SIGHASH_SINGLE) {
5523 if (nIn > txcopy.txOuts.length - 1) {
5524 return Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex');
5525 }
5526
5527 txcopy.txOuts.length = nIn + 1;
5528 txcopy.txOutsVi = VarInt.fromNumber(nIn + 1);
5529
5530 for (let i = 0; i < txcopy.txOuts.length; i++) {
5531 if (i < nIn) {
5532 txcopy.txOuts[i] = TxOut.fromProperties(new Bn().fromBuffer(Buffer.from('ffffffffffffffff', 'hex')), new Script());
5533 }
5534 }
5535
5536 for (let i = 0; i < txcopy.txIns.length; i++) {
5537 if (i !== nIn) {
5538 txcopy.txIns[i].nSequence = 0;
5539 }
5540 }
5541 }
5542
5543 if (nHashType & Sig.SIGHASH_ANYONECANPAY) {
5544 txcopy.txIns[0] = txcopy.txIns[nIn];
5545 txcopy.txIns.length = 1;
5546 txcopy.txInsVi = VarInt.fromNumber(1);
5547 }
5548
5549 const buf = new Bw().write(txcopy.toBuffer()).writeInt32LE(nHashType).toBuffer();
5550 return new Br(Hash.sha256Sha256(buf)).readReverse();
5551 }
5552
5553 async asyncSighash(nHashType, nIn, subScript, valueBn, flags = 0, hashCache = {}) {
5554 const workersResult = await Workers.asyncObjectMethod(this, 'sighash', [nHashType, nIn, subScript, valueBn, flags, hashCache]);
5555 return workersResult.resbuf;
5556 }
5557
5558 sign(keyPair, nHashType = Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID, nIn, subScript, valueBn, flags = Tx.SCRIPT_ENABLE_SIGHASH_FORKID, hashCache = {}) {
5559 const hashBuf = this.sighash(nHashType, nIn, subScript, valueBn, flags, hashCache);
5560 const sig = Ecdsa.sign(hashBuf, keyPair, 'little').fromObject({
5561 nHashType: nHashType
5562 });
5563 return sig;
5564 }
5565
5566 async asyncSign(keyPair, nHashType = Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID, nIn, subScript, valueBn, flags = Tx.SCRIPT_ENABLE_SIGHASH_FORKID, hashCache = {}) {
5567 const workersResult = await Workers.asyncObjectMethod(this, 'sign', [keyPair, nHashType, nIn, subScript, valueBn, flags, hashCache]);
5568 return new Sig().fromFastBuffer(workersResult.resbuf);
5569 }
5570
5571 verify(sig, pubKey, nIn, subScript, enforceLowS = false, valueBn, flags = Tx.SCRIPT_ENABLE_SIGHASH_FORKID, hashCache = {}) {
5572 const hashBuf = this.sighash(sig.nHashType, nIn, subScript, valueBn, flags, hashCache);
5573 return Ecdsa.verify(hashBuf, sig, pubKey, 'little', enforceLowS);
5574 }
5575
5576 async asyncVerify(sig, pubKey, nIn, subScript, enforceLowS = false, valueBn, flags = Tx.SCRIPT_ENABLE_SIGHASH_FORKID, hashCache = {}) {
5577 const workersResult = await Workers.asyncObjectMethod(this, 'verify', [sig, pubKey, nIn, subScript, enforceLowS, valueBn, flags, hashCache]);
5578 return JSON.parse(workersResult.resbuf.toString());
5579 }
5580
5581 hash() {
5582 return Hash.sha256Sha256(this.toBuffer());
5583 }
5584
5585 async asyncHash() {
5586 const workersResult = await Workers.asyncObjectMethod(this, 'hash', []);
5587 return workersResult.resbuf;
5588 }
5589
5590 id() {
5591 return new Br(this.hash()).readReverse().toString('hex');
5592 }
5593
5594 async asyncId() {
5595 const workersResult = await Workers.asyncObjectMethod(this, 'id', []);
5596 return JSON.parse(workersResult.resbuf.toString());
5597 }
5598
5599 addTxIn(txHashBuf, txOutNum, script, nSequence) {
5600 let txIn;
5601
5602 if (txHashBuf instanceof TxIn) {
5603 txIn = txHashBuf;
5604 } else {
5605 txIn = new TxIn().fromObject({
5606 txHashBuf,
5607 txOutNum,
5608 nSequence
5609 }).setScript(script);
5610 }
5611
5612 this.txIns.push(txIn);
5613 this.txInsVi = VarInt.fromNumber(this.txInsVi.toNumber() + 1);
5614 return this;
5615 }
5616
5617 addTxOut(valueBn, script) {
5618 let txOut;
5619
5620 if (valueBn instanceof TxOut) {
5621 txOut = valueBn;
5622 } else {
5623 txOut = new TxOut().fromObject({
5624 valueBn
5625 }).setScript(script);
5626 }
5627
5628 this.txOuts.push(txOut);
5629 this.txOutsVi = VarInt.fromNumber(this.txOutsVi.toNumber() + 1);
5630 return this;
5631 }
5632
5633 isCoinbase() {
5634 return this.txIns.length === 1 && this.txIns[0].hasNullInput();
5635 }
5636
5637 sort() {
5638 this.txIns.sort((first, second) => {
5639 return new Br(first.txHashBuf).readReverse().compare(new Br(second.txHashBuf).readReverse()) || first.txOutNum - second.txOutNum;
5640 });
5641 this.txOuts.sort((first, second) => {
5642 return first.valueBn.sub(second.valueBn).toNumber() || first.script.toBuffer().compare(second.script.toBuffer());
5643 });
5644 return this;
5645 }
5646
5647}
5648
5649Tx.MAX_MONEY = 21000000 * 1e8;
5650Tx.SCRIPT_ENABLE_SIGHASH_FORKID = 1 << 16;
5651
5652class Block extends Struct {
5653 constructor(blockHeader, txsVi, txs) {
5654 super({
5655 blockHeader,
5656 txsVi,
5657 txs
5658 });
5659 }
5660
5661 fromJSON(json) {
5662 const txs = [];
5663 json.txs.forEach(function (tx) {
5664 txs.push(new Tx().fromJSON(tx));
5665 });
5666 this.fromObject({
5667 blockHeader: new BlockHeader().fromJSON(json.blockHeader),
5668 txsVi: new VarInt().fromJSON(json.txsVi),
5669 txs: txs
5670 });
5671 return this;
5672 }
5673
5674 toJSON() {
5675 const txs = [];
5676 this.txs.forEach(function (tx) {
5677 txs.push(tx.toJSON());
5678 });
5679 return {
5680 blockHeader: this.blockHeader.toJSON(),
5681 txsVi: this.txsVi.toJSON(),
5682 txs: txs
5683 };
5684 }
5685
5686 fromBr(br) {
5687 this.blockHeader = new BlockHeader().fromBr(br);
5688 this.txsVi = new VarInt(br.readVarIntBuf());
5689 const txsNum = this.txsVi.toNumber();
5690 this.txs = [];
5691
5692 for (let i = 0; i < txsNum; i++) {
5693 this.txs.push(new Tx().fromBr(br));
5694 }
5695
5696 return this;
5697 }
5698
5699 toBw(bw) {
5700 if (!bw) {
5701 bw = new Bw();
5702 }
5703
5704 bw.write(this.blockHeader.toBuffer());
5705 bw.write(this.txsVi.buf);
5706 const txsNum = this.txsVi.toNumber();
5707
5708 for (let i = 0; i < txsNum; i++) {
5709 this.txs[i].toBw(bw);
5710 }
5711
5712 return bw;
5713 }
5714
5715 hash() {
5716 return Hash.sha256Sha256(this.blockHeader.toBuffer());
5717 }
5718
5719 async asyncHash() {
5720 const workersResult = await Workers.asyncObjectMethod(this, 'hash', []);
5721 return workersResult.resbuf;
5722 }
5723
5724 id() {
5725 return new Br(this.hash()).readReverse().toString('hex');
5726 }
5727
5728 async asyncId() {
5729 const workersResult = await Workers.asyncObjectMethod(this, 'id', []);
5730 return JSON.parse(workersResult.resbuf.toString());
5731 }
5732
5733 verifyMerkleRoot() {
5734 const txsbufs = this.txs.map(tx => tx.toBuffer());
5735 const merkleRootBuf = Merkle.fromBuffers(txsbufs).hash();
5736 return Buffer.compare(merkleRootBuf, this.blockHeader.merkleRootBuf);
5737 }
5738
5739 static iterateTxs(blockBuf) {
5740 const br = new Br(blockBuf);
5741 const blockHeader = new BlockHeader().fromBr(br);
5742 const txsVi = new VarInt(br.readVarIntBuf());
5743 const txsNum = txsVi.toNumber();
5744 return {
5745 blockHeader,
5746 txsVi,
5747 txsNum,
5748
5749 *[Symbol.iterator]() {
5750 for (let i = 0; i < txsNum; i++) {
5751 yield new Tx().fromBr(br);
5752 }
5753 }
5754
5755 };
5756 }
5757
5758}
5759
5760Block.MAX_BLOCK_SIZE = 1000000;
5761
5762class Interp extends Struct {
5763 constructor(script, tx, nIn, stack = [], altStack = [], pc = 0, pBeginCodeHash = 0, nOpCount = 0, ifStack = [], errStr = '', flags = Interp.defaultFlags, valueBn = new Bn(0)) {
5764 super({
5765 script,
5766 tx,
5767 nIn,
5768 stack,
5769 altStack,
5770 pc,
5771 pBeginCodeHash,
5772 nOpCount,
5773 ifStack,
5774 errStr,
5775 flags,
5776 valueBn
5777 });
5778 }
5779
5780 initialize() {
5781 this.script = new Script();
5782 this.stack = [];
5783 this.altStack = [];
5784 this.pc = 0;
5785 this.pBeginCodeHash = 0;
5786 this.nOpCount = 0;
5787 this.ifStack = [];
5788 this.errStr = '';
5789 this.flags = Interp.defaultFlags;
5790 return this;
5791 }
5792
5793 fromJSON(json) {
5794 this.fromJSONNoTx(json);
5795 this.tx = json.tx ? new Tx().fromJSON(json.tx) : undefined;
5796 return this;
5797 }
5798
5799 fromJSONNoTx(json) {
5800 this.fromObject({
5801 script: json.script !== undefined ? new Script().fromJSON(json.script) : undefined,
5802 nIn: json.nIn
5803 });
5804 this.stack = [];
5805 json.stack.forEach(function (hex) {
5806 this.stack.push(Buffer.from(hex, 'hex'));
5807 }.bind(this));
5808 this.altStack = [];
5809 json.altStack.forEach(function (hex) {
5810 this.altStack.push(Buffer.from(hex, 'hex'));
5811 }.bind(this));
5812 this.fromObject({
5813 pc: json.pc,
5814 pBeginCodeHash: json.pBeginCodeHash,
5815 nOpCount: json.nOpCount,
5816 ifStack: json.ifStack,
5817 errStr: json.errStr,
5818 flags: json.flags
5819 });
5820 return this;
5821 }
5822
5823 fromBr(br) {
5824 let jsonNoTxBufLEn = br.readVarIntNum();
5825 let jsonNoTxBuf = br.read(jsonNoTxBufLEn);
5826 this.fromJSONNoTx(JSON.parse(jsonNoTxBuf.toString()));
5827 let txbuflen = br.readVarIntNum();
5828
5829 if (txbuflen > 0) {
5830 let txbuf = br.read(txbuflen);
5831 this.tx = new Tx().fromFastBuffer(txbuf);
5832 }
5833
5834 return this;
5835 }
5836
5837 toJSON() {
5838 let json = this.toJSONNoTx();
5839 json.tx = this.tx ? this.tx.toJSON() : undefined;
5840 return json;
5841 }
5842
5843 toJSONNoTx() {
5844 let stack = [];
5845 this.stack.forEach(function (buf) {
5846 stack.push(buf.toString('hex'));
5847 });
5848 let altStack = [];
5849 this.altStack.forEach(function (buf) {
5850 altStack.push(buf.toString('hex'));
5851 });
5852 return {
5853 script: this.script ? this.script.toJSON() : undefined,
5854 nIn: this.nIn,
5855 stack: stack,
5856 altStack: altStack,
5857 pc: this.pc,
5858 pBeginCodeHash: this.pBeginCodeHash,
5859 nOpCount: this.nOpCount,
5860 ifStack: this.ifStack,
5861 errStr: this.errStr,
5862 flags: this.flags
5863 };
5864 }
5865
5866 toBw(bw) {
5867 if (!bw) {
5868 bw = new Bw();
5869 }
5870
5871 let jsonNoTxBuf = Buffer.from(JSON.stringify(this.toJSONNoTx()));
5872 bw.writeVarIntNum(jsonNoTxBuf.length);
5873 bw.write(jsonNoTxBuf);
5874
5875 if (this.tx) {
5876 let txbuf = this.tx.toFastBuffer();
5877 bw.writeVarIntNum(txbuf.length);
5878 bw.write(txbuf);
5879 } else {
5880 bw.writeVarIntNum(0);
5881 }
5882
5883 return bw;
5884 }
5885
5886 static getFlags(flagstr) {
5887 let flags = 0;
5888
5889 if (flagstr.indexOf('NONE') !== -1) {
5890 flags = flags | Interp.SCRIPT_VERIFY_NONE;
5891 }
5892
5893 if (flagstr.indexOf('P2SH') !== -1) {
5894 flags = flags | Interp.SCRIPT_VERIFY_P2SH;
5895 }
5896
5897 if (flagstr.indexOf('STRICTENC') !== -1) {
5898 flags = flags | Interp.SCRIPT_VERIFY_STRICTENC;
5899 }
5900
5901 if (flagstr.indexOf('DERSIG') !== -1) {
5902 flags = flags | Interp.SCRIPT_VERIFY_DERSIG;
5903 }
5904
5905 if (flagstr.indexOf('LOW_S') !== -1) {
5906 flags = flags | Interp.SCRIPT_VERIFY_LOW_S;
5907 }
5908
5909 if (flagstr.indexOf('NULLDUMMY') !== -1) {
5910 flags = flags | Interp.SCRIPT_VERIFY_NULLDUMMY;
5911 }
5912
5913 if (flagstr.indexOf('SIGPUSHONLY') !== -1) {
5914 flags = flags | Interp.SCRIPT_VERIFY_SIGPUSHONLY;
5915 }
5916
5917 if (flagstr.indexOf('MINIMALDATA') !== -1) {
5918 flags = flags | Interp.SCRIPT_VERIFY_MINIMALDATA;
5919 }
5920
5921 if (flagstr.indexOf('DISCOURAGE_UPGRADABLE_NOPS') !== -1) {
5922 flags = flags | Interp.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS;
5923 }
5924
5925 if (flagstr.indexOf('CLEANSTACK') !== -1) {
5926 flags = flags | Interp.SCRIPT_VERIFY_CLEANSTACK;
5927 }
5928
5929 if (flagstr.indexOf('CHECKLOCKTIMEVERIFY') !== -1) {
5930 flags = flags | Interp.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
5931 }
5932
5933 if (flagstr.indexOf('CHECKSEQUENCEVERIFY') !== -1) {
5934 flags = flags | Interp.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY;
5935 }
5936
5937 if (flagstr.indexOf('SIGHASH_FORKID') !== -1) {
5938 flags = flags | Interp.SCRIPT_ENABLE_SIGHASH_FORKID;
5939 }
5940
5941 return flags;
5942 }
5943
5944 static castToBool(buf) {
5945 for (let i = 0; i < buf.length; i++) {
5946 if (buf[i] !== 0) {
5947 if (i === buf.length - 1 && buf[i] === 0x80) {
5948 return false;
5949 }
5950
5951 return true;
5952 }
5953 }
5954
5955 return false;
5956 }
5957
5958 checkSigEncoding(buf) {
5959 if (buf.length === 0) {
5960 return true;
5961 }
5962
5963 if ((this.flags & (Interp.SCRIPT_VERIFY_DERSIG | Interp.SCRIPT_VERIFY_LOW_S | Interp.SCRIPT_VERIFY_STRICTENC)) !== 0 && !Sig.IsTxDer(buf)) {
5964 this.errStr = 'SCRIPT_ERR_SIG_DER';
5965 return false;
5966 } else if ((this.flags & Interp.SCRIPT_VERIFY_LOW_S) !== 0) {
5967 let sig = new Sig().fromTxFormat(buf);
5968
5969 if (!sig.hasLowS()) {
5970 this.errStr = 'SCRIPT_ERR_SIG_DER';
5971 return false;
5972 }
5973 } else if ((this.flags & Interp.SCRIPT_VERIFY_STRICTENC) !== 0) {
5974 let sig = new Sig().fromTxFormat(buf);
5975
5976 if (!sig.hasDefinedHashType()) {
5977 this.errStr = 'SCRIPT_ERR_SIG_HASHTYPE';
5978 return false;
5979 }
5980 }
5981
5982 return true;
5983 }
5984
5985 checkPubKeyEncoding(buf) {
5986 if ((this.flags & Interp.SCRIPT_VERIFY_STRICTENC) !== 0 && !PubKey.isCompressedOrUncompressed(buf)) {
5987 this.errStr = 'SCRIPT_ERR_PUBKEYTYPE';
5988 return false;
5989 }
5990
5991 return true;
5992 }
5993
5994 checkLockTime(nLockTime) {
5995 if (!(this.tx.nLockTime < Interp.LOCKTIME_THRESHOLD && nLockTime < Interp.LOCKTIME_THRESHOLD || this.tx.nLockTime >= Interp.LOCKTIME_THRESHOLD && nLockTime >= Interp.LOCKTIME_THRESHOLD)) {
5996 return false;
5997 }
5998
5999 if (nLockTime > this.tx.nLockTime) {
6000 return false;
6001 }
6002
6003 if (TxIn.SEQUENCE_FINAL === this.tx.txIns[this.nIn].nSequence) {
6004 return false;
6005 }
6006
6007 return true;
6008 }
6009
6010 checkSequence(nSequence) {
6011 let txToSequence = this.tx.txIns[this.nIn].nSequence;
6012
6013 if (this.tx.versionBytesNum < 2) {
6014 return false;
6015 }
6016
6017 if (txToSequence & TxIn.SEQUENCE_LOCKTIME_DISABLE_FLAG) {
6018 return false;
6019 }
6020
6021 let nLockTimeMask = TxIn.SEQUENCE_LOCKTIME_TYPE_FLAG | TxIn.SEQUENCE_LOCKTIME_MASK;
6022 let txToSequenceMasked = txToSequence & nLockTimeMask;
6023 let nSequenceMasked = nSequence & nLockTimeMask;
6024
6025 if (!(txToSequenceMasked < TxIn.SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < TxIn.SEQUENCE_LOCKTIME_TYPE_FLAG || txToSequenceMasked >= TxIn.SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= TxIn.SEQUENCE_LOCKTIME_TYPE_FLAG)) {
6026 return false;
6027 }
6028
6029 if (nSequenceMasked > txToSequenceMasked) {
6030 return false;
6031 }
6032
6033 return true;
6034 }
6035
6036 *eval() {
6037 if (this.script.toBuffer().length > 10000) {
6038 this.errStr = 'SCRIPT_ERR_SCRIPT_SIZE';
6039 yield false;
6040 }
6041
6042 try {
6043 while (this.pc < this.script.chunks.length) {
6044 let fSuccess = this.step();
6045
6046 if (!fSuccess) {
6047 yield false;
6048 } else {
6049 yield fSuccess;
6050 }
6051 }
6052
6053 if (this.stack.length + this.altStack.length > 1000) {
6054 this.errStr = 'SCRIPT_ERR_STACK_SIZE';
6055 yield false;
6056 }
6057 } catch (e) {
6058 this.errStr = 'SCRIPT_ERR_UNKNOWN_ERROR: ' + e;
6059 yield false;
6060 }
6061
6062 if (this.ifStack.length > 0) {
6063 this.errStr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
6064 yield false;
6065 }
6066
6067 yield true;
6068 }
6069
6070 step() {
6071 let fRequireMinimal = (this.flags & Interp.SCRIPT_VERIFY_MINIMALDATA) !== 0;
6072 let fExec = !(this.ifStack.indexOf(false) + 1);
6073 let chunk = this.script.chunks[this.pc];
6074 this.pc++;
6075 let opCodeNum = chunk.opCodeNum;
6076
6077 if (opCodeNum === undefined) {
6078 this.errStr = 'SCRIPT_ERR_BAD_OPCODE';
6079 return false;
6080 }
6081
6082 if (chunk.buf && chunk.buf.length > Interp.MAX_SCRIPT_ELEMENT_SIZE) {
6083 this.errStr = 'SCRIPT_ERR_PUSH_SIZE';
6084 return false;
6085 }
6086
6087 if (opCodeNum > OpCode.OP_16 && ++this.nOpCount > 201) {
6088 this.errStr = 'SCRIPT_ERR_OP_COUNT';
6089 return false;
6090 }
6091
6092 if (opCodeNum === OpCode.OP_LEFT || opCodeNum === OpCode.OP_RIGHT || opCodeNum === OpCode.OP_2MUL || opCodeNum === OpCode.OP_2DIV) {
6093 this.errStr = 'SCRIPT_ERR_DISABLED_OPCODE';
6094 return false;
6095 }
6096
6097 if (fExec && opCodeNum >= 0 && opCodeNum <= OpCode.OP_PUSHDATA4) {
6098 if (fRequireMinimal && !this.script.checkMinimalPush(this.pc - 1)) {
6099 this.errStr = 'SCRIPT_ERR_MINIMALDATA';
6100 return false;
6101 }
6102
6103 if (!chunk.buf) {
6104 this.stack.push(Interp.false);
6105 } else if (chunk.len !== chunk.buf.length) {
6106 throw new Error('LEngth of push value not equal to length of data');
6107 } else {
6108 this.stack.push(chunk.buf);
6109 }
6110 } else if (fExec || OpCode.OP_IF <= opCodeNum && opCodeNum <= OpCode.OP_ENDIF) {
6111 switch (opCodeNum) {
6112 case OpCode.OP_1NEGATE:
6113 case OpCode.OP_1:
6114 case OpCode.OP_2:
6115 case OpCode.OP_3:
6116 case OpCode.OP_4:
6117 case OpCode.OP_5:
6118 case OpCode.OP_6:
6119 case OpCode.OP_7:
6120 case OpCode.OP_8:
6121 case OpCode.OP_9:
6122 case OpCode.OP_10:
6123 case OpCode.OP_11:
6124 case OpCode.OP_12:
6125 case OpCode.OP_13:
6126 case OpCode.OP_14:
6127 case OpCode.OP_15:
6128 case OpCode.OP_16:
6129 {
6130 let n = opCodeNum - (OpCode.OP_1 - 1);
6131
6132 let _buf = new Bn(n).toScriptNumBuffer();
6133
6134 this.stack.push(_buf);
6135 }
6136 break;
6137
6138 case OpCode.OP_NOP:
6139 break;
6140
6141 case OpCode.OP_CHECKLOCKTIMEVERIFY:
6142 {
6143 if (!(this.flags & Interp.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
6144 if (this.flags & Interp.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
6145 this.errStr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS';
6146 return false;
6147 }
6148
6149 break;
6150 }
6151
6152 if (this.stack.length < 1) {
6153 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6154 return false;
6155 }
6156
6157 let nLockTimebuf = this.stack[this.stack.length - 1];
6158 let nLockTimebn = new Bn().fromScriptNumBuffer(nLockTimebuf, fRequireMinimal, 5);
6159 let nLockTime = nLockTimebn.toNumber();
6160
6161 if (nLockTime < 0) {
6162 this.errStr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME';
6163 return false;
6164 }
6165
6166 if (!this.checkLockTime(nLockTime)) {
6167 this.errStr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME';
6168 return false;
6169 }
6170 }
6171 break;
6172
6173 case OpCode.OP_CHECKSEQUENCEVERIFY:
6174 {
6175 if (!(this.flags & Interp.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) {
6176 if (this.flags & Interp.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
6177 this.errStr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS';
6178 return false;
6179 }
6180
6181 break;
6182 }
6183
6184 if (this.stack.length < 1) {
6185 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6186 return false;
6187 }
6188
6189 let nSequencebuf = this.stack[this.stack.length - 1];
6190 let nSequencebn = new Bn().fromScriptNumBuffer(nSequencebuf, fRequireMinimal, 5);
6191 let nSequence = nSequencebn.toNumber();
6192
6193 if (nSequence < 0) {
6194 this.errStr = 'SCRIPT_ERR_NEGATIVE_LOCKTIME';
6195 return false;
6196 }
6197
6198 if ((nSequence & TxIn.SEQUENCE_LOCKTIME_DISABLE_FLAG) !== 0) {
6199 break;
6200 }
6201
6202 if (!this.checkSequence(nSequence)) {
6203 this.errStr = 'SCRIPT_ERR_UNSATISFIED_LOCKTIME';
6204 return false;
6205 }
6206 }
6207 break;
6208
6209 case OpCode.OP_NOP1:
6210 case OpCode.OP_NOP3:
6211 case OpCode.OP_NOP4:
6212 case OpCode.OP_NOP5:
6213 case OpCode.OP_NOP6:
6214 case OpCode.OP_NOP7:
6215 case OpCode.OP_NOP8:
6216 case OpCode.OP_NOP9:
6217 case OpCode.OP_NOP10:
6218 if (this.flags & Interp.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
6219 this.errStr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS';
6220 return false;
6221 }
6222
6223 break;
6224
6225 case OpCode.OP_IF:
6226 case OpCode.OP_NOTIF:
6227 {
6228 let fValue = false;
6229
6230 if (fExec) {
6231 if (this.stack.length < 1) {
6232 this.errStr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
6233 return false;
6234 }
6235
6236 let _buf2 = this.stack.pop();
6237
6238 fValue = Interp.castToBool(_buf2);
6239
6240 if (opCodeNum === OpCode.OP_NOTIF) {
6241 fValue = !fValue;
6242 }
6243 }
6244
6245 this.ifStack.push(fValue);
6246 }
6247 break;
6248
6249 case OpCode.OP_ELSE:
6250 if (this.ifStack.length === 0) {
6251 this.errStr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
6252 return false;
6253 }
6254
6255 this.ifStack[this.ifStack.length - 1] = !this.ifStack[this.ifStack.length - 1];
6256 break;
6257
6258 case OpCode.OP_ENDIF:
6259 if (this.ifStack.length === 0) {
6260 this.errStr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
6261 return false;
6262 }
6263
6264 this.ifStack.pop();
6265 break;
6266
6267 case OpCode.OP_VERIFY:
6268 {
6269 if (this.stack.length < 1) {
6270 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6271 return false;
6272 }
6273
6274 let _buf3 = this.stack[this.stack.length - 1];
6275 let fValue = Interp.castToBool(_buf3);
6276
6277 if (fValue) {
6278 this.stack.pop();
6279 } else {
6280 this.errStr = 'SCRIPT_ERR_VERIFY';
6281 return false;
6282 }
6283 }
6284 break;
6285
6286 case OpCode.OP_RETURN:
6287 {
6288 this.errStr = 'SCRIPT_ERR_OP_RETURN';
6289 return false;
6290 }
6291
6292 case OpCode.OP_TOALTSTACK:
6293 if (this.stack.length < 1) {
6294 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6295 return false;
6296 }
6297
6298 this.altStack.push(this.stack.pop());
6299 break;
6300
6301 case OpCode.OP_FROMALTSTACK:
6302 if (this.altStack.length < 1) {
6303 this.errStr = 'SCRIPT_ERR_INVALID_ALTSTACK_OPERATION';
6304 return false;
6305 }
6306
6307 this.stack.push(this.altStack.pop());
6308 break;
6309
6310 case OpCode.OP_2DROP:
6311 if (this.stack.length < 2) {
6312 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6313 return false;
6314 }
6315
6316 this.stack.pop();
6317 this.stack.pop();
6318 break;
6319
6320 case OpCode.OP_2DUP:
6321 {
6322 if (this.stack.length < 2) {
6323 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6324 return false;
6325 }
6326
6327 let _buf4 = this.stack[this.stack.length - 2];
6328 let _buf5 = this.stack[this.stack.length - 1];
6329 this.stack.push(_buf4);
6330 this.stack.push(_buf5);
6331 }
6332 break;
6333
6334 case OpCode.OP_3DUP:
6335 {
6336 if (this.stack.length < 3) {
6337 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6338 return false;
6339 }
6340
6341 let _buf6 = this.stack[this.stack.length - 3];
6342 let _buf7 = this.stack[this.stack.length - 2];
6343 let buf3 = this.stack[this.stack.length - 1];
6344 this.stack.push(_buf6);
6345 this.stack.push(_buf7);
6346 this.stack.push(buf3);
6347 }
6348 break;
6349
6350 case OpCode.OP_2OVER:
6351 {
6352 if (this.stack.length < 4) {
6353 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6354 return false;
6355 }
6356
6357 let _buf8 = this.stack[this.stack.length - 4];
6358 let _buf9 = this.stack[this.stack.length - 3];
6359 this.stack.push(_buf8);
6360 this.stack.push(_buf9);
6361 }
6362 break;
6363
6364 case OpCode.OP_2ROT:
6365 {
6366 if (this.stack.length < 6) {
6367 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6368 return false;
6369 }
6370
6371 let spliced = this.stack.splice(this.stack.length - 6, 2);
6372 this.stack.push(spliced[0]);
6373 this.stack.push(spliced[1]);
6374 }
6375 break;
6376
6377 case OpCode.OP_2SWAP:
6378 {
6379 if (this.stack.length < 4) {
6380 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6381 return false;
6382 }
6383
6384 let spliced = this.stack.splice(this.stack.length - 4, 2);
6385 this.stack.push(spliced[0]);
6386 this.stack.push(spliced[1]);
6387 }
6388 break;
6389
6390 case OpCode.OP_IFDUP:
6391 {
6392 if (this.stack.length < 1) {
6393 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6394 return false;
6395 }
6396
6397 let _buf10 = this.stack[this.stack.length - 1];
6398 let fValue = Interp.castToBool(_buf10);
6399
6400 if (fValue) {
6401 this.stack.push(_buf10);
6402 }
6403 }
6404 break;
6405
6406 case OpCode.OP_DEPTH:
6407 {
6408 let _buf11 = new Bn(this.stack.length).toScriptNumBuffer();
6409
6410 this.stack.push(_buf11);
6411 }
6412 break;
6413
6414 case OpCode.OP_DROP:
6415 if (this.stack.length < 1) {
6416 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6417 return false;
6418 }
6419
6420 this.stack.pop();
6421 break;
6422
6423 case OpCode.OP_DUP:
6424 if (this.stack.length < 1) {
6425 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6426 return false;
6427 }
6428
6429 this.stack.push(this.stack[this.stack.length - 1]);
6430 break;
6431
6432 case OpCode.OP_NIP:
6433 if (this.stack.length < 2) {
6434 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6435 return false;
6436 }
6437
6438 this.stack.splice(this.stack.length - 2, 1);
6439 break;
6440
6441 case OpCode.OP_OVER:
6442 if (this.stack.length < 2) {
6443 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6444 return false;
6445 }
6446
6447 this.stack.push(this.stack[this.stack.length - 2]);
6448 break;
6449
6450 case OpCode.OP_PICK:
6451 case OpCode.OP_ROLL:
6452 {
6453 if (this.stack.length < 2) {
6454 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6455 return false;
6456 }
6457
6458 let _buf12 = this.stack[this.stack.length - 1];
6459 let bn = new Bn().fromScriptNumBuffer(_buf12, fRequireMinimal);
6460 let n = bn.toNumber();
6461 this.stack.pop();
6462
6463 if (n < 0 || n >= this.stack.length) {
6464 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6465 return false;
6466 }
6467
6468 _buf12 = this.stack[this.stack.length - n - 1];
6469
6470 if (opCodeNum === OpCode.OP_ROLL) {
6471 this.stack.splice(this.stack.length - n - 1, 1);
6472 }
6473
6474 this.stack.push(_buf12);
6475 }
6476 break;
6477
6478 case OpCode.OP_ROT:
6479 {
6480 if (this.stack.length < 3) {
6481 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6482 return false;
6483 }
6484
6485 let x1 = this.stack[this.stack.length - 3];
6486 let x2 = this.stack[this.stack.length - 2];
6487 let x3 = this.stack[this.stack.length - 1];
6488 this.stack[this.stack.length - 3] = x2;
6489 this.stack[this.stack.length - 2] = x3;
6490 this.stack[this.stack.length - 1] = x1;
6491 }
6492 break;
6493
6494 case OpCode.OP_SWAP:
6495 {
6496 if (this.stack.length < 2) {
6497 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6498 return false;
6499 }
6500
6501 let x1 = this.stack[this.stack.length - 2];
6502 let x2 = this.stack[this.stack.length - 1];
6503 this.stack[this.stack.length - 2] = x2;
6504 this.stack[this.stack.length - 1] = x1;
6505 }
6506 break;
6507
6508 case OpCode.OP_TUCK:
6509 if (this.stack.length < 2) {
6510 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6511 return false;
6512 }
6513
6514 this.stack.splice(this.stack.length - 2, 0, this.stack[this.stack.length - 1]);
6515 break;
6516
6517 case OpCode.OP_SIZE:
6518 {
6519 if (this.stack.length < 1) {
6520 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6521 return false;
6522 }
6523
6524 let bn = new Bn(this.stack[this.stack.length - 1].length);
6525 this.stack.push(bn.toScriptNumBuffer());
6526 }
6527 break;
6528
6529 case OpCode.OP_OR:
6530 case OpCode.OP_AND:
6531 case OpCode.OP_XOR:
6532 if (this.stack.length < 2) {
6533 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6534 return false;
6535 }
6536
6537 let buf1 = this.stack[this.stack.length - 2];
6538 let buf2 = this.stack[this.stack.length - 1];
6539
6540 if (buf1.length != buf2.length) {
6541 this.errStr = 'SCRIPT_ERR_INVALID_OPERAND_SIZE';
6542 return false;
6543 }
6544
6545 switch (opCodeNum) {
6546 case OpCode.OP_AND:
6547 for (let i = 0; i < buf1.length; i++) {
6548 buf1[i] &= buf2[i];
6549 }
6550
6551 break;
6552
6553 case OpCode.OP_OR:
6554 for (let i = 0; i < buf1.length; i++) {
6555 buf1[i] |= buf2[i];
6556 }
6557
6558 break;
6559
6560 case OpCode.OP_XOR:
6561 for (let i = 0; i < buf1.length; i++) {
6562 buf1[i] ^= buf2[i];
6563 }
6564
6565 break;
6566 }
6567
6568 this.stack.pop();
6569 break;
6570
6571 case OpCode.OP_INVERT:
6572 if (this.stack.length < 1) {
6573 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6574 return false;
6575 }
6576
6577 let buf = this.stack[this.stack.length - 1];
6578
6579 for (let i = 0; i < buf.length; i++) {
6580 buf[i] = ~buf[i];
6581 }
6582
6583 break;
6584
6585 case OpCode.OP_LSHIFT:
6586 case OpCode.OP_RSHIFT:
6587 {
6588 if (this.stack.length < 2) {
6589 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6590 return false;
6591 }
6592
6593 let _buf13 = this.stack[this.stack.length - 2];
6594 let value = new Bn(_buf13);
6595 let n = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal).toNumber();
6596
6597 if (n < 0) {
6598 this.errStr = 'SCRIPT_ERR_INVALID_NUMBER_RANGE';
6599 return false;
6600 }
6601
6602 this.stack.pop();
6603 this.stack.pop();
6604
6605 switch (opCodeNum) {
6606 case OpCode.OP_LSHIFT:
6607 value = value.ushln(n);
6608 break;
6609
6610 case OpCode.OP_RSHIFT:
6611 value = value.ushrn(n);
6612 break;
6613 }
6614
6615 let _buf14 = value.toBuffer().slice(-_buf13.length);
6616
6617 if (_buf14.length < _buf13.length) {
6618 _buf14 = Buffer.concat([Buffer.alloc(_buf13.length - _buf14.length), _buf14]);
6619 }
6620
6621 this.stack.push(_buf14);
6622 break;
6623 }
6624
6625 case OpCode.OP_EQUAL:
6626 case OpCode.OP_EQUALVERIFY:
6627 {
6628 if (this.stack.length < 2) {
6629 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6630 return false;
6631 }
6632
6633 let _buf15 = this.stack[this.stack.length - 2];
6634 let _buf16 = this.stack[this.stack.length - 1];
6635 let fEqual = cmp(_buf15, _buf16);
6636 this.stack.pop();
6637 this.stack.pop();
6638 this.stack.push(fEqual ? Interp.true : Interp.false);
6639
6640 if (opCodeNum === OpCode.OP_EQUALVERIFY) {
6641 if (fEqual) {
6642 this.stack.pop();
6643 } else {
6644 this.errStr = 'SCRIPT_ERR_EQUALVERIFY';
6645 return false;
6646 }
6647 }
6648 }
6649 break;
6650
6651 case OpCode.OP_1ADD:
6652 case OpCode.OP_1SUB:
6653 case OpCode.OP_NEGATE:
6654 case OpCode.OP_ABS:
6655 case OpCode.OP_NOT:
6656 case OpCode.OP_0NOTEQUAL:
6657 {
6658 if (this.stack.length < 1) {
6659 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6660 return false;
6661 }
6662
6663 let _buf17 = this.stack[this.stack.length - 1];
6664 let bn = new Bn().fromScriptNumBuffer(_buf17, fRequireMinimal);
6665
6666 switch (opCodeNum) {
6667 case OpCode.OP_1ADD:
6668 bn = bn.add(1);
6669 break;
6670
6671 case OpCode.OP_1SUB:
6672 bn = bn.sub(1);
6673 break;
6674
6675 case OpCode.OP_NEGATE:
6676 bn = bn.neg();
6677 break;
6678
6679 case OpCode.OP_ABS:
6680 if (bn.lt(0)) bn = bn.neg();
6681 break;
6682
6683 case OpCode.OP_NOT:
6684 bn = new Bn(bn.eq(0) + 0);
6685 break;
6686
6687 case OpCode.OP_0NOTEQUAL:
6688 bn = new Bn(bn.neq(0) + 0);
6689 break;
6690 }
6691
6692 this.stack.pop();
6693 this.stack.push(bn.toScriptNumBuffer());
6694 }
6695 break;
6696
6697 case OpCode.OP_ADD:
6698 case OpCode.OP_SUB:
6699 case OpCode.OP_MUL:
6700 case OpCode.OP_DIV:
6701 case OpCode.OP_MOD:
6702 case OpCode.OP_BOOLAND:
6703 case OpCode.OP_BOOLOR:
6704 case OpCode.OP_NUMEQUAL:
6705 case OpCode.OP_NUMEQUALVERIFY:
6706 case OpCode.OP_NUMNOTEQUAL:
6707 case OpCode.OP_LESSTHAN:
6708 case OpCode.OP_GREATERTHAN:
6709 case OpCode.OP_LESSTHANOREQUAL:
6710 case OpCode.OP_GREATERTHANOREQUAL:
6711 case OpCode.OP_MIN:
6712 case OpCode.OP_MAX:
6713 {
6714 if (this.stack.length < 2) {
6715 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6716 return false;
6717 }
6718
6719 let bn1 = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
6720 let bn2 = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
6721 let bn = new Bn(0);
6722
6723 switch (opCodeNum) {
6724 case OpCode.OP_ADD:
6725 bn = bn1.add(bn2);
6726 break;
6727
6728 case OpCode.OP_SUB:
6729 bn = bn1.sub(bn2);
6730 break;
6731
6732 case OpCode.OP_MUL:
6733 bn = bn1.mul(bn2);
6734 break;
6735
6736 case OpCode.OP_DIV:
6737 if (bn2 == 0) {
6738 this.errStr = "SCRIPT_ERR_DIV_BY_ZERO";
6739 return false;
6740 }
6741
6742 bn = bn1.div(bn2);
6743 break;
6744
6745 case OpCode.OP_MOD:
6746 if (bn2 == 0) {
6747 this.errStr = "SCRIPT_ERR_DIV_BY_ZERO";
6748 return false;
6749 }
6750
6751 bn = bn1.mod(bn2);
6752 break;
6753
6754 case OpCode.OP_BOOLAND:
6755 bn = new Bn((bn1.neq(0) && bn2.neq(0)) + 0);
6756 break;
6757
6758 case OpCode.OP_BOOLOR:
6759 bn = new Bn((bn1.neq(0) || bn2.neq(0)) + 0);
6760 break;
6761
6762 case OpCode.OP_NUMEQUAL:
6763 bn = new Bn(bn1.eq(bn2) + 0);
6764 break;
6765
6766 case OpCode.OP_NUMEQUALVERIFY:
6767 bn = new Bn(bn1.eq(bn2) + 0);
6768 break;
6769
6770 case OpCode.OP_NUMNOTEQUAL:
6771 bn = new Bn(bn1.neq(bn2) + 0);
6772 break;
6773
6774 case OpCode.OP_LESSTHAN:
6775 bn = new Bn(bn1.lt(bn2) + 0);
6776 break;
6777
6778 case OpCode.OP_GREATERTHAN:
6779 bn = new Bn(bn1.gt(bn2) + 0);
6780 break;
6781
6782 case OpCode.OP_LESSTHANOREQUAL:
6783 bn = new Bn(bn1.leq(bn2) + 0);
6784 break;
6785
6786 case OpCode.OP_GREATERTHANOREQUAL:
6787 bn = new Bn(bn1.geq(bn2) + 0);
6788 break;
6789
6790 case OpCode.OP_MIN:
6791 bn = bn1.lt(bn2) ? bn1 : bn2;
6792 break;
6793
6794 case OpCode.OP_MAX:
6795 bn = bn1.gt(bn2) ? bn1 : bn2;
6796 break;
6797 }
6798
6799 this.stack.pop();
6800 this.stack.pop();
6801 this.stack.push(bn.toScriptNumBuffer());
6802
6803 if (opCodeNum === OpCode.OP_NUMEQUALVERIFY) {
6804 if (Interp.castToBool(this.stack[this.stack.length - 1])) {
6805 this.stack.pop();
6806 } else {
6807 this.errStr = 'SCRIPT_ERR_NUMEQUALVERIFY';
6808 return false;
6809 }
6810 }
6811 }
6812 break;
6813
6814 case OpCode.OP_WITHIN:
6815 {
6816 if (this.stack.length < 3) {
6817 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6818 return false;
6819 }
6820
6821 let bn1 = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - 3], fRequireMinimal);
6822 let bn2 = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
6823 let bn3 = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
6824 let fValue = bn2.leq(bn1) && bn1.lt(bn3);
6825 this.stack.pop();
6826 this.stack.pop();
6827 this.stack.pop();
6828 this.stack.push(fValue ? Interp.true : Interp.false);
6829 }
6830 break;
6831
6832 case OpCode.OP_RIPEMD160:
6833 case OpCode.OP_SHA1:
6834 case OpCode.OP_SHA256:
6835 case OpCode.OP_HASH160:
6836 case OpCode.OP_HASH256:
6837 {
6838 if (this.stack.length < 1) {
6839 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6840 return false;
6841 }
6842
6843 let _buf18 = this.stack[this.stack.length - 1];
6844 let bufHash;
6845
6846 if (opCodeNum === OpCode.OP_RIPEMD160) {
6847 bufHash = Hash.ripemd160(_buf18);
6848 } else if (opCodeNum === OpCode.OP_SHA1) {
6849 bufHash = Hash.sha1(_buf18);
6850 } else if (opCodeNum === OpCode.OP_SHA256) {
6851 bufHash = Hash.sha256(_buf18);
6852 } else if (opCodeNum === OpCode.OP_HASH160) {
6853 bufHash = Hash.sha256Ripemd160(_buf18);
6854 } else if (opCodeNum === OpCode.OP_HASH256) {
6855 bufHash = Hash.sha256Sha256(_buf18);
6856 }
6857
6858 this.stack.pop();
6859 this.stack.push(bufHash);
6860 }
6861 break;
6862
6863 case OpCode.OP_CODESEPARATOR:
6864 this.pBeginCodeHash = this.pc;
6865 break;
6866
6867 case OpCode.OP_CHECKSIG:
6868 case OpCode.OP_CHECKSIGVERIFY:
6869 {
6870 if (this.stack.length < 2) {
6871 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6872 return false;
6873 }
6874
6875 let bufSig = this.stack[this.stack.length - 2];
6876 let bufPubKey = this.stack[this.stack.length - 1];
6877 let subScript = new Script().fromObject({
6878 chunks: this.script.chunks.slice(this.pBeginCodeHash)
6879 });
6880 let nHashType = bufSig.length > 0 ? bufSig.readUInt8(bufSig.length - 1) : 0;
6881
6882 if (nHashType & Sig.SIGHASH_FORKID) {
6883 if (!(this.flags & Interp.SCRIPT_ENABLE_SIGHASH_FORKID)) {
6884 this.errStr = 'SCRIPT_ERR_ILLEGAL_FORKID';
6885 return false;
6886 }
6887 } else {
6888 subScript.findAndDelete(new Script().writeBuffer(bufSig));
6889 }
6890
6891 if (!this.checkSigEncoding(bufSig) || !this.checkPubKeyEncoding(bufPubKey)) {
6892 return false;
6893 }
6894
6895 let fSuccess;
6896
6897 try {
6898 let sig = new Sig().fromTxFormat(bufSig);
6899 let pubKey = new PubKey().fromBuffer(bufPubKey, false);
6900 fSuccess = this.tx.verify(sig, pubKey, this.nIn, subScript, Boolean(this.flags & Interp.SCRIPT_VERIFY_LOW_S), this.valueBn, this.flags);
6901 } catch (e) {
6902 fSuccess = false;
6903 }
6904
6905 this.stack.pop();
6906 this.stack.pop();
6907 this.stack.push(fSuccess ? Interp.true : Interp.false);
6908
6909 if (opCodeNum === OpCode.OP_CHECKSIGVERIFY) {
6910 if (fSuccess) {
6911 this.stack.pop();
6912 } else {
6913 this.errStr = 'SCRIPT_ERR_CHECKSIGVERIFY';
6914 return false;
6915 }
6916 }
6917 }
6918 break;
6919
6920 case OpCode.OP_CHECKMULTISIG:
6921 case OpCode.OP_CHECKMULTISIGVERIFY:
6922 {
6923 let i = 1;
6924
6925 if (this.stack.length < i) {
6926 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6927 return false;
6928 }
6929
6930 let nKeysCount = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber();
6931
6932 if (nKeysCount < 0 || nKeysCount > 20) {
6933 this.errStr = 'SCRIPT_ERR_PUBKEY_COUNT';
6934 return false;
6935 }
6936
6937 this.nOpCount += nKeysCount;
6938
6939 if (this.nOpCount > 201) {
6940 this.errStr = 'SCRIPT_ERR_OP_COUNT';
6941 return false;
6942 }
6943
6944 let ikey = ++i;
6945 i += nKeysCount;
6946
6947 if (this.stack.length < i) {
6948 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6949 return false;
6950 }
6951
6952 let nSigsCount = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - i], fRequireMinimal).toNumber();
6953
6954 if (nSigsCount < 0 || nSigsCount > nKeysCount) {
6955 this.errStr = 'SCRIPT_ERR_SIG_COUNT';
6956 return false;
6957 }
6958
6959 let isig = ++i;
6960 i += nSigsCount;
6961
6962 if (this.stack.length < i) {
6963 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
6964 return false;
6965 }
6966
6967 let subScript = new Script().fromObject({
6968 chunks: this.script.chunks.slice(this.pBeginCodeHash)
6969 });
6970
6971 for (let k = 0; k < nSigsCount; k++) {
6972 let bufSig = this.stack[this.stack.length - isig - k];
6973 let nHashType = bufSig.length > 0 ? bufSig.readUInt8(bufSig.length - 1) : 0;
6974
6975 if (nHashType & Sig.SIGHASH_FORKID) {
6976 if (!(this.flags & Interp.SCRIPT_ENABLE_SIGHASH_FORKID)) {
6977 this.errStr = 'SCRIPT_ERR_ILLEGAL_FORKID';
6978 return false;
6979 }
6980 } else {
6981 subScript.findAndDelete(new Script().writeBuffer(bufSig));
6982 }
6983 }
6984
6985 let fSuccess = true;
6986
6987 while (fSuccess && nSigsCount > 0) {
6988 let bufSig = this.stack[this.stack.length - isig];
6989 let bufPubKey = this.stack[this.stack.length - ikey];
6990
6991 if (!this.checkSigEncoding(bufSig) || !this.checkPubKeyEncoding(bufPubKey)) {
6992 return false;
6993 }
6994
6995 let fOk;
6996
6997 try {
6998 let sig = new Sig().fromTxFormat(bufSig);
6999 let pubKey = new PubKey().fromBuffer(bufPubKey, false);
7000 fOk = this.tx.verify(sig, pubKey, this.nIn, subScript, Boolean(this.flags & Interp.SCRIPT_VERIFY_LOW_S), this.valueBn, this.flags);
7001 } catch (e) {
7002 fOk = false;
7003 }
7004
7005 if (fOk) {
7006 isig++;
7007 nSigsCount--;
7008 }
7009
7010 ikey++;
7011 nKeysCount--;
7012
7013 if (nSigsCount > nKeysCount) {
7014 fSuccess = false;
7015 }
7016 }
7017
7018 while (i-- > 1) {
7019 this.stack.pop();
7020 }
7021
7022 if (this.stack.length < 1) {
7023 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
7024 return false;
7025 }
7026
7027 if (this.flags & Interp.SCRIPT_VERIFY_NULLDUMMY && this.stack[this.stack.length - 1].length) {
7028 this.errStr = 'SCRIPT_ERR_SIG_NULLDUMMY';
7029 return false;
7030 }
7031
7032 this.stack.pop();
7033 this.stack.push(fSuccess ? Interp.true : Interp.false);
7034
7035 if (opCodeNum === OpCode.OP_CHECKMULTISIGVERIFY) {
7036 if (fSuccess) {
7037 this.stack.pop();
7038 } else {
7039 this.errStr = 'SCRIPT_ERR_CHECKMULTISIGVERIFY';
7040 return false;
7041 }
7042 }
7043 }
7044 break;
7045
7046 case OpCode.OP_CAT:
7047 if (this.stack.length < 2) {
7048 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
7049 return false;
7050 }
7051
7052 let vch1 = this.stack[this.stack.length - 2];
7053 let vch2 = this.stack[this.stack.length - 1];
7054 this.stack[this.stack.length - 2] = Buffer.concat([vch1, vch2]);
7055 this.stack.pop();
7056 break;
7057
7058 case OpCode.OP_SPLIT:
7059 if (this.stack.length < 2) {
7060 this.errStr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
7061 return false;
7062 }
7063
7064 let data = this.stack[this.stack.length - 2];
7065 let position = new Bn().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
7066
7067 if (position.lt(0) || position.gt(data.length)) {
7068 this.errStr = 'SCRIPT_ERR_INVALID_SPLIT_RANGE';
7069 return false;
7070 }
7071
7072 let n1 = data.slice(0, position);
7073 let n2 = data.slice(position);
7074 this.stack.pop();
7075 this.stack.pop();
7076 this.stack.push(n1);
7077 this.stack.push(n2);
7078 break;
7079
7080 default:
7081 this.errStr = 'SCRIPT_ERR_BAD_OPCODE';
7082 return false;
7083 }
7084 }
7085
7086 return true;
7087 }
7088
7089 verify(scriptSig, scriptPubKey, tx, nIn, flags, valueBn) {
7090 let results = this.results(scriptSig, scriptPubKey, tx, nIn, flags, valueBn);
7091
7092 for (let success of results) {
7093 if (!success) {
7094 return false;
7095 }
7096 }
7097
7098 return true;
7099 }
7100
7101 *results(scriptSig, scriptPubKey, tx, nIn, flags, valueBn) {
7102 let stackCopy;
7103 this.fromObject({
7104 script: scriptSig,
7105 tx: tx,
7106 nIn: nIn,
7107 flags: flags,
7108 valueBn: valueBn
7109 });
7110
7111 if ((flags & Interp.SCRIPT_VERIFY_SIGPUSHONLY) !== 0 && !scriptSig.isPushOnly()) {
7112 this.errStr = this.errStr || 'SCRIPT_ERR_SIG_PUSHONLY';
7113 yield false;
7114 }
7115
7116 yield* this.eval();
7117
7118 if (flags & Interp.SCRIPT_VERIFY_P2SH) {
7119 stackCopy = this.stack.slice();
7120 }
7121
7122 let stack = this.stack;
7123 this.initialize();
7124 this.fromObject({
7125 script: scriptPubKey,
7126 stack: stack,
7127 tx: tx,
7128 nIn: nIn,
7129 flags: flags,
7130 valueBn: valueBn
7131 });
7132 yield* this.eval();
7133
7134 if (this.stack.length === 0) {
7135 this.errStr = this.errStr || 'SCRIPT_ERR_EVAL_FALSE';
7136 yield false;
7137 }
7138
7139 let buf = this.stack[this.stack.length - 1];
7140
7141 if (!Interp.castToBool(buf)) {
7142 this.errStr = this.errStr || 'SCRIPT_ERR_EVAL_FALSE';
7143 yield false;
7144 }
7145
7146 if (flags & Interp.SCRIPT_VERIFY_P2SH && scriptPubKey.isScriptHashOut()) {
7147 if (!scriptSig.isPushOnly()) {
7148 this.errStr = this.errStr || 'SCRIPT_ERR_SIG_PUSHONLY';
7149 yield false;
7150 }
7151
7152 let tmp = stack;
7153 stack = stackCopy;
7154 stackCopy = tmp;
7155
7156 if (stack.length === 0) {
7157 throw new Error('internal error - stack copy empty');
7158 }
7159
7160 let pubKeySerialized = stack[stack.length - 1];
7161 let scriptPubKey2 = new Script().fromBuffer(pubKeySerialized);
7162 stack.pop();
7163 this.initialize();
7164 this.fromObject({
7165 script: scriptPubKey2,
7166 stack: stack,
7167 tx: tx,
7168 nIn: nIn,
7169 flags: flags,
7170 valueBn: valueBn
7171 });
7172 yield* this.eval();
7173
7174 if (stack.length === 0) {
7175 this.errStr = this.errStr || 'SCRIPT_ERR_EVAL_FALSE';
7176 yield false;
7177 }
7178
7179 if (!Interp.castToBool(stack[stack.length - 1])) {
7180 this.errStr = this.errStr || 'SCRIPT_ERR_EVAL_FALSE';
7181 yield false;
7182 } else {
7183 yield true;
7184 }
7185 }
7186
7187 if ((flags & Interp.SCRIPT_VERIFY_CLEANSTACK) !== 0) {
7188 if (!(flags & Interp.SCRIPT_VERIFY_P2SH)) {
7189 throw new Error('cannot use CLEANSTACK without P2SH');
7190 }
7191
7192 if (stack.length !== 1) {
7193 this.errStr = this.errStr || 'SCRIPT_ERR_CLEANSTACK';
7194 yield false;
7195 }
7196 }
7197
7198 yield true;
7199 }
7200
7201 getDebugObject() {
7202 let pc = this.pc - 1;
7203 return {
7204 errStr: this.errStr,
7205 scriptStr: this.script ? this.script.toString() : 'no script found',
7206 pc: pc,
7207 stack: this.stack.map(buf => buf.toString('hex')),
7208 altStack: this.altStack.map(buf => buf.toString('hex')),
7209 opCodeStr: this.script ? OpCode.fromNumber(this.script.chunks[pc].opCodeNum).toString() : 'no script found'
7210 };
7211 }
7212
7213 getDebugString() {
7214 return JSON.stringify(this.getDebugObject(), null, 2);
7215 }
7216
7217}
7218
7219Interp.true = Buffer.from([1]);
7220Interp.false = Buffer.from([]);
7221Interp.MAX_SCRIPT_ELEMENT_SIZE = 520;
7222Interp.LOCKTIME_THRESHOLD = 500000000;
7223Interp.SCRIPT_VERIFY_NONE = 0;
7224Interp.SCRIPT_VERIFY_P2SH = 1 << 0;
7225Interp.SCRIPT_VERIFY_STRICTENC = 1 << 1;
7226Interp.SCRIPT_VERIFY_DERSIG = 1 << 2;
7227Interp.SCRIPT_VERIFY_LOW_S = 1 << 3;
7228Interp.SCRIPT_VERIFY_NULLDUMMY = 1 << 4;
7229Interp.SCRIPT_VERIFY_SIGPUSHONLY = 1 << 5;
7230Interp.SCRIPT_VERIFY_MINIMALDATA = 1 << 6;
7231Interp.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = 1 << 7;
7232Interp.SCRIPT_VERIFY_CLEANSTACK = 1 << 8;
7233Interp.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY = 1 << 9;
7234Interp.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = 1 << 10;
7235Interp.SCRIPT_ENABLE_SIGHASH_FORKID = 1 << 16;
7236Interp.defaultFlags = Interp.SCRIPT_VERIFY_P2SH | Interp.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY;
7237
7238class SigOperations extends Struct {
7239 constructor(map = new Map()) {
7240 super({
7241 map
7242 });
7243 }
7244
7245 toJSON() {
7246 const json = {};
7247 this.map.forEach((arr, label) => {
7248 json[label] = arr.map(obj => ({
7249 nScriptChunk: obj.nScriptChunk,
7250 type: obj.type,
7251 addressStr: obj.addressStr,
7252 nHashType: obj.nHashType,
7253 log: obj.log
7254 }));
7255 });
7256 return json;
7257 }
7258
7259 fromJSON(json) {
7260 Object.keys(json).forEach(label => {
7261 this.map.set(label, json[label].map(obj => ({
7262 nScriptChunk: obj.nScriptChunk,
7263 type: obj.type,
7264 addressStr: obj.addressStr,
7265 nHashType: obj.nHashType,
7266 log: obj.log
7267 })));
7268 });
7269 return this;
7270 }
7271
7272 setOne(txHashBuf, txOutNum, nScriptChunk, type = 'sig', addressStr, nHashType = Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID) {
7273 const label = txHashBuf.toString('hex') + ':' + txOutNum;
7274 const obj = {
7275 nScriptChunk,
7276 type,
7277 addressStr,
7278 nHashType
7279 };
7280 this.map.set(label, [obj]);
7281 return this;
7282 }
7283
7284 setMany(txHashBuf, txOutNum, arr) {
7285 const label = txHashBuf.toString('hex') + ':' + txOutNum;
7286 arr = arr.map(obj => ({
7287 type: obj.type || 'sig',
7288 nHashType: obj.nHashType || Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID,
7289 ...obj
7290 }));
7291 this.map.set(label, arr);
7292 return this;
7293 }
7294
7295 addOne(txHashBuf, txOutNum, nScriptChunk, type = 'sig', addressStr, nHashType = Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID) {
7296 const arr = this.get(txHashBuf, txOutNum) || [];
7297 arr.push({
7298 nScriptChunk,
7299 type,
7300 addressStr,
7301 nHashType
7302 });
7303 this.setMany(txHashBuf, txOutNum, arr);
7304 return this;
7305 }
7306
7307 get(txHashBuf, txOutNum) {
7308 const label = txHashBuf.toString('hex') + ':' + txOutNum;
7309 return this.map.get(label);
7310 }
7311
7312}
7313
7314class TxOutMap extends Struct {
7315 constructor(map = new Map()) {
7316 super({
7317 map
7318 });
7319 }
7320
7321 toJSON() {
7322 const json = {};
7323 this.map.forEach((txOut, label) => {
7324 json[label] = txOut.toHex();
7325 });
7326 return json;
7327 }
7328
7329 fromJSON(json) {
7330 Object.keys(json).forEach(label => {
7331 this.map.set(label, TxOut.fromHex(json[label]));
7332 });
7333 return this;
7334 }
7335
7336 set(txHashBuf, txOutNum, txOut) {
7337 const label = txHashBuf.toString('hex') + ':' + txOutNum;
7338 this.map.set(label, txOut);
7339 return this;
7340 }
7341
7342 get(txHashBuf, txOutNum) {
7343 const label = txHashBuf.toString('hex') + ':' + txOutNum;
7344 return this.map.get(label);
7345 }
7346
7347 setTx(tx) {
7348 const txhashhex = tx.hash().toString('hex');
7349 tx.txOuts.forEach((txOut, index) => {
7350 const label = txhashhex + ':' + index;
7351 this.map.set(label, txOut);
7352 });
7353 return this;
7354 }
7355
7356}
7357
7358const Constants$1 = Constants.Default.TxBuilder;
7359
7360class TxBuilder extends Struct {
7361 constructor(tx = new Tx(), txIns = [], txOuts = [], uTxOutMap = new TxOutMap(), sigOperations = new SigOperations(), changeScript, changeAmountBn, feeAmountBn, feePerKbNum = Constants$1.feePerKbNum, nLockTime = 0, versionBytesNum = 1, sigsPerInput = 1, dust = Constants$1.dust, dustChangeToFees = false, hashCache = new HashCache()) {
7362 super({
7363 tx,
7364 txIns,
7365 txOuts,
7366 uTxOutMap,
7367 sigOperations,
7368 changeScript,
7369 changeAmountBn,
7370 feeAmountBn,
7371 feePerKbNum,
7372 nLockTime,
7373 versionBytesNum,
7374 sigsPerInput,
7375 dust,
7376 dustChangeToFees,
7377 hashCache
7378 });
7379 }
7380
7381 toJSON() {
7382 const json = {};
7383 json.tx = this.tx.toHex();
7384 json.txIns = this.txIns.map(txIn => txIn.toHex());
7385 json.txOuts = this.txOuts.map(txOut => txOut.toHex());
7386 json.uTxOutMap = this.uTxOutMap.toJSON();
7387 json.sigOperations = this.sigOperations.toJSON();
7388 json.changeScript = this.changeScript ? this.changeScript.toHex() : undefined;
7389 json.changeAmountBn = this.changeAmountBn ? this.changeAmountBn.toNumber() : undefined;
7390 json.feeAmountBn = this.feeAmountBn ? this.feeAmountBn.toNumber() : undefined;
7391 json.feePerKbNum = this.feePerKbNum;
7392 json.sigsPerInput = this.sigsPerInput;
7393 json.dust = this.dust;
7394 json.dustChangeToFees = this.dustChangeToFees;
7395 json.hashCache = this.hashCache.toJSON();
7396 return json;
7397 }
7398
7399 fromJSON(json) {
7400 this.tx = new Tx().fromHex(json.tx);
7401 this.txIns = json.txIns.map(txIn => TxIn.fromHex(txIn));
7402 this.txOuts = json.txOuts.map(txOut => TxOut.fromHex(txOut));
7403 this.uTxOutMap = new TxOutMap().fromJSON(json.uTxOutMap);
7404 this.sigOperations = new SigOperations().fromJSON(json.sigOperations);
7405 this.changeScript = json.changeScript ? new Script().fromHex(json.changeScript) : undefined;
7406 this.changeAmountBn = json.changeAmountBn ? new Bn(json.changeAmountBn) : undefined;
7407 this.feeAmountBn = json.feeAmountBn ? new Bn(json.feeAmountBn) : undefined;
7408 this.feePerKbNum = json.feePerKbNum || this.feePerKbNum;
7409 this.sigsPerInput = json.sigsPerInput || this.sigsPerInput;
7410 this.dust = json.dust || this.dust;
7411 this.dustChangeToFees = json.dustChangeToFees || this.dustChangeToFees;
7412 this.hashCache = HashCache.fromJSON(json.hashCache);
7413 return this;
7414 }
7415
7416 setFeePerKbNum(feePerKbNum) {
7417 if (typeof feePerKbNum !== 'number' || feePerKbNum <= 0) {
7418 throw new Error('cannot set a fee of zero or less');
7419 }
7420
7421 this.feePerKbNum = feePerKbNum;
7422 return this;
7423 }
7424
7425 setChangeAddress(changeAddress) {
7426 this.changeScript = changeAddress.toTxOutScript();
7427 return this;
7428 }
7429
7430 setChangeScript(changeScript) {
7431 this.changeScript = changeScript;
7432 return this;
7433 }
7434
7435 setNLocktime(nLockTime) {
7436 this.nLockTime = nLockTime;
7437 return this;
7438 }
7439
7440 setVersion(versionBytesNum) {
7441 this.versionBytesNum = versionBytesNum;
7442 return this;
7443 }
7444
7445 setDust(dust = Constants$1.dust) {
7446 this.dust = dust;
7447 return this;
7448 }
7449
7450 sendDustChangeToFees(dustChangeToFees = false) {
7451 this.dustChangeToFees = dustChangeToFees;
7452 return this;
7453 }
7454
7455 importPartiallySignedTx(tx, uTxOutMap = this.uTxOutMap, sigOperations = this.sigOperations) {
7456 this.tx = tx;
7457 this.uTxOutMap = uTxOutMap;
7458 this.sigOperations = sigOperations;
7459 return this;
7460 }
7461
7462 inputFromScript(txHashBuf, txOutNum, txOut, script, nSequence) {
7463 if (!Buffer.isBuffer(txHashBuf) || !(typeof txOutNum === 'number') || !(txOut instanceof TxOut) || !(script instanceof Script)) {
7464 throw new Error('invalid one of: txHashBuf, txOutNum, txOut, script');
7465 }
7466
7467 this.txIns.push(TxIn.fromProperties(txHashBuf, txOutNum, script, nSequence));
7468 this.uTxOutMap.set(txHashBuf, txOutNum, txOut);
7469 return this;
7470 }
7471
7472 addSigOperation(txHashBuf, txOutNum, nScriptChunk, type, addressStr, nHashType) {
7473 this.sigOperations.addOne(txHashBuf, txOutNum, nScriptChunk, type, addressStr, nHashType);
7474 return this;
7475 }
7476
7477 inputFromPubKeyHash(txHashBuf, txOutNum, txOut, pubKey, nSequence, nHashType) {
7478 if (!Buffer.isBuffer(txHashBuf) || typeof txOutNum !== 'number' || !(txOut instanceof TxOut)) {
7479 throw new Error('invalid one of: txHashBuf, txOutNum, txOut');
7480 }
7481
7482 this.txIns.push(new TxIn().fromObject({
7483 nSequence
7484 }).fromPubKeyHashTxOut(txHashBuf, txOutNum, txOut, pubKey));
7485 this.uTxOutMap.set(txHashBuf, txOutNum, txOut);
7486 const addressStr = Address.fromTxOutScript(txOut.script).toString();
7487 this.addSigOperation(txHashBuf, txOutNum, 0, 'sig', addressStr, nHashType);
7488 this.addSigOperation(txHashBuf, txOutNum, 1, 'pubKey', addressStr);
7489 return this;
7490 }
7491
7492 outputToAddress(valueBn, addr) {
7493 if (!(addr instanceof Address) || !(valueBn instanceof Bn)) {
7494 throw new Error('addr must be an Address, and valueBn must be a Bn');
7495 }
7496
7497 const script = new Script().fromPubKeyHash(addr.hashBuf);
7498 this.outputToScript(valueBn, script);
7499 return this;
7500 }
7501
7502 outputToScript(valueBn, script) {
7503 if (!(script instanceof Script) || !(valueBn instanceof Bn)) {
7504 throw new Error('script must be a Script, and valueBn must be a Bn');
7505 }
7506
7507 const txOut = TxOut.fromProperties(valueBn, script);
7508 this.txOuts.push(txOut);
7509 return this;
7510 }
7511
7512 buildOutputs() {
7513 let outAmountBn = new Bn(0);
7514 this.txOuts.forEach(txOut => {
7515 if (txOut.valueBn.lt(this.dust) && !txOut.script.isOpReturn() && !txOut.script.isSafeDataOut()) {
7516 throw new Error('cannot create output lesser than dust');
7517 }
7518
7519 outAmountBn = outAmountBn.add(txOut.valueBn);
7520 this.tx.addTxOut(txOut);
7521 });
7522 return outAmountBn;
7523 }
7524
7525 buildInputs(outAmountBn, extraInputsNum = 0) {
7526 let inAmountBn = new Bn(0);
7527
7528 for (const txIn of this.txIns) {
7529 const txOut = this.uTxOutMap.get(txIn.txHashBuf, txIn.txOutNum);
7530 inAmountBn = inAmountBn.add(txOut.valueBn);
7531 this.tx.addTxIn(txIn);
7532
7533 if (inAmountBn.geq(outAmountBn)) {
7534 if (extraInputsNum <= 0) {
7535 break;
7536 }
7537
7538 extraInputsNum--;
7539 }
7540 }
7541
7542 if (inAmountBn.lt(outAmountBn)) {
7543 throw new Error('not enough funds for outputs: inAmountBn ' + inAmountBn.toNumber() + ' outAmountBn ' + outAmountBn.toNumber());
7544 }
7545
7546 return inAmountBn;
7547 }
7548
7549 estimateSize() {
7550 const sigSize = 1 + 1 + 1 + 1 + 32 + 1 + 1 + 32 + 1 + 1;
7551 const pubKeySize = 1 + 1 + 33;
7552 let size = this.tx.toBuffer().length;
7553 this.tx.txIns.forEach(txIn => {
7554 const {
7555 txHashBuf,
7556 txOutNum
7557 } = txIn;
7558 const sigOperations = this.sigOperations.get(txHashBuf, txOutNum);
7559 sigOperations.forEach(obj => {
7560 const {
7561 nScriptChunk,
7562 type
7563 } = obj;
7564 const script = new Script([txIn.script.chunks[nScriptChunk]]);
7565 const scriptSize = script.toBuffer().length;
7566 size -= scriptSize;
7567
7568 if (type === 'sig') {
7569 size += sigSize;
7570 } else if (obj.type === 'pubKey') {
7571 size += pubKeySize;
7572 } else {
7573 throw new Error('unsupported sig operations type');
7574 }
7575 });
7576 });
7577 size = size + 1;
7578 return Math.round(size);
7579 }
7580
7581 estimateFee(extraFeeAmount = new Bn(0)) {
7582 const fee = Math.ceil(this.estimateSize() / 1000 * this.feePerKbNum);
7583 return new Bn(fee).add(extraFeeAmount);
7584 }
7585
7586 build(opts = {
7587 useAllInputs: false
7588 }) {
7589 let minFeeAmountBn;
7590
7591 if (this.txIns.length <= 0) {
7592 throw Error('tx-builder number of inputs must be greater than 0');
7593 }
7594
7595 if (!this.changeScript) {
7596 throw new Error('must specify change script to use build method');
7597 }
7598
7599 for (let extraInputsNum = opts.useAllInputs ? this.txIns.length - 1 : 0; extraInputsNum < this.txIns.length; extraInputsNum++) {
7600 this.tx = new Tx();
7601 const outAmountBn = this.buildOutputs();
7602 const changeTxOut = TxOut.fromProperties(new Bn(0), this.changeScript);
7603 this.tx.addTxOut(changeTxOut);
7604 let inAmountBn;
7605
7606 try {
7607 inAmountBn = this.buildInputs(outAmountBn, extraInputsNum);
7608 } catch (err) {
7609 if (err.message.includes('not enough funds for outputs')) {
7610 throw new Error('unable to gather enough inputs for outputs and fee');
7611 } else {
7612 throw err;
7613 }
7614 }
7615
7616 this.changeAmountBn = inAmountBn.sub(outAmountBn);
7617 changeTxOut.valueBn = this.changeAmountBn;
7618 minFeeAmountBn = this.estimateFee();
7619
7620 if (this.changeAmountBn.geq(minFeeAmountBn) && this.changeAmountBn.sub(minFeeAmountBn).gt(this.dust)) {
7621 break;
7622 }
7623 }
7624
7625 if (this.changeAmountBn.geq(minFeeAmountBn)) {
7626 this.feeAmountBn = minFeeAmountBn;
7627 this.changeAmountBn = this.changeAmountBn.sub(this.feeAmountBn);
7628 this.tx.txOuts[this.tx.txOuts.length - 1].valueBn = this.changeAmountBn;
7629
7630 if (this.changeAmountBn.lt(this.dust)) {
7631 if (this.dustChangeToFees) {
7632 this.tx.txOuts.pop();
7633 this.tx.txOutsVi = VarInt.fromNumber(this.tx.txOutsVi.toNumber() - 1);
7634 this.feeAmountBn = this.feeAmountBn.add(this.changeAmountBn);
7635 this.changeAmountBn = new Bn(0);
7636 } else {
7637 throw new Error('unable to create change amount greater than dust');
7638 }
7639 }
7640
7641 this.tx.nLockTime = this.nLockTime;
7642 this.tx.versionBytesNum = this.versionBytesNum;
7643
7644 if (this.tx.txOuts.length === 0) {
7645 throw new Error('outputs length is zero - unable to create any outputs greater than dust');
7646 }
7647
7648 return this;
7649 } else {
7650 throw new Error('unable to gather enough inputs for outputs and fee');
7651 }
7652 }
7653
7654 sort() {
7655 this.tx.sort();
7656 return this;
7657 }
7658
7659 static allSigsPresent(m, script) {
7660 let present = 0;
7661
7662 for (let i = 1; i < script.chunks.length - 1; i++) {
7663 if (script.chunks[i].buf) {
7664 present++;
7665 }
7666 }
7667
7668 return present === m;
7669 }
7670
7671 static removeBlankSigs(script) {
7672 script = new Script(script.chunks.slice());
7673
7674 for (let i = 1; i < script.chunks.length - 1; i++) {
7675 if (!script.chunks[i].buf) {
7676 script.chunks.splice(i, 1);
7677 }
7678 }
7679
7680 return script;
7681 }
7682
7683 fillSig(nIn, nScriptChunk, sig) {
7684 const txIn = this.tx.txIns[nIn];
7685 txIn.script.chunks[nScriptChunk] = new Script().writeBuffer(sig.toTxFormat()).chunks[0];
7686 txIn.scriptVi = VarInt.fromNumber(txIn.script.toBuffer().length);
7687 return this;
7688 }
7689
7690 getSig(keyPair, nHashType = Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID, nIn, subScript, flags = Tx.SCRIPT_ENABLE_SIGHASH_FORKID) {
7691 let valueBn;
7692
7693 if (nHashType & Sig.SIGHASH_FORKID && flags & Tx.SCRIPT_ENABLE_SIGHASH_FORKID) {
7694 const txHashBuf = this.tx.txIns[nIn].txHashBuf;
7695 const txOutNum = this.tx.txIns[nIn].txOutNum;
7696 const txOut = this.uTxOutMap.get(txHashBuf, txOutNum);
7697
7698 if (!txOut) {
7699 throw new Error('for SIGHASH_FORKID must provide UTXOs');
7700 }
7701
7702 valueBn = txOut.valueBn;
7703 }
7704
7705 return this.tx.sign(keyPair, nHashType, nIn, subScript, valueBn, flags, this.hashCache);
7706 }
7707
7708 asyncGetSig(keyPair, nHashType = Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID, nIn, subScript, flags = Tx.SCRIPT_ENABLE_SIGHASH_FORKID) {
7709 let valueBn;
7710
7711 if (nHashType & Sig.SIGHASH_FORKID && flags & Tx.SCRIPT_ENABLE_SIGHASH_FORKID) {
7712 const txHashBuf = this.tx.txIns[nIn].txHashBuf;
7713 const txOutNum = this.tx.txIns[nIn].txOutNum;
7714 const txOut = this.uTxOutMap.get(txHashBuf, txOutNum);
7715
7716 if (!txOut) {
7717 throw new Error('for SIGHASH_FORKID must provide UTXOs');
7718 }
7719
7720 valueBn = txOut.valueBn;
7721 }
7722
7723 return this.tx.asyncSign(keyPair, nHashType, nIn, subScript, valueBn, flags, this.hashCache);
7724 }
7725
7726 signTxIn(nIn, keyPair, txOut, nScriptChunk, nHashType = Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID, flags = Tx.SCRIPT_ENABLE_SIGHASH_FORKID) {
7727 const txIn = this.tx.txIns[nIn];
7728 const script = txIn.script;
7729
7730 if (nScriptChunk === undefined && script.isPubKeyHashIn()) {
7731 nScriptChunk = 0;
7732 }
7733
7734 if (nScriptChunk === undefined) {
7735 throw new Error('cannot sign unknown script type for input ' + nIn);
7736 }
7737
7738 const txHashBuf = txIn.txHashBuf;
7739 const txOutNum = txIn.txOutNum;
7740
7741 if (!txOut) {
7742 txOut = this.uTxOutMap.get(txHashBuf, txOutNum);
7743 }
7744
7745 const outScript = txOut.script;
7746 const subScript = outScript;
7747 const sig = this.getSig(keyPair, nHashType, nIn, subScript, flags, this.hashCache);
7748 this.fillSig(nIn, nScriptChunk, sig);
7749 return this;
7750 }
7751
7752 async asyncSignTxIn(nIn, keyPair, txOut, nScriptChunk, nHashType = Sig.SIGHASH_ALL | Sig.SIGHASH_FORKID, flags = Tx.SCRIPT_ENABLE_SIGHASH_FORKID) {
7753 const txIn = this.tx.txIns[nIn];
7754 const script = txIn.script;
7755
7756 if (nScriptChunk === undefined && script.isPubKeyHashIn()) {
7757 nScriptChunk = 0;
7758 }
7759
7760 if (nScriptChunk === undefined) {
7761 throw new Error('cannot sign unknown script type for input ' + nIn);
7762 }
7763
7764 const txHashBuf = txIn.txHashBuf;
7765 const txOutNum = txIn.txOutNum;
7766
7767 if (!txOut) {
7768 txOut = this.uTxOutMap.get(txHashBuf, txOutNum);
7769 }
7770
7771 const outScript = txOut.script;
7772 const subScript = outScript;
7773 const sig = await this.asyncGetSig(keyPair, nHashType, nIn, subScript, flags, this.hashCache);
7774 this.fillSig(nIn, nScriptChunk, sig);
7775 return this;
7776 }
7777
7778 signWithKeyPairs(keyPairs) {
7779 const addressStrMap = {};
7780
7781 for (const keyPair of keyPairs) {
7782 const addressStr = Address.fromPubKey(keyPair.pubKey).toString();
7783 addressStrMap[addressStr] = keyPair;
7784 }
7785
7786 for (const nIn in this.tx.txIns) {
7787 const txIn = this.tx.txIns[nIn];
7788 const arr = this.sigOperations.get(txIn.txHashBuf, txIn.txOutNum);
7789
7790 for (const obj of arr) {
7791 const {
7792 nScriptChunk,
7793 type,
7794 addressStr,
7795 nHashType
7796 } = obj;
7797 const keyPair = addressStrMap[addressStr];
7798
7799 if (!keyPair) {
7800 obj.log = `cannot find keyPair for addressStr ${addressStr}`;
7801 continue;
7802 }
7803
7804 const txOut = this.uTxOutMap.get(txIn.txHashBuf, txIn.txOutNum);
7805
7806 if (type === 'sig') {
7807 this.signTxIn(nIn, keyPair, txOut, nScriptChunk, nHashType);
7808 obj.log = 'successfully inserted signature';
7809 } else if (type === 'pubKey') {
7810 txIn.script.chunks[nScriptChunk] = new Script().writeBuffer(keyPair.pubKey.toBuffer()).chunks[0];
7811 txIn.setScript(txIn.script);
7812 obj.log = 'successfully inserted public key';
7813 } else {
7814 obj.log = `cannot perform operation of type ${type}`;
7815 continue;
7816 }
7817 }
7818 }
7819
7820 return this;
7821 }
7822
7823}
7824
7825class TxVerifier extends Struct {
7826 constructor(tx, txOutMap, errStr, interp) {
7827 super({
7828 tx,
7829 txOutMap,
7830 errStr,
7831 interp
7832 });
7833 }
7834
7835 verify(flags = Interp.SCRIPT_ENABLE_SIGHASH_FORKID) {
7836 return !this.checkStr() && !this.verifyStr(flags);
7837 }
7838
7839 async asyncVerify(flags) {
7840 const verifyStr = await this.asyncVerifyStr(flags);
7841 return !this.checkStr() && !verifyStr;
7842 }
7843
7844 static verify(tx, txOutMap, flags) {
7845 return new TxVerifier(tx, txOutMap).verify(flags);
7846 }
7847
7848 static asyncVerify(tx, txOutMap, flags) {
7849 return new TxVerifier(tx, txOutMap).asyncVerify(flags);
7850 }
7851
7852 checkStr() {
7853 if (this.tx.txIns.length === 0 || this.tx.txInsVi.toNumber() === 0) {
7854 this.errStr = 'transaction txIns empty';
7855 return this.errStr;
7856 }
7857
7858 if (this.tx.txOuts.length === 0 || this.tx.txOutsVi.toNumber() === 0) {
7859 this.errStr = 'transaction txOuts empty';
7860 return this.errStr;
7861 }
7862
7863 if (this.tx.toBuffer().length > Block.MAX_BLOCK_SIZE) {
7864 this.errStr = 'transaction over the maximum block size';
7865 return this.errStr;
7866 }
7867
7868 let valueoutbn = new Bn(0);
7869
7870 for (let i = 0; i < this.tx.txOuts.length; i++) {
7871 const txOut = this.tx.txOuts[i];
7872
7873 if (txOut.valueBn.lt(0)) {
7874 this.errStr = 'transaction txOut ' + i + ' negative';
7875 return this.errStr;
7876 }
7877
7878 if (txOut.valueBn.gt(Tx.MAX_MONEY)) {
7879 this.errStr = 'transaction txOut ' + i + ' greater than MAX_MONEY';
7880 return this.errStr;
7881 }
7882
7883 valueoutbn = valueoutbn.add(txOut.valueBn);
7884
7885 if (valueoutbn.gt(Tx.MAX_MONEY)) {
7886 this.errStr = 'transaction txOut ' + i + ' total output greater than MAX_MONEY';
7887 return this.errStr;
7888 }
7889 }
7890
7891 const txInmap = {};
7892
7893 for (let i = 0; i < this.tx.txIns.length; i++) {
7894 const txIn = this.tx.txIns[i];
7895 const inputid = txIn.txHashBuf.toString('hex') + ':' + txIn.txOutNum;
7896
7897 if (txInmap[inputid] !== undefined) {
7898 this.errStr = 'transaction input ' + i + ' duplicate input';
7899 return this.errStr;
7900 }
7901
7902 txInmap[inputid] = true;
7903 }
7904
7905 if (this.tx.isCoinbase()) {
7906 const buf = this.tx.txIns[0].script.toBuffer();
7907
7908 if (buf.length < 2 || buf.length > 100) {
7909 this.errStr = 'coinbase trasaction script size invalid';
7910 return this.errStr;
7911 }
7912 } else {
7913 for (let i = 0; i < this.tx.txIns.length; i++) {
7914 if (this.tx.txIns[i].hasNullInput()) {
7915 this.errStr = 'transaction input ' + i + ' has null input';
7916 return this.errStr;
7917 }
7918 }
7919 }
7920
7921 return false;
7922 }
7923
7924 verifyStr(flags) {
7925 for (let i = 0; i < this.tx.txIns.length; i++) {
7926 if (!this.verifyNIn(i, flags)) {
7927 this.errStr = 'input ' + i + ' failed script verify';
7928 return this.errStr;
7929 }
7930 }
7931
7932 return false;
7933 }
7934
7935 async asyncVerifyStr(flags) {
7936 for (let i = 0; i < this.tx.txIns.length; i++) {
7937 const verifyNIn = await this.asyncVerifyNIn(i, flags);
7938
7939 if (!verifyNIn) {
7940 this.errStr = 'input ' + i + ' failed script verify';
7941 return this.errStr;
7942 }
7943 }
7944
7945 return false;
7946 }
7947
7948 verifyNIn(nIn, flags) {
7949 const txIn = this.tx.txIns[nIn];
7950 const scriptSig = txIn.script;
7951 const txOut = this.txOutMap.get(txIn.txHashBuf, txIn.txOutNum);
7952
7953 if (!txOut) {
7954 console.log('output ' + txIn.txOutNum + ' not found');
7955 return false;
7956 }
7957
7958 const scriptPubKey = txOut.script;
7959 const valueBn = txOut.valueBn;
7960 this.interp = new Interp();
7961 const verified = this.interp.verify(scriptSig, scriptPubKey, this.tx, nIn, flags, valueBn);
7962 return verified;
7963 }
7964
7965 async asyncVerifyNIn(nIn, flags) {
7966 const txIn = this.tx.txIns[nIn];
7967 const scriptSig = txIn.script;
7968 const txOut = this.txOutMap.get(txIn.txHashBuf, txIn.txOutNum);
7969
7970 if (!txOut) {
7971 console.log('output ' + txIn.txOutNum + ' not found');
7972 return false;
7973 }
7974
7975 const scriptPubKey = txOut.script;
7976 const valueBn = txOut.valueBn;
7977 this.interp = new Interp();
7978 const workersResult = await Workers.asyncObjectMethod(this.interp, 'verify', [scriptSig, scriptPubKey, this.tx, nIn, flags, valueBn]);
7979 const verified = JSON.parse(workersResult.resbuf.toString());
7980 return verified;
7981 }
7982
7983 getDebugObject() {
7984 return {
7985 errStr: this.errStr,
7986 interpFailure: this.interp ? this.interp.getDebugObject() : undefined
7987 };
7988 }
7989
7990 getDebugString() {
7991 return JSON.stringify(this.getDebugObject(), null, 2);
7992 }
7993
7994}
7995
7996class Aes {}
7997
7998Aes.encrypt = function (messageBuf, keyBuf) {
7999 const key = Aes.buf2Words(keyBuf);
8000 const message = Aes.buf2Words(messageBuf);
8001 const a = new _Aes(key);
8002 const enc = a.encrypt(message);
8003 const encBuf = Aes.words2Buf(enc);
8004 return encBuf;
8005};
8006
8007Aes.decrypt = function (encBuf, keyBuf) {
8008 const enc = Aes.buf2Words(encBuf);
8009 const key = Aes.buf2Words(keyBuf);
8010 const a = new _Aes(key);
8011 const message = a.decrypt(enc);
8012 const messageBuf = Aes.words2Buf(message);
8013 return messageBuf;
8014};
8015
8016Aes.buf2Words = function (buf) {
8017 if (buf.length % 4) {
8018 throw new Error('buf length must be a multiple of 4');
8019 }
8020
8021 const words = [];
8022
8023 for (let i = 0; i < buf.length / 4; i++) {
8024 words.push(buf.readUInt32BE(i * 4));
8025 }
8026
8027 return words;
8028};
8029
8030Aes.words2Buf = function (words) {
8031 const buf = Buffer.alloc(words.length * 4);
8032
8033 for (let i = 0; i < words.length; i++) {
8034 buf.writeUInt32BE(words[i], i * 4);
8035 }
8036
8037 return buf;
8038};
8039
8040class Cbc {}
8041
8042Cbc.buf2BlocksBuf = function (buf, blockSize) {
8043 const bytesize = blockSize / 8;
8044 const blockBufs = [];
8045
8046 for (let i = 0; i <= buf.length / bytesize; i++) {
8047 let blockBuf = buf.slice(i * bytesize, i * bytesize + bytesize);
8048
8049 if (blockBuf.length < blockSize) {
8050 blockBuf = Cbc.pkcs7Pad(blockBuf, blockSize);
8051 }
8052
8053 blockBufs.push(blockBuf);
8054 }
8055
8056 return blockBufs;
8057};
8058
8059Cbc.blockBufs2Buf = function (blockBufs) {
8060 let last = blockBufs[blockBufs.length - 1];
8061 last = Cbc.pkcs7Unpad(last);
8062 blockBufs[blockBufs.length - 1] = last;
8063 const buf = Buffer.concat(blockBufs);
8064 return buf;
8065};
8066
8067Cbc.encrypt = function (messageBuf, ivBuf, blockCipher, cipherKeyBuf) {
8068 const blockSize = ivBuf.length * 8;
8069 const blockBufs = Cbc.buf2BlocksBuf(messageBuf, blockSize);
8070 const encBufs = Cbc.encryptBlocks(blockBufs, ivBuf, blockCipher, cipherKeyBuf);
8071 const encBuf = Buffer.concat(encBufs);
8072 return encBuf;
8073};
8074
8075Cbc.decrypt = function (encBuf, ivBuf, blockCipher, cipherKeyBuf) {
8076 const bytesize = ivBuf.length;
8077 const encBufs = [];
8078
8079 for (let i = 0; i < encBuf.length / bytesize; i++) {
8080 encBufs.push(encBuf.slice(i * bytesize, i * bytesize + bytesize));
8081 }
8082
8083 const blockBufs = Cbc.decryptBlocks(encBufs, ivBuf, blockCipher, cipherKeyBuf);
8084 const buf = Cbc.blockBufs2Buf(blockBufs);
8085 return buf;
8086};
8087
8088Cbc.encryptBlock = function (blockBuf, ivBuf, blockCipher, cipherKeyBuf) {
8089 const xorbuf = Cbc.xorBufs(blockBuf, ivBuf);
8090 const encBuf = blockCipher.encrypt(xorbuf, cipherKeyBuf);
8091 return encBuf;
8092};
8093
8094Cbc.decryptBlock = function (encBuf, ivBuf, blockCipher, cipherKeyBuf) {
8095 const xorbuf = blockCipher.decrypt(encBuf, cipherKeyBuf);
8096 const blockBuf = Cbc.xorBufs(xorbuf, ivBuf);
8097 return blockBuf;
8098};
8099
8100Cbc.encryptBlocks = function (blockBufs, ivBuf, blockCipher, cipherKeyBuf) {
8101 const encBufs = [];
8102
8103 for (let i = 0; i < blockBufs.length; i++) {
8104 const blockBuf = blockBufs[i];
8105 const encBuf = Cbc.encryptBlock(blockBuf, ivBuf, blockCipher, cipherKeyBuf);
8106 encBufs.push(encBuf);
8107 ivBuf = encBuf;
8108 }
8109
8110 return encBufs;
8111};
8112
8113Cbc.decryptBlocks = function (encBufs, ivBuf, blockCipher, cipherKeyBuf) {
8114 const blockBufs = [];
8115
8116 for (let i = 0; i < encBufs.length; i++) {
8117 const encBuf = encBufs[i];
8118 const blockBuf = Cbc.decryptBlock(encBuf, ivBuf, blockCipher, cipherKeyBuf);
8119 blockBufs.push(blockBuf);
8120 ivBuf = encBuf;
8121 }
8122
8123 return blockBufs;
8124};
8125
8126Cbc.pkcs7Pad = function (buf, blockSize) {
8127 const bytesize = blockSize / 8;
8128 const padbytesize = bytesize - buf.length;
8129 const pad = Buffer.alloc(padbytesize);
8130 pad.fill(padbytesize);
8131 const paddedbuf = Buffer.concat([buf, pad]);
8132 return paddedbuf;
8133};
8134
8135Cbc.pkcs7Unpad = function (paddedbuf) {
8136 const padlength = paddedbuf[paddedbuf.length - 1];
8137 const padbuf = paddedbuf.slice(paddedbuf.length - padlength, paddedbuf.length);
8138 const padbuf2 = Buffer.alloc(padlength);
8139 padbuf2.fill(padlength);
8140
8141 if (!cmp(padbuf, padbuf2)) {
8142 throw new Error('invalid padding');
8143 }
8144
8145 return paddedbuf.slice(0, paddedbuf.length - padlength);
8146};
8147
8148Cbc.xorBufs = function (buf1, buf2) {
8149 if (buf1.length !== buf2.length) {
8150 throw new Error('bufs must have the same length');
8151 }
8152
8153 const buf = Buffer.alloc(buf1.length);
8154
8155 for (let i = 0; i < buf1.length; i++) {
8156 buf[i] = buf1[i] ^ buf2[i];
8157 }
8158
8159 return buf;
8160};
8161
8162class Aescbc {}
8163
8164Aescbc.encrypt = function (messageBuf, cipherKeyBuf, ivBuf, concatIvBuf = true) {
8165 ivBuf = ivBuf || Random.getRandomBuffer(128 / 8);
8166 const ctBuf = Cbc.encrypt(messageBuf, ivBuf, Aes, cipherKeyBuf);
8167
8168 if (concatIvBuf) {
8169 return Buffer.concat([ivBuf, ctBuf]);
8170 } else {
8171 return ctBuf;
8172 }
8173};
8174
8175Aescbc.decrypt = function (encBuf, cipherKeyBuf, ivBuf = false) {
8176 if (!ivBuf) {
8177 const _ivBuf = encBuf.slice(0, 128 / 8);
8178
8179 const ctBuf = encBuf.slice(128 / 8);
8180 return Cbc.decrypt(ctBuf, _ivBuf, Aes, cipherKeyBuf);
8181 } else {
8182 const ctBuf = encBuf;
8183 return Cbc.decrypt(ctBuf, ivBuf, Aes, cipherKeyBuf);
8184 }
8185};
8186
8187class Ach {}
8188
8189Ach.encrypt = function (messageBuf, cipherKeyBuf, ivBuf) {
8190 const encBuf = Aescbc.encrypt(messageBuf, cipherKeyBuf, ivBuf);
8191 const hmacbuf = Hash.sha256Hmac(encBuf, cipherKeyBuf);
8192 return Buffer.concat([hmacbuf, encBuf]);
8193};
8194
8195Ach.asyncEncrypt = async function (messageBuf, cipherKeyBuf, ivBuf) {
8196 if (!ivBuf) {
8197 ivBuf = Random.getRandomBuffer(128 / 8);
8198 }
8199
8200 const args = [messageBuf, cipherKeyBuf, ivBuf];
8201 const workersResult = await Workers.asyncClassMethod(Ach, 'encrypt', args);
8202 return workersResult.resbuf;
8203};
8204
8205Ach.decrypt = function (encBuf, cipherKeyBuf) {
8206 if (encBuf.length < (256 + 128 + 128) / 8) {
8207 throw new Error('The encrypted data must be at least 256+128+128 bits, which is the length of the Hmac plus the iv plus the smallest encrypted data size');
8208 }
8209
8210 const hmacbuf = encBuf.slice(0, 256 / 8);
8211 encBuf = encBuf.slice(256 / 8, encBuf.length);
8212 const hmacbuf2 = Hash.sha256Hmac(encBuf, cipherKeyBuf);
8213
8214 if (!cmp(hmacbuf, hmacbuf2)) {
8215 throw new Error('Message authentication failed - Hmacs are not equivalent');
8216 }
8217
8218 return Aescbc.decrypt(encBuf, cipherKeyBuf);
8219};
8220
8221Ach.asyncDecrypt = async function (encBuf, cipherKeyBuf) {
8222 const args = [encBuf, cipherKeyBuf];
8223 const workersResult = await Workers.asyncClassMethod(Ach, 'decrypt', args);
8224 return workersResult.resbuf;
8225};
8226
8227class Ecies {}
8228
8229Ecies.ivkEkM = function (privKey, pubKey) {
8230 const r = privKey.bn;
8231 const KB = pubKey.point;
8232 const P = KB.mul(r);
8233 const S = new PubKey(P);
8234 const Sbuf = S.toBuffer();
8235 const hash = Hash.sha512(Sbuf);
8236 return {
8237 iv: hash.slice(0, 16),
8238 kE: hash.slice(16, 32),
8239 kM: hash.slice(32, 64)
8240 };
8241};
8242
8243Ecies.electrumEncrypt = function (messageBuf, toPubKey, fromKeyPair, noKey = false) {
8244 if (!Buffer.isBuffer(messageBuf)) {
8245 throw new Error('messageBuf must be a buffer');
8246 }
8247
8248 let Rbuf;
8249
8250 if (fromKeyPair === null) {
8251 fromKeyPair = KeyPair.fromRandom();
8252 }
8253
8254 if (!noKey) {
8255 Rbuf = fromKeyPair.pubKey.toDer(true);
8256 }
8257
8258 const {
8259 iv,
8260 kE,
8261 kM
8262 } = Ecies.ivkEkM(fromKeyPair.privKey, toPubKey);
8263 const ciphertext = Aescbc.encrypt(messageBuf, kE, iv, false);
8264 const BIE1 = Buffer.from('BIE1');
8265 let encBuf;
8266
8267 if (Rbuf) {
8268 encBuf = Buffer.concat([BIE1, Rbuf, ciphertext]);
8269 } else {
8270 encBuf = Buffer.concat([BIE1, ciphertext]);
8271 }
8272
8273 const hmac = Hash.sha256Hmac(encBuf, kM);
8274 return Buffer.concat([encBuf, hmac]);
8275};
8276
8277Ecies.electrumDecrypt = function (encBuf, toPrivKey, fromPubKey = null) {
8278 if (!Buffer.isBuffer(encBuf)) {
8279 throw new Error('encBuf must be a buffer');
8280 }
8281
8282 const tagLength = 32;
8283 const magic = encBuf.slice(0, 4);
8284
8285 if (!magic.equals(Buffer.from('BIE1'))) {
8286 throw new Error('Invalid Magic');
8287 }
8288
8289 let offset = 4;
8290
8291 if (fromPubKey === null) {
8292 const pub = encBuf.slice(4, 37);
8293 fromPubKey = PubKey.fromDer(pub);
8294 offset = 37;
8295 }
8296
8297 const {
8298 iv,
8299 kE,
8300 kM
8301 } = Ecies.ivkEkM(toPrivKey, fromPubKey);
8302 const ciphertext = encBuf.slice(offset, encBuf.length - tagLength);
8303 const hmac = encBuf.slice(encBuf.length - tagLength, encBuf.length);
8304 const hmac2 = Hash.sha256Hmac(encBuf.slice(0, encBuf.length - tagLength), kM);
8305
8306 if (!hmac.equals(hmac2)) {
8307 throw new Error('Invalid checksum');
8308 }
8309
8310 return Aescbc.decrypt(ciphertext, kE, iv);
8311};
8312
8313Ecies.bitcoreEncrypt = function (messageBuf, toPubKey, fromKeyPair, ivBuf) {
8314 if (!fromKeyPair) {
8315 fromKeyPair = KeyPair.fromRandom();
8316 }
8317
8318 const r = fromKeyPair.privKey.bn;
8319 const RPubKey = fromKeyPair.pubKey;
8320 const RBuf = RPubKey.toDer(true);
8321 const KB = toPubKey.point;
8322 const P = KB.mul(r);
8323 const S = P.getX();
8324 const Sbuf = S.toBuffer({
8325 size: 32
8326 });
8327 const kEkM = Hash.sha512(Sbuf);
8328 const kE = kEkM.slice(0, 32);
8329 const kM = kEkM.slice(32, 64);
8330 const c = Aescbc.encrypt(messageBuf, kE, ivBuf);
8331 const d = Hash.sha256Hmac(c, kM);
8332 const encBuf = Buffer.concat([RBuf, c, d]);
8333 return encBuf;
8334};
8335
8336Ecies.asyncBitcoreEncrypt = async function (messageBuf, toPubKey, fromKeyPair, ivBuf) {
8337 if (!fromKeyPair) {
8338 fromKeyPair = await KeyPair.asyncFromRandom();
8339 }
8340
8341 if (!ivBuf) {
8342 ivBuf = Random.getRandomBuffer(128 / 8);
8343 }
8344
8345 const args = [messageBuf, toPubKey, fromKeyPair, ivBuf];
8346 const workersResult = await Workers.asyncClassMethod(Ecies, 'bitcoreEncrypt', args);
8347 return workersResult.resbuf;
8348};
8349
8350Ecies.bitcoreDecrypt = function (encBuf, toPrivKey) {
8351 const kB = toPrivKey.bn;
8352 const fromPubKey = PubKey.fromDer(encBuf.slice(0, 33));
8353 const R = fromPubKey.point;
8354 const P = R.mul(kB);
8355
8356 if (P.eq(new Point())) {
8357 throw new Error('P equals 0');
8358 }
8359
8360 const S = P.getX();
8361 const Sbuf = S.toBuffer({
8362 size: 32
8363 });
8364 const kEkM = Hash.sha512(Sbuf);
8365 const kE = kEkM.slice(0, 32);
8366 const kM = kEkM.slice(32, 64);
8367 const c = encBuf.slice(33, encBuf.length - 32);
8368 const d = encBuf.slice(encBuf.length - 32, encBuf.length);
8369 const d2 = Hash.sha256Hmac(c, kM);
8370
8371 if (!cmp(d, d2)) {
8372 throw new Error('Invalid checksum');
8373 }
8374
8375 const messageBuf = Aescbc.decrypt(c, kE);
8376 return messageBuf;
8377};
8378
8379Ecies.asyncBitcoreDecrypt = async function (encBuf, toPrivKey) {
8380 const args = [encBuf, toPrivKey];
8381 const workersResult = await Workers.asyncClassMethod(Ecies, 'bitcoreDecrypt', args);
8382 return workersResult.resbuf;
8383};
8384
8385const deps = {
8386 aes: _Aes,
8387 bnjs: _Bn,
8388 bs58,
8389 elliptic,
8390 hashjs,
8391 pbkdf2
8392};
8393
8394export { Ach, Address, Aes, Aescbc, Base58, Base58Check, Bip32, Bip39, Block, BlockHeader, Bn, Br, Bsm, Bw, Cbc, Constants, Ecdsa, Ecies, Hash, Interp, KeyPair, OpCode, Point, PrivKey, PubKey, Random, Script, Sig, Struct, Tx, TxBuilder, TxIn, TxOut, TxOutMap, TxVerifier, VarInt, Workers, WorkersResult, cmp, deps, wordList as en, getConstants, wordList$1 as jp, version };
8395//# sourceMappingURL=bsv.modern.js.map