Browse Source

(Tests) Modified JS from built TS

addTSTests
junderw 6 years ago
parent
commit
5581125077
No known key found for this signature in database GPG Key ID: B256185D3A971908
  1. 171
      test/address.js
  2. 328
      test/bitcoin.core.js
  3. 204
      test/block.js
  4. 65
      test/bufferutils.js
  5. 219
      test/classify.js
  6. 34
      test/crypto.js
  7. 370
      test/ecpair.js
  8. 1
      test/fixtures/address.json
  9. 31
      test/fixtures/core/README.md
  10. 24
      test/fixtures/core/base58_encode_decode.json
  11. 4
      test/fixtures/core/sig_noncanonical.json
  12. 903
      test/fixtures/core/tx_valid.json
  13. 4
      test/fixtures/embed.json
  14. 14
      test/fixtures/p2ms.json
  15. 10
      test/fixtures/p2pk.json
  16. 14
      test/fixtures/p2pkh.json
  17. 16
      test/fixtures/p2sh.json
  18. 14
      test/fixtures/p2wpkh.json
  19. 14
      test/fixtures/p2wsh.json
  20. 238
      test/integration/_regtest.js
  21. 155
      test/integration/addresses.js
  22. 153
      test/integration/bip32.js
  23. 40
      test/integration/blocks.js
  24. 250
      test/integration/cltv.js
  25. 150
      test/integration/csv.js
  26. 137
      test/integration/payments.js
  27. 472
      test/integration/transactions.js
  28. 120
      test/payments.js
  29. 241
      test/payments.utils.js
  30. 196
      test/script.js
  31. 37
      test/script_number.js
  32. 83
      test/script_signature.js
  33. 478
      test/transaction.js
  34. 888
      test/transaction_builder.js
  35. 61
      test/types.js

171
test/address.js

@ -1,134 +1,121 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const baddress = require('../src/address') const bitcoinjs = require("..");
const bscript = require('../src/script') const baddress = bitcoinjs.address;
const fixtures = require('./fixtures/address.json') const bscript = bitcoinjs.script;
const { describe, it } = require('mocha');
const assert = require('assert');
const fixtures = require('../ts_test/fixtures/address.json');
// @ts-ignore
const NETWORKS = Object.assign({ const NETWORKS = Object.assign({
litecoin: { litecoin: {
messagePrefix: '\x19Litecoin Signed Message:\n', messagePrefix: '\x19Litecoin Signed Message:\n',
bip32: { bip32: {
public: 0x019da462, public: 0x019da462,
private: 0x019d9cfe private: 0x019d9cfe,
}, },
pubKeyHash: 0x30, pubKeyHash: 0x30,
scriptHash: 0x32, scriptHash: 0x32,
wif: 0xb0 wif: 0xb0,
} },
}, require('../src/networks')) }, require('../src/networks'));
describe('address', () => { describe('address', () => {
describe('fromBase58Check', () => { describe('fromBase58Check', () => {
fixtures.standard.forEach(f => { fixtures.standard.forEach(f => {
if (!f.base58check) return if (!f.base58check)
return;
it('decodes ' + f.base58check, () => { it('decodes ' + f.base58check, () => {
const decode = baddress.fromBase58Check(f.base58check) const decode = baddress.fromBase58Check(f.base58check);
assert.strictEqual(decode.version, f.version);
assert.strictEqual(decode.version, f.version) assert.strictEqual(decode.hash.toString('hex'), f.hash);
assert.strictEqual(decode.hash.toString('hex'), f.hash) });
}) });
})
fixtures.invalid.fromBase58Check.forEach(f => { fixtures.invalid.fromBase58Check.forEach(f => {
it('throws on ' + f.exception, () => { it('throws on ' + f.exception, () => {
assert.throws(() => { assert.throws(() => {
baddress.fromBase58Check(f.address) baddress.fromBase58Check(f.address);
}, new RegExp(f.address + ' ' + f.exception)) }, new RegExp(f.address + ' ' + f.exception));
}) });
}) });
}) });
describe('fromBech32', () => { describe('fromBech32', () => {
fixtures.standard.forEach(f => { fixtures.standard.forEach(f => {
if (!f.bech32) return if (!f.bech32)
return;
it('decodes ' + f.bech32, () => { it('decodes ' + f.bech32, () => {
const actual = baddress.fromBech32(f.bech32) const actual = baddress.fromBech32(f.bech32);
assert.strictEqual(actual.version, f.version);
assert.strictEqual(actual.version, f.version) assert.strictEqual(actual.prefix, NETWORKS[f.network].bech32);
assert.strictEqual(actual.prefix, NETWORKS[f.network].bech32) assert.strictEqual(actual.data.toString('hex'), f.data);
assert.strictEqual(actual.data.toString('hex'), f.data) });
}) });
})
fixtures.invalid.bech32.forEach((f, i) => { fixtures.invalid.bech32.forEach((f, i) => {
it('decode fails for ' + f.bech32 + '(' + f.exception + ')', () => { it('decode fails for ' + f.bech32 + '(' + f.exception + ')', () => {
assert.throws(() => { assert.throws(() => {
baddress.fromBech32(f.address) baddress.fromBech32(f.address);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
describe('fromOutputScript', () => { describe('fromOutputScript', () => {
fixtures.standard.forEach(f => { fixtures.standard.forEach(f => {
it('encodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', () => { it('encodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', () => {
const script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script);
const address = baddress.fromOutputScript(script, NETWORKS[f.network]) const address = baddress.fromOutputScript(script, NETWORKS[f.network]);
assert.strictEqual(address, f.base58check || f.bech32.toLowerCase());
assert.strictEqual(address, f.base58check || f.bech32.toLowerCase()) });
}) });
})
fixtures.invalid.fromOutputScript.forEach(f => { fixtures.invalid.fromOutputScript.forEach(f => {
it('throws when ' + f.script.slice(0, 30) + '... ' + f.exception, () => { it('throws when ' + f.script.slice(0, 30) + '... ' + f.exception, () => {
const script = bscript.fromASM(f.script) const script = bscript.fromASM(f.script);
assert.throws(() => { assert.throws(() => {
baddress.fromOutputScript(script) baddress.fromOutputScript(script);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
describe('toBase58Check', () => { describe('toBase58Check', () => {
fixtures.standard.forEach(f => { fixtures.standard.forEach(f => {
if (!f.base58check) return if (!f.base58check)
return;
it('encodes ' + f.hash + ' (' + f.network + ')', () => { it('encodes ' + f.hash + ' (' + f.network + ')', () => {
const address = baddress.toBase58Check(Buffer.from(f.hash, 'hex'), f.version) const address = baddress.toBase58Check(Buffer.from(f.hash, 'hex'), f.version);
assert.strictEqual(address, f.base58check);
assert.strictEqual(address, f.base58check) });
}) });
}) });
})
describe('toBech32', () => { describe('toBech32', () => {
fixtures.bech32.forEach((f, i) => { fixtures.bech32.forEach((f, i) => {
if (!f.bech32) return if (!f.bech32)
const data = Buffer.from(f.data, 'hex') return;
const data = Buffer.from(f.data, 'hex');
it('encode ' + f.address, () => { it('encode ' + f.address, () => {
assert.deepStrictEqual(baddress.toBech32(data, f.version, f.prefix), f.address) assert.deepStrictEqual(baddress.toBech32(data, f.version, f.prefix), f.address);
}) });
}) });
fixtures.invalid.bech32.forEach((f, i) => { fixtures.invalid.bech32.forEach((f, i) => {
if (!f.prefix || f.version === undefined || f.data === undefined) return if (!f.prefix || f.version === undefined || f.data === undefined)
return;
it('encode fails (' + f.exception, () => { it('encode fails (' + f.exception, () => {
assert.throws(() => { assert.throws(() => {
baddress.toBech32(Buffer.from(f.data, 'hex'), f.version, f.prefix) baddress.toBech32(Buffer.from(f.data, 'hex'), f.version, f.prefix);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
describe('toOutputScript', () => { describe('toOutputScript', () => {
fixtures.standard.forEach(f => { fixtures.standard.forEach(f => {
it('decodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', () => { it('decodes ' + f.script.slice(0, 30) + '... (' + f.network + ')', () => {
const script = baddress.toOutputScript(f.base58check || f.bech32, NETWORKS[f.network]) const script = baddress.toOutputScript(f.base58check || f.bech32, NETWORKS[f.network]);
assert.strictEqual(bscript.toASM(script), f.script);
assert.strictEqual(bscript.toASM(script), f.script) });
}) });
})
fixtures.invalid.toOutputScript.forEach(f => { fixtures.invalid.toOutputScript.forEach(f => {
it('throws when ' + f.exception, () => { it('throws when ' + f.exception, () => {
assert.throws(() => { assert.throws(() => {
baddress.toOutputScript(f.address, f.network) baddress.toOutputScript(f.address, f.network);
}, new RegExp(f.address + ' ' + f.exception)) }, new RegExp(f.address + ' ' + f.exception));
}) });
}) });
}) });
}) });

328
test/bitcoin.core.js

@ -1,226 +1,200 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const base58 = require('bs58') const bitcoin = require("..");
const bitcoin = require('../') const { describe, it } = require('mocha');
const assert = require('assert');
const base58EncodeDecode = require('./fixtures/core/base58_encode_decode.json') const base58 = require('bs58');
const base58KeysInvalid = require('./fixtures/core/base58_keys_invalid.json') const base58EncodeDecode = require('../ts_test/fixtures/core/base58_encode_decode.json');
const base58KeysValid = require('./fixtures/core/base58_keys_valid.json') const base58KeysInvalid = require('../ts_test/fixtures/core/base58_keys_invalid.json');
const blocksValid = require('./fixtures/core/blocks.json') const base58KeysValid = require('../ts_test/fixtures/core/base58_keys_valid.json');
const sigCanonical = require('./fixtures/core/sig_canonical.json') const blocksValid = require('../ts_test/fixtures/core/blocks.json');
const sigHash = require('./fixtures/core/sighash.json') const sigCanonical = require('../ts_test/fixtures/core/sig_canonical.json');
const sigNoncanonical = require('./fixtures/core/sig_noncanonical.json') const sigHash = require('../ts_test/fixtures/core/sighash.json');
const txValid = require('./fixtures/core/tx_valid.json') const sigNoncanonical = require('../ts_test/fixtures/core/sig_noncanonical.json');
const txValid = require('../ts_test/fixtures/core/tx_valid.json');
describe('Bitcoin-core', () => { describe('Bitcoin-core', () => {
// base58EncodeDecode // base58EncodeDecode
describe('base58', () => { describe('base58', () => {
base58EncodeDecode.forEach(f => { base58EncodeDecode.forEach(f => {
const fhex = f[0] const fhex = f[0];
const fb58 = f[1] const fb58 = f[1];
it('can decode ' + fb58, () => { it('can decode ' + fb58, () => {
const buffer = base58.decode(fb58) const buffer = base58.decode(fb58);
const actual = buffer.toString('hex') const actual = buffer.toString('hex');
assert.strictEqual(actual, fhex);
assert.strictEqual(actual, fhex) });
})
it('can encode ' + fhex, () => { it('can encode ' + fhex, () => {
const buffer = Buffer.from(fhex, 'hex') const buffer = Buffer.from(fhex, 'hex');
const actual = base58.encode(buffer) const actual = base58.encode(buffer);
assert.strictEqual(actual, fb58);
assert.strictEqual(actual, fb58) });
}) });
}) });
})
// base58KeysValid // base58KeysValid
describe('address.toBase58Check', () => { describe('address.toBase58Check', () => {
const typeMap = { const typeMap = {
'pubkey': 'pubKeyHash', pubkey: 'pubKeyHash',
'script': 'scriptHash' script: 'scriptHash',
} };
base58KeysValid.forEach(f => { base58KeysValid.forEach(f => {
const expected = f[0] const expected = f[0];
const hash = Buffer.from(f[1], 'hex') const hash = Buffer.from(f[1], 'hex');
const params = f[2] const params = f[2];
if (params.isPrivkey)
if (params.isPrivkey) return return;
const network = params.isTestnet
const network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin ? bitcoin.networks.testnet
const version = network[typeMap[params.addrType]] : bitcoin.networks.bitcoin;
const version = network[typeMap[params.addrType]];
it('can export ' + expected, () => { it('can export ' + expected, () => {
assert.strictEqual(bitcoin.address.toBase58Check(hash, version), expected) assert.strictEqual(bitcoin.address.toBase58Check(hash, version), expected);
}) });
}) });
}) });
// base58KeysInvalid // base58KeysInvalid
describe('address.fromBase58Check', () => { describe('address.fromBase58Check', () => {
const allowedNetworks = [ const allowedNetworks = [
bitcoin.networks.bitcoin.pubkeyhash, bitcoin.networks.bitcoin.pubKeyHash,
bitcoin.networks.bitcoin.scripthash, bitcoin.networks.bitcoin.scriptHash,
bitcoin.networks.testnet.pubkeyhash, bitcoin.networks.testnet.pubKeyHash,
bitcoin.networks.testnet.scripthash bitcoin.networks.testnet.scriptHash,
] ];
base58KeysInvalid.forEach(f => { base58KeysInvalid.forEach(f => {
const string = f[0] const string0 = f[0];
it('throws on ' + string0, () => {
it('throws on ' + string, () => {
assert.throws(() => { assert.throws(() => {
const address = bitcoin.address.fromBase58Check(string) const address = bitcoin.address.fromBase58Check(string0);
assert.notStrictEqual(allowedNetworks.indexOf(address.version), -1, 'Invalid network');
assert.notStrictEqual(allowedNetworks.indexOf(address.version), -1, 'Invalid network') }, /(Invalid (checksum|network))|(too (short|long))/);
}, /(Invalid (checksum|network))|(too (short|long))/) });
}) });
}) });
})
// base58KeysValid // base58KeysValid
describe('ECPair', () => { describe('ECPair', () => {
base58KeysValid.forEach(f => { base58KeysValid.forEach(f => {
const string = f[0] const string0 = f[0];
const hex = f[1] const hex = f[1];
const params = f[2] const params = f[2];
if (!params.isPrivkey)
if (!params.isPrivkey) return return;
const network = params.isTestnet
const network = params.isTestnet ? bitcoin.networks.testnet : bitcoin.networks.bitcoin ? bitcoin.networks.testnet
const keyPair = bitcoin.ECPair.fromWIF(string, network) : bitcoin.networks.bitcoin;
const keyPair = bitcoin.ECPair.fromWIF(string0, network);
it('fromWIF imports ' + string, () => { it('fromWIF imports ' + string0, () => {
assert.strictEqual(keyPair.privateKey.toString('hex'), hex) assert.strictEqual(keyPair.privateKey.toString('hex'), hex);
assert.strictEqual(keyPair.compressed, params.isCompressed) assert.strictEqual(keyPair.compressed, params.isCompressed);
}) });
it('toWIF exports ' + hex + ' to ' + string0, () => {
it('toWIF exports ' + hex + ' to ' + string, () => { assert.strictEqual(keyPair.toWIF(), string0);
assert.strictEqual(keyPair.toWIF(), string) });
}) });
}) });
})
// base58KeysInvalid // base58KeysInvalid
describe('ECPair.fromWIF', () => { describe('ECPair.fromWIF', () => {
const allowedNetworks = [ const allowedNetworks = [
bitcoin.networks.bitcoin, bitcoin.networks.bitcoin,
bitcoin.networks.testnet bitcoin.networks.testnet,
] ];
base58KeysInvalid.forEach(f => { base58KeysInvalid.forEach(f => {
const string = f[0] const string0 = f[0];
it('throws on ' + string0, () => {
it('throws on ' + string, () => {
assert.throws(() => { assert.throws(() => {
bitcoin.ECPair.fromWIF(string, allowedNetworks) bitcoin.ECPair.fromWIF(string0, allowedNetworks);
}, /(Invalid|Unknown) (checksum|compression flag|network version|WIF length)/) }, /(Invalid|Unknown) (checksum|compression flag|network version|WIF length)/);
}) });
}) });
}) });
describe('Block.fromHex', () => { describe('Block.fromHex', () => {
blocksValid.forEach(f => { blocksValid.forEach(f => {
it('can parse ' + f.id, () => { it('can parse ' + f.id, () => {
const block = bitcoin.Block.fromHex(f.hex) const block = bitcoin.Block.fromHex(f.hex);
assert.strictEqual(block.getId(), f.id);
assert.strictEqual(block.getId(), f.id) assert.strictEqual(block.transactions.length, f.transactions);
assert.strictEqual(block.transactions.length, f.transactions) });
}) });
}) });
})
// txValid // txValid
describe('Transaction.fromHex', () => { describe('Transaction.fromHex', () => {
txValid.forEach(f => { txValid.forEach(f => {
// Objects that are only a single string are ignored // Objects that are only a single string are ignored
if (f.length === 1) return if (f.length === 1)
return;
const inputs = f[0] const inputs = f[0];
const fhex = f[1] const fhex = f[1];
// const verifyFlags = f[2] // TODO: do we need to test this? // const verifyFlags = f[2] // TODO: do we need to test this?
it('can decode ' + fhex, () => { it('can decode ' + fhex, () => {
const transaction = bitcoin.Transaction.fromHex(fhex) const transaction = bitcoin.Transaction.fromHex(fhex);
transaction.ins.forEach((txIn, i) => { transaction.ins.forEach((txIn, i) => {
const input = inputs[i] const input = inputs[i];
// reverse because test data is reversed // reverse because test data is reversed
const prevOutHash = Buffer.from(input[0], 'hex').reverse() const prevOutHash = Buffer.from(input[0], 'hex').reverse();
const prevOutIndex = input[1] const prevOutIndex = input[1];
assert.deepStrictEqual(txIn.hash, prevOutHash);
assert.deepStrictEqual(txIn.hash, prevOutHash)
// we read UInt32, not Int32 // we read UInt32, not Int32
assert.strictEqual(txIn.index & 0xffffffff, prevOutIndex) assert.strictEqual(txIn.index & 0xffffffff, prevOutIndex);
}) });
}) });
}) });
}) });
// sighash // sighash
describe('Transaction', () => { describe('Transaction', () => {
sigHash.forEach(f => { sigHash.forEach(f => {
// Objects that are only a single string are ignored // Objects that are only a single string are ignored
if (f.length === 1) return if (f.length === 1)
return;
const txHex = f[0] const txHex = f[0];
const scriptHex = f[1] const scriptHex = f[1];
const inIndex = f[2] const inIndex = f[2];
const hashType = f[3] const hashType = f[3];
const expectedHash = f[4] const expectedHash = f[4];
const hashTypes = [];
const hashTypes = [] if ((hashType & 0x1f) === bitcoin.Transaction.SIGHASH_NONE)
if ((hashType & 0x1f) === bitcoin.Transaction.SIGHASH_NONE) hashTypes.push('SIGHASH_NONE') hashTypes.push('SIGHASH_NONE');
else if ((hashType & 0x1f) === bitcoin.Transaction.SIGHASH_SINGLE) hashTypes.push('SIGHASH_SINGLE') else if ((hashType & 0x1f) === bitcoin.Transaction.SIGHASH_SINGLE)
else hashTypes.push('SIGHASH_ALL') hashTypes.push('SIGHASH_SINGLE');
if (hashType & bitcoin.Transaction.SIGHASH_ANYONECANPAY) hashTypes.push('SIGHASH_ANYONECANPAY') else
hashTypes.push('SIGHASH_ALL');
const hashTypeName = hashTypes.join(' | ') if (hashType & bitcoin.Transaction.SIGHASH_ANYONECANPAY)
hashTypes.push('SIGHASH_ANYONECANPAY');
const hashTypeName = hashTypes.join(' | ');
it('should hash ' + txHex.slice(0, 40) + '... (' + hashTypeName + ')', () => { it('should hash ' + txHex.slice(0, 40) + '... (' + hashTypeName + ')', () => {
const transaction = bitcoin.Transaction.fromHex(txHex) const transaction = bitcoin.Transaction.fromHex(txHex);
assert.strictEqual(transaction.toHex(), txHex) assert.strictEqual(transaction.toHex(), txHex);
const script = Buffer.from(scriptHex, 'hex');
const script = Buffer.from(scriptHex, 'hex') const scriptChunks = bitcoin.script.decompile(script);
const scriptChunks = bitcoin.script.decompile(script) assert.strictEqual(bitcoin.script.compile(scriptChunks).toString('hex'), scriptHex);
assert.strictEqual(bitcoin.script.compile(scriptChunks).toString('hex'), scriptHex) const hash = transaction.hashForSignature(inIndex, script, hashType);
const hash = transaction.hashForSignature(inIndex, script, hashType)
// reverse because test data is reversed // reverse because test data is reversed
assert.strictEqual(hash.reverse().toString('hex'), expectedHash) // @ts-ignore
}) assert.strictEqual(hash.reverse().toString('hex'), expectedHash);
}) });
}) });
});
describe('script.signature.decode', () => { describe('script.signature.decode', () => {
sigCanonical.forEach(hex => { sigCanonical.forEach(hex => {
const buffer = Buffer.from(hex, 'hex') const buffer = Buffer.from(hex, 'hex');
it('can parse ' + hex, () => { it('can parse ' + hex, () => {
const parsed = bitcoin.script.signature.decode(buffer) const parsed = bitcoin.script.signature.decode(buffer);
const actual = bitcoin.script.signature.encode(parsed.signature, parsed.hashType) const actual = bitcoin.script.signature.encode(parsed.signature, parsed.hashType);
assert.strictEqual(actual.toString('hex'), hex);
assert.strictEqual(actual.toString('hex'), hex) });
}) });
})
sigNoncanonical.forEach((hex, i) => { sigNoncanonical.forEach((hex, i) => {
if (i === 0) return if (i === 0)
if (i % 2 !== 0) return return;
if (i % 2 !== 0)
const description = sigNoncanonical[i - 1].slice(0, -1) return;
const buffer = Buffer.from(hex, 'hex') const description = sigNoncanonical[i - 1].slice(0, -1);
const buffer = Buffer.from(hex, 'hex');
it('throws on ' + description, () => { it('throws on ' + description, () => {
const regexStatement = 'Expected DER (integer|sequence)|(R|S) value (excessively padded|is' +
' negative)|(R|S|DER sequence) length is (zero|too short|too long|i' +
'nvalid)|Invalid hashType';
assert.throws(() => { assert.throws(() => {
bitcoin.script.signature.decode(buffer) bitcoin.script.signature.decode(buffer);
}, /Expected DER (integer|sequence)|(R|S) value (excessively padded|is negative)|(R|S|DER sequence) length is (zero|too short|too long|invalid)|Invalid hashType/) }, new RegExp(regexStatement));
}) });
}) });
}) });
}) });

204
test/block.js

@ -1,157 +1,133 @@
const { describe, it, beforeEach } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const Block = require('..').Block const __1 = require("..");
const { describe, it, beforeEach } = require('mocha');
const fixtures = require('./fixtures/block') const assert = require('assert');
const fixtures = require('../ts_test/fixtures/block');
describe('Block', () => { describe('Block', () => {
describe('version', () => { describe('version', () => {
it('should be interpreted as an int32le', () => { it('should be interpreted as an int32le', () => {
const blockHex = 'ffffffff0000000000000000000000000000000000000000000000000000000000000000414141414141414141414141414141414141414141414141414141414141414101000000020000000300000000' const blockHex = 'ffffffff000000000000000000000000000000000000000000000000000000000000' +
const block = Block.fromHex(blockHex) '00004141414141414141414141414141414141414141414141414141414141414141' +
assert.strictEqual(-1, block.version) '01000000020000000300000000';
assert.strictEqual(1, block.timestamp) const block = __1.Block.fromHex(blockHex);
}) assert.strictEqual(-1, block.version);
}) assert.strictEqual(1, block.timestamp);
});
});
describe('calculateTarget', () => { describe('calculateTarget', () => {
fixtures.targets.forEach(f => { fixtures.targets.forEach(f => {
it('returns ' + f.expected + ' for 0x' + f.bits, () => { it('returns ' + f.expected + ' for 0x' + f.bits, () => {
const bits = parseInt(f.bits, 16) const bits = parseInt(f.bits, 16);
assert.strictEqual(__1.Block.calculateTarget(bits).toString('hex'), f.expected);
assert.strictEqual(Block.calculateTarget(bits).toString('hex'), f.expected) });
}) });
}) });
})
describe('fromBuffer/fromHex', () => { describe('fromBuffer/fromHex', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('imports ' + f.description, () => { it('imports ' + f.description, () => {
const block = Block.fromHex(f.hex) const block = __1.Block.fromHex(f.hex);
assert.strictEqual(block.version, f.version);
assert.strictEqual(block.version, f.version) assert.strictEqual(block.prevHash.toString('hex'), f.prevHash);
assert.strictEqual(block.prevHash.toString('hex'), f.prevHash) assert.strictEqual(block.merkleRoot.toString('hex'), f.merkleRoot);
assert.strictEqual(block.merkleRoot.toString('hex'), f.merkleRoot)
if (block.witnessCommit) { if (block.witnessCommit) {
assert.strictEqual(block.witnessCommit.toString('hex'), f.witnessCommit) assert.strictEqual(block.witnessCommit.toString('hex'), f.witnessCommit);
} }
assert.strictEqual(block.timestamp, f.timestamp) assert.strictEqual(block.timestamp, f.timestamp);
assert.strictEqual(block.bits, f.bits) assert.strictEqual(block.bits, f.bits);
assert.strictEqual(block.nonce, f.nonce) assert.strictEqual(block.nonce, f.nonce);
assert.strictEqual(!block.transactions, f.hex.length === 160) assert.strictEqual(!block.transactions, f.hex.length === 160);
}) });
}) });
fixtures.invalid.forEach(f => { fixtures.invalid.forEach(f => {
it('throws on ' + f.exception, () => { it('throws on ' + f.exception, () => {
assert.throws(() => { assert.throws(() => {
Block.fromHex(f.hex) __1.Block.fromHex(f.hex);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
describe('toBuffer/toHex', () => { describe('toBuffer/toHex', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
let block let block;
beforeEach(() => { beforeEach(() => {
block = Block.fromHex(f.hex) block = __1.Block.fromHex(f.hex);
}) });
it('exports ' + f.description, () => { it('exports ' + f.description, () => {
assert.strictEqual(block.toHex(true), f.hex.slice(0, 160)) assert.strictEqual(block.toHex(true), f.hex.slice(0, 160));
assert.strictEqual(block.toHex(), f.hex) assert.strictEqual(block.toHex(), f.hex);
}) });
}) });
}) });
describe('getHash/getId', () => { describe('getHash/getId', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
let block let block;
beforeEach(() => { beforeEach(() => {
block = Block.fromHex(f.hex) block = __1.Block.fromHex(f.hex);
}) });
it('returns ' + f.id + ' for ' + f.description, () => { it('returns ' + f.id + ' for ' + f.description, () => {
assert.strictEqual(block.getHash().toString('hex'), f.hash) assert.strictEqual(block.getHash().toString('hex'), f.hash);
assert.strictEqual(block.getId(), f.id) assert.strictEqual(block.getId(), f.id);
}) });
}) });
}) });
describe('getUTCDate', () => { describe('getUTCDate', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
let block let block;
beforeEach(() => { beforeEach(() => {
block = Block.fromHex(f.hex) block = __1.Block.fromHex(f.hex);
}) });
it('returns UTC date of ' + f.id, () => { it('returns UTC date of ' + f.id, () => {
const utcDate = block.getUTCDate().getTime() const utcDate = block.getUTCDate().getTime();
assert.strictEqual(utcDate, f.timestamp * 1e3);
assert.strictEqual(utcDate, f.timestamp * 1e3) });
}) });
}) });
})
describe('calculateMerkleRoot', () => { describe('calculateMerkleRoot', () => {
it('should throw on zero-length transaction array', () => { it('should throw on zero-length transaction array', () => {
assert.throws(() => { assert.throws(() => {
Block.calculateMerkleRoot([]) __1.Block.calculateMerkleRoot([]);
}, /Cannot compute merkle root for zero transactions/) }, /Cannot compute merkle root for zero transactions/);
}) });
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
if (f.hex.length === 160) return if (f.hex.length === 160)
return;
let block let block;
beforeEach(() => { beforeEach(() => {
block = Block.fromHex(f.hex) block = __1.Block.fromHex(f.hex);
}) });
it('returns ' + f.merkleRoot + ' for ' + f.id, () => { it('returns ' + f.merkleRoot + ' for ' + f.id, () => {
assert.strictEqual(Block.calculateMerkleRoot(block.transactions).toString('hex'), f.merkleRoot) assert.strictEqual(__1.Block.calculateMerkleRoot(block.transactions).toString('hex'), f.merkleRoot);
}) });
if (f.witnessCommit) { if (f.witnessCommit) {
it('returns witness commit ' + f.witnessCommit + ' for ' + f.id, () => { it('returns witness commit ' + f.witnessCommit + ' for ' + f.id, () => {
assert.strictEqual(Block.calculateMerkleRoot(block.transactions, true).toString('hex'), f.witnessCommit) assert.strictEqual(__1.Block.calculateMerkleRoot(block.transactions, true).toString('hex'), f.witnessCommit);
}) });
} }
}) });
}) });
describe('checkTxRoots', () => { describe('checkTxRoots', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
if (f.hex.length === 160) return if (f.hex.length === 160)
return;
let block let block;
beforeEach(() => { beforeEach(() => {
block = Block.fromHex(f.hex) block = __1.Block.fromHex(f.hex);
}) });
it('returns ' + f.valid + ' for ' + f.id, () => { it('returns ' + f.valid + ' for ' + f.id, () => {
assert.strictEqual(block.checkTxRoots(), true) assert.strictEqual(block.checkTxRoots(), true);
}) });
}) });
}) });
describe('checkProofOfWork', () => { describe('checkProofOfWork', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
let block let block;
beforeEach(() => { beforeEach(() => {
block = Block.fromHex(f.hex) block = __1.Block.fromHex(f.hex);
}) });
it('returns ' + f.valid + ' for ' + f.id, () => { it('returns ' + f.valid + ' for ' + f.id, () => {
assert.strictEqual(block.checkProofOfWork(), f.valid) assert.strictEqual(block.checkProofOfWork(), f.valid);
}) });
}) });
}) });
}) });

65
test/bufferutils.js

@ -1,49 +1,42 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bufferutils = require('../src/bufferutils') const { describe, it } = require('mocha');
const assert = require('assert');
const fixtures = require('./fixtures/bufferutils.json') const bufferutils = require('../src/bufferutils');
const fixtures = require('../ts_test/fixtures/bufferutils.json');
describe('bufferutils', () => { describe('bufferutils', () => {
describe('readUInt64LE', () => { describe('readUInt64LE', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('decodes ' + f.hex, () => { it('decodes ' + f.hex, () => {
const buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex');
const number = bufferutils.readUInt64LE(buffer, 0) const number0 = bufferutils.readUInt64LE(buffer, 0);
assert.strictEqual(number0, f.dec);
assert.strictEqual(number, f.dec) });
}) });
})
fixtures.invalid.readUInt64LE.forEach(f => { fixtures.invalid.readUInt64LE.forEach(f => {
it('throws on ' + f.description, () => { it('throws on ' + f.description, () => {
const buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex');
assert.throws(() => { assert.throws(() => {
bufferutils.readUInt64LE(buffer, 0) bufferutils.readUInt64LE(buffer, 0);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
describe('writeUInt64LE', () => { describe('writeUInt64LE', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('encodes ' + f.dec, () => { it('encodes ' + f.dec, () => {
const buffer = Buffer.alloc(8, 0) const buffer = Buffer.alloc(8, 0);
bufferutils.writeUInt64LE(buffer, f.dec, 0);
bufferutils.writeUInt64LE(buffer, f.dec, 0) assert.strictEqual(buffer.toString('hex'), f.hex);
assert.strictEqual(buffer.toString('hex'), f.hex) });
}) });
})
fixtures.invalid.readUInt64LE.forEach(f => { fixtures.invalid.readUInt64LE.forEach(f => {
it('throws on ' + f.description, () => { it('throws on ' + f.description, () => {
const buffer = Buffer.alloc(8, 0) const buffer = Buffer.alloc(8, 0);
assert.throws(() => { assert.throws(() => {
bufferutils.writeUInt64LE(buffer, f.dec, 0) bufferutils.writeUInt64LE(buffer, f.dec, 0);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
}) });

219
test/classify.js

@ -1,19 +1,18 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bscript = require('../src/script') const { describe, it } = require('mocha');
const classify = require('../src/classify') const assert = require('assert');
const bscript = require('../src/script');
const fixtures = require('./fixtures/templates.json') const classify = require('../src/classify');
const fixtures = require('../ts_test/fixtures/templates.json');
const multisig = require('../src/templates/multisig') const multisig = require('../src/templates/multisig');
const nullData = require('../src/templates/nulldata') const nullData = require('../src/templates/nulldata');
const pubKey = require('../src/templates/pubkey') const pubKey = require('../src/templates/pubkey');
const pubKeyHash = require('../src/templates/pubkeyhash') const pubKeyHash = require('../src/templates/pubkeyhash');
const scriptHash = require('../src/templates/scripthash') const scriptHash = require('../src/templates/scripthash');
const witnessPubKeyHash = require('../src/templates/witnesspubkeyhash') const witnessPubKeyHash = require('../src/templates/witnesspubkeyhash');
const witnessScriptHash = require('../src/templates/witnessscripthash') const witnessScriptHash = require('../src/templates/witnessscripthash');
const witnessCommitment = require('../src/templates/witnesscommitment') const witnessCommitment = require('../src/templates/witnesscommitment');
const tmap = { const tmap = {
pubKey, pubKey,
pubKeyHash, pubKeyHash,
@ -22,49 +21,43 @@ const tmap = {
witnessScriptHash, witnessScriptHash,
multisig, multisig,
nullData, nullData,
witnessCommitment witnessCommitment,
} };
describe('classify', () => { describe('classify', () => {
describe('input', () => { describe('input', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
if (!f.input) return if (!f.input)
return;
it('classifies ' + f.input + ' as ' + f.type, () => { it('classifies ' + f.input + ' as ' + f.type, () => {
const input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input);
const type = classify.input(input) const type = classify.input(input);
assert.strictEqual(type, f.type);
assert.strictEqual(type, f.type) });
}) });
})
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
if (!f.input) return if (!f.input)
if (!f.typeIncomplete) return return;
if (!f.typeIncomplete)
return;
it('classifies incomplete ' + f.input + ' as ' + f.typeIncomplete, () => { it('classifies incomplete ' + f.input + ' as ' + f.typeIncomplete, () => {
const input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input);
const type = classify.input(input, true) const type = classify.input(input, true);
assert.strictEqual(type, f.typeIncomplete);
assert.strictEqual(type, f.typeIncomplete) });
}) });
}) });
})
describe('classifyOutput', () => { describe('classifyOutput', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
if (!f.output) return if (!f.output)
return;
it('classifies ' + f.output + ' as ' + f.type, () => { it('classifies ' + f.output + ' as ' + f.type, () => {
const output = bscript.fromASM(f.output) const output = bscript.fromASM(f.output);
const type = classify.output(output) const type = classify.output(output);
assert.strictEqual(type, f.type);
assert.strictEqual(type, f.type) });
}) });
}) });
}) [
;[
'pubKey', 'pubKey',
'pubKeyHash', 'pubKeyHash',
'scriptHash', 'scriptHash',
@ -72,85 +65,87 @@ describe('classify', () => {
'witnessScriptHash', 'witnessScriptHash',
'multisig', 'multisig',
'nullData', 'nullData',
'witnessCommitment' 'witnessCommitment',
].forEach(name => { ].forEach(name => {
const inputType = tmap[name].input const inputType = tmap[name].input;
const outputType = tmap[name].output const outputType = tmap[name].output;
describe(name + '.input.check', () => { describe(name + '.input.check', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
if (name.toLowerCase() === classify.types.P2WPKH) return if (name.toLowerCase() === classify.types.P2WPKH)
if (name.toLowerCase() === classify.types.P2WSH) return return;
const expected = name.toLowerCase() === f.type.toLowerCase() if (name.toLowerCase() === classify.types.P2WSH)
return;
const expected = name.toLowerCase() === f.type.toLowerCase();
if (inputType && f.input) { if (inputType && f.input) {
const input = bscript.fromASM(f.input) const input = bscript.fromASM(f.input);
it('returns ' + expected + ' for ' + f.input, () => { it('returns ' + expected + ' for ' + f.input, () => {
assert.strictEqual(inputType.check(input), expected) assert.strictEqual(inputType.check(input), expected);
}) });
if (f.typeIncomplete) { if (f.typeIncomplete) {
const expectedIncomplete = name.toLowerCase() === f.typeIncomplete const expectedIncomplete = name.toLowerCase() === f.typeIncomplete;
it('returns ' + expected + ' for ' + f.input, () => { it('returns ' + expected + ' for ' + f.input, () => {
assert.strictEqual(inputType.check(input, true), expectedIncomplete) assert.strictEqual(inputType.check(input, true), expectedIncomplete);
}) });
} }
} }
}) });
if (!fixtures.invalid[name])
if (!(fixtures.invalid[name])) return return;
fixtures.invalid[name].inputs.forEach(f => { fixtures.invalid[name].inputs.forEach(f => {
if (!f.input && !f.inputHex) return if (!f.input && !f.inputHex)
return;
it('returns false for ' + f.description + ' (' + (f.input || f.inputHex) + ')', () => { it('returns false for ' +
let input f.description +
' (' +
(f.input || f.inputHex) +
')', () => {
let input;
if (f.input) { if (f.input) {
input = bscript.fromASM(f.input) input = bscript.fromASM(f.input);
} else {
input = Buffer.from(f.inputHex, 'hex')
} }
else {
assert.strictEqual(inputType.check(input), false) input = Buffer.from(f.inputHex, 'hex');
}) }
}) assert.strictEqual(inputType.check(input), false);
}) });
});
});
describe(name + '.output.check', () => { describe(name + '.output.check', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
const expected = name.toLowerCase() === f.type const expected = name.toLowerCase() === f.type;
if (outputType && f.output) { if (outputType && f.output) {
it('returns ' + expected + ' for ' + f.output, () => { it('returns ' + expected + ' for ' + f.output, () => {
const output = bscript.fromASM(f.output) const output = bscript.fromASM(f.output);
if (name.toLowerCase() === 'nulldata' &&
if (name.toLowerCase() === 'nulldata' && f.type === classify.types.WITNESS_COMMITMENT) return f.type === classify.types.WITNESS_COMMITMENT)
if (name.toLowerCase() === 'witnesscommitment' && f.type === classify.types.NULLDATA) return return;
assert.strictEqual(outputType.check(output), expected) if (name.toLowerCase() === 'witnesscommitment' &&
}) f.type === classify.types.NULLDATA)
return;
assert.strictEqual(outputType.check(output), expected);
});
} }
}) });
if (!fixtures.invalid[name])
if (!(fixtures.invalid[name])) return return;
fixtures.invalid[name].outputs.forEach(f => { fixtures.invalid[name].outputs.forEach(f => {
if (!f.output && !f.outputHex) return if (!f.output && !f.outputHex)
return;
it('returns false for ' + f.description + ' (' + (f.output || f.outputHex) + ')', () => { it('returns false for ' +
let output f.description +
' (' +
(f.output || f.outputHex) +
')', () => {
let output;
if (f.output) { if (f.output) {
output = bscript.fromASM(f.output) output = bscript.fromASM(f.output);
} else { }
output = Buffer.from(f.outputHex, 'hex') else {
output = Buffer.from(f.outputHex, 'hex');
} }
assert.strictEqual(outputType.check(output), false);
assert.strictEqual(outputType.check(output), false) });
}) });
}) });
}) });
}) });
})

34
test/crypto.js

@ -1,23 +1,21 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bcrypto = require('../src/crypto') const __1 = require("..");
const { describe, it } = require('mocha');
const fixtures = require('./fixtures/crypto') const assert = require('assert');
const fixtures = require('../ts_test/fixtures/crypto');
describe('crypto', () => { describe('crypto', () => {
['hash160', 'hash256', 'ripemd160', 'sha1', 'sha256'].forEach(algorithm => { ['hash160', 'hash256', 'ripemd160', 'sha1', 'sha256'].forEach(algorithm => {
describe(algorithm, () => { describe(algorithm, () => {
fixtures.forEach(f => { fixtures.forEach(f => {
const fn = bcrypto[algorithm] const fn = __1.crypto[algorithm];
const expected = f[algorithm] const expected = f[algorithm];
it('returns ' + expected + ' for ' + f.hex, () => { it('returns ' + expected + ' for ' + f.hex, () => {
const data = Buffer.from(f.hex, 'hex') const data = Buffer.from(f.hex, 'hex');
const actual = fn(data).toString('hex') const actual = fn(data).toString('hex');
assert.strictEqual(actual, expected);
assert.strictEqual(actual, expected) });
}) });
}) });
}) });
}) });
})

370
test/ecpair.js

@ -1,262 +1,224 @@
const { describe, it, beforeEach } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const proxyquire = require('proxyquire') const __1 = require("..");
const hoodwink = require('hoodwink') const __2 = require("..");
const { describe, it, beforeEach } = require('mocha');
const ECPair = require('../src/ecpair') const assert = require('assert');
const tinysecp = require('tiny-secp256k1') const proxyquire = require('proxyquire');
const hoodwink = require('hoodwink');
const fixtures = require('./fixtures/ecpair.json') const tinysecp = require('tiny-secp256k1');
const fixtures = require('../ts_test/fixtures/ecpair.json');
const NETWORKS = require('../src/networks') const NETWORKS_LIST = []; // Object.values(NETWORKS)
const NETWORKS_LIST = [] // Object.values(NETWORKS) for (const networkName in __2.networks) {
for (let networkName in NETWORKS) { if (networkName)
NETWORKS_LIST.push(NETWORKS[networkName]) NETWORKS_LIST.push(__2.networks[networkName]);
} }
const ZERO = Buffer.alloc(32, 0);
const ZERO = Buffer.alloc(32, 0) const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex');
const ONE = Buffer.from('0000000000000000000000000000000000000000000000000000000000000001', 'hex') const GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex');
const GROUP_ORDER = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 'hex') const GROUP_ORDER_LESS_1 = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 'hex');
const GROUP_ORDER_LESS_1 = Buffer.from('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 'hex')
describe('ECPair', () => { describe('ECPair', () => {
describe('getPublicKey', () => { describe('getPublicKey', () => {
let keyPair let keyPair;
beforeEach(() => { beforeEach(() => {
keyPair = ECPair.fromPrivateKey(ONE) keyPair = __1.ECPair.fromPrivateKey(ONE);
}) });
it('calls pointFromScalar lazily', hoodwink(() => { it('calls pointFromScalar lazily', hoodwink(() => {
assert.strictEqual(keyPair.__Q, undefined) assert.strictEqual(keyPair.__Q, undefined);
// .publicKey forces the memoization // .publicKey forces the memoization
assert.strictEqual(keyPair.publicKey.toString('hex'), '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798') assert.strictEqual(keyPair.publicKey.toString('hex'), '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
assert.strictEqual(keyPair.__Q.toString('hex'), '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798') assert.strictEqual(keyPair.__Q.toString('hex'), '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798');
})) }));
}) });
describe('fromPrivateKey', () => { describe('fromPrivateKey', () => {
it('defaults to compressed', () => { it('defaults to compressed', () => {
const keyPair = ECPair.fromPrivateKey(ONE) const keyPair = __1.ECPair.fromPrivateKey(ONE);
assert.strictEqual(keyPair.compressed, true);
assert.strictEqual(keyPair.compressed, true) });
})
it('supports the uncompressed option', () => { it('supports the uncompressed option', () => {
const keyPair = ECPair.fromPrivateKey(ONE, { const keyPair = __1.ECPair.fromPrivateKey(ONE, {
compressed: false compressed: false,
}) });
assert.strictEqual(keyPair.compressed, false);
assert.strictEqual(keyPair.compressed, false) });
})
it('supports the network option', () => { it('supports the network option', () => {
const keyPair = ECPair.fromPrivateKey(ONE, { const keyPair = __1.ECPair.fromPrivateKey(ONE, {
compressed: false, compressed: false,
network: NETWORKS.testnet network: __2.networks.testnet,
}) });
assert.strictEqual(keyPair.network, __2.networks.testnet);
assert.strictEqual(keyPair.network, NETWORKS.testnet) });
})
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('derives public key for ' + f.WIF, () => { it('derives public key for ' + f.WIF, () => {
const d = Buffer.from(f.d, 'hex') const d = Buffer.from(f.d, 'hex');
const keyPair = ECPair.fromPrivateKey(d, { const keyPair = __1.ECPair.fromPrivateKey(d, {
compressed: f.compressed compressed: f.compressed,
}) });
assert.strictEqual(keyPair.publicKey.toString('hex'), f.Q);
assert.strictEqual(keyPair.publicKey.toString('hex'), f.Q) });
}) });
})
fixtures.invalid.fromPrivateKey.forEach(f => { fixtures.invalid.fromPrivateKey.forEach(f => {
it('throws ' + f.exception, () => { it('throws ' + f.exception, () => {
const d = Buffer.from(f.d, 'hex') const d = Buffer.from(f.d, 'hex');
assert.throws(() => { assert.throws(() => {
ECPair.fromPrivateKey(d, f.options) __1.ECPair.fromPrivateKey(d, f.options);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
describe('fromPublicKey', () => { describe('fromPublicKey', () => {
fixtures.invalid.fromPublicKey.forEach(f => { fixtures.invalid.fromPublicKey.forEach(f => {
it('throws ' + f.exception, () => { it('throws ' + f.exception, () => {
const Q = Buffer.from(f.Q, 'hex') const Q = Buffer.from(f.Q, 'hex');
assert.throws(() => { assert.throws(() => {
ECPair.fromPublicKey(Q, f.options) __1.ECPair.fromPublicKey(Q, f.options);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
describe('fromWIF', () => { describe('fromWIF', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('imports ' + f.WIF + ' (' + f.network + ')', () => { it('imports ' + f.WIF + ' (' + f.network + ')', () => {
const network = NETWORKS[f.network] const network = __2.networks[f.network];
const keyPair = ECPair.fromWIF(f.WIF, network) const keyPair = __1.ECPair.fromWIF(f.WIF, network);
assert.strictEqual(keyPair.privateKey.toString('hex'), f.d);
assert.strictEqual(keyPair.privateKey.toString('hex'), f.d) assert.strictEqual(keyPair.compressed, f.compressed);
assert.strictEqual(keyPair.compressed, f.compressed) assert.strictEqual(keyPair.network, network);
assert.strictEqual(keyPair.network, network) });
}) });
})
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('imports ' + f.WIF + ' (via list of networks)', () => { it('imports ' + f.WIF + ' (via list of networks)', () => {
const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST) const keyPair = __1.ECPair.fromWIF(f.WIF, NETWORKS_LIST);
assert.strictEqual(keyPair.privateKey.toString('hex'), f.d);
assert.strictEqual(keyPair.privateKey.toString('hex'), f.d) assert.strictEqual(keyPair.compressed, f.compressed);
assert.strictEqual(keyPair.compressed, f.compressed) assert.strictEqual(keyPair.network, __2.networks[f.network]);
assert.strictEqual(keyPair.network, NETWORKS[f.network]) });
}) });
})
fixtures.invalid.fromWIF.forEach(f => { fixtures.invalid.fromWIF.forEach(f => {
it('throws on ' + f.WIF, () => { it('throws on ' + f.WIF, () => {
assert.throws(() => { assert.throws(() => {
const networks = f.network ? NETWORKS[f.network] : NETWORKS_LIST const networks = f.network ? __2.networks[f.network] : NETWORKS_LIST;
__1.ECPair.fromWIF(f.WIF, networks);
ECPair.fromWIF(f.WIF, networks) }, new RegExp(f.exception));
}, new RegExp(f.exception)) });
}) });
}) });
})
describe('toWIF', () => { describe('toWIF', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('exports ' + f.WIF, () => { it('exports ' + f.WIF, () => {
const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST) const keyPair = __1.ECPair.fromWIF(f.WIF, NETWORKS_LIST);
const result = keyPair.toWIF() const result = keyPair.toWIF();
assert.strictEqual(result, f.WIF) assert.strictEqual(result, f.WIF);
}) });
}) });
}) });
describe('makeRandom', () => { describe('makeRandom', () => {
const d = Buffer.alloc(32, 4) const d = Buffer.alloc(32, 4);
const exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv' const exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv';
describe('uses randombytes RNG', () => { describe('uses randombytes RNG', () => {
it('generates a ECPair', () => { it('generates a ECPair', () => {
const stub = { randombytes: () => { return d } } const stub = {
const ProxiedECPair = proxyquire('../src/ecpair', stub) randombytes: () => {
return d;
const keyPair = ProxiedECPair.makeRandom() },
assert.strictEqual(keyPair.toWIF(), exWIF) };
}) const ProxiedECPair = proxyquire('../src/ecpair', stub);
}) const keyPair = ProxiedECPair.makeRandom();
assert.strictEqual(keyPair.toWIF(), exWIF);
});
});
it('allows a custom RNG to be used', () => { it('allows a custom RNG to be used', () => {
const keyPair = ECPair.makeRandom({ const keyPair = __1.ECPair.makeRandom({
rng: size => { return d.slice(0, size) } rng: (size) => {
}) return d.slice(0, size);
},
assert.strictEqual(keyPair.toWIF(), exWIF) });
}) assert.strictEqual(keyPair.toWIF(), exWIF);
});
it('retains the same defaults as ECPair constructor', () => { it('retains the same defaults as ECPair constructor', () => {
const keyPair = ECPair.makeRandom() const keyPair = __1.ECPair.makeRandom();
assert.strictEqual(keyPair.compressed, true);
assert.strictEqual(keyPair.compressed, true) assert.strictEqual(keyPair.network, __2.networks.bitcoin);
assert.strictEqual(keyPair.network, NETWORKS.bitcoin) });
})
it('supports the options parameter', () => { it('supports the options parameter', () => {
const keyPair = ECPair.makeRandom({ const keyPair = __1.ECPair.makeRandom({
compressed: false, compressed: false,
network: NETWORKS.testnet network: __2.networks.testnet,
}) });
assert.strictEqual(keyPair.compressed, false);
assert.strictEqual(keyPair.compressed, false) assert.strictEqual(keyPair.network, __2.networks.testnet);
assert.strictEqual(keyPair.network, NETWORKS.testnet) });
})
it('throws if d is bad length', () => { it('throws if d is bad length', () => {
function rng () { function rng() {
return Buffer.alloc(28) return Buffer.alloc(28);
} }
assert.throws(() => { assert.throws(() => {
ECPair.makeRandom({ rng: rng }) __1.ECPair.makeRandom({ rng });
}, /Expected Buffer\(Length: 32\), got Buffer\(Length: 28\)/) }, /Expected Buffer\(Length: 32\), got Buffer\(Length: 28\)/);
}) });
it('loops until d is within interval [1, n) : 1', hoodwink(function () { it('loops until d is within interval [1, n) : 1', hoodwink(function () {
const rng = this.stub(() => { const rng = this.stub(() => {
if (rng.calls === 0) return ZERO // 0 if (rng.calls === 0)
return ONE // >0 return ZERO; // 0
}, 2) return ONE; // >0
}, 2);
ECPair.makeRandom({ rng: rng }) __1.ECPair.makeRandom({ rng });
})) }));
it('loops until d is within interval [1, n) : n - 1', hoodwink(function () { it('loops until d is within interval [1, n) : n - 1', hoodwink(function () {
const rng = this.stub(() => { const rng = this.stub(() => {
if (rng.calls === 0) return ZERO // <1 if (rng.calls === 0)
if (rng.calls === 1) return GROUP_ORDER // >n-1 return ZERO; // <1
return GROUP_ORDER_LESS_1 // n-1 if (rng.calls === 1)
}, 3) return GROUP_ORDER; // >n-1
return GROUP_ORDER_LESS_1; // n-1
ECPair.makeRandom({ rng: rng }) }, 3);
})) __1.ECPair.makeRandom({ rng });
}) }));
});
describe('.network', () => { describe('.network', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('returns ' + f.network + ' for ' + f.WIF, () => { it('returns ' + f.network + ' for ' + f.WIF, () => {
const network = NETWORKS[f.network] const network = __2.networks[f.network];
const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST) const keyPair = __1.ECPair.fromWIF(f.WIF, NETWORKS_LIST);
assert.strictEqual(keyPair.network, network);
assert.strictEqual(keyPair.network, network) });
}) });
}) });
})
describe('tinysecp wrappers', () => { describe('tinysecp wrappers', () => {
let keyPair let keyPair;
let hash let hash;
let signature let signature;
beforeEach(() => { beforeEach(() => {
keyPair = ECPair.makeRandom() keyPair = __1.ECPair.makeRandom();
hash = ZERO hash = ZERO;
signature = Buffer.alloc(64, 1) signature = Buffer.alloc(64, 1);
}) });
describe('signing', () => { describe('signing', () => {
it('wraps tinysecp.sign', hoodwink(function () { it('wraps tinysecp.sign', hoodwink(function () {
this.mock(tinysecp, 'sign', (h, d) => { this.mock(tinysecp, 'sign', (h, d) => {
assert.strictEqual(h, hash) assert.strictEqual(h, hash);
assert.strictEqual(d, keyPair.privateKey) assert.strictEqual(d, keyPair.privateKey);
return signature return signature;
}, 1) }, 1);
assert.strictEqual(keyPair.sign(hash), signature);
assert.strictEqual(keyPair.sign(hash), signature) }));
}))
it('throws if no private key is found', () => { it('throws if no private key is found', () => {
delete keyPair.__D delete keyPair.__D;
assert.throws(() => { assert.throws(() => {
keyPair.sign(hash) keyPair.sign(hash);
}, /Missing private key/) }, /Missing private key/);
}) });
}) });
describe('verify', () => { describe('verify', () => {
it('wraps tinysecp.verify', hoodwink(function () { it('wraps tinysecp.verify', hoodwink(function () {
this.mock(tinysecp, 'verify', (h, q, s) => { this.mock(tinysecp, 'verify', (h, q, s) => {
assert.strictEqual(h, hash) assert.strictEqual(h, hash);
assert.strictEqual(q, keyPair.publicKey) assert.strictEqual(q, keyPair.publicKey);
assert.strictEqual(s, signature) assert.strictEqual(s, signature);
return true return true;
}, 1) }, 1);
assert.strictEqual(keyPair.verify(hash, signature), true);
assert.strictEqual(keyPair.verify(hash, signature), true) }));
})) });
}) });
}) });
})

1
test/fixtures/address.json

@ -48,7 +48,6 @@
"bech32": "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4", "bech32": "BC1QW508D6QEJXTDG4Y5R3ZARVARY0C5XW7KV8F3T4",
"data": "751e76e8199196d454941c45d1b3a323f1433bd6", "data": "751e76e8199196d454941c45d1b3a323f1433bd6",
"script": "OP_0 751e76e8199196d454941c45d1b3a323f1433bd6" "script": "OP_0 751e76e8199196d454941c45d1b3a323f1433bd6"
}, },
{ {
"network": "testnet", "network": "testnet",

31
test/fixtures/core/README.md

@ -1,31 +0,0 @@
Description
------------
This directory contains data-driven tests for various aspects of Bitcoin.
Bitcoinjs-lib notes
-------------------
This directory does not contain all the Bitcoin core tests.
Missing core test data includes:
* `alertTests.raw`
Bitcoin-js does not interact with the Bitcoin network directly.
* `tx_invalid.json`
Bitcoin-js can not evaluate Scripts, making testing this irrelevant.
It can decode valid Transactions, therefore `tx_valid.json` remains.
* `script*.json`
Bitcoin-js can not evaluate Scripts, making testing this irrelevant.
License
--------
The data files in this directory are
Copyright (c) 2012-2014 The Bitcoin Core developers
Distributed under the MIT/X11 software license, see the accompanying
file COPYING or http://www.opensource.org/licenses/mit-license.php.

24
test/fixtures/core/base58_encode_decode.json

@ -1,14 +1,14 @@
[ [
["", ""], ["", ""],
["61", "2g"], ["61", "2g"],
["626262", "a3gV"], ["626262", "a3gV"],
["636363", "aPEr"], ["636363", "aPEr"],
["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"], ["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"],
["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"], ["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"],
["516b6fcd0f", "ABnLTmg"], ["516b6fcd0f", "ABnLTmg"],
["bf4f89001e670274dd", "3SEo3LWLoPntC"], ["bf4f89001e670274dd", "3SEo3LWLoPntC"],
["572e4794", "3EFU7m"], ["572e4794", "3EFU7m"],
["ecac89cad93923c02321", "EJDM8drfXA6uyA"], ["ecac89cad93923c02321", "EJDM8drfXA6uyA"],
["10c8511e", "Rt5zm"], ["10c8511e", "Rt5zm"],
["00000000000000000000", "1111111111"] ["00000000000000000000", "1111111111"]
] ]

4
test/fixtures/core/sig_noncanonical.json

@ -1,6 +1,5 @@
[ [
"non-hex strings are ignored", "non-hex strings are ignored",
"too short:", "30050201FF020001", "too short:", "30050201FF020001",
"too long:", "30470221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", "too long:", "30470221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
"hashtype:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed11", "hashtype:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed11",
@ -8,13 +7,10 @@
"total length:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", "total length:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
"S len oob:", "301F01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb101", "S len oob:", "301F01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb101",
"R+S:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed0001", "R+S:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed0001",
"R type:", "304401205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", "R type:", "304401205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
"R len = 0:", "3024020002202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", "R len = 0:", "3024020002202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
"R<0:", "304402208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", "R<0:", "304402208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
"R padded:", "30450221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", "R padded:", "30450221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
"S type:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610501202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", "S type:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610501202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",
"S len = 0:", "302402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105020001", "S len = 0:", "302402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105020001",
"S<0:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", "S<0:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01",

903
test/fixtures/core/tx_valid.json

@ -1,515 +1,416 @@
[ [
["The following are deserialized transactions which are valid."], ["The following are deserialized transactions which are valid."],
["They are in the form"], ["They are in the form"],
["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], ["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"],
["serializedTransaction, verifyFlags]"], ["serializedTransaction, verifyFlags]"],
["Objects that are only a single string (like this one) are ignored"], ["Objects that are only a single string (like this one) are ignored"],
["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"],
["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"], ["See http://r6.ca/blog/20111119T211504Z.html"],
["See http://r6.ca/blog/20111119T211504Z.html"], ["It is also the first OP_CHECKMULTISIG transaction in standard form"],
["It is also the first OP_CHECKMULTISIG transaction in standard form"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"],
["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], ["The dummy byte is fine however, so the NULLDUMMY flag should be happy"],
["It is an OP_CHECKMULTISIG with an arbitrary extra byte stuffed into the signature at pos length - 2"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
["The dummy byte is fine however, so the NULLDUMMY flag should be happy"], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"],
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], ["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"],
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH,NULLDUMMY"], ["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"],
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
["It is an OP_CHECKMULTISIG with the dummy value set to something other than an empty string"], ["As above, but using a OP_1"],
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004a01ff47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
["As above, but using a OP_1NEGATE"],
["As above, but using a OP_1"], [[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]],
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"],
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000495147304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"],
["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"],
["As above, but using a OP_1NEGATE"], [[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]],
[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], "01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", "P2SH"],
"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000494f47304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", "P2SH"], ["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]],
["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"], ["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"],
[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]],
"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", "P2SH"], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"],
["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"],
["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"], ["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]], [[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]],
"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", "P2SH"],
["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"], ["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], ["It results in signing the constant 1, instead of something generated based on the transaction,"],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", "P2SH"], ["when the input doing the signing has an index greater than the maximum output index"],
["bitcoinjs note, these inputs have been reversed for convenience, as the original data was unordered, and it is easier to check the inputs if they are ordered"],
["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"], [[["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"], ["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"]],
["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"], "01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", "P2SH"],
[[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"], ["An invalid P2SH Transaction"],
["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]],
"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", "P2SH"], "010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "NONE"],
["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"],
["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]],
["It results in signing the constant 1, instead of something generated based on the transaction,"], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", "P2SH"],
["when the input doing the signing has an index greater than the maximum output index"], ["Tests for CheckTransaction()"],
["bitcoinjs note, these inputs have been reversed for convenience, as the original data was unordered, and it is easier to check the inputs if they are ordered"], ["MAX_MONEY output"],
[[["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"], ["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]],
"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", "P2SH"], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", "P2SH"],
["MAX_MONEY output + 0 output"],
["An invalid P2SH Transaction"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", "P2SH"],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", "NONE"], ["Coinbase of size 2"],
["Note the input is just required to make the tester happy"],
["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]], "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", "P2SH"],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", "P2SH"], ["Coinbase of size 100"],
["Note the input is just required to make the tester happy"],
["Tests for CheckTransaction()"], [[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
["MAX_MONEY output"], "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], ["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", "P2SH"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
["MAX_MONEY output + 0 output"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", "P2SH"],
["Coinbase of size 2"],
["Note the input is just required to make the tester happy"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", "P2SH"],
["Coinbase of size 100"],
["Note the input is just required to make the tester happy"],
[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]],
"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", "P2SH"],
["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
"010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"], "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"],
["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"],
["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"],
["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]],
"01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"], "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", "P2SH"],
["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"],
["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"], [[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
[[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"],
["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]], ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]],
"010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", "P2SH"], "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", "P2SH"],
["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"], ["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"],
[[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]], [[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]],
"0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", "P2SH"], "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", "P2SH"],
["Correct signature order"],
["Correct signature order"], ["Note the input is just required to make the tester happy"],
["Note the input is just required to make the tester happy"], [[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]],
[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], "01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"],
"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", "P2SH"], ["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"],
[[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]],
["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"], "0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", "P2SH"],
[[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]], ["Empty pubkey"],
"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", "P2SH"], [[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]],
"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", "P2SH"],
["Empty pubkey"], ["Empty signature"],
[[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]], [[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]],
"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", "P2SH"], "0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", "P2SH"],
[[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]],
["Empty signature"], "0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", "P2SH"],
[[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]], [[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]],
"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", "P2SH"], "010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", "P2SH"],
[[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]],
[[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]], "0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", "P2SH"],
"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", "P2SH"], [[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]],
"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"],
[[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]], ["OP_CODESEPARATOR tests"],
"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", "P2SH"], ["Test that SignatureHash() removes OP_CODESEPARATOR with FindAndDelete()"],
[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
[[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]], "01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH"],
"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", "P2SH"], [[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]],
"01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH"],
[[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]], ["Hashed data starts at the CODESEPARATOR"],
"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", "P2SH"], [[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]],
"01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH"],
["But only if execution has reached it"],
["OP_CODESEPARATOR tests"], [[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"],
["Test that SignatureHash() removes OP_CODESEPARATOR with FindAndDelete()"], ["CODESEPARATOR in an unexecuted IF block does not change what is hashed"],
[[["bc7fd132fcf817918334822ee6d9bd95c889099c96e07ca2c1eb2cc70db63224", 0, "CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], [[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
"01000000012432b60dc72cebc1a27ce0969c0989c895bdd9e62e8234839117f8fc32d17fbc000000004a493046022100a576b52051962c25e642c0fd3d77ee6c92487048e5d90818bcf5b51abaccd7900221008204f8fb121be4ec3b24483b1f92d89b1b0548513a134e345c5442e86e8617a501ffffffff010000000000000000016a00000000", "P2SH"], "010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH"],
[[["83e194f90b6ef21fa2e3a365b63794fb5daa844bdc9b25de30899fcfe7b01047", 0, "CODESEPARATOR CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIG"]], ["As above, with the IF block executed"],
"01000000014710b0e7cf9f8930de259bdc4b84aa5dfb9437b665a3e3a21ff26e0bf994e183000000004a493046022100a166121a61b4eeb19d8f922b978ff6ab58ead8a5a5552bf9be73dc9c156873ea02210092ad9bc43ee647da4f6652c320800debcf08ec20a094a0aaf085f63ecb37a17201ffffffff010000000000000000016a00000000", "P2SH"], [[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH"],
["Hashed data starts at the CODESEPARATOR"], ["CHECKSIG is legal in scriptSigs"],
[[["326882a7f22b5191f1a0cc9962ca4b878cd969cf3b3a70887aece4d801a0ba5e", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CODESEPARATOR CHECKSIG"]], [[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"01000000015ebaa001d8e4ec7a88703a3bcf69d98c874bca6299cca0f191512bf2a7826832000000004948304502203bf754d1c6732fbf87c5dcd81258aefd30f2060d7bd8ac4a5696f7927091dad1022100f5bcb726c4cf5ed0ed34cc13dadeedf628ae1045b7cb34421bc60b89f4cecae701ffffffff010000000000000000016a00000000", "P2SH"], "0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
["Same semantics for OP_CODESEPARATOR"],
["But only if execution has reached it"], [[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 0x21 0x038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041 CHECKSIGVERIFY CODESEPARATOR 1"]], "01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a900000000924830450221009c0a27f886a1d8cb87f6f595fbc3163d28f7a81ec3c4b252ee7f3ac77fd13ffa02203caa8dfa09713c8c4d7ef575c75ed97812072405d932bd11e6a1593a98b679370148304502201e3861ef39a526406bad1e20ecad06be7375ad40ddb582c9be42d26c3a0d7b240221009d0a3985e96522e59635d19cc4448547477396ce0ef17a58e7d74c3ef464292301ffffffff010000000000000000016a00000000", "P2SH"], ["Signatures are removed from the script they are in by FindAndDelete() in the CHECKSIG code; even multiple instances of one signature can be removed."],
[[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
["CODESEPARATOR in an unexecuted IF block does not change what is hashed"], "01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], ["That also includes ahead of the opcode being executed."],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a48304502207a6974a77c591fa13dff60cabbb85a0de9e025c09c65a4b2285e47ce8e22f761022100f0efaac9ff8ac36b10721e0aae1fb975c90500b50c56e8a0cc52b0403f0425dd0100ffffffff010000000000000000016a00000000", "P2SH"], [[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
["As above, with the IF block executed"], ["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."],
[[["a955032f4d6b0c9bfe8cad8f00a8933790b9c1dc28c82e0f48e75b35da0e4944", 0, "IF CODESEPARATOR ENDIF 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 CHECKSIGVERIFY CODESEPARATOR 1"]], ["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"],
"010000000144490eda355be7480f2ec828dcc1b9903793a8008fad8cfe9b0c6b4d2f0355a9000000004a483045022100fa4a74ba9fd59c59f46c3960cf90cbe0d2b743c471d24a3d5d6db6002af5eebb02204d70ec490fd0f7055a7c45f86514336e3a7f03503dacecabb247fc23f15c83510151ffffffff010000000000000000016a00000000", "P2SH"], [[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
["CHECKSIG is legal in scriptSigs"],
[[["ccf7f4053a02e653c36ac75c891b7496d0dc5ce5214f6c913d9cf8f1329ebee0", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"0100000001e0be9e32f1f89c3d916c4f21e55cdcd096741b895cc76ac353e6023a05f4f7cc00000000d86149304602210086e5f736a2c3622ebb62bd9d93d8e5d76508b98be922b97160edc3dcca6d8c47022100b23c312ac232a4473f19d2aeb95ab7bdf2b65518911a0d72d50e38b5dd31dc820121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac4730440220508fa761865c8abd81244a168392876ee1d94e8ed83897066b5e2df2400dad24022043f5ee7538e87e9c6aef7ef55133d3e51da7cc522830a9c4d736977a76ef755c0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
["Same semantics for OP_CODESEPARATOR"],
[[["10c9f0effe83e97f80f067de2b11c6a00c3088a4bce42c5ae761519af9306f3c", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"01000000013c6f30f99a5161e75a2ce4bca488300ca0c6112bde67f0807fe983feeff0c91001000000e608646561646265656675ab61493046022100ce18d384221a731c993939015e3d1bcebafb16e8c0b5b5d14097ec8177ae6f28022100bcab227af90bab33c3fe0a9abfee03ba976ee25dc6ce542526e9b2e56e14b7f10121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac493046022100c3b93edcc0fd6250eb32f2dd8a0bba1754b0f6c3be8ed4100ed582f3db73eba2022100bf75b5bd2eff4d6bf2bda2e34a40fcc07d4aa3cf862ceaa77b47b81eff829f9a01ab21038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
["Signatures are removed from the script they are in by FindAndDelete() in the CHECKSIG code; even multiple instances of one signature can be removed."],
[[["6056ebd549003b10cbbd915cea0d82209fe40b8617104be917a26fa92cbe3d6f", 0, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"01000000016f3dbe2ca96fa217e94b1017860be49f20820dea5c91bdcb103b0049d5eb566000000000fd1d0147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140147304402203989ac8f9ad36b5d0919d97fa0a7f70c5272abee3b14477dc646288a8b976df5022027d19da84a066af9053ad3d1d7459d171b7e3a80bc6c4ef7a330677a6be548140121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ac47304402203757e937ba807e4a5da8534c17f9d121176056406a6465054bdd260457515c1a02200f02eccf1bec0f3a0d65df37889143c2e88ab7acec61a7b6f5aa264139141a2b0121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
["That also includes ahead of the opcode being executed."],
[[["5a6b0021a6042a686b6b94abc36b387bef9109847774e8b1e51eb8cc55c53921", 1, "DUP HASH160 0x14 0xee5a6aa40facefb2655ac23c0c28c57c65c41f9b EQUALVERIFY CHECKSIG"]],
"01000000012139c555ccb81ee5b1e87477840991ef7b386bc3ab946b6b682a04a621006b5a01000000fdb40148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390121038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f2204148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a5800390175ac4830450220646b72c35beeec51f4d5bc1cbae01863825750d7f490864af354e6ea4f625e9c022100f04b98432df3a9641719dbced53393022e7249fb59db993af1118539830aab870148304502201723e692e5f409a7151db386291b63524c5eb2030df652b1f53022fd8207349f022100b90d9bbf2f3366ce176e5e780a00433da67d9e5c79312c6388312a296a580039017521038479a0fa998cd35259a2ef0a7a5c68662c1474f88ccb6d08a7677bbec7f22041ffffffff010000000000000000016a00000000", "P2SH"],
["Finally CHECKMULTISIG removes all signatures prior to hashing the script containing those signatures. In conjunction with the SIGHASH_SINGLE bug this lets us test whether or not FindAndDelete() is actually present in scriptPubKey/redeemScript evaluation by including a signature of the digest 0x01 We can compute in advance for our pubkey, embed it it in the scriptPubKey, and then also using a normal SIGHASH_ALL signature. If FindAndDelete() wasn't run, the 'bugged' signature would still be in the hashed script, and the normal signature would fail."],
["Here's an example on mainnet within a P2SH redeemScript. Remarkably it's a standard transaction in <0.9"],
[[["b5b598de91787439afd5938116654e0b16b7a0d0f82742ba37564219c5afcbf9", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]], ["ab9805c6d57d7070d9a42c5176e47bb705023e6b67249fb6760880548298e742", 0, "HASH160 0x14 0xd8dacdadb7462ae15cd906f1878706d0da8660e6 EQUAL"]],
"0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH"], "0100000002f9cbafc519425637ba4227f8d0a0b7160b4e65168193d5af39747891de98b5b5000000006b4830450221008dd619c563e527c47d9bd53534a770b102e40faa87f61433580e04e271ef2f960220029886434e18122b53d5decd25f1f4acb2480659fea20aabd856987ba3c3907e0121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffff42e7988254800876b69f24676b3e0205b77be476512ca4d970707dd5c60598ab00000000fd260100483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a53034930460221008431bdfa72bc67f9d41fe72e94c88fb8f359ffa30b33c72c121c5a877d922e1002210089ef5fc22dd8bfc6bf9ffdb01a9862d27687d424d1fefbab9e9c7176844a187a014c9052483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71210378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c7153aeffffffff01a08601000000000017a914d8dacdadb7462ae15cd906f1878706d0da8660e68700000000", "P2SH"],
["Same idea, but with bare CHECKMULTISIG"],
["Same idea, but with bare CHECKMULTISIG"], [[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
[[["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 0, "DUP HASH160 0x14 0xf6f365c40f0739b61de827a44751e5e99032ed8f EQUALVERIFY CHECKSIG"],
["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]], ["ceafe58e0f6e7d67c0409fbbf673c84c166e3c5d3c24af58f7175b18df3bb3db", 1, "2 0x48 0x3045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 0x21 0x0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71 3 CHECKMULTISIG"]],
"0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"], "0100000002dbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce000000006b4830450221009627444320dc5ef8d7f68f35010b4c050a6ed0d96b67a84db99fda9c9de58b1e02203e4b4aaa019e012e65d69b487fdf8719df72f488fa91506a80c49a33929f1fd50121022b78b756e2258af13779c1a1f37ea6800259716ca4b7f0b87610e0bf3ab52a01ffffffffdbb33bdf185b17f758af243c5d3c6e164cc873f6bb9f40c0677d6e0f8ee5afce010000009300483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303483045022015bd0139bcccf990a6af6ec5c1c52ed8222e03a0d51c334df139968525d2fcd20221009f9efe325476eb64c3958e4713e9eefe49bf1d820ed58d2112721b134e2a1a5303ffffffff01a0860100000000001976a9149bc0bbdd3024da4d0c38ed1aecf5c68dd1d3fa1288ac00000000", "P2SH"],
["CHECKLOCKTIMEVERIFY tests"],
["By-height locks, with argument == 0 and == tx nLockTime"],
["CHECKLOCKTIMEVERIFY tests"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
["By-height locks, with argument == 0 and == tx nLockTime"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 CHECKLOCKTIMEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 CHECKLOCKTIMEVERIFY 1"]], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], ["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ff64cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKLOCKTIMEVERIFY 1"]],
["By-time locks, with argument just beyond tx nLockTime (but within numerical boundaries)"], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKLOCKTIMEVERIFY 1"]], ["Any non-maxint nSequence is fine"],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "500000000 CHECKLOCKTIMEVERIFY 1"]], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000ffffffff", "P2SH,CHECKLOCKTIMEVERIFY"], ["The argument can be calculated rather than created directly by a PUSHDATA"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 1ADD CHECKLOCKTIMEVERIFY 1"]],
["Any non-maxint nSequence is fine"], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKLOCKTIMEVERIFY 1"]], ["Perhaps even by an ADD producing a 5-byte result that is out of bounds for other opcodes"],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 2147483647 ADD CHECKLOCKTIMEVERIFY 1"]],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"],
["The argument can be calculated rather than created directly by a PUSHDATA"], ["5 byte non-minimally-encoded arguments are valid"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "499999999 1ADD CHECKLOCKTIMEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKLOCKTIMEVERIFY 1"]],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000065cd1d", "P2SH,CHECKLOCKTIMEVERIFY"], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"],
["Valid CHECKLOCKTIMEVERIFY in scriptSig"],
["Perhaps even by an ADD producing a 5-byte result that is out of bounds for other opcodes"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 2147483647 ADD CHECKLOCKTIMEVERIFY 1"]], "01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000feffffff", "P2SH,CHECKLOCKTIMEVERIFY"], ["Valid CHECKLOCKTIMEVERIFY in redeemScript"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]],
["5 byte non-minimally-encoded arguments are valid"], "0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKLOCKTIMEVERIFY 1"]], ["A transaction with a non-standard DER signature."],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKLOCKTIMEVERIFY"], [[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]],
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"],
["Valid CHECKLOCKTIMEVERIFY in scriptSig"], ["CHECKSEQUENCEVERIFY tests"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]], ["By-height locks, with argument == 0 and == txin.nSequence"],
"01000000010001000000000000000000000000000000000000000000000000000000000000000000000251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Valid CHECKLOCKTIMEVERIFY in redeemScript"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xc5b93064159b3b2d6ab506a41b1f50463771b988 EQUAL"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"0100000001000100000000000000000000000000000000000000000000000000000000000000000000030251b1000000000100000000000000000001000000", "P2SH,CHECKLOCKTIMEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["A transaction with a non-standard DER signature."], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]],
[[["b1dbc81696c8a9c0fccd0693ab66d7c368dbc38c0def4e800685560ddd1b2132", 0, "DUP HASH160 0x14 0x4b3bd7eba3bc0284fd3007be7f3be275e94f5826 EQUALVERIFY CHECKSIG"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"010000000132211bdd0d568506804eef0d8cc3db68c3d766ab9306cdfcc0a9c89616c8dbb1000000006c493045022100c7bb0faea0522e74ff220c20c022d2cb6033f8d167fb89e75a50e237a35fd6d202203064713491b1f8ad5f79e623d0219ad32510bfaa1009ab30cbee77b59317d6e30001210237af13eb2d84e4545af287b919c2282019c9691cc509e78e196a9d8274ed1be0ffffffff0100000000000000001976a914f1b3ed2eda9a2ebe5a9374f692877cdf87c0f95b88ac00000000", "P2SH"], ["By-time locks, with argument == 0 and == txin.nSequence"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
["CHECKSEQUENCEVERIFY tests"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
["By-height locks, with argument == 0 and == txin.nSequence"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "65535 CHECKSEQUENCEVERIFY 1"]], ["Upper sequence with upper sequence is fine"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["By-time locks, with argument == 0 and == txin.nSequence"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff40000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4259839 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument 2^31 with various nSequence"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
["Upper sequence with upper sequence is fine"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000800100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], ["Argument 2^32-1 with various nSequence"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000feffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Argument 3<<31 with various nSequence"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
["Argument 2^31 with various nSequence"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483648 CHECKSEQUENCEVERIFY 1"]], ["5 byte non-minimally-encoded operandss are valid"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument 2^32-1 with various nSequence"], ["The argument can be calculated rather than created directly by a PUSHDATA"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4294967295 CHECKSEQUENCEVERIFY 1"]], ["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 CHECKSEQUENCEVERIFY 1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["Argument 3<<31 with various nSequence"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD CHECKSEQUENCEVERIFY 1"]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], "020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffbf7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Valid CHECKSEQUENCEVERIFY in scriptSig"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffff7f0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "6442450944 CHECKSEQUENCEVERIFY 1"]], ["Valid CHECKSEQUENCEVERIFY in redeemScript"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff0100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]],
"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"],
["5 byte non-minimally-encoded operandss are valid"], ["Valid P2WPKH (Private key of segwit tests is L5AQtV2HDm4xGsseLokK2VAT2EtYKcTm3c7HwqnJBFt9LdaQULsM)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x05 0x0000000000 CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
["Valid P2WSH"],
["The argument can be calculated rather than created directly by a PUSHDATA"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db", 1000]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194303 1ADD CHECKSEQUENCEVERIFY 1"]], "0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Valid P2SH(P2WPKH)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "4194304 1SUB CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xfe9c7dacc9fcfbf7e3b7d5ad06aa2b28c5a7b7e3 EQUAL", 1000]],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000ffff00000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "01000000000101000100000000000000000000000000000000000000000000000000000000000000000000171600144c9c3dfac4207d5d8cb89df5722cb3d712385e3fffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
["Valid P2SH(P2WSH)"],
["An ADD producing a 5-byte result that sets CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x2135ab4f0981830311e35600eebc7376dce3a914 EQUAL", 1000]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 65536 CHECKSEQUENCEVERIFY 1"]], "0100000000010100010000000000000000000000000000000000000000000000000000000000000000000023220020ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Witness with SigHash Single|AnyoneCanPay"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "2147483647 4259840 ADD CHECKSEQUENCEVERIFY 1"]], [[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
"020000000100010000000000000000000000000000000000000000000000000000000000000000000000000040000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
["Valid CHECKSEQUENCEVERIFY in scriptSig"], ["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "1"]], "0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff05540b0000000000000151d0070000000000000151840300000000000001513c0f00000000000001512c010000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71000000000000", "P2SH,WITNESS"],
"02000000010001000000000000000000000000000000000000000000000000000000000000000000000251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], ["Witness with SigHash Single|AnyoneCanPay (same signature as previous)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
["Valid CHECKSEQUENCEVERIFY in redeemScript"], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7c17aff532f22beb54069942f9bf567a66133eaf EQUAL"]], ["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
"0200000001000100000000000000000000000000000000000000000000000000000000000000000000030251b2010000000100000000000000000000000000", "P2SH,CHECKSEQUENCEVERIFY"], "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["Witness with SigHash Single"],
["Valid P2WPKH (Private key of segwit tests is L5AQtV2HDm4xGsseLokK2VAT2EtYKcTm3c7HwqnJBFt9LdaQULsM)"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff0484030000000000000151d0070000000000000151540b0000000000000151c800000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["Valid P2WSH"], ["Witness with SigHash Single (same signature as previous)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3db", 1000]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
["Valid P2SH(P2WPKH)"], "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xfe9c7dacc9fcfbf7e3b7d5ad06aa2b28c5a7b7e3 EQUAL", 1000]], ["Witness with SigHash None|AnyoneCanPay"],
"01000000000101000100000000000000000000000000000000000000000000000000000000000000000000171600144c9c3dfac4207d5d8cb89df5722cb3d712385e3fffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100cfb07164b36ba64c1b1e8c7720a56ad64d96f6ef332d3d37f9cb3c96477dc44502200a464cd7a9cf94cd70f66ce4f4f0625ef650052c7afcfe29d7d7e01830ff91ed012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"], [[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
["Valid P2SH(P2WSH)"], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x2135ab4f0981830311e35600eebc7376dce3a914 EQUAL", 1000]], ["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000023220020ff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbffffffff01e8030000000000001976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac02483045022100aa5d8aa40a90f23ce2c3d11bc845ca4a12acd99cbea37de6b9f6d86edebba8cb022022dedc2aa0a255f74d04c0b76ece2d7c691f9dd11a64a8ac49f62a99c3a05f9d01232103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ac00000000", "P2SH,WITNESS"], "0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff04b60300000000000001519e070000000000000151860b00000000000001009600000000000000015100000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["Witness with SigHash None|AnyoneCanPay (same signature as previous)"],
["Witness with SigHash Single|AnyoneCanPay"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
[[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], ["Witness with SigHash None"],
"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff05540b0000000000000151d0070000000000000151840300000000000001513c0f00000000000001512c010000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71000000000000", "P2SH,WITNESS"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
["Witness with SigHash Single|AnyoneCanPay (same signature as previous)"], ["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["Witness with SigHash None (same signature as previous)"],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210092f4777a0f17bf5aeb8ae768dec5f2c14feabf9d1fe2c89c78dfed0f13fdb86902206da90a86042e252bcd1e80a168c719e4a1ddcc3cebea24b9812c5453c79107e9832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
["Witness with SigHash Single"], "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], ["Witness with SigHash None (same signature, only sequences changed)"],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff0484030000000000000151d0070000000000000151540b0000000000000151c800000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
"01000000000103000100000000000000000000000000000000000000000000000000000000000000000000000200000000010000000000000000000000000000000000000000000000000000000000000100000000ffffffff000100000000000000000000000000000000000000000000000000000000000002000000000200000003e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["Witness with SigHash Single (same signature as previous)"], ["Witness with SigHash All|AnyoneCanPay"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], [[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b000000000000015100024730440220699e6b0cfe015b64ca3283e6551440a34f901ba62dd4c72fe1cb815afb2e6761022021cc5e84db498b1479de14efda49093219441adc6c543e5534979605e273d80b032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]],
"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["Witness with SigHash None|AnyoneCanPay"], ["Witness with SigHash All|AnyoneCanPay (same signature as previous)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff04b60300000000000001519e070000000000000151860b00000000000001009600000000000000015100000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], ["Unknown witness program version (without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
["Witness with SigHash None|AnyoneCanPay (same signature as previous)"], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], ["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], "0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], ["Witness with a push of 520 bytes"],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000248304502210091b32274295c2a3fa02f5bce92fb2789e3fc6ea947fbe1a76e52ea3f4ef2381a022079ad72aefa3837a2e0c033a8652a59731da05fa4a813f4fc48e87c075037256b822103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]],
"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"],
["Witness with SigHash None"], ["Transaction mixing all SigHash, segwit and normal inputs"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], ["0000000000000000000000000000000000000000000000000000000000000100", 2, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1002],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff04b60300000000000001519e070000000000000151860b0000000000000100960000000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 3, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1003],
["0000000000000000000000000000000000000000000000000000000000000100", 4, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1004],
["Witness with SigHash None (same signature as previous)"], ["0000000000000000000000000000000000000000000000000000000000000100", 5, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1005],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], ["0000000000000000000000000000000000000000000000000000000000000100", 6, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1006],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["0000000000000000000000000000000000000000000000000000000000000100", 7, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1007],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], ["0000000000000000000000000000000000000000000000000000000000000100", 8, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1008],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 9, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1009],
["0000000000000000000000000000000000000000000000000000000000000100", 10, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1010],
["Witness with SigHash None (same signature, only sequences changed)"], ["0000000000000000000000000000000000000000000000000000000000000100", 11, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1011]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], "0100000000010c00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff0001000000000000000000000000000000000000000000000000000000000000020000006a473044022026c2e65b33fcd03b2a3b0f25030f0244bd23cc45ae4dec0f48ae62255b1998a00220463aa3982b718d593a6b9e0044513fd67a5009c2fdccc59992cffc2b167889f4012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000030000006a4730440220008bd8382911218dcb4c9f2e75bf5c5c3635f2f2df49b36994fde85b0be21a1a02205a539ef10fb4c778b522c1be852352ea06c67ab74200977c722b0bc68972575a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000040000006b483045022100d9436c32ff065127d71e1a20e319e4fe0a103ba0272743dbd8580be4659ab5d302203fd62571ee1fe790b182d078ecfd092a509eac112bea558d122974ef9cc012c7012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000050000006a47304402200e2c149b114ec546015c13b2b464bbcb0cdc5872e6775787527af6cbc4830b6c02207e9396c6979fb15a9a2b96ca08a633866eaf20dc0ff3c03e512c1d5a1654f148012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000060000006b483045022100b20e70d897dc15420bccb5e0d3e208d27bdd676af109abbd3f88dbdb7721e6d6022005836e663173fbdfe069f54cde3c2decd3d0ea84378092a5d9d85ec8642e8a41012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff00010000000000000000000000000000000000000000000000000000000000000700000000ffffffff00010000000000000000000000000000000000000000000000000000000000000800000000ffffffff00010000000000000000000000000000000000000000000000000000000000000900000000ffffffff00010000000000000000000000000000000000000000000000000000000000000a00000000ffffffff00010000000000000000000000000000000000000000000000000000000000000b0000006a47304402206639c6e05e3b9d2675a7f3876286bdf7584fe2bbd15e0ce52dd4e02c0092cdc60220757d60b0a61fc95ada79d23746744c72bac1545a75ff6c2c7cdb6ae04e7e9592012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0ce8030000000000000151e9030000000000000151ea030000000000000151eb030000000000000151ec030000000000000151ed030000000000000151ee030000000000000151ef030000000000000151f0030000000000000151f1030000000000000151f2030000000000000151f30300000000000001510248304502210082219a54f61bf126bfc3fa068c6e33831222d1d7138c6faa9d33ca87fd4202d6022063f9902519624254d7c2c8ea7ba2d66ae975e4e229ae38043973ec707d5d4a83012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022017fb58502475848c1b09f162cb1688d0920ff7f142bed0ef904da2ccc88b168f02201798afa61850c65e77889cbcd648a5703b487895517c88f85cdd18b021ee246a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000000247304402202830b7926e488da75782c81a54cd281720890d1af064629ebf2e31bf9f5435f30220089afaa8b455bbeb7d9b9c3fe1ed37d07685ade8455c76472cda424d93e4074a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022026326fcdae9207b596c2b05921dbac11d81040c4d40378513670f19d9f4af893022034ecd7a282c0163b89aaa62c22ec202cef4736c58cd251649bad0d8139bcbf55012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71024730440220214978daeb2f38cd426ee6e2f44131a33d6b191af1c216247f1dd7d74c16d84a02205fdc05529b0bc0c430b4d5987264d9d075351c4f4484c16e91662e90a72aab24012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402204a6e9f199dc9672cf2ff8094aaa784363be1eb62b679f7ff2df361124f1dca3302205eeb11f70fab5355c9c8ad1a0700ea355d315e334822fa182227e9815308ee8f012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["Unknown version witness program with empty witness"],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
"01000000000103000100000000000000000000000000000000000000000000000000000000000000000000000200000000010000000000000000000000000000000000000000000000000000000000000100000000ffffffff000100000000000000000000000000000000000000000000000000000000000002000000000200000003e8030000000000000151d0070000000000000151b80b00000000000001510002473044022022fceb54f62f8feea77faac7083c3b56c4676a78f93745adc8a35800bc36adfa022026927df9abcf0a8777829bcfcce3ff0a385fa54c3f9df577405e3ef24ee56479022103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS"],
["Witness SIGHASH_SINGLE with output out of bound"],
["Witness with SigHash All|AnyoneCanPay"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000],
[[["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3100], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x20 0x4d6c2a32c87821d68fc016fca70797abdb80df6cd84651d40a9300c6bad79e62", 1000]],
["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1100], "0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff01d00700000000000001510003483045022100e078de4e96a0e05dcdc0a414124dd8475782b5f3f0ed3f607919e9a5eeeb22bf02201de309b3a3109adb3de8074b3610d4cf454c49b61247a2779a0bcbf31c889333032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc711976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac00000000", "P2SH,WITNESS"],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["1 byte push should not be considered a witness scriptPubKey"],
["0000000000000000000000000000000000000000000000000000000000000100", 3, "0x51", 4100]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x01 0x01", 1000]],
"0100000000010400010000000000000000000000000000000000000000000000000000000000000200000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000300000000ffffffff03e8030000000000000151d0070000000000000151b80b0000000000000151000002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
["41 bytes push should not be considered a witness scriptPubKey"],
["Witness with SigHash All|AnyoneCanPay (same signature as previous)"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x29 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff0000000000000000", 1000]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["The witness version must use OP_1 to OP_16 only"],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x01 0x10 0x02 0x0001", 1000]],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623eeef89e0ba1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
["The witness program push must be canonical"],
["Unknown witness program version (without DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)"], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x4c02 0x0001", 1000]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], "010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 2000], ["Witness Single|AnyoneCanPay does not hash input's position"],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "0x51", 3000]], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000],
"0100000000010300010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000200000000ffffffff03e8030000000000000151d0070000000000000151b80b00000000000001510002483045022100a3cec69b52cba2d2de623ffffffffff1606184ea55476c0f8189fda231bc9cbb022003181ad597f7c380a7d1c740286b1d022b8b04ded028b833282e055e03b8efef812103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001]],
"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff02e8030000000000000151e90300000000000001510247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
["Witness with a push of 520 bytes"], ["Witness Single|AnyoneCanPay does not hash input's position (permutation)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x20 0x33198a9bfef674ebddb9ffaa52928017b8472791e54c609cb95f278ac6b1e349", 1000]], [[["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001],
"0100000000010100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff010000000000000000015102fd08020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002755100000000", "P2SH,WITNESS"], ["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
"0100000000010200010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff02e9030000000000000151e80300000000000001510248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
["Transaction mixing all SigHash, segwit and normal inputs"], ["Non witness Single|AnyoneCanPay hash input's position"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000], [[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001], ["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]],
["0000000000000000000000000000000000000000000000000000000000000100", 2, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1002], "01000000020001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff00010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff02e8030000000000000151e903000000000000015100000000", "P2SH,WITNESS"],
["0000000000000000000000000000000000000000000000000000000000000100", 3, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1003], ["BIP143 examples: details and private keys are available in BIP143"],
["0000000000000000000000000000000000000000000000000000000000000100", 4, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1004], ["BIP143 example: P2WSH with OP_CODESEPARATOR and out-of-range SIGHASH_SINGLE."],
["0000000000000000000000000000000000000000000000000000000000000100", 5, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1005], [[["6eb316926b1c5d567cd6f5e6a84fec606fc53d7b474526d1fff3948020c93dfe", 0, "0x21 0x036d5c20fa14fb2f635474c1dc4ef5909d4568e5569b79fc94d3448486e14685f8 CHECKSIG", 156250000],
["0000000000000000000000000000000000000000000000000000000000000100", 6, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1006], ["f825690aee1b3dc247da796cacb12687a5e802429fd291cfd63e010f02cf1508", 0, "0x00 0x20 0x5d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0", 4900000000]],
["0000000000000000000000000000000000000000000000000000000000000100", 7, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1007], "01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000", "P2SH,WITNESS"],
["0000000000000000000000000000000000000000000000000000000000000100", 8, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1008], ["BIP143 example: P2WSH with unexecuted OP_CODESEPARATOR and SINGLE|ANYONECANPAY"],
["0000000000000000000000000000000000000000000000000000000000000100", 9, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1009], [[["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215],
["0000000000000000000000000000000000000000000000000000000000000100", 10, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1010], ["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215]],
["0000000000000000000000000000000000000000000000000000000000000100", 11, "DUP HASH160 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f EQUALVERIFY CHECKSIG", 1011]], "01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"],
"0100000000010c00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff0001000000000000000000000000000000000000000000000000000000000000020000006a473044022026c2e65b33fcd03b2a3b0f25030f0244bd23cc45ae4dec0f48ae62255b1998a00220463aa3982b718d593a6b9e0044513fd67a5009c2fdccc59992cffc2b167889f4012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000030000006a4730440220008bd8382911218dcb4c9f2e75bf5c5c3635f2f2df49b36994fde85b0be21a1a02205a539ef10fb4c778b522c1be852352ea06c67ab74200977c722b0bc68972575a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000040000006b483045022100d9436c32ff065127d71e1a20e319e4fe0a103ba0272743dbd8580be4659ab5d302203fd62571ee1fe790b182d078ecfd092a509eac112bea558d122974ef9cc012c7012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000050000006a47304402200e2c149b114ec546015c13b2b464bbcb0cdc5872e6775787527af6cbc4830b6c02207e9396c6979fb15a9a2b96ca08a633866eaf20dc0ff3c03e512c1d5a1654f148012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0001000000000000000000000000000000000000000000000000000000000000060000006b483045022100b20e70d897dc15420bccb5e0d3e208d27bdd676af109abbd3f88dbdb7721e6d6022005836e663173fbdfe069f54cde3c2decd3d0ea84378092a5d9d85ec8642e8a41012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff00010000000000000000000000000000000000000000000000000000000000000700000000ffffffff00010000000000000000000000000000000000000000000000000000000000000800000000ffffffff00010000000000000000000000000000000000000000000000000000000000000900000000ffffffff00010000000000000000000000000000000000000000000000000000000000000a00000000ffffffff00010000000000000000000000000000000000000000000000000000000000000b0000006a47304402206639c6e05e3b9d2675a7f3876286bdf7584fe2bbd15e0ce52dd4e02c0092cdc60220757d60b0a61fc95ada79d23746744c72bac1545a75ff6c2c7cdb6ae04e7e9592012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71ffffffff0ce8030000000000000151e9030000000000000151ea030000000000000151eb030000000000000151ec030000000000000151ed030000000000000151ee030000000000000151ef030000000000000151f0030000000000000151f1030000000000000151f2030000000000000151f30300000000000001510248304502210082219a54f61bf126bfc3fa068c6e33831222d1d7138c6faa9d33ca87fd4202d6022063f9902519624254d7c2c8ea7ba2d66ae975e4e229ae38043973ec707d5d4a83012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022017fb58502475848c1b09f162cb1688d0920ff7f142bed0ef904da2ccc88b168f02201798afa61850c65e77889cbcd648a5703b487895517c88f85cdd18b021ee246a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000000247304402202830b7926e488da75782c81a54cd281720890d1af064629ebf2e31bf9f5435f30220089afaa8b455bbeb7d9b9c3fe1ed37d07685ade8455c76472cda424d93e4074a012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7102473044022026326fcdae9207b596c2b05921dbac11d81040c4d40378513670f19d9f4af893022034ecd7a282c0163b89aaa62c22ec202cef4736c58cd251649bad0d8139bcbf55012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71024730440220214978daeb2f38cd426ee6e2f44131a33d6b191af1c216247f1dd7d74c16d84a02205fdc05529b0bc0c430b4d5987264d9d075351c4f4484c16e91662e90a72aab24012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402204a6e9f199dc9672cf2ff8094aaa784363be1eb62b679f7ff2df361124f1dca3302205eeb11f70fab5355c9c8ad1a0700ea355d315e334822fa182227e9815308ee8f012103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710000000000", "P2SH,WITNESS"], ["BIP143 example: Same as the previous example with input-output paris swapped"],
[[["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215],
["Unknown version witness program with empty witness"], ["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]], "0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS"], ["BIP143 example: P2SH-P2WSH 6-of-6 multisig signed with 6 different SIGHASH types"],
[[["6eb98797a21c6c10aa74edf29d618be109f48a8e94c694f3701e08ca69186436", 1, "HASH160 0x14 0x9993a429037b5d912407a71c252019287b8d27a5 EQUAL", 987654321]],
["Witness SIGHASH_SINGLE with output out of bound"], "0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", "P2SH,WITNESS"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x51", 1000], ["FindAndDelete tests"],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x20 0x4d6c2a32c87821d68fc016fca70797abdb80df6cd84651d40a9300c6bad79e62", 1000]], ["This is a test of FindAndDelete. The first tx is a spend of normal P2SH and the second tx is a spend of bare P2WSH."],
"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff01d00700000000000001510003483045022100e078de4e96a0e05dcdc0a414124dd8475782b5f3f0ed3f607919e9a5eeeb22bf02201de309b3a3109adb3de8074b3610d4cf454c49b61247a2779a0bcbf31c889333032103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc711976a9144c9c3dfac4207d5d8cb89df5722cb3d712385e3f88ac00000000", "P2SH,WITNESS"], ["The redeemScript/witnessScript is CHECKSIGVERIFY <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01>."],
["The signature is <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01> <pubkey>,"],
["1 byte push should not be considered a witness scriptPubKey"], ["where the pubkey is obtained through key recovery with sig and correct sighash."],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x01 0x01", 1000]], ["This is to show that FindAndDelete is applied only to non-segwit scripts"],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], ["Non-segwit: correct sighash (with FindAndDelete) = 1ba1fe3bc90c5d1265460e684ce6774e324f0fabdf67619eda729e64e8b6bc08"],
[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7000, "HASH160 0x14 0x0c746489e2d83cdbb5b90b432773342ba809c134 EQUAL", 200000]],
["41 bytes push should not be considered a witness scriptPubKey"], "010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0121037a3fb04bcdb09eba90f69961ba1692a3528e45e67c85b200df820212d7594d334aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x29 0xff25429251b5a84f452230a3c75fd886b7fc5a7865ce4a7bb7a9d7c5be6da3dbff0000000000000000", 1000]], ["BIP143: correct sighash (without FindAndDelete) = 71c9cd9b2869b9c70b01b1f0360c148f42dee72297db312638df136f43311f23"],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], [[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7500, "0x00 0x20 0x9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", 200000]],
"0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61fb5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000", "P2SH,WITNESS"],
["The witness version must use OP_1 to OP_16 only"], ["This is multisig version of the FindAndDelete tests"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x01 0x10 0x02 0x0001", 1000]], ["Script is 2 CHECKMULTISIGVERIFY <sig1> <sig2> DROP"],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], ["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"],
["Signature is 0 <sig1> <sig2> 2 <key1> <key2>"],
["The witness program push must be canonical"], ["Non-segwit: correct sighash (with FindAndDelete) = 1d50f00ba4db2917b903b0ec5002e017343bb38876398c9510570f5dce099295"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x60 0x4c02 0x0001", 1000]], [[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7000, "HASH160 0x14 0x5748407f5ca5cdca53ba30b79040260770c9ee1b EQUAL", 200000]],
"010000000100010000000000000000000000000000000000000000000000000000000000000000000000ffffffff01e803000000000000015100000000", "P2SH,WITNESS,DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM"], "01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601522102cd74a2809ffeeed0092bc124fd79836706e41f048db3f6ae9df8708cefb83a1c2102e615999372426e46fd107b76eaf007156a507584aa2cc21de9eee3bdbd26d36c4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
["BIP143: correct sighash (without FindAndDelete) = c1628a1e7c67f14ca0c27c06e4fdeec2e6d1a73c7a91d7c046ff83e835aebb72"],
["Witness Single|AnyoneCanPay does not hash input's position"], [[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7500, "0x00 0x20 0x9b66c15b4e0b4eb49fa877982cafded24859fe5b0e2dbfbe4f0df1de7743fd52", 200000]],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000], "010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960101022102966f109c54e85d3aee8321301136cedeb9fc710fdef58a9de8a73942f8e567c021034ffc99dd9a79dd3cb31e2ab3e0b09e0e67db41ac068c625cd1f491576016c84e9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS"],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001]], ["Make diffs cleaner by leaving a comment here without comma at the end"]
"0100000000010200010000000000000000000000000000000000000000000000000000000000000000000000ffffffff00010000000000000000000000000000000000000000000000000000000000000100000000ffffffff02e8030000000000000151e90300000000000001510247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
["Witness Single|AnyoneCanPay does not hash input's position (permutation)"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1001],
["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x00 0x14 0x4c9c3dfac4207d5d8cb89df5722cb3d712385e3f", 1000]],
"0100000000010200010000000000000000000000000000000000000000000000000000000000000100000000ffffffff00010000000000000000000000000000000000000000000000000000000000000000000000ffffffff02e9030000000000000151e80300000000000001510248304502210085001a820bfcbc9f9de0298af714493f8a37b3b354bfd21a7097c3e009f2018c022050a8b4dbc8155d4d04da2f5cdd575dcf8dd0108de8bec759bd897ea01ecb3af7832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc710247304402206d59682663faab5e4cb733c562e22cdae59294895929ec38d7c016621ff90da0022063ef0af5f970afe8a45ea836e3509b8847ed39463253106ac17d19c437d3d56b832103596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc7100000000", "P2SH,WITNESS"],
["Non witness Single|AnyoneCanPay hash input's position"],
[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1000],
["0000000000000000000000000000000000000000000000000000000000000100", 1, "0x21 0x03596d3451025c19dbbdeb932d6bf8bfb4ad499b95b6f88db8899efac102e5fc71 CHECKSIG", 1001]],
"01000000020001000000000000000000000000000000000000000000000000000000000000000000004847304402202a0b4b1294d70540235ae033d78e64b4897ec859c7b6f1b2b1d8a02e1d46006702201445e756d2254b0f1dfda9ab8e1e1bc26df9668077403204f32d16a49a36eb6983ffffffff00010000000000000000000000000000000000000000000000000000000000000100000049483045022100acb96cfdbda6dc94b489fd06f2d720983b5f350e31ba906cdbd800773e80b21c02200d74ea5bdf114212b4bbe9ed82c36d2e369e302dff57cb60d01c428f0bd3daab83ffffffff02e8030000000000000151e903000000000000015100000000", "P2SH,WITNESS"],
["BIP143 examples: details and private keys are available in BIP143"],
["BIP143 example: P2WSH with OP_CODESEPARATOR and out-of-range SIGHASH_SINGLE."],
[[["6eb316926b1c5d567cd6f5e6a84fec606fc53d7b474526d1fff3948020c93dfe", 0, "0x21 0x036d5c20fa14fb2f635474c1dc4ef5909d4568e5569b79fc94d3448486e14685f8 CHECKSIG", 156250000],
["f825690aee1b3dc247da796cacb12687a5e802429fd291cfd63e010f02cf1508", 0, "0x00 0x20 0x5d1b56b63d714eebe542309525f484b7e9d6f686b3781b6f61ef925d66d6f6a0", 4900000000]],
"01000000000102fe3dc9208094f3ffd12645477b3dc56f60ec4fa8e6f5d67c565d1c6b9216b36e000000004847304402200af4e47c9b9629dbecc21f73af989bdaa911f7e6f6c2e9394588a3aa68f81e9902204f3fcf6ade7e5abb1295b6774c8e0abd94ae62217367096bc02ee5e435b67da201ffffffff0815cf020f013ed6cf91d29f4202e8a58726b1ac6c79da47c23d1bee0a6925f80000000000ffffffff0100f2052a010000001976a914a30741f8145e5acadf23f751864167f32e0963f788ac000347304402200de66acf4527789bfda55fc5459e214fa6083f936b430a762c629656216805ac0220396f550692cd347171cbc1ef1f51e15282e837bb2b30860dc77c8f78bc8501e503473044022027dc95ad6b740fe5129e7e62a75dd00f291a2aeb1200b84b09d9e3789406b6c002201a9ecd315dd6a0e632ab20bbb98948bc0c6fb204f2c286963bb48517a7058e27034721026dccc749adc2a9d0d89497ac511f760f45c47dc5ed9cf352a58ac706453880aeadab210255a9626aebf5e29c0e6538428ba0d1dcf6ca98ffdf086aa8ced5e0d0215ea465ac00000000", "P2SH,WITNESS"],
["BIP143 example: P2WSH with unexecuted OP_CODESEPARATOR and SINGLE|ANYONECANPAY"],
[[["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215],
["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215]],
"01000000000102e9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff80e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffff0280969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac80969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"],
["BIP143 example: Same as the previous example with input-output paris swapped"],
[[["1b2a9a426ba603ba357ce7773cb5805cb9c7c2b386d100d1fc9263513188e680", 0, "0x00 0x20 0xd9bbfbe56af7c4b7f960a70d7ea107156913d9e5a26b0a71429df5e097ca6537", 16777215],
["01c0cf7fba650638e55eb91261b183251fbb466f90dff17f10086817c542b5e9", 0, "0x00 0x20 0xba468eea561b26301e4cf69fa34bde4ad60c81e70f059f045ca9a79931004a4d", 16777215]],
"0100000000010280e68831516392fcd100d186b3c2c7b95c80b53c77e77c35ba03a66b429a2a1b0000000000ffffffffe9b542c5176808107ff1df906f46bb1f2583b16112b95ee5380665ba7fcfc0010000000000ffffffff0280969800000000001976a9146648a8cd4531e1ec47f35916de8e259237294d1e88ac80969800000000001976a914de4b231626ef508c9a74a8517e6783c0546d6b2888ac024730440220032521802a76ad7bf74d0e2c218b72cf0cbc867066e2e53db905ba37f130397e02207709e2188ed7f08f4c952d9d13986da504502b8c3be59617e043552f506c46ff83275163ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac02483045022100f6a10b8604e6dc910194b79ccfc93e1bc0ec7c03453caaa8987f7d6c3413566002206216229ede9b4d6ec2d325be245c5b508ff0339bf1794078e20bfe0babc7ffe683270063ab68210392972e2eb617b2388771abe27235fd5ac44af8e61693261550447a4c3e39da98ac00000000", "P2SH,WITNESS"],
["BIP143 example: P2SH-P2WSH 6-of-6 multisig signed with 6 different SIGHASH types"],
[[["6eb98797a21c6c10aa74edf29d618be109f48a8e94c694f3701e08ca69186436", 1, "HASH160 0x14 0x9993a429037b5d912407a71c252019287b8d27a5 EQUAL", 987654321]],
"0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", "P2SH,WITNESS"],
["FindAndDelete tests"],
["This is a test of FindAndDelete. The first tx is a spend of normal P2SH and the second tx is a spend of bare P2WSH."],
["The redeemScript/witnessScript is CHECKSIGVERIFY <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01>."],
["The signature is <0x30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01> <pubkey>,"],
["where the pubkey is obtained through key recovery with sig and correct sighash."],
["This is to show that FindAndDelete is applied only to non-segwit scripts"],
["Non-segwit: correct sighash (with FindAndDelete) = 1ba1fe3bc90c5d1265460e684ce6774e324f0fabdf67619eda729e64e8b6bc08"],
[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7000, "HASH160 0x14 0x0c746489e2d83cdbb5b90b432773342ba809c134 EQUAL", 200000]],
"010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f1581b0000b64830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0121037a3fb04bcdb09eba90f69961ba1692a3528e45e67c85b200df820212d7594d334aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e01ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
["BIP143: correct sighash (without FindAndDelete) = 71c9cd9b2869b9c70b01b1f0360c148f42dee72297db312638df136f43311f23"],
[[["f18783ace138abac5d3a7a5cf08e88fe6912f267ef936452e0c27d090621c169", 7500, "0x00 0x20 0x9e1be07558ea5cc8e02ed1d80c0911048afad949affa36d5c3951e3159dbea19", 200000]],
"0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61fb5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000", "P2SH,WITNESS"],
["This is multisig version of the FindAndDelete tests"],
["Script is 2 CHECKMULTISIGVERIFY <sig1> <sig2> DROP"],
["52af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175"],
["Signature is 0 <sig1> <sig2> 2 <key1> <key2>"],
["Non-segwit: correct sighash (with FindAndDelete) = 1d50f00ba4db2917b903b0ec5002e017343bb38876398c9510570f5dce099295"],
[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7000, "HASH160 0x14 0x5748407f5ca5cdca53ba30b79040260770c9ee1b EQUAL", 200000]],
"01000000019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a662896581b0000fd6f01004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c03959601522102cd74a2809ffeeed0092bc124fd79836706e41f048db3f6ae9df8708cefb83a1c2102e615999372426e46fd107b76eaf007156a507584aa2cc21de9eee3bdbd26d36c4c9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960175ffffffff0101000000000000000000000000", "P2SH,WITNESS"],
["BIP143: correct sighash (without FindAndDelete) = c1628a1e7c67f14ca0c27c06e4fdeec2e6d1a73c7a91d7c046ff83e835aebb72"],
[[["9628667ad48219a169b41b020800162287d2c0f713c04157e95c484a8dcb7592", 7500, "0x00 0x20 0x9b66c15b4e0b4eb49fa877982cafded24859fe5b0e2dbfbe4f0df1de7743fd52", 200000]],
"010000000001019275cb8d4a485ce95741c013f7c0d28722160008021bb469a11982d47a6628964c1d000000ffffffff0101000000000000000007004830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c0395960101022102966f109c54e85d3aee8321301136cedeb9fc710fdef58a9de8a73942f8e567c021034ffc99dd9a79dd3cb31e2ab3e0b09e0e67db41ac068c625cd1f491576016c84e9552af4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0148304502205286f726690b2e9b0207f0345711e63fa7012045b9eb0f19c2458ce1db90cf43022100e89f17f86abc5b149eba4115d4f128bcf45d77fb3ecdd34f594091340c039596017500000000", "P2SH,WITNESS"],
["Make diffs cleaner by leaving a comment here without comma at the end"]
] ]

4
test/fixtures/embed.json

@ -48,8 +48,8 @@
], ],
"dynamic": { "dynamic": {
"depends": { "depends": {
"data": [ "data", "output" ], "data": ["data", "output"],
"output": [ "output", "data" ] "output": ["output", "data"]
}, },
"details": [ "details": [
{ {

14
test/fixtures/p2ms.json

@ -365,13 +365,13 @@
], ],
"dynamic": { "dynamic": {
"depends": { "depends": {
"m": [ "output" ], "m": ["output"],
"n": [ "output", [ "m", "pubkeys" ] ], "n": ["output", ["m", "pubkeys"]],
"output": [ "output", [ "m", "pubkeys" ] ], "output": ["output", ["m", "pubkeys"]],
"pubkeys": [ "output" ], "pubkeys": ["output"],
"signatures": [ ["input", "output"] ], "signatures": [["input", "output"]],
"input": [ ["signatures", "output"] ], "input": [["signatures", "output"]],
"witness": [ ["input", "output"] ] "witness": [["input", "output"]]
}, },
"details": [ "details": [
{ {

10
test/fixtures/p2pk.json

@ -135,11 +135,11 @@
], ],
"dynamic": { "dynamic": {
"depends": { "depends": {
"output": [ "pubkey" ], "output": ["pubkey"],
"pubkey": [ "output" ], "pubkey": ["output"],
"signature": [ ["input", "output"] ], "signature": [["input", "output"]],
"input": [ ["signature", "output"] ], "input": [["signature", "output"]],
"witness": [ ["input", "output"] ] "witness": [["input", "output"]]
}, },
"details": [ "details": [
{ {

14
test/fixtures/p2pkh.json

@ -217,13 +217,13 @@
], ],
"dynamic": { "dynamic": {
"depends": { "depends": {
"address": [ "address", "output", "hash", "pubkey", "input" ], "address": ["address", "output", "hash", "pubkey", "input"],
"hash": [ "address", "output", "hash", "pubkey", "input" ], "hash": ["address", "output", "hash", "pubkey", "input"],
"output": [ "address", "output", "hash", "pubkey", "input" ], "output": ["address", "output", "hash", "pubkey", "input"],
"pubkey": [ "input" ], "pubkey": ["input"],
"signature": [ "input" ], "signature": ["input"],
"input": [ [ "pubkey", "signature" ] ], "input": [["pubkey", "signature"]],
"witness": [ "input" ] "witness": ["input"]
}, },
"details": [ "details": [
{ {

16
test/fixtures/p2sh.json

@ -370,14 +370,14 @@
], ],
"dynamic": { "dynamic": {
"depends": { "depends": {
"address": [ "address", "output", "hash", "redeem.output", [ "input", "witness" ] ], "address": ["address", "output", "hash", "redeem.output", ["input", "witness"]],
"hash": [ "address", "output", "hash", "redeem.output", [ "input", "witness" ] ], "hash": ["address", "output", "hash", "redeem.output", ["input", "witness"]],
"output": [ "address", "output", "hash", "redeem.output", [ "input", "witness" ] ], "output": ["address", "output", "hash", "redeem.output", ["input", "witness"]],
"redeem.output": [ [ "input", "witness" ] ], "redeem.output": [["input", "witness"]],
"redeem.input": [ [ "input", "witness" ] ], "redeem.input": [["input", "witness"]],
"redeem.witness": [ [ "input", "witness" ] ], "redeem.witness": [["input", "witness"]],
"input": [ "redeem" ], "input": ["redeem"],
"witness": [ "redeem" ] "witness": ["redeem"]
}, },
"details": [ "details": [
{ {

14
test/fixtures/p2wpkh.json

@ -201,13 +201,13 @@
], ],
"dynamic": { "dynamic": {
"depends": { "depends": {
"address": [ "address", "output", "hash", "pubkey", "witness" ], "address": ["address", "output", "hash", "pubkey", "witness"],
"hash": [ "address", "output", "hash", "pubkey", "witness" ], "hash": ["address", "output", "hash", "pubkey", "witness"],
"output": [ "address", "output", "hash", "pubkey", "witness" ], "output": ["address", "output", "hash", "pubkey", "witness"],
"pubkey": [ "witness" ], "pubkey": ["witness"],
"signature": [ "witness" ], "signature": ["witness"],
"input": [ "witness" ], "input": ["witness"],
"witness": [ [ "pubkey", "signature" ] ] "witness": [["pubkey", "signature"]]
}, },
"details": [ "details": [
{ {

14
test/fixtures/p2wsh.json

@ -354,13 +354,13 @@
], ],
"dynamic": { "dynamic": {
"depends": { "depends": {
"address": [ "address", "output", "hash", "redeem.output", "witness" ], "address": ["address", "output", "hash", "redeem.output", "witness"],
"hash": [ "address", "output", "hash", "redeem.output", "witness" ], "hash": ["address", "output", "hash", "redeem.output", "witness"],
"output": [ "address", "output", "hash", "redeem.output", "witness" ], "output": ["address", "output", "hash", "redeem.output", "witness"],
"redeem.output": [ "witness" ], "redeem.output": ["witness"],
"redeem.input": [ [ "input", "witness" ], "witness" ], "redeem.input": [["input", "witness"], "witness"],
"input": [ "witness" ], "input": ["witness"],
"witness": [ "redeem" ] "witness": ["redeem"]
}, },
"details": [ "details": [
{ {

238
test/integration/_regtest.js

@ -1,152 +1,142 @@
const assert = require('assert') "use strict";
const bitcoin = require('../../') Object.defineProperty(exports, "__esModule", { value: true });
const dhttpCallback = require('dhttp/200') const assert = require("assert");
const bitcoin = require("../..");
const dhttpCallback = require('dhttp/200');
// use Promises // use Promises
const dhttp = options => new Promise((resolve, reject) => { exports.dhttp = (options) =>
// @ts-ignore
new Promise((resolve, reject) => {
return dhttpCallback(options, (err, data) => { return dhttpCallback(options, (err, data) => {
if (err) return reject(err) if (err)
else return resolve(data) return reject(err);
}) else
}) return resolve(data);
});
const APIPASS = process.env.APIPASS || 'satoshi' });
const APIURL = process.env.APIURL || 'https://regtest.bitbank.cc/1' const APIPASS = process.env.APIPASS || 'satoshi';
const NETWORK = bitcoin.networks.testnet const APIURL = process.env.APIURL || 'https://regtest.bitbank.cc/1';
const NETWORK = bitcoin.networks.testnet;
function broadcast (txHex) { function broadcast(txHex) {
return dhttp({ return exports.dhttp({
method: 'POST', method: 'POST',
url: APIURL + '/t/push', url: APIURL + '/t/push',
body: txHex body: txHex,
}) });
} }
exports.broadcast = broadcast;
function mine (count) { function mine(count) {
return dhttp({ return exports.dhttp({
method: 'POST', method: 'POST',
url: APIURL + '/r/generate?count=' + count + '&key=' + APIPASS url: `${APIURL}/r/generate?count=${count}&key=${APIPASS}`,
}) });
} }
exports.mine = mine;
function height () { function height() {
return dhttp({ return exports.dhttp({
method: 'GET', method: 'GET',
url: APIURL + '/b/best/height' url: APIURL + '/b/best/height',
}) });
} }
exports.height = height;
function _faucetRequest (address, value) { function fetch(txId) {
return dhttp({ return exports.dhttp({
method: 'GET',
url: `${APIURL}/t/${txId}/json`,
});
}
exports.fetch = fetch;
function unspents(address) {
return exports.dhttp({
method: 'GET',
url: `${APIURL}/a/${address}/unspents`,
});
}
exports.unspents = unspents;
function _faucetRequest(address, value) {
return exports.dhttp({
method: 'POST', method: 'POST',
url: APIURL + '/r/faucet?address=' + address + '&value=' + value + '&key=' + APIPASS url: `${APIURL}/r/faucet?address=${address}&value=${value}&key=${APIPASS}`,
}) });
} }
// @ts-ignore
async function faucet (address, value) { async function faucet(address, value) {
let count = 0 let count = 0;
let _unspents = [] let _unspents = [];
const sleep = ms => new Promise((resolve, reject) => setTimeout(resolve, ms)) const sleep = (ms) =>
const randInt = (min, max) => min + Math.floor((max - min + 1) * Math.random()) // @ts-ignore
new Promise((resolve) => setTimeout(resolve, ms));
const randInt = (min, max) => min + Math.floor((max - min + 1) * Math.random());
while (_unspents.length === 0) { while (_unspents.length === 0) {
if (count > 0) { if (count > 0) {
if (count >= 5) throw new Error('Missing Inputs') if (count >= 5)
console.log('Missing Inputs, retry #' + count) throw new Error('Missing Inputs');
await sleep(randInt(150, 250)) console.log('Missing Inputs, retry #' + count);
await sleep(randInt(150, 250));
} }
const txId = await _faucetRequest(address, value).then(v => v, // Pass success value as is
const txId = await _faucetRequest(address, value) async (err) => {
.then(
v => v, // Pass success value as is
async err => {
// Bad Request error is fixed by making sure height is >= 432 // Bad Request error is fixed by making sure height is >= 432
const currentHeight = await height() const currentHeight = (await height());
if (err.message === 'Bad Request' && currentHeight < 432) { if (err.message === 'Bad Request' && currentHeight < 432) {
await mine(432 - currentHeight) await mine(432 - currentHeight);
return _faucetRequest(address, value) return _faucetRequest(address, value);
} else if (err.message === 'Bad Request' && currentHeight >= 432) {
return _faucetRequest(address, value)
} else {
throw err
} }
else if (err.message === 'Bad Request' && currentHeight >= 432) {
return _faucetRequest(address, value);
} }
) else {
throw err;
await sleep(randInt(10, 40))
const results = await unspents(address)
_unspents = results.filter(x => x.txId === txId)
count++
} }
});
return _unspents.pop() await sleep(randInt(50, 150));
const results = await unspents(address);
_unspents = results.filter(x => x.txId === txId);
count++;
}
return _unspents.pop();
} }
exports.faucet = faucet;
async function faucetComplex (output, value) { async function faucetComplex(output, value) {
const keyPair = bitcoin.ECPair.makeRandom({ network: NETWORK }) const keyPair = bitcoin.ECPair.makeRandom({ network: NETWORK });
const p2pkh = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: NETWORK }) const p2pkh = bitcoin.payments.p2pkh({
pubkey: keyPair.publicKey,
const unspent = await faucet(p2pkh.address, value * 2) network: NETWORK,
});
const txvb = new bitcoin.TransactionBuilder(NETWORK) const unspent = await faucet(p2pkh.address, value * 2);
txvb.addInput(unspent.txId, unspent.vout, null, p2pkh.output) const txvb = new bitcoin.TransactionBuilder(NETWORK);
txvb.addOutput(output, value) txvb.addInput(unspent.txId, unspent.vout, undefined, p2pkh.output);
txvb.sign(0, keyPair) txvb.addOutput(output, value);
const txv = txvb.build() txvb.sign(0, keyPair);
const txv = txvb.build();
await broadcast(txv.toHex()) await broadcast(txv.toHex());
return { return {
height: -1,
txId: txv.getId(), txId: txv.getId(),
vout: 0, vout: 0,
value value,
} };
} }
exports.faucetComplex = faucetComplex;
function fetch (txId) { // @ts-ignore
return dhttp({ async function verify(txo) {
method: 'GET', const tx = await fetch(txo.txId);
url: APIURL + '/t/' + txId + '/json' const txoActual = tx.outs[txo.vout];
}) if (txo.address)
} assert.strictEqual(txoActual.address, txo.address);
if (txo.value)
function unspents (address) { assert.strictEqual(txoActual.value, txo.value);
return dhttp({
method: 'GET',
url: APIURL + '/a/' + address + '/unspents'
})
} }
exports.verify = verify;
async function verify (txo) { function getAddress(node, myNetwork) {
const tx = await fetch(txo.txId) return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network: myNetwork })
.address;
const txoActual = tx.outs[txo.vout]
if (txo.address) assert.strictEqual(txoActual.address, txo.address)
if (txo.value) assert.strictEqual(txoActual.value, txo.value)
} }
function randomAddress() {
function getAddress (node, network) {
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address
}
function randomAddress () {
return getAddress(bitcoin.ECPair.makeRandom({ return getAddress(bitcoin.ECPair.makeRandom({
network: bitcoin.networks.testnet network: bitcoin.networks.testnet,
}), bitcoin.networks.testnet) }), bitcoin.networks.testnet);
}
module.exports = {
broadcast,
dhttp,
faucet,
faucetComplex,
fetch,
height,
mine,
network: NETWORK,
unspents,
verify,
randomAddress,
RANDOM_ADDRESS: randomAddress()
} }
exports.randomAddress = randomAddress;
exports.RANDOM_ADDRESS = randomAddress();
exports.network = NETWORK;

155
test/integration/addresses.js

@ -1,117 +1,110 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bitcoin = require('../../') const { describe, it } = require('mocha');
const dhttp = require('./_regtest').dhttp const assert = require('assert');
const TESTNET = bitcoin.networks.testnet const bitcoin = require("../..");
const _regtest_1 = require("./_regtest");
const TESTNET = bitcoin.networks.testnet;
describe('bitcoinjs-lib (addresses)', () => { describe('bitcoinjs-lib (addresses)', () => {
it('can generate a random address [and support the retrieval of transactions for that address (via 3PBP)', async () => { // @ts-ignore
const keyPair = bitcoin.ECPair.makeRandom() it('can generate a random address [and support retrieval of transactions for that address (via 3PBP)', async () => {
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey }) const keyPair = bitcoin.ECPair.makeRandom();
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey });
// bitcoin P2PKH addresses start with a '1' // bitcoin P2PKH addresses start with a '1'
assert.strictEqual(address.startsWith('1'), true) // @ts-ignore
assert.strictEqual(address.startsWith('1'), true);
const result = await dhttp({ const result = (await _regtest_1.dhttp({
method: 'GET', method: 'GET',
url: 'https://blockchain.info/rawaddr/' + address url: 'https://blockchain.info/rawaddr/' + address,
}) }));
// random private keys [probably!] have no transactions // random private keys [probably!] have no transactions
assert.strictEqual(result.n_tx, 0) assert.strictEqual(result.n_tx, 0);
assert.strictEqual(result.total_received, 0) assert.strictEqual(result.total_received, 0);
assert.strictEqual(result.total_sent, 0) assert.strictEqual(result.total_sent, 0);
}) });
it('can import an address via WIF', () => { it('can import an address via WIF', () => {
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn') const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn');
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey }) const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey });
assert.strictEqual(address, '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH');
assert.strictEqual(address, '1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH') });
})
it('can generate a P2SH, pay-to-multisig (2-of-3) address', () => { it('can generate a P2SH, pay-to-multisig (2-of-3) address', () => {
const pubkeys = [ const pubkeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9', '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
'03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9' '03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9',
].map((hex) => Buffer.from(hex, 'hex')) ].map(hex => Buffer.from(hex, 'hex'));
const { address } = bitcoin.payments.p2sh({ const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2ms({ m: 2, pubkeys }) redeem: bitcoin.payments.p2ms({ m: 2, pubkeys }),
}) });
assert.strictEqual(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7');
assert.strictEqual(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7') });
})
it('can generate a SegWit address', () => { it('can generate a SegWit address', () => {
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn') const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn');
const { address } = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey }) const { address } = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey });
assert.strictEqual(address, 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4');
assert.strictEqual(address, 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4') });
})
it('can generate a SegWit address (via P2SH)', () => { it('can generate a SegWit address (via P2SH)', () => {
const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn') const keyPair = bitcoin.ECPair.fromWIF('KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn');
const { address } = bitcoin.payments.p2sh({ const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey }) redeem: bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey }),
}) });
assert.strictEqual(address, '3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN');
assert.strictEqual(address, '3JvL6Ymt8MVWiCNHC7oWU6nLeHNJKLZGLN') });
})
it('can generate a P2WSH (SegWit), pay-to-multisig (3-of-4) address', () => { it('can generate a P2WSH (SegWit), pay-to-multisig (3-of-4) address', () => {
const pubkeys = [ const pubkeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9', '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
'023e4740d0ba639e28963f3476157b7cf2fb7c6fdf4254f97099cf8670b505ea59', '023e4740d0ba639e28963f3476157b7cf2fb7c6fdf4254f97099cf8670b505ea59',
'03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9' '03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9',
].map((hex) => Buffer.from(hex, 'hex')) ].map(hex => Buffer.from(hex, 'hex'));
const { address } = bitcoin.payments.p2wsh({ const { address } = bitcoin.payments.p2wsh({
redeem: bitcoin.payments.p2ms({ m: 3, pubkeys }) redeem: bitcoin.payments.p2ms({ m: 3, pubkeys }),
}) });
assert.strictEqual(address, 'bc1q75f6dv4q8ug7zhujrsp5t0hzf33lllnr3fe7e2pra3v24mzl8rrqtp3qul');
assert.strictEqual(address, 'bc1q75f6dv4q8ug7zhujrsp5t0hzf33lllnr3fe7e2pra3v24mzl8rrqtp3qul') });
})
it('can generate a P2SH(P2WSH(...)), pay-to-multisig (2-of-2) address', () => { it('can generate a P2SH(P2WSH(...)), pay-to-multisig (2-of-2) address', () => {
const pubkeys = [ const pubkeys = [
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01', '026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9' '02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
].map((hex) => Buffer.from(hex, 'hex')) ].map(hex => Buffer.from(hex, 'hex'));
const { address } = bitcoin.payments.p2sh({ const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wsh({ redeem: bitcoin.payments.p2wsh({
redeem: bitcoin.payments.p2ms({ m: 2, pubkeys }) redeem: bitcoin.payments.p2ms({ m: 2, pubkeys }),
}) }),
}) });
assert.strictEqual(address, '3P4mrxQfmExfhxqjLnR2Ah4WES5EB1KBrN');
assert.strictEqual(address, '3P4mrxQfmExfhxqjLnR2Ah4WES5EB1KBrN') });
})
// examples using other network information // examples using other network information
it('can generate a Testnet address', () => { it('can generate a Testnet address', () => {
const keyPair = bitcoin.ECPair.makeRandom({ network: TESTNET }) const keyPair = bitcoin.ECPair.makeRandom({ network: TESTNET });
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: TESTNET }) const { address } = bitcoin.payments.p2pkh({
pubkey: keyPair.publicKey,
network: TESTNET,
});
// bitcoin testnet P2PKH addresses start with a 'm' or 'n' // bitcoin testnet P2PKH addresses start with a 'm' or 'n'
assert.strictEqual(address.startsWith('m') || address.startsWith('n'), true) assert.strictEqual(
}) // @ts-ignore
address.startsWith('m') || address.startsWith('n'), true);
});
it('can generate a Litecoin address', () => { it('can generate a Litecoin address', () => {
// WARNING: although possible, bitcoinjs is NOT necessarily compatible with Litecoin // WARNING: although possible, bitcoinjs is NOT necessarily compatible with Litecoin
const LITECOIN = { const LITECOIN = {
messagePrefix: '\x19Litecoin Signed Message:\n', messagePrefix: '\x19Litecoin Signed Message:\n',
bech32: 'lt',
bip32: { bip32: {
public: 0x019da462, public: 0x019da462,
private: 0x019d9cfe private: 0x019d9cfe,
}, },
pubKeyHash: 0x30, pubKeyHash: 0x30,
scriptHash: 0x32, scriptHash: 0x32,
wif: 0xb0 wif: 0xb0,
} };
const keyPair = bitcoin.ECPair.makeRandom({ network: LITECOIN });
const keyPair = bitcoin.ECPair.makeRandom({ network: LITECOIN }) const { address } = bitcoin.payments.p2pkh({
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: LITECOIN }) pubkey: keyPair.publicKey,
network: LITECOIN,
assert.strictEqual(address.startsWith('L'), true) });
}) // @ts-ignore
}) assert.strictEqual(address.startsWith('L'), true);
});
});

153
test/integration/bip32.js

@ -1,101 +1,90 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bip32 = require('bip32') const bip32 = require("bip32");
const bip39 = require('bip39') const bip39 = require("bip39");
const bitcoin = require('../../') const bitcoin = require("../..");
const { describe, it } = require('mocha');
function getAddress (node, network) { const assert = require('assert');
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address function getAddress(node, network) {
return bitcoin.payments.p2pkh({ pubkey: node.publicKey, network }).address;
} }
describe('bitcoinjs-lib (BIP32)', () => { describe('bitcoinjs-lib (BIP32)', () => {
it('can import a BIP32 testnet xpriv and export to WIF', () => { it('can import a BIP32 testnet xpriv and export to WIF', () => {
const xpriv = 'tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK' const xpriv = 'tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK';
const node = bip32.fromBase58(xpriv, bitcoin.networks.testnet) const node = bip32.fromBase58(xpriv, bitcoin.networks.testnet);
assert.strictEqual(node.toWIF(), 'cQfoY67cetFNunmBUX5wJiw3VNoYx3gG9U9CAofKE6BfiV1fSRw7');
assert.strictEqual(node.toWIF(), 'cQfoY67cetFNunmBUX5wJiw3VNoYx3gG9U9CAofKE6BfiV1fSRw7') });
})
it('can export a BIP32 xpriv, then import it', () => { it('can export a BIP32 xpriv, then import it', () => {
const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost' const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost';
const seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeedSync(mnemonic);
const node = bip32.fromSeed(seed) const node = bip32.fromSeed(seed);
const string = node.toBase58() const string0 = node.toBase58();
const restored = bip32.fromBase58(string) const restored = bip32.fromBase58(string0);
assert.strictEqual(getAddress(node), getAddress(restored)); // same public key
assert.strictEqual(getAddress(node), getAddress(restored)) // same public key assert.strictEqual(node.toWIF(), restored.toWIF()); // same private key
assert.strictEqual(node.toWIF(), restored.toWIF()) // same private key });
})
it('can export a BIP32 xpub', () => { it('can export a BIP32 xpub', () => {
const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost' const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost';
const seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeedSync(mnemonic);
const node = bip32.fromSeed(seed) const node = bip32.fromSeed(seed);
const string = node.neutered().toBase58() const string0 = node.neutered().toBase58();
assert.strictEqual(string0, 'xpub661MyMwAqRbcGhVeaVfEBA25e3cP9DsJQZoE8iep5fZSxy3TnPBNBgWnMZx56oreNc48ZoTkQfatNJ9VWnQ7ZcLZcVStpaXLTeG8bGrzX3n');
assert.strictEqual(string, 'xpub661MyMwAqRbcGhVeaVfEBA25e3cP9DsJQZoE8iep5fZSxy3TnPBNBgWnMZx56oreNc48ZoTkQfatNJ9VWnQ7ZcLZcVStpaXLTeG8bGrzX3n') });
})
it('can create a BIP32, bitcoin, account 0, external address', () => { it('can create a BIP32, bitcoin, account 0, external address', () => {
const path = "m/0'/0/0" const path = "m/0'/0/0"; // tslint:disable-line:quotemark
const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex')) const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex'));
const child1 = root.derivePath(path);
const child1 = root.derivePath(path)
// option 2, manually // option 2, manually
const child1b = root.deriveHardened(0) const child1b = root
.derive(0) .deriveHardened(0)
.derive(0) .derive(0)
.derive(0);
assert.strictEqual(getAddress(child1), '1JHyB1oPXufr4FXkfitsjgNB5yRY9jAaa7') assert.strictEqual(getAddress(child1), '1JHyB1oPXufr4FXkfitsjgNB5yRY9jAaa7');
assert.strictEqual(getAddress(child1b), '1JHyB1oPXufr4FXkfitsjgNB5yRY9jAaa7') assert.strictEqual(getAddress(child1b), '1JHyB1oPXufr4FXkfitsjgNB5yRY9jAaa7');
}) });
it('can create a BIP44, bitcoin, account 0, external address', () => { it('can create a BIP44, bitcoin, account 0, external address', () => {
const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex')) const root = bip32.fromSeed(Buffer.from('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd', 'hex'));
const child1 = root.derivePath("m/44'/0'/0'/0/0"); // tslint:disable-line:quotemark
const child1 = root.derivePath("m/44'/0'/0'/0/0")
// option 2, manually // option 2, manually
const child1b = root.deriveHardened(44) const child1b = root
.deriveHardened(44)
.deriveHardened(0) .deriveHardened(0)
.deriveHardened(0) .deriveHardened(0)
.derive(0) .derive(0)
.derive(0) .derive(0);
assert.strictEqual(getAddress(child1), '12Tyvr1U8A3ped6zwMEU5M8cx3G38sP5Au');
assert.strictEqual(getAddress(child1), '12Tyvr1U8A3ped6zwMEU5M8cx3G38sP5Au') assert.strictEqual(getAddress(child1b), '12Tyvr1U8A3ped6zwMEU5M8cx3G38sP5Au');
assert.strictEqual(getAddress(child1b), '12Tyvr1U8A3ped6zwMEU5M8cx3G38sP5Au') });
})
it('can create a BIP49, bitcoin testnet, account 0, external address', () => { it('can create a BIP49, bitcoin testnet, account 0, external address', () => {
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about' const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
const seed = bip39.mnemonicToSeed(mnemonic) const seed = bip39.mnemonicToSeedSync(mnemonic);
const root = bip32.fromSeed(seed) const root = bip32.fromSeed(seed);
const path = "m/49'/1'/0'/0/0"; // tslint:disable-line:quotemark
const path = "m/49'/1'/0'/0/0" const child = root.derivePath(path);
const child = root.derivePath(path)
const { address } = bitcoin.payments.p2sh({ const { address } = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({ pubkey: child.publicKey, network: bitcoin.networks.testnet }), redeem: bitcoin.payments.p2wpkh({
network: bitcoin.networks.testnet pubkey: child.publicKey,
}) network: bitcoin.networks.testnet,
assert.strictEqual(address, '2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2') }),
}) network: bitcoin.networks.testnet,
});
assert.strictEqual(address, '2Mww8dCYPUpKHofjgcXcBCEGmniw9CoaiD2');
});
it('can use BIP39 to generate BIP32 addresses', () => { it('can use BIP39 to generate BIP32 addresses', () => {
// var mnemonic = bip39.generateMnemonic() // var mnemonic = bip39.generateMnemonic()
const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost' const mnemonic = 'praise you muffin lion enable neck grocery crumble super myself license ghost';
assert(bip39.validateMnemonic(mnemonic)) assert(bip39.validateMnemonic(mnemonic));
const seed = bip39.mnemonicToSeedSync(mnemonic);
const seed = bip39.mnemonicToSeed(mnemonic) const root = bip32.fromSeed(seed);
const root = bip32.fromSeed(seed)
// receive addresses // receive addresses
assert.strictEqual(getAddress(root.derivePath("m/0'/0/0")), '1AVQHbGuES57wD68AJi7Gcobc3RZrfYWTC') assert.strictEqual(getAddress(root.derivePath("m/0'/0/0")), // tslint:disable-line:quotemark
assert.strictEqual(getAddress(root.derivePath("m/0'/0/1")), '1Ad6nsmqDzbQo5a822C9bkvAfrYv9mc1JL') '1AVQHbGuES57wD68AJi7Gcobc3RZrfYWTC');
assert.strictEqual(getAddress(root.derivePath("m/0'/0/1")), // tslint:disable-line:quotemark
'1Ad6nsmqDzbQo5a822C9bkvAfrYv9mc1JL');
// change addresses // change addresses
assert.strictEqual(getAddress(root.derivePath("m/0'/1/0")), '1349KVc5NgedaK7DvuD4xDFxL86QN1Hvdn') assert.strictEqual(getAddress(root.derivePath("m/0'/1/0")), // tslint:disable-line:quotemark
assert.strictEqual(getAddress(root.derivePath("m/0'/1/1")), '1EAvj4edpsWcSer3duybAd4KiR4bCJW5J6') '1349KVc5NgedaK7DvuD4xDFxL86QN1Hvdn');
}) assert.strictEqual(getAddress(root.derivePath("m/0'/1/1")), // tslint:disable-line:quotemark
}) '1EAvj4edpsWcSer3duybAd4KiR4bCJW5J6');
});
});

40
test/integration/blocks.js

@ -1,22 +1,26 @@
'use strict' "use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const { describe, it } = require('mocha') const bitcoin = require("../..");
const assert = require('assert') const { describe, it } = require('mocha');
const bitcoin = require('../../') const assert = require('assert');
describe('bitcoinjs-lib (blocks)', () => { describe('bitcoinjs-lib (blocks)', () => {
it('can extract a height from a CoinBase transaction', () => { it('can extract a height from a CoinBase transaction', () => {
// from 00000000000000000097669cdca131f24d40c4cc7d80eaa65967a2d09acf6ce6 // from 00000000000000000097669cdca131f24d40c4cc7d80eaa65967a2d09acf6ce6
const txHex = '010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a2b1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98fd16761d220400000000000000aa340000d49f0000ffffffff02b07fc366000000001976a9148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266a24aa21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12bf1e400120000000000000000000000000000000000000000000000000000000000000000000000000' const txHex = '0100000000010100000000000000000000000000000000000000000000000000000000' +
const tx = bitcoin.Transaction.fromHex(txHex) '00000000ffffffff50037f9a07174d696e656420627920416e74506f6f6c685b205a2b' +
'1f7bfabe6d6d36afe1910eca9405b66f97750940a656e38e2c0312958190ff8e98fd16' +
assert.strictEqual(tx.ins.length, 1) '761d220400000000000000aa340000d49f0000ffffffff02b07fc366000000001976a9' +
const script = tx.ins[0].script '148349212dc27ce3ab4c5b29b85c4dec643d764b1788ac0000000000000000266a24aa' +
'21a9ed72d9432948505e3d3062f1307a3f027a5dea846ff85e47159680919c12bf1e40' +
'0120000000000000000000000000000000000000000000000000000000000000000000' +
'000000';
const tx = bitcoin.Transaction.fromHex(txHex);
assert.strictEqual(tx.ins.length, 1);
const script = tx.ins[0].script;
// bitcoin.script.decompile(script) // returns [] :( // bitcoin.script.decompile(script) // returns [] :(
assert.strictEqual(script[0], 0x03);
assert.strictEqual(script[0], 0x03) const heightBuffer = script.slice(1, 4);
const heightBuffer = script.slice(1, 4) const height = bitcoin.script.number.decode(heightBuffer);
const height = bitcoin.script.number.decode(heightBuffer) assert.strictEqual(height, 498303);
assert.strictEqual(height, 498303) });
}) });
})

250
test/integration/cltv.js

@ -1,197 +1,201 @@
const { describe, it, before } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bitcoin = require('../../') const bitcoin = require("../..");
const regtestUtils = require('./_regtest') const _regtest_1 = require("./_regtest");
const regtest = regtestUtils.network const regtestUtils = require("./_regtest");
const bip65 = require('bip65') const { describe, it, before } = require('mocha');
const assert = require('assert');
const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest) const bip65 = require('bip65');
const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest) const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', _regtest_1.network);
const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', _regtest_1.network);
describe('bitcoinjs-lib (transactions w/ CLTV)', () => { describe('bitcoinjs-lib (transactions w/ CLTV)', () => {
// force update MTP // force update MTP
// @ts-ignore
before(async () => { before(async () => {
await regtestUtils.mine(11) await regtestUtils.mine(11);
}) });
const hashType = bitcoin.Transaction.SIGHASH_ALL;
const hashType = bitcoin.Transaction.SIGHASH_ALL function cltvCheckSigOutput(aQ, bQ, lockTime) {
function cltvCheckSigOutput (aQ, bQ, lockTime) {
return bitcoin.script.compile([ return bitcoin.script.compile([
bitcoin.opcodes.OP_IF, bitcoin.opcodes.OP_IF,
bitcoin.script.number.encode(lockTime), bitcoin.script.number.encode(lockTime),
bitcoin.opcodes.OP_CHECKLOCKTIMEVERIFY, bitcoin.opcodes.OP_CHECKLOCKTIMEVERIFY,
bitcoin.opcodes.OP_DROP, bitcoin.opcodes.OP_DROP,
bitcoin.opcodes.OP_ELSE, bitcoin.opcodes.OP_ELSE,
bQ.publicKey, bQ.publicKey,
bitcoin.opcodes.OP_CHECKSIGVERIFY, bitcoin.opcodes.OP_CHECKSIGVERIFY,
bitcoin.opcodes.OP_ENDIF, bitcoin.opcodes.OP_ENDIF,
aQ.publicKey, aQ.publicKey,
bitcoin.opcodes.OP_CHECKSIG bitcoin.opcodes.OP_CHECKSIG,
]) ]);
} }
function utcNow() {
function utcNow () { return Math.floor(Date.now() / 1000);
return Math.floor(Date.now() / 1000)
} }
// expiry past, {Alice's signature} OP_TRUE // expiry past, {Alice's signature} OP_TRUE
it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the past)', async () => { it('can create (and broadcast via 3PBP) a Transaction where ' +
'Alice can redeem the output after the expiry (in the past)',
// @ts-ignore
async () => {
// 3 hours ago // 3 hours ago
const lockTime = bip65.encode({ utc: utcNow() - (3600 * 3) }) const lockTime = bip65.encode({ utc: utcNow() - 3600 * 3 });
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
const { address } = bitcoin.payments.p2sh({ redeem: { output: redeemScript, network: regtest }, network: regtest }) const { address } = bitcoin.payments.p2sh({
redeem: { output: redeemScript, network: _regtest_1.network },
network: _regtest_1.network,
});
// fund the P2SH(CLTV) address // fund the P2SH(CLTV) address
const unspent = await regtestUtils.faucet(address, 1e5) const unspent = await regtestUtils.faucet(address, 1e5);
const txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.setLockTime(lockTime) txb.setLockTime(lockTime);
// Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable. // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
txb.addInput(unspent.txId, unspent.vout, 0xfffffffe) txb.addInput(unspent.txId, unspent.vout, 0xfffffffe);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
const tx = txb.buildIncomplete() const tx = txb.buildIncomplete();
const signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
const redeemScriptSig = bitcoin.payments.p2sh({ const redeemScriptSig = bitcoin.payments.p2sh({
redeem: { redeem: {
input: bitcoin.script.compile([ input: bitcoin.script.compile([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE,
]), ]),
output: redeemScript output: redeemScript,
} },
}).input }).input;
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig);
await regtestUtils.broadcast(tx.toHex());
await regtestUtils.broadcast(tx.toHex())
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 7e4 value: 7e4,
}) });
}) });
// expiry will pass, {Alice's signature} OP_TRUE // expiry will pass, {Alice's signature} OP_TRUE
it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future)', async () => { it('can create (and broadcast via 3PBP) a Transaction where ' +
const height = await regtestUtils.height() 'Alice can redeem the output after the expiry (in the future)',
// @ts-ignore
async () => {
const height = await regtestUtils.height();
// 5 blocks from now // 5 blocks from now
const lockTime = bip65.encode({ blocks: height + 5 }) const lockTime = bip65.encode({ blocks: height + 5 });
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
const { address } = bitcoin.payments.p2sh({ redeem: { output: redeemScript, network: regtest }, network: regtest }) const { address } = bitcoin.payments.p2sh({
redeem: { output: redeemScript, network: _regtest_1.network },
network: _regtest_1.network,
});
// fund the P2SH(CLTV) address // fund the P2SH(CLTV) address
const unspent = await regtestUtils.faucet(address, 1e5) const unspent = await regtestUtils.faucet(address, 1e5);
const txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.setLockTime(lockTime) txb.setLockTime(lockTime);
// Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable. // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
txb.addInput(unspent.txId, unspent.vout, 0xfffffffe) txb.addInput(unspent.txId, unspent.vout, 0xfffffffe);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
const tx = txb.buildIncomplete() const tx = txb.buildIncomplete();
const signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
const redeemScriptSig = bitcoin.payments.p2sh({ const redeemScriptSig = bitcoin.payments.p2sh({
redeem: { redeem: {
input: bitcoin.script.compile([ input: bitcoin.script.compile([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE,
]), ]),
output: redeemScript output: redeemScript,
} },
}).input }).input;
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig);
// TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently // TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
// ... // ...
// into the future! // into the future!
await regtestUtils.mine(5) await regtestUtils.mine(5);
await regtestUtils.broadcast(tx.toHex()) await regtestUtils.broadcast(tx.toHex());
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 7e4 value: 7e4,
}) });
}) });
// expiry ignored, {Bob's signature} {Alice's signature} OP_FALSE // expiry ignored, {Bob's signature} {Alice's signature} OP_FALSE
it('can create (and broadcast via 3PBP) a Transaction where Alice and Bob can redeem the output at any time', async () => { it('can create (and broadcast via 3PBP) a Transaction where ' +
'Alice and Bob can redeem the output at any time',
// @ts-ignore
async () => {
// two hours ago // two hours ago
const lockTime = bip65.encode({ utc: utcNow() - (3600 * 2) }) const lockTime = bip65.encode({ utc: utcNow() - 3600 * 2 });
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
const { address } = bitcoin.payments.p2sh({ redeem: { output: redeemScript, network: regtest }, network: regtest }) const { address } = bitcoin.payments.p2sh({
redeem: { output: redeemScript, network: _regtest_1.network },
network: _regtest_1.network,
});
// fund the P2SH(CLTV) address // fund the P2SH(CLTV) address
const unspent = await regtestUtils.faucet(address, 2e5) const unspent = await regtestUtils.faucet(address, 2e5);
const txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.setLockTime(lockTime) txb.setLockTime(lockTime);
// Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable. // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
txb.addInput(unspent.txId, unspent.vout, 0xfffffffe) txb.addInput(unspent.txId, unspent.vout, 0xfffffffe);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 8e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 8e4);
// {Alice's signature} {Bob's signature} OP_FALSE // {Alice's signature} {Bob's signature} OP_FALSE
const tx = txb.buildIncomplete() const tx = txb.buildIncomplete();
const signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
const redeemScriptSig = bitcoin.payments.p2sh({ const redeemScriptSig = bitcoin.payments.p2sh({
redeem: { redeem: {
input: bitcoin.script.compile([ input: bitcoin.script.compile([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType), bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
bitcoin.opcodes.OP_FALSE bitcoin.opcodes.OP_FALSE,
]), ]),
output: redeemScript output: redeemScript,
} },
}).input }).input;
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig);
await regtestUtils.broadcast(tx.toHex());
await regtestUtils.broadcast(tx.toHex())
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 8e4 value: 8e4,
}) });
}) });
// expiry in the future, {Alice's signature} OP_TRUE // expiry in the future, {Alice's signature} OP_TRUE
it('can create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry', async () => { it('can create (but fail to broadcast via 3PBP) a Transaction where ' +
'Alice attempts to redeem before the expiry',
// @ts-ignore
async () => {
// two hours from now // two hours from now
const lockTime = bip65.encode({ utc: utcNow() + (3600 * 2) }) const lockTime = bip65.encode({ utc: utcNow() + 3600 * 2 });
const redeemScript = cltvCheckSigOutput(alice, bob, lockTime) const redeemScript = cltvCheckSigOutput(alice, bob, lockTime);
const { address } = bitcoin.payments.p2sh({ redeem: { output: redeemScript, network: regtest }, network: regtest }) const { address } = bitcoin.payments.p2sh({
redeem: { output: redeemScript, network: _regtest_1.network },
network: _regtest_1.network,
});
// fund the P2SH(CLTV) address // fund the P2SH(CLTV) address
const unspent = await regtestUtils.faucet(address, 2e4) const unspent = await regtestUtils.faucet(address, 2e4);
const txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.setLockTime(lockTime) txb.setLockTime(lockTime);
// Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable. // Note: nSequence MUST be <= 0xfffffffe otherwise LockTime is ignored, and is immediately spendable.
txb.addInput(unspent.txId, unspent.vout, 0xfffffffe) txb.addInput(unspent.txId, unspent.vout, 0xfffffffe);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4);
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
const tx = txb.buildIncomplete() const tx = txb.buildIncomplete();
const signatureHash = tx.hashForSignature(0, redeemScript, hashType) const signatureHash = tx.hashForSignature(0, redeemScript, hashType);
const redeemScriptSig = bitcoin.payments.p2sh({ const redeemScriptSig = bitcoin.payments.p2sh({
redeem: { redeem: {
input: bitcoin.script.compile([ input: bitcoin.script.compile([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType), bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE,
]), ]),
output: redeemScript output: redeemScript,
} },
}).input }).input;
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig);
await regtestUtils.broadcast(tx.toHex()).catch(err => { await regtestUtils.broadcast(tx.toHex()).catch(err => {
assert.throws(() => { assert.throws(() => {
if (err) throw err if (err)
}, /Error: non-final \(code 64\)/) throw err;
}) }, /Error: non-final \(code 64\)/);
}) });
}) });
});

150
test/integration/csv.js

@ -1,127 +1,119 @@
const { describe, it, before } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bitcoin = require('../../') const bitcoin = require("../..");
const regtestUtils = require('./_regtest') const _regtest_1 = require("./_regtest");
const regtest = regtestUtils.network const regtestUtils = require("./_regtest");
const bip68 = require('bip68') const { describe, it, before } = require('mocha');
const assert = require('assert');
const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', regtest) const bip68 = require('bip68');
const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', regtest) const alice = bitcoin.ECPair.fromWIF('cScfkGjbzzoeewVWmU2hYPUHeVGJRDdFt7WhmrVVGkxpmPP8BHWe', _regtest_1.network);
const bob = bitcoin.ECPair.fromWIF('cMkopUXKWsEzAjfa1zApksGRwjVpJRB3831qM9W4gKZsLwjHXA9x', _regtest_1.network);
describe('bitcoinjs-lib (transactions w/ CSV)', () => { describe('bitcoinjs-lib (transactions w/ CSV)', () => {
// force update MTP // force update MTP
// @ts-ignore
before(async () => { before(async () => {
await regtestUtils.mine(11) await regtestUtils.mine(11);
}) });
const hashType = bitcoin.Transaction.SIGHASH_ALL;
const hashType = bitcoin.Transaction.SIGHASH_ALL
// IF MTP (from when confirmed) > seconds, aQ can redeem // IF MTP (from when confirmed) > seconds, aQ can redeem
function csvCheckSigOutput (aQ, bQ, sequence) { function csvCheckSigOutput(aQ, bQ, sequence) {
return bitcoin.script.compile([ return bitcoin.script.compile([
bitcoin.opcodes.OP_IF, bitcoin.opcodes.OP_IF,
bitcoin.script.number.encode(sequence), bitcoin.script.number.encode(sequence),
bitcoin.opcodes.OP_CHECKSEQUENCEVERIFY, bitcoin.opcodes.OP_CHECKSEQUENCEVERIFY,
bitcoin.opcodes.OP_DROP, bitcoin.opcodes.OP_DROP,
bitcoin.opcodes.OP_ELSE, bitcoin.opcodes.OP_ELSE,
bQ.publicKey, bQ.publicKey,
bitcoin.opcodes.OP_CHECKSIGVERIFY, bitcoin.opcodes.OP_CHECKSIGVERIFY,
bitcoin.opcodes.OP_ENDIF, bitcoin.opcodes.OP_ENDIF,
aQ.publicKey, aQ.publicKey,
bitcoin.opcodes.OP_CHECKSIG bitcoin.opcodes.OP_CHECKSIG,
]) ]);
} }
// expiry will pass, {Alice's signature} OP_TRUE // expiry will pass, {Alice's signature} OP_TRUE
it('can create (and broadcast via 3PBP) a Transaction where Alice can redeem the output after the expiry (in the future)', async () => { it('can create (and broadcast via 3PBP) a Transaction where ' +
'Alice can redeem the output after the expiry (in the future)',
// @ts-ignore
async () => {
// 5 blocks from now // 5 blocks from now
const sequence = bip68.encode({ blocks: 5 }) const sequence = bip68.encode({ blocks: 5 });
const p2sh = bitcoin.payments.p2sh({ const p2sh = bitcoin.payments.p2sh({
redeem: { redeem: {
output: csvCheckSigOutput(alice, bob, sequence) output: csvCheckSigOutput(alice, bob, sequence),
}, },
network: regtest network: _regtest_1.network,
}) });
// fund the P2SH(CSV) address // fund the P2SH(CSV) address
const unspent = await regtestUtils.faucet(p2sh.address, 1e5) const unspent = await regtestUtils.faucet(p2sh.address, 1e5);
const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
const txb = new bitcoin.TransactionBuilder(regtest) txb.addInput(unspent.txId, unspent.vout, sequence);
txb.addInput(unspent.txId, unspent.vout, sequence) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 7e4)
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
const tx = txb.buildIncomplete() const tx = txb.buildIncomplete();
const signatureHash = tx.hashForSignature(0, p2sh.redeem.output, hashType) const signatureHash = tx.hashForSignature(0, p2sh.redeem.output, hashType);
const redeemScriptSig = bitcoin.payments.p2sh({ const redeemScriptSig = bitcoin.payments.p2sh({
network: regtest, network: _regtest_1.network,
redeem: { redeem: {
network: regtest, network: _regtest_1.network,
output: p2sh.redeem.output, output: p2sh.redeem.output,
input: bitcoin.script.compile([ input: bitcoin.script.compile([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE,
]) ]),
} },
}).input }).input;
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig);
// TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently // TODO: test that it failures _prior_ to expiry, unfortunately, race conditions when run concurrently
// ... // ...
// into the future! // into the future!
await regtestUtils.mine(10) await regtestUtils.mine(10);
await regtestUtils.broadcast(tx.toHex());
await regtestUtils.broadcast(tx.toHex())
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 7e4 value: 7e4,
}) });
}) });
// expiry in the future, {Alice's signature} OP_TRUE // expiry in the future, {Alice's signature} OP_TRUE
it('can create (but fail to broadcast via 3PBP) a Transaction where Alice attempts to redeem before the expiry', async () => { it('can create (but fail to broadcast via 3PBP) a Transaction where ' +
'Alice attempts to redeem before the expiry',
// @ts-ignore
async () => {
// two hours after confirmation // two hours after confirmation
const sequence = bip68.encode({ seconds: 7168 }) const sequence = bip68.encode({ seconds: 7168 });
const p2sh = bitcoin.payments.p2sh({ const p2sh = bitcoin.payments.p2sh({
network: regtest, network: _regtest_1.network,
redeem: { redeem: {
output: csvCheckSigOutput(alice, bob, sequence) output: csvCheckSigOutput(alice, bob, sequence),
} },
}) });
// fund the P2SH(CSV) address // fund the P2SH(CSV) address
const unspent = await regtestUtils.faucet(p2sh.address, 2e4) const unspent = await regtestUtils.faucet(p2sh.address, 2e4);
const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
const txb = new bitcoin.TransactionBuilder(regtest) txb.addInput(unspent.txId, unspent.vout, sequence);
txb.addInput(unspent.txId, unspent.vout, sequence) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4)
// {Alice's signature} OP_TRUE // {Alice's signature} OP_TRUE
const tx = txb.buildIncomplete() const tx = txb.buildIncomplete();
const signatureHash = tx.hashForSignature(0, p2sh.redeem.output, hashType) const signatureHash = tx.hashForSignature(0, p2sh.redeem.output, hashType);
const redeemScriptSig = bitcoin.payments.p2sh({ const redeemScriptSig = bitcoin.payments.p2sh({
network: regtest, network: _regtest_1.network,
redeem: { redeem: {
network: regtest, network: _regtest_1.network,
output: p2sh.redeem.output, output: p2sh.redeem.output,
input: bitcoin.script.compile([ input: bitcoin.script.compile([
bitcoin.script.signature.encode(alice.sign(signatureHash), hashType), bitcoin.script.signature.encode(alice.sign(signatureHash), hashType),
bitcoin.script.signature.encode(bob.sign(signatureHash), hashType), bitcoin.script.signature.encode(bob.sign(signatureHash), hashType),
bitcoin.opcodes.OP_TRUE bitcoin.opcodes.OP_TRUE,
]) ]),
} },
}).input }).input;
tx.setInputScript(0, redeemScriptSig) tx.setInputScript(0, redeemScriptSig);
await regtestUtils.broadcast(tx.toHex()).catch(err => { await regtestUtils.broadcast(tx.toHex()).catch(err => {
assert.throws(() => { assert.throws(() => {
if (err) throw err if (err)
}, /Error: non-BIP68-final \(code 64\)/) throw err;
}) }, /Error: non-BIP68-final \(code 64\)/);
}) });
}) });
});

137
test/integration/payments.js

@ -1,67 +1,86 @@
const bitcoin = require('../../') "use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const { describe, it } = require('mocha') const bitcoin = require("../..");
const regtestUtils = require('./_regtest') const _regtest_1 = require("./_regtest");
const NETWORK = regtestUtils.network const regtestUtils = require("./_regtest");
const { describe, it } = require('mocha');
const keyPairs = [ const keyPairs = [
bitcoin.ECPair.makeRandom({ network: NETWORK }), bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
bitcoin.ECPair.makeRandom({ network: NETWORK }) bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
] ];
async function buildAndSign(depends, prevOutput, redeemScript, witnessScript) {
async function buildAndSign (depends, prevOutput, redeemScript, witnessScript) { const unspent = await regtestUtils.faucetComplex(prevOutput, 5e4);
const unspent = await regtestUtils.faucetComplex(prevOutput, 5e4) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.addInput(unspent.txId, unspent.vout, null, prevOutput);
const txb = new bitcoin.TransactionBuilder(NETWORK) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4);
txb.addInput(unspent.txId, unspent.vout, null, prevOutput)
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4)
if (depends.signatures) { if (depends.signatures) {
keyPairs.forEach(keyPair => { keyPairs.forEach(keyPair => {
txb.sign(0, keyPair, redeemScript, null, unspent.value, witnessScript) txb.sign(0, keyPair, redeemScript, null, unspent.value, witnessScript);
}) });
} else if (depends.signature) {
txb.sign(0, keyPairs[0], redeemScript, null, unspent.value, witnessScript)
} }
else if (depends.signature) {
return regtestUtils.broadcast(txb.build().toHex()) txb.sign(0, keyPairs[0], redeemScript, null, unspent.value, witnessScript);
}
return regtestUtils.broadcast(txb.build().toHex());
} }
['p2ms', 'p2pk', 'p2pkh', 'p2wpkh'].forEach(k => {
;['p2ms', 'p2pk', 'p2pkh', 'p2wpkh'].forEach(k => { const fixtures = require('../../ts_test/fixtures/' + k);
const fixtures = require('../fixtures/' + k) const { depends } = fixtures.dynamic;
const { depends } = fixtures.dynamic const fn = bitcoin.payments[k];
const fn = bitcoin.payments[k] const base = {};
if (depends.pubkey)
const base = {} base.pubkey = keyPairs[0].publicKey;
if (depends.pubkey) base.pubkey = keyPairs[0].publicKey if (depends.pubkeys)
if (depends.pubkeys) base.pubkeys = keyPairs.map(x => x.publicKey) base.pubkeys = keyPairs.map(x => x.publicKey);
if (depends.m) base.m = base.pubkeys.length if (depends.m)
base.m = base.pubkeys.length;
const { output } = fn(base) const { output } = fn(base);
if (!output) throw new TypeError('Missing output') if (!output)
throw new TypeError('Missing output');
describe('bitcoinjs-lib (payments - ' + k + ')', () => { describe('bitcoinjs-lib (payments - ' + k + ')', () => {
// @ts-ignore
it('can broadcast as an output, and be spent as an input', async () => { it('can broadcast as an output, and be spent as an input', async () => {
await buildAndSign(depends, output, null, null) await buildAndSign(depends, output, null, null);
}) });
it('can (as P2SH(' +
it('can (as P2SH(' + k + ')) broadcast as an output, and be spent as an input', async () => { k +
const p2sh = bitcoin.payments.p2sh({ redeem: { output }, network: NETWORK }) ')) broadcast as an output, and be spent as an input',
await buildAndSign(depends, p2sh.output, p2sh.redeem.output, null) // @ts-ignore
}) async () => {
const p2sh = bitcoin.payments.p2sh({
redeem: { output },
network: _regtest_1.network,
});
await buildAndSign(depends, p2sh.output, p2sh.redeem.output, null);
});
// NOTE: P2WPKH cannot be wrapped in P2WSH, consensus fail // NOTE: P2WPKH cannot be wrapped in P2WSH, consensus fail
if (k === 'p2wpkh') return if (k === 'p2wpkh')
return;
it('can (as P2WSH(' + k + ')) broadcast as an output, and be spent as an input', async () => { it('can (as P2WSH(' +
const p2wsh = bitcoin.payments.p2wsh({ redeem: { output }, network: NETWORK }) k +
await buildAndSign(depends, p2wsh.output, null, p2wsh.redeem.output) ')) broadcast as an output, and be spent as an input',
}) // @ts-ignore
async () => {
it('can (as P2SH(P2WSH(' + k + '))) broadcast as an output, and be spent as an input', async () => { const p2wsh = bitcoin.payments.p2wsh({
const p2wsh = bitcoin.payments.p2wsh({ redeem: { output }, network: NETWORK }) redeem: { output },
const p2sh = bitcoin.payments.p2sh({ redeem: { output: p2wsh.output }, network: NETWORK }) network: _regtest_1.network,
});
await buildAndSign(depends, p2sh.output, p2sh.redeem.output, p2wsh.redeem.output) await buildAndSign(depends, p2wsh.output, null, p2wsh.redeem.output);
}) });
}) it('can (as P2SH(P2WSH(' +
}) k +
'))) broadcast as an output, and be spent as an input',
// @ts-ignore
async () => {
const p2wsh = bitcoin.payments.p2wsh({
redeem: { output },
network: _regtest_1.network,
});
const p2sh = bitcoin.payments.p2sh({
redeem: { output: p2wsh.output },
network: _regtest_1.network,
});
await buildAndSign(depends, p2sh.output, p2sh.redeem.output, p2wsh.redeem.output);
});
});
});

472
test/integration/transactions.js

@ -1,288 +1,308 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bitcoin = require('../../') const bitcoin = require("../..");
const regtestUtils = require('./_regtest') const _regtest_1 = require("./_regtest");
const regtest = regtestUtils.network const regtestUtils = require("./_regtest");
const { describe, it } = require('mocha');
function rng () { const assert = require('assert');
return Buffer.from('YT8dAtK4d16A3P1z+TpwB2jJ4aFH3g9M1EioIBkLEV4=', 'base64') function rng() {
return Buffer.from('YT8dAtK4d16A3P1z+TpwB2jJ4aFH3g9M1EioIBkLEV4=', 'base64');
} }
describe('bitcoinjs-lib (transactions)', () => { describe('bitcoinjs-lib (transactions)', () => {
it('can create a 1-to-1 Transaction', () => { it('can create a 1-to-1 Transaction', () => {
const alice = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy') const alice = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy');
const txb = new bitcoin.TransactionBuilder() const txb = new bitcoin.TransactionBuilder();
txb.setVersion(1);
txb.setVersion(1) txb.addInput('61d520ccb74288c96bc1a2b20ea1c0d5a704776dd0164a396efec3ea7040349d', 0); // Alice's previous transaction output, has 15000 satoshis
txb.addInput('61d520ccb74288c96bc1a2b20ea1c0d5a704776dd0164a396efec3ea7040349d', 0) // Alice's previous transaction output, has 15000 satoshis txb.addOutput('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP', 12000);
txb.addOutput('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP', 12000)
// (in)15000 - (out)12000 = (fee)3000, this is the miner fee // (in)15000 - (out)12000 = (fee)3000, this is the miner fee
txb.sign(0, alice);
txb.sign(0, alice)
// prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below // prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below
assert.strictEqual(txb.build().toHex(), '01000000019d344070eac3fe6e394a16d06d7704a7d5c0a10eb2a2c16bc98842b7cc20d561000000006b48304502210088828c0bdfcdca68d8ae0caeb6ec62cd3fd5f9b2191848edae33feb533df35d302202e0beadd35e17e7f83a733f5277028a9b453d525553e3f5d2d7a7aa8010a81d60121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b59fffffffff01e02e0000000000001976a91406afd46bcdfd22ef94ac122aa11f241244a37ecc88ac00000000') assert.strictEqual(txb.build().toHex(), '01000000019d344070eac3fe6e394a16d06d7704a7d5c0a10eb2a2c16bc98842b7cc20' +
}) 'd561000000006b48304502210088828c0bdfcdca68d8ae0caeb6ec62cd3fd5f9b21918' +
'48edae33feb533df35d302202e0beadd35e17e7f83a733f5277028a9b453d525553e3f' +
'5d2d7a7aa8010a81d60121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6' +
'b1242bca47eb93b59fffffffff01e02e0000000000001976a91406afd46bcdfd22ef94' +
'ac122aa11f241244a37ecc88ac00000000');
});
it('can create a 2-to-2 Transaction', () => { it('can create a 2-to-2 Transaction', () => {
const alice = bitcoin.ECPair.fromWIF('L1Knwj9W3qK3qMKdTvmg3VfzUs3ij2LETTFhxza9LfD5dngnoLG1') const alice = bitcoin.ECPair.fromWIF('L1Knwj9W3qK3qMKdTvmg3VfzUs3ij2LETTFhxza9LfD5dngnoLG1');
const bob = bitcoin.ECPair.fromWIF('KwcN2pT3wnRAurhy7qMczzbkpY5nXMW2ubh696UBc1bcwctTx26z') const bob = bitcoin.ECPair.fromWIF('KwcN2pT3wnRAurhy7qMczzbkpY5nXMW2ubh696UBc1bcwctTx26z');
const txb = new bitcoin.TransactionBuilder();
const txb = new bitcoin.TransactionBuilder() txb.setVersion(1);
txb.setVersion(1) txb.addInput('b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c', 6); // Alice's previous transaction output, has 200000 satoshis
txb.addInput('b5bb9d8014a0f9b1d61e21e796d78dccdf1352f23cd32812f4850b878ae4944c', 6) // Alice's previous transaction output, has 200000 satoshis txb.addInput('7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730', 0); // Bob's previous transaction output, has 300000 satoshis
txb.addInput('7d865e959b2466918c9863afca942d0fb89d7c9ac0c99bafc3749504ded97730', 0) // Bob's previous transaction output, has 300000 satoshis txb.addOutput('1CUNEBjYrCn2y1SdiUMohaKUi4wpP326Lb', 180000);
txb.addOutput('1CUNEBjYrCn2y1SdiUMohaKUi4wpP326Lb', 180000) txb.addOutput('1JtK9CQw1syfWj1WtFMWomrYdV3W2tWBF9', 170000);
txb.addOutput('1JtK9CQw1syfWj1WtFMWomrYdV3W2tWBF9', 170000)
// (in)(200000 + 300000) - (out)(180000 + 170000) = (fee)150000, this is the miner fee // (in)(200000 + 300000) - (out)(180000 + 170000) = (fee)150000, this is the miner fee
txb.sign(1, bob); // Bob signs his input, which was the second input (1th)
txb.sign(1, bob) // Bob signs his input, which was the second input (1th) txb.sign(0, alice); // Alice signs her input, which was the first input (0th)
txb.sign(0, alice) // Alice signs her input, which was the first input (0th)
// prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below // prepare for broadcast to the Bitcoin network, see "can broadcast a Transaction" below
assert.strictEqual(txb.build().toHex(), '01000000024c94e48a870b85f41228d33cf25213dfcc8dd796e7211ed6b1f9a014809dbbb5060000006a473044022041450c258ce7cac7da97316bf2ea1ce66d88967c4df94f3e91f4c2a30f5d08cb02203674d516e6bb2b0afd084c3551614bd9cec3c2945231245e891b145f2d6951f0012103e05ce435e462ec503143305feb6c00e06a3ad52fbf939e85c65f3a765bb7baacffffffff3077d9de049574c3af9bc9c09a7c9db80f2d94caaf63988c9166249b955e867d000000006b483045022100aeb5f1332c79c446d3f906e4499b2e678500580a3f90329edf1ba502eec9402e022072c8b863f8c8d6c26f4c691ac9a6610aa4200edc697306648ee844cfbc089d7a012103df7940ee7cddd2f97763f67e1fb13488da3fbdd7f9c68ec5ef0864074745a289ffffffff0220bf0200000000001976a9147dd65592d0ab2fe0d0257d571abf032cd9db93dc88ac10980200000000001976a914c42e7ef92fdb603af844d064faad95db9bcdfd3d88ac00000000') assert.strictEqual(txb.build().toHex(), '01000000024c94e48a870b85f41228d33cf25213dfcc8dd796e7211ed6b1f9a014809d' +
}) 'bbb5060000006a473044022041450c258ce7cac7da97316bf2ea1ce66d88967c4df94f' +
'3e91f4c2a30f5d08cb02203674d516e6bb2b0afd084c3551614bd9cec3c2945231245e' +
'891b145f2d6951f0012103e05ce435e462ec503143305feb6c00e06a3ad52fbf939e85' +
'c65f3a765bb7baacffffffff3077d9de049574c3af9bc9c09a7c9db80f2d94caaf6398' +
'8c9166249b955e867d000000006b483045022100aeb5f1332c79c446d3f906e4499b2e' +
'678500580a3f90329edf1ba502eec9402e022072c8b863f8c8d6c26f4c691ac9a6610a' +
'a4200edc697306648ee844cfbc089d7a012103df7940ee7cddd2f97763f67e1fb13488' +
'da3fbdd7f9c68ec5ef0864074745a289ffffffff0220bf0200000000001976a9147dd6' +
'5592d0ab2fe0d0257d571abf032cd9db93dc88ac10980200000000001976a914c42e7e' +
'f92fdb603af844d064faad95db9bcdfd3d88ac00000000');
});
// @ts-ignore
it('can create (and broadcast via 3PBP) a typical Transaction', async () => { it('can create (and broadcast via 3PBP) a typical Transaction', async () => {
const alice1 = bitcoin.ECPair.makeRandom({ network: regtest }) const alice1 = bitcoin.ECPair.makeRandom({ network: _regtest_1.network });
const alice2 = bitcoin.ECPair.makeRandom({ network: regtest }) const alice2 = bitcoin.ECPair.makeRandom({ network: _regtest_1.network });
const aliceChange = bitcoin.ECPair.makeRandom({ network: regtest, rng: rng }) const aliceChange = bitcoin.ECPair.makeRandom({
network: _regtest_1.network,
const alice1pkh = bitcoin.payments.p2pkh({ pubkey: alice1.publicKey, network: regtest }) rng,
const alice2pkh = bitcoin.payments.p2pkh({ pubkey: alice2.publicKey, network: regtest }) });
const aliceCpkh = bitcoin.payments.p2pkh({ pubkey: aliceChange.publicKey, network: regtest }) const alice1pkh = bitcoin.payments.p2pkh({
pubkey: alice1.publicKey,
network: _regtest_1.network,
});
const alice2pkh = bitcoin.payments.p2pkh({
pubkey: alice2.publicKey,
network: _regtest_1.network,
});
const aliceCpkh = bitcoin.payments.p2pkh({
pubkey: aliceChange.publicKey,
network: _regtest_1.network,
});
// give Alice 2 unspent outputs // give Alice 2 unspent outputs
const unspent0 = await regtestUtils.faucet(alice1pkh.address, 5e4) const unspent0 = await regtestUtils.faucet(alice1pkh.address, 5e4);
const unspent1 = await regtestUtils.faucet(alice2pkh.address, 7e4);
const unspent1 = await regtestUtils.faucet(alice2pkh.address, 7e4) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.addInput(unspent0.txId, unspent0.vout); // alice1 unspent
const txb = new bitcoin.TransactionBuilder(regtest) txb.addInput(unspent1.txId, unspent1.vout); // alice2 unspent
txb.addInput(unspent0.txId, unspent0.vout) // alice1 unspent txb.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4); // the actual "spend"
txb.addInput(unspent1.txId, unspent1.vout) // alice2 unspent txb.addOutput(aliceCpkh.address, 1e4); // Alice's change
txb.addOutput('mwCwTceJvYV27KXBc3NJZys6CjsgsoeHmf', 8e4) // the actual "spend"
txb.addOutput(aliceCpkh.address, 1e4) // Alice's change
// (in)(5e4 + 7e4) - (out)(8e4 + 1e4) = (fee)3e4 = 30000, this is the miner fee // (in)(5e4 + 7e4) - (out)(8e4 + 1e4) = (fee)3e4 = 30000, this is the miner fee
// Alice signs each input with the respective private keys // Alice signs each input with the respective private keys
txb.sign(0, alice1) txb.sign(0, alice1);
txb.sign(1, alice2) txb.sign(1, alice2);
// build and broadcast our RegTest network // build and broadcast our RegTest network
await regtestUtils.broadcast(txb.build().toHex()) await regtestUtils.broadcast(txb.build().toHex());
// to build and broadcast to the actual Bitcoin network, see https://github.com/bitcoinjs/bitcoinjs-lib/issues/839 // to build and broadcast to the actual Bitcoin network, see https://github.com/bitcoinjs/bitcoinjs-lib/issues/839
}) });
// @ts-ignore
it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', async () => { it('can create (and broadcast via 3PBP) a Transaction with an OP_RETURN output', async () => {
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) const keyPair = bitcoin.ECPair.makeRandom({ network: _regtest_1.network });
const p2pkh = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey, network: regtest }) const p2pkh = bitcoin.payments.p2pkh({
pubkey: keyPair.publicKey,
const unspent = await regtestUtils.faucet(p2pkh.address, 2e5) network: _regtest_1.network,
});
const txb = new bitcoin.TransactionBuilder(regtest) const unspent = await regtestUtils.faucet(p2pkh.address, 2e5);
const data = Buffer.from('bitcoinjs-lib', 'utf8') const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
const embed = bitcoin.payments.embed({ data: [data] }) const data = Buffer.from('bitcoinjs-lib', 'utf8');
txb.addInput(unspent.txId, unspent.vout) const embed = bitcoin.payments.embed({ data: [data] });
txb.addOutput(embed.output, 1000) txb.addInput(unspent.txId, unspent.vout);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e5) txb.addOutput(embed.output, 1000);
txb.sign(0, keyPair) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e5);
txb.sign(0, keyPair);
// build and broadcast to the RegTest network // build and broadcast to the RegTest network
await regtestUtils.broadcast(txb.build().toHex()) await regtestUtils.broadcast(txb.build().toHex());
}) });
// @ts-ignore
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2MS(2 of 4)) (multisig) input', async () => { it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2MS(2 of 4)) (multisig) input', async () => {
const keyPairs = [ const keyPairs = [
bitcoin.ECPair.makeRandom({ network: regtest }), bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
bitcoin.ECPair.makeRandom({ network: regtest }), bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
bitcoin.ECPair.makeRandom({ network: regtest }), bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
bitcoin.ECPair.makeRandom({ network: regtest }) bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
] ];
const pubkeys = keyPairs.map(x => x.publicKey) const pubkeys = keyPairs.map(x => x.publicKey);
const p2ms = bitcoin.payments.p2ms({ m: 2, pubkeys: pubkeys, network: regtest }) const p2ms = bitcoin.payments.p2ms({
const p2sh = bitcoin.payments.p2sh({ redeem: p2ms, network: regtest }) m: 2,
pubkeys,
const unspent = await regtestUtils.faucet(p2sh.address, 2e4) network: _regtest_1.network,
});
const txb = new bitcoin.TransactionBuilder(regtest) const p2sh = bitcoin.payments.p2sh({ redeem: p2ms, network: _regtest_1.network });
txb.addInput(unspent.txId, unspent.vout) const unspent = await regtestUtils.faucet(p2sh.address, 2e4);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.addInput(unspent.txId, unspent.vout);
txb.sign(0, keyPairs[0], p2sh.redeem.output) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 1e4);
txb.sign(0, keyPairs[2], p2sh.redeem.output) txb.sign(0, keyPairs[0], p2sh.redeem.output);
const tx = txb.build() txb.sign(0, keyPairs[2], p2sh.redeem.output);
const tx = txb.build();
// build and broadcast to the Bitcoin RegTest network // build and broadcast to the Bitcoin RegTest network
await regtestUtils.broadcast(tx.toHex()) await regtestUtils.broadcast(tx.toHex());
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 1e4 value: 1e4,
}) });
}) });
// @ts-ignore
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input', async () => { it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WPKH) input', async () => {
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) const keyPair = bitcoin.ECPair.makeRandom({ network: _regtest_1.network });
const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network: regtest }) const p2wpkh = bitcoin.payments.p2wpkh({
const p2sh = bitcoin.payments.p2sh({ redeem: p2wpkh, network: regtest }) pubkey: keyPair.publicKey,
network: _regtest_1.network,
const unspent = await regtestUtils.faucet(p2sh.address, 5e4) });
const p2sh = bitcoin.payments.p2sh({ redeem: p2wpkh, network: _regtest_1.network });
const txb = new bitcoin.TransactionBuilder(regtest) const unspent = await regtestUtils.faucet(p2sh.address, 5e4);
txb.addInput(unspent.txId, unspent.vout) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) txb.addInput(unspent.txId, unspent.vout);
txb.sign(0, keyPair, p2sh.redeem.output, null, unspent.value) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4);
txb.sign(0, keyPair, p2sh.redeem.output, null, unspent.value);
const tx = txb.build() const tx = txb.build();
// build and broadcast to the Bitcoin RegTest network // build and broadcast to the Bitcoin RegTest network
await regtestUtils.broadcast(tx.toHex()) await regtestUtils.broadcast(tx.toHex());
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 2e4 value: 2e4,
}) });
}) });
// @ts-ignore
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', async () => { it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WPKH input', async () => {
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) const keyPair = bitcoin.ECPair.makeRandom({ network: _regtest_1.network });
const p2wpkh = bitcoin.payments.p2wpkh({ pubkey: keyPair.publicKey, network: regtest }) const p2wpkh = bitcoin.payments.p2wpkh({
pubkey: keyPair.publicKey,
const unspent = await regtestUtils.faucetComplex(p2wpkh.address, 5e4) network: _regtest_1.network,
});
const unspent = await regtestUtils.faucetComplex(p2wpkh.address, 5e4);
// XXX: build the Transaction w/ a P2WPKH input // XXX: build the Transaction w/ a P2WPKH input
const txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.addInput(unspent.txId, unspent.vout, null, p2wpkh.output) // NOTE: provide the prevOutScript! txb.addInput(unspent.txId, unspent.vout, null, p2wpkh.output); // NOTE: provide the prevOutScript!
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4);
txb.sign(0, keyPair, null, null, unspent.value) // NOTE: no redeem script txb.sign(0, keyPair, null, null, unspent.value); // NOTE: no redeem script
const tx = txb.build() const tx = txb.build();
// build and broadcast (the P2WPKH transaction) to the Bitcoin RegTest network // build and broadcast (the P2WPKH transaction) to the Bitcoin RegTest network
await regtestUtils.broadcast(tx.toHex()) await regtestUtils.broadcast(tx.toHex());
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 2e4 value: 2e4,
}) });
}) });
// @ts-ignore
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input', async () => { it('can create (and broadcast via 3PBP) a Transaction, w/ a P2WSH(P2PK) input', async () => {
const keyPair = bitcoin.ECPair.makeRandom({ network: regtest }) const keyPair = bitcoin.ECPair.makeRandom({ network: _regtest_1.network });
const p2pk = bitcoin.payments.p2pk({ pubkey: keyPair.publicKey, network: regtest }) const p2pk = bitcoin.payments.p2pk({
const p2wsh = bitcoin.payments.p2wsh({ redeem: p2pk, network: regtest }) pubkey: keyPair.publicKey,
network: _regtest_1.network,
const unspent = await regtestUtils.faucetComplex(p2wsh.address, 5e4) });
const p2wsh = bitcoin.payments.p2wsh({ redeem: p2pk, network: _regtest_1.network });
const unspent = await regtestUtils.faucetComplex(p2wsh.address, 5e4);
// XXX: build the Transaction w/ a P2WSH input // XXX: build the Transaction w/ a P2WSH input
const txb = new bitcoin.TransactionBuilder(regtest) const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
txb.addInput(unspent.txId, unspent.vout, null, p2wsh.output) // NOTE: provide the prevOutScript! txb.addInput(unspent.txId, unspent.vout, null, p2wsh.output); // NOTE: provide the prevOutScript!
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4) txb.addOutput(regtestUtils.RANDOM_ADDRESS, 2e4);
txb.sign(0, keyPair, null, null, 5e4, p2wsh.redeem.output) // NOTE: provide a witnessScript! txb.sign(0, keyPair, null, null, 5e4, p2wsh.redeem.output); // NOTE: provide a witnessScript!
const tx = txb.build() const tx = txb.build();
// build and broadcast (the P2WSH transaction) to the Bitcoin RegTest network // build and broadcast (the P2WSH transaction) to the Bitcoin RegTest network
await regtestUtils.broadcast(tx.toHex()) await regtestUtils.broadcast(tx.toHex());
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 2e4 value: 2e4,
}) });
}) });
it('can create (and broadcast via 3PBP) a Transaction, w/ a ' +
it('can create (and broadcast via 3PBP) a Transaction, w/ a P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input', async () => { 'P2SH(P2WSH(P2MS(3 of 4))) (SegWit multisig) input',
// @ts-ignore
async () => {
const keyPairs = [ const keyPairs = [
bitcoin.ECPair.makeRandom({ network: regtest }), bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
bitcoin.ECPair.makeRandom({ network: regtest }), bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
bitcoin.ECPair.makeRandom({ network: regtest }), bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
bitcoin.ECPair.makeRandom({ network: regtest }) bitcoin.ECPair.makeRandom({ network: _regtest_1.network }),
] ];
const pubkeys = keyPairs.map(x => x.publicKey) const pubkeys = keyPairs.map(x => x.publicKey);
const p2ms = bitcoin.payments.p2ms({ m: 3, pubkeys, network: _regtest_1.network });
const p2ms = bitcoin.payments.p2ms({ m: 3, pubkeys, network: regtest }) const p2wsh = bitcoin.payments.p2wsh({ redeem: p2ms, network: _regtest_1.network });
const p2wsh = bitcoin.payments.p2wsh({ redeem: p2ms, network: regtest }) const p2sh = bitcoin.payments.p2sh({ redeem: p2wsh, network: _regtest_1.network });
const p2sh = bitcoin.payments.p2sh({ redeem: p2wsh, network: regtest }) const unspent = await regtestUtils.faucet(p2sh.address, 6e4);
const txb = new bitcoin.TransactionBuilder(_regtest_1.network);
const unspent = await regtestUtils.faucet(p2sh.address, 6e4) txb.addInput(unspent.txId, unspent.vout, null, p2sh.output);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 3e4);
const txb = new bitcoin.TransactionBuilder(regtest) txb.sign(0, keyPairs[0], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output);
txb.addInput(unspent.txId, unspent.vout, null, p2sh.output) txb.sign(0, keyPairs[2], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output);
txb.addOutput(regtestUtils.RANDOM_ADDRESS, 3e4) txb.sign(0, keyPairs[3], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output);
txb.sign(0, keyPairs[0], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output) const tx = txb.build();
txb.sign(0, keyPairs[2], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output)
txb.sign(0, keyPairs[3], p2sh.redeem.output, null, unspent.value, p2wsh.redeem.output)
const tx = txb.build()
// build and broadcast to the Bitcoin RegTest network // build and broadcast to the Bitcoin RegTest network
await regtestUtils.broadcast(tx.toHex()) await regtestUtils.broadcast(tx.toHex());
await regtestUtils.verify({ await regtestUtils.verify({
txId: tx.getId(), txId: tx.getId(),
address: regtestUtils.RANDOM_ADDRESS, address: regtestUtils.RANDOM_ADDRESS,
vout: 0, vout: 0,
value: 3e4 value: 3e4,
}) });
}) });
it('can verify Transaction (P2PKH) signatures', () => { it('can verify Transaction (P2PKH) signatures', () => {
const txHex = '010000000321c5f7e7bc98b3feda84aad36a5c99a02bcb8823a2f3eccbcd5da209698b5c20000000006b48304502210099e021772830207cf7c55b69948d3b16b4dcbf1f55a9cd80ebf8221a169735f9022064d33f11d62cd28240b3862afc0b901adc9f231c7124dd19bdb30367b61964c50121032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63dffffffff8a75ce85441ddb3f342708ee33cc8ed418b07d9ba9e0e7c4e1cccfe9f52d8a88000000006946304302207916c23dae212c95a920423902fa44e939fb3d542f4478a7b46e9cde53705800021f0d74e9504146e404c1b8f9cba4dff2d4782e3075491c9ed07ce4a7d1c4461a01210216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2affffffffdfef93f69fe32e944fad79fa8f882b3a155d80383252348caba1a77a5abbf7ef000000006b483045022100faa6e9ca289b46c64764a624c59ac30d9abcf1d4a04c4de9089e67cbe0d300a502206930afa683f6807502de5c2431bf9a1fd333c8a2910a76304df0f3d23d83443f0121039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18fffffffff01ff4b0000000000001976a9146c86476d1d85cd60116cd122a274e6a570a5a35c88acc96d0700' const txHex = '010000000321c5f7e7bc98b3feda84aad36a5c99a02bcb8823a2f3eccbcd5da209698b' +
'5c20000000006b48304502210099e021772830207cf7c55b69948d3b16b4dcbf1f55a9' +
'cd80ebf8221a169735f9022064d33f11d62cd28240b3862afc0b901adc9f231c7124dd' +
'19bdb30367b61964c50121032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f' +
'29f14ec605d62fb63dffffffff8a75ce85441ddb3f342708ee33cc8ed418b07d9ba9e0' +
'e7c4e1cccfe9f52d8a88000000006946304302207916c23dae212c95a920423902fa44' +
'e939fb3d542f4478a7b46e9cde53705800021f0d74e9504146e404c1b8f9cba4dff2d4' +
'782e3075491c9ed07ce4a7d1c4461a01210216c92abe433106491bdeb4a261226f20f5' +
'a4ac86220cc6e37655aac6bf3c1f2affffffffdfef93f69fe32e944fad79fa8f882b3a' +
'155d80383252348caba1a77a5abbf7ef000000006b483045022100faa6e9ca289b46c6' +
'4764a624c59ac30d9abcf1d4a04c4de9089e67cbe0d300a502206930afa683f6807502' +
'de5c2431bf9a1fd333c8a2910a76304df0f3d23d83443f0121039e05da8b8ea4f9868e' +
'cebb25998c7701542986233f4401799551fbecf316b18fffffffff01ff4b0000000000' +
'001976a9146c86476d1d85cd60116cd122a274e6a570a5a35c88acc96d0700';
const keyPairs = [ const keyPairs = [
'032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d', '032b4c06c06c3ec0b7fa29519dfa5aae193ee2cc35ca127f29f14ec605d62fb63d',
'0216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2a', '0216c92abe433106491bdeb4a261226f20f5a4ac86220cc6e37655aac6bf3c1f2a',
'039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18f' '039e05da8b8ea4f9868ecebb25998c7701542986233f4401799551fbecf316b18f',
].map(q => { return bitcoin.ECPair.fromPublicKey(Buffer.from(q, 'hex')) }) ].map(q => {
return bitcoin.ECPair.fromPublicKey(Buffer.from(q, 'hex'));
const tx = bitcoin.Transaction.fromHex(txHex) });
const tx = bitcoin.Transaction.fromHex(txHex);
tx.ins.forEach((input, i) => { tx.ins.forEach((input, i) => {
const keyPair = keyPairs[i] const keyPair = keyPairs[i];
const p2pkh = bitcoin.payments.p2pkh({ const p2pkh = bitcoin.payments.p2pkh({
pubkey: keyPair.publicKey, pubkey: keyPair.publicKey,
input: input.script input: input.script,
}) });
const ss = bitcoin.script.signature.decode(p2pkh.signature);
const ss = bitcoin.script.signature.decode(p2pkh.signature) const hash = tx.hashForSignature(i, p2pkh.output, ss.hashType);
const hash = tx.hashForSignature(i, p2pkh.output, ss.hashType) assert.strictEqual(keyPair.verify(hash, ss.signature), true);
});
assert.strictEqual(keyPair.verify(hash, ss.signature), true) });
})
})
it('can verify Transaction (P2SH(P2WPKH)) signatures', () => { it('can verify Transaction (P2SH(P2WPKH)) signatures', () => {
const utxos = { const utxos = {
'f72d1d83ac40fcedd01415751556a905844ab5f44bbb7728565ebb91b1590109:0': { 'f72d1d83ac40fcedd01415751556a905844ab5f44bbb7728565ebb91b1590109:0': {
value: 50000 value: 50000,
} },
} };
const txHex = '02000000000101090159b191bb5e562877bb4bf4b54a8405a95615751514d0edfc40ac' +
const txHex = '02000000000101090159b191bb5e562877bb4bf4b54a8405a95615751514d0edfc40ac831d2df7000000001716001435a179e5516947a39ae9c8a25e9fe62c0fc598edffffffff01204e0000000000001976a91431d43308d3c886d53e9ae8a45728370571ff456988ac0247304402206ec41f685b997a51f325b07ee852e82a535f6b52ef54485cc133e05168aa052a022070bafa86108acb51c77b2b259ae8fb7fd1efa10fef804fcfe9b13c2db719acf5012103fb03e9d0a9af86cbed94225dbb8bb70f6b82109bce0a61ddcf41dab6cbb4871100000000' '831d2df7000000001716001435a179e5516947a39ae9c8a25e9fe62c0fc598edffffff' +
const tx = bitcoin.Transaction.fromHex(txHex) 'ff01204e0000000000001976a91431d43308d3c886d53e9ae8a45728370571ff456988' +
'ac0247304402206ec41f685b997a51f325b07ee852e82a535f6b52ef54485cc133e051' +
'68aa052a022070bafa86108acb51c77b2b259ae8fb7fd1efa10fef804fcfe9b13c2db7' +
'19acf5012103fb03e9d0a9af86cbed94225dbb8bb70f6b82109bce0a61ddcf41dab6cb' +
'b4871100000000';
const tx = bitcoin.Transaction.fromHex(txHex);
tx.ins.forEach((input, i) => { tx.ins.forEach((input, i) => {
const txId = Buffer.from(input.hash).reverse().toString('hex') // @ts-ignore
const utxo = utxos[`${txId}:${i}`] const txId = Buffer.from(input.hash)
if (!utxo) throw new Error('Missing utxo') .reverse()
.toString('hex');
const utxo = utxos[`${txId}:${i}`];
if (!utxo)
throw new Error('Missing utxo');
const p2sh = bitcoin.payments.p2sh({ const p2sh = bitcoin.payments.p2sh({
input: input.script, input: input.script,
witness: input.witness witness: input.witness,
}) });
const p2wpkh = bitcoin.payments.p2wpkh(p2sh.redeem) const p2wpkh = bitcoin.payments.p2wpkh(p2sh.redeem);
const p2pkh = bitcoin.payments.p2pkh({ pubkey: p2wpkh.pubkey }) // because P2WPKH is annoying const p2pkh = bitcoin.payments.p2pkh({ pubkey: p2wpkh.pubkey }); // because P2WPKH is annoying
const ss = bitcoin.script.signature.decode(p2wpkh.signature);
const ss = bitcoin.script.signature.decode(p2wpkh.signature) const hash = tx.hashForWitnessV0(i, p2pkh.output, utxo.value, ss.hashType);
const hash = tx.hashForWitnessV0(i, p2pkh.output, utxo.value, ss.hashType) // aka, cQ3EtF4mApRcogNGSeyPTKbmfxxn3Yfb1wecfKSws9a8bnYuxoAk
const keyPair = bitcoin.ECPair.fromPublicKey(p2wpkh.pubkey) // aka, cQ3EtF4mApRcogNGSeyPTKbmfxxn3Yfb1wecfKSws9a8bnYuxoAk const keyPair = bitcoin.ECPair.fromPublicKey(p2wpkh.pubkey);
assert.strictEqual(keyPair.verify(hash, ss.signature), true);
assert.strictEqual(keyPair.verify(hash, ss.signature), true) });
}) });
}) });
})

120
test/payments.js

@ -1,71 +1,69 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const u = require('./payments.utils') const __1 = require("..");
const { describe, it } = require('mocha');
;['embed', 'p2ms', 'p2pk', 'p2pkh', 'p2sh', 'p2wpkh', 'p2wsh'].forEach(p => { const assert = require('assert');
const u = require('./payments.utils');
['embed', 'p2ms', 'p2pk', 'p2pkh', 'p2sh', 'p2wpkh', 'p2wsh'].forEach(p => {
describe(p, () => { describe(p, () => {
let fn const fn = __1.payments[p];
let payment = require('../src/payments/' + p) const fixtures = require('../ts_test/fixtures/' + p);
if (p === 'embed') {
fn = payment.p2data
} else {
fn = payment[p]
}
const fixtures = require('./fixtures/' + p)
fixtures.valid.forEach((f, i) => { fixtures.valid.forEach((f, i) => {
it(f.description + ' as expected', () => { it(f.description + ' as expected', () => {
const args = u.preform(f.arguments) const args = u.preform(f.arguments);
const actual = fn(args, f.options) const actual = fn(args, f.options);
u.equate(actual, f.expected, f.arguments);
u.equate(actual, f.expected, f.arguments) });
})
it(f.description + ' as expected (no validation)', () => { it(f.description + ' as expected (no validation)', () => {
const args = u.preform(f.arguments) const args = u.preform(f.arguments);
const actual = fn(args, Object.assign({}, f.options, { const actual = fn(args,
validate: false // @ts-ignore
})) Object.assign({}, f.options, {
validate: false,
u.equate(actual, f.expected, f.arguments) }));
}) u.equate(actual, f.expected, f.arguments);
}) });
});
fixtures.invalid.forEach(f => { fixtures.invalid.forEach(f => {
it('throws ' + f.exception + (f.description ? ('for ' + f.description) : ''), () => { it('throws ' + f.exception + (f.description ? 'for ' + f.description : ''), () => {
const args = u.preform(f.arguments) const args = u.preform(f.arguments);
assert.throws(() => { assert.throws(() => {
fn(args, f.options) fn(args, f.options);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
// cross-verify dynamically too // cross-verify dynamically too
if (!fixtures.dynamic) return if (!fixtures.dynamic)
const { depends, details } = fixtures.dynamic return;
const { depends, details } = fixtures.dynamic;
details.forEach(f => { details.forEach(f => {
const detail = u.preform(f) const detail = u.preform(f);
const disabled = {} const disabled = {};
if (f.disabled) f.disabled.forEach(k => { disabled[k] = true }) if (f.disabled)
f.disabled.forEach(k => {
for (let key in depends) { disabled[k] = true;
if (key in disabled) continue });
const dependencies = depends[key] for (const key in depends) {
if (key in disabled)
continue;
const dependencies = depends[key];
dependencies.forEach(dependency => { dependencies.forEach(dependency => {
if (!Array.isArray(dependency)) dependency = [dependency] if (!Array.isArray(dependency))
dependency = [dependency];
const args = {} const args = {};
dependency.forEach(d => { u.from(d, detail, args) }) dependency.forEach(d => {
const expected = u.from(key, detail) u.from(d, detail, args);
});
it(f.description + ', ' + key + ' derives from ' + JSON.stringify(dependency), () => { const expected = u.from(key, detail);
u.equate(fn(args), expected) it(f.description +
}) ', ' +
}) key +
' derives from ' +
JSON.stringify(dependency), () => {
u.equate(fn(args), expected);
});
});
} }
}) });
}) });
}) });

241
test/payments.utils.js

@ -1,134 +1,169 @@
const t = require('assert') "use strict";
const bscript = require('../src/script') Object.defineProperty(exports, "__esModule", { value: true });
const BNETWORKS = require('../src/networks') const __1 = require("..");
const t = require('assert');
function tryHex (x) { function tryHex(x) {
if (Buffer.isBuffer(x)) return x.toString('hex') if (Buffer.isBuffer(x))
if (Array.isArray(x)) return x.map(tryHex) return x.toString('hex');
return x if (Array.isArray(x))
return x.map(tryHex);
return x;
} }
function fromHex(x) {
function fromHex (x) { if (typeof x === 'string')
if (typeof x === 'string') return Buffer.from(x, 'hex') return Buffer.from(x, 'hex');
if (Array.isArray(x)) return x.map(fromHex) if (Array.isArray(x))
return x return x.map(fromHex);
return x;
} }
function tryASM (x) { function tryASM(x) {
if (Buffer.isBuffer(x)) return bscript.toASM(x) if (Buffer.isBuffer(x))
return x return __1.script.toASM(x);
return x;
} }
function asmToBuffer (x) { function asmToBuffer(x) {
if (x === '') return Buffer.alloc(0) if (x === '')
return bscript.fromASM(x) return Buffer.alloc(0);
return __1.script.fromASM(x);
} }
function carryOver (a, b) { function carryOver(a, b) {
for (let k in b) { for (const k in b) {
if (k) {
if (k in a && k === 'redeem') { if (k in a && k === 'redeem') {
carryOver(a[k], b[k]) carryOver(a[k], b[k]);
continue continue;
} }
// don't, the value was specified // don't, the value was specified
if (k in a) continue if (k in a)
continue;
// otherwise, expect match // otherwise, expect match
a[k] = b[k] a[k] = b[k];
}
} }
} }
function equateBase(a, b, context) {
function equateBase (a, b, context) { if ('output' in b)
if ('output' in b) t.strictEqual(tryASM(a.output), tryASM(b.output), `Inequal ${context}output`) t.strictEqual(tryASM(a.output), tryASM(b.output), `Inequal ${context}output`);
if ('input' in b) t.strictEqual(tryASM(a.input), tryASM(b.input), `Inequal ${context}input`) if ('input' in b)
if ('witness' in b) t.deepStrictEqual(tryHex(a.witness), tryHex(b.witness), `Inequal ${context}witness`) t.strictEqual(tryASM(a.input), tryASM(b.input), `Inequal ${context}input`);
if ('witness' in b)
t.deepStrictEqual(tryHex(a.witness), tryHex(b.witness), `Inequal ${context}witness`);
} }
function equate(a, b, args) {
function equate (a, b, args) { // @ts-ignore
b = Object.assign({}, b) b = Object.assign({}, b);
carryOver(b, args) carryOver(b, args);
// by null, we mean 'undefined', but JSON // by null, we mean 'undefined', but JSON
if (b.input === null) b.input = undefined if (b.input === null)
if (b.output === null) b.output = undefined b.input = undefined;
if (b.witness === null) b.witness = undefined if (b.output === null)
b.output = undefined;
if (b.witness === null)
b.witness = undefined;
if (b.redeem) { if (b.redeem) {
if (b.redeem.input === null) b.redeem.input = undefined if (b.redeem.input === null)
if (b.redeem.output === null) b.redeem.output = undefined b.redeem.input = undefined;
if (b.redeem.witness === null) b.redeem.witness = undefined if (b.redeem.output === null)
b.redeem.output = undefined;
if (b.redeem.witness === null)
b.redeem.witness = undefined;
} }
equateBase(a, b, '');
equateBase(a, b, '') if (b.redeem)
if (b.redeem) equateBase(a.redeem, b.redeem, 'redeem.') equateBase(a.redeem, b.redeem, 'redeem.');
if (b.network) t.deepStrictEqual(a.network, BNETWORKS[b.network], 'Inequal *.network') if (b.network)
t.deepStrictEqual(a.network, __1.networks[b.network], 'Inequal *.network');
// contextual // contextual
if (b.signature === null) b.signature = undefined if (b.signature === null)
if (b.signatures === null) b.signatures = undefined b.signature = undefined;
if ('address' in b) t.strictEqual(a.address, b.address, 'Inequal *.address') if (b.signatures === null)
if ('hash' in b) t.strictEqual(tryHex(a.hash), tryHex(b.hash), 'Inequal *.hash') b.signatures = undefined;
if ('pubkey' in b) t.strictEqual(tryHex(a.pubkey), tryHex(b.pubkey), 'Inequal *.pubkey') if ('address' in b)
if ('signature' in b) t.strictEqual(tryHex(a.signature), tryHex(b.signature), 'Inequal signature') t.strictEqual(a.address, b.address, 'Inequal *.address');
if ('m' in b) t.strictEqual(a.m, b.m, 'Inequal *.m') if ('hash' in b)
if ('n' in b) t.strictEqual(a.n, b.n, 'Inequal *.n') t.strictEqual(tryHex(a.hash), tryHex(b.hash), 'Inequal *.hash');
if ('pubkeys' in b) t.deepStrictEqual(tryHex(a.pubkeys), tryHex(b.pubkeys), 'Inequal *.pubkeys') if ('pubkey' in b)
if ('signatures' in b) t.deepStrictEqual(tryHex(a.signatures), tryHex(b.signatures), 'Inequal *.signatures') t.strictEqual(tryHex(a.pubkey), tryHex(b.pubkey), 'Inequal *.pubkey');
if ('data' in b) t.deepStrictEqual(tryHex(a.data), tryHex(b.data), 'Inequal *.data') if ('signature' in b)
t.strictEqual(tryHex(a.signature), tryHex(b.signature), 'Inequal signature');
if ('m' in b)
t.strictEqual(a.m, b.m, 'Inequal *.m');
if ('n' in b)
t.strictEqual(a.n, b.n, 'Inequal *.n');
if ('pubkeys' in b)
t.deepStrictEqual(tryHex(a.pubkeys), tryHex(b.pubkeys), 'Inequal *.pubkeys');
if ('signatures' in b)
t.deepStrictEqual(tryHex(a.signatures), tryHex(b.signatures), 'Inequal *.signatures');
if ('data' in b)
t.deepStrictEqual(tryHex(a.data), tryHex(b.data), 'Inequal *.data');
} }
function preform(x) {
function preform (x) { // @ts-ignore
x = Object.assign({}, x) x = Object.assign({}, x);
if (x.network)
if (x.network) x.network = BNETWORKS[x.network] x.network = __1.networks[x.network];
if (typeof x.inputHex === 'string') { if (typeof x.inputHex === 'string') {
x.input = Buffer.from(x.inputHex, 'hex') x.input = Buffer.from(x.inputHex, 'hex');
delete x.inputHex delete x.inputHex;
} }
if (typeof x.outputHex === 'string') { if (typeof x.outputHex === 'string') {
x.output = Buffer.from(x.outputHex, 'hex') x.output = Buffer.from(x.outputHex, 'hex');
delete x.outputHex delete x.outputHex;
} }
if (typeof x.output === 'string') x.output = asmToBuffer(x.output) if (typeof x.output === 'string')
if (typeof x.input === 'string') x.input = asmToBuffer(x.input) x.output = asmToBuffer(x.output);
if (Array.isArray(x.witness)) x.witness = x.witness.map(fromHex) if (typeof x.input === 'string')
x.input = asmToBuffer(x.input);
if (x.data) x.data = x.data.map(fromHex) if (Array.isArray(x.witness))
if (x.hash) x.hash = Buffer.from(x.hash, 'hex') x.witness = x.witness.map(fromHex);
if (x.pubkey) x.pubkey = Buffer.from(x.pubkey, 'hex') if (x.data)
if (x.signature) x.signature = Buffer.from(x.signature, 'hex') x.data = x.data.map(fromHex);
if (x.pubkeys) x.pubkeys = x.pubkeys.map(fromHex) if (x.hash)
if (x.signatures) x.signatures = x.signatures.map(y => { return Number.isFinite(y) ? y : Buffer.from(y, 'hex') }) x.hash = Buffer.from(x.hash, 'hex');
if (x.pubkey)
x.pubkey = Buffer.from(x.pubkey, 'hex');
if (x.signature)
x.signature = Buffer.from(x.signature, 'hex');
if (x.pubkeys)
x.pubkeys = x.pubkeys.map(fromHex);
if (x.signatures)
x.signatures = x.signatures.map(y => {
// @ts-ignore
return Number.isFinite(y) ? y : Buffer.from(y, 'hex');
});
if (x.redeem) { if (x.redeem) {
x.redeem = Object.assign({}, x.redeem) // @ts-ignore
if (typeof x.redeem.input === 'string') x.redeem.input = asmToBuffer(x.redeem.input) x.redeem = Object.assign({}, x.redeem);
if (typeof x.redeem.output === 'string') x.redeem.output = asmToBuffer(x.redeem.output) if (typeof x.redeem.input === 'string')
if (Array.isArray(x.redeem.witness)) x.redeem.witness = x.redeem.witness.map(fromHex) x.redeem.input = asmToBuffer(x.redeem.input);
if (x.redeem.network) x.redeem.network = BNETWORKS[x.redeem.network] if (typeof x.redeem.output === 'string')
x.redeem.output = asmToBuffer(x.redeem.output);
if (Array.isArray(x.redeem.witness))
x.redeem.witness = x.redeem.witness.map(fromHex);
if (x.redeem.network)
x.redeem.network = __1.networks[x.redeem.network];
} }
return x;
return x
} }
function from(path, object, result) {
function from (path, object, result) { path = path.split('.');
path = path.split('.') result = result || {};
result = result || {} let r = result;
let r = result
path.forEach((k, i) => { path.forEach((k, i) => {
if (i < path.length - 1) { if (i < path.length - 1) {
r[k] = r[k] || {} r[k] = r[k] || {};
// recurse // recurse
r = r[k] r = r[k];
object = object[k] object = object[k];
} else { }
r[k] = object[k] else {
r[k] = object[k];
} }
}) });
return result;
return result
} }
module.exports = { module.exports = {
from, from,
equate, equate,
preform preform,
} };

196
test/script.js

@ -1,157 +1,133 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bscript = require('../src/script') const __1 = require("..");
const minimalData = require('minimaldata') const { describe, it } = require('mocha');
const assert = require('assert');
const fixtures = require('./fixtures/script.json') const minimalData = require('minimaldata');
const fixtures2 = require('./fixtures/templates.json') const fixtures = require('../ts_test/fixtures/script.json');
const fixtures2 = require('../ts_test/fixtures/templates.json');
describe('script', () => { describe('script', () => {
// TODO // TODO
describe('isCanonicalPubKey', () => { describe('isCanonicalPubKey', () => {
it('rejects if not provided a Buffer', () => { it('rejects if not provided a Buffer', () => {
assert.strictEqual(false, bscript.isCanonicalPubKey(0)) // @ts-ignore
}) assert.strictEqual(false, __1.script.isCanonicalPubKey(0));
});
it('rejects smaller than 33', () => { it('rejects smaller than 33', () => {
for (var i = 0; i < 33; i++) { for (let i = 0; i < 33; i++) {
assert.strictEqual(false, bscript.isCanonicalPubKey(Buffer.from('', i))) assert.strictEqual(false, __1.script.isCanonicalPubKey(Buffer.allocUnsafe(i)));
} }
}) });
}) });
describe.skip('isCanonicalScriptSignature', () => { describe.skip('isCanonicalScriptSignature', () => {
}) console.log('skip me');
});
describe('fromASM/toASM', () => { describe('fromASM/toASM', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('encodes/decodes ' + f.asm, () => { it('encodes/decodes ' + f.asm, () => {
const script = bscript.fromASM(f.asm) const script = __1.script.fromASM(f.asm);
assert.strictEqual(bscript.toASM(script), f.asm) assert.strictEqual(__1.script.toASM(script), f.asm);
}) });
}) });
fixtures.invalid.fromASM.forEach(f => { fixtures.invalid.fromASM.forEach(f => {
it('throws ' + f.description, () => { it('throws ' + f.description, () => {
assert.throws(() => { assert.throws(() => {
bscript.fromASM(f.script) __1.script.fromASM(f.script);
}, new RegExp(f.description)) }, new RegExp(f.description));
}) });
}) });
}) });
describe('fromASM/toASM (templates)', () => { describe('fromASM/toASM (templates)', () => {
fixtures2.valid.forEach(f => { fixtures2.valid.forEach(f => {
if (f.inputHex) { if (f.inputHex) {
const ih = bscript.toASM(Buffer.from(f.inputHex, 'hex')) const ih = __1.script.toASM(Buffer.from(f.inputHex, 'hex'));
it('encodes/decodes ' + ih, () => { it('encodes/decodes ' + ih, () => {
const script = bscript.fromASM(f.input) const script = __1.script.fromASM(f.input);
assert.strictEqual(script.toString('hex'), f.inputHex) assert.strictEqual(script.toString('hex'), f.inputHex);
assert.strictEqual(bscript.toASM(script), f.input) assert.strictEqual(__1.script.toASM(script), f.input);
}) });
} }
if (f.outputHex) { if (f.outputHex) {
it('encodes/decodes ' + f.output, () => { it('encodes/decodes ' + f.output, () => {
const script = bscript.fromASM(f.output) const script = __1.script.fromASM(f.output);
assert.strictEqual(script.toString('hex'), f.outputHex) assert.strictEqual(script.toString('hex'), f.outputHex);
assert.strictEqual(bscript.toASM(script), f.output) assert.strictEqual(__1.script.toASM(script), f.output);
}) });
} }
}) });
}) });
describe('isPushOnly', () => { describe('isPushOnly', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('returns ' + !!f.stack + ' for ' + f.asm, () => { it('returns ' + !!f.stack + ' for ' + f.asm, () => {
const script = bscript.fromASM(f.asm) const script = __1.script.fromASM(f.asm);
const chunks = bscript.decompile(script) const chunks = __1.script.decompile(script);
assert.strictEqual(__1.script.isPushOnly(chunks), !!f.stack);
assert.strictEqual(bscript.isPushOnly(chunks), !!f.stack) });
}) });
}) });
})
describe('toStack', () => { describe('toStack', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('returns ' + !!f.stack + ' for ' + f.asm, () => { it('returns ' + !!f.stack + ' for ' + f.asm, () => {
if (!f.stack || !f.asm) return if (!f.stack || !f.asm)
return;
const script = bscript.fromASM(f.asm) const script = __1.script.fromASM(f.asm);
const stack = __1.script.toStack(script);
const stack = bscript.toStack(script)
assert.deepStrictEqual(stack.map(x => { assert.deepStrictEqual(stack.map(x => {
return x.toString('hex') return x.toString('hex');
}), f.stack) }), f.stack);
assert.strictEqual(__1.script.toASM(__1.script.compile(stack)), f.asm, 'should rebuild same script from stack');
assert.strictEqual(bscript.toASM(bscript.compile(stack)), f.asm, 'should rebuild same script from stack') });
}) });
}) });
})
describe('compile (via fromASM)', () => { describe('compile (via fromASM)', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('(' + f.type + ') compiles ' + f.asm, () => { it('(' + f.type + ') compiles ' + f.asm, () => {
const scriptSig = bscript.fromASM(f.asm) const scriptSig = __1.script.fromASM(f.asm);
assert.strictEqual(scriptSig.toString('hex'), f.script);
assert.strictEqual(scriptSig.toString('hex'), f.script)
if (f.nonstandard) { if (f.nonstandard) {
const scriptSigNS = bscript.fromASM(f.nonstandard.scriptSig) const scriptSigNS = __1.script.fromASM(f.nonstandard.scriptSig);
assert.strictEqual(scriptSigNS.toString('hex'), f.script);
assert.strictEqual(scriptSigNS.toString('hex'), f.script)
} }
}) });
}) });
}) });
describe('decompile', () => { describe('decompile', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('decompiles ' + f.asm, () => { it('decompiles ' + f.asm, () => {
const chunks = bscript.decompile(Buffer.from(f.script, 'hex')) const chunks = __1.script.decompile(Buffer.from(f.script, 'hex'));
assert.strictEqual(__1.script.compile(chunks).toString('hex'), f.script);
assert.strictEqual(bscript.compile(chunks).toString('hex'), f.script) assert.strictEqual(__1.script.toASM(chunks), f.asm);
assert.strictEqual(bscript.toASM(chunks), f.asm)
if (f.nonstandard) { if (f.nonstandard) {
const chunksNS = bscript.decompile(Buffer.from(f.nonstandard.scriptSigHex, 'hex')) const chunksNS = __1.script.decompile(Buffer.from(f.nonstandard.scriptSigHex, 'hex'));
assert.strictEqual(__1.script.compile(chunksNS).toString('hex'), f.script);
assert.strictEqual(bscript.compile(chunksNS).toString('hex'), f.script)
// toASM converts verbatim, only `compile` transforms the script to a minimalpush compliant script // toASM converts verbatim, only `compile` transforms the script to a minimalpush compliant script
assert.strictEqual(bscript.toASM(chunksNS), f.nonstandard.scriptSig) assert.strictEqual(__1.script.toASM(chunksNS), f.nonstandard.scriptSig);
} }
}) });
}) });
fixtures.invalid.decompile.forEach(f => { fixtures.invalid.decompile.forEach(f => {
it('fails to decompile ' + f.script + ', because "' + f.description + '"', () => { it('fails to decompile ' + f.script + ', because "' + f.description + '"', () => {
const chunks = bscript.decompile(Buffer.from(f.script, 'hex')) const chunks = __1.script.decompile(Buffer.from(f.script, 'hex'));
assert.strictEqual(chunks, null);
assert.strictEqual(chunks, null) });
}) });
}) });
})
describe('SCRIPT_VERIFY_MINIMALDATA policy', () => { describe('SCRIPT_VERIFY_MINIMALDATA policy', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('compliant for ' + f.type + ' scriptSig ' + f.asm, () => { it('compliant for ' + f.type + ' scriptSig ' + f.asm, () => {
const script = Buffer.from(f.script, 'hex') const script = Buffer.from(f.script, 'hex');
assert(minimalData(script));
assert(minimalData(script)) });
}) });
}) function testEncodingForSize(i) {
function testEncodingForSize (i) {
it('compliant for data PUSH of length ' + i, () => { it('compliant for data PUSH of length ' + i, () => {
const buffer = Buffer.alloc(i) const buffer = Buffer.alloc(i);
const script = bscript.compile([buffer]) const script = __1.script.compile([buffer]);
assert(minimalData(script), 'Failed for ' + i + ' length script: ' + script.toString('hex'));
assert(minimalData(script), 'Failed for ' + i + ' length script: ' + script.toString('hex')) });
})
} }
for (let i = 0; i < 520; ++i) {
for (var i = 0; i < 520; ++i) { testEncodingForSize(i);
testEncodingForSize(i)
} }
}) });
}) });

37
test/script_number.js

@ -1,26 +1,25 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const scriptNumber = require('../src/script_number') const __1 = require("..");
const fixtures = require('./fixtures/script_number.json') const { describe, it } = require('mocha');
const assert = require('assert');
const scriptNumber = __1.script.number;
const fixtures = require('../ts_test/fixtures/script_number.json');
describe('script-number', () => { describe('script-number', () => {
describe('decode', () => { describe('decode', () => {
fixtures.forEach(f => { fixtures.forEach(f => {
it(f.hex + ' returns ' + f.number, () => { it(f.hex + ' returns ' + f.number, () => {
const actual = scriptNumber.decode(Buffer.from(f.hex, 'hex'), f.bytes) const actual = scriptNumber.decode(Buffer.from(f.hex, 'hex'), f.bytes);
assert.strictEqual(actual, f.number);
assert.strictEqual(actual, f.number) });
}) });
}) });
})
describe('encode', () => { describe('encode', () => {
fixtures.forEach(f => { fixtures.forEach(f => {
it(f.number + ' returns ' + f.hex, () => { it(f.number + ' returns ' + f.hex, () => {
const actual = scriptNumber.encode(f.number) const actual = scriptNumber.encode(f.number);
assert.strictEqual(actual.toString('hex'), f.hex);
assert.strictEqual(actual.toString('hex'), f.hex) });
}) });
}) });
}) });
})

83
test/script_signature.js

@ -1,64 +1,53 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bscriptSig = require('../src/script').signature const __1 = require("..");
const Buffer = require('safe-buffer').Buffer const { describe, it } = require('mocha');
const fixtures = require('./fixtures/signature.json') const assert = require('assert');
const bscriptSig = __1.script.signature;
const fixtures = require('../ts_test/fixtures/signature.json');
describe('Script Signatures', () => { describe('Script Signatures', () => {
function fromRaw (signature) { function fromRaw(signature) {
return Buffer.concat([ return Buffer.concat([Buffer.from(signature.r, 'hex'), Buffer.from(signature.s, 'hex')], 64);
Buffer.from(signature.r, 'hex'),
Buffer.from(signature.s, 'hex')
], 64)
} }
function toRaw(signature) {
function toRaw (signature) {
return { return {
r: signature.slice(0, 32).toString('hex'), r: signature.slice(0, 32).toString('hex'),
s: signature.slice(32, 64).toString('hex') s: signature.slice(32, 64).toString('hex'),
};
} }
}
describe('encode', () => { describe('encode', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('encodes ' + f.hex, () => { it('encodes ' + f.hex, () => {
const buffer = bscriptSig.encode(fromRaw(f.raw), f.hashType) const buffer = bscriptSig.encode(fromRaw(f.raw), f.hashType);
assert.strictEqual(buffer.toString('hex'), f.hex);
assert.strictEqual(buffer.toString('hex'), f.hex) });
}) });
})
fixtures.invalid.forEach(f => { fixtures.invalid.forEach(f => {
if (!f.raw) return if (!f.raw)
return;
it('throws ' + f.exception, () => { it('throws ' + f.exception, () => {
const signature = fromRaw(f.raw) const signature = fromRaw(f.raw);
assert.throws(() => { assert.throws(() => {
bscriptSig.encode(signature, f.hashType) bscriptSig.encode(signature, f.hashType);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
describe('decode', () => { describe('decode', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('decodes ' + f.hex, () => { it('decodes ' + f.hex, () => {
const decode = bscriptSig.decode(Buffer.from(f.hex, 'hex')) const decode = bscriptSig.decode(Buffer.from(f.hex, 'hex'));
assert.deepStrictEqual(toRaw(decode.signature), f.raw);
assert.deepStrictEqual(toRaw(decode.signature), f.raw) assert.strictEqual(decode.hashType, f.hashType);
assert.strictEqual(decode.hashType, f.hashType) });
}) });
})
fixtures.invalid.forEach(f => { fixtures.invalid.forEach(f => {
it('throws on ' + f.hex, () => { it('throws on ' + f.hex, () => {
const buffer = Buffer.from(f.hex, 'hex') const buffer = Buffer.from(f.hex, 'hex');
assert.throws(() => { assert.throws(() => {
bscriptSig.decode(buffer) bscriptSig.decode(buffer);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
}) });

478
test/transaction.js

@ -1,288 +1,256 @@
const { describe, it, beforeEach } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const bscript = require('../src/script') const assert = require("assert");
const fixtures = require('./fixtures/transaction') const mocha_1 = require("mocha");
const Transaction = require('..').Transaction const __1 = require("..");
const fixtures = require('../ts_test/fixtures/transaction');
describe('Transaction', () => { const __2 = require("..");
function fromRaw (raw, noWitness) { mocha_1.describe('Transaction', () => {
const tx = new Transaction() function fromRaw(raw, noWitness) {
tx.version = raw.version const tx = new __2.Transaction();
tx.locktime = raw.locktime tx.version = raw.version;
tx.locktime = raw.locktime;
raw.ins.forEach((txIn, i) => { raw.ins.forEach((txIn, i) => {
const txHash = Buffer.from(txIn.hash, 'hex') const txHash = Buffer.from(txIn.hash, 'hex');
let scriptSig let scriptSig;
if (txIn.data) { if (txIn.data) {
scriptSig = Buffer.from(txIn.data, 'hex') scriptSig = Buffer.from(txIn.data, 'hex');
} else if (txIn.script) {
scriptSig = bscript.fromASM(txIn.script)
} }
else if (txIn.script) {
tx.addInput(txHash, txIn.index, txIn.sequence, scriptSig) scriptSig = __1.script.fromASM(txIn.script);
}
tx.addInput(txHash, txIn.index, txIn.sequence, scriptSig);
if (!noWitness && txIn.witness) { if (!noWitness && txIn.witness) {
const witness = txIn.witness.map(x => { const witness = txIn.witness.map(x => {
return Buffer.from(x, 'hex') return Buffer.from(x, 'hex');
}) });
tx.setWitness(i, witness);
tx.setWitness(i, witness)
} }
}) });
raw.outs.forEach(txOut => { raw.outs.forEach(txOut => {
let script let script;
if (txOut.data) { if (txOut.data) {
script = Buffer.from(txOut.data, 'hex') script = Buffer.from(txOut.data, 'hex');
} else if (txOut.script) { }
script = bscript.fromASM(txOut.script) else if (txOut.script) {
script = __1.script.fromASM(txOut.script);
} }
tx.addOutput(script, txOut.value);
tx.addOutput(script, txOut.value) });
}) return tx;
return tx
} }
mocha_1.describe('fromBuffer/fromHex', () => {
describe('fromBuffer/fromHex', () => { function importExport(f) {
function importExport (f) { const id = f.id || f.hash;
const id = f.id || f.hash const txHex = f.hex || f.txHex;
const txHex = f.hex || f.txHex mocha_1.it('imports ' + f.description + ' (' + id + ')', () => {
const actual = __2.Transaction.fromHex(txHex);
it('imports ' + f.description + ' (' + id + ')', () => { assert.strictEqual(actual.toHex(), txHex);
const actual = Transaction.fromHex(txHex) });
assert.strictEqual(actual.toHex(), txHex)
})
if (f.whex) { if (f.whex) {
it('imports ' + f.description + ' (' + id + ') as witness', () => { mocha_1.it('imports ' + f.description + ' (' + id + ') as witness', () => {
const actual = Transaction.fromHex(f.whex) const actual = __2.Transaction.fromHex(f.whex);
assert.strictEqual(actual.toHex(), f.whex);
assert.strictEqual(actual.toHex(), f.whex) });
})
} }
} }
fixtures.valid.forEach(importExport);
fixtures.valid.forEach(importExport) fixtures.hashForSignature.forEach(importExport);
fixtures.hashForSignature.forEach(importExport) fixtures.hashForWitnessV0.forEach(importExport);
fixtures.hashForWitnessV0.forEach(importExport)
fixtures.invalid.fromBuffer.forEach(f => { fixtures.invalid.fromBuffer.forEach(f => {
it('throws on ' + f.exception, () => { mocha_1.it('throws on ' + f.exception, () => {
assert.throws(() => { assert.throws(() => {
Transaction.fromHex(f.hex) __2.Transaction.fromHex(f.hex);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
mocha_1.it('.version should be interpreted as an int32le', () => {
it('.version should be interpreted as an int32le', () => { const txHex = 'ffffffff0000ffffffff';
const txHex = 'ffffffff0000ffffffff' const tx = __2.Transaction.fromHex(txHex);
const tx = Transaction.fromHex(txHex) assert.strictEqual(-1, tx.version);
assert.strictEqual(-1, tx.version) assert.strictEqual(0xffffffff, tx.locktime);
assert.strictEqual(0xffffffff, tx.locktime) });
}) });
}) mocha_1.describe('toBuffer/toHex', () => {
describe('toBuffer/toHex', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('exports ' + f.description + ' (' + f.id + ')', () => { mocha_1.it('exports ' + f.description + ' (' + f.id + ')', () => {
const actual = fromRaw(f.raw, true) const actual = fromRaw(f.raw, true);
assert.strictEqual(actual.toHex(), f.hex) assert.strictEqual(actual.toHex(), f.hex);
}) });
if (f.whex) { if (f.whex) {
it('exports ' + f.description + ' (' + f.id + ') as witness', () => { mocha_1.it('exports ' + f.description + ' (' + f.id + ') as witness', () => {
const wactual = fromRaw(f.raw) const wactual = fromRaw(f.raw);
assert.strictEqual(wactual.toHex(), f.whex) assert.strictEqual(wactual.toHex(), f.whex);
}) });
} }
}) });
mocha_1.it('accepts target Buffer and offset parameters', () => {
it('accepts target Buffer and offset parameters', () => { const f = fixtures.valid[0];
const f = fixtures.valid[0] const actual = fromRaw(f.raw);
const actual = fromRaw(f.raw) const byteLength = actual.byteLength();
const byteLength = actual.byteLength() const target = Buffer.alloc(byteLength * 2);
const a = actual.toBuffer(target, 0);
const target = Buffer.alloc(byteLength * 2) const b = actual.toBuffer(target, byteLength);
const a = actual.toBuffer(target, 0) assert.strictEqual(a.length, byteLength);
const b = actual.toBuffer(target, byteLength) assert.strictEqual(b.length, byteLength);
assert.strictEqual(a.toString('hex'), f.hex);
assert.strictEqual(a.length, byteLength) assert.strictEqual(b.toString('hex'), f.hex);
assert.strictEqual(b.length, byteLength) assert.deepStrictEqual(a, b);
assert.strictEqual(a.toString('hex'), f.hex) assert.deepStrictEqual(a, target.slice(0, byteLength));
assert.strictEqual(b.toString('hex'), f.hex) assert.deepStrictEqual(b, target.slice(byteLength));
assert.deepStrictEqual(a, b) });
assert.deepStrictEqual(a, target.slice(0, byteLength)) });
assert.deepStrictEqual(b, target.slice(byteLength)) mocha_1.describe('hasWitnesses', () => {
})
})
describe('hasWitnesses', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
it('detects if the transaction has witnesses: ' + (f.whex ? 'true' : 'false'), () => { mocha_1.it('detects if the transaction has witnesses: ' +
assert.strictEqual(Transaction.fromHex(f.whex ? f.whex : f.hex).hasWitnesses(), !!f.whex) (f.whex ? 'true' : 'false'), () => {
}) assert.strictEqual(__2.Transaction.fromHex(f.whex ? f.whex : f.hex).hasWitnesses(), !!f.whex);
}) });
}) });
});
describe('weight/virtualSize', () => { mocha_1.describe('weight/virtualSize', () => {
it('computes virtual size', () => { mocha_1.it('computes virtual size', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
const transaction = Transaction.fromHex(f.whex ? f.whex : f.hex) const transaction = __2.Transaction.fromHex(f.whex ? f.whex : f.hex);
assert.strictEqual(transaction.virtualSize(), f.virtualSize);
assert.strictEqual(transaction.virtualSize(), f.virtualSize) });
}) });
}) mocha_1.it('computes weight', () => {
it('computes weight', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
const transaction = Transaction.fromHex(f.whex ? f.whex : f.hex) const transaction = __2.Transaction.fromHex(f.whex ? f.whex : f.hex);
assert.strictEqual(transaction.weight(), f.weight);
assert.strictEqual(transaction.weight(), f.weight) });
}) });
}) });
}) mocha_1.describe('addInput', () => {
let prevTxHash;
describe('addInput', () => { mocha_1.beforeEach(() => {
let prevTxHash prevTxHash = Buffer.from('ffffffff00ffff000000000000000000000000000000000000000000101010ff', 'hex');
beforeEach(() => { });
prevTxHash = Buffer.from('ffffffff00ffff000000000000000000000000000000000000000000101010ff', 'hex') mocha_1.it('returns an index', () => {
}) const tx = new __2.Transaction();
assert.strictEqual(tx.addInput(prevTxHash, 0), 0);
it('returns an index', () => { assert.strictEqual(tx.addInput(prevTxHash, 0), 1);
const tx = new Transaction() });
assert.strictEqual(tx.addInput(prevTxHash, 0), 0) mocha_1.it('defaults to empty script, witness and 0xffffffff SEQUENCE number', () => {
assert.strictEqual(tx.addInput(prevTxHash, 0), 1) const tx = new __2.Transaction();
}) tx.addInput(prevTxHash, 0);
assert.strictEqual(tx.ins[0].script.length, 0);
it('defaults to empty script, witness and 0xffffffff SEQUENCE number', () => { assert.strictEqual(tx.ins[0].witness.length, 0);
const tx = new Transaction() assert.strictEqual(tx.ins[0].sequence, 0xffffffff);
tx.addInput(prevTxHash, 0) });
assert.strictEqual(tx.ins[0].script.length, 0)
assert.strictEqual(tx.ins[0].witness.length, 0)
assert.strictEqual(tx.ins[0].sequence, 0xffffffff)
})
fixtures.invalid.addInput.forEach(f => { fixtures.invalid.addInput.forEach(f => {
it('throws on ' + f.exception, () => { mocha_1.it('throws on ' + f.exception, () => {
const tx = new Transaction() const tx = new __2.Transaction();
const hash = Buffer.from(f.hash, 'hex') const hash = Buffer.from(f.hash, 'hex');
assert.throws(() => { assert.throws(() => {
tx.addInput(hash, f.index) tx.addInput(hash, f.index);
}, new RegExp(f.exception)) }, new RegExp(f.exception));
}) });
}) });
}) });
mocha_1.describe('addOutput', () => {
describe('addOutput', () => { mocha_1.it('returns an index', () => {
it('returns an index', () => { const tx = new __2.Transaction();
const tx = new Transaction() assert.strictEqual(tx.addOutput(Buffer.alloc(0), 0), 0);
assert.strictEqual(tx.addOutput(Buffer.alloc(0), 0), 0) assert.strictEqual(tx.addOutput(Buffer.alloc(0), 0), 1);
assert.strictEqual(tx.addOutput(Buffer.alloc(0), 0), 1) });
}) });
}) mocha_1.describe('clone', () => {
describe('clone', () => {
fixtures.valid.forEach(f => { fixtures.valid.forEach(f => {
let actual let actual;
let expected let expected;
mocha_1.beforeEach(() => {
beforeEach(() => { expected = __2.Transaction.fromHex(f.hex);
expected = Transaction.fromHex(f.hex) actual = expected.clone();
actual = expected.clone() });
}) mocha_1.it('should have value equality', () => {
assert.deepStrictEqual(actual, expected);
it('should have value equality', () => { });
assert.deepStrictEqual(actual, expected) mocha_1.it('should not have reference equality', () => {
}) assert.notStrictEqual(actual, expected);
});
it('should not have reference equality', () => { });
assert.notStrictEqual(actual, expected) });
}) mocha_1.describe('getHash/getId', () => {
}) function verify(f) {
}) mocha_1.it('should return the id for ' + f.id + '(' + f.description + ')', () => {
const tx = __2.Transaction.fromHex(f.whex || f.hex);
describe('getHash/getId', () => { assert.strictEqual(tx.getHash().toString('hex'), f.hash);
function verify (f) { assert.strictEqual(tx.getId(), f.id);
it('should return the id for ' + f.id + '(' + f.description + ')', () => { });
const tx = Transaction.fromHex(f.whex || f.hex)
assert.strictEqual(tx.getHash().toString('hex'), f.hash)
assert.strictEqual(tx.getId(), f.id)
})
} }
fixtures.valid.forEach(verify);
fixtures.valid.forEach(verify) });
}) mocha_1.describe('isCoinbase', () => {
function verify(f) {
describe('isCoinbase', () => { mocha_1.it('should return ' +
function verify (f) { f.coinbase +
it('should return ' + f.coinbase + ' for ' + f.id + '(' + f.description + ')', () => { ' for ' +
const tx = Transaction.fromHex(f.hex) f.id +
'(' +
assert.strictEqual(tx.isCoinbase(), f.coinbase) f.description +
}) ')', () => {
const tx = __2.Transaction.fromHex(f.hex);
assert.strictEqual(tx.isCoinbase(), f.coinbase);
});
} }
fixtures.valid.forEach(verify);
fixtures.valid.forEach(verify) });
}) mocha_1.describe('hashForSignature', () => {
mocha_1.it('does not use Witness serialization', () => {
describe('hashForSignature', () => { const randScript = Buffer.from('6a', 'hex');
it('does not use Witness serialization', () => { const tx = new __2.Transaction();
const randScript = Buffer.from('6a', 'hex') tx.addInput(Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'), 0);
tx.addOutput(randScript, 5000000000);
const tx = new Transaction() // @ts-ignore
tx.addInput(Buffer.from('0000000000000000000000000000000000000000000000000000000000000000', 'hex'), 0) const original = tx.__toBuffer;
tx.addOutput(randScript, 5000000000) // @ts-ignore
const original = tx.__toBuffer
tx.__toBuffer = (a, b, c) => { tx.__toBuffer = (a, b, c) => {
if (c !== false) throw new Error('hashForSignature MUST pass false') if (c !== false)
throw new Error('hashForSignature MUST pass false');
return original.call(this, a, b, c) return original.call(this, a, b, c);
} };
assert.throws(() => { assert.throws(() => {
tx.__toBuffer(undefined, undefined, true) // @ts-ignore
}, /hashForSignature MUST pass false/) tx.__toBuffer(undefined, undefined, true);
}, /hashForSignature MUST pass false/);
// assert hashForSignature does not pass false // assert hashForSignature does not pass false
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
tx.hashForSignature(0, randScript, 1) tx.hashForSignature(0, randScript, 1);
}) });
}) });
fixtures.hashForSignature.forEach(f => { fixtures.hashForSignature.forEach(f => {
it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : f.script), () => { mocha_1.it('should return ' +
const tx = Transaction.fromHex(f.txHex) f.hash +
const script = bscript.fromASM(f.script) ' for ' +
(f.description ? 'case "' + f.description + '"' : f.script), () => {
assert.strictEqual(tx.hashForSignature(f.inIndex, script, f.type).toString('hex'), f.hash) const tx = __2.Transaction.fromHex(f.txHex);
}) const script = __1.script.fromASM(f.script);
}) assert.strictEqual(tx.hashForSignature(f.inIndex, script, f.type).toString('hex'), f.hash);
}) });
});
describe('hashForWitnessV0', () => { });
mocha_1.describe('hashForWitnessV0', () => {
fixtures.hashForWitnessV0.forEach(f => { fixtures.hashForWitnessV0.forEach(f => {
it('should return ' + f.hash + ' for ' + (f.description ? ('case "' + f.description + '"') : ''), () => { mocha_1.it('should return ' +
const tx = Transaction.fromHex(f.txHex) f.hash +
const script = bscript.fromASM(f.script) ' for ' +
(f.description ? 'case "' + f.description + '"' : ''), () => {
assert.strictEqual(tx.hashForWitnessV0(f.inIndex, script, f.value, f.type).toString('hex'), f.hash) const tx = __2.Transaction.fromHex(f.txHex);
}) const script = __1.script.fromASM(f.script);
}) assert.strictEqual(tx
}) .hashForWitnessV0(f.inIndex, script, f.value, f.type)
.toString('hex'), f.hash);
describe('setWitness', () => { });
it('only accepts a a witness stack (Array of Buffers)', () => { });
});
mocha_1.describe('setWitness', () => {
mocha_1.it('only accepts a a witness stack (Array of Buffers)', () => {
assert.throws(() => { assert.throws(() => {
(new Transaction()).setWitness(0, 'foobar') // @ts-ignore
}, /Expected property "1" of type \[Buffer], got String "foobar"/) new __2.Transaction().setWitness(0, 'foobar');
}) }, /Expected property "1" of type \[Buffer], got String "foobar"/);
}) });
}) });
});

888
test/transaction_builder.js

File diff suppressed because it is too large

61
test/types.js

@ -1,39 +1,34 @@
const { describe, it } = require('mocha') "use strict";
const assert = require('assert') Object.defineProperty(exports, "__esModule", { value: true });
const types = require('../src/types') const { describe, it } = require('mocha');
const typeforce = require('typeforce') const assert = require('assert');
const types = require('../src/types');
const typeforce = require('typeforce');
describe('types', () => { describe('types', () => {
describe('Buffer Hash160/Hash256', () => { describe('Buffer Hash160/Hash256', () => {
const buffer20byte = Buffer.alloc(20) const buffer20byte = Buffer.alloc(20);
const buffer32byte = Buffer.alloc(32) const buffer32byte = Buffer.alloc(32);
it('return true for valid size', () => { it('return true for valid size', () => {
assert(types.Hash160bit(buffer20byte)) assert(types.Hash160bit(buffer20byte));
assert(types.Hash256bit(buffer32byte)) assert(types.Hash256bit(buffer32byte));
}) });
it('return true for oneOf', () => { it('return true for oneOf', () => {
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
typeforce(types.oneOf(types.Hash160bit, types.Hash256bit), buffer32byte) typeforce(types.oneOf(types.Hash160bit, types.Hash256bit), buffer32byte);
}) });
assert.doesNotThrow(() => { assert.doesNotThrow(() => {
typeforce(types.oneOf(types.Hash256bit, types.Hash160bit), buffer32byte) typeforce(types.oneOf(types.Hash256bit, types.Hash160bit), buffer32byte);
}) });
}) });
it('throws for invalid size', () => { it('throws for invalid size', () => {
assert.throws(() => { assert.throws(() => {
types.Hash160bit(buffer32byte) types.Hash160bit(buffer32byte);
}, /Expected Buffer\(Length: 20\), got Buffer\(Length: 32\)/) }, /Expected Buffer\(Length: 20\), got Buffer\(Length: 32\)/);
assert.throws(() => { assert.throws(() => {
types.Hash256bit(buffer20byte) types.Hash256bit(buffer20byte);
}, /Expected Buffer\(Length: 32\), got Buffer\(Length: 20\)/) }, /Expected Buffer\(Length: 32\), got Buffer\(Length: 20\)/);
}) });
}) });
describe('Satoshi', () => { describe('Satoshi', () => {
[ [
{ value: -1, result: false }, { value: -1, result: false },
@ -41,11 +36,11 @@ describe('types', () => {
{ value: 1, result: true }, { value: 1, result: true },
{ value: 20999999 * 1e8, result: true }, { value: 20999999 * 1e8, result: true },
{ value: 21000000 * 1e8, result: true }, { value: 21000000 * 1e8, result: true },
{ value: 21000001 * 1e8, result: false } { value: 21000001 * 1e8, result: false },
].forEach(f => { ].forEach(f => {
it('returns ' + f.result + ' for valid for ' + f.value, () => { it('returns ' + f.result + ' for valid for ' + f.value, () => {
assert.strictEqual(types.Satoshi(f.value), f.result) assert.strictEqual(types.Satoshi(f.value), f.result);
}) });
}) });
}) });
}) });

Loading…
Cancel
Save