@opcat-labs/opcat 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/.mocharc.yaml +3 -0
  2. package/index.d.ts +1541 -0
  3. package/index.js +74 -0
  4. package/lib/address.js +478 -0
  5. package/lib/block/block.js +277 -0
  6. package/lib/block/blockheader.js +295 -0
  7. package/lib/block/index.js +4 -0
  8. package/lib/block/merkleblock.js +323 -0
  9. package/lib/bn.js +3423 -0
  10. package/lib/crypto/bn.js +278 -0
  11. package/lib/crypto/ecdsa.js +339 -0
  12. package/lib/crypto/hash.browser.js +171 -0
  13. package/lib/crypto/hash.js +2 -0
  14. package/lib/crypto/hash.node.js +171 -0
  15. package/lib/crypto/point.js +221 -0
  16. package/lib/crypto/random.browser.js +28 -0
  17. package/lib/crypto/random.js +2 -0
  18. package/lib/crypto/random.node.js +11 -0
  19. package/lib/crypto/signature.js +325 -0
  20. package/lib/encoding/base58.js +111 -0
  21. package/lib/encoding/base58check.js +121 -0
  22. package/lib/encoding/bufferreader.js +212 -0
  23. package/lib/encoding/bufferwriter.js +140 -0
  24. package/lib/encoding/decode-asm.js +24 -0
  25. package/lib/encoding/decode-hex.js +32 -0
  26. package/lib/encoding/decode-script-chunks.js +43 -0
  27. package/lib/encoding/encode-hex.js +284 -0
  28. package/lib/encoding/is-hex.js +7 -0
  29. package/lib/encoding/varint.js +75 -0
  30. package/lib/errors/index.js +54 -0
  31. package/lib/errors/spec.js +314 -0
  32. package/lib/hash-cache.js +50 -0
  33. package/lib/hdprivatekey.js +678 -0
  34. package/lib/hdpublickey.js +525 -0
  35. package/lib/message/message.js +191 -0
  36. package/lib/mnemonic/mnemonic.js +303 -0
  37. package/lib/mnemonic/pbkdf2.browser.js +68 -0
  38. package/lib/mnemonic/pbkdf2.js +2 -0
  39. package/lib/mnemonic/pbkdf2.node.js +68 -0
  40. package/lib/mnemonic/words/chinese.js +2054 -0
  41. package/lib/mnemonic/words/english.js +2054 -0
  42. package/lib/mnemonic/words/french.js +2054 -0
  43. package/lib/mnemonic/words/index.js +8 -0
  44. package/lib/mnemonic/words/italian.js +2054 -0
  45. package/lib/mnemonic/words/japanese.js +2054 -0
  46. package/lib/mnemonic/words/spanish.js +2054 -0
  47. package/lib/networks.js +379 -0
  48. package/lib/opcode.js +255 -0
  49. package/lib/privatekey.js +374 -0
  50. package/lib/publickey.js +386 -0
  51. package/lib/script/index.js +5 -0
  52. package/lib/script/interpreter.js +1834 -0
  53. package/lib/script/script.js +1074 -0
  54. package/lib/script/stack.js +109 -0
  55. package/lib/script/write-i32-le.js +17 -0
  56. package/lib/script/write-push-data.js +35 -0
  57. package/lib/script/write-u16-le.js +12 -0
  58. package/lib/script/write-u32-le.js +16 -0
  59. package/lib/script/write-u64-le.js +24 -0
  60. package/lib/script/write-u8-le.js +8 -0
  61. package/lib/script/write-varint.js +46 -0
  62. package/lib/transaction/index.js +7 -0
  63. package/lib/transaction/input/index.js +5 -0
  64. package/lib/transaction/input/input.js +354 -0
  65. package/lib/transaction/input/multisig.js +242 -0
  66. package/lib/transaction/input/publickey.js +100 -0
  67. package/lib/transaction/input/publickeyhash.js +118 -0
  68. package/lib/transaction/output.js +231 -0
  69. package/lib/transaction/sighash.js +167 -0
  70. package/lib/transaction/signature.js +97 -0
  71. package/lib/transaction/transaction.js +1639 -0
  72. package/lib/transaction/unspentoutput.js +113 -0
  73. package/lib/util/_.js +47 -0
  74. package/lib/util/js.js +90 -0
  75. package/lib/util/preconditions.js +33 -0
  76. package/package.json +26 -0
  77. package/test/address.js +509 -0
  78. package/test/block/block.js +251 -0
  79. package/test/block/blockheader.js +275 -0
  80. package/test/block/merklebloack.js +211 -0
  81. package/test/crypto/bn.js +177 -0
  82. package/test/crypto/ecdsa.js +391 -0
  83. package/test/crypto/hash.browser.js +135 -0
  84. package/test/crypto/hash.js +136 -0
  85. package/test/crypto/point.js +224 -0
  86. package/test/crypto/random.js +32 -0
  87. package/test/crypto/signature.js +409 -0
  88. package/test/data/bip69.json +215 -0
  89. package/test/data/bitcoind/base58_keys_invalid.json +52 -0
  90. package/test/data/bitcoind/base58_keys_valid.json +335 -0
  91. package/test/data/bitcoind/blocks.json +22 -0
  92. package/test/data/bitcoind/script_tests.json +3822 -0
  93. package/test/data/bitcoind/sig_canonical.json +7 -0
  94. package/test/data/bitcoind/sig_noncanonical.json +36 -0
  95. package/test/data/bitcoind/tx_invalid.json +445 -0
  96. package/test/data/bitcoind/tx_valid.json +44 -0
  97. package/test/data/blk86756-testnet.dat +0 -0
  98. package/test/data/blk86756-testnet.js +14 -0
  99. package/test/data/blk86756-testnet.json +684 -0
  100. package/test/data/block.hex +1 -0
  101. package/test/data/ecdsa.json +230 -0
  102. package/test/data/merkleblocks.js +488 -0
  103. package/test/data/messages.json +22 -0
  104. package/test/data/sighash.json +12 -0
  105. package/test/data/tx_creation.json +95 -0
  106. package/test/encoding/base58.js +131 -0
  107. package/test/encoding/base58check.js +136 -0
  108. package/test/encoding/bufferreader.js +337 -0
  109. package/test/encoding/bufferwriter.js +172 -0
  110. package/test/encoding/varint.js +104 -0
  111. package/test/hashCache.js +67 -0
  112. package/test/hdkeys.js +445 -0
  113. package/test/hdprivatekey.js +332 -0
  114. package/test/hdpublickey.js +304 -0
  115. package/test/index.js +16 -0
  116. package/test/message/message.js +204 -0
  117. package/test/mnemonic/data/fixtures.json +300 -0
  118. package/test/mnemonic/mnemonic.js +259 -0
  119. package/test/mnemonic/mocha.opts +1 -0
  120. package/test/mnemonic/pbkdf2.test.js +59 -0
  121. package/test/networks.js +159 -0
  122. package/test/opcode.js +161 -0
  123. package/test/privatekey.js +439 -0
  124. package/test/publickey.js +554 -0
  125. package/test/script/interpreter.js +734 -0
  126. package/test/script/script.js +1437 -0
  127. package/test/transaction/deserialize.js +34 -0
  128. package/test/transaction/input/input.js +90 -0
  129. package/test/transaction/input/multisig.js +90 -0
  130. package/test/transaction/input/publickey.js +68 -0
  131. package/test/transaction/input/publickeyhash.js +51 -0
  132. package/test/transaction/output.js +185 -0
  133. package/test/transaction/sighash.js +65 -0
  134. package/test/transaction/signature.js +114 -0
  135. package/test/transaction/transaction.js +1109 -0
  136. package/test/transaction/unspentoutput.js +110 -0
  137. package/test/util/js.js +76 -0
  138. package/test/util/preconditions.js +79 -0
@@ -0,0 +1,34 @@
1
+ 'use strict';
2
+
3
+ var Transaction = require('../../lib/transaction');
4
+
5
+ var vectorsValid = require('../data/bitcoind/tx_valid.json');
6
+ var vectorsInvalid = require('../data/bitcoind/tx_invalid.json');
7
+
8
+ describe('Transaction deserialization', function () {
9
+ describe('valid transaction test case', function () {
10
+ var index = 0;
11
+ vectorsValid.forEach(function (vector) {
12
+ it('vector #' + index, function () {
13
+ if (vector.length > 1) {
14
+ var hexa = vector[1];
15
+ Transaction(hexa).serialize(true).should.equal(hexa);
16
+ index++;
17
+ }
18
+ });
19
+ });
20
+ });
21
+ describe('invalid transaction test case', function () {
22
+ // TODO:
23
+ // var index = 0;
24
+ // vectorsInvalid.forEach(function (vector) {
25
+ // it('invalid vector #' + index, function () {
26
+ // if (vector.length > 1) {
27
+ // var hexa = vector[1];
28
+ // Transaction(hexa).serialize(true).should.equal(hexa);
29
+ // index++;
30
+ // }
31
+ // });
32
+ // });
33
+ });
34
+ });
@@ -0,0 +1,90 @@
1
+ 'use strict';
2
+
3
+ var should = require('chai').should();
4
+ var expect = require('chai').expect;
5
+
6
+ var opcat = require('../../..');
7
+ var PrivateKey = opcat.PrivateKey;
8
+ var Address = opcat.Address;
9
+ var Script = opcat.Script;
10
+ var Networks = opcat.Networks;
11
+ var Input = opcat.Transaction.Input;
12
+
13
+ describe('Transaction.Input', function () {
14
+ var privateKey = new PrivateKey('KwF9LjRraetZuEjR8VqEq539z137LW5anYDUnVK11vM3mNMHTWb4');
15
+ var publicKey = privateKey.publicKey;
16
+ var address = new Address(publicKey, Networks.livenet);
17
+ var output = {
18
+ address: '33zbk2aSZYdNbRsMPPt6jgy6Kq1kQreqeb',
19
+ prevTxId: '66e64ef8a3b384164b78453fa8c8194de9a473ba14f89485a0e433699daec140',
20
+ outputIndex: 0,
21
+ script: new Script(address),
22
+ satoshis: 1000000,
23
+ };
24
+ var coinbase = {
25
+ prevTxId: '0000000000000000000000000000000000000000000000000000000000000000',
26
+ outputIndex: 0xffffffff,
27
+ script: new Script(),
28
+ satoshis: 1000000,
29
+ };
30
+
31
+ var coinbaseJSON = JSON.stringify({
32
+ prevTxId: '0000000000000000000000000000000000000000000000000000000000000000',
33
+ outputIndex: 4294967295,
34
+ script: '',
35
+ });
36
+
37
+ it('has abstract methods: "getSignatures", "isFullySigned", "addSignature", "clearSignatures"', function () {
38
+ // var input = new Input(output)
39
+ // _.each(['getSignatures', 'isFullySigned', 'addSignature', 'clearSignatures'], function (method) {
40
+ // expect(function () {
41
+ // return input[method]()
42
+ // }).to.throw(errors.AbstractMethodInvoked)
43
+ // })
44
+ });
45
+ it('detects coinbase transactions', function () {
46
+ new Input(output).isNull().should.equal(false);
47
+ var ci = new Input(coinbase);
48
+ ci.isNull().should.equal(true);
49
+ });
50
+
51
+ describe('instantiation', function () {
52
+ it('works without new', function () {
53
+ var input = Input();
54
+ should.exist(input);
55
+ });
56
+ it('fails with no script info', function () {
57
+ expect(function () {
58
+ var input = new Input({});
59
+ input.toString();
60
+ }).to.throw('Invalid params: require prevTxId and outputIndex.');
61
+ });
62
+ it('fromObject should work', function () {
63
+ var jsonData = JSON.parse(coinbaseJSON);
64
+ var input = Input.fromObject(jsonData);
65
+ should.exist(input);
66
+ input.prevTxId.toString('hex').should.equal(jsonData.prevTxId);
67
+ input.outputIndex.should.equal(jsonData.outputIndex);
68
+ });
69
+ it('fromObject should work', function () {
70
+ var input = Input.fromObject(JSON.parse(coinbaseJSON));
71
+ var obj = input.toObject();
72
+ Input.fromObject(obj).should.deep.equal(input);
73
+ obj.script = 42;
74
+ Input.fromObject.bind(null, obj).should.throw('Invalid argument type: script');
75
+ });
76
+ });
77
+
78
+ it('_estimateSize returns correct size', function () {
79
+ var input = new Input(output);
80
+ input._estimateSize().should.equal(66);
81
+ });
82
+
83
+ it('defaults isFinal correctly', function () {
84
+ new Input(output).isFinal().should.equal(true);
85
+ });
86
+
87
+ it('handles isFinal when sequence number is set to non default value', function () {
88
+ new Input({ ...output, sequenceNumber: 0 }).isFinal().should.equal(false);
89
+ });
90
+ });
@@ -0,0 +1,90 @@
1
+ 'use strict';
2
+
3
+ var should = require('chai').should();
4
+ var _ = require('../../../lib/util/_');
5
+
6
+ var opcat = require('../../..');
7
+ var Transaction = opcat.Transaction;
8
+ var PrivateKey = opcat.PrivateKey;
9
+ var Script = opcat.Script;
10
+ var MultiSigInput = opcat.Transaction.Input.MultiSig;
11
+
12
+ describe('MultiSigInput', function () {
13
+ var privateKey1 = new PrivateKey('KwF9LjRraetZuEjR8VqEq539z137LW5anYDUnVK11vM3mNMHTWb4');
14
+ var privateKey2 = new PrivateKey('L4PqnaPTCkYhAqH3YQmefjxQP6zRcF4EJbdGqR8v6adtG9XSsadY');
15
+ var privateKey3 = new PrivateKey('L4CTX79zFeksZTyyoFuPQAySfmP7fL3R41gWKTuepuN7hxuNuJwV');
16
+ var public1 = privateKey1.publicKey;
17
+ var public2 = privateKey2.publicKey;
18
+ var public3 = privateKey3.publicKey;
19
+ var output = {
20
+ txId: '66e64ef8a3b384164b78453fa8c8194de9a473ba14f89485a0e433699daec140',
21
+ outputIndex: 0,
22
+ script: new Script(
23
+ '5221025c95ec627038e85b5688a9b3d84d28c5ebe66e8c8d697d498e20fe96e3b1ab1d2102cdddfc974d41a62f1f80081deee70592feb7d6e6cf6739d6592edbe7946720e72103c95924e02c240b5545089c69c6432447412b58be43fd671918bd184a5009834353ae',
24
+ ),
25
+ satoshis: 1000000,
26
+ };
27
+
28
+ it('can parse list of signature buffers, from TX signed with key 1 and 2', function () {
29
+ var transaction = new Transaction(
30
+ '010000000140c1ae9d6933e4a08594f814ba73a4e94d19c8a83f45784b1684b3a3f84ee66600000000920047304402207031af27ed2b2440f11b803e0c311c257f5b69b94d1b231428d7157085d7f6c20220132dbdebaa417c2f54790bcdcc3730bd1b943fe9aa71e504b13be674111eecd301483045022100f6f1d3c135ac3ff8a81614a56142cf5aa68efde447955373980f8fc73068f3bb0220497f40851cc930a7783159fde902108ad3d936879413e448b7fcb7803930663d01ffffffff0140420f000000000017a91419438da7d16709643be5abd8df62ca4034a489a7870000000000',
31
+ );
32
+
33
+ var inputObj = transaction.inputs[0].toObject();
34
+ inputObj.output = output;
35
+ transaction.inputs[0] = new Transaction.Input(inputObj);
36
+
37
+ inputObj.signatures = MultiSigInput.normalizeSignatures(
38
+ transaction,
39
+ transaction.inputs[0],
40
+ 0,
41
+ transaction.inputs[0].script.chunks.slice(1).map(function (s) {
42
+ return s.buf;
43
+ }),
44
+ [public1, public2, public3],
45
+ );
46
+
47
+ transaction.inputs[0] = new MultiSigInput(inputObj, [public1, public2, public3], 2);
48
+
49
+ transaction.inputs[0].signatures[0].publicKey.should.deep.equal(public1);
50
+ transaction.inputs[0].signatures[1].publicKey.should.deep.equal(public2);
51
+ should.equal(transaction.inputs[0].signatures[2], undefined);
52
+ transaction.inputs[0]
53
+ .isValidSignature(transaction, transaction.inputs[0].signatures[0])
54
+ .should.equal(true);
55
+ transaction.inputs[0]
56
+ .isValidSignature(transaction, transaction.inputs[0].signatures[1])
57
+ .should.equal(true);
58
+ });
59
+ it('can parse list of signature buffers, from TX signed with key 3 and 1', function () {
60
+ var transaction = new Transaction(
61
+ '010000000140c1ae9d6933e4a08594f814ba73a4e94d19c8a83f45784b1684b3a3f84ee66600000000910047304402207031af27ed2b2440f11b803e0c311c257f5b69b94d1b231428d7157085d7f6c20220132dbdebaa417c2f54790bcdcc3730bd1b943fe9aa71e504b13be674111eecd301473044022059e3652eb43cb42a65f633dd6ecd1014350a164f89cb44104f926b93affbe09f02206bdf93eddf0c2fadd9ea1b9ab273f90e15a03e821fe5de87e457d1940b569dc001ffffffff0140420f000000000017a91419438da7d16709643be5abd8df62ca4034a489a7870000000000',
62
+ );
63
+
64
+ var inputObj = transaction.inputs[0].toObject();
65
+ inputObj.output = output;
66
+ transaction.inputs[0] = new Transaction.Input(inputObj);
67
+
68
+ inputObj.signatures = MultiSigInput.normalizeSignatures(
69
+ transaction,
70
+ transaction.inputs[0],
71
+ 0,
72
+ transaction.inputs[0].script.chunks.slice(1).map(function (s) {
73
+ return s.buf;
74
+ }),
75
+ [public1, public2, public3],
76
+ );
77
+
78
+ transaction.inputs[0] = new MultiSigInput(inputObj, [public1, public2, public3], 2);
79
+
80
+ transaction.inputs[0].signatures[0].publicKey.should.deep.equal(public1);
81
+ should.equal(transaction.inputs[0].signatures[1], undefined);
82
+ transaction.inputs[0].signatures[2].publicKey.should.deep.equal(public3);
83
+ transaction.inputs[0]
84
+ .isValidSignature(transaction, transaction.inputs[0].signatures[0])
85
+ .should.equal(true);
86
+ transaction.inputs[0]
87
+ .isValidSignature(transaction, transaction.inputs[0].signatures[2])
88
+ .should.equal(true);
89
+ });
90
+ });
@@ -0,0 +1,68 @@
1
+ 'use strict';
2
+
3
+ var opcat = require('../../..');
4
+ var Transaction = opcat.Transaction;
5
+ var PrivateKey = opcat.PrivateKey;
6
+
7
+ describe('PublicKeyInput', function () {
8
+ var utxo = {
9
+ txid: '7f3b688cb224ed83e12d9454145c26ac913687086a0a62f2ae0bc10934a4030f',
10
+ vout: 0,
11
+ address: 'n4McBrSkw42eYGX5YMACGpkGUJKL3jVSbo',
12
+ scriptPubKey: '2103c9594cb2ebfebcb0cfd29eacd40ba012606a197beef76f0269ed8c101e56ceddac',
13
+ amount: 50,
14
+ confirmations: 104,
15
+ spendable: true,
16
+ };
17
+ var privateKey = PrivateKey.fromWIF('cQ7tSSQDEwaxg9usnnP1Aztqvm9nCQVfNWz9kU2rdocDjknF2vd6');
18
+ var address = privateKey.toAddress();
19
+ utxo.address.should.equal(address.toString());
20
+
21
+ var destKey = new PrivateKey();
22
+
23
+ it('will correctly sign a publickey out transaction', function () {
24
+ var tx = new Transaction();
25
+ tx.from(utxo);
26
+ tx.to(destKey.toAddress(), 10000);
27
+ tx.sign(privateKey);
28
+ tx.inputs[0].script.toBuffer().length.should.be.above(0);
29
+ });
30
+
31
+ it('count can count missing signatures', function () {
32
+ var tx = new Transaction();
33
+ tx.from(utxo);
34
+ tx.to(destKey.toAddress(), 10000);
35
+ var input = tx.inputs[0];
36
+ input.isFullySigned().should.equal(false);
37
+ tx.sign(privateKey);
38
+ input.isFullySigned().should.equal(true);
39
+ });
40
+
41
+ it("it's size can be estimated", function () {
42
+ var tx = new Transaction();
43
+ tx.from(utxo);
44
+ tx.to(destKey.toAddress(), 10000);
45
+ var input = tx.inputs[0];
46
+ input._estimateSize().should.equal(114);
47
+ });
48
+
49
+ it("it's signature can be removed", function () {
50
+ var tx = new Transaction();
51
+ tx.from(utxo);
52
+ tx.to(destKey.toAddress(), 10000);
53
+ var input = tx.inputs[0];
54
+ tx.sign(privateKey);
55
+ input.isFullySigned().should.equal(true);
56
+ input.clearSignatures();
57
+ input.isFullySigned().should.equal(false);
58
+ });
59
+
60
+ it('returns an empty array if private key mismatches', function () {
61
+ var tx = new Transaction();
62
+ tx.from(utxo);
63
+ tx.to(destKey.toAddress(), 10000);
64
+ var input = tx.inputs[0];
65
+ var signatures = input.getSignatures(tx, new PrivateKey(), 0);
66
+ signatures.length.should.equal(0);
67
+ });
68
+ });
@@ -0,0 +1,51 @@
1
+ 'use strict';
2
+
3
+ require('chai').should();
4
+
5
+ var opcat = require('../../..');
6
+ var Transaction = opcat.Transaction;
7
+ var PrivateKey = opcat.PrivateKey;
8
+ var Address = opcat.Address;
9
+ var Script = opcat.Script;
10
+ var Networks = opcat.Networks;
11
+
12
+ describe('PublicKeyHashInput', function () {
13
+ var privateKey = new PrivateKey('KwF9LjRraetZuEjR8VqEq539z137LW5anYDUnVK11vM3mNMHTWb4');
14
+ var publicKey = privateKey.publicKey;
15
+ var address = new Address(publicKey, Networks.livenet);
16
+
17
+ var output = {
18
+ address: address.toString(),
19
+ txId: '66e64ef8a3b384164b78453fa8c8194de9a473ba14f89485a0e433699daec140',
20
+ outputIndex: 0,
21
+ script: new Script(address),
22
+ satoshis: 1000000,
23
+ };
24
+ it('can count missing signatures', function () {
25
+ var transaction = new Transaction().from(output).to(address, 1000000);
26
+ var input = transaction.inputs[0];
27
+
28
+ input.isFullySigned().should.equal(false);
29
+ transaction.sign(privateKey);
30
+ input.isFullySigned().should.equal(true);
31
+ });
32
+ it("it's size can be estimated", function () {
33
+ var transaction = new Transaction().from(output).to(address, 1000000);
34
+ var input = transaction.inputs[0];
35
+ input._estimateSize().should.equal(180);
36
+ });
37
+ it("it's signature can be removed", function () {
38
+ var transaction = new Transaction().from(output).to(address, 1000000);
39
+ var input = transaction.inputs[0];
40
+
41
+ transaction.sign(privateKey);
42
+ input.clearSignatures();
43
+ input.isFullySigned().should.equal(false);
44
+ });
45
+ it('returns an empty array if private key mismatches', function () {
46
+ var transaction = new Transaction().from(output).to(address, 1000000);
47
+ var input = transaction.inputs[0];
48
+ var signatures = input.getSignatures(transaction, new PrivateKey(), 0);
49
+ signatures.length.should.equal(0);
50
+ });
51
+ });
@@ -0,0 +1,185 @@
1
+ 'use strict';
2
+
3
+ var should = require('chai').should();
4
+
5
+ var opcat = require('../..');
6
+ var BN = opcat.crypto.BN;
7
+ var BufferWriter = opcat.encoding.BufferWriter;
8
+ var BufferReader = opcat.encoding.BufferReader;
9
+ var Output = opcat.Transaction.Output;
10
+ var Script = opcat.Script;
11
+
12
+ describe('Output', function () {
13
+ var output = new Output({
14
+ satoshis: 0,
15
+ script: Script.empty(),
16
+ });
17
+
18
+ it('throws error with unrecognized argument', function () {
19
+ (function () {
20
+ new Output(12345);
21
+ }).should.throw(TypeError);
22
+ });
23
+
24
+ it('can be assigned a satoshi amount in big number', function () {
25
+ var newOutput = new Output({
26
+ satoshis: new BN(100),
27
+ script: Script.empty(),
28
+ });
29
+ newOutput.satoshis.should.equal(100);
30
+ });
31
+
32
+ it('can be assigned a satoshi amount with a string', function () {
33
+ var newOutput = new Output({
34
+ satoshis: '100',
35
+ script: Script.empty(),
36
+ });
37
+ newOutput.satoshis.should.equal(100);
38
+ });
39
+
40
+ describe('will error if output is not a positive integer', function () {
41
+ it('-100', function () {
42
+ (function () {
43
+ new Output({
44
+ satoshis: -100,
45
+ script: Script.empty(),
46
+ });
47
+ }).should.throw('Output satoshis is not a natural number');
48
+ });
49
+
50
+ it('1.1', function () {
51
+ (function () {
52
+ new Output({
53
+ satoshis: 1.1,
54
+ script: Script.empty(),
55
+ });
56
+ }).should.throw('Output satoshis is not a natural number');
57
+ });
58
+
59
+ it('NaN', function () {
60
+ (function () {
61
+ new Output({
62
+ satoshis: NaN,
63
+ script: Script.empty(),
64
+ });
65
+ }).should.throw('Output satoshis is not a natural number');
66
+ });
67
+
68
+ it('Infinity', function () {
69
+ (function () {
70
+ new Output({
71
+ satoshis: Infinity,
72
+ script: Script.empty(),
73
+ });
74
+ }).should.throw('Output satoshis is not a natural number');
75
+ });
76
+ });
77
+
78
+ var expectEqualOutputs = function (a, b) {
79
+ a.satoshis.should.equal(b.satoshis);
80
+ a.script.toString().should.equal(b.script.toString());
81
+ a.data.toString().should.equal(b.data.toString());
82
+ };
83
+
84
+ it('deserializes correctly a simple output', function () {
85
+ var writer = new BufferWriter();
86
+ output.toBufferWriter(false, writer);
87
+ var deserialized = Output.fromBufferReader(new BufferReader(writer.toBuffer()));
88
+ expectEqualOutputs(output, deserialized);
89
+ });
90
+
91
+ it('can instantiate from an object', function () {
92
+ var out = new Output(output.toObject());
93
+ should.exist(out);
94
+ });
95
+
96
+ it('can set a script from a buffer', function () {
97
+ var newOutput = new Output(output.toObject());
98
+ newOutput.setScript(Script().add(0).toBuffer());
99
+ newOutput.inspect().should.equal('<Output (0 sats) <Script: OP_0>>');
100
+ });
101
+
102
+ it('has a inspect property', function () {
103
+ output.inspect().should.equal('<Output (0 sats) <Script: >>');
104
+ });
105
+
106
+ var output2 = new Output({
107
+ satoshis: 1100000000,
108
+ script: new Script(
109
+ 'OP_2 33 0x038282263212c609d9ea2a6e3e172de238d8c39' +
110
+ 'cabd5ac1ca10646e23fd5f51508 33 0x038282263212c609d9ea2a6e3e172de23' +
111
+ '8d8c39cabd5ac1ca10646e23fd5f51508 OP_2 OP_CHECKMULTISIG OP_EQUAL',
112
+ ),
113
+ });
114
+
115
+ it('toBufferWriter', function () {
116
+ output2
117
+ .toBufferWriter(false)
118
+ .toBuffer()
119
+ .toString('hex')
120
+ .should.equal(
121
+ '00ab904100000000485221038282263212c609d9ea2a6e3e172de2' +
122
+ '38d8c39cabd5ac1ca10646e23fd5f5150821038282263212c609d9ea2a6e3e172d' +
123
+ 'e238d8c39cabd5ac1ca10646e23fd5f5150852ae8700',
124
+ );
125
+ });
126
+
127
+ it('roundtrips to/from object', function () {
128
+ var newOutput = new Output({
129
+ satoshis: 50,
130
+ script: new Script().add(0),
131
+ });
132
+ var otherOutput = new Output(newOutput.toObject());
133
+ expectEqualOutputs(newOutput, otherOutput);
134
+ });
135
+
136
+ it('toObject will handle an invalid (null) script', function () {
137
+ // block 000000000000000b7e48f88e86ceee3e97b4df7c139f5411d14735c1b3c36791 (livenet)
138
+ // transaction index 2
139
+ // txid ebc9fa1196a59e192352d76c0f6e73167046b9d37b8302b6bb6968dfd279b767
140
+ var transaction = opcat.Transaction();
141
+ transaction.fromString(
142
+ '01000000019ac03d5ae6a875d970128ef9086cef276a1919684a6988023cc7254691d97e6d010000006b4830450221009d41dc793ba24e65f571473d40b299b6459087cea1509f0d381740b1ac863cb6022039c425906fcaf51b2b84d8092569fb3213de43abaff2180e2a799d4fcb4dd0aa012102d5ede09a8ae667d0f855ef90325e27f6ce35bbe60a1e6e87af7f5b3c652140fdffffffff0801000000000000000101000100000000000000020201000100000000000000014c000100000000000000034c0201000100000000000000014d000100000000000000044dffff01000100000000000000014e000100000000000000064effffffff010000000000',
143
+ );
144
+ var obj = transaction.toObject();
145
+ obj.outputs[2].script.should.equal('4c');
146
+ obj.outputs[4].script.should.equal('4d');
147
+ obj.outputs[6].script.should.equal('4e');
148
+ });
149
+
150
+ it('#toObject roundtrip will handle an invalid (null) script', function () {
151
+ var invalidOutputScript = Buffer.from('0100000000000000014c00', 'hex');
152
+ var br = new opcat.encoding.BufferReader(invalidOutputScript);
153
+ var output = Output.fromBufferReader(br);
154
+ var output2 = new Output(output.toObject());
155
+ should.equal(output2.script.toString('hex'), output.script.toString('hex'));
156
+ should.equal(output2.script.toHex(), '4c');
157
+ should.equal(output2.data.toString('hex'), '');
158
+ });
159
+
160
+ it('inspect will work with an invalid (null) script', function () {
161
+ var invalidOutputScript = Buffer.from('0100000000000000014c00', 'hex');
162
+ var br = new opcat.encoding.BufferReader(invalidOutputScript);
163
+ var output = Output.fromBufferReader(br);
164
+ output.inspect().should.equal('<Output (1 sats) <Script: OP_PUSHDATA1>>');
165
+ });
166
+
167
+ it('roundtrips to/from JSON', function () {
168
+ var json = JSON.stringify(output2);
169
+ var o3 = new Output(JSON.parse(json));
170
+ JSON.stringify(o3).should.equal(json);
171
+ });
172
+
173
+ it('setScript fails with invalid input', function () {
174
+ var out = new Output(output2.toJSON());
175
+ out.setScript.bind(out, 45).should.throw('Invalid argument type: script');
176
+ });
177
+
178
+ it('sets script not null if it is an InvalidBuffer', function () {
179
+ var output = new Output({
180
+ satoshis: 1000,
181
+ script: Buffer.from('4c', 'hex'),
182
+ });
183
+ should.equal(output.script.toString(), 'OP_PUSHDATA1');
184
+ });
185
+ });
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ var buffer = require('buffer');
4
+
5
+ var chai = require('chai');
6
+ chai.should();
7
+ var opcat = require('../../');
8
+ var Script = opcat.Script;
9
+ var BN = opcat.crypto.BN;
10
+ var Transaction = opcat.Transaction;
11
+ var Signature = opcat.crypto.Signature;
12
+ var sighash = Transaction.sighash;
13
+
14
+ var vectorsSighash = require('../data/sighash.json');
15
+
16
+ describe('sighash', function () {
17
+ it('should be able to compute sighash for a coinbase tx', function () {
18
+ var txhex =
19
+ '02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff2e039b1e1304c0737c5b68747470733a2f2f6769746875622e636f6d2f62636578742f01000001c096020000000000ffffffff014a355009000000001976a91448b20e254c0677e760bab964aec16818d6b7134a88ac0000000000';
20
+ var tx = new Transaction(txhex);
21
+ tx.inputs[0].output = new Transaction.Output({
22
+ satoshis: 1,
23
+ script: Script.empty(),
24
+ data: Buffer.from('')
25
+ });
26
+ var sighash = Transaction.Sighash.sighash(tx, Signature.SIGHASH_ALL, 0);
27
+ sighash
28
+ .toString('hex')
29
+ .should.equal('09edc84f4bbf481368554aadb182f2944808cc26f294cbb67679641d135fc41c');
30
+ });
31
+
32
+ var zeroBN = BN.Zero;
33
+ vectorsSighash.forEach(function (vector, i) {
34
+ if (i === 0 || !vector[6]) {
35
+ // First element is just a row describing the next ones
36
+ return;
37
+ }
38
+ it('test vector from bitcoind #' + i + ' (' + vector[6].substring(0, 16) + ')', function () {
39
+ var txbuf = buffer.Buffer.from(vector[0], 'hex');
40
+ var satoshis = vector[1];
41
+ var scriptbuf = buffer.Buffer.from(vector[2], 'hex');
42
+ var script = Script(scriptbuf);
43
+ var data = vector[3];
44
+ var nin = vector[4];
45
+ var nhashtype = vector[5];
46
+ // var nhashtype = vector[3]>>>0;
47
+ var sighashbuf = buffer.Buffer.from(vector[6], 'hex');
48
+ var tx = new Transaction(txbuf);
49
+ tx.inputs[0].output = new Transaction.Output({
50
+ satoshis: satoshis,
51
+ script: script,
52
+ data: data
53
+ });
54
+
55
+ // make sure transacion to/from buffer is isomorphic
56
+ tx.uncheckedSerialize().should.equal(txbuf.toString('hex'));
57
+
58
+ // sighash ought to be correct
59
+ sighash
60
+ .sighash(tx, nhashtype, nin)
61
+ .toString('hex')
62
+ .should.equal(sighashbuf.toString('hex'));
63
+ });
64
+ });
65
+ });