2015-02-23 00:36:57 +01:00
/* global describe, it */
2014-05-28 17:21:56 +02:00
2015-02-23 00:36:57 +01:00
var assert = require ( 'assert' )
2014-10-15 13:36:10 +02:00
var base58 = require ( 'bs58' )
2015-08-20 05:10:03 +02:00
var bitcoin = require ( '../' )
2015-03-04 15:14:48 +01:00
2015-02-23 00:36:57 +01:00
var base58 _encode _decode = require ( './fixtures/core/base58_encode_decode.json' )
var base58 _keys _invalid = require ( './fixtures/core/base58_keys_invalid.json' )
var base58 _keys _valid = require ( './fixtures/core/base58_keys_valid.json' )
2015-03-04 15:14:48 +01:00
var blocks _valid = require ( './fixtures/core/blocks.json' )
2015-02-23 00:36:57 +01:00
var sig _canonical = require ( './fixtures/core/sig_canonical.json' )
var sig _noncanonical = require ( './fixtures/core/sig_noncanonical.json' )
var sighash = require ( './fixtures/core/sighash.json' )
var tx _valid = require ( './fixtures/core/tx_valid.json' )
2014-05-28 17:21:56 +02:00
2015-02-23 00:36:57 +01:00
describe ( 'Bitcoin-core' , function ( ) {
2014-05-28 17:21:56 +02:00
// base58_encode_decode
2015-02-23 00:36:57 +01:00
describe ( 'base58' , function ( ) {
base58 _encode _decode . forEach ( function ( f ) {
2014-05-28 17:21:56 +02:00
var fhex = f [ 0 ]
var fb58 = f [ 1 ]
2015-02-23 00:36:57 +01:00
it ( 'can decode ' + fb58 , function ( ) {
2014-05-28 17:21:56 +02:00
var buffer = base58 . decode ( fb58 )
2014-10-03 11:11:38 +02:00
var actual = new Buffer ( buffer ) . toString ( 'hex' )
2014-05-28 17:21:56 +02:00
2015-05-07 03:29:20 +02:00
assert . strictEqual ( actual , fhex )
2014-05-28 17:21:56 +02:00
} )
2015-02-23 00:36:57 +01:00
it ( 'can encode ' + fhex , function ( ) {
2014-05-28 17:21:56 +02:00
var buffer = new Buffer ( fhex , 'hex' )
var actual = base58 . encode ( buffer )
2015-05-07 03:29:20 +02:00
assert . strictEqual ( actual , fb58 )
2014-05-28 17:21:56 +02:00
} )
} )
} )
// base58_keys_valid
2015-08-20 05:12:05 +02:00
describe ( 'address.toBase58Check' , function ( ) {
2015-02-23 00:36:57 +01:00
var typeMap = {
'pubkey' : 'pubKeyHash' ,
'script' : 'scriptHash'
}
base58 _keys _valid . forEach ( function ( f ) {
2015-07-21 03:03:40 +02:00
var expected = f [ 0 ]
var hash = new Buffer ( f [ 1 ] , 'hex' )
2014-05-28 17:21:56 +02:00
var params = f [ 2 ]
if ( params . isPrivkey ) return
2015-08-20 05:10:03 +02:00
var network = params . isTestnet ? bitcoin . networks . testnet : bitcoin . networks . bitcoin
2015-07-21 03:03:40 +02:00
var version = network [ typeMap [ params . addrType ] ]
2014-05-28 17:21:56 +02:00
2015-07-21 03:03:40 +02:00
it ( 'can export ' + expected , function ( ) {
2015-08-20 05:10:03 +02:00
assert . strictEqual ( bitcoin . address . toBase58Check ( hash , version ) , expected )
2014-05-28 17:21:56 +02:00
} )
} )
} )
// base58_keys_invalid
2015-08-20 05:12:05 +02:00
describe ( 'address.fromBase58Check' , function ( ) {
2014-05-28 17:21:56 +02:00
var allowedNetworks = [
2015-08-20 05:10:03 +02:00
bitcoin . networks . bitcoin . pubkeyhash ,
bitcoin . networks . bitcoin . scripthash ,
bitcoin . networks . testnet . pubkeyhash ,
bitcoin . networks . testnet . scripthash
2014-05-28 17:21:56 +02:00
]
2015-02-23 00:36:57 +01:00
base58 _keys _invalid . forEach ( function ( f ) {
2014-05-28 17:21:56 +02:00
var string = f [ 0 ]
2015-02-23 00:36:57 +01:00
it ( 'throws on ' + string , function ( ) {
assert . throws ( function ( ) {
2015-08-20 05:12:05 +02:00
var address = bitcoin . address . fromBase58Check ( string )
2014-05-28 17:21:56 +02:00
assert . notEqual ( allowedNetworks . indexOf ( address . version ) , - 1 , 'Invalid network' )
2015-08-18 02:20:49 +02:00
} , /(Invalid (checksum|network))|(too (short|long))/ )
2014-05-28 17:21:56 +02:00
} )
} )
} )
// base58_keys_valid
2015-03-02 06:48:36 +01:00
describe ( 'ECPair' , function ( ) {
2015-02-23 00:36:57 +01:00
base58 _keys _valid . forEach ( function ( f ) {
2014-05-28 17:21:56 +02:00
var string = f [ 0 ]
var hex = f [ 1 ]
var params = f [ 2 ]
if ( ! params . isPrivkey ) return
2015-07-28 08:42:57 +02:00
2015-08-20 05:10:03 +02:00
var network = params . isTestnet ? bitcoin . networks . testnet : bitcoin . networks . bitcoin
var keyPair = bitcoin . ECPair . fromWIF ( string , network )
2014-05-28 17:21:56 +02:00
2015-07-08 04:33:48 +02:00
it ( 'fromWIF imports ' + string , function ( ) {
2015-05-07 03:29:20 +02:00
assert . strictEqual ( keyPair . d . toHex ( ) , hex )
assert . strictEqual ( keyPair . compressed , params . isCompressed )
2014-05-28 17:21:56 +02:00
} )
2015-02-23 00:26:01 +01:00
2015-07-08 04:33:48 +02:00
it ( 'toWIF exports ' + hex + ' to ' + string , function ( ) {
2015-05-07 03:29:20 +02:00
assert . strictEqual ( keyPair . toWIF ( ) , string )
2015-02-23 00:26:01 +01:00
} )
2014-05-28 17:21:56 +02:00
} )
} )
// base58_keys_invalid
2015-07-08 04:33:48 +02:00
describe ( 'ECPair.fromWIF' , function ( ) {
2014-05-28 17:21:56 +02:00
var allowedNetworks = [
2015-08-20 05:10:03 +02:00
bitcoin . networks . bitcoin ,
bitcoin . networks . testnet
2014-05-28 17:21:56 +02:00
]
2015-02-23 00:36:57 +01:00
base58 _keys _invalid . forEach ( function ( f ) {
2014-05-28 17:21:56 +02:00
var string = f [ 0 ]
2015-02-23 00:36:57 +01:00
it ( 'throws on ' + string , function ( ) {
assert . throws ( function ( ) {
2015-08-20 05:10:03 +02:00
bitcoin . ECPair . fromWIF ( string , allowedNetworks )
2015-08-20 12:16:57 +02:00
} , /(Invalid|Unknown) (checksum|compression flag|network version|WIF length)/ )
2014-05-28 17:21:56 +02:00
} )
} )
} )
2015-07-08 04:33:48 +02:00
describe ( 'Block.fromHex' , function ( ) {
2015-03-04 15:14:48 +01:00
blocks _valid . forEach ( function ( f ) {
2015-07-08 04:33:48 +02:00
it ( 'can parse ' + f . id , function ( ) {
2015-08-20 05:10:03 +02:00
var block = bitcoin . Block . fromHex ( f . hex )
2015-03-04 15:14:48 +01:00
2015-05-07 03:29:20 +02:00
assert . strictEqual ( block . getId ( ) , f . id )
assert . strictEqual ( block . transactions . length , f . transactions )
2015-03-04 15:14:48 +01:00
} )
} )
} )
2014-05-28 17:21:56 +02:00
// tx_valid
2015-07-08 04:33:48 +02:00
describe ( 'Transaction.fromHex' , function ( ) {
2015-02-23 00:36:57 +01:00
tx _valid . forEach ( function ( f ) {
2014-05-28 17:21:56 +02:00
// Objects that are only a single string are ignored
if ( f . length === 1 ) return
var inputs = f [ 0 ]
var fhex = f [ 1 ]
2015-02-23 00:36:57 +01:00
// var verifyFlags = f[2] // TODO: do we need to test this?
2014-05-28 17:21:56 +02:00
2015-02-23 00:36:57 +01:00
it ( 'can decode ' + fhex , function ( ) {
2015-08-20 05:10:03 +02:00
var transaction = bitcoin . Transaction . fromHex ( fhex )
2014-05-28 17:21:56 +02:00
2015-04-28 02:58:00 +02:00
transaction . ins . forEach ( function ( txIn , i ) {
2014-05-28 17:21:56 +02:00
var input = inputs [ i ]
2015-04-28 02:58:00 +02:00
// reverse because test data is big-endian
2015-08-20 05:10:03 +02:00
var prevOutHash = bitcoin . bufferutils . reverse ( new Buffer ( input [ 0 ] , 'hex' ) )
2014-05-28 17:21:56 +02:00
var prevOutIndex = input [ 1 ]
2015-04-28 02:58:00 +02:00
assert . deepEqual ( txIn . hash , prevOutHash )
2014-05-28 17:21:56 +02:00
// we read UInt32, not Int32
2015-05-07 03:29:20 +02:00
assert . strictEqual ( txIn . index & 0xffffffff , prevOutIndex )
2014-05-28 17:21:56 +02:00
} )
} )
} )
} )
2015-08-20 05:31:29 +02:00
describe ( 'script.fromASM' , function ( ) {
2015-04-28 03:49:01 +02:00
tx _valid . forEach ( function ( f ) {
// Objects that are only a single string are ignored
if ( f . length === 1 ) return
var inputs = f [ 0 ]
inputs . forEach ( function ( input ) {
var prevOutScriptPubKey = input [ 2 ]
2015-07-08 04:33:36 +02:00
. replace ( /(^| )([0-9])( |$)/g , 'OP_$2 ' )
2015-04-28 03:49:01 +02:00
. replace ( /0x[a-f0-9]+ 0x([a-f0-9]+)/ , '$1' )
. replace ( /DUP/g , 'OP_DUP' )
. replace ( /NOT/g , 'OP_NOT' )
. replace ( /HASH160/g , 'OP_HASH160' )
. replace ( /EQUALVERIFY/g , 'OP_EQUALVERIFY' )
. replace ( /EQUAL( |$)/g , 'OP_EQUAL ' )
. replace ( /CHECKSIG/g , 'OP_CHECKSIG' )
. replace ( / CHECKMULTISIG/g , ' OP_CHECKMULTISIG' )
. replace ( /CODESEPARATOR/g , 'OP_CODESEPARATOR' )
. replace ( /CHECKSIGVERIFY/g , 'OP_CHECKSIGVERIFY' )
2015-07-08 04:33:48 +02:00
it ( 'can parse ' + prevOutScriptPubKey , function ( ) {
2015-04-28 03:49:01 +02:00
// TODO: we can probably do better validation than this
2015-08-20 05:31:29 +02:00
bitcoin . script . fromASM ( prevOutScriptPubKey )
2015-04-28 03:49:01 +02:00
} )
} )
} )
} )
2014-05-28 17:21:56 +02:00
// sighash
2015-02-23 00:36:57 +01:00
describe ( 'Transaction' , function ( ) {
sighash . forEach ( function ( f ) {
2014-05-28 17:21:56 +02:00
// Objects that are only a single string are ignored
if ( f . length === 1 ) return
var txHex = f [ 0 ]
var scriptHex = f [ 1 ]
var inIndex = f [ 2 ]
var hashType = f [ 3 ]
2015-04-28 02:58:00 +02:00
// reverse because test data is big-endian
2015-08-20 05:10:03 +02:00
var expectedHash = bitcoin . bufferutils . reverse ( new Buffer ( f [ 4 ] , 'hex' ) )
2014-05-28 17:21:56 +02:00
2015-04-28 02:38:10 +02:00
var hashTypes = [ ]
2015-08-20 05:10:03 +02:00
if ( ( hashType & 0x1f ) === bitcoin . Transaction . SIGHASH _NONE ) hashTypes . push ( 'SIGHASH_NONE' )
else if ( ( hashType & 0x1f ) === bitcoin . Transaction . SIGHASH _SINGLE ) hashTypes . push ( 'SIGHASH_SINGLE' )
2015-04-28 02:38:10 +02:00
else hashTypes . push ( 'SIGHASH_ALL' )
2015-08-20 05:10:03 +02:00
if ( hashType & bitcoin . Transaction . SIGHASH _ANYONECANPAY ) hashTypes . push ( 'SIGHASH_ANYONECANPAY' )
2015-04-28 02:38:10 +02:00
var hashTypeName = hashTypes . join ( ' | ' )
it ( 'should hash ' + txHex . slice ( 0 , 40 ) + '... (' + hashTypeName + ')' , function ( ) {
2015-08-20 05:10:03 +02:00
var transaction = bitcoin . Transaction . fromHex ( txHex )
2015-05-07 03:29:20 +02:00
assert . strictEqual ( transaction . toHex ( ) , txHex )
2014-05-28 17:21:56 +02:00
2015-08-18 02:17:04 +02:00
var script = new Buffer ( scriptHex , 'hex' )
2015-08-20 05:31:29 +02:00
var scriptChunks = bitcoin . script . decompile ( script )
assert . strictEqual ( bitcoin . script . compile ( scriptChunks ) . toString ( 'hex' ) , scriptHex )
2014-05-28 17:21:56 +02:00
2015-04-28 02:38:10 +02:00
var hash = transaction . hashForSignature ( inIndex , script , hashType )
assert . deepEqual ( hash , expectedHash )
2014-05-28 17:21:56 +02:00
} )
} )
} )
2014-06-20 07:25:23 +02:00
2015-07-08 04:33:48 +02:00
describe ( 'ECSignature.parseScriptSignature' , function ( ) {
2015-02-23 00:36:57 +01:00
sig _canonical . forEach ( function ( hex ) {
2014-06-20 07:25:23 +02:00
var buffer = new Buffer ( hex , 'hex' )
2015-02-23 00:36:57 +01:00
it ( 'can parse ' + hex , function ( ) {
2015-08-20 05:10:03 +02:00
var parsed = bitcoin . ECSignature . parseScriptSignature ( buffer )
2014-06-20 07:25:23 +02:00
var actual = parsed . signature . toScriptSignature ( parsed . hashType )
2015-05-07 03:29:20 +02:00
assert . strictEqual ( actual . toString ( 'hex' ) , hex )
2014-06-20 07:25:23 +02:00
} )
} )
2015-02-23 00:36:57 +01:00
sig _noncanonical . forEach ( function ( hex , i ) {
2014-06-20 07:25:23 +02:00
if ( i === 0 ) return
if ( i % 2 !== 0 ) return
var description = sig _noncanonical [ i - 1 ] . slice ( 0 , - 1 )
var buffer = new Buffer ( hex , 'hex' )
2015-02-23 00:36:57 +01:00
it ( 'throws on ' + description , function ( ) {
assert . throws ( function ( ) {
2015-08-20 05:10:03 +02:00
bitcoin . ECSignature . parseScriptSignature ( buffer )
2015-08-21 12:39:24 +02:00
} , /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/ )
2014-06-20 07:25:23 +02:00
} )
} )
} )
2014-05-28 17:21:56 +02:00
} )