25 changed files with 2078 additions and 2128 deletions
@ -1,29 +1,25 @@ |
|||
var Key = require('./eckey'); |
|||
var Key = require('./eckey') |
|||
var T = require('./transaction') |
|||
|
|||
module.exports = { |
|||
Address: require('./address'), |
|||
Key: Key.ECKey, |
|||
ECKey: Key.ECKey, |
|||
ECPubKey: Key.ECPubKey, |
|||
Message: require('./message'), |
|||
BigInteger: require('./jsbn/jsbn'), |
|||
Crypto: require('crypto-js'), //should we expose this at all?
|
|||
Script: require('./script'), |
|||
Opcode: require('./opcode'), |
|||
Transaction: require('./transaction').Transaction, |
|||
Util: require('./util'), |
|||
TransactionIn: require('./transaction').TransactionIn, |
|||
TransactionOut: require('./transaction').TransactionOut, |
|||
ECPointFp: require('./jsbn/ec').ECPointFp, |
|||
Wallet: require('./wallet'), |
|||
network: require('./network'), |
|||
|
|||
ecdsa: require('./ecdsa'), |
|||
HDWallet: require('./hdwallet.js'), |
|||
|
|||
// base58 encoding/decoding to bytes
|
|||
base58: require('./base58'), |
|||
|
|||
// conversions
|
|||
convert: require('./convert') |
|||
Address: require('./address'), |
|||
Key: Key.ECKey, |
|||
ECKey: Key.ECKey, |
|||
ECPubKey: Key.ECPubKey, |
|||
Message: require('./message'), |
|||
BigInteger: require('./jsbn/jsbn'), |
|||
Crypto: require('crypto-js'), //should we expose this at all?
|
|||
Script: require('./script'), |
|||
Opcode: require('./opcode'), |
|||
Transaction: T.Transaction, |
|||
Util: require('./util'), |
|||
TransactionIn: T.TransactionIn, |
|||
TransactionOut: T.TransactionOut, |
|||
ECPointFp: require('./jsbn/ec').ECPointFp, |
|||
Wallet: require('./wallet'), |
|||
network: require('./network'), |
|||
ecdsa: require('./ecdsa'), |
|||
HDWallet: require('./hdwallet.js'), |
|||
base58: require('./base58'), |
|||
convert: require('./convert') |
|||
} |
|||
|
@ -1,147 +1,147 @@ |
|||
var Opcode = { |
|||
map: { |
|||
// push value
|
|||
OP_0 : 0, |
|||
OP_FALSE : 0, |
|||
OP_PUSHDATA1 : 76, |
|||
OP_PUSHDATA2 : 77, |
|||
OP_PUSHDATA4 : 78, |
|||
OP_1NEGATE : 79, |
|||
OP_RESERVED : 80, |
|||
OP_1 : 81, |
|||
OP_TRUE : 81, |
|||
OP_2 : 82, |
|||
OP_3 : 83, |
|||
OP_4 : 84, |
|||
OP_5 : 85, |
|||
OP_6 : 86, |
|||
OP_7 : 87, |
|||
OP_8 : 88, |
|||
OP_9 : 89, |
|||
OP_10 : 90, |
|||
OP_11 : 91, |
|||
OP_12 : 92, |
|||
OP_13 : 93, |
|||
OP_14 : 94, |
|||
OP_15 : 95, |
|||
OP_16 : 96, |
|||
map: { |
|||
// push value
|
|||
OP_0 : 0, |
|||
OP_FALSE : 0, |
|||
OP_PUSHDATA1 : 76, |
|||
OP_PUSHDATA2 : 77, |
|||
OP_PUSHDATA4 : 78, |
|||
OP_1NEGATE : 79, |
|||
OP_RESERVED : 80, |
|||
OP_1 : 81, |
|||
OP_TRUE : 81, |
|||
OP_2 : 82, |
|||
OP_3 : 83, |
|||
OP_4 : 84, |
|||
OP_5 : 85, |
|||
OP_6 : 86, |
|||
OP_7 : 87, |
|||
OP_8 : 88, |
|||
OP_9 : 89, |
|||
OP_10 : 90, |
|||
OP_11 : 91, |
|||
OP_12 : 92, |
|||
OP_13 : 93, |
|||
OP_14 : 94, |
|||
OP_15 : 95, |
|||
OP_16 : 96, |
|||
|
|||
// control
|
|||
OP_NOP : 97, |
|||
OP_VER : 98, |
|||
OP_IF : 99, |
|||
OP_NOTIF : 100, |
|||
OP_VERIF : 101, |
|||
OP_VERNOTIF : 102, |
|||
OP_ELSE : 103, |
|||
OP_ENDIF : 104, |
|||
OP_VERIFY : 105, |
|||
OP_RETURN : 106, |
|||
// control
|
|||
OP_NOP : 97, |
|||
OP_VER : 98, |
|||
OP_IF : 99, |
|||
OP_NOTIF : 100, |
|||
OP_VERIF : 101, |
|||
OP_VERNOTIF : 102, |
|||
OP_ELSE : 103, |
|||
OP_ENDIF : 104, |
|||
OP_VERIFY : 105, |
|||
OP_RETURN : 106, |
|||
|
|||
// stack ops
|
|||
OP_TOALTSTACK : 107, |
|||
OP_FROMALTSTACK : 108, |
|||
OP_2DROP : 109, |
|||
OP_2DUP : 110, |
|||
OP_3DUP : 111, |
|||
OP_2OVER : 112, |
|||
OP_2ROT : 113, |
|||
OP_2SWAP : 114, |
|||
OP_IFDUP : 115, |
|||
OP_DEPTH : 116, |
|||
OP_DROP : 117, |
|||
OP_DUP : 118, |
|||
OP_NIP : 119, |
|||
OP_OVER : 120, |
|||
OP_PICK : 121, |
|||
OP_ROLL : 122, |
|||
OP_ROT : 123, |
|||
OP_SWAP : 124, |
|||
OP_TUCK : 125, |
|||
// stack ops
|
|||
OP_TOALTSTACK : 107, |
|||
OP_FROMALTSTACK : 108, |
|||
OP_2DROP : 109, |
|||
OP_2DUP : 110, |
|||
OP_3DUP : 111, |
|||
OP_2OVER : 112, |
|||
OP_2ROT : 113, |
|||
OP_2SWAP : 114, |
|||
OP_IFDUP : 115, |
|||
OP_DEPTH : 116, |
|||
OP_DROP : 117, |
|||
OP_DUP : 118, |
|||
OP_NIP : 119, |
|||
OP_OVER : 120, |
|||
OP_PICK : 121, |
|||
OP_ROLL : 122, |
|||
OP_ROT : 123, |
|||
OP_SWAP : 124, |
|||
OP_TUCK : 125, |
|||
|
|||
// splice ops
|
|||
OP_CAT : 126, |
|||
OP_SUBSTR : 127, |
|||
OP_LEFT : 128, |
|||
OP_RIGHT : 129, |
|||
OP_SIZE : 130, |
|||
// splice ops
|
|||
OP_CAT : 126, |
|||
OP_SUBSTR : 127, |
|||
OP_LEFT : 128, |
|||
OP_RIGHT : 129, |
|||
OP_SIZE : 130, |
|||
|
|||
// bit logic
|
|||
OP_INVERT : 131, |
|||
OP_AND : 132, |
|||
OP_OR : 133, |
|||
OP_XOR : 134, |
|||
OP_EQUAL : 135, |
|||
OP_EQUALVERIFY : 136, |
|||
OP_RESERVED1 : 137, |
|||
OP_RESERVED2 : 138, |
|||
// bit logic
|
|||
OP_INVERT : 131, |
|||
OP_AND : 132, |
|||
OP_OR : 133, |
|||
OP_XOR : 134, |
|||
OP_EQUAL : 135, |
|||
OP_EQUALVERIFY : 136, |
|||
OP_RESERVED1 : 137, |
|||
OP_RESERVED2 : 138, |
|||
|
|||
// numeric
|
|||
OP_1ADD : 139, |
|||
OP_1SUB : 140, |
|||
OP_2MUL : 141, |
|||
OP_2DIV : 142, |
|||
OP_NEGATE : 143, |
|||
OP_ABS : 144, |
|||
OP_NOT : 145, |
|||
OP_0NOTEQUAL : 146, |
|||
// numeric
|
|||
OP_1ADD : 139, |
|||
OP_1SUB : 140, |
|||
OP_2MUL : 141, |
|||
OP_2DIV : 142, |
|||
OP_NEGATE : 143, |
|||
OP_ABS : 144, |
|||
OP_NOT : 145, |
|||
OP_0NOTEQUAL : 146, |
|||
|
|||
OP_ADD : 147, |
|||
OP_SUB : 148, |
|||
OP_MUL : 149, |
|||
OP_DIV : 150, |
|||
OP_MOD : 151, |
|||
OP_LSHIFT : 152, |
|||
OP_RSHIFT : 153, |
|||
OP_ADD : 147, |
|||
OP_SUB : 148, |
|||
OP_MUL : 149, |
|||
OP_DIV : 150, |
|||
OP_MOD : 151, |
|||
OP_LSHIFT : 152, |
|||
OP_RSHIFT : 153, |
|||
|
|||
OP_BOOLAND : 154, |
|||
OP_BOOLOR : 155, |
|||
OP_NUMEQUAL : 156, |
|||
OP_NUMEQUALVERIFY : 157, |
|||
OP_NUMNOTEQUAL : 158, |
|||
OP_LESSTHAN : 159, |
|||
OP_GREATERTHAN : 160, |
|||
OP_LESSTHANOREQUAL : 161, |
|||
OP_GREATERTHANOREQUAL : 162, |
|||
OP_MIN : 163, |
|||
OP_MAX : 164, |
|||
OP_BOOLAND : 154, |
|||
OP_BOOLOR : 155, |
|||
OP_NUMEQUAL : 156, |
|||
OP_NUMEQUALVERIFY : 157, |
|||
OP_NUMNOTEQUAL : 158, |
|||
OP_LESSTHAN : 159, |
|||
OP_GREATERTHAN : 160, |
|||
OP_LESSTHANOREQUAL : 161, |
|||
OP_GREATERTHANOREQUAL : 162, |
|||
OP_MIN : 163, |
|||
OP_MAX : 164, |
|||
|
|||
OP_WITHIN : 165, |
|||
OP_WITHIN : 165, |
|||
|
|||
// crypto
|
|||
OP_RIPEMD160 : 166, |
|||
OP_SHA1 : 167, |
|||
OP_SHA256 : 168, |
|||
OP_HASH160 : 169, |
|||
OP_HASH256 : 170, |
|||
OP_CODESEPARATOR : 171, |
|||
OP_CHECKSIG : 172, |
|||
OP_CHECKSIGVERIFY : 173, |
|||
OP_CHECKMULTISIG : 174, |
|||
OP_CHECKMULTISIGVERIFY : 175, |
|||
// crypto
|
|||
OP_RIPEMD160 : 166, |
|||
OP_SHA1 : 167, |
|||
OP_SHA256 : 168, |
|||
OP_HASH160 : 169, |
|||
OP_HASH256 : 170, |
|||
OP_CODESEPARATOR : 171, |
|||
OP_CHECKSIG : 172, |
|||
OP_CHECKSIGVERIFY : 173, |
|||
OP_CHECKMULTISIG : 174, |
|||
OP_CHECKMULTISIGVERIFY : 175, |
|||
|
|||
// expansion
|
|||
OP_NOP1 : 176, |
|||
OP_NOP2 : 177, |
|||
OP_NOP3 : 178, |
|||
OP_NOP4 : 179, |
|||
OP_NOP5 : 180, |
|||
OP_NOP6 : 181, |
|||
OP_NOP7 : 182, |
|||
OP_NOP8 : 183, |
|||
OP_NOP9 : 184, |
|||
OP_NOP10 : 185, |
|||
// expansion
|
|||
OP_NOP1 : 176, |
|||
OP_NOP2 : 177, |
|||
OP_NOP3 : 178, |
|||
OP_NOP4 : 179, |
|||
OP_NOP5 : 180, |
|||
OP_NOP6 : 181, |
|||
OP_NOP7 : 182, |
|||
OP_NOP8 : 183, |
|||
OP_NOP9 : 184, |
|||
OP_NOP10 : 185, |
|||
|
|||
// template matching params
|
|||
OP_PUBKEYHASH : 253, |
|||
OP_PUBKEY : 254, |
|||
OP_INVALIDOPCODE : 255 |
|||
}, |
|||
reverseMap: [] |
|||
// template matching params
|
|||
OP_PUBKEYHASH : 253, |
|||
OP_PUBKEY : 254, |
|||
OP_INVALIDOPCODE : 255 |
|||
}, |
|||
reverseMap: [] |
|||
} |
|||
|
|||
for(var i in Opcode.map) { |
|||
Opcode.reverseMap[Opcode.map[i]] = i |
|||
Opcode.reverseMap[Opcode.map[i]] = i |
|||
} |
|||
|
|||
module.exports = Opcode; |
|||
module.exports = Opcode |
|||
|
@ -1,311 +1,311 @@ |
|||
var convert = require('./convert'); |
|||
var Transaction = require('./transaction').Transaction; |
|||
var convert = require('./convert') |
|||
var Transaction = require('./transaction').Transaction |
|||
var HDNode = require('./hdwallet.js') |
|||
var rng = require('secure-random'); |
|||
var rng = require('secure-random') |
|||
|
|||
var Wallet = function (seed, options) { |
|||
if (!(this instanceof Wallet)) { return new Wallet(seed, options); } |
|||
|
|||
var options = options || {} |
|||
var network = options.network || 'mainnet' |
|||
|
|||
// Stored in a closure to make accidental serialization less likely
|
|||
var masterkey = null; |
|||
var me = this; |
|||
var accountZero = null; |
|||
var internalAccount = null; |
|||
var externalAccount = null; |
|||
|
|||
// Addresses
|
|||
this.addresses = []; |
|||
this.changeAddresses = []; |
|||
|
|||
// Transaction output data
|
|||
this.outputs = {}; |
|||
|
|||
// Make a new master key
|
|||
this.newMasterKey = function(seed, network) { |
|||
if (!seed) seed= rng(32, { array: true }) |
|||
masterkey = new HDNode(seed, network); |
|||
|
|||
// HD first-level child derivation method should be private
|
|||
// See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
|
|||
accountZero = masterkey.derivePrivate(0) |
|||
externalAccount = accountZero.derive(0) |
|||
internalAccount = accountZero.derive(1) |
|||
|
|||
me.addresses = []; |
|||
me.changeAddresses = []; |
|||
|
|||
me.outputs = {}; |
|||
} |
|||
this.newMasterKey(seed, network) |
|||
|
|||
|
|||
this.generateAddress = function() { |
|||
var key = externalAccount.derive(this.addresses.length) |
|||
this.addresses.push(key.getAddress().toString()) |
|||
return this.addresses[this.addresses.length - 1] |
|||
} |
|||
|
|||
this.generateChangeAddress = function() { |
|||
var key = internalAccount.derive(this.changeAddresses.length) |
|||
this.changeAddresses.push(key.getAddress().toString()) |
|||
return this.changeAddresses[this.changeAddresses.length - 1] |
|||
if (!(this instanceof Wallet)) { return new Wallet(seed, options); } |
|||
|
|||
var options = options || {} |
|||
var network = options.network || 'mainnet' |
|||
|
|||
// Stored in a closure to make accidental serialization less likely
|
|||
var masterkey = null |
|||
var me = this |
|||
var accountZero = null |
|||
var internalAccount = null |
|||
var externalAccount = null |
|||
|
|||
// Addresses
|
|||
this.addresses = [] |
|||
this.changeAddresses = [] |
|||
|
|||
// Transaction output data
|
|||
this.outputs = {} |
|||
|
|||
// Make a new master key
|
|||
this.newMasterKey = function(seed, network) { |
|||
if (!seed) seed = rng(32, { array: true }); |
|||
masterkey = new HDNode(seed, network) |
|||
|
|||
// HD first-level child derivation method should be private
|
|||
// See https://bitcointalk.org/index.php?topic=405179.msg4415254#msg4415254
|
|||
accountZero = masterkey.derivePrivate(0) |
|||
externalAccount = accountZero.derive(0) |
|||
internalAccount = accountZero.derive(1) |
|||
|
|||
me.addresses = [] |
|||
me.changeAddresses = [] |
|||
|
|||
me.outputs = {} |
|||
} |
|||
this.newMasterKey(seed, network) |
|||
|
|||
|
|||
this.generateAddress = function() { |
|||
var key = externalAccount.derive(this.addresses.length) |
|||
this.addresses.push(key.getAddress().toString()) |
|||
return this.addresses[this.addresses.length - 1] |
|||
} |
|||
|
|||
this.generateChangeAddress = function() { |
|||
var key = internalAccount.derive(this.changeAddresses.length) |
|||
this.changeAddresses.push(key.getAddress().toString()) |
|||
return this.changeAddresses[this.changeAddresses.length - 1] |
|||
} |
|||
|
|||
this.getBalance = function() { |
|||
return this.getUnspentOutputs().reduce(function(memo, output){ |
|||
return memo + output.value |
|||
}, 0) |
|||
} |
|||
|
|||
this.getUnspentOutputs = function() { |
|||
var utxo = [] |
|||
|
|||
for(var key in this.outputs){ |
|||
var output = this.outputs[key] |
|||
if(!output.spend) utxo.push(outputToUnspentOutput(output)) |
|||
} |
|||
|
|||
this.getBalance = function() { |
|||
return this.getUnspentOutputs().reduce(function(memo, output){ |
|||
return memo + output.value |
|||
}, 0) |
|||
return utxo |
|||
} |
|||
|
|||
this.setUnspentOutputs = function(utxo) { |
|||
var outputs = {} |
|||
|
|||
utxo.forEach(function(uo){ |
|||
validateUnspentOutput(uo) |
|||
var o = unspentOutputToOutput(uo) |
|||
outputs[o.receive] = o |
|||
}) |
|||
|
|||
this.outputs = outputs |
|||
} |
|||
|
|||
this.setUnspentOutputsAsync = function(utxo, callback) { |
|||
var error = null |
|||
try { |
|||
this.setUnspentOutputs(utxo) |
|||
} catch(err) { |
|||
error = err |
|||
} finally { |
|||
process.nextTick(function(){ callback(error) }) |
|||
} |
|||
} |
|||
|
|||
this.getUnspentOutputs = function() { |
|||
var utxo = [] |
|||
function outputToUnspentOutput(output){ |
|||
var hashAndIndex = output.receive.split(":") |
|||
|
|||
for(var key in this.outputs){ |
|||
var output = this.outputs[key] |
|||
if(!output.spend) utxo.push(outputToUnspentOutput(output)) |
|||
} |
|||
|
|||
return utxo |
|||
return { |
|||
hash: hashAndIndex[0], |
|||
hashLittleEndian: convert.reverseEndian(hashAndIndex[0]), |
|||
outputIndex: parseInt(hashAndIndex[1]), |
|||
address: output.address, |
|||
value: output.value |
|||
} |
|||
|
|||
this.setUnspentOutputs = function(utxo) { |
|||
var outputs = {} |
|||
|
|||
utxo.forEach(function(uo){ |
|||
validateUnspentOutput(uo) |
|||
var o = unspentOutputToOutput(uo) |
|||
outputs[o.receive] = o |
|||
}) |
|||
|
|||
this.outputs = outputs |
|||
} |
|||
|
|||
function unspentOutputToOutput(o) { |
|||
var hash = o.hash || convert.reverseEndian(o.hashLittleEndian) |
|||
var key = hash + ":" + o.outputIndex |
|||
return { |
|||
receive: key, |
|||
address: o.address, |
|||
value: o.value |
|||
} |
|||
} |
|||
|
|||
this.setUnspentOutputsAsync = function(utxo, callback) { |
|||
var error = null |
|||
try { |
|||
this.setUnspentOutputs(utxo) |
|||
} catch(err) { |
|||
error = err |
|||
} finally { |
|||
process.nextTick(function(){ callback(error) }) |
|||
} |
|||
} |
|||
function validateUnspentOutput(uo) { |
|||
var missingField |
|||
|
|||
function outputToUnspentOutput(output){ |
|||
var hashAndIndex = output.receive.split(":") |
|||
|
|||
return { |
|||
hash: hashAndIndex[0], |
|||
hashLittleEndian: convert.reverseEndian(hashAndIndex[0]), |
|||
outputIndex: parseInt(hashAndIndex[1]), |
|||
address: output.address, |
|||
value: output.value |
|||
} |
|||
if(isNullOrUndefined(uo.hash) && isNullOrUndefined(uo.hashLittleEndian)){ |
|||
missingField = "hash(or hashLittleEndian)" |
|||
} |
|||
|
|||
function unspentOutputToOutput(o) { |
|||
var hash = o.hash || convert.reverseEndian(o.hashLittleEndian) |
|||
var key = hash + ":" + o.outputIndex |
|||
return { |
|||
receive: key, |
|||
address: o.address, |
|||
value: o.value |
|||
var requiredKeys = ['outputIndex', 'address', 'value'] |
|||
requiredKeys.forEach(function(key){ |
|||
if(isNullOrUndefined(uo[key])){ |
|||
missingField = key |
|||
} |
|||
}) |
|||
|
|||
if(missingField) { |
|||
var message = [ |
|||
'Invalid unspent output: key', field, 'is missing.', |
|||
'A valid unspent output must contain' |
|||
] |
|||
message.push(requiredKeys.join(', ')) |
|||
message.push("and hash(or hashLittleEndian)") |
|||
throw new Error(message.join(' ')) |
|||
} |
|||
|
|||
function validateUnspentOutput(uo) { |
|||
var missingField; |
|||
|
|||
if(isNullOrUndefined(uo.hash) && isNullOrUndefined(uo.hashLittleEndian)){ |
|||
missingField = "hash(or hashLittleEndian)" |
|||
} |
|||
|
|||
var requiredKeys = ['outputIndex', 'address', 'value'] |
|||
requiredKeys.forEach(function(key){ |
|||
if(isNullOrUndefined(uo[key])){ |
|||
missingField = key |
|||
} |
|||
|
|||
function isNullOrUndefined(value){ |
|||
return value == undefined |
|||
} |
|||
|
|||
this.processTx = function(tx) { |
|||
var txhash = convert.bytesToHex(tx.getHash()) |
|||
|
|||
tx.outs.forEach(function(txOut, i){ |
|||
var address = txOut.address.toString() |
|||
if (isMyAddress(address)) { |
|||
var output = txhash+':'+i |
|||
me.outputs[output] = { |
|||
receive: output, |
|||
value: txOut.value, |
|||
address: address, |
|||
} |
|||
}) |
|||
|
|||
if(missingField) { |
|||
var message = [ |
|||
'Invalid unspent output: key', field, 'is missing.', |
|||
'A valid unspent output must contain' |
|||
] |
|||
message.push(requiredKeys.join(', ')) |
|||
message.push("and hash(or hashLittleEndian)") |
|||
throw new Error(message.join(' ')) |
|||
} |
|||
} |
|||
|
|||
function isNullOrUndefined(value){ |
|||
return value == undefined |
|||
} |
|||
|
|||
this.processTx = function(tx) { |
|||
var txhash = convert.bytesToHex(tx.getHash()) |
|||
|
|||
tx.outs.forEach(function(txOut, i){ |
|||
var address = txOut.address.toString() |
|||
if (isMyAddress(address)) { |
|||
var output = txhash+':'+i |
|||
me.outputs[output] = { |
|||
receive: output, |
|||
value: txOut.value, |
|||
address: address, |
|||
} |
|||
} |
|||
}) |
|||
|
|||
tx.ins.forEach(function(txIn, i){ |
|||
var op = txIn.outpoint |
|||
var o = me.outputs[op.hash+':'+op.index] |
|||
if (o) { |
|||
o.spend = txhash+':'+i |
|||
} |
|||
}) |
|||
} |
|||
|
|||
this.createTx = function(to, value, fixedFee) { |
|||
checkDust(value) |
|||
|
|||
var tx = new Transaction() |
|||
tx.addOutput(to, value) |
|||
}) |
|||
|
|||
var utxo = getCandidateOutputs(value) |
|||
var totalInValue = 0 |
|||
for(var i=0; i<utxo.length; i++){ |
|||
var output = utxo[i] |
|||
tx.addInput(output.receive) |
|||
|
|||
totalInValue += output.value |
|||
if(totalInValue < value) continue; |
|||
tx.ins.forEach(function(txIn, i){ |
|||
var op = txIn.outpoint |
|||
var o = me.outputs[op.hash+':'+op.index] |
|||
if (o) { |
|||
o.spend = txhash+':'+i |
|||
} |
|||
}) |
|||
} |
|||
|
|||
var fee = fixedFee == undefined ? estimateFeePadChangeOutput(tx) : fixedFee |
|||
if(totalInValue < value + fee) continue; |
|||
this.createTx = function(to, value, fixedFee) { |
|||
checkDust(value) |
|||
|
|||
var change = totalInValue - value - fee |
|||
if(change > 0 && !isDust(change)) { |
|||
tx.addOutput(getChangeAddress(), change) |
|||
} |
|||
break; |
|||
} |
|||
var tx = new Transaction() |
|||
tx.addOutput(to, value) |
|||
|
|||
checkInsufficientFund(totalInValue, value, fee) |
|||
var utxo = getCandidateOutputs(value) |
|||
var totalInValue = 0 |
|||
for(var i=0; i<utxo.length; i++){ |
|||
var output = utxo[i] |
|||
tx.addInput(output.receive) |
|||
|
|||
this.sign(tx) |
|||
totalInValue += output.value |
|||
if(totalInValue < value) continue |
|||
|
|||
return tx |
|||
} |
|||
var fee = fixedFee == undefined ? estimateFeePadChangeOutput(tx) : fixedFee |
|||
if(totalInValue < value + fee) continue |
|||
|
|||
this.createTxAsync = function(to, value, fixedFee, callback){ |
|||
if(fixedFee instanceof Function) { |
|||
callback = fixedFee |
|||
fixedFee = undefined |
|||
} |
|||
var tx = null |
|||
var error = null |
|||
|
|||
try { |
|||
tx = this.createTx(to, value, fixedFee) |
|||
} catch(err) { |
|||
error = err |
|||
} finally { |
|||
process.nextTick(function(){ callback(error, tx) }) |
|||
var change = totalInValue - value - fee |
|||
if(change > 0 && !isDust(change)) { |
|||
tx.addOutput(getChangeAddress(), change) |
|||
} |
|||
break |
|||
} |
|||
|
|||
this.dustThreshold = 5430 |
|||
function isDust(amount) { |
|||
return amount <= me.dustThreshold |
|||
} |
|||
|
|||
function checkDust(value){ |
|||
if (isNullOrUndefined(value) || isDust(value)) { |
|||
throw new Error("Value must be above dust threshold") |
|||
} |
|||
} |
|||
checkInsufficientFund(totalInValue, value, fee) |
|||
|
|||
function getCandidateOutputs(value){ |
|||
var unspent = [] |
|||
for (var key in me.outputs){ |
|||
var output = me.outputs[key] |
|||
if(!output.spend) unspent.push(output) |
|||
} |
|||
this.sign(tx) |
|||
|
|||
var sortByValueDesc = unspent.sort(function(o1, o2){ |
|||
return o2.value - o1.value |
|||
}) |
|||
return tx |
|||
} |
|||
|
|||
return sortByValueDesc; |
|||
this.createTxAsync = function(to, value, fixedFee, callback){ |
|||
if(fixedFee instanceof Function) { |
|||
callback = fixedFee |
|||
fixedFee = undefined |
|||
} |
|||
|
|||
function estimateFeePadChangeOutput(tx){ |
|||
var tmpTx = tx.clone() |
|||
tmpTx.addOutput(getChangeAddress(), 0) |
|||
return tmpTx.estimateFee() |
|||
var tx = null |
|||
var error = null |
|||
|
|||
try { |
|||
tx = this.createTx(to, value, fixedFee) |
|||
} catch(err) { |
|||
error = err |
|||
} finally { |
|||
process.nextTick(function(){ callback(error, tx) }) |
|||
} |
|||
} |
|||
|
|||
function getChangeAddress() { |
|||
if(me.changeAddresses.length === 0) me.generateChangeAddress() |
|||
return me.changeAddresses[me.changeAddresses.length - 1] |
|||
} |
|||
this.dustThreshold = 5430 |
|||
function isDust(amount) { |
|||
return amount <= me.dustThreshold |
|||
} |
|||
|
|||
function checkInsufficientFund(totalInValue, value, fee) { |
|||
if(totalInValue < value + fee) { |
|||
throw new Error('Not enough money to send funds including transaction fee. Have: ' + |
|||
totalInValue + ', needed: ' + (value + fee)) |
|||
} |
|||
function checkDust(value){ |
|||
if (isNullOrUndefined(value) || isDust(value)) { |
|||
throw new Error("Value must be above dust threshold") |
|||
} |
|||
} |
|||
|
|||
this.sign = function(tx) { |
|||
tx.ins.forEach(function(inp,i) { |
|||
var output = me.outputs[inp.outpoint.hash+':'+inp.outpoint.index] |
|||
if (output) { |
|||
tx.sign(i, me.getPrivateKeyForAddress(output.address)) |
|||
} |
|||
}) |
|||
return tx; |
|||
function getCandidateOutputs(value){ |
|||
var unspent = [] |
|||
for (var key in me.outputs){ |
|||
var output = me.outputs[key] |
|||
if(!output.spend) unspent.push(output) |
|||
} |
|||
|
|||
this.getMasterKey = function() { return masterkey } |
|||
this.getAccountZero = function() { return accountZero } |
|||
this.getInternalAccount = function() { return internalAccount } |
|||
this.getExternalAccount = function() { return externalAccount } |
|||
var sortByValueDesc = unspent.sort(function(o1, o2){ |
|||
return o2.value - o1.value |
|||
}) |
|||
|
|||
this.getPrivateKey = function(index) { |
|||
return externalAccount.derive(index).priv |
|||
} |
|||
return sortByValueDesc |
|||
} |
|||
|
|||
function estimateFeePadChangeOutput(tx){ |
|||
var tmpTx = tx.clone() |
|||
tmpTx.addOutput(getChangeAddress(), 0) |
|||
return tmpTx.estimateFee() |
|||
} |
|||
|
|||
function getChangeAddress() { |
|||
if(me.changeAddresses.length === 0) me.generateChangeAddress(); |
|||
return me.changeAddresses[me.changeAddresses.length - 1] |
|||
} |
|||
|
|||
this.getInternalPrivateKey = function(index) { |
|||
return internalAccount.derive(index).priv |
|||
function checkInsufficientFund(totalInValue, value, fee) { |
|||
if(totalInValue < value + fee) { |
|||
throw new Error('Not enough money to send funds including transaction fee. Have: ' + |
|||
totalInValue + ', needed: ' + (value + fee)) |
|||
} |
|||
} |
|||
|
|||
this.getPrivateKeyForAddress = function(address) { |
|||
var index; |
|||
if((index = this.addresses.indexOf(address)) > -1) { |
|||
return this.getPrivateKey(index) |
|||
} else if((index = this.changeAddresses.indexOf(address)) > -1) { |
|||
return this.getInternalPrivateKey(index) |
|||
} else { |
|||
throw new Error('Unknown address. Make sure the address is from the keychain and has been generated.') |
|||
this.sign = function(tx) { |
|||
tx.ins.forEach(function(inp,i) { |
|||
var output = me.outputs[inp.outpoint.hash + ':' + inp.outpoint.index] |
|||
if (output) { |
|||
tx.sign(i, me.getPrivateKeyForAddress(output.address)) |
|||
} |
|||
}) |
|||
return tx |
|||
} |
|||
|
|||
this.getMasterKey = function() { return masterkey } |
|||
this.getAccountZero = function() { return accountZero } |
|||
this.getInternalAccount = function() { return internalAccount } |
|||
this.getExternalAccount = function() { return externalAccount } |
|||
|
|||
this.getPrivateKey = function(index) { |
|||
return externalAccount.derive(index).priv |
|||
} |
|||
|
|||
this.getInternalPrivateKey = function(index) { |
|||
return internalAccount.derive(index).priv |
|||
} |
|||
|
|||
this.getPrivateKeyForAddress = function(address) { |
|||
var index |
|||
if((index = this.addresses.indexOf(address)) > -1) { |
|||
return this.getPrivateKey(index) |
|||
} else if((index = this.changeAddresses.indexOf(address)) > -1) { |
|||
return this.getInternalPrivateKey(index) |
|||
} else { |
|||
throw new Error('Unknown address. Make sure the address is from the keychain and has been generated.') |
|||
} |
|||
} |
|||
|
|||
function isReceiveAddress(address){ |
|||
return me.addresses.indexOf(address) > -1 |
|||
} |
|||
function isReceiveAddress(address){ |
|||
return me.addresses.indexOf(address) > -1 |
|||
} |
|||
|
|||
function isChangeAddress(address){ |
|||
return me.changeAddresses.indexOf(address) > -1 |
|||
} |
|||
function isChangeAddress(address){ |
|||
return me.changeAddresses.indexOf(address) > -1 |
|||
} |
|||
|
|||
function isMyAddress(address) { |
|||
return isReceiveAddress(address) || isChangeAddress(address) |
|||
} |
|||
}; |
|||
function isMyAddress(address) { |
|||
return isReceiveAddress(address) || isChangeAddress(address) |
|||
} |
|||
} |
|||
|
|||
module.exports = Wallet; |
|||
module.exports = Wallet |
|||
|
@ -1,49 +1,48 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var base58 = require('../').base58; |
|||
var convert = require('../').convert; |
|||
var assert = require('assert') |
|||
var base58 = require('../').base58 |
|||
var convert = require('../').convert |
|||
|
|||
describe('base58', function() { |
|||
describe('decode', function() { |
|||
it('validates known examples', function() { |
|||
var enc = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'; |
|||
var hex = '800c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d507a5b8d'; |
|||
assert.deepEqual(base58.decode(enc), convert.hexToBytes(hex)); |
|||
}) |
|||
describe('decode', function() { |
|||
it('validates known examples', function() { |
|||
var enc = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ' |
|||
var hex = '800c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d507a5b8d' |
|||
assert.deepEqual(base58.decode(enc), convert.hexToBytes(hex)) |
|||
}) |
|||
}) |
|||
|
|||
describe('encode', function() { |
|||
it('handles known examples', function() { |
|||
var enc = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ'; |
|||
var hex = '800c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d507a5b8d'; |
|||
assert.equal(base58.encode(convert.hexToBytes(hex)), enc); |
|||
}) |
|||
describe('encode', function() { |
|||
it('handles known examples', function() { |
|||
var enc = '5HueCGU8rMjxEXxiPuD5BDku4MkFqeZyd4dZ1jvhTVqvbTLvyTJ' |
|||
var hex = '800c28fca386c7a227600b2fe50b7cae11ec86d3bf1fbe471be89827e19d72aa1d507a5b8d' |
|||
assert.equal(base58.encode(convert.hexToBytes(hex)), enc) |
|||
}) |
|||
}) |
|||
|
|||
describe('checkEncode', function() { |
|||
it('handles known examples', function() { |
|||
var input = [ |
|||
171, 210, 178, 125, 2, 16, 86, 184, 248, 88, 235, |
|||
163, 244, 160, 83, 156, 184, 186, 45, 167, 169, 164, |
|||
67, 125, 163, 89, 106, 243, 207, 193, 149, 206 |
|||
] |
|||
var vbyte = 239 |
|||
describe('checkEncode', function() { |
|||
it('handles known examples', function() { |
|||
var input = [ |
|||
171, 210, 178, 125, 2, 16, 86, 184, 248, 88, 235, |
|||
163, 244, 160, 83, 156, 184, 186, 45, 167, 169, 164, |
|||
67, 125, 163, 89, 106, 243, 207, 193, 149, 206 |
|||
] |
|||
var vbyte = 239 |
|||
|
|||
assert.equal(base58.checkEncode(input, vbyte), |
|||
'92tb9mjz6q9eKZjYvLsgk87kPrMoh7BGRumSzPeUGhmigtsfrbP'); |
|||
}) |
|||
assert.equal(base58.checkEncode(input, vbyte), |
|||
'92tb9mjz6q9eKZjYvLsgk87kPrMoh7BGRumSzPeUGhmigtsfrbP') |
|||
}) |
|||
}) |
|||
|
|||
describe('checkDecode', function() { |
|||
it('handles known examples', function() { |
|||
var input = '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa' |
|||
var expected = [ |
|||
98, 233, 7, 177, 92, 191, 39, 213, 66, 83, |
|||
153, 235, 246, 240, 251, 80, 235, 184, 143, 24 |
|||
]; |
|||
expected.version = 0 |
|||
describe('checkDecode', function() { |
|||
it('handles known examples', function() { |
|||
var input = '1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa' |
|||
var expected = [ |
|||
98, 233, 7, 177, 92, 191, 39, 213, 66, 83, |
|||
153, 235, 246, 240, 251, 80, 235, 184, 143, 24 |
|||
] |
|||
expected.version = 0 |
|||
|
|||
assert.deepEqual(base58.checkDecode(input), expected); |
|||
}) |
|||
assert.deepEqual(base58.checkDecode(input), expected) |
|||
}) |
|||
}) |
|||
}) |
|||
|
@ -1,144 +1,143 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var convert = require('../src/convert.js'); |
|||
var assert = require('assert') |
|||
var convert = require('../src/convert.js') |
|||
|
|||
describe('convert', function() { |
|||
describe('bytesToHex', function() { |
|||
it('handles example 1', function() { |
|||
assert.equal(convert.bytesToHex([0, 1, 2, 255]), '000102ff'); |
|||
}) |
|||
describe('bytesToHex', function() { |
|||
it('handles example 1', function() { |
|||
assert.equal(convert.bytesToHex([0, 1, 2, 255]), '000102ff') |
|||
}) |
|||
}) |
|||
|
|||
describe('hexToBytes', function() { |
|||
it('handles example 1', function() { |
|||
assert.deepEqual(convert.hexToBytes('000102ff'), [0, 1, 2, 255]); |
|||
}) |
|||
describe('hexToBytes', function() { |
|||
it('handles example 1', function() { |
|||
assert.deepEqual(convert.hexToBytes('000102ff'), [0, 1, 2, 255]) |
|||
}) |
|||
|
|||
it('converts from bytes to hex and back', function() { |
|||
var bytes = []; |
|||
for (var i=0 ; i<256 ; ++i) { |
|||
bytes.push(i); |
|||
} |
|||
|
|||
var hex = convert.bytesToHex(bytes); |
|||
assert.equal(hex.length, 512); |
|||
assert.deepEqual(convert.hexToBytes(hex), bytes); |
|||
}) |
|||
|
|||
it('converts from bytes to hex and back', function() { |
|||
var bytes = [] |
|||
for (var i=0 ; i<256 ; ++i) { |
|||
bytes.push(i) |
|||
} |
|||
|
|||
var hex = convert.bytesToHex(bytes) |
|||
assert.equal(hex.length, 512) |
|||
assert.deepEqual(convert.hexToBytes(hex), bytes) |
|||
}) |
|||
|
|||
describe('bytesToBase64', function() { |
|||
it('passes RFC4648 test vectors', function() { |
|||
// Test vectors from:
|
|||
// http://tools.ietf.org/html/rfc4648#page-12
|
|||
|
|||
var b64 = function(s) { |
|||
return convert.bytesToBase64(convert.stringToBytes(s)) |
|||
} |
|||
|
|||
assert.equal(b64(''), '') |
|||
assert.equal(b64('f'), 'Zg==') |
|||
assert.equal(b64('fo'), 'Zm8=') |
|||
assert.equal(b64('foo'), 'Zm9v') |
|||
assert.equal(b64('foob'), 'Zm9vYg==') |
|||
assert.equal(b64('fooba'), 'Zm9vYmE=') |
|||
assert.equal(b64('foobar'), 'Zm9vYmFy') |
|||
}) |
|||
|
|||
describe('bytesToBase64', function() { |
|||
it('passes RFC4648 test vectors', function() { |
|||
// Test vectors from:
|
|||
// http://tools.ietf.org/html/rfc4648#page-12
|
|||
|
|||
var b64 = function(s) { |
|||
return convert.bytesToBase64(convert.stringToBytes(s)) |
|||
} |
|||
|
|||
assert.equal(b64(''), '') |
|||
assert.equal(b64('f'), 'Zg==') |
|||
assert.equal(b64('fo'), 'Zm8=') |
|||
assert.equal(b64('foo'), 'Zm9v') |
|||
assert.equal(b64('foob'), 'Zm9vYg==') |
|||
assert.equal(b64('fooba'), 'Zm9vYmE=') |
|||
assert.equal(b64('foobar'), 'Zm9vYmFy') |
|||
}) |
|||
}) |
|||
|
|||
describe('byte array and word array conversions', function(){ |
|||
var bytes, wordArray; |
|||
|
|||
beforeEach(function(){ |
|||
bytes = [ |
|||
98, 233, 7, 177, 92, 191, 39, 213, 66, 83, |
|||
153, 235, 246, 240, 251, 80, 235, 184, 143, 24 |
|||
] |
|||
wordArray = { |
|||
words: [1659439025, 1556031445, 1112775147, -151979184, -340226280], |
|||
sigBytes: 20 |
|||
} |
|||
}) |
|||
|
|||
describe('bytesToWords', function() { |
|||
it('works', function() { |
|||
assert.deepEqual(convert.bytesToWordArray(bytes), wordArray) |
|||
}) |
|||
}) |
|||
|
|||
describe('bytesToWords', function() { |
|||
it('works', function() { |
|||
assert.deepEqual(convert.wordArrayToBytes(wordArray), bytes) |
|||
}) |
|||
}) |
|||
}) |
|||
|
|||
describe('byte array and word array conversions', function(){ |
|||
var bytes, wordArray |
|||
|
|||
beforeEach(function(){ |
|||
bytes = [ |
|||
98, 233, 7, 177, 92, 191, 39, 213, 66, 83, |
|||
153, 235, 246, 240, 251, 80, 235, 184, 143, 24 |
|||
] |
|||
wordArray = { |
|||
words: [1659439025, 1556031445, 1112775147, -151979184, -340226280], |
|||
sigBytes: 20 |
|||
} |
|||
}) |
|||
|
|||
describe('numToVarInt', function() { |
|||
describe('works', function() { |
|||
var data = [ |
|||
0, 128, 252, // 8-bit
|
|||
256, 512, 1024, // 16-bit
|
|||
65541, // 32-bit
|
|||
4294967299, // 64-bit
|
|||
] |
|||
var expected = [ |
|||
[0], [128], [252], // 8-bit
|
|||
[253, 0, 1], [253, 0, 2], [253, 0, 4], // 16-bit
|
|||
[254, 5, 0, 1, 0], // 32-bit
|
|||
[255, 3, 0, 0, 0, 1, 0, 0, 0] // 64-bit
|
|||
] |
|||
|
|||
for (var i = 0; i < data.length; ++i) { |
|||
var actual = convert.numToVarInt(data[i]) |
|||
assert.deepEqual(actual, expected[i]) |
|||
} |
|||
describe('bytesToWords', function() { |
|||
it('works', function() { |
|||
assert.deepEqual(convert.bytesToWordArray(bytes), wordArray) |
|||
}) |
|||
}) |
|||
|
|||
describe('varIntToNum', function() { |
|||
it('works on valid input', function() { |
|||
var data = [ |
|||
[0], [128], [252], // 8-bit
|
|||
[253, 0, 1], [253, 0, 2], [253, 0, 4], // 16-bit
|
|||
[254, 5, 0, 1, 0], // 32-bit
|
|||
[255, 3, 0, 0, 0, 1, 0, 0, 0] // 64-bit
|
|||
] |
|||
var expected = [ |
|||
0, 128, 252, // 8-bit
|
|||
256, 512, 1024, // 16-bit
|
|||
65541, // 32-bit
|
|||
4294967299, // 64-bit
|
|||
] |
|||
|
|||
for (var i = 0; i < data.length; ++i) { |
|||
var actual = convert.varIntToNum(data[i]) |
|||
assert.equal(actual.number, expected[i]) |
|||
assert.deepEqual(actual.bytes, data[i]) |
|||
} |
|||
}) |
|||
|
|||
it('uses only what is necessary', function() { |
|||
var data = [ |
|||
[0, 99], |
|||
[253, 0, 1, 99], |
|||
[254, 5, 0, 1, 0, 99], |
|||
[255, 3, 0, 0, 0, 1, 0, 0, 0, 99] |
|||
] |
|||
var expected = [0, 256, 65541, 4294967299] |
|||
|
|||
for (var i = 0; i < data.length; ++i) { |
|||
var actual = convert.varIntToNum(data[i]) |
|||
assert.equal(actual.number, expected[i]) |
|||
assert.deepEqual(actual.bytes, data[i].slice(0, -1)) |
|||
} |
|||
describe('bytesToWords', function() { |
|||
it('works', function() { |
|||
assert.deepEqual(convert.wordArrayToBytes(wordArray), bytes) |
|||
}) |
|||
}) |
|||
}) |
|||
|
|||
describe('numToVarInt', function() { |
|||
describe('works', function() { |
|||
var data = [ |
|||
0, 128, 252, // 8-bit
|
|||
256, 512, 1024, // 16-bit
|
|||
65541, // 32-bit
|
|||
4294967299, // 64-bit
|
|||
] |
|||
var expected = [ |
|||
[0], [128], [252], // 8-bit
|
|||
[253, 0, 1], [253, 0, 2], [253, 0, 4], // 16-bit
|
|||
[254, 5, 0, 1, 0], // 32-bit
|
|||
[255, 3, 0, 0, 0, 1, 0, 0, 0] // 64-bit
|
|||
] |
|||
|
|||
for (var i = 0; i < data.length; ++i) { |
|||
var actual = convert.numToVarInt(data[i]) |
|||
assert.deepEqual(actual, expected[i]) |
|||
} |
|||
}) |
|||
}) |
|||
|
|||
describe('varIntToNum', function() { |
|||
it('works on valid input', function() { |
|||
var data = [ |
|||
[0], [128], [252], // 8-bit
|
|||
[253, 0, 1], [253, 0, 2], [253, 0, 4], // 16-bit
|
|||
[254, 5, 0, 1, 0], // 32-bit
|
|||
[255, 3, 0, 0, 0, 1, 0, 0, 0] // 64-bit
|
|||
] |
|||
var expected = [ |
|||
0, 128, 252, // 8-bit
|
|||
256, 512, 1024, // 16-bit
|
|||
65541, // 32-bit
|
|||
4294967299, // 64-bit
|
|||
] |
|||
|
|||
for (var i = 0; i < data.length; ++i) { |
|||
var actual = convert.varIntToNum(data[i]) |
|||
assert.equal(actual.number, expected[i]) |
|||
assert.deepEqual(actual.bytes, data[i]) |
|||
} |
|||
}) |
|||
|
|||
describe('reverseEndian', function() { |
|||
it('works', function() { |
|||
var bigEndian = "6a4062273ac4f9ea4ffca52d9fd102b08f6c32faa0a4d1318e3a7b2e437bb9c7" |
|||
var littleEdian = "c7b97b432e7b3a8e31d1a4a0fa326c8fb002d19f2da5fc4feaf9c43a2762406a" |
|||
assert.deepEqual(convert.reverseEndian(bigEndian), littleEdian) |
|||
assert.deepEqual(convert.reverseEndian(littleEdian), bigEndian) |
|||
}) |
|||
it('uses only what is necessary', function() { |
|||
var data = [ |
|||
[0, 99], |
|||
[253, 0, 1, 99], |
|||
[254, 5, 0, 1, 0, 99], |
|||
[255, 3, 0, 0, 0, 1, 0, 0, 0, 99] |
|||
] |
|||
var expected = [0, 256, 65541, 4294967299] |
|||
|
|||
for (var i = 0; i < data.length; ++i) { |
|||
var actual = convert.varIntToNum(data[i]) |
|||
assert.equal(actual.number, expected[i]) |
|||
assert.deepEqual(actual.bytes, data[i].slice(0, -1)) |
|||
} |
|||
}) |
|||
}) |
|||
|
|||
describe('reverseEndian', function() { |
|||
it('works', function() { |
|||
var bigEndian = "6a4062273ac4f9ea4ffca52d9fd102b08f6c32faa0a4d1318e3a7b2e437bb9c7" |
|||
var littleEdian = "c7b97b432e7b3a8e31d1a4a0fa326c8fb002d19f2da5fc4feaf9c43a2762406a" |
|||
assert.deepEqual(convert.reverseEndian(bigEndian), littleEdian) |
|||
assert.deepEqual(convert.reverseEndian(littleEdian), bigEndian) |
|||
}) |
|||
}) |
|||
}) |
|||
|
@ -1,23 +1,22 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var sec = require('../src/jsbn/sec'); |
|||
var ecdsa = require('../').ecdsa; |
|||
var assert = require('assert') |
|||
var sec = require('../src/jsbn/sec') |
|||
var ecdsa = require('../').ecdsa |
|||
|
|||
var ecparams = sec('secp256k1'); |
|||
var ecparams = sec('secp256k1') |
|||
|
|||
describe('ecdsa', function() { |
|||
it('handles point multiplication', function() { |
|||
var G = ecparams.getG(); |
|||
var n = ecparams.getN(); |
|||
it('handles point multiplication', function() { |
|||
var G = ecparams.getG() |
|||
var n = ecparams.getN() |
|||
|
|||
assert.ok(G.multiply(n).isInfinity(), "Gn is infinite"); |
|||
assert.ok(G.multiply(n).isInfinity(), "Gn is infinite") |
|||
|
|||
var k = ecdsa.getBigRandom(n); |
|||
var P = G.multiply(k); |
|||
assert.ok(!P.isInfinity(), "kG is not infinite"); |
|||
assert.ok(P.isOnCurve(), "kG on curve"); |
|||
assert.ok(P.multiply(n).isInfinity(), "kGn is infinite"); |
|||
var k = ecdsa.getBigRandom(n) |
|||
var P = G.multiply(k) |
|||
assert.ok(!P.isInfinity(), "kG is not infinite") |
|||
assert.ok(P.isOnCurve(), "kG on curve") |
|||
assert.ok(P.multiply(n).isInfinity(), "kGn is infinite") |
|||
|
|||
assert.ok(P.validate(), "kG validates as a public key"); |
|||
}) |
|||
assert.ok(P.validate(), "kG validates as a public key") |
|||
}) |
|||
}) |
|||
|
@ -1,190 +1,187 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
|
|||
var ECKey = require('../src/eckey.js').ECKey; |
|||
var ECPubKey = require('../src/eckey.js').ECPubKey; |
|||
|
|||
var convert = require('../src/convert.js'); |
|||
var bytesToHex = convert.bytesToHex; |
|||
var hexToBytes = convert.hexToBytes; |
|||
var Address = require('../src/address'); |
|||
var assert = require('assert') |
|||
var ECKey = require('../src/eckey.js').ECKey |
|||
var ECPubKey = require('../src/eckey.js').ECPubKey |
|||
var convert = require('../src/convert.js') |
|||
var bytesToHex = convert.bytesToHex |
|||
var hexToBytes = convert.hexToBytes |
|||
var Address = require('../src/address') |
|||
var Network = require('../src/network') |
|||
var testnet = Network.testnet.addressVersion |
|||
|
|||
describe('ECKey', function() { |
|||
describe('constructor', function() { |
|||
it('parses hex', function() { |
|||
var priv = '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725'; |
|||
var pub = '0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b235' + |
|||
'22cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6'; |
|||
var key = new ECKey(priv); |
|||
|
|||
assert.equal(key.getPub().toHex(), pub); |
|||
assert.equal(key.compressed, false); |
|||
}) |
|||
|
|||
it('parses base64', function() { |
|||
var priv = 'VYdB+iv47y5FaUVIPdQInkgATrABeuD1lACUoM4x7tU='; |
|||
var pub = '042f43c16c08849fed20a35bb7b1947bbf0923c52d613ee13b5c665a1e10d24b2' + |
|||
'8be909a70f5f87c1adb79fbcd1b3f17d20aa91c04fc355112dba2ce9b1cbf013b'; |
|||
var key = new ECKey(priv); |
|||
|
|||
assert.equal(key.getPub().toHex(), pub); |
|||
assert.equal(key.compressed, false); |
|||
}) |
|||
|
|||
it('parses WIF', function() { |
|||
var priv = '5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh'; |
|||
var pub = '044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0' + |
|||
'f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1'; |
|||
var addr = '1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a'; |
|||
var key = new ECKey(priv); |
|||
|
|||
assert.equal(key.compressed, false); |
|||
assert.equal(key.getPub().toHex(), pub); |
|||
assert.equal(key.getAddress().toString(), addr); |
|||
}) |
|||
|
|||
it('parses compressed WIF', function() { |
|||
var priv = 'KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp'; |
|||
var pub = '034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa' |
|||
var addr = '1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9'; |
|||
var key = new ECKey(priv); |
|||
|
|||
assert.equal(key.compressed, true); |
|||
assert.equal(key.getPub().toHex(), pub); |
|||
assert.equal(key.getAddress().toString(), addr); |
|||
}) |
|||
|
|||
it('alternative constructor syntax', function() { |
|||
var priv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458'; |
|||
var pub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199' + |
|||
'283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566'; |
|||
var key = ECKey(priv, false); |
|||
|
|||
assert.equal(key.getPub().toHex(), pub); |
|||
assert.equal(key.compressed, false); |
|||
assert.equal(key.toHex(), priv); |
|||
}) |
|||
describe('constructor', function() { |
|||
it('parses hex', function() { |
|||
var priv = '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725' |
|||
var pub = '0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b235' + |
|||
'22cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6' |
|||
var key = new ECKey(priv) |
|||
|
|||
assert.equal(key.getPub().toHex(), pub) |
|||
assert.equal(key.compressed, false) |
|||
}) |
|||
|
|||
it('parses base64', function() { |
|||
var priv = 'VYdB+iv47y5FaUVIPdQInkgATrABeuD1lACUoM4x7tU=' |
|||
var pub = '042f43c16c08849fed20a35bb7b1947bbf0923c52d613ee13b5c665a1e10d24b2' + |
|||
'8be909a70f5f87c1adb79fbcd1b3f17d20aa91c04fc355112dba2ce9b1cbf013b' |
|||
var key = new ECKey(priv) |
|||
|
|||
assert.equal(key.getPub().toHex(), pub) |
|||
assert.equal(key.compressed, false) |
|||
}) |
|||
|
|||
describe('toAddress', function() { |
|||
var privkeys = [ |
|||
'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458', |
|||
'1111111111111111111111111111111111111111111111111111111111111111', |
|||
'18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725' |
|||
]; |
|||
|
|||
// compressed pubkeys
|
|||
var cpubkeys = [ |
|||
'024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992', |
|||
'034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa', |
|||
'0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352' |
|||
]; |
|||
|
|||
var pubkeys = cpubkeys.map(function(x) { |
|||
return ECPubKey(x).toHex(false) |
|||
}); |
|||
|
|||
it('mainnet', function() { |
|||
var addresses = [ |
|||
'19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui', |
|||
'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a', |
|||
'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM' |
|||
]; |
|||
var compressedAddresses = [ |
|||
'1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q', |
|||
'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9', |
|||
'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs', |
|||
]; |
|||
|
|||
for (var i = 0; i < addresses.length; ++i) { |
|||
var priv = new ECKey(privkeys[i], false); |
|||
var pub = new ECPubKey(pubkeys[i], false); |
|||
var cpub = new ECPubKey(cpubkeys[i], true); |
|||
|
|||
var addr = addresses[i]; |
|||
var caddr = compressedAddresses[i]; |
|||
|
|||
assert.equal(priv.getAddress().toString(), addr); |
|||
assert.equal(pub.getAddress().toString(), addr); |
|||
assert.equal(cpub.getAddress().toString(), caddr); |
|||
} |
|||
}) |
|||
|
|||
it('testnet', function() { |
|||
var addresses = [ |
|||
'19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui', |
|||
'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a', |
|||
'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM' |
|||
]; |
|||
var compressedAddresses = [ |
|||
'1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q', |
|||
'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9', |
|||
'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs', |
|||
]; |
|||
|
|||
for (var i = 0; i < addresses.length; ++i) { |
|||
var priv = new ECKey(privkeys[i], false); |
|||
var pub = new ECPubKey(pubkeys[i], false); |
|||
var cpub = new ECPubKey(cpubkeys[i], true); |
|||
|
|||
var addr = addresses[i]; |
|||
var caddr = compressedAddresses[i]; |
|||
|
|||
assert.equal(priv.getAddress().toString(), addr); |
|||
assert.equal(pub.getAddress().toString(), addr); |
|||
assert.equal(cpub.getAddress().toString(), caddr); |
|||
} |
|||
}) |
|||
}); |
|||
|
|||
describe('signing', function() { |
|||
var hpriv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458' |
|||
var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992' |
|||
var message = 'Vires in numeris' |
|||
|
|||
it('should verify against the private key', function() { |
|||
var priv = new ECKey(hpriv) |
|||
var signature = priv.sign(message) |
|||
|
|||
assert(priv.verify(message, signature)) |
|||
}) |
|||
|
|||
it('should verify against the public key', function() { |
|||
var priv = new ECKey(hpriv) |
|||
var pub = new ECPubKey(hcpub, true) |
|||
var signature = priv.sign(message) |
|||
|
|||
assert(pub.verify(message, signature)) |
|||
}) |
|||
|
|||
it('should not verify against the wrong private key', function() { |
|||
var priv1 = new ECKey(hpriv) |
|||
var priv2 = new ECKey('1111111111111111111111111111111111111111111111111111111111111111') |
|||
|
|||
var signature = priv1.sign(message) |
|||
|
|||
assert(!priv2.verify(message, signature)) |
|||
}) |
|||
it('parses WIF', function() { |
|||
var priv = '5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh' |
|||
var pub = '044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0' + |
|||
'f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1' |
|||
var addr = '1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a' |
|||
var key = new ECKey(priv) |
|||
|
|||
assert.equal(key.compressed, false) |
|||
assert.equal(key.getPub().toHex(), pub) |
|||
assert.equal(key.getAddress().toString(), addr) |
|||
}) |
|||
|
|||
describe('output of ECPubKey', function() { |
|||
var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992' |
|||
var hpub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566' |
|||
it('parses compressed WIF', function() { |
|||
var priv = 'KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp' |
|||
var pub = '034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa' |
|||
var addr = '1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9' |
|||
var key = new ECKey(priv) |
|||
|
|||
assert.equal(key.compressed, true) |
|||
assert.equal(key.getPub().toHex(), pub) |
|||
assert.equal(key.getAddress().toString(), addr) |
|||
}) |
|||
|
|||
it('using toHex should support compression', function() { |
|||
var pub = new ECPubKey(hpub) |
|||
it('alternative constructor syntax', function() { |
|||
var priv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458' |
|||
var pub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199' + |
|||
'283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566' |
|||
var key = ECKey(priv, false) |
|||
|
|||
assert.equal(key.getPub().toHex(), pub) |
|||
assert.equal(key.compressed, false) |
|||
assert.equal(key.toHex(), priv) |
|||
}) |
|||
}) |
|||
|
|||
describe('toAddress', function() { |
|||
var privkeys = [ |
|||
'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458', |
|||
'1111111111111111111111111111111111111111111111111111111111111111', |
|||
'18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725' |
|||
] |
|||
|
|||
// compressed pubkeys
|
|||
var cpubkeys = [ |
|||
'024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992', |
|||
'034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa', |
|||
'0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352' |
|||
] |
|||
|
|||
var pubkeys = cpubkeys.map(function(x) { |
|||
return ECPubKey(x).toHex(false) |
|||
}) |
|||
|
|||
it('mainnet', function() { |
|||
var addresses = [ |
|||
'19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui', |
|||
'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a', |
|||
'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM' |
|||
] |
|||
var compressedAddresses = [ |
|||
'1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q', |
|||
'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9', |
|||
'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs', |
|||
] |
|||
|
|||
for (var i = 0; i < addresses.length; ++i) { |
|||
var priv = new ECKey(privkeys[i], false) |
|||
var pub = new ECPubKey(pubkeys[i], false) |
|||
var cpub = new ECPubKey(cpubkeys[i], true) |
|||
|
|||
var addr = addresses[i] |
|||
var caddr = compressedAddresses[i] |
|||
|
|||
assert.equal(priv.getAddress().toString(), addr) |
|||
assert.equal(pub.getAddress().toString(), addr) |
|||
assert.equal(cpub.getAddress().toString(), caddr) |
|||
} |
|||
}) |
|||
|
|||
it('testnet', function() { |
|||
var addresses = [ |
|||
'19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui', |
|||
'1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a', |
|||
'16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM' |
|||
] |
|||
var compressedAddresses = [ |
|||
'1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q', |
|||
'1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9', |
|||
'1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs', |
|||
] |
|||
|
|||
for (var i = 0; i < addresses.length; ++i) { |
|||
var priv = new ECKey(privkeys[i], false) |
|||
var pub = new ECPubKey(pubkeys[i], false) |
|||
var cpub = new ECPubKey(cpubkeys[i], true) |
|||
|
|||
var addr = addresses[i] |
|||
var caddr = compressedAddresses[i] |
|||
|
|||
assert.equal(priv.getAddress().toString(), addr) |
|||
assert.equal(pub.getAddress().toString(), addr) |
|||
assert.equal(cpub.getAddress().toString(), caddr) |
|||
} |
|||
}) |
|||
}) |
|||
|
|||
assert.equal(pub.toHex(true), hcpub) |
|||
assert.equal(pub.toHex(false), hpub) |
|||
}) |
|||
describe('signing', function() { |
|||
var hpriv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458' |
|||
var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992' |
|||
var message = 'Vires in numeris' |
|||
|
|||
it('should verify against the private key', function() { |
|||
var priv = new ECKey(hpriv) |
|||
var signature = priv.sign(message) |
|||
|
|||
assert(priv.verify(message, signature)) |
|||
}) |
|||
|
|||
it('should verify against the public key', function() { |
|||
var priv = new ECKey(hpriv) |
|||
var pub = new ECPubKey(hcpub, true) |
|||
var signature = priv.sign(message) |
|||
|
|||
assert(pub.verify(message, signature)) |
|||
}) |
|||
|
|||
it('should not verify against the wrong private key', function() { |
|||
var priv1 = new ECKey(hpriv) |
|||
var priv2 = new ECKey('1111111111111111111111111111111111111111111111111111111111111111') |
|||
|
|||
var signature = priv1.sign(message) |
|||
|
|||
assert(!priv2.verify(message, signature)) |
|||
}) |
|||
}) |
|||
|
|||
describe('output of ECPubKey', function() { |
|||
var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992' |
|||
var hpub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566' |
|||
|
|||
it('using toHex should support compression', function() { |
|||
var pub = new ECPubKey(hpub) |
|||
|
|||
assert.equal(pub.toHex(true), hcpub) |
|||
assert.equal(pub.toHex(false), hpub) |
|||
}) |
|||
|
|||
it('using toBytes should support compression', function() { |
|||
var pub = new ECPubKey(hpub) |
|||
it('using toBytes should support compression', function() { |
|||
var pub = new ECPubKey(hpub) |
|||
|
|||
assert.equal(bytesToHex(pub.toBytes(true)), hcpub) |
|||
assert.equal(bytesToHex(pub.toBytes(false)), hpub) |
|||
}) |
|||
assert.equal(bytesToHex(pub.toBytes(true)), hcpub) |
|||
assert.equal(bytesToHex(pub.toBytes(false)), hpub) |
|||
}) |
|||
}) |
|||
}) |
|||
|
@ -1,37 +1,36 @@ |
|||
/* global describe, it */ |
|||
var assert = require('assert'); |
|||
var assert = require('assert') |
|||
var BigInteger = require('../src/jsbn/jsbn.js') |
|||
var bytesToHex = require('../src/convert.js').bytesToHex; |
|||
var secureRandom = require('secure-random'); |
|||
var bytesToHex = require('../src/convert.js').bytesToHex |
|||
var secureRandom = require('secure-random') |
|||
|
|||
describe('BigInteger', function() { |
|||
describe('toByteArraySigned', function() { |
|||
it('handles examples', function() { |
|||
function hex(num) { |
|||
var bytes = BigInteger.valueOf(num).toByteArraySigned(); |
|||
var h = bytesToHex(bytes); |
|||
return '0x' + h; |
|||
} |
|||
describe('toByteArraySigned', function() { |
|||
it('handles examples', function() { |
|||
function hex(num) { |
|||
var bytes = BigInteger.valueOf(num).toByteArraySigned() |
|||
var h = bytesToHex(bytes) |
|||
return '0x' + h |
|||
} |
|||
|
|||
assert.equal(hex( 0), '0x'); |
|||
assert.equal(hex( 1), '0x01'); |
|||
assert.equal(hex(-1), '0x81'); |
|||
assert.equal(hex( 127), '0x7f'); |
|||
assert.equal(hex(-127), '0xff'); |
|||
assert.equal(hex( 255), '0x00ff'); |
|||
assert.equal(hex(-255), '0x80ff'); |
|||
assert.equal(hex( 16300), '0x3fac'); |
|||
assert.equal(hex(-16300), '0xbfac'); |
|||
assert.equal(hex( 62300), '0x00f35c'); |
|||
assert.equal(hex(-62300), '0x80f35c'); |
|||
}) |
|||
assert.equal(hex( 0), '0x') |
|||
assert.equal(hex( 1), '0x01') |
|||
assert.equal(hex(-1), '0x81') |
|||
assert.equal(hex( 127), '0x7f') |
|||
assert.equal(hex(-127), '0xff') |
|||
assert.equal(hex( 255), '0x00ff') |
|||
assert.equal(hex(-255), '0x80ff') |
|||
assert.equal(hex( 16300), '0x3fac') |
|||
assert.equal(hex(-16300), '0xbfac') |
|||
assert.equal(hex( 62300), '0x00f35c') |
|||
assert.equal(hex(-62300), '0x80f35c') |
|||
}) |
|||
}) |
|||
|
|||
describe('with RNG passed into constructor as the 2nd argument', function(){ |
|||
it('returns a BigInteger with the limit of the specified length', function(){ |
|||
var bitLength = 256 |
|||
var i = new BigInteger(bitLength, secureRandom) |
|||
assert(i.bitLength() <= 256) |
|||
}) |
|||
describe('with RNG passed into constructor as the 2nd argument', function(){ |
|||
it('returns a BigInteger with the limit of the specified length', function(){ |
|||
var bitLength = 256 |
|||
var i = new BigInteger(bitLength, secureRandom) |
|||
assert(i.bitLength() <= 256) |
|||
}) |
|||
}) |
|||
}) |
|||
|
@ -1,65 +1,65 @@ |
|||
var assert = require('assert'); |
|||
var bitcoinjs = require('../'); |
|||
var sec = require('../src/jsbn/sec'); |
|||
var BigInteger = require('../src/jsbn/jsbn.js'); |
|||
var SHA256 = require('crypto-js/sha256'); |
|||
var rng = require('secure-random'); |
|||
var ecparams = sec('secp256k1'); |
|||
var ECPointFp = bitcoinjs.ECPointFp; |
|||
var convert = require('../src/convert'); |
|||
var assert = require('assert') |
|||
var bitcoinjs = require('../') |
|||
var sec = require('../src/jsbn/sec') |
|||
var BigInteger = require('../src/jsbn/jsbn.js') |
|||
var SHA256 = require('crypto-js/sha256') |
|||
var rng = require('secure-random') |
|||
var ecparams = sec('secp256k1') |
|||
var ECPointFp = bitcoinjs.ECPointFp |
|||
var convert = require('../src/convert') |
|||
|
|||
function sha256FromBytesToBytes(message){ |
|||
return convert.wordArrayToBytes(SHA256(convert.bytesToWordArray(message))) |
|||
} |
|||
|
|||
it('Keys & Key Management', function () { |
|||
var p1 = bitcoinjs.Key().getPub().toBytes() |
|||
assert.equal(p1.length, 65) |
|||
var p1 = bitcoinjs.Key().getPub().toBytes() |
|||
assert.equal(p1.length, 65) |
|||
|
|||
var p1_q = ECPointFp.decodeFrom(ecparams.getCurve(), p1); |
|||
assert.ok(p1_q); |
|||
assert.ok(p1_q.validate()); |
|||
var p1_q = ECPointFp.decodeFrom(ecparams.getCurve(), p1) |
|||
assert.ok(p1_q) |
|||
assert.ok(p1_q.validate()) |
|||
|
|||
var p2 = bitcoinjs.convert.hexToBytes( |
|||
'0486f356006a38b847bedec1bf47013776925d939d5a35a97a4d1263e550c7f1a' + |
|||
'b5aba44ab74d22892097a0e851addf07ba97e33416df5affaceeb35d5607cd23c'); |
|||
var p2 = bitcoinjs.convert.hexToBytes( |
|||
'0486f356006a38b847bedec1bf47013776925d939d5a35a97a4d1263e550c7f1a' + |
|||
'b5aba44ab74d22892097a0e851addf07ba97e33416df5affaceeb35d5607cd23c') |
|||
|
|||
var p2_q = ECPointFp.decodeFrom(ecparams.getCurve(), p2); |
|||
assert.ok(p2_q); |
|||
assert.ok(p2_q.validate()); |
|||
}); |
|||
var p2_q = ECPointFp.decodeFrom(ecparams.getCurve(), p2) |
|||
assert.ok(p2_q) |
|||
assert.ok(p2_q.validate()) |
|||
}) |
|||
|
|||
it('Signing and Verifying', function () { |
|||
var s1 = bitcoinjs.Key(); |
|||
var sig_a = s1.sign(BigInteger.ZERO); |
|||
assert.ok(sig_a, 'Sign null'); |
|||
var s1 = bitcoinjs.Key() |
|||
var sig_a = s1.sign(BigInteger.ZERO) |
|||
assert.ok(sig_a, 'Sign null') |
|||
|
|||
assert.ok(s1.verify(BigInteger.ZERO, sig_a)); |
|||
assert.ok(s1.verify(BigInteger.ZERO, sig_a)) |
|||
|
|||
var message = new BigInteger(1024, rng).toByteArrayUnsigned(); |
|||
var hash = sha256FromBytesToBytes(message); |
|||
var sig_b = s1.sign(hash); |
|||
assert.ok(sig_b, 'Sign random string'); |
|||
assert.ok(s1.verify(hash, sig_b)); |
|||
var message = new BigInteger(1024, rng).toByteArrayUnsigned() |
|||
var hash = sha256FromBytesToBytes(message) |
|||
var sig_b = s1.sign(hash) |
|||
assert.ok(sig_b, 'Sign random string') |
|||
assert.ok(s1.verify(hash, sig_b)) |
|||
|
|||
var message2 = bitcoinjs.convert.hexToBytes( |
|||
'12dce2c169986b3346827ffb2305cf393984627f5f9722a1b1368e933c8d' + |
|||
'd296653fbe5d7ac031c4962ad0eb1c4298c3b91d244e1116b4a76a130c13' + |
|||
'1e7aec7fa70184a71a2e66797052831511b93c6e8d72ae58a1980eaacb66' + |
|||
'8a33f50d7cefb96a5dab897b5efcb99cbafb0d777cb83fc9b2115b69c0fa' + |
|||
'3d82507b932b84e4'); |
|||
var message2 = bitcoinjs.convert.hexToBytes( |
|||
'12dce2c169986b3346827ffb2305cf393984627f5f9722a1b1368e933c8d' + |
|||
'd296653fbe5d7ac031c4962ad0eb1c4298c3b91d244e1116b4a76a130c13' + |
|||
'1e7aec7fa70184a71a2e66797052831511b93c6e8d72ae58a1980eaacb66' + |
|||
'8a33f50d7cefb96a5dab897b5efcb99cbafb0d777cb83fc9b2115b69c0fa' + |
|||
'3d82507b932b84e4') |
|||
|
|||
var hash2 = sha256FromBytesToBytes(message2); |
|||
var hash2 = sha256FromBytesToBytes(message2) |
|||
|
|||
var sig_c = bitcoinjs.convert.hexToBytes( |
|||
'3044022038d9b8dd5c9fbf330565c1f51d72a59ba869aeb2c2001be959d3' + |
|||
'79e861ec71960220a73945f32cf90d03127d2c3410d16cee120fa1a4b4c3' + |
|||
'f273ab082801a95506c4'); |
|||
var sig_c = bitcoinjs.convert.hexToBytes( |
|||
'3044022038d9b8dd5c9fbf330565c1f51d72a59ba869aeb2c2001be959d3' + |
|||
'79e861ec71960220a73945f32cf90d03127d2c3410d16cee120fa1a4b4c3' + |
|||
'f273ab082801a95506c4') |
|||
|
|||
var s2 = bitcoinjs.convert.hexToBytes( |
|||
'045a1594316e433fb91f35ef4874610d22177c3f1a1060f6c1e70a609d51' + |
|||
'b20be5795cd2a5eae0d6b872ba42db95e9afaeea3fbb89e98099575b6828' + |
|||
'609a978528'); |
|||
var s2 = bitcoinjs.convert.hexToBytes( |
|||
'045a1594316e433fb91f35ef4874610d22177c3f1a1060f6c1e70a609d51' + |
|||
'b20be5795cd2a5eae0d6b872ba42db95e9afaeea3fbb89e98099575b6828' + |
|||
'609a978528') |
|||
|
|||
assert.ok(bitcoinjs.ecdsa.verify(hash2, sig_c, s2), 'Verify constant signature'); |
|||
}); |
|||
assert.ok(bitcoinjs.ecdsa.verify(hash2, sig_c, s2), 'Verify constant signature') |
|||
}) |
|||
|
Loading…
Reference in new issue