Merge pull request #332 from bitcoinjs/typeforce

Typeforce
This commit is contained in:
Wei Lu 2014-12-23 15:20:59 +10:00
commit 646fbbd85a
14 changed files with 47 additions and 114 deletions

View file

@ -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",

View file

@ -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')

View file

@ -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')

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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')

View file

@ -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)) {

View file

@ -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()])
} }

View file

@ -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')

View file

@ -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
}

View file

@ -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'))

View file

@ -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() {

View file

@ -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 '))
})
}
})
})
})
})