commit
12dbe571a4
23 changed files with 753 additions and 670 deletions
151
src/ecpair.js
Normal file
151
src/ecpair.js
Normal file
|
@ -0,0 +1,151 @@
|
|||
var assert = require('assert')
|
||||
var base58check = require('bs58check')
|
||||
var bcrypto = require('./crypto')
|
||||
var ecdsa = require('./ecdsa')
|
||||
var ecurve = require('ecurve')
|
||||
var networks = require('./networks')
|
||||
var randomBytes = require('randombytes')
|
||||
var typeForce = require('typeforce')
|
||||
|
||||
var Address = require('./address')
|
||||
var BigInteger = require('bigi')
|
||||
|
||||
function findNetworkByWIFVersion (version) {
|
||||
for (var networkName in networks) {
|
||||
var network = networks[networkName]
|
||||
|
||||
if (network.wif === version) return network
|
||||
}
|
||||
|
||||
assert(false, 'Unknown network')
|
||||
}
|
||||
|
||||
function ECPair (d, Q, options) {
|
||||
options = options || {}
|
||||
|
||||
var compressed = options.compressed === undefined ? true : options.compressed
|
||||
var network = options.network === undefined ? networks.bitcoin : options.network
|
||||
|
||||
typeForce('Boolean', compressed)
|
||||
assert('pubKeyHash' in network, 'Unknown pubKeyHash constants for network')
|
||||
|
||||
if (d) {
|
||||
assert(d.signum() > 0, 'Private key must be greater than 0')
|
||||
assert(d.compareTo(ECPair.curve.n) < 0, 'Private key must be less than the curve order')
|
||||
|
||||
assert(!Q, 'Unexpected publicKey parameter')
|
||||
this.d = d
|
||||
|
||||
// enforce Q is a public key if no private key given
|
||||
} else {
|
||||
typeForce('Point', Q)
|
||||
this.__Q = Q
|
||||
}
|
||||
|
||||
this.compressed = compressed
|
||||
this.network = network
|
||||
}
|
||||
|
||||
Object.defineProperty(ECPair.prototype, 'Q', {
|
||||
get: function () {
|
||||
if (!this.__Q && this.d) {
|
||||
this.__Q = ECPair.curve.G.multiply(this.d)
|
||||
}
|
||||
|
||||
return this.__Q
|
||||
}
|
||||
})
|
||||
|
||||
// Public access to secp256k1 curve
|
||||
ECPair.curve = ecurve.getCurveByName('secp256k1')
|
||||
|
||||
ECPair.fromPublicKeyBuffer = function (buffer, network) {
|
||||
var Q = ecurve.Point.decodeFrom(ECPair.curve, buffer)
|
||||
|
||||
return new ECPair(null, Q, {
|
||||
compressed: Q.compressed,
|
||||
network: network
|
||||
})
|
||||
}
|
||||
|
||||
ECPair.fromWIF = function (string) {
|
||||
var payload = base58check.decode(string)
|
||||
var version = payload.readUInt8(0)
|
||||
var compressed
|
||||
|
||||
if (payload.length === 34) {
|
||||
assert.strictEqual(payload[33], 0x01, 'Invalid compression flag')
|
||||
|
||||
// truncate the version/compression bytes
|
||||
payload = payload.slice(1, -1)
|
||||
compressed = true
|
||||
|
||||
// no compression flag
|
||||
} else {
|
||||
assert.equal(payload.length, 33, 'Invalid WIF payload length')
|
||||
|
||||
// Truncate the version byte
|
||||
payload = payload.slice(1)
|
||||
compressed = false
|
||||
}
|
||||
|
||||
var network = findNetworkByWIFVersion(version)
|
||||
var d = BigInteger.fromBuffer(payload)
|
||||
|
||||
return new ECPair(d, null, {
|
||||
compressed: compressed,
|
||||
network: network
|
||||
})
|
||||
}
|
||||
|
||||
ECPair.makeRandom = function (options) {
|
||||
options = options || {}
|
||||
|
||||
var rng = options.rng || randomBytes
|
||||
var buffer = rng(32)
|
||||
typeForce('Buffer', buffer)
|
||||
assert.equal(buffer.length, 32, 'Expected 256-bit Buffer from RNG')
|
||||
|
||||
var d = BigInteger.fromBuffer(buffer)
|
||||
d = d.mod(ECPair.curve.n)
|
||||
|
||||
return new ECPair(d, null, options)
|
||||
}
|
||||
|
||||
ECPair.prototype.toWIF = function () {
|
||||
assert(this.d, 'Missing private key')
|
||||
|
||||
var bufferLen = this.compressed ? 34 : 33
|
||||
var buffer = new Buffer(bufferLen)
|
||||
|
||||
buffer.writeUInt8(this.network.wif, 0)
|
||||
this.d.toBuffer(32).copy(buffer, 1)
|
||||
|
||||
if (this.compressed) {
|
||||
buffer.writeUInt8(0x01, 33)
|
||||
}
|
||||
|
||||
return base58check.encode(buffer)
|
||||
}
|
||||
|
||||
ECPair.prototype.getAddress = function () {
|
||||
var pubKey = this.getPublicKeyBuffer()
|
||||
|
||||
return new Address(bcrypto.hash160(pubKey), this.network.pubKeyHash)
|
||||
}
|
||||
|
||||
ECPair.prototype.getPublicKeyBuffer = function () {
|
||||
return this.Q.getEncoded(this.compressed)
|
||||
}
|
||||
|
||||
ECPair.prototype.sign = function (hash) {
|
||||
assert(this.d, 'Missing private key')
|
||||
|
||||
return ecdsa.sign(ECPair.curve, hash, this.d)
|
||||
}
|
||||
|
||||
ECPair.prototype.verify = function (hash, signature) {
|
||||
return ecdsa.verify(ECPair.curve, hash, signature, this.Q)
|
||||
}
|
||||
|
||||
module.exports = ECPair
|
|
@ -6,8 +6,7 @@ var typeForce = require('typeforce')
|
|||
var networks = require('./networks')
|
||||
|
||||
var BigInteger = require('bigi')
|
||||
var ECKey = require('./eckey')
|
||||
var ECPubKey = require('./ecpubkey')
|
||||
var ECPair = require('./ecpair')
|
||||
|
||||
var ecurve = require('ecurve')
|
||||
var curve = ecurve.getCurveByName('secp256k1')
|
||||
|
@ -24,32 +23,19 @@ function findBIP32NetworkByVersion (version) {
|
|||
assert(false, 'Could not find network for ' + version.toString(16))
|
||||
}
|
||||
|
||||
function HDNode (K, chainCode, network) {
|
||||
network = network || networks.bitcoin
|
||||
|
||||
function HDNode (keyPair, chainCode) {
|
||||
typeForce('ECPair', keyPair)
|
||||
typeForce('Buffer', chainCode)
|
||||
|
||||
assert.equal(chainCode.length, 32, 'Expected chainCode length of 32, got ' + chainCode.length)
|
||||
assert(network.bip32, 'Unknown BIP32 constants for network')
|
||||
assert('bip32' in keyPair.network, 'Unknown BIP32 constants for network')
|
||||
assert.equal(keyPair.compressed, true, 'BIP32 only allows compressed keyPairs')
|
||||
|
||||
this.keyPair = keyPair
|
||||
this.chainCode = chainCode
|
||||
this.depth = 0
|
||||
this.index = 0
|
||||
this.parentFingerprint = 0x00000000
|
||||
this.network = network
|
||||
|
||||
if (K instanceof BigInteger) {
|
||||
this.privKey = new ECKey(K, true)
|
||||
this.pubKey = this.privKey.pub
|
||||
} else if (K instanceof ECKey) {
|
||||
assert(K.pub.compressed, 'ECKey must be compressed')
|
||||
this.privKey = K
|
||||
} else if (K instanceof ECPubKey) {
|
||||
assert(K.compressed, 'ECPubKey must be compressed')
|
||||
this.pubKey = K
|
||||
} else {
|
||||
this.pubKey = new ECPubKey(K, true)
|
||||
}
|
||||
}
|
||||
|
||||
HDNode.MASTER_SECRET = new Buffer('Bitcoin seed')
|
||||
|
@ -67,10 +53,13 @@ HDNode.fromSeedBuffer = function (seed, network) {
|
|||
var IR = I.slice(32)
|
||||
|
||||
// In case IL is 0 or >= n, the master key is invalid
|
||||
// This is handled by `new ECKey` in the HDNode constructor
|
||||
// This is handled by the ECPair constructor
|
||||
var pIL = BigInteger.fromBuffer(IL)
|
||||
var keyPair = new ECPair(pIL, null, {
|
||||
network: network
|
||||
})
|
||||
|
||||
return new HDNode(pIL, IR, network)
|
||||
return new HDNode(keyPair, IR)
|
||||
}
|
||||
|
||||
HDNode.fromSeedHex = function (hex, network) {
|
||||
|
@ -108,14 +97,17 @@ HDNode.fromBase58 = function (string, network) {
|
|||
|
||||
// 32 bytes: the chain code
|
||||
var chainCode = buffer.slice(13, 45)
|
||||
var data, hd
|
||||
var data, keyPair
|
||||
|
||||
// 33 bytes: private key data (0x00 + k)
|
||||
if (version === network.bip32.private) {
|
||||
assert.strictEqual(buffer.readUInt8(45), 0x00, 'Invalid private key')
|
||||
data = buffer.slice(46, 78)
|
||||
var d = BigInteger.fromBuffer(data)
|
||||
hd = new HDNode(d, chainCode, network)
|
||||
|
||||
keyPair = new ECPair(d, null, {
|
||||
network: network
|
||||
})
|
||||
|
||||
// 33 bytes: public key data (0x02 + X or 0x03 + X)
|
||||
} else {
|
||||
|
@ -127,9 +119,12 @@ HDNode.fromBase58 = function (string, network) {
|
|||
// If not, the extended public key is invalid.
|
||||
curve.validate(Q)
|
||||
|
||||
hd = new HDNode(Q, chainCode, network)
|
||||
keyPair = new ECPair(null, Q, {
|
||||
network: network
|
||||
})
|
||||
}
|
||||
|
||||
var hd = new HDNode(keyPair, chainCode)
|
||||
hd.depth = depth
|
||||
hd.index = index
|
||||
hd.parentFingerprint = parentFingerprint
|
||||
|
@ -138,7 +133,7 @@ HDNode.fromBase58 = function (string, network) {
|
|||
}
|
||||
|
||||
HDNode.prototype.getIdentifier = function () {
|
||||
return bcrypto.hash160(this.pubKey.toBuffer())
|
||||
return bcrypto.hash160(this.keyPair.getPublicKeyBuffer())
|
||||
}
|
||||
|
||||
HDNode.prototype.getFingerprint = function () {
|
||||
|
@ -146,11 +141,15 @@ HDNode.prototype.getFingerprint = function () {
|
|||
}
|
||||
|
||||
HDNode.prototype.getAddress = function () {
|
||||
return this.pubKey.getAddress(this.network)
|
||||
return this.keyPair.getAddress()
|
||||
}
|
||||
|
||||
HDNode.prototype.neutered = function () {
|
||||
var neutered = new HDNode(this.pubKey.Q, this.chainCode, this.network)
|
||||
var neuteredKeyPair = new ECPair(null, this.keyPair.Q, {
|
||||
network: this.keyPair.network
|
||||
})
|
||||
|
||||
var neutered = new HDNode(neuteredKeyPair, this.chainCode)
|
||||
neutered.depth = this.depth
|
||||
neutered.index = this.index
|
||||
neutered.parentFingerprint = this.parentFingerprint
|
||||
|
@ -162,7 +161,8 @@ HDNode.prototype.toBase58 = function (__isPrivate) {
|
|||
assert.strictEqual(__isPrivate, undefined, 'Unsupported argument in 2.0.0')
|
||||
|
||||
// Version
|
||||
var version = this.privKey ? this.network.bip32.private : this.network.bip32.public
|
||||
var network = this.keyPair.network
|
||||
var version = this.keyPair.d ? network.bip32.private : network.bip32.public
|
||||
var buffer = new Buffer(HDNode.LENGTH)
|
||||
|
||||
// 4 bytes: version bytes
|
||||
|
@ -182,16 +182,16 @@ HDNode.prototype.toBase58 = function (__isPrivate) {
|
|||
// 32 bytes: the chain code
|
||||
this.chainCode.copy(buffer, 13)
|
||||
|
||||
// 33 bytes: the private key, or
|
||||
if (this.privKey) {
|
||||
// 33 bytes: the public key or private key data
|
||||
if (this.keyPair.d) {
|
||||
// 0x00 + k for private keys
|
||||
buffer.writeUInt8(0, 45)
|
||||
this.privKey.d.toBuffer(32).copy(buffer, 46)
|
||||
this.keyPair.d.toBuffer(32).copy(buffer, 46)
|
||||
|
||||
// 33 bytes: the public key
|
||||
} else {
|
||||
// X9.62 encoding for public keys
|
||||
this.pubKey.toBuffer().copy(buffer, 45)
|
||||
this.keyPair.getPublicKeyBuffer().copy(buffer, 45)
|
||||
}
|
||||
|
||||
return base58check.encode(buffer)
|
||||
|
@ -207,11 +207,11 @@ HDNode.prototype.derive = function (index) {
|
|||
|
||||
// Hardened child
|
||||
if (isHardened) {
|
||||
assert(this.privKey, 'Could not derive hardened child key')
|
||||
assert(this.keyPair.d, 'Could not derive hardened child key')
|
||||
|
||||
// data = 0x00 || ser256(kpar) || ser32(index)
|
||||
data = Buffer.concat([
|
||||
this.privKey.d.toBuffer(33),
|
||||
this.keyPair.d.toBuffer(33),
|
||||
indexBuffer
|
||||
])
|
||||
|
||||
|
@ -220,7 +220,7 @@ HDNode.prototype.derive = function (index) {
|
|||
// data = serP(point(kpar)) || ser32(index)
|
||||
// = serP(Kpar) || ser32(index)
|
||||
data = Buffer.concat([
|
||||
this.pubKey.toBuffer(),
|
||||
this.keyPair.getPublicKeyBuffer(),
|
||||
indexBuffer
|
||||
])
|
||||
}
|
||||
|
@ -237,32 +237,37 @@ HDNode.prototype.derive = function (index) {
|
|||
}
|
||||
|
||||
// Private parent key -> private child key
|
||||
var hd
|
||||
if (this.privKey) {
|
||||
var derivedKeyPair
|
||||
if (this.keyPair.d) {
|
||||
// ki = parse256(IL) + kpar (mod n)
|
||||
var ki = pIL.add(this.privKey.d).mod(curve.n)
|
||||
var ki = pIL.add(this.keyPair.d).mod(curve.n)
|
||||
|
||||
// In case ki == 0, proceed with the next value for i
|
||||
if (ki.signum() === 0) {
|
||||
return this.derive(index + 1)
|
||||
}
|
||||
|
||||
hd = new HDNode(ki, IR, this.network)
|
||||
derivedKeyPair = new ECPair(ki, null, {
|
||||
network: this.keyPair.network
|
||||
})
|
||||
|
||||
// Public parent key -> public child key
|
||||
} else {
|
||||
// Ki = point(parse256(IL)) + Kpar
|
||||
// = G*IL + Kpar
|
||||
var Ki = curve.G.multiply(pIL).add(this.pubKey.Q)
|
||||
var Ki = curve.G.multiply(pIL).add(this.keyPair.Q)
|
||||
|
||||
// In case Ki is the point at infinity, proceed with the next value for i
|
||||
if (curve.isInfinity(Ki)) {
|
||||
return this.derive(index + 1)
|
||||
}
|
||||
|
||||
hd = new HDNode(Ki, IR, this.network)
|
||||
derivedKeyPair = new ECPair(null, Ki, {
|
||||
network: this.keyPair.network
|
||||
})
|
||||
}
|
||||
|
||||
var hd = new HDNode(derivedKeyPair, IR)
|
||||
hd.depth = this.depth + 1
|
||||
hd.index = index
|
||||
hd.parentFingerprint = this.getFingerprint().readUInt32BE(0)
|
||||
|
|
|
@ -4,8 +4,7 @@ module.exports = {
|
|||
bufferutils: require('./bufferutils'),
|
||||
crypto: require('./crypto'),
|
||||
ecdsa: require('./ecdsa'),
|
||||
ECKey: require('./eckey'),
|
||||
ECPubKey: require('./ecpubkey'),
|
||||
ECPair: require('./ecpair'),
|
||||
ECSignature: require('./ecsignature'),
|
||||
message: require('./message'),
|
||||
opcodes: require('./opcodes'),
|
||||
|
|
|
@ -4,7 +4,7 @@ var ecdsa = require('./ecdsa')
|
|||
var networks = require('./networks')
|
||||
|
||||
var BigInteger = require('bigi')
|
||||
var ECPubKey = require('./ecpubkey')
|
||||
var ECPair = require('./ecpair')
|
||||
var ECSignature = require('./ecsignature')
|
||||
|
||||
var ecurve = require('ecurve')
|
||||
|
@ -19,15 +19,15 @@ function magicHash (message, network) {
|
|||
return crypto.hash256(buffer)
|
||||
}
|
||||
|
||||
function sign (privKey, message, network) {
|
||||
function sign (keyPair, message, network) {
|
||||
network = network || networks.bitcoin
|
||||
|
||||
var hash = magicHash(message, network)
|
||||
var signature = privKey.sign(hash)
|
||||
var signature = keyPair.sign(hash)
|
||||
var e = BigInteger.fromBuffer(hash)
|
||||
var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, signature, privKey.pub.Q)
|
||||
var i = ecdsa.calcPubKeyRecoveryParam(ecparams, e, signature, keyPair.Q)
|
||||
|
||||
return signature.toCompact(i, privKey.pub.compressed)
|
||||
return signature.toCompact(i, keyPair.compressed)
|
||||
}
|
||||
|
||||
// TODO: network could be implied from address
|
||||
|
@ -42,9 +42,12 @@ function verify (address, signature, message, network) {
|
|||
var parsed = ECSignature.parseCompact(signature)
|
||||
var e = BigInteger.fromBuffer(hash)
|
||||
var Q = ecdsa.recoverPubKey(ecparams, e, parsed.signature, parsed.i)
|
||||
var keyPair = new ECPair(null, Q, {
|
||||
compressed: parsed.compressed,
|
||||
network: network
|
||||
})
|
||||
|
||||
var pubKey = new ECPubKey(Q, parsed.compressed)
|
||||
return pubKey.getAddress(network).toString() === address.toString()
|
||||
return keyPair.getAddress().toString() === address.toString()
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -170,7 +170,7 @@ function classifyInput (script, allowIncomplete) {
|
|||
// {pubKey} OP_CHECKSIG
|
||||
function pubKeyOutput (pubKey) {
|
||||
return Script.fromChunks([
|
||||
pubKey.toBuffer(),
|
||||
pubKey,
|
||||
ops.OP_CHECKSIG
|
||||
])
|
||||
}
|
||||
|
@ -201,18 +201,14 @@ function scriptHashOutput (hash) {
|
|||
|
||||
// m [pubKeys ...] n OP_CHECKMULTISIG
|
||||
function multisigOutput (m, pubKeys) {
|
||||
typeForce(['ECPubKey'], pubKeys)
|
||||
typeForce(['Buffer'], pubKeys)
|
||||
|
||||
assert(pubKeys.length >= m, 'Not enough pubKeys provided')
|
||||
|
||||
var pubKeyBuffers = pubKeys.map(function (pubKey) {
|
||||
return pubKey.toBuffer()
|
||||
})
|
||||
var n = pubKeys.length
|
||||
assert(n >= m, 'Not enough pubKeys provided')
|
||||
|
||||
return Script.fromChunks([].concat(
|
||||
(ops.OP_1 - 1) + m,
|
||||
pubKeyBuffers,
|
||||
pubKeys,
|
||||
(ops.OP_1 - 1) + n,
|
||||
ops.OP_CHECKMULTISIG
|
||||
))
|
||||
|
@ -228,8 +224,9 @@ function pubKeyInput (signature) {
|
|||
// {signature} {pubKey}
|
||||
function pubKeyHashInput (signature, pubKey) {
|
||||
typeForce('Buffer', signature)
|
||||
typeForce('Buffer', pubKey)
|
||||
|
||||
return Script.fromChunks([signature, pubKey.toBuffer()])
|
||||
return Script.fromChunks([signature, pubKey])
|
||||
}
|
||||
|
||||
// <scriptSig> {serialized scriptPubKey script}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
var assert = require('assert')
|
||||
var bufferutils = require('./bufferutils')
|
||||
var ops = require('./opcodes')
|
||||
var scripts = require('./scripts')
|
||||
|
||||
var Address = require('./address')
|
||||
var ECPubKey = require('./ecpubkey')
|
||||
var ECPair = require('./ecpair')
|
||||
var ECSignature = require('./ecsignature')
|
||||
var Script = require('./script')
|
||||
var Transaction = require('./transaction')
|
||||
|
@ -33,9 +34,9 @@ function extractInput (txIn) {
|
|||
case 'pubkeyhash': {
|
||||
parsed = ECSignature.parseScriptSignature(scriptSig.chunks[0])
|
||||
hashType = parsed.hashType
|
||||
pubKeys = [ECPubKey.fromBuffer(scriptSig.chunks[1])]
|
||||
pubKeys = scriptSig.chunks.slice(1)
|
||||
signatures = [parsed.signature]
|
||||
prevOutScript = pubKeys[0].getAddress().toOutputScript()
|
||||
prevOutScript = ECPair.fromPublicKeyBuffer(pubKeys[0]).getAddress().toOutputScript()
|
||||
|
||||
break
|
||||
}
|
||||
|
@ -46,7 +47,7 @@ function extractInput (txIn) {
|
|||
signatures = [parsed.signature]
|
||||
|
||||
if (redeemScript) {
|
||||
pubKeys = [ECPubKey.fromBuffer(redeemScript.chunks[0])]
|
||||
pubKeys = redeemScript.chunks.slice(0, 1)
|
||||
}
|
||||
|
||||
break
|
||||
|
@ -63,7 +64,7 @@ function extractInput (txIn) {
|
|||
})
|
||||
|
||||
if (redeemScript) {
|
||||
pubKeys = redeemScript.chunks.slice(1, -2).map(ECPubKey.fromBuffer)
|
||||
pubKeys = redeemScript.chunks.slice(1, -2)
|
||||
}
|
||||
|
||||
break
|
||||
|
@ -141,12 +142,12 @@ TransactionBuilder.prototype.addInput = function (txHash, vout, sequence, prevOu
|
|||
// if we can, extract pubKey information
|
||||
switch (prevOutType) {
|
||||
case 'multisig': {
|
||||
input.pubKeys = prevOutScript.chunks.slice(1, -2).map(ECPubKey.fromBuffer)
|
||||
input.pubKeys = prevOutScript.chunks.slice(1, -2)
|
||||
break
|
||||
}
|
||||
|
||||
case 'pubkey': {
|
||||
input.pubKeys = prevOutScript.chunks.slice(0, 1).map(ECPubKey.fromBuffer)
|
||||
input.pubKeys = prevOutScript.chunks.slice(0, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -280,7 +281,7 @@ TransactionBuilder.prototype.__build = function (allowIncomplete) {
|
|||
return tx
|
||||
}
|
||||
|
||||
TransactionBuilder.prototype.sign = function (index, privKey, redeemScript, hashType) {
|
||||
TransactionBuilder.prototype.sign = function (index, keyPair, redeemScript, hashType) {
|
||||
assert(index in this.inputs, 'No input at index: ' + index)
|
||||
hashType = hashType || Transaction.SIGHASH_ALL
|
||||
|
||||
|
@ -292,6 +293,8 @@ TransactionBuilder.prototype.sign = function (index, privKey, redeemScript, hash
|
|||
input.scriptType &&
|
||||
input.signatures
|
||||
|
||||
var kpPubKey = keyPair.getPublicKeyBuffer()
|
||||
|
||||
// are we almost ready to sign?
|
||||
if (canSign) {
|
||||
// if redeemScript was provided, enforce consistency
|
||||
|
@ -319,21 +322,21 @@ TransactionBuilder.prototype.sign = function (index, privKey, redeemScript, hash
|
|||
var pubKeys = []
|
||||
switch (scriptType) {
|
||||
case 'multisig': {
|
||||
pubKeys = redeemScript.chunks.slice(1, -2).map(ECPubKey.fromBuffer)
|
||||
pubKeys = redeemScript.chunks.slice(1, -2)
|
||||
break
|
||||
}
|
||||
|
||||
case 'pubkeyhash': {
|
||||
var pkh1 = redeemScript.chunks[2]
|
||||
var pkh2 = privKey.pub.getAddress().hash
|
||||
var pkh2 = keyPair.getAddress().hash
|
||||
|
||||
assert.deepEqual(pkh1, pkh2, 'privateKey cannot sign for this input')
|
||||
pubKeys = [privKey.pub]
|
||||
pubKeys = [kpPubKey]
|
||||
break
|
||||
}
|
||||
|
||||
case 'pubkey': {
|
||||
pubKeys = redeemScript.chunks.slice(0, 1).map(ECPubKey.fromBuffer)
|
||||
pubKeys = redeemScript.chunks.slice(0, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -357,9 +360,9 @@ TransactionBuilder.prototype.sign = function (index, privKey, redeemScript, hash
|
|||
|
||||
// we know nothin' Jon Snow, assume pubKeyHash
|
||||
} else {
|
||||
input.prevOutScript = privKey.pub.getAddress().toOutputScript()
|
||||
input.prevOutScript = keyPair.getAddress().toOutputScript()
|
||||
input.prevOutType = 'pubkeyhash'
|
||||
input.pubKeys = [privKey.pub]
|
||||
input.pubKeys = [kpPubKey]
|
||||
input.scriptType = input.prevOutType
|
||||
}
|
||||
}
|
||||
|
@ -378,10 +381,11 @@ TransactionBuilder.prototype.sign = function (index, privKey, redeemScript, hash
|
|||
|
||||
input.signatures = input.pubKeys.map(function (pubKey) {
|
||||
var match
|
||||
var keyPair2 = ECPair.fromPublicKeyBuffer(pubKey)
|
||||
|
||||
// check for any matching signatures
|
||||
unmatched.some(function (signature, i) {
|
||||
if (!pubKey.verify(signatureHash, signature)) return false
|
||||
if (!keyPair2.verify(signatureHash, signature)) return false
|
||||
match = signature
|
||||
|
||||
// remove matched signature from unmatched
|
||||
|
@ -396,14 +400,15 @@ TransactionBuilder.prototype.sign = function (index, privKey, redeemScript, hash
|
|||
|
||||
// enforce in order signing of public keys
|
||||
assert(input.pubKeys.some(function (pubKey, i) {
|
||||
if (!privKey.pub.Q.equals(pubKey.Q)) return false
|
||||
if (!bufferutils.equal(kpPubKey, pubKey)) return false
|
||||
|
||||
assert(!input.signatures[i], 'Signature already exists')
|
||||
var signature = privKey.sign(signatureHash)
|
||||
|
||||
var signature = keyPair.sign(signatureHash)
|
||||
input.signatures[i] = signature
|
||||
|
||||
return true
|
||||
}, this), 'privateKey cannot sign for this input')
|
||||
}, this), 'key pair cannot sign for this input')
|
||||
}
|
||||
|
||||
module.exports = TransactionBuilder
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
var assert = require('assert')
|
||||
var base58 = require('bs58')
|
||||
var base58check = require('bs58check')
|
||||
|
||||
var Bitcoin = require('../')
|
||||
var Address = Bitcoin.Address
|
||||
var Block = Bitcoin.Block
|
||||
var ECKey = Bitcoin.ECKey
|
||||
var ECPair = Bitcoin.ECPair
|
||||
var ECSignature = Bitcoin.ECSignature
|
||||
var Transaction = Bitcoin.Transaction
|
||||
var Script = Bitcoin.Script
|
||||
|
@ -95,32 +94,31 @@ describe('Bitcoin-core', function () {
|
|||
})
|
||||
|
||||
// base58_keys_valid
|
||||
describe('ECKey', function () {
|
||||
describe('ECPair', function () {
|
||||
base58_keys_valid.forEach(function (f) {
|
||||
var string = f[0]
|
||||
var hex = f[1]
|
||||
var params = f[2]
|
||||
var network = params.isTestnet ? networks.testnet : networks.bitcoin
|
||||
|
||||
if (!params.isPrivkey) return
|
||||
var privKey = ECKey.fromWIF(string)
|
||||
var keyPair = ECPair.fromWIF(string)
|
||||
|
||||
it('imports ' + string + ' correctly', function () {
|
||||
assert.equal(privKey.d.toHex(), hex)
|
||||
assert.equal(privKey.pub.compressed, params.isCompressed)
|
||||
assert.equal(keyPair.d.toHex(), hex)
|
||||
assert.equal(keyPair.compressed, params.isCompressed)
|
||||
})
|
||||
|
||||
it('exports ' + hex + ' to ' + string, function () {
|
||||
assert.equal(privKey.toWIF(network), string)
|
||||
assert.equal(keyPair.toWIF(), string)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// base58_keys_invalid
|
||||
describe('ECKey', function () {
|
||||
describe('ECPair', function () {
|
||||
var allowedNetworks = [
|
||||
networks.bitcoin.wif,
|
||||
networks.testnet.wif
|
||||
networks.bitcoin,
|
||||
networks.testnet
|
||||
]
|
||||
|
||||
base58_keys_invalid.forEach(function (f) {
|
||||
|
@ -128,11 +126,10 @@ describe('Bitcoin-core', function () {
|
|||
|
||||
it('throws on ' + string, function () {
|
||||
assert.throws(function () {
|
||||
ECKey.fromWIF(string)
|
||||
var version = base58check.decode(string).readUInt8(0)
|
||||
var keyPair = ECPair.fromWIF(string)
|
||||
|
||||
assert.notEqual(allowedNetworks.indexOf(version), -1, 'Invalid network')
|
||||
}, /Invalid (checksum|compression flag|network|WIF payload)/)
|
||||
assert(allowedNetworks.indexOf(keyPair.network) > -1, 'Invalid network')
|
||||
}, /(Invalid|Unknown) (checksum|compression flag|network|WIF payload)/)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
143
test/eckey.js
143
test/eckey.js
|
@ -1,143 +0,0 @@
|
|||
/* global describe, it */
|
||||
/* eslint-disable no-new */
|
||||
|
||||
var assert = require('assert')
|
||||
var ecurve = require('ecurve')
|
||||
var networks = require('../src/networks')
|
||||
var proxyquire = require('proxyquire')
|
||||
var randomBytes = require('randombytes')
|
||||
|
||||
var BigInteger = require('bigi')
|
||||
var ECKey = require('../src/eckey')
|
||||
|
||||
var fixtures = require('./fixtures/eckey.json')
|
||||
|
||||
describe('ECKey', function () {
|
||||
describe('constructor', function () {
|
||||
it('defaults to compressed', function () {
|
||||
var privKey = new ECKey(BigInteger.ONE)
|
||||
|
||||
assert.equal(privKey.pub.compressed, true)
|
||||
})
|
||||
|
||||
it('supports the uncompressed flag', function () {
|
||||
var privKey = new ECKey(BigInteger.ONE, false)
|
||||
|
||||
assert.equal(privKey.pub.compressed, false)
|
||||
})
|
||||
|
||||
fixtures.valid.forEach(function (f) {
|
||||
it('calculates the matching pubKey for ' + f.d, function () {
|
||||
var d = new BigInteger(f.d)
|
||||
var privKey = new ECKey(d)
|
||||
|
||||
assert.equal(privKey.pub.Q.toString(), f.Q)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.invalid.constructor.forEach(function (f) {
|
||||
it('throws on ' + f.d, function () {
|
||||
var d = new BigInteger(f.d)
|
||||
|
||||
assert.throws(function () {
|
||||
new ECKey(d)
|
||||
}, new RegExp(f.exception))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('uses the secp256k1 curve by default', function () {
|
||||
var secp256k1 = ecurve.getCurveByName('secp256k1')
|
||||
|
||||
for (var property in secp256k1) {
|
||||
// FIXME: circular structures in ecurve
|
||||
if (property === 'G') continue
|
||||
if (property === 'infinity') continue
|
||||
|
||||
var actual = ECKey.curve[property]
|
||||
var expected = secp256k1[property]
|
||||
|
||||
assert.deepEqual(actual, expected)
|
||||
}
|
||||
})
|
||||
|
||||
describe('fromWIF', function () {
|
||||
fixtures.valid.forEach(function (f) {
|
||||
f.WIFs.forEach(function (wif) {
|
||||
it('imports ' + wif.string + ' correctly', function () {
|
||||
var privKey = ECKey.fromWIF(wif.string)
|
||||
|
||||
assert.equal(privKey.d.toString(), f.d)
|
||||
assert.equal(privKey.pub.compressed, wif.compressed)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.invalid.WIF.forEach(function (f) {
|
||||
it('throws on ' + f.string, function () {
|
||||
assert.throws(function () {
|
||||
ECKey.fromWIF(f.string)
|
||||
}, new RegExp(f.exception))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('toWIF', function () {
|
||||
fixtures.valid.forEach(function (f) {
|
||||
f.WIFs.forEach(function (wif) {
|
||||
it('exports ' + wif.string + ' correctly', function () {
|
||||
var privKey = ECKey.fromWIF(wif.string)
|
||||
var network = networks[wif.network]
|
||||
var result = privKey.toWIF(network)
|
||||
|
||||
assert.equal(result, wif.string)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('makeRandom', function () {
|
||||
var exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'
|
||||
var exPrivKey = ECKey.fromWIF(exWIF)
|
||||
var exBuffer = exPrivKey.d.toBuffer(32)
|
||||
|
||||
it("uses the RNG provided by the 'randombytes' module by default", function () {
|
||||
var stub = { randombytes: function () { return exBuffer } }
|
||||
var ProxiedECKey = proxyquire('../src/eckey', stub)
|
||||
|
||||
var privKey = ProxiedECKey.makeRandom()
|
||||
|
||||
assert.equal(privKey.toWIF(), exWIF)
|
||||
})
|
||||
|
||||
it('allows a custom RNG to be used', function () {
|
||||
function rng (size) {
|
||||
return exBuffer.slice(0, size)
|
||||
}
|
||||
|
||||
var privKey = ECKey.makeRandom(undefined, rng)
|
||||
assert.equal(privKey.toWIF(), exWIF)
|
||||
})
|
||||
|
||||
it('supports compression', function () {
|
||||
assert.equal(ECKey.makeRandom(true).pub.compressed, true)
|
||||
assert.equal(ECKey.makeRandom(false).pub.compressed, false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('signing', function () {
|
||||
var hash = randomBytes(32)
|
||||
var priv = ECKey.makeRandom()
|
||||
var signature = priv.sign(hash)
|
||||
|
||||
it('should verify against the public key', function () {
|
||||
assert(priv.pub.verify(hash, signature))
|
||||
})
|
||||
|
||||
it('should not verify against the wrong public key', function () {
|
||||
var priv2 = ECKey.makeRandom()
|
||||
|
||||
assert(!priv2.pub.verify(hash, signature))
|
||||
})
|
||||
})
|
||||
})
|
234
test/ecpair.js
Normal file
234
test/ecpair.js
Normal file
|
@ -0,0 +1,234 @@
|
|||
/* global describe, it, beforeEach */
|
||||
/* eslint-disable no-new */
|
||||
|
||||
var assert = require('assert')
|
||||
var ecdsa = require('../src/ecdsa')
|
||||
var ecurve = require('ecurve')
|
||||
var networks = require('../src/networks')
|
||||
var proxyquire = require('proxyquire')
|
||||
var sinon = require('sinon')
|
||||
|
||||
var BigInteger = require('bigi')
|
||||
var ECPair = require('../src/ecpair')
|
||||
|
||||
var fixtures = require('./fixtures/ecpair.json')
|
||||
|
||||
describe('ECPair', function () {
|
||||
describe('constructor', function () {
|
||||
it('defaults to compressed', function () {
|
||||
var keyPair = new ECPair(BigInteger.ONE)
|
||||
|
||||
assert.equal(keyPair.compressed, true)
|
||||
})
|
||||
|
||||
it('supports the uncompressed option', function () {
|
||||
var keyPair = new ECPair(BigInteger.ONE, null, {
|
||||
compressed: false
|
||||
})
|
||||
|
||||
assert.equal(keyPair.compressed, false)
|
||||
})
|
||||
|
||||
it('supports the network option', function () {
|
||||
var keyPair = new ECPair(BigInteger.ONE, null, {
|
||||
compressed: false,
|
||||
network: networks.testnet
|
||||
})
|
||||
|
||||
assert.equal(keyPair.network, networks.testnet)
|
||||
})
|
||||
|
||||
it('throws if compressed option is not a bool', function () {
|
||||
assert.throws(function () {
|
||||
new ECPair(null, null, {
|
||||
compressed: 2
|
||||
}, /Expected Boolean, got 2/)
|
||||
})
|
||||
})
|
||||
|
||||
it('throws if public and private key given', function () {
|
||||
var qBuffer = new Buffer('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 'hex')
|
||||
var Q = ecurve.Point.decodeFrom(ECPair.curve, qBuffer)
|
||||
|
||||
assert.throws(function () {
|
||||
new ECPair(BigInteger.ONE, Q)
|
||||
}, /Unexpected publicKey parameter/)
|
||||
})
|
||||
|
||||
it('throws if network is missing pubKeyHash constants', function () {
|
||||
assert.throws(function () {
|
||||
new ECPair(null, null, {
|
||||
network: {}
|
||||
}, /Unknown pubKeyHash constants for network/)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.valid.forEach(function (f) {
|
||||
it('calculates the public point for ' + f.WIF, function () {
|
||||
var d = new BigInteger(f.d)
|
||||
var keyPair = new ECPair(d, null, {
|
||||
compressed: f.compressed
|
||||
})
|
||||
|
||||
assert.equal(keyPair.getPublicKeyBuffer().toString('hex'), f.Q)
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.invalid.constructor.forEach(function (f) {
|
||||
it('throws on ' + f.d, function () {
|
||||
var d = new BigInteger(f.d)
|
||||
|
||||
assert.throws(function () {
|
||||
new ECPair(d)
|
||||
}, new RegExp(f.exception))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getPublicKeyBuffer', function () {
|
||||
var keyPair
|
||||
|
||||
beforeEach(function () {
|
||||
keyPair = new ECPair(BigInteger.ONE)
|
||||
})
|
||||
|
||||
it('wraps Q.getEncoded', sinon.test(function () {
|
||||
this.mock(keyPair.Q).expects('getEncoded')
|
||||
.once().calledWith(keyPair.compressed)
|
||||
|
||||
keyPair.getPublicKeyBuffer()
|
||||
}))
|
||||
})
|
||||
|
||||
describe('fromWIF', function () {
|
||||
fixtures.valid.forEach(function (f) {
|
||||
it('imports ' + f.WIF + ' correctly', function () {
|
||||
var keyPair = ECPair.fromWIF(f.WIF)
|
||||
|
||||
assert.equal(keyPair.d.toString(), f.d)
|
||||
assert.equal(keyPair.compressed, f.compressed)
|
||||
assert.equal(keyPair.network, networks[f.network])
|
||||
})
|
||||
})
|
||||
|
||||
fixtures.invalid.fromWIF.forEach(function (f) {
|
||||
it('throws on ' + f.string, function () {
|
||||
assert.throws(function () {
|
||||
ECPair.fromWIF(f.string)
|
||||
}, new RegExp(f.exception))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('toWIF', function () {
|
||||
fixtures.valid.forEach(function (f) {
|
||||
it('exports ' + f.WIF + ' correctly', function () {
|
||||
var keyPair = ECPair.fromWIF(f.WIF)
|
||||
var result = keyPair.toWIF()
|
||||
|
||||
assert.equal(result, f.WIF)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('makeRandom', function () {
|
||||
var d = new Buffer('0404040404040404040404040404040404040404040404040404040404040404', 'hex')
|
||||
var exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'
|
||||
|
||||
describe('uses randombytes RNG', function () {
|
||||
it('generates a ECPair', function () {
|
||||
var stub = { randombytes: function () { return d } }
|
||||
var ProxiedECPair = proxyquire('../src/ecpair', stub)
|
||||
|
||||
var keyPair = ProxiedECPair.makeRandom()
|
||||
assert.equal(keyPair.toWIF(), exWIF)
|
||||
})
|
||||
|
||||
it('passes the options param', sinon.test(function () {
|
||||
var options = {
|
||||
compressed: true
|
||||
}
|
||||
|
||||
// FIXME: waiting on https://github.com/cjohansen/Sinon.JS/issues/613
|
||||
// this.mock(ECPair).expects('constructor')
|
||||
// .once().calledWith(options)
|
||||
|
||||
ECPair.makeRandom(options)
|
||||
}))
|
||||
})
|
||||
|
||||
it('allows a custom RNG to be used', function () {
|
||||
var keyPair = ECPair.makeRandom({
|
||||
rng: function (size) { return d.slice(0, size) }
|
||||
})
|
||||
|
||||
assert.equal(keyPair.toWIF(), exWIF)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAddress', function () {
|
||||
fixtures.valid.forEach(function (f) {
|
||||
it('returns ' + f.address + ' for ' + f.WIF, function () {
|
||||
var keyPair = ECPair.fromWIF(f.WIF)
|
||||
|
||||
assert.equal(keyPair.getAddress().toString(), f.address)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('ecdsa wrappers', function () {
|
||||
var keyPair, hash
|
||||
|
||||
beforeEach(function () {
|
||||
keyPair = ECPair.makeRandom()
|
||||
hash = new Buffer(32)
|
||||
})
|
||||
|
||||
it('uses the secp256k1 curve by default', function () {
|
||||
var secp256k1 = ecurve.getCurveByName('secp256k1')
|
||||
|
||||
for (var property in secp256k1) {
|
||||
// FIXME: circular structures in ecurve
|
||||
if (property === 'G') continue
|
||||
if (property === 'infinity') continue
|
||||
|
||||
var actual = ECPair.curve[property]
|
||||
var expected = secp256k1[property]
|
||||
|
||||
assert.deepEqual(actual, expected)
|
||||
}
|
||||
})
|
||||
|
||||
describe('signing', function () {
|
||||
it('wraps ecdsa.sign', sinon.test(function () {
|
||||
this.mock(ecdsa).expects('sign')
|
||||
.once().calledWith(ECPair.curve, hash, keyPair.d)
|
||||
|
||||
keyPair.sign(hash)
|
||||
}))
|
||||
|
||||
it('throws if no private key is found', function () {
|
||||
keyPair.d = null
|
||||
|
||||
assert.throws(function () {
|
||||
keyPair.sign(hash)
|
||||
}, /Missing private key/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('verify', function () {
|
||||
var signature
|
||||
|
||||
beforeEach(function () {
|
||||
signature = keyPair.sign(hash)
|
||||
})
|
||||
|
||||
it('wraps ecdsa.verify', sinon.test(function () {
|
||||
this.mock(ecdsa).expects('verify')
|
||||
.once().calledWith(ECPair.curve, hash, signature, keyPair.Q)
|
||||
|
||||
keyPair.verify(hash, signature)
|
||||
}))
|
||||
})
|
||||
})
|
||||
})
|
120
test/ecpubkey.js
120
test/ecpubkey.js
|
@ -1,120 +0,0 @@
|
|||
/* global describe, it, beforeEach */
|
||||
|
||||
var assert = require('assert')
|
||||
var crypto = require('../src/crypto')
|
||||
var networks = require('../src/networks')
|
||||
|
||||
var BigInteger = require('bigi')
|
||||
var ECPubKey = require('../src/ecpubkey')
|
||||
|
||||
var ecurve = require('ecurve')
|
||||
var curve = ecurve.getCurveByName('secp256k1')
|
||||
|
||||
var fixtures = require('./fixtures/ecpubkey.json')
|
||||
|
||||
describe('ECPubKey', function () {
|
||||
var Q
|
||||
|
||||
beforeEach(function () {
|
||||
Q = ecurve.Point.fromAffine(
|
||||
curve,
|
||||
new BigInteger(fixtures.Q.x),
|
||||
new BigInteger(fixtures.Q.y)
|
||||
)
|
||||
})
|
||||
|
||||
describe('constructor', function () {
|
||||
it('defaults to compressed', function () {
|
||||
var pubKey = new ECPubKey(Q)
|
||||
|
||||
assert.equal(pubKey.compressed, true)
|
||||
})
|
||||
|
||||
it('supports the uncompressed flag', function () {
|
||||
var pubKey = new ECPubKey(Q, false)
|
||||
|
||||
assert.equal(pubKey.compressed, false)
|
||||
})
|
||||
})
|
||||
|
||||
it('uses the secp256k1 curve by default', function () {
|
||||
var secp256k1 = ecurve.getCurveByName('secp256k1')
|
||||
|
||||
for (var property in secp256k1) {
|
||||
// FIXME: circular structures in ecurve
|
||||
if (property === 'G') continue
|
||||
if (property === 'infinity') continue
|
||||
|
||||
var actual = ECPubKey.curve[property]
|
||||
var expected = secp256k1[property]
|
||||
|
||||
assert.deepEqual(actual, expected)
|
||||
}
|
||||
})
|
||||
|
||||
describe('fromHex/toHex', function () {
|
||||
it('supports compressed points', function () {
|
||||
var pubKey = ECPubKey.fromHex(fixtures.compressed.hex)
|
||||
|
||||
assert(pubKey.Q.equals(Q))
|
||||
assert.equal(pubKey.toHex(), fixtures.compressed.hex)
|
||||
assert.equal(pubKey.compressed, true)
|
||||
})
|
||||
|
||||
it('supports uncompressed points', function () {
|
||||
var pubKey = ECPubKey.fromHex(fixtures.uncompressed.hex)
|
||||
|
||||
assert(pubKey.Q.equals(Q))
|
||||
assert.equal(pubKey.toHex(), fixtures.uncompressed.hex)
|
||||
assert.equal(pubKey.compressed, false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAddress', function () {
|
||||
it('calculates the expected hash (compressed)', function () {
|
||||
var pubKey = new ECPubKey(Q, true)
|
||||
var address = pubKey.getAddress()
|
||||
|
||||
assert.equal(address.hash.toString('hex'), fixtures.compressed.hash160)
|
||||
})
|
||||
|
||||
it('calculates the expected hash (uncompressed)', function () {
|
||||
var pubKey = new ECPubKey(Q, false)
|
||||
var address = pubKey.getAddress()
|
||||
|
||||
assert.equal(address.hash.toString('hex'), fixtures.uncompressed.hash160)
|
||||
})
|
||||
|
||||
it('supports alternative networks', function () {
|
||||
var pubKey = new ECPubKey(Q)
|
||||
var address = pubKey.getAddress(networks.testnet)
|
||||
|
||||
assert.equal(address.version, networks.testnet.pubKeyHash)
|
||||
assert.equal(address.hash.toString('hex'), fixtures.compressed.hash160)
|
||||
})
|
||||
})
|
||||
|
||||
describe('verify', function () {
|
||||
var pubKey, signature
|
||||
beforeEach(function () {
|
||||
pubKey = new ECPubKey(Q)
|
||||
|
||||
signature = {
|
||||
r: new BigInteger(fixtures.signature.r),
|
||||
s: new BigInteger(fixtures.signature.s)
|
||||
}
|
||||
})
|
||||
|
||||
it('verifies a valid signature', function () {
|
||||
var hash = crypto.sha256(fixtures.message)
|
||||
|
||||
assert(pubKey.verify(hash, signature))
|
||||
})
|
||||
|
||||
it("doesn't verify the wrong signature", function () {
|
||||
var hash = crypto.sha256('mushrooms')
|
||||
|
||||
assert(!pubKey.verify(hash, signature))
|
||||
})
|
||||
})
|
||||
})
|
102
test/fixtures/eckey.json
vendored
102
test/fixtures/eckey.json
vendored
|
@ -1,102 +0,0 @@
|
|||
{
|
||||
"valid": [
|
||||
{
|
||||
"d": "1",
|
||||
"Q": "(55066263022277343669578718895168534326250603453777594175500187360389116729240,32670510020758816978083085130507043184471273380659243275938904335757337482424)",
|
||||
"WIFs": [
|
||||
{
|
||||
"network": "bitcoin",
|
||||
"string": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"compressed": true
|
||||
},
|
||||
{
|
||||
"network": "bitcoin",
|
||||
"string": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf",
|
||||
"compressed": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"d": "19898843618908353587043383062236220484949425084007183071220218307100305431102",
|
||||
"Q": "(83225686012142088543596389522774768397204444195709443235253141114409346958144,23739058578904784236915560265041168694780215705543362357495033621678991351768)",
|
||||
"WIFs": [
|
||||
{
|
||||
"network": "bitcoin",
|
||||
"string": "KxhEDBQyyEFymvfJD96q8stMbJMbZUb6D1PmXqBWZDU2WvbvVs9o",
|
||||
"compressed": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
|
||||
"Q": "(30095590000961171681152428142595206241714764354580127609094760797518133922356,93521207164355458151597931319591130635754976513751247168472016818884561919702)",
|
||||
"WIFs": [
|
||||
{
|
||||
"network": "bitcoin",
|
||||
"string": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx",
|
||||
"compressed": true
|
||||
},
|
||||
{
|
||||
"network": "bitcoin",
|
||||
"string": "5JdxzLtFPHNe7CAL8EBC6krdFv9pwPoRo4e3syMZEQT9srmK8hh",
|
||||
"compressed": false
|
||||
},
|
||||
{
|
||||
"network": "testnet",
|
||||
"string": "cRD9b1m3vQxmwmjSoJy7Mj56f4uNFXjcWMCzpQCEmHASS4edEwXv",
|
||||
"compressed": true
|
||||
},
|
||||
{
|
||||
"network": "testnet",
|
||||
"string": "92Qba5hnyWSn5Ffcka56yMQauaWY6ZLd91Vzxbi4a9CCetaHtYj",
|
||||
"compressed": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"d": "115792089237316195423570985008687907852837564279074904382605163141518161494336",
|
||||
"Q": "(55066263022277343669578718895168534326250603453777594175500187360389116729240,83121579216557378445487899878180864668798711284981320763518679672151497189239)",
|
||||
"WIFs": [
|
||||
{
|
||||
"network": "bitcoin",
|
||||
"string": "L5oLkpV3aqBjhki6LmvChTCV6odsp4SXM6FfU2Gppt5kFLaHLuZ9",
|
||||
"compressed": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"invalid": {
|
||||
"constructor": [
|
||||
{
|
||||
"exception": "Private key must be greater than 0",
|
||||
"d": "-1"
|
||||
},
|
||||
{
|
||||
"exception": "Private key must be greater than 0",
|
||||
"d": "0"
|
||||
},
|
||||
{
|
||||
"exception": "Private key must be less than the curve order",
|
||||
"d": "115792089237316195423570985008687907852837564279074904382605163141518161494337"
|
||||
},
|
||||
{
|
||||
"exception": "Private key must be less than the curve order",
|
||||
"d": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
|
||||
}
|
||||
],
|
||||
"WIF": [
|
||||
{
|
||||
"exception": "Invalid compression flag",
|
||||
"string": "ju9rooVsmagsb4qmNyTysUSFB1GB6MdpD7eoGjUTPmZRAApJxRz"
|
||||
},
|
||||
{
|
||||
"exception": "Invalid WIF payload length",
|
||||
"string": "7ZEtRQLhCsDQrd6ZKfmcESdXgas8ggZPN24ByEi5ey6VJW"
|
||||
},
|
||||
{
|
||||
"exception": "Invalid WIF payload length",
|
||||
"string": "5qibUKwsnMo1qDiNp3prGaQkD2JfVJa8F8Na87H2CkMHvuVg6uKhw67Rh"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
102
test/fixtures/ecpair.json
vendored
Normal file
102
test/fixtures/ecpair.json
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
{
|
||||
"valid": [
|
||||
{
|
||||
"d": "1",
|
||||
"Q": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
||||
"compressed": true,
|
||||
"network": "bitcoin",
|
||||
"address": "1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH",
|
||||
"WIF": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
},
|
||||
{
|
||||
"d": "1",
|
||||
"Q": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
|
||||
"compressed": false,
|
||||
"network": "bitcoin",
|
||||
"address": "1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm",
|
||||
"WIF": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf"
|
||||
},
|
||||
{
|
||||
"d": "19898843618908353587043383062236220484949425084007183071220218307100305431102",
|
||||
"Q": "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340",
|
||||
"compressed": true,
|
||||
"network": "bitcoin",
|
||||
"address": "1MasfEKgSiaSeri2C6kgznaqBNtyrZPhNq",
|
||||
"WIF": "KxhEDBQyyEFymvfJD96q8stMbJMbZUb6D1PmXqBWZDU2WvbvVs9o"
|
||||
},
|
||||
{
|
||||
"d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
|
||||
"Q": "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34",
|
||||
"compressed": true,
|
||||
"network": "bitcoin",
|
||||
"address": "1LwwMWdSEMHJ2dMhSvAHZ3g95tG2UBv9jg",
|
||||
"WIF": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx"
|
||||
},
|
||||
{
|
||||
"d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
|
||||
"Q": "044289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34cec320a0565fb7caf11b1ca2f445f9b7b012dda5718b3cface369ee3a034ded6",
|
||||
"compressed": false,
|
||||
"network": "bitcoin",
|
||||
"address": "1zXcfvKCLgsFdJDYPuqpu1sF3q92tnnUM",
|
||||
"WIF": "5JdxzLtFPHNe7CAL8EBC6krdFv9pwPoRo4e3syMZEQT9srmK8hh"
|
||||
},
|
||||
{
|
||||
"d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
|
||||
"Q": "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34",
|
||||
"compressed": true,
|
||||
"network": "testnet",
|
||||
"address": "n1TteZiR3NiYojqKAV8fNxtTwsrjM7kVdj",
|
||||
"WIF": "cRD9b1m3vQxmwmjSoJy7Mj56f4uNFXjcWMCzpQCEmHASS4edEwXv"
|
||||
},
|
||||
{
|
||||
"d": "48968302285117906840285529799176770990048954789747953886390402978935544927851",
|
||||
"Q": "044289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34cec320a0565fb7caf11b1ca2f445f9b7b012dda5718b3cface369ee3a034ded6",
|
||||
"compressed": false,
|
||||
"network": "testnet",
|
||||
"address": "mgWUuj1J1N882jmqFxtDepEC73Rr22E9GU",
|
||||
"WIF": "92Qba5hnyWSn5Ffcka56yMQauaWY6ZLd91Vzxbi4a9CCetaHtYj"
|
||||
},
|
||||
{
|
||||
"d": "115792089237316195423570985008687907852837564279074904382605163141518161494336",
|
||||
"Q": "0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
||||
"compressed": true,
|
||||
"network": "bitcoin",
|
||||
"address": "1GrLCmVQXoyJXaPJQdqssNqwxvha1eUo2E",
|
||||
"WIF": "L5oLkpV3aqBjhki6LmvChTCV6odsp4SXM6FfU2Gppt5kFLaHLuZ9"
|
||||
}
|
||||
],
|
||||
"invalid": {
|
||||
"constructor": [
|
||||
{
|
||||
"exception": "Private key must be greater than 0",
|
||||
"d": "-1"
|
||||
},
|
||||
{
|
||||
"exception": "Private key must be greater than 0",
|
||||
"d": "0"
|
||||
},
|
||||
{
|
||||
"exception": "Private key must be less than the curve order",
|
||||
"d": "115792089237316195423570985008687907852837564279074904382605163141518161494337"
|
||||
},
|
||||
{
|
||||
"exception": "Private key must be less than the curve order",
|
||||
"d": "115792089237316195423570985008687907853269984665640564039457584007913129639935"
|
||||
}
|
||||
],
|
||||
"fromWIF": [
|
||||
{
|
||||
"exception": "Invalid compression flag",
|
||||
"string": "ju9rooVsmagsb4qmNyTysUSFB1GB6MdpD7eoGjUTPmZRAApJxRz"
|
||||
},
|
||||
{
|
||||
"exception": "Invalid WIF payload length",
|
||||
"string": "7ZEtRQLhCsDQrd6ZKfmcESdXgas8ggZPN24ByEi5ey6VJW"
|
||||
},
|
||||
{
|
||||
"exception": "Invalid WIF payload length",
|
||||
"string": "5qibUKwsnMo1qDiNp3prGaQkD2JfVJa8F8Na87H2CkMHvuVg6uKhw67Rh"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
19
test/fixtures/ecpubkey.json
vendored
19
test/fixtures/ecpubkey.json
vendored
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
"Q": {
|
||||
"x": "55066263022277343669578718895168534326250603453777594175500187360389116729240",
|
||||
"y": "32670510020758816978083085130507043184471273380659243275938904335757337482424"
|
||||
},
|
||||
"compressed": {
|
||||
"hex": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
|
||||
"hash160": "751e76e8199196d454941c45d1b3a323f1433bd6"
|
||||
},
|
||||
"uncompressed": {
|
||||
"hex": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8",
|
||||
"hash160": "91b24bf9f5288532960ac687abb035127b1d28a5"
|
||||
},
|
||||
"message": "vires in numeris",
|
||||
"signature": {
|
||||
"r": "68972263025625296948424563184904289678530916807200550828762374724416876919710",
|
||||
"s": "43478152510424186005054433052302509227777805602212468112169549534899266476898"
|
||||
}
|
||||
}
|
94
test/fixtures/transaction_builder.json
vendored
94
test/fixtures/transaction_builder.json
vendored
|
@ -10,7 +10,7 @@
|
|||
"vout": 0,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
|||
"prevTxScript": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 OP_CHECKSIG",
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -53,7 +53,7 @@
|
|||
"vout": 0,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"redeemScript": "OP_DUP OP_HASH160 751e76e8199196d454941c45d1b3a323f1433bd6 OP_EQUALVERIFY OP_CHECKSIG"
|
||||
}
|
||||
]
|
||||
|
@ -75,11 +75,11 @@
|
|||
"vout": 0,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG"
|
||||
},
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT"
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -101,10 +101,10 @@
|
|||
"prevTxScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG",
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx"
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx"
|
||||
},
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT"
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -126,10 +126,10 @@
|
|||
"prevTxScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG",
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT"
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT"
|
||||
},
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx"
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -150,11 +150,11 @@
|
|||
"vout": 0,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a 04f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672 OP_3 OP_CHECKMULTISIG"
|
||||
},
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe"
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -176,7 +176,7 @@
|
|||
"prevTxScript": "OP_HASH160 e89677d91455e541630d62c63718bef738b478b1 OP_EQUAL",
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KxLDMPtVM7sLSu2v5n1LybDibw6P9FFbL4pUwJ51UDm7rp5AmXWW",
|
||||
"keyPair": "KxLDMPtVM7sLSu2v5n1LybDibw6P9FFbL4pUwJ51UDm7rp5AmXWW",
|
||||
"redeemScript": "033e29aea1168a835d5e386c292082db7b7807172a10ec634ad34226f36d79e70f OP_CHECKSIG"
|
||||
}
|
||||
]
|
||||
|
@ -198,7 +198,7 @@
|
|||
"vout": 1,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -222,7 +222,7 @@
|
|||
"sequence": 2147001,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -246,12 +246,12 @@
|
|||
"signs": [
|
||||
{
|
||||
"pubKeyIndex": 0,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae"
|
||||
},
|
||||
{
|
||||
"pubKeyIndex": 1,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae"
|
||||
}
|
||||
]
|
||||
|
@ -275,12 +275,12 @@
|
|||
"signs": [
|
||||
{
|
||||
"pubKeyIndex": 1,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"scriptSig": "OP_0 OP_0 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae"
|
||||
},
|
||||
{
|
||||
"pubKeyIndex": 0,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae"
|
||||
}
|
||||
]
|
||||
|
@ -304,12 +304,12 @@
|
|||
"signs": [
|
||||
{
|
||||
"pubKeyIndex": 0,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae"
|
||||
},
|
||||
{
|
||||
"pubKeyIndex": 1,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"scriptSig": "OP_0 3045022100e37e33a4fe5fccfb87afb0e951e83fcea4820d73b327d21edc1adec3b916c437022061c5786908b674e323a1863cc2feeb60e1679f1892c10ee08ac21e51fd50ba9001 3045022100aa0c323bc639d3d71591be98ccaf7b8cb8c86aa95f060aef5e36fc3f04c4d029022010e2b18de17e307a12ae7e0e88518fe814f18a0ca1ee4510ba23a65628b0657601 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a52ae"
|
||||
}
|
||||
]
|
||||
|
@ -333,12 +333,12 @@
|
|||
"signs": [
|
||||
{
|
||||
"pubKeyIndex": 0,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
},
|
||||
{
|
||||
"pubKeyIndex": 1,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 3045022100ae06d8269b79b5cfa0297d1d88261b0061e52fc2814948c3aa05fa78ee76894302206e0c79a5c90569d8c72a542ef9a06471cbbcd2c651b312339983dfba4f8ff46301 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
}
|
||||
]
|
||||
|
@ -362,12 +362,12 @@
|
|||
"signs": [
|
||||
{
|
||||
"pubKeyIndex": 0,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
},
|
||||
{
|
||||
"pubKeyIndex": 2,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe",
|
||||
"scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
}
|
||||
]
|
||||
|
@ -391,12 +391,12 @@
|
|||
"signs": [
|
||||
{
|
||||
"pubKeyIndex": 2,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe",
|
||||
"scriptSig": "OP_0 OP_0 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
},
|
||||
{
|
||||
"pubKeyIndex": 0,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
}
|
||||
]
|
||||
|
@ -420,12 +420,12 @@
|
|||
"signs": [
|
||||
{
|
||||
"pubKeyIndex": 0,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 OP_0 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
},
|
||||
{
|
||||
"pubKeyIndex": 2,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe",
|
||||
"scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
}
|
||||
]
|
||||
|
@ -449,13 +449,13 @@
|
|||
"signs": [
|
||||
{
|
||||
"pubKeyIndex": 2,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe",
|
||||
"scriptSig": "OP_0 OP_0 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
},
|
||||
{
|
||||
"filterOP_0": true,
|
||||
"pubKeyIndex": 0,
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"scriptSig": "OP_0 3045022100daf0f4f3339d9fbab42b098045c1e4958ee3b308f4ae17be80b63808558d0adb02202f07e3d1f79dc8da285ae0d7f68083d769c11f5621ebd9691d6b48c0d4283d7d01 OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae",
|
||||
"scriptSigFiltered": "OP_0 3045022100a346c61738304eac5e7702188764d19cdf68f4466196729db096d6c87ce18cdd022018c0e8ad03054b0e7e235cda6bedecf35881d7aa7d94ff425a8ace7220f38af001 52410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b84104c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a4104f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e67253ae"
|
||||
}
|
||||
|
@ -522,7 +522,7 @@
|
|||
"vout": 0,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -556,10 +556,10 @@
|
|||
"vout": 1,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn"
|
||||
},
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"throws": true
|
||||
}
|
||||
]
|
||||
|
@ -580,7 +580,7 @@
|
|||
"vout": 1,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"redeemScript": "OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474",
|
||||
"throws": true
|
||||
}
|
||||
|
@ -603,7 +603,7 @@
|
|||
"prevTxScript": "OP_HASH160 7f67f0521934a57d3039f77f9f32cf313f3ac74b OP_EQUAL",
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"throws": true
|
||||
}
|
||||
]
|
||||
|
@ -625,11 +625,11 @@
|
|||
"signs": [
|
||||
{
|
||||
"redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG",
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx"
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx"
|
||||
},
|
||||
{
|
||||
"redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG",
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"throws": true
|
||||
}
|
||||
]
|
||||
|
@ -651,11 +651,11 @@
|
|||
"signs": [
|
||||
{
|
||||
"redeemScript": "OP_2 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 04c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee51ae168fea63dc339a3c58419466ceaeef7f632653266d0e1236431a950cfe52a OP_2 OP_CHECKMULTISIG",
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx",
|
||||
"hashType": 4
|
||||
},
|
||||
{
|
||||
"privKey": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"keyPair": "91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT",
|
||||
"hashType": 2,
|
||||
"throws": true
|
||||
}
|
||||
|
@ -677,7 +677,7 @@
|
|||
"vout": 1,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"redeemScript": "OP_HASH160 7f67f0521934a57d3039f77f9f32cf313f3ac74b OP_EQUAL",
|
||||
"throws": true
|
||||
}
|
||||
|
@ -700,7 +700,7 @@
|
|||
"prevTxScript": "OP_DUP OP_HASH160 aa4d7985c57e011a8b3dd8e0e5a73aaef41629c5 OP_EQUALVERIFY OP_CHECKSIG",
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"keyPair": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG",
|
||||
"throws": true
|
||||
}
|
||||
|
@ -723,11 +723,11 @@
|
|||
"vout": 1,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"keyPair": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf",
|
||||
"redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG"
|
||||
},
|
||||
{
|
||||
"privKey": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn",
|
||||
"keyPair": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf",
|
||||
"throws": true
|
||||
}
|
||||
]
|
||||
|
@ -741,15 +741,15 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"description": "Wrong private key for multisig redeemScript",
|
||||
"exception": "privateKey cannot sign for this input",
|
||||
"description": "Wrong key pair for multisig redeemScript",
|
||||
"exception": "key pair cannot sign for this input",
|
||||
"inputs": [
|
||||
{
|
||||
"txId": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"vout": 1,
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx",
|
||||
"keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx",
|
||||
"redeemScript": "OP_1 0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 OP_1 OP_CHECKMULTISIG",
|
||||
"throws": true
|
||||
}
|
||||
|
@ -772,7 +772,7 @@
|
|||
"prevTxScript": "OP_RETURN 06deadbeef03f895a2ad89fb6d696497af486cb7c644a27aa568c7a18dd06113401115185474",
|
||||
"signs": [
|
||||
{
|
||||
"privKey": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx",
|
||||
"keyPair": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx",
|
||||
"throws": true
|
||||
}
|
||||
]
|
||||
|
|
117
test/hdnode.js
117
test/hdnode.js
|
@ -1,98 +1,54 @@
|
|||
/* global describe, it */
|
||||
/* global describe, it, beforeEach */
|
||||
/* eslint-disable no-new */
|
||||
|
||||
var assert = require('assert')
|
||||
var networks = require('../src/networks')
|
||||
var sinon = require('sinon')
|
||||
|
||||
var BigInteger = require('bigi')
|
||||
var ECKey = require('../src/eckey')
|
||||
var ECPubKey = require('../src/ecpubkey')
|
||||
var ECPair = require('../src/ecpair')
|
||||
var HDNode = require('../src/hdnode')
|
||||
|
||||
var ecurve = require('ecurve')
|
||||
var curve = ecurve.getCurveByName('secp256k1')
|
||||
|
||||
var fixtures = require('./fixtures/hdnode.json')
|
||||
|
||||
describe('HDNode', function () {
|
||||
describe('Constructor', function () {
|
||||
var d = BigInteger.ONE
|
||||
var Q = curve.G.multiply(d)
|
||||
var chainCode = new Buffer(32)
|
||||
chainCode.fill(1)
|
||||
var keyPair, chainCode
|
||||
|
||||
it('calculates the publicKey from a BigInteger', function () {
|
||||
var hd = new HDNode(d, chainCode)
|
||||
beforeEach(function () {
|
||||
var d = BigInteger.ONE
|
||||
|
||||
assert(hd.pubKey.Q.equals(Q))
|
||||
})
|
||||
|
||||
it('allows initialization directly from an ECKey', function () {
|
||||
var ek = new ECKey(d)
|
||||
var hd = new HDNode(ek, chainCode)
|
||||
|
||||
assert.equal(hd.privKey, ek)
|
||||
})
|
||||
|
||||
it('allows initialization directly from an ECPubKey', function () {
|
||||
var ek = new ECPubKey(Q)
|
||||
var hd = new HDNode(ek, chainCode)
|
||||
|
||||
assert.equal(hd.pubKey, ek)
|
||||
})
|
||||
|
||||
it('throws if ECKey is not compressed', function () {
|
||||
var ek = new ECKey(d, false)
|
||||
|
||||
assert.throws(function () {
|
||||
new HDNode(ek, chainCode)
|
||||
}, /ECKey must be compressed/)
|
||||
})
|
||||
|
||||
it('throws if ECPubKey is not compressed', function () {
|
||||
var ek = new ECPubKey(Q, false)
|
||||
|
||||
assert.throws(function () {
|
||||
new HDNode(ek, chainCode)
|
||||
}, /ECPubKey must be compressed/)
|
||||
})
|
||||
|
||||
it('only uses compressed points', function () {
|
||||
var hd = new HDNode(Q, chainCode)
|
||||
var hdP = new HDNode(d, chainCode)
|
||||
|
||||
assert.strictEqual(hd.pubKey.compressed, true)
|
||||
assert.strictEqual(hdP.pubKey.compressed, true)
|
||||
keyPair = new ECPair(d, null)
|
||||
chainCode = new Buffer(32)
|
||||
chainCode.fill(1)
|
||||
})
|
||||
|
||||
it('has a default depth/index of 0', function () {
|
||||
var hd = new HDNode(Q, chainCode)
|
||||
var hd = new HDNode(keyPair, chainCode)
|
||||
|
||||
assert.strictEqual(hd.depth, 0)
|
||||
assert.strictEqual(hd.index, 0)
|
||||
})
|
||||
|
||||
it('defaults to the bitcoin network', function () {
|
||||
var hd = new HDNode(Q, chainCode)
|
||||
it('throws on uncompressed keyPair', function () {
|
||||
keyPair.compressed = false
|
||||
|
||||
assert.equal(hd.network, networks.bitcoin)
|
||||
})
|
||||
|
||||
it('supports alternative networks', function () {
|
||||
var hd = new HDNode(Q, chainCode, networks.testnet)
|
||||
|
||||
assert.equal(hd.network, networks.testnet)
|
||||
assert.throws(function () {
|
||||
new HDNode(keyPair, chainCode)
|
||||
}, /BIP32 only allows compressed keyPairs/)
|
||||
})
|
||||
|
||||
it('throws when an invalid length chain code is given', function () {
|
||||
assert.throws(function () {
|
||||
new HDNode(d, chainCode.slice(0, 20), networks.testnet)
|
||||
new HDNode(keyPair, chainCode.slice(0, 20))
|
||||
}, /Expected chainCode length of 32, got 20/)
|
||||
})
|
||||
|
||||
it('throws when an unknown network is given', function () {
|
||||
keyPair.network = {}
|
||||
|
||||
assert.throws(function () {
|
||||
new HDNode(d, chainCode, {})
|
||||
new HDNode(keyPair, chainCode)
|
||||
}, /Unknown BIP32 constants for network/)
|
||||
})
|
||||
})
|
||||
|
@ -103,7 +59,7 @@ describe('HDNode', function () {
|
|||
var network = networks[f.network]
|
||||
var hd = HDNode.fromSeedHex(f.master.seed, network)
|
||||
|
||||
assert.equal(hd.privKey.toWIF(network), f.master.wif)
|
||||
assert.equal(hd.keyPair.toWIF(), f.master.wif)
|
||||
assert.equal(hd.chainCode.toString('hex'), f.master.chainCode)
|
||||
})
|
||||
})
|
||||
|
@ -148,7 +104,7 @@ describe('HDNode', function () {
|
|||
var hd = HDNode.fromBase58(f.master.base58)
|
||||
|
||||
assert.equal(hd.toBase58(), f.master.base58)
|
||||
assert.equal(hd.network, network)
|
||||
assert.equal(hd.keyPair.network, network)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -158,7 +114,7 @@ describe('HDNode', function () {
|
|||
var hd = HDNode.fromBase58(f.master.base58Priv, network)
|
||||
|
||||
assert.equal(hd.toBase58(), f.master.base58Priv)
|
||||
assert.equal(hd.network, network)
|
||||
assert.equal(hd.keyPair.network, network)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -194,13 +150,20 @@ describe('HDNode', function () {
|
|||
})
|
||||
|
||||
describe('getAddress', function () {
|
||||
fixtures.valid.forEach(function (f) {
|
||||
it('returns ' + f.master.address + ' for ' + f.master.fingerprint, function () {
|
||||
var hd = HDNode.fromBase58(f.master.base58)
|
||||
var hd
|
||||
|
||||
assert.equal(hd.getAddress().toString(), f.master.address)
|
||||
})
|
||||
beforeEach(function () {
|
||||
var f = fixtures.valid[0]
|
||||
|
||||
hd = HDNode.fromBase58(f.master.base58)
|
||||
})
|
||||
|
||||
it('wraps ECPair.getAddress', sinon.test(function () {
|
||||
this.mock(hd.keyPair).expects('getAddress')
|
||||
.once().returns('foobar')
|
||||
|
||||
assert.equal(hd.getAddress(), 'foobar')
|
||||
}))
|
||||
})
|
||||
|
||||
describe('neutered', function () {
|
||||
|
@ -210,8 +173,8 @@ describe('HDNode', function () {
|
|||
var hd = HDNode.fromBase58(f.master.base58)
|
||||
var hdn = hd.neutered()
|
||||
|
||||
assert.equal(hdn.privKey, undefined)
|
||||
assert.equal(hdn.pubKey.toHex(), hd.pubKey.toHex())
|
||||
assert.equal(hdn.keyPair.d, null)
|
||||
assert.equal(hdn.keyPair.Q, hd.keyPair.Q)
|
||||
assert.equal(hdn.chainCode, hd.chainCode)
|
||||
assert.equal(hdn.depth, hd.depth)
|
||||
assert.equal(hdn.index, hd.index)
|
||||
|
@ -219,9 +182,9 @@ describe('HDNode', function () {
|
|||
})
|
||||
|
||||
describe('derive', function () {
|
||||
function verifyVector (hd, network, v, depth) {
|
||||
assert.equal(hd.privKey.toWIF(network), v.wif)
|
||||
assert.equal(hd.pubKey.toHex(), v.pubKey)
|
||||
function verifyVector (hd, v, depth) {
|
||||
assert.equal(hd.keyPair.toWIF(), v.wif)
|
||||
assert.equal(hd.keyPair.getPublicKeyBuffer().toString('hex'), v.pubKey)
|
||||
assert.equal(hd.chainCode.toString('hex'), v.chainCode)
|
||||
assert.equal(hd.depth, depth || 0)
|
||||
|
||||
|
@ -245,7 +208,7 @@ describe('HDNode', function () {
|
|||
hd = hd.derive(c.m)
|
||||
}
|
||||
|
||||
verifyVector(hd, network, c, i + 1)
|
||||
verifyVector(hd, c, i + 1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -6,10 +6,10 @@ var blockchain = new (require('cb-helloblock'))('testnet')
|
|||
|
||||
describe('bitcoinjs-lib (advanced)', function () {
|
||||
it('can sign a Bitcoin message', function () {
|
||||
var key = bitcoin.ECKey.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss')
|
||||
var keyPair = bitcoin.ECPair.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss')
|
||||
var message = 'This is an example of a signed message.'
|
||||
|
||||
var signature = bitcoin.message.sign(key, message)
|
||||
var signature = bitcoin.message.sign(keyPair, message)
|
||||
assert.equal(signature.toString('base64'), 'G9L5yLFjti0QTHhPyFrZCT1V/MMnBtXKmoiKDZ78NDBjERki6ZTQZdSMCtkgoNmp17By9ItJr8o7ChX0XxY91nk=')
|
||||
})
|
||||
|
||||
|
@ -24,8 +24,10 @@ describe('bitcoinjs-lib (advanced)', function () {
|
|||
it('can create an OP_RETURN transaction', function (done) {
|
||||
this.timeout(20000)
|
||||
|
||||
var key = bitcoin.ECKey.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy')
|
||||
var address = key.pub.getAddress(bitcoin.networks.testnet).toString()
|
||||
var keyPair = bitcoin.ECPair.makeRandom({
|
||||
network: bitcoin.networks.testnet
|
||||
})
|
||||
var address = keyPair.getAddress().toString()
|
||||
|
||||
blockchain.addresses.__faucetWithdraw(address, 2e4, function (err) {
|
||||
if (err) return done(err)
|
||||
|
@ -41,7 +43,7 @@ describe('bitcoinjs-lib (advanced)', function () {
|
|||
|
||||
tx.addInput(unspent.txId, unspent.vout)
|
||||
tx.addOutput(dataScript, 1000)
|
||||
tx.sign(0, key)
|
||||
tx.sign(0, keyPair)
|
||||
|
||||
var txBuilt = tx.build()
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ describe('bitcoinjs-lib (basic)', function () {
|
|||
// for testing only
|
||||
function rng () { return new Buffer('zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz') }
|
||||
|
||||
// generate random key (custom rng for testing only)
|
||||
var key = bitcoin.ECKey.makeRandom(undefined, rng)
|
||||
var address = key.pub.getAddress().toString()
|
||||
// generate random keyPair
|
||||
var keyPair = bitcoin.ECPair.makeRandom({ rng: rng })
|
||||
var address = keyPair.getAddress().toString()
|
||||
|
||||
assert.equal(address, '1F5VhMHukdnUES9kfXqzPzMeF1GPHKiF64')
|
||||
})
|
||||
|
@ -20,25 +20,26 @@ describe('bitcoinjs-lib (basic)', function () {
|
|||
var hash = bitcoin.crypto.sha256('correct horse battery staple')
|
||||
var d = bigi.fromBuffer(hash)
|
||||
|
||||
var key = new bitcoin.ECKey(d)
|
||||
var keyPair = new bitcoin.ECPair(d)
|
||||
var address = keyPair.getAddress().toString()
|
||||
|
||||
assert.equal(key.pub.getAddress().toString(), '1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8')
|
||||
assert.equal(address, '1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8')
|
||||
})
|
||||
|
||||
it('can import an address via WIF', function () {
|
||||
var key = bitcoin.ECKey.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
var address = key.pub.getAddress().toString()
|
||||
var keyPair = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
var address = keyPair.getAddress().toString()
|
||||
|
||||
assert.equal(address, '19AAjaTUbRjQCMuVczepkoPswiZRhjtg31')
|
||||
})
|
||||
|
||||
it('can create a Transaction', function () {
|
||||
var key = bitcoin.ECKey.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy')
|
||||
var keyPair = bitcoin.ECPair.fromWIF('L1uyy5qTuGrVXrmrsvHWHgVzW9kKdrp27wBC7Vs6nZDTF2BRUVwy')
|
||||
var tx = new bitcoin.TransactionBuilder()
|
||||
|
||||
tx.addInput('aa94ab02c182214f090e99a0d57021caffd0f195a81c24602b1028b130b63e31', 0)
|
||||
tx.addOutput('1Gokm82v6DmtwKEB8AiVhm82hyFSsEvBDK', 15000)
|
||||
tx.sign(0, key)
|
||||
tx.sign(0, keyPair)
|
||||
|
||||
assert.equal(tx.build().toHex(), '0100000001313eb630b128102b60241ca895f1d0ffca2170d5a0990e094f2182c102ab94aa000000006b483045022100aefbcf847900b01dd3e3debe054d3b6d03d715d50aea8525f5ea3396f168a1fb022013d181d05b15b90111808b22ef4f9ebe701caf2ab48db269691fdf4e9048f4f60121029f50f51d63b345039a290c94bffd3180c99ed659ff6ea6b1242bca47eb93b59fffffffff01983a0000000000001976a914ad618cf4333b3b248f9744e8e81db2964d0ae39788ac00000000')
|
||||
})
|
||||
|
|
|
@ -9,17 +9,17 @@ var crypto = require('crypto')
|
|||
|
||||
describe('bitcoinjs-lib (crypto)', function () {
|
||||
it('can generate a single-key stealth address', function () {
|
||||
var receiver = bitcoin.ECKey.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss')
|
||||
var receiver = bitcoin.ECPair.fromWIF('5KYZdUEo39z3FPrtuX2QbbwGnNP5zTd7yyr2SC1j299sBCnWjss')
|
||||
|
||||
// XXX: ephemeral, must be random (and secret to sender) to preserve privacy
|
||||
var sender = bitcoin.ECKey.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
var sender = bitcoin.ECPair.fromWIF('Kxr9tQED9H44gCmp6HAdmemAzU3n84H3dGkuWTKvE23JgHMW8gct')
|
||||
|
||||
var G = bitcoin.ECKey.curve.G
|
||||
var G = bitcoin.ECPair.curve.G
|
||||
var d = receiver.d // secret (receiver only)
|
||||
var Q = receiver.pub.Q // shared
|
||||
var Q = receiver.Q // shared
|
||||
|
||||
var e = sender.d // secret (sender only)
|
||||
var P = sender.pub.Q // shared
|
||||
var P = sender.Q // shared
|
||||
|
||||
// derived shared secret
|
||||
var eQ = Q.multiply(e) // sender
|
||||
|
@ -35,7 +35,7 @@ describe('bitcoinjs-lib (crypto)', function () {
|
|||
assert.deepEqual(QprimeR.getEncoded(), QprimeS.getEncoded())
|
||||
|
||||
// derived shared-secret address
|
||||
var address = new bitcoin.ECPubKey(QprimeS).getAddress().toString()
|
||||
var address = new bitcoin.ECPair(null, QprimeS).getAddress().toString()
|
||||
|
||||
assert.equal(address, '1EwCNJNZM5q58YPPTnjR1H5BvYRNeyZi47')
|
||||
})
|
||||
|
@ -45,13 +45,14 @@ describe('bitcoinjs-lib (crypto)', function () {
|
|||
|
||||
it("can recover a parent private key from the parent's public key and a derived non-hardened child private key", function () {
|
||||
function recoverParent (master, child) {
|
||||
assert(!master.privKey, 'You already have the parent private key')
|
||||
assert(child.privKey, 'Missing child private key')
|
||||
assert(!master.keyPair.d, 'You already have the parent private key')
|
||||
assert(child.keyPair.d, 'Missing child private key')
|
||||
|
||||
var curve = bitcoin.ECKey.curve
|
||||
var QP = master.pubKey.toBuffer()
|
||||
var QP64 = QP.toString('base64')
|
||||
var d1 = child.privKey.d
|
||||
var curve = bitcoin.ECPair.curve
|
||||
var QP = master.keyPair.Q
|
||||
var serQP = master.keyPair.getPublicKeyBuffer()
|
||||
|
||||
var d1 = child.keyPair.d
|
||||
var d2
|
||||
var indexBuffer = new Buffer(4)
|
||||
|
||||
|
@ -60,7 +61,7 @@ describe('bitcoinjs-lib (crypto)', function () {
|
|||
indexBuffer.writeUInt32BE(i, 0)
|
||||
|
||||
// calculate I
|
||||
var data = Buffer.concat([QP, indexBuffer])
|
||||
var data = Buffer.concat([serQP, indexBuffer])
|
||||
var I = crypto.createHmac('sha512', master.chainCode).update(data).digest()
|
||||
var IL = I.slice(0, 32)
|
||||
var pIL = bigi.fromBuffer(IL)
|
||||
|
@ -68,11 +69,11 @@ describe('bitcoinjs-lib (crypto)', function () {
|
|||
// See hdnode.js:273 to understand
|
||||
d2 = d1.subtract(pIL).mod(curve.n)
|
||||
|
||||
var Qp = new bitcoin.ECKey(d2, true).pub.toBuffer()
|
||||
if (Qp.toString('base64') === QP64) break
|
||||
var Qp = new bitcoin.ECPair(d2).Q
|
||||
if (Qp.equals(QP)) break
|
||||
}
|
||||
|
||||
var node = new bitcoin.HDNode(d2, master.chainCode, master.network)
|
||||
var node = new bitcoin.HDNode(new bitcoin.ECPair(d2), master.chainCode, master.network)
|
||||
node.depth = master.depth
|
||||
node.index = master.index
|
||||
node.masterFingerprint = master.masterFingerprint
|
||||
|
@ -133,7 +134,7 @@ describe('bitcoinjs-lib (crypto)', function () {
|
|||
var prevOutScript = prevOut.outs[prevVout].script
|
||||
|
||||
var scriptSignature = bitcoin.ECSignature.parseScriptSignature(script.chunks[0])
|
||||
var publicKey = bitcoin.ECPubKey.fromBuffer(script.chunks[1])
|
||||
var publicKey = bitcoin.ECPair.fromPublicKeyBuffer(script.chunks[1])
|
||||
|
||||
var m = transaction.hashForSignature(input.vout, prevOutScript, scriptSignature.hashType)
|
||||
assert(publicKey.verify(m, scriptSignature.signature), 'Invalid m')
|
||||
|
@ -151,7 +152,8 @@ describe('bitcoinjs-lib (crypto)', function () {
|
|||
async.parallel(tasks, function (err) {
|
||||
if (err)
|
||||
throw err
|
||||
var n = bitcoin.ECKey.curve.n
|
||||
|
||||
var n = bitcoin.ECPair.curve.n
|
||||
|
||||
for (var i = 0; i < inputs.length; ++i) {
|
||||
for (var j = i + 1; j < inputs.length; ++j) {
|
||||
|
|
|
@ -10,11 +10,13 @@ describe('bitcoinjs-lib (multisig)', function () {
|
|||
'026477115981fe981a6918a6297d9803c4dc04f328f22041bedff886bbc2962e01',
|
||||
'02c96db2302d19b43d4c69368babace7854cc84eb9e061cde51cfa77ca4a22b8b9',
|
||||
'03c6103b3b83e4a24a0e33a4df246ef11772f9992663db0c35759a5e2ebf68d8e9'
|
||||
].map(bitcoin.ECPubKey.fromHex)
|
||||
].map(function (hex) {
|
||||
return new Buffer(hex, 'hex')
|
||||
})
|
||||
|
||||
var redeemScript = bitcoin.scripts.multisigOutput(2, pubKeys) // 2 of 3
|
||||
var scriptPubKey = bitcoin.scripts.scriptHashOutput(redeemScript.getHash())
|
||||
var address = bitcoin.Address.fromOutputScript(scriptPubKey).toString()
|
||||
var address = bitcoin.Address.fromOutputScript(scriptPubKey)
|
||||
|
||||
assert.equal(address, '36NUkt6FWUi3LAWBqWRdDmdTWbt91Yvfu7')
|
||||
})
|
||||
|
@ -22,15 +24,13 @@ describe('bitcoinjs-lib (multisig)', function () {
|
|||
it('can spend from a 2-of-4 multsig P2SH address', function (done) {
|
||||
this.timeout(20000)
|
||||
|
||||
var privKeys = [
|
||||
var keyPairs = [
|
||||
'91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgwmaKkrx',
|
||||
'91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgww7vXtT',
|
||||
'91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx3cTMqe',
|
||||
'91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbgx9rcrL7'
|
||||
].map(bitcoin.ECKey.fromWIF)
|
||||
var pubKeys = privKeys.map(function (x) {
|
||||
return x.pub
|
||||
})
|
||||
].map(bitcoin.ECPair.fromWIF)
|
||||
var pubKeys = keyPairs.map(function (x) { return x.getPublicKeyBuffer() })
|
||||
|
||||
var redeemScript = bitcoin.scripts.multisigOutput(2, pubKeys) // 2 of 4
|
||||
var scriptPubKey = bitcoin.scripts.scriptHashOutput(redeemScript.getHash())
|
||||
|
@ -44,7 +44,7 @@ describe('bitcoinjs-lib (multisig)', function () {
|
|||
blockchain.addresses.unspents(address, function (err, unspents) {
|
||||
if (err) return done(err)
|
||||
|
||||
// filter small unspents
|
||||
// filter small unspents
|
||||
unspents = unspents.filter(function (unspent) {
|
||||
return unspent.value > 1e4
|
||||
})
|
||||
|
@ -53,15 +53,17 @@ describe('bitcoinjs-lib (multisig)', function () {
|
|||
var unspent = unspents.pop()
|
||||
|
||||
// make a random destination address
|
||||
var targetAddress = bitcoin.ECKey.makeRandom().pub.getAddress(bitcoin.networks.testnet).toString()
|
||||
var targetAddress = bitcoin.ECPair.makeRandom({
|
||||
network: bitcoin.networks.testnet
|
||||
}).getAddress().toString()
|
||||
|
||||
var txb = new bitcoin.TransactionBuilder()
|
||||
txb.addInput(unspent.txId, unspent.vout)
|
||||
txb.addOutput(targetAddress, 1e4)
|
||||
|
||||
// sign with 1st and 3rd key
|
||||
txb.sign(0, privKeys[0], redeemScript)
|
||||
txb.sign(0, privKeys[2], redeemScript)
|
||||
txb.sign(0, keyPairs[0], redeemScript)
|
||||
txb.sign(0, keyPairs[2], redeemScript)
|
||||
|
||||
// broadcast our transaction
|
||||
blockchain.transactions.propagate(txb.build().toHex(), function (err) {
|
||||
|
|
|
@ -6,7 +6,7 @@ var networks = require('../src/networks')
|
|||
|
||||
var Address = require('../src/address')
|
||||
var BigInteger = require('bigi')
|
||||
var ECKey = require('../src/eckey')
|
||||
var ECPair = require('../src/ecpair')
|
||||
|
||||
var fixtures = require('./fixtures/message.json')
|
||||
|
||||
|
@ -55,12 +55,14 @@ describe('message', function () {
|
|||
it(f.description, function () {
|
||||
var network = networks[f.network]
|
||||
|
||||
var privKey = new ECKey(new BigInteger(f.d), false)
|
||||
var signature = message.sign(privKey, f.message, network)
|
||||
var keyPair = new ECPair(new BigInteger(f.d), null, {
|
||||
compressed: false
|
||||
})
|
||||
var signature = message.sign(keyPair, f.message, network)
|
||||
assert.equal(signature.toString('base64'), f.signature)
|
||||
|
||||
if (f.compressed) {
|
||||
var compressedPrivKey = new ECKey(new BigInteger(f.d))
|
||||
var compressedPrivKey = new ECPair(new BigInteger(f.d))
|
||||
var compressedSignature = message.sign(compressedPrivKey, f.message)
|
||||
|
||||
assert.equal(compressedSignature.toString('base64'), f.compressed.signature)
|
||||
|
|
|
@ -15,7 +15,7 @@ describe('networks', function () {
|
|||
var extb58 = f.bip32[name]
|
||||
|
||||
it(extb58 + ' auto-detects ' + f.network, function () {
|
||||
assert.equal(HDNode.fromBase58(extb58).network, network)
|
||||
assert.equal(HDNode.fromBase58(extb58).keyPair.network, network)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -4,7 +4,7 @@ var assert = require('assert')
|
|||
var ops = require('../src/opcodes')
|
||||
var scripts = require('../src/scripts')
|
||||
|
||||
var ECPubKey = require('../src/ecpubkey')
|
||||
var ECPair = require('../src/ecpair')
|
||||
var Script = require('../src/script')
|
||||
|
||||
var fixtures = require('./fixtures/scripts.json')
|
||||
|
@ -150,8 +150,7 @@ describe('Scripts', function () {
|
|||
if (f.type !== 'pubkey') return
|
||||
|
||||
it('returns ' + f.scriptPubKey, function () {
|
||||
var pubKey = ECPubKey.fromHex(f.pubKey)
|
||||
|
||||
var pubKey = new Buffer(f.pubKey, 'hex')
|
||||
var scriptPubKey = scripts.pubKeyOutput(pubKey)
|
||||
assert.equal(scriptPubKey.toASM(), f.scriptPubKey)
|
||||
})
|
||||
|
@ -162,7 +161,7 @@ describe('Scripts', function () {
|
|||
fixtures.valid.forEach(function (f) {
|
||||
if (f.type !== 'pubkeyhash') return
|
||||
|
||||
var pubKey = ECPubKey.fromHex(f.pubKey)
|
||||
var pubKey = new Buffer(f.pubKey, 'hex')
|
||||
|
||||
it('returns ' + f.scriptSig, function () {
|
||||
var signature = new Buffer(f.signature, 'hex')
|
||||
|
@ -177,8 +176,8 @@ describe('Scripts', function () {
|
|||
fixtures.valid.forEach(function (f) {
|
||||
if (f.type !== 'pubkeyhash') return
|
||||
|
||||
var pubKey = ECPubKey.fromHex(f.pubKey)
|
||||
var address = pubKey.getAddress()
|
||||
var pubKey = new Buffer(f.pubKey, 'hex')
|
||||
var address = ECPair.fromPublicKeyBuffer(pubKey).getAddress()
|
||||
|
||||
it('returns ' + f.scriptPubKey, function () {
|
||||
var scriptPubKey = scripts.pubKeyHashOutput(address.hash)
|
||||
|
@ -220,7 +219,7 @@ describe('Scripts', function () {
|
|||
fixtures.valid.forEach(function (f) {
|
||||
if (f.type !== 'multisig') return
|
||||
|
||||
var pubKeys = f.pubKeys.map(ECPubKey.fromHex)
|
||||
var pubKeys = f.pubKeys.map(function (p) { return new Buffer(p, 'hex') })
|
||||
var scriptPubKey = scripts.multisigOutput(pubKeys.length, pubKeys)
|
||||
|
||||
it('returns ' + f.scriptPubKey, function () {
|
||||
|
@ -229,7 +228,9 @@ describe('Scripts', function () {
|
|||
})
|
||||
|
||||
fixtures.invalid.multisigOutput.forEach(function (f) {
|
||||
var pubKeys = f.pubKeys.map(ECPubKey.fromHex)
|
||||
var pubKeys = f.pubKeys.map(function (p) {
|
||||
return new Buffer(p, 'hex')
|
||||
})
|
||||
|
||||
it('throws on ' + f.exception, function () {
|
||||
assert.throws(function () {
|
||||
|
|
|
@ -6,7 +6,7 @@ var scripts = require('../src/scripts')
|
|||
|
||||
var Address = require('../src/address')
|
||||
var BigInteger = require('bigi')
|
||||
var ECKey = require('../src/eckey')
|
||||
var ECPair = require('../src/ecpair')
|
||||
var Script = require('../src/script')
|
||||
var Transaction = require('../src/transaction')
|
||||
var TransactionBuilder = require('../src/transaction_builder')
|
||||
|
@ -33,14 +33,14 @@ function construct (txb, f, sign) {
|
|||
if (sign === undefined || sign) {
|
||||
f.inputs.forEach(function (input, index) {
|
||||
input.signs.forEach(function (sign) {
|
||||
var privKey = ECKey.fromWIF(sign.privKey)
|
||||
var keyPair = ECPair.fromWIF(sign.keyPair)
|
||||
var redeemScript
|
||||
|
||||
if (sign.redeemScript) {
|
||||
redeemScript = Script.fromASM(sign.redeemScript)
|
||||
}
|
||||
|
||||
txb.sign(index, privKey, redeemScript, sign.hashType)
|
||||
txb.sign(index, keyPair, redeemScript, sign.hashType)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ function construct (txb, f, sign) {
|
|||
describe('TransactionBuilder', function () {
|
||||
var privAddress, privScript
|
||||
var prevTx, prevTxHash
|
||||
var privKey
|
||||
var keyPair
|
||||
var txb
|
||||
|
||||
beforeEach(function () {
|
||||
|
@ -69,8 +69,8 @@ describe('TransactionBuilder', function () {
|
|||
prevTx.addOutput(Address.fromBase58Check('1cMh228HTCiwS8ZsaakH8A8wze1JR5ZsP').toOutputScript(), 1)
|
||||
prevTxHash = prevTx.getHash()
|
||||
|
||||
privKey = new ECKey(BigInteger.ONE, false)
|
||||
privAddress = privKey.pub.getAddress()
|
||||
keyPair = new ECPair(BigInteger.ONE)
|
||||
privAddress = keyPair.getAddress()
|
||||
privScript = privAddress.toOutputScript()
|
||||
})
|
||||
|
||||
|
@ -115,7 +115,7 @@ describe('TransactionBuilder', function () {
|
|||
|
||||
it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', function () {
|
||||
txb.addInput(prevTxHash, 0)
|
||||
txb.sign(0, privKey)
|
||||
txb.sign(0, keyPair)
|
||||
|
||||
assert.throws(function () {
|
||||
txb.addInput(prevTxHash, 0)
|
||||
|
@ -154,7 +154,7 @@ describe('TransactionBuilder', function () {
|
|||
it('throws if SIGHASH_ALL has been used to sign any existing scriptSigs', function () {
|
||||
txb.addInput(prevTxHash, 0)
|
||||
txb.addOutput(privScript, 2000)
|
||||
txb.sign(0, privKey)
|
||||
txb.sign(0, keyPair)
|
||||
|
||||
assert.throws(function () {
|
||||
txb.addOutput(privScript, 9000)
|
||||
|
@ -169,7 +169,7 @@ describe('TransactionBuilder', function () {
|
|||
|
||||
f.inputs.forEach(function (input, index) {
|
||||
input.signs.forEach(function (sign) {
|
||||
var privKey = ECKey.fromWIF(sign.privKey)
|
||||
var keyPair = ECPair.fromWIF(sign.keyPair)
|
||||
var redeemScript
|
||||
|
||||
if (sign.redeemScript) {
|
||||
|
@ -177,10 +177,11 @@ describe('TransactionBuilder', function () {
|
|||
}
|
||||
|
||||
if (!sign.throws) {
|
||||
txb.sign(index, privKey, redeemScript, sign.hashType)
|
||||
txb.sign(index, keyPair, redeemScript, sign.hashType)
|
||||
|
||||
} else {
|
||||
assert.throws(function () {
|
||||
txb.sign(index, privKey, redeemScript, sign.hashType)
|
||||
txb.sign(index, keyPair, redeemScript, sign.hashType)
|
||||
}, new RegExp(f.exception))
|
||||
}
|
||||
})
|
||||
|
@ -256,8 +257,8 @@ describe('TransactionBuilder', function () {
|
|||
txb = TransactionBuilder.fromTransaction(tx)
|
||||
}
|
||||
|
||||
var privKey = ECKey.fromWIF(sign.privKey)
|
||||
txb.sign(i, privKey, redeemScript, sign.hashType)
|
||||
var keyPair = ECPair.fromWIF(sign.keyPair)
|
||||
txb.sign(i, keyPair, redeemScript, sign.hashType)
|
||||
|
||||
// update the tx
|
||||
tx = txb.buildIncomplete()
|
||||
|
|
Loading…
Reference in a new issue