commit
646fbbd85a
14 changed files with 47 additions and 114 deletions
|
@ -51,7 +51,8 @@
|
||||||
"bigi": "^1.1.0",
|
"bigi": "^1.1.0",
|
||||||
"bs58check": "1.0.3",
|
"bs58check": "1.0.3",
|
||||||
"crypto-browserify": "^3.2.6",
|
"crypto-browserify": "^3.2.6",
|
||||||
"ecurve": "1.0.0"
|
"ecurve": "1.0.0",
|
||||||
|
"typeforce": "0.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"async": "^0.9.0",
|
"async": "^0.9.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var base58check = require('bs58check')
|
var base58check = require('bs58check')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
var networks = require('./networks')
|
var networks = require('./networks')
|
||||||
var scripts = require('./scripts')
|
var scripts = require('./scripts')
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ function findScriptTypeByVersion(version) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function Address(hash, version) {
|
function Address(hash, version) {
|
||||||
enforceType('Buffer', hash)
|
typeForce('Buffer', hash)
|
||||||
|
|
||||||
assert.strictEqual(hash.length, 20, 'Invalid hash length')
|
assert.strictEqual(hash.length, 20, 'Invalid hash length')
|
||||||
assert.strictEqual(version & 0xff, version, 'Invalid version byte')
|
assert.strictEqual(version & 0xff, version, 'Invalid version byte')
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var crypto = require('crypto')
|
var crypto = require('crypto')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
|
|
||||||
var BigInteger = require('bigi')
|
var BigInteger = require('bigi')
|
||||||
var ECSignature = require('./ecsignature')
|
var ECSignature = require('./ecsignature')
|
||||||
|
@ -10,8 +10,8 @@ var ONE = new Buffer([1])
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc6979#section-3.2
|
// https://tools.ietf.org/html/rfc6979#section-3.2
|
||||||
function deterministicGenerateK(curve, hash, d) {
|
function deterministicGenerateK(curve, hash, d) {
|
||||||
enforceType('Buffer', hash)
|
typeForce('Buffer', hash)
|
||||||
enforceType(BigInteger, d)
|
typeForce('BigInteger', d)
|
||||||
|
|
||||||
// sanity check
|
// sanity check
|
||||||
assert.equal(hash.length, 32, 'Hash must be 256 bit')
|
assert.equal(hash.length, 32, 'Hash must be 256 bit')
|
||||||
|
|
|
@ -2,7 +2,7 @@ var assert = require('assert')
|
||||||
var base58check = require('bs58check')
|
var base58check = require('bs58check')
|
||||||
var crypto = require('crypto')
|
var crypto = require('crypto')
|
||||||
var ecdsa = require('./ecdsa')
|
var ecdsa = require('./ecdsa')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
var networks = require('./networks')
|
var networks = require('./networks')
|
||||||
|
|
||||||
var BigInteger = require('bigi')
|
var BigInteger = require('bigi')
|
||||||
|
@ -50,7 +50,7 @@ ECKey.makeRandom = function(compressed, rng) {
|
||||||
rng = rng || crypto.randomBytes
|
rng = rng || crypto.randomBytes
|
||||||
|
|
||||||
var buffer = rng(32)
|
var buffer = rng(32)
|
||||||
enforceType('Buffer', buffer)
|
typeForce('Buffer', buffer)
|
||||||
assert.equal(buffer.length, 32, 'Expected 256-bit Buffer from RNG')
|
assert.equal(buffer.length, 32, 'Expected 256-bit Buffer from RNG')
|
||||||
|
|
||||||
var d = BigInteger.fromBuffer(buffer)
|
var d = BigInteger.fromBuffer(buffer)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
var crypto = require('./crypto')
|
var crypto = require('./crypto')
|
||||||
var ecdsa = require('./ecdsa')
|
var ecdsa = require('./ecdsa')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
var networks = require('./networks')
|
var networks = require('./networks')
|
||||||
|
|
||||||
var Address = require('./address')
|
var Address = require('./address')
|
||||||
|
@ -11,8 +11,8 @@ var secp256k1 = ecurve.getCurveByName('secp256k1')
|
||||||
function ECPubKey(Q, compressed) {
|
function ECPubKey(Q, compressed) {
|
||||||
if (compressed === undefined) compressed = true
|
if (compressed === undefined) compressed = true
|
||||||
|
|
||||||
enforceType(ecurve.Point, Q)
|
typeForce('Point', Q)
|
||||||
enforceType('Boolean', compressed)
|
typeForce('Boolean', compressed)
|
||||||
|
|
||||||
this.compressed = compressed
|
this.compressed = compressed
|
||||||
this.Q = Q
|
this.Q = Q
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
|
|
||||||
var BigInteger = require('bigi')
|
var BigInteger = require('bigi')
|
||||||
|
|
||||||
function ECSignature(r, s) {
|
function ECSignature(r, s) {
|
||||||
enforceType(BigInteger, r)
|
typeForce('BigInteger', r)
|
||||||
enforceType(BigInteger, s)
|
typeForce('BigInteger', s)
|
||||||
|
|
||||||
this.r = r
|
this.r = r
|
||||||
this.s = s
|
this.s = s
|
||||||
|
|
|
@ -2,7 +2,7 @@ var assert = require('assert')
|
||||||
var base58check = require('bs58check')
|
var base58check = require('bs58check')
|
||||||
var bcrypto = require('./crypto')
|
var bcrypto = require('./crypto')
|
||||||
var crypto = require('crypto')
|
var crypto = require('crypto')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
var networks = require('./networks')
|
var networks = require('./networks')
|
||||||
|
|
||||||
var BigInteger = require('bigi')
|
var BigInteger = require('bigi')
|
||||||
|
@ -29,7 +29,7 @@ function findBIP32NetworkByVersion(version) {
|
||||||
function HDNode(K, chainCode, network) {
|
function HDNode(K, chainCode, network) {
|
||||||
network = network || networks.bitcoin
|
network = network || networks.bitcoin
|
||||||
|
|
||||||
enforceType('Buffer', chainCode)
|
typeForce('Buffer', chainCode)
|
||||||
|
|
||||||
assert.equal(chainCode.length, 32, 'Expected chainCode length of 32, got ' + chainCode.length)
|
assert.equal(chainCode.length, 32, 'Expected chainCode length of 32, got ' + chainCode.length)
|
||||||
assert(network.bip32, 'Unknown BIP32 constants for network')
|
assert(network.bip32, 'Unknown BIP32 constants for network')
|
||||||
|
@ -53,7 +53,7 @@ HDNode.HIGHEST_BIT = 0x80000000
|
||||||
HDNode.LENGTH = 78
|
HDNode.LENGTH = 78
|
||||||
|
|
||||||
HDNode.fromSeedBuffer = function(seed, network) {
|
HDNode.fromSeedBuffer = function(seed, network) {
|
||||||
enforceType('Buffer', seed)
|
typeForce('Buffer', seed)
|
||||||
|
|
||||||
assert(seed.length >= 16, 'Seed should be at least 128 bits')
|
assert(seed.length >= 16, 'Seed should be at least 128 bits')
|
||||||
assert(seed.length <= 64, 'Seed should be at most 512 bits')
|
assert(seed.length <= 64, 'Seed should be at most 512 bits')
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var bufferutils = require('./bufferutils')
|
var bufferutils = require('./bufferutils')
|
||||||
var crypto = require('./crypto')
|
var crypto = require('./crypto')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
var opcodes = require('./opcodes')
|
var opcodes = require('./opcodes')
|
||||||
|
|
||||||
function Script(buffer, chunks) {
|
function Script(buffer, chunks) {
|
||||||
enforceType('Buffer', buffer)
|
typeForce('Buffer', buffer)
|
||||||
enforceType('Array', chunks)
|
typeForce('Array', chunks)
|
||||||
|
|
||||||
this.buffer = buffer
|
this.buffer = buffer
|
||||||
this.chunks = chunks
|
this.chunks = chunks
|
||||||
|
@ -56,7 +56,7 @@ Script.fromBuffer = function(buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Script.fromChunks = function(chunks) {
|
Script.fromChunks = function(chunks) {
|
||||||
enforceType('Array', chunks)
|
typeForce('Array', chunks)
|
||||||
|
|
||||||
var bufferSize = chunks.reduce(function(accum, chunk) {
|
var bufferSize = chunks.reduce(function(accum, chunk) {
|
||||||
if (Buffer.isBuffer(chunk)) {
|
if (Buffer.isBuffer(chunk)) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
var ops = require('./opcodes')
|
var ops = require('./opcodes')
|
||||||
|
|
||||||
var ecurve = require('ecurve')
|
var ecurve = require('ecurve')
|
||||||
|
@ -117,7 +117,7 @@ function isNullDataOutput(script) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function classifyOutput(script) {
|
function classifyOutput(script) {
|
||||||
enforceType(Script, script)
|
typeForce('Script', script)
|
||||||
|
|
||||||
if (isPubKeyHashOutput(script)) {
|
if (isPubKeyHashOutput(script)) {
|
||||||
return 'pubkeyhash'
|
return 'pubkeyhash'
|
||||||
|
@ -135,7 +135,7 @@ function classifyOutput(script) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function classifyInput(script) {
|
function classifyInput(script) {
|
||||||
enforceType(Script, script)
|
typeForce('Script', script)
|
||||||
|
|
||||||
if (isPubKeyHashInput(script)) {
|
if (isPubKeyHashInput(script)) {
|
||||||
return 'pubkeyhash'
|
return 'pubkeyhash'
|
||||||
|
@ -161,7 +161,7 @@ function pubKeyOutput(pubKey) {
|
||||||
|
|
||||||
// OP_DUP OP_HASH160 {pubKeyHash} OP_EQUALVERIFY OP_CHECKSIG
|
// OP_DUP OP_HASH160 {pubKeyHash} OP_EQUALVERIFY OP_CHECKSIG
|
||||||
function pubKeyHashOutput(hash) {
|
function pubKeyHashOutput(hash) {
|
||||||
enforceType('Buffer', hash)
|
typeForce('Buffer', hash)
|
||||||
|
|
||||||
return Script.fromChunks([
|
return Script.fromChunks([
|
||||||
ops.OP_DUP,
|
ops.OP_DUP,
|
||||||
|
@ -174,7 +174,7 @@ function pubKeyHashOutput(hash) {
|
||||||
|
|
||||||
// OP_HASH160 {scriptHash} OP_EQUAL
|
// OP_HASH160 {scriptHash} OP_EQUAL
|
||||||
function scriptHashOutput(hash) {
|
function scriptHashOutput(hash) {
|
||||||
enforceType('Buffer', hash)
|
typeForce('Buffer', hash)
|
||||||
|
|
||||||
return Script.fromChunks([
|
return Script.fromChunks([
|
||||||
ops.OP_HASH160,
|
ops.OP_HASH160,
|
||||||
|
@ -185,7 +185,7 @@ function scriptHashOutput(hash) {
|
||||||
|
|
||||||
// m [pubKeys ...] n OP_CHECKMULTISIG
|
// m [pubKeys ...] n OP_CHECKMULTISIG
|
||||||
function multisigOutput(m, pubKeys) {
|
function multisigOutput(m, pubKeys) {
|
||||||
enforceType('Array', pubKeys)
|
typeForce(['ECPubKey'], pubKeys)
|
||||||
|
|
||||||
assert(pubKeys.length >= m, 'Not enough pubKeys provided')
|
assert(pubKeys.length >= m, 'Not enough pubKeys provided')
|
||||||
|
|
||||||
|
@ -204,14 +204,14 @@ function multisigOutput(m, pubKeys) {
|
||||||
|
|
||||||
// {signature}
|
// {signature}
|
||||||
function pubKeyInput(signature) {
|
function pubKeyInput(signature) {
|
||||||
enforceType('Buffer', signature)
|
typeForce('Buffer', signature)
|
||||||
|
|
||||||
return Script.fromChunks([signature])
|
return Script.fromChunks([signature])
|
||||||
}
|
}
|
||||||
|
|
||||||
// {signature} {pubKey}
|
// {signature} {pubKey}
|
||||||
function pubKeyHashInput(signature, pubKey) {
|
function pubKeyHashInput(signature, pubKey) {
|
||||||
enforceType('Buffer', signature)
|
typeForce('Buffer', signature)
|
||||||
|
|
||||||
return Script.fromChunks([signature, pubKey.toBuffer()])
|
return Script.fromChunks([signature, pubKey.toBuffer()])
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var bufferutils = require('./bufferutils')
|
var bufferutils = require('./bufferutils')
|
||||||
var crypto = require('./crypto')
|
var crypto = require('./crypto')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
var opcodes = require('./opcodes')
|
var opcodes = require('./opcodes')
|
||||||
var scripts = require('./scripts')
|
var scripts = require('./scripts')
|
||||||
|
|
||||||
|
@ -108,10 +108,10 @@ Transaction.prototype.addInput = function(hash, index, sequence, script) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceType('Buffer', hash)
|
typeForce('Buffer', hash)
|
||||||
enforceType('Number', index)
|
typeForce('Number', index)
|
||||||
enforceType('Number', sequence)
|
typeForce('Number', sequence)
|
||||||
enforceType(Script, script)
|
typeForce('Script', script)
|
||||||
|
|
||||||
assert.equal(hash.length, 32, 'Expected hash length of 32, got ' + hash.length)
|
assert.equal(hash.length, 32, 'Expected hash length of 32, got ' + hash.length)
|
||||||
|
|
||||||
|
@ -144,8 +144,8 @@ Transaction.prototype.addOutput = function(scriptPubKey, value) {
|
||||||
scriptPubKey = scriptPubKey.toOutputScript()
|
scriptPubKey = scriptPubKey.toOutputScript()
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceType(Script, scriptPubKey)
|
typeForce('Script', scriptPubKey)
|
||||||
enforceType('Number', value)
|
typeForce('Number', value)
|
||||||
|
|
||||||
// Add the output and return the output's index
|
// Add the output and return the output's index
|
||||||
return (this.outs.push({
|
return (this.outs.push({
|
||||||
|
@ -197,9 +197,9 @@ Transaction.prototype.hashForSignature = function(inIndex, prevOutScript, hashTy
|
||||||
prevOutScript = tmp
|
prevOutScript = tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceType('Number', inIndex)
|
typeForce('Number', inIndex)
|
||||||
enforceType(Script, prevOutScript)
|
typeForce('Script', prevOutScript)
|
||||||
enforceType('Number', hashType)
|
typeForce('Number', hashType)
|
||||||
|
|
||||||
assert(inIndex >= 0, 'Invalid vin index')
|
assert(inIndex >= 0, 'Invalid vin index')
|
||||||
assert(inIndex < this.ins.length, 'Invalid vin index')
|
assert(inIndex < this.ins.length, 'Invalid vin index')
|
||||||
|
|
40
src/types.js
40
src/types.js
|
@ -1,40 +0,0 @@
|
||||||
module.exports = function enforce(type, value) {
|
|
||||||
switch (type) {
|
|
||||||
case 'Array': {
|
|
||||||
if (Array.isArray(value)) return
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'Boolean': {
|
|
||||||
if (typeof value === 'boolean') return
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'Buffer': {
|
|
||||||
if (Buffer.isBuffer(value)) return
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'Number': {
|
|
||||||
if (typeof value === 'number') return
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'String': {
|
|
||||||
if (typeof value === 'string') return
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
default: {
|
|
||||||
if (getName(value.constructor) === getName(type)) return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new TypeError('Expected ' + (getName(type) || type) + ', got ' + value)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getName(fn) {
|
|
||||||
// Why not fn.name: https://kangax.github.io/compat-table/es6/#function_name_property
|
|
||||||
var match = fn.toString().match(/function (.*?)\(/)
|
|
||||||
return match ? match[1] : null
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
var assert = require('assert')
|
var assert = require('assert')
|
||||||
var bufferutils = require('./bufferutils')
|
var bufferutils = require('./bufferutils')
|
||||||
var crypto = require('crypto')
|
var crypto = require('crypto')
|
||||||
var enforceType = require('./types')
|
var typeForce = require('typeforce')
|
||||||
var networks = require('./networks')
|
var networks = require('./networks')
|
||||||
|
|
||||||
var Address = require('./address')
|
var Address = require('./address')
|
||||||
|
@ -303,9 +303,9 @@ Wallet.prototype.setUnspentOutputs = function(unspents) {
|
||||||
index = unspent.outputIndex
|
index = unspent.outputIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
enforceType('String', txId)
|
typeForce('String', txId)
|
||||||
enforceType('Number', index)
|
typeForce('Number', index)
|
||||||
enforceType('Number', unspent.value)
|
typeForce('Number', unspent.value)
|
||||||
|
|
||||||
assert.equal(txId.length, 64, 'Expected valid txId, got ' + txId)
|
assert.equal(txId.length, 64, 'Expected valid txId, got ' + txId)
|
||||||
assert.doesNotThrow(function() { Address.fromBase58Check(unspent.address) }, 'Expected Base58 Address, got ' + unspent.address)
|
assert.doesNotThrow(function() { Address.fromBase58Check(unspent.address) }, 'Expected Base58 Address, got ' + unspent.address)
|
||||||
|
@ -313,7 +313,7 @@ Wallet.prototype.setUnspentOutputs = function(unspents) {
|
||||||
|
|
||||||
// FIXME: remove branch in 2.0.0
|
// FIXME: remove branch in 2.0.0
|
||||||
if (unspent.confirmations !== undefined) {
|
if (unspent.confirmations !== undefined) {
|
||||||
enforceType('Number', unspent.confirmations)
|
typeForce('Number', unspent.confirmations)
|
||||||
}
|
}
|
||||||
|
|
||||||
var txHash = bufferutils.reverse(new Buffer(txId, 'hex'))
|
var txHash = bufferutils.reverse(new Buffer(txId, 'hex'))
|
||||||
|
|
|
@ -168,7 +168,7 @@ describe('Scripts', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
fixtures.invalid.multisigOutput.forEach(function(f) {
|
fixtures.invalid.multisigOutput.forEach(function(f) {
|
||||||
var pubKeys = f.pubKeys.map(function(p) { return new Buffer(p, 'hex') })
|
var pubKeys = f.pubKeys.map(ECPubKey.fromHex)
|
||||||
|
|
||||||
it('throws on ' + f.exception, function() {
|
it('throws on ' + f.exception, function() {
|
||||||
assert.throws(function() {
|
assert.throws(function() {
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
var assert = require('assert')
|
|
||||||
var enforceType = require('../src/types')
|
|
||||||
|
|
||||||
function CustomType() { return "ensure non-greedy match".toUpperCase() }
|
|
||||||
|
|
||||||
var types = ['Array', 'Boolean', 'Buffer', 'Number', 'String', CustomType]
|
|
||||||
var values = [[], true, new Buffer(1), 1234, 'foobar', new CustomType()]
|
|
||||||
|
|
||||||
describe('enforceType', function() {
|
|
||||||
types.forEach(function(type, i) {
|
|
||||||
describe(type, function() {
|
|
||||||
values.forEach(function(value, j) {
|
|
||||||
if (j === i) {
|
|
||||||
it('passes for ' + types[j], function() {
|
|
||||||
enforceType(type, value)
|
|
||||||
})
|
|
||||||
|
|
||||||
} else {
|
|
||||||
it('fails for ' + types[j], function() {
|
|
||||||
assert.throws(function() {
|
|
||||||
enforceType(type, value)
|
|
||||||
}, new RegExp('Expected ' + (type.name || type) + ', got '))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
Loading…
Reference in a new issue