Browse Source

Merge pull request #394 from ryanxcharles/feature/beautify

ran js-beautify on all bitcore source
patch-2
Manuel Aráoz 11 years ago
parent
commit
12e7101ffa
  1. 47
      bitcore.js
  2. 2
      browser/build.js
  3. 20
      const.js
  4. 1
      examples/Armory.js
  5. 11
      examples/ConnectionTor.js
  6. 47
      examples/CreateAndSignTx-Multisig.js
  7. 59
      examples/CreateAndSignTx-PayToPubkeyHash.js
  8. 63
      examples/CreateAndSignTx-PayToScriptHash.js
  9. 24
      examples/CreateKey.js
  10. 40
      examples/CreateScript.js
  11. 8
      examples/ECIES.js
  12. 2
      examples/HierarchicalKey.js
  13. 6
      examples/PeerDiscovery.js
  14. 2
      examples/SendTx.js
  15. 28
      examples/SimpleP2Pmonitor.js
  16. 6
      examples/VanityAddress.js
  17. 17
      lib/Address.js
  18. 28
      lib/Armory.js
  19. 15
      lib/BIP39.js
  20. 2
      lib/BIP39WordlistEn.js
  21. 27
      lib/Base58.js
  22. 179
      lib/Block.js
  23. 25
      lib/Bloom.js
  24. 470
      lib/Connection.js
  25. 15
      lib/Curve.js
  26. 5
      lib/Deserialize.js
  27. 26
      lib/Electrum.js
  28. 106
      lib/HierarchicalKey.js
  29. 3
      lib/Message.js
  30. 244
      lib/Opcode.js
  31. 18
      lib/Peer.js
  32. 81
      lib/PeerManager.js
  33. 16
      lib/Point.js
  34. 43
      lib/PrivateKey.js
  35. 72
      lib/RpcClient.js
  36. 24
      lib/SIN.js
  37. 6
      lib/SINKey.js
  38. 60
      lib/Script.js
  39. 2
      lib/ScriptInterpreter.js
  40. 117
      lib/Sign.js
  41. 16
      lib/Transaction.js
  42. 397
      lib/TransactionBuilder.js
  43. 39
      lib/Wallet.js
  44. 2
      lib/WalletKey.js
  45. 2620
      lib/browser/Bignum.js
  46. 22
      lib/browser/ECIES.js
  47. 26
      lib/browser/Key.js
  48. 58
      lib/browser/Point.js
  49. 15
      lib/common/ECIES.js
  50. 3
      lib/common/SecureRandom.js
  51. 4
      networks.js
  52. 73
      util/BinaryParser.js
  53. 14
      util/EncFile.js
  54. 25
      util/EncodedData.js
  55. 20
      util/VersionedData.js
  56. 9
      util/error.js
  57. 2
      util/index.js
  58. 23
      util/log.js
  59. 5
      util/time.js
  60. 8
      util/util.js

47
bitcore.js

@ -7,19 +7,27 @@ Instead, we can set the 'get' property of each class to only require them when
they are accessed, saving memory if they are not used in a given project.
*/
var requireWhenAccessed = function(name, file) {
Object.defineProperty(module.exports, name, {get: function() {return require(file)}});
Object.defineProperty(module.exports, name, {
get: function() {
return require(file)
}
});
};
requireWhenAccessed('Bignum', 'bignum');
Object.defineProperty(module.exports, 'bignum', {get: function() {
console.log('bignum (with a lower-case "b") is deprecated. Use bitcore.Bignum (capital "B") instead.');
return require('bignum');
}});
Object.defineProperty(module.exports, 'bignum', {
get: function() {
console.log('bignum (with a lower-case "b") is deprecated. Use bitcore.Bignum (capital "B") instead.');
return require('bignum');
}
});
requireWhenAccessed('Base58', './lib/Base58');
Object.defineProperty(module.exports, 'base58', {get: function() {
console.log('base58 (with a lower-case "b") is deprecated. Use bitcore.Base58 (capital "B") instead.');
return require('./lib/Base58');
}});
Object.defineProperty(module.exports, 'base58', {
get: function() {
console.log('base58 (with a lower-case "b") is deprecated. Use bitcore.Base58 (capital "B") instead.');
return require('./lib/Base58');
}
});
requireWhenAccessed('bufferput', 'bufferput');
requireWhenAccessed('buffertools', 'buffertools');
requireWhenAccessed('Buffers.monkey', './patches/Buffers.monkey');
@ -38,10 +46,12 @@ requireWhenAccessed('VersionedData', './util/VersionedData');
requireWhenAccessed('BinaryParser', './util/BinaryParser');
requireWhenAccessed('Address', './lib/Address');
requireWhenAccessed('HierarchicalKey', './lib/HierarchicalKey');
Object.defineProperty(module.exports, 'BIP32', {get: function() {
console.log('BIP32 is deprecated. Use bitcore.HierarchicalKey instead.');
return require('./lib/HierarchicalKey');
}});
Object.defineProperty(module.exports, 'BIP32', {
get: function() {
console.log('BIP32 is deprecated. Use bitcore.HierarchicalKey instead.');
return require('./lib/HierarchicalKey');
}
});
requireWhenAccessed('BIP39', './lib/BIP39');
requireWhenAccessed('BIP39WordlistEn', './lib/BIP39WordlistEn');
requireWhenAccessed('Point', './lib/Point');
@ -55,10 +65,12 @@ requireWhenAccessed('Block', './lib/Block');
requireWhenAccessed('ScriptInterpreter', './lib/ScriptInterpreter');
requireWhenAccessed('Bloom', './lib/Bloom');
requireWhenAccessed('Key', './lib/Key');
Object.defineProperty(module.exports, 'KeyModule', {get: function() {
console.log('KeyModule is deprecated.');
return require('bindings')('KeyModule');
}});
Object.defineProperty(module.exports, 'KeyModule', {
get: function() {
console.log('KeyModule is deprecated.');
return require('bindings')('KeyModule');
}
});
requireWhenAccessed('SINKey', './lib/SINKey');
requireWhenAccessed('SIN', './lib/SIN');
requireWhenAccessed('PrivateKey', './lib/PrivateKey');
@ -70,4 +82,3 @@ requireWhenAccessed('Message', './lib/Message');
requireWhenAccessed('Electrum', './lib/Electrum');
requireWhenAccessed('Armory', './lib/Armory');
module.exports.Buffer = Buffer;

2
browser/build.js

@ -11,7 +11,7 @@ var puts = function(error, stdout, stderr) {
//sys.puts(stderr);
};
var pack = function (params) {
var pack = function(params) {
var file = require.resolve('soop');
var dir = file.substr(0, file.length - String('soop.js').length);
var preludePath = dir + 'example/custom_prelude.js';

20
const.js

@ -1,18 +1,20 @@
MSG = {
TX: 1,
BLOCK: 2,
TX: 1,
BLOCK: 2,
FILTERED_BLOCK: 3,
};
MSG.to_str = function(t) {
switch(t) {
case MSG.TX: return 'transaction';
case MSG.BLOCK: return 'block';
case MSG.FILTERED_BLOCK: return 'filtered block';
default: return 'unknown';
switch (t) {
case MSG.TX:
return 'transaction';
case MSG.BLOCK:
return 'block';
case MSG.FILTERED_BLOCK:
return 'filtered block';
default:
return 'unknown';
}
}
exports.MSG = MSG;

1
examples/Armory.js

@ -63,4 +63,3 @@ for (var i = 0; i < 5; i++) {
console.log(Address.fromPubKey(b.pubkey).as('base58'));
b = b.next();
}

11
examples/ConnectionTor.js

@ -1,6 +1,6 @@
var Peer = require('../lib/Peer');
var Peer = require('../lib/Peer');
var Connection = require('../lib/Connection');
var dns = require('dns');
var dns = require('dns');
// get a peer from dns seed
dns.resolve('dnsseed.bluematt.me', function(err, seeds) {
@ -9,12 +9,15 @@ dns.resolve('dnsseed.bluematt.me', function(err, seeds) {
//Custom peer:
//var peer = new Peer('180.153.139.246', '8888');
// create a connection without an existing socket
// but specify a socks5 proxy to create a socket
// that's bound to that proxy in it's place
var connection = new Connection(null, peer, {
proxy: { host: '127.0.0.1', port: 9050 }
proxy: {
host: '127.0.0.1',
port: 9050
}
});
connection.open();

47
examples/CreateAndSignTx-Multisig.js

@ -1,10 +1,11 @@
var run = function() {
bitcore = typeof (bitcore) === 'undefined' ? require('../bitcore') : bitcore;
bitcore = typeof(bitcore) === 'undefined' ? require('../bitcore') : bitcore;
var networks = require('../networks');
var WalletKey = bitcore.WalletKey;
var Builder = bitcore.TransactionBuilder;
var opts = {network: networks.testnet};
var opts = {
network: networks.testnet
};
console.log('## Network: ' + opts.network.name);
@ -13,8 +14,7 @@ var run = function() {
input.priv = "cS62Ej4SobZnpFQYN1PEEBr2KWf5sgRYYnELtumcG6WVCfxno39V";
// Complete with the corresponding UTXO you want to use
var utxos = [
{
var utxos = [{
address: input.addr,
txid: "39c71ebda371f75f4b854a720eaf9898b237facf3c2b101b58cd4383a44a6adc",
vout: 1,
@ -22,10 +22,9 @@ var run = function() {
scriptPubKey: "76a914e867aad8bd361f57c50adc37a0c018692b5b0c9a88ac",
amount: 0.4296,
confirmations: 2
}
];
}];
var privs = [
var privs = [
"cP6JBHuQf7yqeqtdKRd22ibF3VehDv7G6BdzxSNABgrv3jFJUGoN",
"cQfRwF7XLSM5xGUpF8PZvob2MZyULvZPA2j5cat2RKDJrja7FtCZ",
"cUkYub4jtFVYymHh38yMMW36nJB4pXG5Pzd5QjResq79kAndkJcg",
@ -36,18 +35,24 @@ var run = function() {
var pubkeys = []
privs.forEach(function(p) {
var wk = new WalletKey(opts);
wk.fromObj({priv: p});
wk.fromObj({
priv: p
});
pubkeys.push(bitcore.buffertools.toHex(wk.privKey.public));
});
var outs = [{nreq:3, pubkeys:pubkeys, amount:0.05}];
var outs = [{
nreq: 3,
pubkeys: pubkeys,
amount: 0.05
}];
var tx = new Builder(opts)
.setUnspent(utxos)
.setOutputs(outs)
.sign([input.priv])
.build();
var txHex = tx.serialize().toString('hex');
var txHex = tx.serialize().toString('hex');
console.log('1) SEND TO MULSISIG TX: ', txHex);
console.log('[this example originally generated TXID: e4bc22d8c519d3cf848d710619f8480be56176a4a6548dfbe865ab3886b578b5 on testnet]\n\n\thttp://test.bitcore.io/tx/e4bc22d8c519d3cf848d710619f8480be56176a4a6548dfbe865ab3886b578b5\n\n');
@ -59,31 +64,32 @@ var run = function() {
*
* REDDEEM TX
*/
var utxos2 = [
{
var utxos2 = [{
address: input.addr,
txid: "e4bc22d8c519d3cf848d710619f8480be56176a4a6548dfbe865ab3886b578b5",
vout: 0,
ts: 1396288753,
scriptPubKey: scriptPubKey,
scriptPubKey: scriptPubKey,
amount: 0.05,
confirmations: 2
}
];
}];
outs = [{address:input.addr, amount:0.04}];
outs = [{
address: input.addr,
amount: 0.04
}];
var b = new Builder(opts)
.setUnspent(utxos2)
.setOutputs(outs)
.sign(privs);
tx= b.build();
tx = b.build();
var txHex = tx.serialize().toString('hex');
var txHex = tx.serialize().toString('hex');
console.log('2) REDEEM SCRIPT: ', txHex);
console.log('=> Is signed status:', b.isFullySigned(), tx.countInputMissingSignatures(0) );
console.log('=> Is signed status:', b.isFullySigned(), tx.countInputMissingSignatures(0));
console.log('[this example originally generated TXID: 1eb388977b2de99562eb0fbcc661a100eaffed99c53bfcfebe5a087002039b83 on testnet]\n\n\thttp://test.bitcore.io/tx/1eb388977b2de99562eb0fbcc661a100eaffed99c53bfcfebe5a087002039b83');
@ -100,4 +106,3 @@ if (typeof module !== 'undefined') {
}
////

59
examples/CreateAndSignTx-PayToPubkeyHash.js

@ -1,11 +1,8 @@
var run = function() {
bitcore = typeof (bitcore) === 'undefined' ? require('../bitcore') : bitcore;
bitcore = typeof(bitcore) === 'undefined' ? require('../bitcore') : bitcore;
var priv = 'cTgGUrcro89yUtKeG6gHBAS14r3qp25KwTTxG9d4kEzcFxecuZDm';
var amt = '0.005';
var priv = 'cTgGUrcro89yUtKeG6gHBAS14r3qp25KwTTxG9d4kEzcFxecuZDm';
var amt = '0.005';
var toAddress = 'myuAQcCc1REUgXGsCTiYhZvPPc3XxZ36G1';
var changeAddressString = 'moDz3jEo9q7CxjBDjmb13sL4SKkgo2AACE';
@ -19,13 +16,20 @@ var run = function() {
confirmations: 2
}];
console.log('TX Data: BTC:' + amt + ' => '+ toAddress + ', change To:' + changeAddressString ) ;
console.log('TX Data: BTC:' + amt + ' => ' + toAddress + ', change To:' + changeAddressString);
console.log('Unspends Outputs:', utxos);
var outs = [{address:toAddress, amount:amt}];
var outs = [{
address: toAddress,
amount: amt
}];
var keys = [priv];
var opts = {remainderOut: {address: changeAddressString}};
var opts = {
remainderOut: {
address: changeAddressString
}
};
var Builder = bitcore.TransactionBuilder;
var tx = new Builder(opts)
@ -34,25 +38,25 @@ var run = function() {
.sign(keys)
.build();
/* create and signing can be done in multiple steps using:
*
* var builder = new bitcore.TransactionBuilder(opts)
* .setUnspent(utxos)
* .setOutputs(outs);
*
* builder.sign(key1);
* builder.sign(key2);
* ...
* if (builder.isFullySigned()){
* var tx = builder.build();
* }
*
* The selected Unspent Outputs for the transaction can be retrieved with:
*
* var selectedUnspent = build.getSelectedUnspent();
*/
/* create and signing can be done in multiple steps using:
*
* var builder = new bitcore.TransactionBuilder(opts)
* .setUnspent(utxos)
* .setOutputs(outs);
*
* builder.sign(key1);
* builder.sign(key2);
* ...
* if (builder.isFullySigned()){
* var tx = builder.build();
* }
*
* The selected Unspent Outputs for the transaction can be retrieved with:
*
* var selectedUnspent = build.getSelectedUnspent();
*/
var txHex = tx.serialize().toString('hex');
var txHex = tx.serialize().toString('hex');
console.log('TX HEX IS: ', txHex);
};
@ -67,4 +71,3 @@ if (typeof module !== 'undefined') {
}
////

63
examples/CreateAndSignTx-PayToScriptHash.js

@ -1,10 +1,12 @@
var run = function() {
bitcore = typeof (bitcore) === 'undefined' ? require('../bitcore') : bitcore;
bitcore = typeof(bitcore) === 'undefined' ? require('../bitcore') : bitcore;
var networks = require('../networks');
var WalletKey = bitcore.WalletKey;
var Script = bitcore.Script;
var Builder = bitcore.TransactionBuilder;
var opts = {network: networks.testnet};
var opts = {
network: networks.testnet
};
console.log('## Network: ' + opts.network.name);
@ -13,19 +15,17 @@ var run = function() {
input.priv = "cS62Ej4SobZnpFQYN1PEEBr2KWf5sgRYYnELtumcG6WVCfxno39V";
// Complete with the corresponding UTXO you want to use
var utxos = [
{
var utxos = [{
address: "n2hoFVbPrYQf7RJwiRy1tkbuPPqyhAEfbp",
txid: "e4bc22d8c519d3cf848d710619f8480be56176a4a6548dfbe865ab3886b578b5",
vout: 1,
ts: 1396290442,
scriptPubKey: "76a914e867aad8bd361f57c50adc37a0c018692b5b0c9a88ac",
amount: 0.3795,
amount: 0.3795,
confirmations: 7
}
];
}];
var privs = [
var privs = [
"cMpKwGr5oxEacN95WFKNEq6tTcvi11regFwS3muHvGYVxMPJX8JA",
"cVf32m9MR4vxcPwKNJuPepUe8XrHD2z63eCk76d6njRGyCkXpkSM",
"cQ2sVRFX4jQYMLhWyzz6jTQ2xju51P36968ecXnPhRLKLH677eKR",
@ -36,29 +36,37 @@ var run = function() {
var pubkeys = []
privs.forEach(function(p) {
var wk = new WalletKey(opts);
wk.fromObj({priv: p});
wk.fromObj({
priv: p
});
pubkeys.push(bitcore.buffertools.toHex(wk.privKey.public));
});
// multisig p2sh
var opts = {nreq:3, pubkeys:pubkeys};
var opts = {
nreq: 3,
pubkeys: pubkeys
};
// p2scriphash p2sh
//var opts = [{address: an_address}];
var info = Builder.infoForP2sh(opts, 'testnet');
var p2shScript = info.scriptBufHex;
var p2shAddress = info.address;
var outs = [{address:p2shAddress, amount:0.05}];
var outs = [{
address: p2shAddress,
amount: 0.05
}];
var tx = new Builder(opts)
.setUnspent(utxos)
.setOutputs(outs)
.sign([input.priv])
.build();
var txHex = tx.serialize().toString('hex');
var txHex = tx.serialize().toString('hex');
console.log('## p2sh address: ' + p2shAddress); //TODO
@ -72,8 +80,7 @@ var run = function() {
*
* REDDEEM TX
*/
var utxos2 = [
{
var utxos2 = [{
address: p2shAddress,
txid: "c2e50d1c8c581d8c4408378b751633f7eb86687fc5f0502be7b467173f275ae7",
vout: 0,
@ -81,13 +88,15 @@ var run = function() {
scriptPubKey: scriptPubKey,
amount: 0.05,
confirmations: 1
}
];
}];
outs = [{address:input.addr, amount:0.04}];
outs = [{
address: input.addr,
amount: 0.04
}];
var hashMap = {};
hashMap[p2shAddress]=p2shScript;
hashMap[p2shAddress] = p2shScript;
var b = new Builder(opts)
.setUnspent(utxos2)
@ -95,21 +104,21 @@ var run = function() {
.setOutputs(outs)
.sign(privs);
tx= b.build();
tx = b.build();
console.log('Builder:');
console.log('\tSignatures:' + tx.countInputMissingSignatures(0) );
console.log('\t#isFullySigned:' + b.isFullySigned() );
console.log('Builder:');
console.log('\tSignatures:' + tx.countInputMissingSignatures(0));
console.log('\t#isFullySigned:' + b.isFullySigned());
console.log('TX:');
console.log('\t #isComplete:' + tx.isComplete() );
console.log('TX:');
console.log('\t #isComplete:' + tx.isComplete());
var txHex = tx.serialize().toString('hex');
var txHex = tx.serialize().toString('hex');
console.log('2) REDEEM SCRIPT: ', txHex);
console.log('[this example originally generated TXID: 8284aa3b6f9c71c35ecb1d61d05ae78c8ca1f36940eaa615b50584dfc3d95cb7 on testnet]\n\n\thttp://test.bitcore.io/tx/8284aa3b6f9c71c35ecb1d61d05ae78c8ca1f36940eaa615b50584dfc3d95cb7\n\n');
/*
/*
// To send TX with RPC:
var RpcClient = bitcore.RpcClient;
var config = {

24
examples/CreateKey.js

@ -8,21 +8,23 @@ var run = function() {
var networks = require('../networks');
var WalletKey = bitcore.WalletKey;
var opts = {network: networks.testnet};
var opts = {
network: networks.testnet
};
function print(wk) {
console.log('\n## Network: ' + wk.network.name);
console.log ('\t * Hex Representation');
console.log ('\tPrivate: ' + bitcore.buffertools.toHex(wk.privKey.private));
console.log ('\tPublic : ' + bitcore.buffertools.toHex(wk.privKey.public));
console.log ('\tPublic Compressed : ' + (wk.privKey.compressed?'Yes':'No'));
console.log('\t * Hex Representation');
console.log('\tPrivate: ' + bitcore.buffertools.toHex(wk.privKey.private));
console.log('\tPublic : ' + bitcore.buffertools.toHex(wk.privKey.public));
console.log('\tPublic Compressed : ' + (wk.privKey.compressed ? 'Yes' : 'No'));
var wkObj = wk.storeObj();
console.log ('\n\t * WalletKey Store Object');
console.log ('\tPrivate: ' + wkObj.priv);
console.log ('\tPublic : ' + wkObj.pub);
console.log ('\tAddr : ' + wkObj.addr);
console.log('\n\t * WalletKey Store Object');
console.log('\tPrivate: ' + wkObj.priv);
console.log('\tPublic : ' + wkObj.pub);
console.log('\tAddr : ' + wkObj.addr);
};
//Generate a new one (compressed public key, compressed WIF flag)
@ -32,7 +34,9 @@ var run = function() {
//Generate from private Key WIF. Compressed status taken from WIF.
var wk2 = new WalletKey(opts);
wk2.fromObj({priv:'cMpKwGr5oxEacN95WFKNEq6tTcvi11regFwS3muHvGYVxMPJX8JA'});
wk2.fromObj({
priv: 'cMpKwGr5oxEacN95WFKNEq6tTcvi11regFwS3muHvGYVxMPJX8JA'
});
print(wk2);

40
examples/CreateScript.js

@ -9,7 +9,9 @@ var run = function() {
var buffertools = bitcore.buffertools;
var Address = bitcore.Address;
var util = bitcore.util;
var opts = {network: networks.testnet};
var opts = {
network: networks.testnet
};
var p = console.log;
@ -22,38 +24,38 @@ var run = function() {
p('\tHex : ' + buffertools.toHex(s.buffer));
p('\tHuman : ' + s.toHumanReadable());
p('\tKey -------------------------------');
console.log ('\tPrivate: ' + wkObj.priv);
console.log ('\tPublic : ' + wkObj.pub);
console.log ('\tAddr : ' + wkObj.addr);
console.log('\tPrivate: ' + wkObj.priv);
console.log('\tPublic : ' + wkObj.pub);
console.log('\tAddr : ' + wkObj.addr);
s = Script.createPubKeyHashOut(wk.privKey.public);
p('\nScript PubKeyHash:');
p('\tHex : ' + buffertools.toHex(s.buffer));
p('\tHuman : ' + s.toHumanReadable());
p('\tKey -------------------------------');
console.log ('\tPrivate: ' + wkObj.priv);
console.log ('\tPublic : ' + wkObj.pub);
console.log ('\tAddr : ' + wkObj.addr);
console.log('\tPrivate: ' + wkObj.priv);
console.log('\tPublic : ' + wkObj.pub);
console.log('\tAddr : ' + wkObj.addr);
var wks=[];
var wks = [];
var pubs = [];
for (var i =0; i<5; i++) {
for (var i = 0; i < 5; i++) {
wks[i] = new WalletKey(opts);
wks[i].generate();
pubs.push(wks[i].privKey.public);
}
s = Script.createMultisig(3,pubs);
s = Script.createMultisig(3, pubs);
p('\nScript MultiSig (3 out of 5 required signatures):');
p('\tHex : ' + buffertools.toHex(s.buffer));
p('\tHuman : ' + s.toHumanReadable());
for (i =0; i<5; i++) {
for (i = 0; i < 5; i++) {
wkObj = wks[i].storeObj();
p('\tKey ['+i+'] -------------------------------');
console.log ('\tPrivate: ' + wkObj.priv);
console.log ('\tPublic : ' + wkObj.pub);
console.log ('\tAddr : ' + wkObj.addr);
p('\tKey [' + i + '] -------------------------------');
console.log('\tPrivate: ' + wkObj.priv);
console.log('\tPublic : ' + wkObj.pub);
console.log('\tAddr : ' + wkObj.addr);
}
var hash = util.sha256ripe160(s.buffer);
@ -62,10 +64,10 @@ var run = function() {
p('\nScript P2SH:');
p('\tHex : ' + buffertools.toHex(s.buffer));
p('\tHuman : ' + s.toHumanReadable());
p('\tScript Hash: ' + buffertools.toHex(hash));
var a = new Address(networks.livenet.P2SHVersion,hash);
p('\tp2sh Addr: ' + a.toString());
p('\tScript Hash: ' + buffertools.toHex(hash));
var a = new Address(networks.livenet.P2SHVersion, hash);
p('\tp2sh Addr: ' + a.toString());
};
module.exports.run = run;

8
examples/ECIES.js

@ -1,16 +1,16 @@
var run = function() {
bitcore = typeof (bitcore) === 'undefined' ? require('../bitcore') : bitcore;
bitcore = typeof(bitcore) === 'undefined' ? require('../bitcore') : bitcore;
console.log('ECIES: Elliptic Curve Integrated Encryption Scheme');
console.log('A way of encrypting with a public key and decrypting with a private key.');
var key = bitcore.Key.generateSync();
console.log('Private key: ' + key.private.toString('hex'));
console.log('Public key: ' + key.public.toString('hex'));
var message = new Buffer('This is a message to be encrypted');
console.log('Message: "' + message.toString() + '"');
var encrypted = bitcore.ECIES.encrypt(key.public, message);
console.log('Encrypted (with public key): ' + encrypted.toString('hex'));

2
examples/HierarchicalKey.js

@ -1,5 +1,5 @@
var run = function() {
bitcore = typeof (bitcore) === 'undefined' ? require('../bitcore') : bitcore;
bitcore = typeof(bitcore) === 'undefined' ? require('../bitcore') : bitcore;
var HierarchicalKey = bitcore.HierarchicalKey;
var Address = bitcore.Address;
var networks = bitcore.networks;

6
examples/PeerDiscovery.js

@ -1,4 +1,6 @@
var PeerManager = require('../lib/PeerManager');
var peerman = new PeerManager();
var peerman = new PeerManager();
peerman.discover({ limit: 12 }).start();
peerman.discover({
limit: 12
}).start();

2
examples/SendTx.js

@ -81,7 +81,7 @@ var run = function() {
*/
var txid = tx.getHash().toString('hex');
console.log('Created transaction with txid '+txid);
console.log('Created transaction with txid ' + txid);
var raw_tx = tx.serialize().toString('hex');
console.log('Transaction raw hex dump:');
console.log('-------------------------------------');

28
examples/SimpleP2Pmonitor.js

@ -18,16 +18,17 @@ var socket = peer.createConnection();
var con = new Connection(socket, peer);
con.on('error', function (msg) {
var peer = msg.peer, err = msg.err;
con.on('error', function(msg) {
var peer = msg.peer,
err = msg.err;
console.error('Error connecting to peer', peer.host + ':' + peer.port, '(' + err.message + ')');
});
con.on('disconnect', function (msg) {
con.on('disconnect', function(msg) {
console.log('disconnect: ', msg);
});
con.on('connect', function (msg) {
con.on('connect', function(msg) {
console.log('Connected to %s', msg.peer.host + ':' + msg.peer.port);
});
@ -36,37 +37,36 @@ con.on('connect', function (msg) {
// Make a log function available to all listeners
// The log function is just like console.log except it prefixes
// messages with [host:port]
function listen (event_name, fn) {
con.on(event_name, function (event) {
fn(event, function () {
function listen(event_name, fn) {
con.on(event_name, function(event) {
fn(event, function() {
var args = Array.prototype.slice.call(arguments);
var str = args.shift();
str = '[%s:%s] ' + str;
args = [ str, event.peer.host, event.peer.port ].concat(args);
args = [str, event.peer.host, event.peer.port].concat(args);
console.log.apply(console, args);
});
});
}
listen('getaddr', function (event, log) {
listen('getaddr', function(event, log) {
log('Received message getaddr');
log(event);
});
listen('verack', function (event, log) {
listen('verack', function(event, log) {
log('Received message verack');
});
listen('version', function (event, log) {
listen('version', function(event, log) {
log('Received message version (%s)', event.message.version);
});
listen('addr', function (event, log) {
listen('addr', function(event, log) {
log('Received message addr (%s addresses)', event.message.addrs.length);
});
listen('inv', function (event, log) {
listen('inv', function(event, log) {
log('Received message inv (%s invs)', event.message.count);
console.log(event.message.invs);
});

6
examples/VanityAddress.js

@ -10,15 +10,15 @@ var run = function() {
// config your regular expression
var re = /[0-9]{6}$/; // ends in 6 digits
var a,k,m;
var a, k, m;
while (true) {
k = Key.generateSync();
a = Address.fromKey(k);
m = a.toString().match(re);
if (m) break;
}
console.log('Address: '+a.toString());
console.log('Private Key: '+k.private.toString('hex'));
console.log('Address: ' + a.toString());
console.log('Private Key: ' + k.private.toString('hex'));
};

17
lib/Address.js

@ -85,7 +85,7 @@ Address.fromScript = function(script, network) {
network = 'livenet';
if (typeof script === 'string') {
script = new Script(new Buffer(script,'hex'));
script = new Script(new Buffer(script, 'hex'));
}
var version = networks[network].P2SHVersion;
@ -99,16 +99,17 @@ Address.fromScript = function(script, network) {
Address.fromScriptPubKey = function(scriptPubKey, network) {
if (typeof scriptPubKey === 'string') {
scriptPubKey = new Script(new Buffer(scriptPubKey,'hex'));
scriptPubKey = new Script(new Buffer(scriptPubKey, 'hex'));
}
if (!network)
network = 'livenet';
var ret=[], version;
var ret = [],
version;
var payload = scriptPubKey.capture();
if (payload) {
if (payload) {
var txType = scriptPubKey.classify();
switch (txType) {
case Script.TX_PUBKEY:
@ -120,15 +121,15 @@ Address.fromScriptPubKey = function(scriptPubKey, network) {
break;
case Script.TX_MULTISIG:
version = networks[network].addressVersion;
for(var i in payload)
for (var i in payload)
payload[i] = coinUtil.sha256ripe160(payload[i]);
break;
case Script.TX_SCRIPTHASH:
version = networks[network].P2SHVersion;
break;
}
for(var i in payload)
ret.push(new Address(version,payload[i]));
for (var i in payload)
ret.push(new Address(version, payload[i]));
}
return ret;
};
@ -137,7 +138,7 @@ Address.fromScriptPubKey = function(scriptPubKey, network) {
Address.prototype.validate = function() {
this.doAsBinary(function() {
Address.super(this, 'validate', arguments);
if(this.data.length !== 21) throw new Error('invalid data length');
if (this.data.length !== 21) throw new Error('invalid data length');
});
if (typeof this.network() === 'undefined') throw new Error('invalid network');
};

28
lib/Armory.js

@ -9,12 +9,12 @@ var Point = require('./Point'),
*
* @example examples/Armory.js
*/
function Armory (chaincode, pubkey) {
function Armory(chaincode, pubkey) {
this.chaincode = new Buffer(chaincode, 'hex');
this.pubkey = new Buffer(pubkey, 'hex');
}
Armory.prototype.generatePubKey = function () {
Armory.prototype.generatePubKey = function() {
var pubKey = this.pubkey;
var chainCode = this.chaincode;
var chainXor = twoSha256(pubKey);
@ -30,7 +30,7 @@ Armory.prototype.generatePubKey = function () {
return new_pubkey;
};
Armory.prototype.next = function () {
Armory.prototype.next = function() {
var next_pubkey = this.generatePubKey();
return new Armory(this.chaincode, next_pubkey);
};
@ -44,13 +44,13 @@ Armory.prototype.next = function () {
*
* https://github.com/etotheipi/BitcoinArmory/issues/204#issuecomment-42217801
*/
Armory.fromMasterPublicKey = function (mpk) {
Armory.fromMasterPublicKey = function(mpk) {
var pubkey = mpk.substr(0, 130);
var chaincode = mpk.substr(130, mpk.length);
return new Armory(chaincode, pubkey);
};
function decode (str) {
function decode(str) {
var from = '0123456789abcdef';
var to = 'asdfghjkwertuion';
var res = '';
@ -59,20 +59,20 @@ function decode (str) {
return res;
}
Armory.decodeSeed = function (seed) {
Armory.decodeSeed = function(seed) {
var keys = seed.trim().split('\n');
var lines = [];
for (var i = 0; i < keys.length; i++) {
var k = keys[i].replace(' ','');
var k = keys[i].replace(' ', '');
var raw = new Buffer(decode(k), 'hex');
var data = raw.slice(0, 16);
lines.push(data);
}
var privKey = Buffer.concat([ lines[0], lines[1] ]);
var chainCode = (lines.length==4) ?
Buffer.concat([ lines[2], lines[3] ]) : Armory.deriveChaincode(privKey);
var privKey = Buffer.concat([lines[0], lines[1]]);
var chainCode = (lines.length == 4) ?
Buffer.concat([lines[2], lines[3]]) : Armory.deriveChaincode(privKey);
return {
privKey: privKey,
@ -81,7 +81,7 @@ Armory.decodeSeed = function (seed) {
};
// Derive chain code from root key
Armory.fromSeed = function (seed) {
Armory.fromSeed = function(seed) {
var res = Armory.decodeSeed(seed);
// generate first public key
var key = new Key();
@ -92,7 +92,7 @@ Armory.fromSeed = function (seed) {
return new Armory(res.chainCode, key.public);
};
Armory.deriveChaincode = function (root) {
Armory.deriveChaincode = function(root) {
var msg = 'Derive Chaincode from Root Key';
var hash = twoSha256(root);
@ -107,8 +107,8 @@ Armory.deriveChaincode = function (root) {
ikey = new Buffer(ikey);
var m = new Buffer(msg, 'utf8');
var a = sha256(Buffer.concat([ ikey, m ]));
var b = sha256(Buffer.concat([ okey, a ]));
var a = sha256(Buffer.concat([ikey, m]));
var b = sha256(Buffer.concat([okey, a]));
return b;
};

15
lib/BIP39.js

@ -3,10 +3,10 @@ var coinUtil = imports.coinUtil || require('../util');
var sjcl = imports.sjcl || require('./sjcl');
var SecureRandom = require('./SecureRandom');
var hmacSHA512 = function (key) {
var hmacSHA512 = function(key) {
var hasher = new sjcl.misc.hmac(key, sjcl.hash.sha512);
this.encrypt = function () {
return hasher.encrypt.apply(hasher, arguments);
this.encrypt = function() {
return hasher.encrypt.apply(hasher, arguments);
};
};
@ -15,8 +15,7 @@ var pbkdf2Sync_sha512 = function(password, salt, iterations, keylen) {
return sjcl.codec.hex.fromBits(derivedKey)
};
var BIP39 = function() {
};
var BIP39 = function() {};
BIP39.mnemonic = function(wordlist, bits) {
if (!bits)
@ -31,11 +30,11 @@ BIP39.entropy2mnemonic = function(wordlist, buf) {
var hash = coinUtil.sha256(buf);
var bin = "";
var bits = buf.length * 8;
for (var i = 0 ; i < buf.length ; i++) {
for (var i = 0; i < buf.length; i++) {
bin = bin + ("00000000" + buf[i].toString(2)).slice(-8);
}
var hashbits = hash[0].toString(2);
hashbits = ("00000000" + hashbits).slice(-8).slice(0, bits/32);
hashbits = ("00000000" + hashbits).slice(-8).slice(0, bits / 32);
bin = bin + hashbits;
if (bin.length % 11 != 0)
throw new Error("internal error - entropy not an even multiple of 11 bits - " + bin.length);
@ -43,7 +42,7 @@ BIP39.entropy2mnemonic = function(wordlist, buf) {
for (var i = 0; i < bin.length / 11; i++) {
if (mnemonic != "")
mnemonic = mnemonic + " ";
var wi = parseInt(bin.slice(i*11, (i+1)*11), 2);
var wi = parseInt(bin.slice(i * 11, (i + 1) * 11), 2);
mnemonic = mnemonic + wordlist[wi];
}
return mnemonic;

2
lib/BIP39WordlistEn.js

File diff suppressed because one or more lines are too long

27
lib/Base58.js

@ -7,7 +7,7 @@ var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
var ALPHABET_ZERO = ALPHABET[0];
var ALPHABET_BUF = new Buffer(ALPHABET, 'ascii');
var ALPHABET_INV = {};
for(var i=0; i < ALPHABET.length; i++) {
for (var i = 0; i < ALPHABET.length; i++) {
ALPHABET_INV[ALPHABET[i]] = i;
};
@ -18,13 +18,13 @@ var base58 = {
var x = bignum.fromBuffer(buf);
var r;
if(buf.length < 512) {
if (buf.length < 512) {
str = globalBuffer;
} else {
str = new Buffer(buf.length << 1);
}
var i = str.length - 1;
while(x.gt(0)) {
while (x.gt(0)) {
r = x.mod(58);
x = x.div(58);
str[i] = ALPHABET_BUF[r.toNumber()];
@ -32,32 +32,33 @@ var base58 = {
}
// deal with leading zeros
var j=0;
while(buf[j] == 0) {
var j = 0;
while (buf[j] == 0) {
str[i] = ALPHABET_BUF[0];
j++; i--;
j++;
i--;
}
return str.slice(i+1,str.length).toString('ascii');
return str.slice(i + 1, str.length).toString('ascii');
},
decode: function(str) {
if(str.length == 0) return zerobuf;
if (str.length == 0) return zerobuf;
var answer = bignum(0);
for(var i=0; i<str.length; i++) {
for (var i = 0; i < str.length; i++) {
answer = answer.mul(58);
answer = answer.add(ALPHABET_INV[str[i]]);
};
var i = 0;
while(i < str.length && str[i] == ALPHABET_ZERO) {
while (i < str.length && str[i] == ALPHABET_ZERO) {
i++;
}
if(i > 0) {
if (i > 0) {
var zb = new Buffer(i);
zb.fill(0);
if(i == str.length) return zb;
if (i == str.length) return zb;
answer = answer.toBuffer();
return Buffer.concat([zb, answer], i+answer.length);
return Buffer.concat([zb, answer], i + answer.length);
} else {
return answer.toBuffer();
}

179
lib/Block.js

@ -1,24 +1,23 @@
var imports = require('soop').imports();
var util = imports.util || require('../util');
var Debug1 = imports.Debug1 || function() {};
var Script = imports.Script || require('./Script');
var Bignum = imports.Bignum || require('bignum');
var Binary = imports.Binary || require('binary');
var Step = imports.Step || require('step');
var buffertools = imports.buffertools || require('buffertools');
var Transaction = imports.Transaction || require('./Transaction');
var TransactionIn = Transaction.In;
var TransactionOut = Transaction.Out;
var COINBASE_OP = Transaction.COINBASE_OP;
var imports = require('soop').imports();
var util = imports.util || require('../util');
var Debug1 = imports.Debug1 || function() {};
var Script = imports.Script || require('./Script');
var Bignum = imports.Bignum || require('bignum');
var Binary = imports.Binary || require('binary');
var Step = imports.Step || require('step');
var buffertools = imports.buffertools || require('buffertools');
var Transaction = imports.Transaction || require('./Transaction');
var TransactionIn = Transaction.In;
var TransactionOut = Transaction.Out;
var COINBASE_OP = Transaction.COINBASE_OP;
var VerificationError = imports.VerificationError || require('../util/error').VerificationError;
var BlockRules = {
maxTimeOffset: 2 * 60 * 60, // How far block timestamps can be into the future
maxTimeOffset: 2 * 60 * 60, // How far block timestamps can be into the future
largestHash: Bignum(2).pow(256)
};
function Block(data)
{
function Block(data) {
if ("object" !== typeof data) {
data = {};
}
@ -39,12 +38,18 @@ function Block(data)
Block.prototype.getHeader = function getHeader() {
var buf = new Buffer(80);
var ofs = 0;
buf.writeUInt32LE(this.version, ofs); ofs += 4;
this.prev_hash.copy(buf, ofs); ofs += 32;
this.merkle_root.copy(buf, ofs); ofs += 32;
buf.writeUInt32LE(this.timestamp, ofs); ofs += 4;
buf.writeUInt32LE(this.bits, ofs); ofs += 4;
buf.writeUInt32LE(this.nonce, ofs); ofs += 4;
buf.writeUInt32LE(this.version, ofs);
ofs += 4;
this.prev_hash.copy(buf, ofs);
ofs += 32;
this.merkle_root.copy(buf, ofs);
ofs += 32;
buf.writeUInt32LE(this.timestamp, ofs);
ofs += 4;
buf.writeUInt32LE(this.bits, ofs);
ofs += 4;
buf.writeUInt32LE(this.nonce, ofs);
ofs += 4;
return buf;
};
@ -102,12 +107,12 @@ Block.prototype.checkProofOfWork = function checkProofOfWork() {
};
/**
* Returns the amount of work that went into this block.
*
* Work is defined as the average number of tries required to meet this
* block's difficulty target. For example a target that is greater than 5%
* of all possible hashes would mean that 20 "work" is required to meet it.
*/
* Returns the amount of work that went into this block.
*
* Work is defined as the average number of tries required to meet this
* block's difficulty target. For example a target that is greater than 5%
* of all possible hashes would mean that 20 "work" is required to meet it.
*/
Block.prototype.getWork = function getWork() {
var target = util.decodeDiffBits(this.bits, true);
return BlockRules.largestHash.div(target.add(1));
@ -131,7 +136,7 @@ Block.prototype.checkTransactions = function checkTransactions(txs) {
}
for (var i = 1; i < txs.length; i++) {
if (txs[i].isCoinBase()) {
throw new VerificationError('Tx index '+i+' must not be coinbase');
throw new VerificationError('Tx index ' + i + ' must not be coinbase');
}
}
@ -139,11 +144,11 @@ Block.prototype.checkTransactions = function checkTransactions(txs) {
};
/**
* Build merkle tree.
*
* Ported from Java. Original code: BitcoinJ by Mike Hearn
* Copyright (c) 2011 Google Inc.
*/
* Build merkle tree.
*
* Ported from Java. Original code: BitcoinJ by Mike Hearn
* Copyright (c) 2011 Google Inc.
*/
Block.prototype.getMerkleTree = function getMerkleTree(txs) {
// The merkle hash is based on a tree of hashes calculated from the transactions:
//
@ -165,7 +170,7 @@ Block.prototype.getMerkleTree = function getMerkleTree(txs) {
}
// Start by adding all the hashes of the transactions as leaves of the tree.
var tree = txs.map(function (tx) {
var tree = txs.map(function(tx) {
return tx instanceof Transaction ? tx.getHash() : tx;
});
@ -177,7 +182,7 @@ Block.prototype.getMerkleTree = function getMerkleTree(txs) {
var i2 = Math.min(i + 1, size - 1);
var a = tree[j + i];
var b = tree[j + i2];
tree.push(util.twoSha256(Buffer.concat([a,b])));
tree.push(util.twoSha256(Buffer.concat([a, b])));
}
j += size;
}
@ -229,24 +234,23 @@ Block.prototype.getBlockValue = function getBlockValue() {
};
Block.prototype.toString = function toString() {
return "<Block " + util.formatHashAlt(this.hash) + " height="+this.height+">";
return "<Block " + util.formatHashAlt(this.hash) + " height=" + this.height + ">";
};
Block.prototype.createCoinbaseTx =
function createCoinbaseTx(beneficiary)
{
var tx = new Transaction();
tx.ins.push(new TransactionIn({
s: util.EMPTY_BUFFER,
q: 0xffffffff,
o: COINBASE_OP
}));
tx.outs.push(new TransactionOut({
v: util.bigIntToValue(this.getBlockValue()),
s: Script.createPubKeyOut(beneficiary).getBuffer()
}));
return tx;
function createCoinbaseTx(beneficiary) {
var tx = new Transaction();
tx.ins.push(new TransactionIn({
s: util.EMPTY_BUFFER,
q: 0xffffffff,
o: COINBASE_OP
}));
tx.outs.push(new TransactionOut({
v: util.bigIntToValue(this.getBlockValue()),
s: Script.createPubKeyOut(beneficiary).getBuffer()
}));
return tx;
};
Block.prototype.solve = function solve(miner, callback) {
@ -256,45 +260,44 @@ Block.prototype.solve = function solve(miner, callback) {
};
/**
* Returns an object with the same field names as jgarzik's getblock patch.
*/
* Returns an object with the same field names as jgarzik's getblock patch.
*/
Block.prototype.getStandardizedObject =
function getStandardizedObject(txs)
{
var block = {
hash: util.formatHashFull(this.getHash()),
version: this.version,
prev_block: util.formatHashFull(this.prev_hash),
mrkl_root: util.formatHashFull(this.merkle_root),
time: this.timestamp,
bits: this.bits,
nonce: this.nonce,
height: this.height
};
if (txs) {
var mrkl_tree = this.getMerkleTree(txs).map(function (buffer) {
return util.formatHashFull(buffer);
});
block.mrkl_root = mrkl_tree[mrkl_tree.length - 1];
block.n_tx = txs.length;
var totalSize = 80; // Block header
totalSize += util.getVarIntSize(txs.length); // txn_count
txs = txs.map(function (tx) {
tx = tx.getStandardizedObject();
totalSize += tx.size;
return tx;
});
block.size = totalSize;
block.tx = txs;
block.mrkl_tree = mrkl_tree;
} else {
block.size = this.size;
}
return block;
function getStandardizedObject(txs) {
var block = {
hash: util.formatHashFull(this.getHash()),
version: this.version,
prev_block: util.formatHashFull(this.prev_hash),
mrkl_root: util.formatHashFull(this.merkle_root),
time: this.timestamp,
bits: this.bits,
nonce: this.nonce,
height: this.height
};
if (txs) {
var mrkl_tree = this.getMerkleTree(txs).map(function(buffer) {
return util.formatHashFull(buffer);
});
block.mrkl_root = mrkl_tree[mrkl_tree.length - 1];
block.n_tx = txs.length;
var totalSize = 80; // Block header
totalSize += util.getVarIntSize(txs.length); // txn_count
txs = txs.map(function(tx) {
tx = tx.getStandardizedObject();
totalSize += tx.size;
return tx;
});
block.size = totalSize;
block.tx = txs;
block.mrkl_tree = mrkl_tree;
} else {
block.size = this.size;
}
return block;
};
module.exports = require('soop')(Block);

25
lib/Bloom.js

@ -1,4 +1,4 @@
var MAX_BLOOM_FILTER_SIZE = 36000; // bytes
var MAX_BLOOM_FILTER_SIZE = 36000; // bytes
var MAX_HASH_FUNCS = 50;
var LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455;
var LN2 = 0.6931471805599453094172321214581765680755001343602552;
@ -47,13 +47,16 @@ Bloom.prototype.hash = function(hashNum, data) {
var k1 = 0;
switch (data.length & 3) {
case 3: k1 ^= tail[2] << 16;
case 2: k1 ^= tail[1] << 8;
case 1: k1 ^= tail[0];
k1 *= c1;
k1 = ROTL32(k1, 15);
k1 *= c2;
h1 ^= k1;
case 3:
k1 ^= tail[2] << 16;
case 2:
k1 ^= tail[1] << 8;
case 1:
k1 ^= tail[0];
k1 *= c1;
k1 = ROTL32(k1, 15);
k1 *= c2;
h1 ^= k1;
}
// finalize
@ -90,7 +93,7 @@ Bloom.prototype.sizeOk = function() {
};
function toInt(v) {
return ~~v;
return~~ v;
}
function min(a, b) {
@ -101,10 +104,10 @@ function min(a, b) {
Bloom.prototype.init = function(elements, FPRate) {
var filterSize = min(toInt(-1.0 / LN2SQUARED * elements * Math.log(FPRate)),
MAX_BLOOM_FILTER_SIZE * 8) / 8;
MAX_BLOOM_FILTER_SIZE * 8) / 8;
this.data[filterSize] = 0;
this.hashFuncs = min(toInt(this.data.length * 8 / elements * LN2),
MAX_HASH_FUNCS);
MAX_HASH_FUNCS);
};

470
lib/Connection.js

@ -1,32 +1,32 @@
var imports = require('soop').imports();
var imports = require('soop').imports();
var log = imports.log || require('../util/log');
var log = imports.log || require('../util/log');
var MAX_RECEIVE_BUFFER = 10000000;
var PROTOCOL_VERSION = 70000;
var PROTOCOL_VERSION = 70000;
var Put = imports.Put || require('bufferput');
var Buffers = imports.Buffers || require('buffers');
var Put = imports.Put || require('bufferput');
var Buffers = imports.Buffers || require('buffers');
require('../patches/Buffers.monkey').patch(Buffers);
var bitcoreDefaults = imports.config || require('../config');
var networks = imports.networks || require('../networks');
var Block = imports.Block || require('./Block');
var Transaction = imports.Transaction || require('./Transaction');
var util = imports.util || require('../util');
var Parser = imports.Parser || require('../util/BinaryParser');
var buffertools = imports.buffertools || require('buffertools');
var doubleSha256 = imports.doubleSha256 || util.twoSha256;
var SecureRandom = imports.SecureRandom || require('./SecureRandom');
var nonce = SecureRandom.getPseudoRandomBuffer(8);
var networks = imports.networks || require('../networks');
var Block = imports.Block || require('./Block');
var Transaction = imports.Transaction || require('./Transaction');
var util = imports.util || require('../util');
var Parser = imports.Parser || require('../util/BinaryParser');
var buffertools = imports.buffertools || require('buffertools');
var doubleSha256 = imports.doubleSha256 || util.twoSha256;
var SecureRandom = imports.SecureRandom || require('./SecureRandom');
var nonce = SecureRandom.getPseudoRandomBuffer(8);
var BIP0031_VERSION = 60000;
function Connection(socket, peer, opts) {
Connection.super(this, arguments);
this.config = opts || bitcoreDefaults;
this.network = networks[this.config.network] || networks.livenet;
this.socket = socket;
this.peer = peer;
@ -70,22 +70,22 @@ Connection.prototype.open = function(callback) {
return this;
};
Connection.prototype.setupHandlers = function () {
Connection.prototype.setupHandlers = function() {
this.socket.addListener('connect', this.handleConnect.bind(this));
this.socket.addListener('error', this.handleError.bind(this));
this.socket.addListener('end', this.handleDisconnect.bind(this));
this.socket.addListener('data', (function (data) {
this.socket.addListener('data', (function(data) {
var dumpLen = 35;
log.debug('['+this.peer+'] '+
'Recieved '+data.length+' bytes of data:');
log.debug('... '+ buffertools.toHex(data.slice(0, dumpLen > data.length ?
data.length : dumpLen)) +
(data.length > dumpLen ? '...' : ''));
log.debug('[' + this.peer + '] ' +
'Recieved ' + data.length + ' bytes of data:');
log.debug('... ' + buffertools.toHex(data.slice(0, dumpLen > data.length ?
data.length : dumpLen)) +
(data.length > dumpLen ? '...' : ''));
}).bind(this));
this.socket.addListener('data', this.handleData.bind(this));
};
Connection.prototype.handleConnect = function () {
Connection.prototype.handleConnect = function() {
if (!this.inbound) {
this.sendVersion();
}
@ -98,11 +98,11 @@ Connection.prototype.handleConnect = function () {
Connection.prototype.handleError = function(err) {
if (err.errno == 110 || err.errno == 'ETIMEDOUT') {
log.info('connection timed out for '+this.peer);
log.info('connection timed out for ' + this.peer);
} else if (err.errno == 111 || err.errno == 'ECONNREFUSED') {
log.info('connection refused for '+this.peer);
log.info('connection refused for ' + this.peer);
} else {
log.warn('connection with '+this.peer+' '+err.toString());
log.warn('connection with ' + this.peer + ' ' + err.toString());
}
this.emit('error', {
conn: this,
@ -112,7 +112,7 @@ Connection.prototype.handleError = function(err) {
});
};
Connection.prototype.handleDisconnect = function () {
Connection.prototype.handleDisconnect = function() {
this.emit('disconnect', {
conn: this,
socket: this.socket,
@ -128,48 +128,48 @@ Connection.prototype.handleMessage = function(message) {
try {
switch (message.command) {
case 'version':
// Did we connect to ourself?
if (buffertools.compare(nonce, message.nonce) === 0) {
this.socket.end();
return;
}
if (this.inbound) {
this.sendVersion();
}
if (message.version >= 209) {
this.sendMessage('verack', new Buffer([]));
}
this.sendVer = Math.min(message.version, PROTOCOL_VERSION);
if (message.version < 209) {
case 'version':
// Did we connect to ourself?
if (buffertools.compare(nonce, message.nonce) === 0) {
this.socket.end();
return;
}
if (this.inbound) {
this.sendVersion();
}
if (message.version >= 209) {
this.sendMessage('verack', new Buffer([]));
}
this.sendVer = Math.min(message.version, PROTOCOL_VERSION);
if (message.version < 209) {
this.recvVer = Math.min(message.version, PROTOCOL_VERSION);
} else {
// We won't start expecting a checksum until after we've received
// the 'verack' message.
this.once('verack', (function() {
this.recvVer = message.version;
}).bind(this));
}
this.bestHeight = message.start_height;
break;
case 'verack':
this.recvVer = Math.min(message.version, PROTOCOL_VERSION);
} else {
// We won't start expecting a checksum until after we've received
// the 'verack' message.
this.once('verack', (function () {
this.recvVer = message.version;
}).bind(this));
}
this.bestHeight = message.start_height;
break;
case 'verack':
this.recvVer = Math.min(message.version, PROTOCOL_VERSION);
this.active = true;
break;
case 'ping':
if ('object' === typeof message.nonce) {
this.sendPong(message.nonce);
}
break;
this.active = true;
break;
case 'ping':
if ('object' === typeof message.nonce) {
this.sendPong(message.nonce);
}
break;
}
} catch (e) {
log.err('Error while handling "'+message.command+'" message from ' +
this.peer + ':\n' +
(e.stack ? e.stack : e.toString()));
log.err('Error while handling "' + message.command + '" message from ' +
this.peer + ':\n' +
(e.stack ? e.stack : e.toString()));
return;
}
this.emit(message.command, {
@ -180,17 +180,17 @@ Connection.prototype.handleMessage = function(message) {
});
};
Connection.prototype.sendPong = function (nonce) {
Connection.prototype.sendPong = function(nonce) {
this.sendMessage('pong', nonce);
};
Connection.prototype.sendVersion = function () {
Connection.prototype.sendVersion = function() {
var subversion = '/BitcoinX:0.1/';
var put = new Put();
put.word32le(PROTOCOL_VERSION); // version
put.word64le(1); // services
put.word64le(Math.round(new Date().getTime()/1000)); // timestamp
put.word64le(Math.round(new Date().getTime() / 1000)); // timestamp
put.pad(26); // addr_me
put.pad(26); // addr_you
put.put(nonce);
@ -201,7 +201,7 @@ Connection.prototype.sendVersion = function () {
this.sendMessage('version', put.buffer());
};
Connection.prototype.sendGetBlocks = function (starts, stop, wantHeaders) {
Connection.prototype.sendGetBlocks = function(starts, stop, wantHeaders) {
// Default value for stop is 0 to get as many blocks as possible (500)
stop = stop || util.NULL_HASH;
@ -236,7 +236,7 @@ Connection.prototype.sendGetHeaders = function(starts, stop) {
this.sendGetBlocks(starts, stop, true);
};
Connection.prototype.sendGetData = function (invs) {
Connection.prototype.sendGetData = function(invs) {
var put = new Put();
put.varint(invs.length);
for (var i = 0; i < invs.length; i++) {
@ -246,16 +246,16 @@ Connection.prototype.sendGetData = function (invs) {
this.sendMessage('getdata', put.buffer());
};
Connection.prototype.sendGetAddr = function (invs) {
Connection.prototype.sendGetAddr = function(invs) {
var put = new Put();
this.sendMessage('getaddr', put.buffer());
};
Connection.prototype.sendInv = function(data) {
if(!Array.isArray(data)) data = [data];
if (!Array.isArray(data)) data = [data];
var put = new Put();
put.varint(data.length);
data.forEach(function (value) {
data.forEach(function(value) {
if (value instanceof Block) {
// Block
put.word32le(2); // MSG_BLOCK
@ -268,10 +268,10 @@ Connection.prototype.sendInv = function(data) {
this.sendMessage('inv', put.buffer());
};
Connection.prototype.sendHeaders = function (headers) {
Connection.prototype.sendHeaders = function(headers) {
var put = new Put();
put.varint(headers.length);
headers.forEach(function (header) {
headers.forEach(function(header) {
put.put(header);
// Indicate 0 transactions
@ -280,11 +280,11 @@ Connection.prototype.sendHeaders = function (headers) {
this.sendMessage('headers', put.buffer());
};
Connection.prototype.sendTx = function (tx) {
Connection.prototype.sendTx = function(tx) {
this.sendMessage('tx', tx.serialize());
};
Connection.prototype.sendBlock = function (block, txs) {
Connection.prototype.sendBlock = function(block, txs) {
var put = new Put();
// Block header
@ -292,14 +292,14 @@ Connection.prototype.sendBlock = function (block, txs) {
// List of transactions
put.varint(txs.length);
txs.forEach(function (tx) {
txs.forEach(function(tx) {
put.put(tx.serialize());
});
this.sendMessage('block', put.buffer());
};
Connection.prototype.sendMessage = function (command, payload) {
Connection.prototype.sendMessage = function(command, payload) {
try {
var magic = this.network.magic;
var commandBuf = new Buffer(command, 'ascii');
@ -312,35 +312,35 @@ Connection.prototype.sendMessage = function (command, payload) {
checksum = new Buffer([]);
}
var message = new Put(); // -- HEADER --
message.put(magic); // magic bytes
message.put(commandBuf); // command name
message.pad(12 - commandBuf.length); // zero-padded
message.word32le(payload.length); // payload length
message.put(checksum); // checksum
var message = new Put(); // -- HEADER --
message.put(magic); // magic bytes
message.put(commandBuf); // command name
message.pad(12 - commandBuf.length); // zero-padded
message.word32le(payload.length); // payload length
message.put(checksum); // checksum
// -- BODY --
message.put(payload); // payload data
message.put(payload); // payload data
var buffer = message.buffer();
log.debug('['+this.peer+'] '+
'Sending message '+command+' ('+payload.length+' bytes)');
log.debug('[' + this.peer + '] ' +
'Sending message ' + command + ' (' + payload.length + ' bytes)');
this.socket.write(buffer);
} catch (err) {
// TODO: We should catch this error one level higher in order to better
// determine how to react to it. For now though, ignoring it will do.
log.err('Error while sending message to peer '+this.peer+': '+
(err.stack ? err.stack : err.toString()));
log.err('Error while sending message to peer ' + this.peer + ': ' +
(err.stack ? err.stack : err.toString()));
}
};
Connection.prototype.handleData = function (data) {
Connection.prototype.handleData = function(data) {
this.buffers.push(data);
if (this.buffers.length > MAX_RECEIVE_BUFFER) {
log.err('Peer '+this.peer+' exceeded maxreceivebuffer, disconnecting.'+
(err.stack ? err.stack : err.toString()));
log.err('Peer ' + this.peer + ' exceeded maxreceivebuffer, disconnecting.' +
(err.stack ? err.stack : err.toString()));
this.socket.destroy();
return;
}
@ -348,22 +348,22 @@ Connection.prototype.handleData = function (data) {
this.processData();
};
Connection.prototype.processData = function () {
Connection.prototype.processData = function() {
// If there are less than 20 bytes there can't be a message yet.
if (this.buffers.length < 20) return;
var magic = this.network.magic;
var i = 0;
for (;;) {
if (this.buffers.get(i ) === magic[0] &&
this.buffers.get(i+1) === magic[1] &&
this.buffers.get(i+2) === magic[2] &&
this.buffers.get(i+3) === magic[3]) {
if (this.buffers.get(i) === magic[0] &&
this.buffers.get(i + 1) === magic[1] &&
this.buffers.get(i + 2) === magic[2] &&
this.buffers.get(i + 3) === magic[3]) {
if (i !== 0) {
log.debug('['+this.peer+'] '+
'Received '+i+
' bytes of inter-message garbage: ');
log.debug('... '+this.buffers.slice(0,i));
log.debug('[' + this.peer + '] ' +
'Received ' + i +
' bytes of inter-message garbage: ');
log.debug('... ' + this.buffers.slice(0, i));
this.buffers.skip(i);
}
@ -377,32 +377,33 @@ Connection.prototype.processData = function () {
i++;
}
var payloadLen = (this.buffers.get(16) ) +
(this.buffers.get(17) << 8) +
(this.buffers.get(18) << 16) +
(this.buffers.get(19) << 24);
var payloadLen = (this.buffers.get(16)) +
(this.buffers.get(17) << 8) +
(this.buffers.get(18) << 16) +
(this.buffers.get(19) << 24);
var startPos = (this.recvVer >= 209) ? 24 : 20;
var endPos = startPos + payloadLen;
if (this.buffers.length < endPos) return;
var command = this.buffers.slice(4, 16).toString('ascii').replace(/\0+$/,'');
var command = this.buffers.slice(4, 16).toString('ascii').replace(/\0+$/, '');
var payload = this.buffers.slice(startPos, endPos);
var checksum = (this.recvVer >= 209) ? this.buffers.slice(20, 24) : null;
log.debug('['+this.peer+'] ' +
'Received message ' + command +
' (' + payloadLen + ' bytes)');
log.debug('[' + this.peer + '] ' +
'Received message ' + command +
' (' + payloadLen + ' bytes)');
if (checksum !== null) {
var checksumConfirm = doubleSha256(payload).slice(0, 4);
if (buffertools.compare(checksumConfirm, checksum) !== 0) {
log.err('['+this.peer+'] '+
'Checksum failed',
{ cmd: command,
expected: checksumConfirm.toString('hex'),
actual: checksum.toString('hex') });
log.err('[' + this.peer + '] ' +
'Checksum failed', {
cmd: command,
expected: checksumConfirm.toString('hex'),
actual: checksum.toString('hex')
});
return;
}
}
@ -411,9 +412,9 @@ Connection.prototype.processData = function () {
try {
message = this.parseMessage(command, payload);
} catch (e) {
log.err('Error while parsing message '+command+' from ' +
this.peer + ':\n' +
(e.stack ? e.stack : e.toString()));
log.err('Error while parsing message ' + command + ' from ' +
this.peer + ':\n' +
(e.stack ? e.stack : e.toString()));
}
if (message) {
@ -424,7 +425,7 @@ Connection.prototype.processData = function () {
this.processData();
};
Connection.prototype.parseMessage = function (command, payload) {
Connection.prototype.parseMessage = function(command, payload) {
var parser = new Parser(payload);
var data = {
@ -434,129 +435,130 @@ Connection.prototype.parseMessage = function (command, payload) {
var i;
switch (command) {
case 'version': // https://en.bitcoin.it/wiki/Protocol_specification#version
data.version = parser.word32le();
data.services = parser.word64le();
data.timestamp = parser.word64le();
data.addr_me = parser.buffer(26);
data.addr_you = parser.buffer(26);
data.nonce = parser.buffer(8);
data.subversion = parser.varStr();
data.start_height = parser.word32le();
break;
case 'inv':
case 'getdata':
data.count = parser.varInt();
data.invs = [];
for (i = 0; i < data.count; i++) {
data.invs.push({
type: parser.word32le(),
hash: parser.buffer(32)
});
}
break;
case 'version': // https://en.bitcoin.it/wiki/Protocol_specification#version
data.version = parser.word32le();
data.services = parser.word64le();
data.timestamp = parser.word64le();
data.addr_me = parser.buffer(26);
data.addr_you = parser.buffer(26);
data.nonce = parser.buffer(8);
data.subversion = parser.varStr();
data.start_height = parser.word32le();
break;
case 'headers':
data.count = parser.varInt();
case 'inv':
case 'getdata':
data.count = parser.varInt();
data.headers = [];
for (i = 0; i < data.count; i++) {
var header = new Block();
header.parse(parser);
data.headers.push(header);
}
break;
case 'block':
var block = new Block();
block.parse(parser);
data.block = block;
data.version = block.version;
data.prev_hash = block.prev_hash;
data.merkle_root = block.merkle_root;
data.timestamp = block.timestamp;
data.bits = block.bits;
data.nonce = block.nonce;
data.txs = block.txs;
data.size = payload.length;
break;
case 'tx':
var tx = new Transaction();
tx.parse(parser);
return {
command: command,
version: tx.version,
lock_time: tx.lock_time,
ins: tx.ins,
outs: tx.outs,
tx: tx,
};
case 'getblocks':
case 'getheaders':
// parse out the version
data.version = parser.word32le();
// TODO: Limit block locator size?
// reference implementation limits to 500 results
var startCount = parser.varInt();
data.starts = [];
for (i = 0; i < startCount; i++) {
data.starts.push(parser.buffer(32));
}
data.stop = parser.buffer(32);
break;
data.invs = [];
for (i = 0; i < data.count; i++) {
data.invs.push({
type: parser.word32le(),
hash: parser.buffer(32)
});
}
break;
case 'addr':
var addrCount = parser.varInt();
case 'headers':
data.count = parser.varInt();
// Enforce a maximum number of addresses per message
if (addrCount > 1000) {
addrCount = 1000;
}
data.headers = [];
for (i = 0; i < data.count; i++) {
var header = new Block();
header.parse(parser);
data.headers.push(header);
}
break;
data.addrs = [];
for (i = 0; i < addrCount; i++) {
// TODO: Time actually depends on the version of the other peer (>=31402)
data.addrs.push({
time: parser.word32le(),
services: parser.word64le(),
ip: parser.buffer(16),
port: parser.word16be()
});
}
break;
case 'block':
var block = new Block();
block.parse(parser);
case 'alert':
data.payload = parser.varStr();
data.signature = parser.varStr();
break;
data.block = block;
data.version = block.version;
data.prev_hash = block.prev_hash;
data.merkle_root = block.merkle_root;
data.timestamp = block.timestamp;
data.bits = block.bits;
data.nonce = block.nonce;
case 'ping':
if (this.recvVer > BIP0031_VERSION) {
data.nonce = parser.buffer(8);
}
break;
data.txs = block.txs;
case 'getaddr':
case 'verack':
case 'reject':
// Empty message, nothing to parse
break;
data.size = payload.length;
break;
default:
log.err('Connection.parseMessage(): Command not implemented',
{cmd: command});
case 'tx':
var tx = new Transaction();
tx.parse(parser);
return {
command: command,
version: tx.version,
lock_time: tx.lock_time,
ins: tx.ins,
outs: tx.outs,
tx: tx,
};
case 'getblocks':
case 'getheaders':
// parse out the version
data.version = parser.word32le();
// TODO: Limit block locator size?
// reference implementation limits to 500 results
var startCount = parser.varInt();
data.starts = [];
for (i = 0; i < startCount; i++) {
data.starts.push(parser.buffer(32));
}
data.stop = parser.buffer(32);
break;
case 'addr':
var addrCount = parser.varInt();
// Enforce a maximum number of addresses per message
if (addrCount > 1000) {
addrCount = 1000;
}
data.addrs = [];
for (i = 0; i < addrCount; i++) {
// TODO: Time actually depends on the version of the other peer (>=31402)
data.addrs.push({
time: parser.word32le(),
services: parser.word64le(),
ip: parser.buffer(16),
port: parser.word16be()
});
}
break;
case 'alert':
data.payload = parser.varStr();
data.signature = parser.varStr();
break;
case 'ping':
if (this.recvVer > BIP0031_VERSION) {
data.nonce = parser.buffer(8);
}
break;
case 'getaddr':
case 'verack':
case 'reject':
// Empty message, nothing to parse
break;
default:
log.err('Connection.parseMessage(): Command not implemented', {
cmd: command
});
// This tells the calling function not to issue an event
return null;
// This tells the calling function not to issue an event
return null;
}
return data;

15
lib/Curve.js

@ -3,11 +3,12 @@ var imports = require('soop');
var bignum = imports.bignum || require('bignum');
var Point = imports.Point || require('./Point');
var n = bignum.fromBuffer(new Buffer("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 'hex'), {size: 32});
var n = bignum.fromBuffer(new Buffer("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 'hex'), {
size: 32
});
var Curve = function() {
};
var Curve = function() {};
/* secp256k1 curve */
var G;
@ -16,8 +17,12 @@ Curve.getG = function() {
// when Point is not loaded yet
// use cached version if available
G = G || new Point(bignum.fromBuffer(new Buffer("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 'hex'), {size: 32}),
bignum.fromBuffer(new Buffer("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 'hex'), {size: 32}));
G = G || new Point(bignum.fromBuffer(new Buffer("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 'hex'), {
size: 32
}),
bignum.fromBuffer(new Buffer("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 'hex'), {
size: 32
}));
return G;
};

5
lib/Deserialize.js

@ -1,8 +1,5 @@
exports.intFromCompact = function(c)
{
exports.intFromCompact = function(c) {
var bytes = ((c >>> 24) & 0xff) >>> 0;
var v = ((c & 0xffffff) << (8 * (bytes - 3))) >>> 0;
return v;
}

26
lib/Electrum.js

@ -12,19 +12,23 @@ var Key = require('./Key'),
*
* @example examples/ElectrumMPK.js
*/
function Electrum (master_public_key) {
function Electrum(master_public_key) {
this.mpk = new Buffer(master_public_key, 'hex');
}
Electrum.prototype.getSequence = function (for_change, n) {
Electrum.prototype.getSequence = function(for_change, n) {
var mode = for_change ? 1 : 0;
var buf = Buffer.concat([ new Buffer(n + ':' + mode + ':', 'utf8'), this.mpk ]);
var buf = Buffer.concat([new Buffer(n + ':' + mode + ':', 'utf8'), this.mpk]);
return bignum.fromBuffer(twoSha256(buf));
};
Electrum.prototype.generatePubKey = function (n, for_change) {
var x = bignum.fromBuffer(this.mpk.slice(0, 32), { size: 32 });
var y = bignum.fromBuffer(this.mpk.slice(32, 64), { size: 32 });
Electrum.prototype.generatePubKey = function(n, for_change) {
var x = bignum.fromBuffer(this.mpk.slice(0, 32), {
size: 32
});
var y = bignum.fromBuffer(this.mpk.slice(32, 64), {
size: 32
});
var mpk_pt = new Point(x, y);
var sequence = this.getSequence(for_change, n);
@ -37,8 +41,12 @@ Electrum.prototype.generatePubKey = function (n, for_change) {
pt = Point.add(mpk_pt, sequence_pt);
var xbuf = pt.x.toBuffer({ size: 32 });
var ybuf = pt.y.toBuffer({ size: 32 });
var xbuf = pt.x.toBuffer({
size: 32
});
var ybuf = pt.y.toBuffer({
size: 32
});
var prefix = new Buffer([0x04]);
var key = new Key();
@ -48,7 +56,7 @@ Electrum.prototype.generatePubKey = function (n, for_change) {
return key.public;
};
Electrum.prototype.generateChangePubKey = function (sequence) {
Electrum.prototype.generateChangePubKey = function(sequence) {
return this.generatePubKey(sequence, true);
};

106
lib/HierarchicalKey.js

@ -19,8 +19,7 @@ var HierarchicalKey = function(bytes) {
if (typeof bytes == 'undefined' || bytes == 'mainnet' || bytes == 'livenet') {
bytes = 'livenet';
this.version = networks['livenet'].hkeyPrivateVersion;
}
else if (bytes == 'testnet') {
} else if (bytes == 'testnet') {
this.version = networks['testnet'].hkeyPrivateVersion;
}
if (bytes == 'livenet' || bytes == 'testnet') {
@ -35,12 +34,12 @@ var HierarchicalKey = function(bytes) {
this.buildExtendedPrivateKey();
return;
}
// decode base58
if (typeof bytes === 'string') {
var decoded = base58.decode(bytes);
if (decoded.length != 82)
throw new Error('Not enough data, expected 82 and received '+decoded.length);
throw new Error('Not enough data, expected 82 and received ' + decoded.length);
var checksum = decoded.slice(78, 82);
bytes = decoded.slice(0, 78);
@ -51,7 +50,7 @@ var HierarchicalKey = function(bytes) {
}
}
if (bytes !== undefined && bytes !== null)
if (bytes !== undefined && bytes !== null)
this.initFromBytes(bytes);
}
@ -61,9 +60,9 @@ HierarchicalKey.seed = function(bytes, network) {
if (!Buffer.isBuffer(bytes))
bytes = new Buffer(bytes, 'hex'); //if not buffer, assume hex
if (bytes.length < 128/8)
if (bytes.length < 128 / 8)
return false; //need more entropy
if (bytes.length > 512/8)
if (bytes.length > 512 / 8)
return false;
var hash = coinUtil.sha512hmac(bytes, new Buffer('Bitcoin seed'));
@ -87,23 +86,23 @@ HierarchicalKey.seed = function(bytes, network) {
HierarchicalKey.prototype.initFromBytes = function(bytes) {
// Both pub and private extended keys are 78 bytes
if(bytes.length != 78) throw new Error('not enough data');
if (bytes.length != 78) throw new Error('not enough data');
this.version = u32(bytes.slice(0, 4));
this.depth = u8(bytes.slice(4, 5));
this.version = u32(bytes.slice(0, 4));
this.depth = u8(bytes.slice(4, 5));
this.parentFingerprint = bytes.slice(5, 9);
this.childIndex = u32(bytes.slice(9, 13));
this.chainCode = bytes.slice(13, 45);
this.childIndex = u32(bytes.slice(9, 13));
this.chainCode = bytes.slice(13, 45);
var keyBytes = bytes.slice(45, 78);
var isPrivate =
(this.version == networks['livenet'].hkeyPrivateVersion ||
this.version == networks['testnet'].hkeyPrivateVersion );
var isPrivate =
(this.version == networks['livenet'].hkeyPrivateVersion ||
this.version == networks['testnet'].hkeyPrivateVersion);
var isPublic =
(this.version == networks['livenet'].hkeyPublicVersion ||
this.version == networks['testnet'].hkeyPublicVersion );
var isPublic =
(this.version == networks['livenet'].hkeyPublicVersion ||
this.version == networks['testnet'].hkeyPublicVersion);
if (isPrivate && keyBytes[0] == 0) {
this.eckey = new Key();
@ -129,17 +128,17 @@ HierarchicalKey.prototype.buildExtendedPublicKey = function() {
this.extendedPublicKey = new Buffer([]);
var v = null;
switch(this.version) {
case networks['livenet'].hkeyPublicVersion:
case networks['livenet'].hkeyPrivateVersion:
v = networks['livenet'].hkeyPublicVersion;
break;
case networks['testnet'].hkeyPublicVersion:
case networks['testnet'].hkeyPrivateVersion:
v = networks['testnet'].hkeyPublicVersion;
break;
default:
throw new Error('Unknown version');
switch (this.version) {
case networks['livenet'].hkeyPublicVersion:
case networks['livenet'].hkeyPrivateVersion:
v = networks['livenet'].hkeyPublicVersion;
break;
case networks['testnet'].hkeyPublicVersion:
case networks['testnet'].hkeyPrivateVersion:
v = networks['testnet'].hkeyPublicVersion;
break;
default:
throw new Error('Unknown version');
}
// Version
@ -220,12 +219,12 @@ HierarchicalKey.prototype.derive = function(path) {
for (var i in e) {
var c = e[i];
if (i == 0 ) {
if (i == 0) {
if (c != 'm') throw new Error('invalid path');
continue;
}
var usePrivate = (c.length > 1) && (c[c.length-1] == '\'');
var usePrivate = (c.length > 1) && (c[c.length - 1] == '\'');
var childIndex = parseInt(usePrivate ? c.slice(0, c.length - 1) : c) & 0x7fffffff;
if (usePrivate)
@ -241,15 +240,15 @@ HierarchicalKey.prototype.deriveChild = function(i) {
var ib = [];
ib.push((i >> 24) & 0xff);
ib.push((i >> 16) & 0xff);
ib.push((i >> 8) & 0xff);
ib.push((i >> 8) & 0xff);
ib.push(i & 0xff);
ib = new Buffer(ib);
var usePrivate = (i & 0x80000000) != 0;
var isPrivate =
(this.version == networks['livenet'].hkeyPrivateVersion ||
this.version == networks['testnet'].hkeyPrivateVersion );
var isPrivate =
(this.version == networks['livenet'].hkeyPrivateVersion ||
this.version == networks['testnet'].hkeyPrivateVersion);
if (usePrivate && (!this.hasPrivateKey || !isPrivate))
throw new Error('Cannot do private key derivation without private key');
@ -265,18 +264,24 @@ HierarchicalKey.prototype.deriveChild = function(i) {
}
var hash = coinUtil.sha512hmac(data, this.chainCode);
var il = bignum.fromBuffer(hash.slice(0, 32), {size: 32});
var il = bignum.fromBuffer(hash.slice(0, 32), {
size: 32
});
var ir = hash.slice(32, 64);
// ki = IL + kpar (mod n).
var priv = bignum.fromBuffer(this.eckey.private, {size: 32});
var priv = bignum.fromBuffer(this.eckey.private, {
size: 32
});
var k = il.add(priv).mod(secp256k1_n);
ret = new HierarchicalKey(null);
ret.chainCode = ir;
ret.eckey = new Key();
ret.eckey.private = k.toBuffer({size: 32});
ret.eckey.private = k.toBuffer({
size: 32
});
ret.eckey.regenerateSync();
ret.hasPrivateKey = true;
@ -302,14 +307,14 @@ HierarchicalKey.prototype.deriveChild = function(i) {
ret.chainCode = new Buffer(ir);
var eckey = new Key();
eckey.public = newpub;
eckey.public = newpub;
eckey.compressed = true;
ret.eckey = eckey;
ret.hasPrivateKey = false;
}
ret.childIndex = i;
ret.parentFingerprint = this.pubKeyHash.slice(0,4);
ret.parentFingerprint = this.pubKeyHash.slice(0, 4);
ret.version = this.version;
ret.depth = this.depth + 1;
@ -334,9 +339,20 @@ function uint(f, size) {
return n;
}
function u8(f) {return uint(f,1);}
function u16(f) {return uint(f,2);}
function u32(f) {return uint(f,4);}
function u64(f) {return uint(f,8);}
function u8(f) {
return uint(f, 1);
}
function u16(f) {
return uint(f, 2);
}
function u32(f) {
return uint(f, 4);
}
function u64(f) {
return uint(f, 8);
}
module.exports = require('soop')(HierarchicalKey);

3
lib/Message.js

@ -3,8 +3,7 @@ var imports = require('soop').imports();
var coinUtil = imports.coinUtil || require('../util');
var Key = imports.Key || require('./Key');
var Message = function() {
};
var Message = function() {};
Message.sign = function(str, key) {
var hash = Message.magicHash(str);

244
lib/Opcode.js

@ -1,156 +1,156 @@
var imports = require('soop').imports();
var imports = require('soop').imports();
function Opcode(num) {
this.code = num;
};
Opcode.prototype.toString = function () {
Opcode.prototype.toString = function() {
return Opcode.reverseMap[this.code];
};
Opcode.map = {
// push value
OP_FALSE : 0,
OP_0 : 0,
OP_PUSHDATA1 : 76,
OP_PUSHDATA2 : 77,
OP_PUSHDATA4 : 78,
OP_1NEGATE : 79,
OP_RESERVED : 80,
OP_TRUE : 81,
OP_1 : 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,
OP_FALSE: 0,
OP_0: 0,
OP_PUSHDATA1: 76,
OP_PUSHDATA2: 77,
OP_PUSHDATA4: 78,
OP_1NEGATE: 79,
OP_RESERVED: 80,
OP_TRUE: 81,
OP_1: 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,
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,
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,
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,
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,
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_WITHIN : 165,
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_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,
// 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,
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,
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
OP_PUBKEYHASH: 253,
OP_PUBKEY: 254,
OP_INVALIDOPCODE: 255
};
Opcode.reverseMap = [];
for (var k in Opcode.map) {
if(Opcode.map.hasOwnProperty(k)) {
if (Opcode.map.hasOwnProperty(k)) {
Opcode.reverseMap[Opcode.map[k]] = k.substr(3);
}
}

18
lib/Peer.js

@ -1,7 +1,7 @@
var imports = require('soop').imports();
var imports = require('soop').imports();
var Net = imports.Net || require('net');
var Binary = imports.Binary || require('binary');
var Net = imports.Net || require('net');
var Binary = imports.Binary || require('binary');
var buffertools = imports.buffertools || require('buffertools');
function Peer(host, port, services) {
@ -24,29 +24,29 @@ function Peer(host, port, services) {
this.port = +port || 8333;
} else {
throw new Error('Could not instantiate peer, invalid parameter type: ' +
typeof host);
typeof host);
}
this.services = (services) ? services : null;
this.lastSeen = 0;
};
Peer.IPV6_IPV4_PADDING = new Buffer([0,0,0,0,0,0,0,0,0,0,255,255]);
Peer.IPV6_IPV4_PADDING = new Buffer([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255]);
Peer.prototype.createConnection = function () {
Peer.prototype.createConnection = function() {
this.connection = Net.createConnection(this.port, this.host);
return this.connection;
};
Peer.prototype.getHostAsBuffer = function () {
Peer.prototype.getHostAsBuffer = function() {
return new Buffer(this.host.split('.'));
};
Peer.prototype.toString = function () {
Peer.prototype.toString = function() {
return this.host + ":" + this.port;
};
Peer.prototype.toBuffer = function () {
Peer.prototype.toBuffer = function() {
var put = Binary.put();
put.word32le(this.lastSeen);
put.word64le(this.services);

81
lib/PeerManager.js

@ -1,10 +1,10 @@
var imports = require('soop').imports();
var log = imports.log || require('../util/log');
var imports = require('soop').imports();
var log = imports.log || require('../util/log');
var bitcoreDefaults = imports.config || require('../config');
var Connection = imports.Connection || require ('./Connection');
var Peer = imports.Peer || require('./Peer');
var Connection = imports.Connection || require('./Connection');
var Peer = imports.Peer || require('./Peer');
GetAdjustedTime = imports.GetAdjustedTime || function () {
GetAdjustedTime = imports.GetAdjustedTime || function() {
// TODO: Implement actual adjustment
return Math.floor(new Date().getTime() / 1000);
};
@ -42,36 +42,37 @@ PeerManager.Connection = Connection;
PeerManager.prototype.start = function() {
this.active = true;
if(!this.timer) {
if (!this.timer) {
this.timer = setInterval(this.checkStatus.bind(this), this.interval);
}
};
PeerManager.prototype.stop = function() {
this.active = false;
if(this.timer) {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
for(var i=0; i<this.connections.length; i++) {
for (var i = 0; i < this.connections.length; i++) {
this.connections[i].socket.end();
};
};
PeerManager.prototype.addPeer = function(peer, port) {
if(peer instanceof Peer) {
if (peer instanceof Peer) {
this.peers.push(peer);
} else if ("string" == typeof peer) {
this.addPeer(new Peer(peer, port));
} else {
log.err('Node.addPeer(): Invalid value provided for peer',
{val: peer});
log.err('Node.addPeer(): Invalid value provided for peer', {
val: peer
});
throw 'Node.addPeer(): Invalid value provided for peer.';
}
};
PeerManager.prototype.removePeer = function(peer) {
var index = this.peers.indexOf(peer);
var index = this.peers.indexOf(peer);
var exists = !!~index;
if (exists) this.peers.splice(index, 1);
return exists;
@ -79,7 +80,7 @@ PeerManager.prototype.removePeer = function(peer) {
PeerManager.prototype.checkStatus = function checkStatus() {
// Make sure we are connected to all forcePeers
if(this.peers.length) {
if (this.peers.length) {
var peerIndex = {};
this.peers.forEach(function(peer) {
peerIndex[peer.toString()] = peer;
@ -88,7 +89,7 @@ PeerManager.prototype.checkStatus = function checkStatus() {
// Ignore the ones we're already connected to
this.connections.forEach(function(conn) {
var peerName = conn.peer.toString();
if("undefined" !== peerIndex[peerName]) {
if ("undefined" !== peerIndex[peerName]) {
delete peerIndex[peerName];
}
});
@ -111,7 +112,7 @@ PeerManager.prototype.connectTo = function(peer) {
try {
return this.addConnection(peer.createConnection(), peer);
} catch (e) {
log.err('creating connection',e);
log.err('creating connection', e);
return null;
}
};
@ -139,15 +140,15 @@ PeerManager.prototype.handleVersion = function(e) {
// TODO: Advertise our address (if listening)
}
// Get recent addresses
if(this.peerDiscovery &&
(e.message.version >= 31402 || this.peers.length < 1000)) {
if (this.peerDiscovery &&
(e.message.version >= 31402 || this.peers.length < 1000)) {
e.conn.sendGetAddr();
e.conn.getaddr = true;
}
};
PeerManager.prototype.handleReady = function (e) {
log.info('connected to '+e.conn.peer.host+':'+e.conn.peer.port);
PeerManager.prototype.handleReady = function(e) {
log.info('connected to ' + e.conn.peer.host + ':' + e.conn.peer.port);
this.emit('connect', {
pm: this,
conn: e.conn,
@ -155,17 +156,17 @@ PeerManager.prototype.handleReady = function (e) {
peer: e.peer
});
if(this.isConnected == false) {
if (this.isConnected == false) {
this.emit('netConnected', e);
this.isConnected = true;
}
};
PeerManager.prototype.handleAddr = function (e) {
if(!this.peerDiscovery) return;
PeerManager.prototype.handleAddr = function(e) {
if (!this.peerDiscovery) return;
var now = GetAdjustedTime();
e.message.addrs.forEach(function (addr) {
e.message.addrs.forEach(function(addr) {
try {
// In case of an invalid time, assume "5 days ago"
if (addr.time <= 100000000 || addr.time > (now + 10 * 60)) {
@ -178,11 +179,11 @@ PeerManager.prototype.handleAddr = function (e) {
this.peers.push(peer);
// TODO: Handle addr relay
} catch(e) {
log.warn("Invalid addr received: "+e.message);
} catch (e) {
log.warn("Invalid addr received: " + e.message);
}
}.bind(this));
if (e.message.addrs.length < 1000 ) {
if (e.message.addrs.length < 1000) {
e.conn.getaddr = false;
}
};
@ -192,14 +193,14 @@ PeerManager.prototype.handleGetAddr = function(e) {
};
PeerManager.prototype.handleError = function(e) {
log.err('unkown error with peer '+e.peer+' (disconnecting): '+e.err);
log.err('unkown error with peer ' + e.peer + ' (disconnecting): ' + e.err);
this.handleDisconnect.apply(this, [].slice.call(arguments));
};
PeerManager.prototype.handleDisconnect = function(e) {
log.info('disconnected from peer ' + e.peer);
var i = this.connections.indexOf(e.conn);
if(i != -1) this.connections.splice(i, 1);
if (i != -1) this.connections.splice(i, 1);
this.removePeer(e.peer);
if (this.pool.length) {
@ -207,19 +208,19 @@ PeerManager.prototype.handleDisconnect = function(e) {
this.addPeer(this.pool.pop());
}
if(!this.connections.length) {
if (!this.connections.length) {
this.emit('netDisconnected');
this.isConnected = false;
}
};
PeerManager.prototype.getActiveConnection = function () {
var activeConnections = this.connections.filter(function (conn) {
PeerManager.prototype.getActiveConnection = function() {
var activeConnections = this.connections.filter(function(conn) {
return conn.active;
});
if (activeConnections.length) {
var randomIndex = Math.floor(Math.random()*activeConnections.length);
var randomIndex = Math.floor(Math.random() * activeConnections.length);
var candidate = activeConnections[randomIndex];
if (candidate.socket.writable) {
return candidate;
@ -237,16 +238,16 @@ PeerManager.prototype.getActiveConnection = function () {
}
};
PeerManager.prototype.getActiveConnections = function () {
PeerManager.prototype.getActiveConnections = function() {
return this.connections.slice(0);
};
PeerManager.prototype.discover = function(options, callback) {
var self = this;
var async = imports.async || require('async');
var dns = imports.dns || require('dns');
var self = this;
var async = imports.async || require('async');
var dns = imports.dns || require('dns');
var networks = imports.networks || require('../networks');
var seeds = networks[self.config.network].dnsSeeds;
var seeds = networks[self.config.network].dnsSeeds;
self.limit = options.limit || 12;
@ -264,16 +265,16 @@ PeerManager.prototype.discover = function(options, callback) {
return done(null, []);
}
log.info('resolving dns seed '+ seed);
log.info('resolving dns seed ' + seed);
dns.resolve(seed, function(err, peers) {
if (err) {
log.err('failed to resolve dns seed '+ seed, err);
log.err('failed to resolve dns seed ' + seed, err);
self.seeds.failed.push(seed);
return done(null, []);
}
log.info('found '+ peers.length + ' peers from ' + seed);
log.info('found ' + peers.length + ' peers from ' + seed);
self.seeds.resolved.push(seed);
// transform that list into a list of Peer instances

16
lib/Point.js

@ -28,15 +28,23 @@ Point.multiply = function(p1, x) {
//convert the public key of a Key into a Point
Point.fromUncompressedPubKey = function(pubkey) {
var point = new Point();
point.x = bignum.fromBuffer(pubkey.slice(1, 33), {size: 32});
point.y = bignum.fromBuffer(pubkey.slice(33, 65), {size: 32});
point.x = bignum.fromBuffer(pubkey.slice(1, 33), {
size: 32
});
point.y = bignum.fromBuffer(pubkey.slice(33, 65), {
size: 32
});
return point;
};
//convert the Point into the Key containing a compressed public key
Point.prototype.toUncompressedPubKey = function() {
var xbuf = this.x.toBuffer({size: 32});
var ybuf = this.y.toBuffer({size: 32});
var xbuf = this.x.toBuffer({
size: 32
});
var ybuf = this.y.toBuffer({
size: 32
});
var prefix = new Buffer([0x04]);
var pubkey = Buffer.concat([prefix, xbuf, ybuf]);
return pubkey;

43
lib/PrivateKey.js

@ -1,7 +1,7 @@
var imports = require('soop').imports();
var imports = require('soop').imports();
var parent = imports.parent || require('../util/VersionedData');
var networks= imports.networks || require('../networks');
var networks = imports.networks || require('../networks');
//compressed is true if public key is compressed; false otherwise
function PrivateKey(version, buf, compressed) {
@ -16,7 +16,7 @@ parent.applyEncodingsTo(PrivateKey);
PrivateKey.prototype.validate = function() {
this.doAsBinary(function() {
PrivateKey.super(this, 'validate', arguments);
if (this.data.length < 32 || (this.data.length > 1+32 && !this.compressed()) || (this.data.length==1+32+1 && this.data[1+32+1-1]!=1) || this.data.length>1+32+1)
if (this.data.length < 32 || (this.data.length > 1 + 32 && !this.compressed()) || (this.data.length == 1 + 32 + 1 && this.data[1 + 32 + 1 - 1] != 1) || this.data.length > 1 + 32 + 1)
throw new Error('invalid data length');
});
if (typeof this.network() === 'undefined') throw new Error('invalid network');
@ -25,38 +25,39 @@ PrivateKey.prototype.validate = function() {
// get or set the payload data (as a Buffer object)
// overloaded from VersionedData
PrivateKey.prototype.payload = function(data) {
if(data) {
this.doAsBinary(function() {data.copy(this.data,1);});
if (data) {
this.doAsBinary(function() {
data.copy(this.data, 1);
});
return data;
}
var buf=this.as('binary');
if (buf.length==1+32+1)
return buf.slice(1,1+32);
else if (buf.length==1+32)
var buf = this.as('binary');
if (buf.length == 1 + 32 + 1)
return buf.slice(1, 1 + 32);
else if (buf.length == 1 + 32)
return buf.slice(1);
};
// get or set whether the corresponding public key is compressed
PrivateKey.prototype.compressed = function(compressed) {
if (compressed !== undefined) {
this.doAsBinary(function(){
var len=1+32+1;
this.doAsBinary(function() {
var len = 1 + 32 + 1;
if (compressed) {
var data=new Buffer(len);
var data = new Buffer(len);
this.data.copy(data);
this.data=data;
this.data[len-1]=1;
this.data = data;
this.data[len - 1] = 1;
} else {
this.data=this.data.slice(0,len-1);
this.data = this.data.slice(0, len - 1);
}
});
}
else {
var len=1+32+1;
var data=this.as('binary');
if (data.length==len && data[len-1]==1)
} else {
var len = 1 + 32 + 1;
var data = this.as('binary');
if (data.length == len && data[len - 1] == 1)
return true;
else if (data.length==len-1)
else if (data.length == len - 1)
return false;
else
throw new Error('invalid private key');

72
lib/RpcClient.js

@ -3,9 +3,9 @@
// Copyright 2013 BitPay, Inc.
//
var imports = require('soop').imports();
var http = imports.http || require('http');
var https = imports.https || require('https');
var log = imports.log || require('../util/log');
var http = imports.http || require('http');
var https = imports.https || require('https');
var log = imports.log || require('../util/log');
function RpcClient(opts) {
opts = opts || {};
@ -15,9 +15,9 @@ function RpcClient(opts) {
this.pass = opts.pass || 'pass';
this.protocol = (opts.protocol == 'http') ? http : https;
this.batchedCalls = null;
this.disableAgent = opts.disableAgent || false;
this.disableAgent = opts.disableAgent || false;
}
RpcClient.prototype.batch = function(batchCallback, resultCallback) {
this.batchedCalls = [];
batchCallback();
@ -77,7 +77,7 @@ var callspec = {
lockUnspent: '',
move: 'str str float int str',
sendFrom: 'str str float int str str',
sendMany: 'str str int str', //not sure this is will work
sendMany: 'str str int str', //not sure this is will work
sendRawTransaction: '',
sendToAddress: 'str float str str',
setAccount: '',
@ -102,30 +102,45 @@ function generateRPCMethods(constructor, apiCalls, rpc) {
function createRPCMethod(methodName, argMap) {
return function() {
var limit = arguments.length - 1;
if(this.batchedCalls) var limit = arguments.length;
for (var i=0; i<limit; i++) {
if(argMap[i]) arguments[i] = argMap[i](arguments[i]);
if (this.batchedCalls) var limit = arguments.length;
for (var i = 0; i < limit; i++) {
if (argMap[i]) arguments[i] = argMap[i](arguments[i]);
};
if(this.batchedCalls) {
this.batchedCalls.push({jsonrpc: '2.0', method: methodName, params: slice(arguments)});
if (this.batchedCalls) {
this.batchedCalls.push({
jsonrpc: '2.0',
method: methodName,
params: slice(arguments)
});
} else {
rpc.call(this, {method: methodName, params: slice(arguments, 0, arguments.length - 1)}, arguments[arguments.length - 1]);
rpc.call(this, {
method: methodName,
params: slice(arguments, 0, arguments.length - 1)
}, arguments[arguments.length - 1]);
}
};
};
var types = {
str: function(arg) {return arg.toString();},
int: function(arg) {return parseFloat(arg);},
float: function(arg) {return parseFloat(arg);},
bool: function(arg) {return (arg === true || arg == '1' || arg == 'true' || arg.toString().toLowerCase() == 'true');},
str: function(arg) {
return arg.toString();
},
int: function(arg) {
return parseFloat(arg);
},
float: function(arg) {
return parseFloat(arg);
},
bool: function(arg) {
return (arg === true || arg == '1' || arg == 'true' || arg.toString().toLowerCase() == 'true');
},
};
for(var k in apiCalls) {
for (var k in apiCalls) {
if (apiCalls.hasOwnProperty(k)) {
var spec = apiCalls[k].split(' ');
for (var i = 0; i < spec.length; i++) {
if(types[spec[i]]) {
if (types[spec[i]]) {
spec[i] = types[spec[i]];
} else {
spec[i] = types.string;
@ -149,10 +164,10 @@ function rpc(request, callback) {
path: '/',
method: 'POST',
port: self.port,
agent: self.disableAgent ? false : undefined,
agent: self.disableAgent ? false : undefined,
};
if(self.httpOptions) {
for(var k in self.httpOptions) {
if (self.httpOptions) {
for (var k in self.httpOptions) {
options[k] = self.httpOptions[k];
}
}
@ -161,25 +176,25 @@ function rpc(request, callback) {
var buf = '';
res.on('data', function(data) {
buf += data;
buf += data;
});
res.on('end', function() {
if(res.statusCode == 401) {
if (res.statusCode == 401) {
callback(new Error('bitcoin JSON-RPC connection rejected: 401 unauthorized'));
return;
}
if(res.statusCode == 403) {
if (res.statusCode == 403) {
callback(new Error('bitcoin JSON-RPC connection rejected: 403 forbidden'));
return;
}
if(err) {
if (err) {
callback(err);
return;
}
try {
var parsedBuf = JSON.parse(buf);
} catch(e) {
} catch (e) {
log.err(e.stack);
log.err(buf);
log.err('HTTP Status code:' + res.statusCode);
@ -190,11 +205,11 @@ function rpc(request, callback) {
});
});
req.on('error', function(e) {
var err = new Error('Could not connect to bitcoin via RPC: '+e.message);
var err = new Error('Could not connect to bitcoin via RPC: ' + e.message);
log.err(err);
callback(err);
});
req.setHeader('Content-Length', request.length);
req.setHeader('Content-Type', 'application/json');
req.setHeader('Authorization', 'Basic ' + auth);
@ -205,4 +220,3 @@ function rpc(request, callback) {
generateRPCMethods(RpcClient, callspec, rpc);
module.exports = require('soop')(RpcClient);

24
lib/SIN.js

@ -1,5 +1,5 @@
var imports = require('soop').imports();
var parent = imports.parent || require('../util/VersionedData');
var parent = imports.parent || require('../util/VersionedData');
function SIN(type, payload) {
if (typeof type != 'number') {
@ -8,7 +8,7 @@ function SIN(type, payload) {
};
this.data = new Buffer(1 + 1 + payload.length);
this.__proto__ = this.encodings['binary'];
this.prefix(0x0F); // SIN magic number, in numberspace
this.prefix(0x0F); // SIN magic number, in numberspace
this.type(type);
this.payload(payload);
};
@ -17,12 +17,14 @@ parent.applyEncodingsTo(SIN);
SIN.SIN_PERSIST_MAINNET = 0x01; // associated with sacrifice TX
SIN.SIN_PERSIST_TESTNET = 0x11; // associated with sacrifice TX
SIN.SIN_EPHEM = 0x02; // generate off-net at any time
SIN.SIN_EPHEM = 0x02; // generate off-net at any time
// get or set the prefix data (the first byte of the address)
SIN.prototype.prefix = function(num) {
if(num || (num === 0)) {
this.doAsBinary(function() {this.data.writeUInt8(num, 0);});
if (num || (num === 0)) {
this.doAsBinary(function() {
this.data.writeUInt8(num, 0);
});
return num;
}
return this.as('binary').readUInt8(0);
@ -30,8 +32,10 @@ SIN.prototype.prefix = function(num) {
// get or set the SIN-type data (the second byte of the address)
SIN.prototype.type = function(num) {
if(num || (num === 0)) {
this.doAsBinary(function() {this.data.writeUInt8(num, 1);});
if (num || (num === 0)) {
this.doAsBinary(function() {
this.data.writeUInt8(num, 1);
});
return num;
}
return this.as('binary').readUInt8(1);
@ -39,8 +43,10 @@ SIN.prototype.type = function(num) {
// get or set the payload data (as a Buffer object)
SIN.prototype.payload = function(data) {
if(data) {
this.doAsBinary(function() {data.copy(this.data, 2);});
if (data) {
this.doAsBinary(function() {
data.copy(this.data, 2);
});
return data;
}
return this.as('binary').slice(1);

6
lib/SINKey.js

@ -1,7 +1,7 @@
var coinUtil = require('../util');
var timeUtil = require('../util/time');
var coinUtil = require('../util');
var timeUtil = require('../util/time');
var Key = require('./Key');
var SIN = require('./SIN');
var SIN = require('./SIN');
function SINKey(cfg) {
if (typeof cfg != 'object')

60
lib/Script.js

@ -1,12 +1,12 @@
var imports = require('soop').imports();
var config = imports.config || require('../config');
var log = imports.log || require('../util/log');
var Opcode = imports.Opcode || require('./Opcode');
var imports = require('soop').imports();
var config = imports.config || require('../config');
var log = imports.log || require('../util/log');
var Opcode = imports.Opcode || require('./Opcode');
var buffertools = imports.buffertools || require('buffertools');
var util = imports.util || require('../util/util');
var util = imports.util || require('../util/util');
var Parser = imports.Parser || require('../util/BinaryParser');
var Put = imports.Put || require('bufferput');
var Put = imports.Put || require('bufferput');
var TX_UNKNOWN = 0;
var TX_PUBKEY = 1;
@ -110,40 +110,41 @@ function isSmallIntOp(opcode) {
Script.prototype.isMultiSig = function() {
return (this.chunks.length > 3 &&
isSmallIntOp(this.chunks[0]) &&
this.chunks.slice(1,this.chunks.length-2).every(function(i){return Buffer.isBuffer(i);}) &&
this.chunks.slice(1, this.chunks.length - 2).every(function(i) {
return Buffer.isBuffer(i);
}) &&
isSmallIntOp(this.chunks[this.chunks.length - 2]) &&
this.chunks[this.chunks.length - 1] == Opcode.map.OP_CHECKMULTISIG);
};
Script.prototype.isP2shScriptSig = function() {
if( !isSmallIntOp(this.chunks[0]) || this.chunks[0] !==0 )
if (!isSmallIntOp(this.chunks[0]) || this.chunks[0] !== 0)
return false;
var redeemScript = new Script(this.chunks[this.chunks.length-1]);
var type=redeemScript.classify();
var redeemScript = new Script(this.chunks[this.chunks.length - 1]);
var type = redeemScript.classify();
return type !== TX_UNKNOWN;
};
Script.prototype.isMultiSigScriptSig = function() {
if( !isSmallIntOp(this.chunks[0]) || this.chunks[0] !==0 )
if (!isSmallIntOp(this.chunks[0]) || this.chunks[0] !== 0)
return false;
return !this.isP2shScriptSig();
};
Script.prototype.countSignatures = function() {
var ret = 0;
var l =this.chunks.length;
var l = this.chunks.length;
// Multisig?
if (this.isMultiSigScriptSig()){
if (this.isMultiSigScriptSig()) {
ret = l - 1;
}
else if (this.isP2shScriptSig()) {
} else if (this.isP2shScriptSig()) {
ret = l - 2;
}
// p2pubkey or p2pubkeyhash
else {
ret = buffertools.compare(this.getBuffer(), util.EMPTY_BUFFER)===0?0:1;
ret = buffertools.compare(this.getBuffer(), util.EMPTY_BUFFER) === 0 ? 0 : 1;
}
return ret;
};
@ -155,14 +156,13 @@ Script.prototype.countMissingSignatures = function() {
}
var ret = 0;
var l =this.chunks.length;
var l = this.chunks.length;
// P2SH?
if (isSmallIntOp(this.chunks[0]) && this.chunks[0] ===0) {
var redeemScript = new Script(this.chunks[l-1]);
if (isSmallIntOp(this.chunks[0]) && this.chunks[0] === 0) {
var redeemScript = new Script(this.chunks[l - 1]);
if (!isSmallIntOp(redeemScript.chunks[0])) {
log.debug("Unrecognized script type");
}
else {
} else {
var nreq = redeemScript.chunks[0] - 80; //see OP_2-OP_16
ret = nreq - (l - 2); // 2-> marked 0 + redeemScript
}
@ -201,9 +201,9 @@ Script.prototype.getMultiSigInfo = function() {
}
return {
nsigs : nsigs,
npubkeys : npubkeys,
pubkeys : pubkeys
nsigs: nsigs,
npubkeys: npubkeys,
pubkeys: pubkeys
}
};
@ -567,7 +567,7 @@ Script.prototype.toHumanReadable = function() {
} else {
var opcode = Opcode.reverseMap[chunk];
if (typeof opcode === 'undefined') {
opcode = '0x'+chunk.toString(16);
opcode = '0x' + chunk.toString(16);
}
s += opcode;
}
@ -598,17 +598,17 @@ Script.stringToBuffer = function(s) {
//console.log('integer');
var data = util.intToBufferSM(integer);
buf.put(Script.chunksToBuffer([data]));
} else if (word[0] === '\'' && word[word.length-1] === '\'') {
} else if (word[0] === '\'' && word[word.length - 1] === '\'') {
// string
//console.log('string');
word = word.substring(1,word.length-1);
word = word.substring(1, word.length - 1);
var hexString = '';
for(var c=0;c<word.length;c++) {
hexString += ''+word.charCodeAt(c).toString(16);
for (var c = 0; c < word.length; c++) {
hexString += '' + word.charCodeAt(c).toString(16);
}
buf.put(Script.chunksToBuffer([new Buffer(word)]));
} else {
throw new Error('Could not parse word "' +word+'" from script "'+s+'"');
throw new Error('Could not parse word "' + word + '" from script "' + s + '"');
}
}
}

2
lib/ScriptInterpreter.js

@ -1015,7 +1015,7 @@ var checkSig = ScriptInterpreter.checkSig =
key.public = pubkey;
key.verifySignature(hash, sig, callback);
};
};
ScriptInterpreter.prototype.isCanonicalSignature = function(sig) {
// See https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623

117
lib/Sign.js

@ -1,6 +1,4 @@
function signOne(hash, addrStr, keys)
{
function signOne(hash, addrStr, keys) {
var keyObj = keys[addrStr];
var rawPrivKey = new Buffer(keyObj.priv, 'hex');
var key = new KeyModule.Key();
@ -10,8 +8,7 @@ function signOne(hash, addrStr, keys)
return signature;
}
function signTxIn(nIn, tx, txInputs, network, keys, scripts)
{
function signTxIn(nIn, tx, txInputs, network, keys, scripts) {
// locate TX input needing a signature
var txin = tx.ins[nIn];
var scriptSig = txin.getScript();
@ -55,79 +52,77 @@ function signTxIn(nIn, tx, txInputs, network, keys, scripts)
var hash = tx.hashForSignature(scriptPubKey, i, 0);
switch (txType) {
case TX_PUBKEY:
// already signed
if (scriptSig.chunks.length > 0)
return;
case TX_PUBKEY:
// already signed
if (scriptSig.chunks.length > 0)
return;
var pubkeyhash = util.sha256ripe160(scriptData[0]);
var addr = new Address(network.addressVersion, pubkeyhash);
var addrStr = addr.toString();
if (!(addrStr in keys))
throw new Error("unknown pubkey");
var pubkeyhash = util.sha256ripe160(scriptData[0]);
var addr = new Address(network.addressVersion, pubkeyhash);
var addrStr = addr.toString();
if (!(addrStr in keys))
throw new Error("unknown pubkey");
var signature = signOne(hash, addrStr, keys);
scriptSig.writeBytes(signature);
break;
var signature = signOne(hash, addrStr, keys);
scriptSig.writeBytes(signature);
break;
case TX_PUBKEYHASH:
// already signed
if (scriptSig.chunks.length > 0)
return;
case TX_PUBKEYHASH:
// already signed
if (scriptSig.chunks.length > 0)
return;
var addr = new Address(network.addressVersion, scriptData[0]);
var addrStr = addr.toString();
if (!(addrStr in keys))
throw new Error("unknown pubkey hash address");
var addr = new Address(network.addressVersion, scriptData[0]);
var addrStr = addr.toString();
if (!(addrStr in keys))
throw new Error("unknown pubkey hash address");
var signature = signOne(hash, addrStr, keys);
scriptSig.writeBytes(signature);
scriptSig.writeBytes(key.public);
break;
var signature = signOne(hash, addrStr, keys);
scriptSig.writeBytes(signature);
scriptSig.writeBytes(key.public);
break;
case TX_SCRIPTHASH:
// already signed
if (scriptSig.chunks.length > 0)
return;
case TX_SCRIPTHASH:
// already signed
if (scriptSig.chunks.length > 0)
return;
var addr = new Address(network.addressVersion, subData[0]);
var addrStr = addr.toString();
if (!(addrStr in keys))
throw new Error("unknown script(pubkey hash) address");
var signature = signOne(hash, addrStr, keys);
scriptSig.writeBytes(signature);
scriptSig.writeBytes(key.public);
break;
case TX_MULTISIG:
while (scriptSig.chunks.length < scriptData.length) {
scriptSig.writeBytes(util.EMPTY_BUFFER);
}
for (var i = 0; i < scriptData.length; i++) {
// skip already signed
if (scriptSig.chunks[i].length > 0)
continue;
var pubkeyhash = util.sha256ripe160(scriptSig.chunks[i]);
var addr = new Address(network.addressVersion, pubkeyhash);
var addr = new Address(network.addressVersion, subData[0]);
var addrStr = addr.toString();
if (!(addrStr in keys))
continue;
throw new Error("unknown script(pubkey hash) address");
var signature = signOne(hash, addrStr, keys);
scriptSig.chunks[i] = signature;
}
break;
scriptSig.writeBytes(signature);
scriptSig.writeBytes(key.public);
break;
case TX_MULTISIG:
while (scriptSig.chunks.length < scriptData.length) {
scriptSig.writeBytes(util.EMPTY_BUFFER);
}
for (var i = 0; i < scriptData.length; i++) {
// skip already signed
if (scriptSig.chunks[i].length > 0)
continue;
var pubkeyhash = util.sha256ripe160(scriptSig.chunks[i]);
var addr = new Address(network.addressVersion, pubkeyhash);
var addrStr = addr.toString();
if (!(addrStr in keys))
continue;
var signature = signOne(hash, addrStr, keys);
scriptSig.chunks[i] = signature;
}
break;
}
if (txtype == TX_SCRIPTHASH)
scriptSig.writeBytes(subscriptRaw);
}
exports.Transaction = function Transaction(tx, txInputs, network, keys, scripts)
{
exports.Transaction = function Transaction(tx, txInputs, network, keys, scripts) {
for (var i = 0; i < tx.ins.length; i++)
signTxIn(i, tx, txInputs, network, keys, scripts);
};

16
lib/Transaction.js

@ -199,13 +199,13 @@ Transaction.prototype.getHash = function getHash() {
};
Transaction.prototype.calcNormalizedHash = function () {
this.normalizedHash = this.hashForSignature(new Script(),0, SIGHASH_ALL);
Transaction.prototype.calcNormalizedHash = function() {
this.normalizedHash = this.hashForSignature(new Script(), 0, SIGHASH_ALL);
return this.normalizedHash;
};
Transaction.prototype.getNormalizedHash = function () {
Transaction.prototype.getNormalizedHash = function() {
if (!this.normalizedHash || !this.normalizedHash.length) {
this.normalizedHash = this.calcNormalizedHash();
}
@ -403,7 +403,7 @@ var oneBuffer = function() {
// see https://bitcointalk.org/index.php?topic=260595
var ret = new Buffer(32);
ret.writeUInt8(1, 0);
for (var i=1; i<32; i++) ret.writeUInt8(0, i);
for (var i = 1; i < 32; i++) ret.writeUInt8(0, i);
return ret; // return 1 bug
};
@ -586,7 +586,7 @@ Transaction.prototype.calcSize = function() {
return totalSize;
};
Transaction.prototype.getSize = function () {
Transaction.prototype.getSize = function() {
if (!this.size) {
this.size = this.calcSize();
}
@ -609,17 +609,17 @@ Transaction.prototype.countInputMissingSignatures = function(index) {
// Works on p2pubkey, p2pubkeyhash & p2sh (no normal multisig)
Transaction.prototype.isInputComplete = function(index) {
var m = this.countInputMissingSignatures(index);
if (m===null) return null;
if (m === null) return null;
return m === 0;
};
// Works on p2pubkey, p2pubkeyhash & p2sh (no normal multisig)
Transaction.prototype.isComplete = function() {
var ret = true;
var l = this.ins.length;
var l = this.ins.length;
for (var i = 0; i < l; i++) {
if (!this.isInputComplete(i)){
if (!this.isInputComplete(i)) {
ret = false;
break;
}

397
lib/TransactionBuilder.js

@ -97,8 +97,8 @@ var FEE_PER_1000B_SAT = parseInt(0.0001 * util.COIN);
// ```
function TransactionBuilder(opts) {
opts = opts || {};
this.lockTime = opts.lockTime || 0;
opts = opts || {};
this.lockTime = opts.lockTime || 0;
this.spendUnconfirmed = opts.spendUnconfirmed || false;
if (opts.fee || opts.feeSat) {
@ -107,9 +107,9 @@ function TransactionBuilder(opts) {
this.remainderOut = opts.remainderOut;
this.signhash = opts.signhash || Transaction.SIGHASH_ALL;
this.tx = {};
this.inputsSigned= 0;
this.signaturesAdded= 0;
this.tx = {};
this.inputsSigned = 0;
this.signaturesAdded = 0;
return this;
}
@ -119,10 +119,10 @@ TransactionBuilder.FEE_PER_1000B_SAT = FEE_PER_1000B_SAT;
TransactionBuilder._scriptForPubkeys = function(out) {
var l = out.pubkeys.length;
var pubKeyBuf=[];
var pubKeyBuf = [];
for (var i=0; i<l; i++) {
pubKeyBuf.push(new Buffer(out.pubkeys[i],'hex'));
for (var i = 0; i < l; i++) {
pubKeyBuf.push(new Buffer(out.pubkeys[i], 'hex'));
}
return Script.createMultisig(out.nreq, pubKeyBuf);
@ -143,7 +143,7 @@ TransactionBuilder._scriptForOut = function(out) {
TransactionBuilder.infoForP2sh = function(opts, networkName) {
var script = this._scriptForOut(opts);
var hash = util.sha256ripe160(script.getBuffer());
var hash = util.sha256ripe160(script.getBuffer());
var version = networkName === 'testnet' ?
networks.testnet.P2SHVersion : networks.livenet.P2SHVersion;
@ -187,14 +187,14 @@ TransactionBuilder.prototype._setInputMap = function() {
var l = this.selectedUtxos.length;
for (var i = 0; i < l; i++) {
var utxo = this.selectedUtxos[i];
var scriptBuf = new Buffer(utxo.scriptPubKey, 'hex');
var scriptPubKey = new Script(scriptBuf);
var scriptType = scriptPubKey.classify();
var utxo = this.selectedUtxos[i];
var scriptBuf = new Buffer(utxo.scriptPubKey, 'hex');
var scriptPubKey = new Script(scriptBuf);
var scriptType = scriptPubKey.classify();
if (scriptType === Script.TX_UNKNOWN)
throw new Error('unkown output type at:' + i +
' Type:' + scriptPubKey.getRawOutType());
' Type:' + scriptPubKey.getRawOutType());
inputMap.push({
address: utxo.address,
@ -218,10 +218,10 @@ TransactionBuilder.prototype.getSelectedUnspent = function() {
};
/* _selectUnspent
* TODO(?): sort sel (at the end) and check is some inputs can be avoided.
* If the initial utxos are sorted, this step would be necesary only if
* utxos were selected from different minConfirmationSteps.
*/
* TODO(?): sort sel (at the end) and check is some inputs can be avoided.
* If the initial utxos are sorted, this step would be necesary only if
* utxos were selected from different minConfirmationSteps.
*/
TransactionBuilder.prototype._selectUnspent = function(neededAmountSat) {
@ -231,11 +231,11 @@ TransactionBuilder.prototype._selectUnspent = function(neededAmountSat) {
var minConfirmationSteps = [6, 1];
if (this.spendUnconfirmed) minConfirmationSteps.push(0);
var sel = [],
totalSat = bignum(0),
fulfill = false,
var sel = [],
totalSat = bignum(0),
fulfill = false,
maxConfirmations = null,
l = this.utxos.length;
l = this.utxos.length;
do {
var minConfirmations = minConfirmationSteps.shift();
@ -259,7 +259,7 @@ TransactionBuilder.prototype._selectUnspent = function(neededAmountSat) {
if (!fulfill)
throw new Error('not enough unspent tx outputs to fulfill totalNeededAmount [SAT]:' +
neededAmountSat);
neededAmountSat);
this.selectedUtxos = sel;
this._setInputMap();
@ -271,7 +271,7 @@ TransactionBuilder.prototype._setInputs = function(txobj) {
var l = ins.length;
var valueInSat = bignum(0);
txobj.ins=[];
txobj.ins = [];
for (var i = 0; i < l; i++) {
valueInSat = valueInSat.add(util.parseValue(ins[i].amount));
@ -294,7 +294,7 @@ TransactionBuilder.prototype._setInputs = function(txobj) {
};
TransactionBuilder.prototype._setFee = function(feeSat) {
if ( typeof this.valueOutSat === 'undefined')
if (typeof this.valueOutSat === 'undefined')
throw new Error('valueOutSat undefined');
@ -312,13 +312,13 @@ TransactionBuilder.prototype._setFee = function(feeSat) {
TransactionBuilder.prototype._setRemainder = function(txobj, remainderIndex) {
if ( typeof this.valueInSat === 'undefined' ||
typeof this.valueOutSat === 'undefined')
if (typeof this.valueInSat === 'undefined' ||
typeof this.valueOutSat === 'undefined')
throw new Error('valueInSat / valueOutSat undefined');
/* add remainder (without modifying outs[]) */
var remainderSat = this.valueInSat.sub(this.valueOutSat).sub(this.feeSat);
var l =txobj.outs.length;
var l = txobj.outs.length;
this.remainderSat = bignum(0);
/*remove old remainder? */
@ -344,7 +344,8 @@ TransactionBuilder.prototype._setRemainder = function(txobj, remainderIndex) {
TransactionBuilder.prototype._setFeeAndRemainder = function(txobj) {
/* starting size estimation */
var size = 500, maxSizeK, remainderIndex = txobj.outs.length;
var size = 500,
maxSizeK, remainderIndex = txobj.outs.length;
do {
/* based on https://en.bitcoin.it/wiki/Transaction_fees */
maxSizeK = parseInt(size / 1000) + 1;
@ -355,11 +356,11 @@ TransactionBuilder.prototype._setFeeAndRemainder = function(txobj) {
var neededAmountSat = this.valueOutSat.add(feeSat);
this._selectUnspent(neededAmountSat)
._setInputs(txobj)
._setFee(feeSat)
._setRemainder(txobj, remainderIndex);
._setInputs(txobj)
._setFee(feeSat)
._setRemainder(txobj, remainderIndex);
size = new Transaction(txobj).getSize();
} while (size > (maxSizeK + 1) * 1000);
return this;
@ -383,13 +384,13 @@ TransactionBuilder.prototype._setFeeAndRemainder = function(txobj) {
TransactionBuilder.prototype.setOutputs = function(outs) {
var valueOutSat = bignum(0);
var txobj = {};
txobj.version = 1;
txobj.lock_time = this.lockTime || 0;
txobj.ins = [];
var txobj = {};
txobj.version = 1;
txobj.lock_time = this.lockTime || 0;
txobj.ins = [];
txobj.outs = [];
var l =outs.length;
var l = outs.length;
for (var i = 0; i < l; i++) {
var amountSat = outs[i].amountSat || util.parseValue(outs[i].amount);
var value = util.bigIntToValue(amountSat);
@ -422,13 +423,15 @@ TransactionBuilder._mapKeys = function(keys) {
if (typeof k === 'string') {
var pk = new PrivateKey(k);
wk = new WalletKey({ network: pk.network() });
wk.fromObj({ priv: k });
}
else if (k instanceof WalletKey) {
wk = new WalletKey({
network: pk.network()
});
wk.fromObj({
priv: k
});
} else if (k instanceof WalletKey) {
wk = k;
}
else {
} else {
throw new Error('argument must be an array of strings (WIF format) or WalletKey objects');
}
walletKeyMap[wk.storeObj().addr] = wk;
@ -437,30 +440,31 @@ TransactionBuilder._mapKeys = function(keys) {
};
TransactionBuilder._signHashAndVerify = function(wk, txSigHash) {
var triesLeft = 10, sigRaw;
var triesLeft = 10,
sigRaw;
do {
sigRaw = wk.privKey.signSync(txSigHash);
} while (wk.privKey.verifySignatureSync(txSigHash, sigRaw) === false &&
triesLeft--);
triesLeft--);
if (triesLeft<0)
if (triesLeft < 0)
throw new Error('could not sign input: verification failed');
return sigRaw;
};
TransactionBuilder.prototype._checkTx = function() {
if (! this.tx || !this.tx.ins.length || !this.tx.outs.length)
if (!this.tx || !this.tx.ins.length || !this.tx.outs.length)
throw new Error('tx is not defined');
};
TransactionBuilder.prototype._multiFindKey = function(walletKeyMap,pubKeyHash) {
TransactionBuilder.prototype._multiFindKey = function(walletKeyMap, pubKeyHash) {
var wk;
[ networks.livenet, networks.testnet].forEach(function(n) {
[ n.addressVersion, n.P2SHVersion].forEach(function(v) {
var a = new Address(v,pubKeyHash);
[networks.livenet, networks.testnet].forEach(function(n) {
[n.addressVersion, n.P2SHVersion].forEach(function(v) {
var a = new Address(v, pubKeyHash);
if (!wk && walletKeyMap[a]) {
wk = walletKeyMap[a];
}
@ -474,14 +478,12 @@ TransactionBuilder.prototype._findWalletKey = function(walletKeyMap, input) {
var wk;
if (input.address) {
wk = walletKeyMap[input.address];
}
else if (input.pubKeyHash) {
wk = this._multiFindKey(walletKeyMap, input.pubKeyHash);
}
else if (input.pubKeyBuf) {
wk = walletKeyMap[input.address];
} else if (input.pubKeyHash) {
wk = this._multiFindKey(walletKeyMap, input.pubKeyHash);
} else if (input.pubKeyBuf) {
var pubKeyHash = util.sha256ripe160(input.pubKeyBuf);
wk = this._multiFindKey(walletKeyMap, pubKeyHash);
wk = this._multiFindKey(walletKeyMap, pubKeyHash);
} else {
throw new Error('no infomation at input to find keys');
}
@ -491,37 +493,45 @@ TransactionBuilder.prototype._findWalletKey = function(walletKeyMap, input) {
TransactionBuilder.prototype._signPubKey = function(walletKeyMap, input, txSigHash) {
if (this.tx.ins[input.i].s.length > 0) return {};
var wk = this._findWalletKey(walletKeyMap, input);
var wk = this._findWalletKey(walletKeyMap, input);
if (!wk) return;
var sigRaw = TransactionBuilder._signHashAndVerify(wk, txSigHash);
var sigType = new Buffer(1);
sigType[0] = this.signhash;
var sig = Buffer.concat([sigRaw, sigType]);
var sigRaw = TransactionBuilder._signHashAndVerify(wk, txSigHash);
var sigType = new Buffer(1);
sigType[0] = this.signhash;
var sig = Buffer.concat([sigRaw, sigType]);
var scriptSig = new Script();
scriptSig.chunks.push(sig);
scriptSig.updateBuffer();
return {inputFullySigned: true, signaturesAdded: 1, script: scriptSig.getBuffer()};
return {
inputFullySigned: true,
signaturesAdded: 1,
script: scriptSig.getBuffer()
};
};
TransactionBuilder.prototype._signPubKeyHash = function(walletKeyMap, input, txSigHash) {
if (this.tx.ins[input.i].s.length > 0) return {};
var wk = this._findWalletKey(walletKeyMap, input);
var wk = this._findWalletKey(walletKeyMap, input);
if (!wk) return;
var sigRaw = TransactionBuilder._signHashAndVerify(wk, txSigHash);
var sigType = new Buffer(1);
sigType[0] = this.signhash;
var sig = Buffer.concat([sigRaw, sigType]);
var sigRaw = TransactionBuilder._signHashAndVerify(wk, txSigHash);
var sigType = new Buffer(1);
sigType[0] = this.signhash;
var sig = Buffer.concat([sigRaw, sigType]);
var scriptSig = new Script();
scriptSig.chunks.push(sig);
scriptSig.chunks.push(wk.privKey.public);
scriptSig.updateBuffer();
return {inputFullySigned: true, signaturesAdded: 1, script: scriptSig.getBuffer()};
return {
inputFullySigned: true,
signaturesAdded: 1,
script: scriptSig.getBuffer()
};
};
/* FOR TESTING
@ -537,13 +547,13 @@ var _dumpChunks = function (scriptSig, label) {
TransactionBuilder.prototype._chunkSignedWithKey = function(scriptSig, txSigHash, publicKey) {
var ret;
var k = new Key();
k.public =publicKey;
k.public = publicKey;
for(var i=1; i<= scriptSig.countSignatures(); i++) {
for (var i = 1; i <= scriptSig.countSignatures(); i++) {
var chunk = scriptSig.chunks[i];
var sigRaw = new Buffer(chunk.slice(0,chunk.length-1));
if (k.verifySignatureSync(txSigHash, sigRaw) ) {
ret=chunk;
var sigRaw = new Buffer(chunk.slice(0, chunk.length - 1));
if (k.verifySignatureSync(txSigHash, sigRaw)) {
ret = chunk;
}
}
return ret;
@ -551,10 +561,10 @@ TransactionBuilder.prototype._chunkSignedWithKey = function(scriptSig, txSigHash
TransactionBuilder.prototype._getSignatureOrder = function(sigPrio, sigRaw, txSigHash, pubkeys) {
var l=pubkeys.length;
for(var j=0; j<l; j++) {
var l = pubkeys.length;
for (var j = 0; j < l; j++) {
var k = new Key();
k.public = new Buffer(pubkeys[j],'hex');
k.public = new Buffer(pubkeys[j], 'hex');
if (k.verifySignatureSync(txSigHash, sigRaw))
break;
}
@ -563,17 +573,17 @@ TransactionBuilder.prototype._getSignatureOrder = function(sigPrio, sigRaw, txSi
TransactionBuilder.prototype._getNewSignatureOrder = function(sigPrio, scriptSig, txSigHash, pubkeys) {
var iPrio;
for(var i=1; i<= scriptSig.countSignatures(); i++) {
for (var i = 1; i <= scriptSig.countSignatures(); i++) {
var chunk = scriptSig.chunks[i];
var sigRaw = new Buffer(chunk.slice(0,chunk.length-1));
var sigRaw = new Buffer(chunk.slice(0, chunk.length - 1));
iPrio = this._getSignatureOrder(sigPrio, sigRaw, txSigHash, pubkeys);
if (sigPrio <= iPrio) break;
}
return (sigPrio === iPrio? -1: i-1);
return (sigPrio === iPrio ? -1 : i - 1);
};
TransactionBuilder.prototype._chunkIsEmpty = function(chunk) {
return chunk === 0 || // when serializing and back, EMPTY_BUFFER becomes 0
return chunk === 0 || // when serializing and back, EMPTY_BUFFER becomes 0
buffertools.compare(chunk, util.EMPTY_BUFFER) === 0;
};
@ -593,16 +603,16 @@ TransactionBuilder.prototype._updateMultiSig = function(sigPrio, wk, scriptSig,
return null;
// Create signature
var sigRaw = TransactionBuilder._signHashAndVerify(wk, txSigHash);
var sigRaw = TransactionBuilder._signHashAndVerify(wk, txSigHash);
var sigType = new Buffer(1);
sigType[0] = this.signhash;
var sig = Buffer.concat([sigRaw, sigType]);
sigType[0] = this.signhash;
var sig = Buffer.concat([sigRaw, sigType]);
// Add signature
var order = this._getNewSignatureOrder(sigPrio,scriptSig,txSigHash,pubkeys);
scriptSig.chunks.splice(order+1,0,sig);
var order = this._getNewSignatureOrder(sigPrio, scriptSig, txSigHash, pubkeys);
scriptSig.chunks.splice(order + 1, 0, sig);
scriptSig.updateBuffer();
wasUpdated=true;
wasUpdated = true;
return wasUpdated ? scriptSig : null;
};
@ -610,15 +620,17 @@ TransactionBuilder.prototype._updateMultiSig = function(sigPrio, wk, scriptSig,
TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSigHash) {
var pubkeys = input.scriptPubKey.capture(),
nreq = input.scriptPubKey.chunks[0] - 80, //see OP_2-OP_16
nreq = input.scriptPubKey.chunks[0] - 80, //see OP_2-OP_16
l = pubkeys.length,
originalScriptBuf = this.tx.ins[input.i].s;
var scriptSig = new Script (originalScriptBuf);
var scriptSig = new Script(originalScriptBuf);
var signaturesAdded = 0;
for(var j=0; j<l && scriptSig.countSignatures() < nreq ; j++) {
var wk = this._findWalletKey(walletKeyMap, {pubKeyBuf: pubkeys[j]});
for (var j = 0; j < l && scriptSig.countSignatures() < nreq; j++) {
var wk = this._findWalletKey(walletKeyMap, {
pubKeyBuf: pubkeys[j]
});
if (!wk) continue;
var newScriptSig = this._updateMultiSig(j, wk, scriptSig, txSigHash, pubkeys);
@ -629,22 +641,22 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig
}
var ret = {
inputFullySigned: scriptSig.countSignatures() === nreq,
inputFullySigned: scriptSig.countSignatures() === nreq,
signaturesAdded: signaturesAdded,
script: scriptSig.getBuffer(),
};
return ret;
};
var fnToSign = {};
TransactionBuilder.prototype._scriptIsAppended = function(script, scriptToAddBuf) {
var len = script.chunks.length;
if (script.chunks[len-1] === undefined)
if (script.chunks[len - 1] === undefined)
return false;
if (typeof script.chunks[len-1] === 'number')
if (typeof script.chunks[len - 1] === 'number')
return false;
if (buffertools.compare(script.chunks[len-1] , scriptToAddBuf) !==0 )
if (buffertools.compare(script.chunks[len - 1], scriptToAddBuf) !== 0)
return false;
return true;
@ -659,17 +671,17 @@ TransactionBuilder.prototype._addScript = function(scriptBuf, scriptToAddBuf) {
}
return s.getBuffer();
};
TransactionBuilder.prototype._getInputForP2sh = function(script, index) {
var scriptType = script.classify();
/* pubKeyHash is needed for TX_PUBKEYHASH and TX_PUBKEY to retrieve the keys. */
var pubKeyHash;
switch(scriptType) {
switch (scriptType) {
case Script.TX_PUBKEYHASH:
pubKeyHash = script.captureOne();
break;
case Script.TX_PUBKEY:
var chunk = script.captureOne();
var chunk = script.captureOne();
pubKeyHash = util.sha256ripe160(chunk);
}
@ -689,16 +701,16 @@ TransactionBuilder.prototype._p2shInput = function(input) {
var scriptHex = this.hashToScriptMap[input.address];
if (!scriptHex) return;
var scriptBuf = new Buffer(scriptHex,'hex');
var script = new Script(scriptBuf);
var scriptType = script.classify();
var scriptBuf = new Buffer(scriptHex, 'hex');
var script = new Script(scriptBuf);
var scriptType = script.classify();
if (!fnToSign[scriptType] || scriptType === Script.TX_SCRIPTHASH)
throw new Error('dont know how to sign p2sh script type:'+ script.getRawOutType());
throw new Error('dont know how to sign p2sh script type:' + script.getRawOutType());
return {
input: this._getInputForP2sh(script, input.i),
txSigHash: this.tx.hashForSignature( script, input.i, this.signhash),
txSigHash: this.tx.hashForSignature(script, input.i, this.signhash),
scriptType: script.classify(),
scriptBuf: scriptBuf,
};
@ -706,9 +718,9 @@ TransactionBuilder.prototype._p2shInput = function(input) {
TransactionBuilder.prototype._signScriptHash = function(walletKeyMap, input, txSigHash) {
var p2sh = this._p2shInput(input);
var p2sh = this._p2shInput(input);
var ret = fnToSign[p2sh.scriptType].call(this, walletKeyMap, p2sh.input, p2sh.txSigHash);
var ret = fnToSign[p2sh.scriptType].call(this, walletKeyMap, p2sh.input, p2sh.txSigHash);
if (ret && ret.script && ret.signaturesAdded) {
ret.script = this._addScript(ret.script, p2sh.scriptBuf);
}
@ -716,8 +728,8 @@ TransactionBuilder.prototype._signScriptHash = function(walletKeyMap, input, txS
};
fnToSign[Script.TX_PUBKEYHASH] = TransactionBuilder.prototype._signPubKeyHash;
fnToSign[Script.TX_PUBKEY] = TransactionBuilder.prototype._signPubKey;
fnToSign[Script.TX_MULTISIG] = TransactionBuilder.prototype._signMultiSig;
fnToSign[Script.TX_PUBKEY] = TransactionBuilder.prototype._signPubKey;
fnToSign[Script.TX_MULTISIG] = TransactionBuilder.prototype._signMultiSig;
fnToSign[Script.TX_SCRIPTHASH] = TransactionBuilder.prototype._signScriptHash;
// sign
@ -736,10 +748,10 @@ fnToSign[Script.TX_SCRIPTHASH] = TransactionBuilder.prototype._signScriptHash;
//
TransactionBuilder.prototype.sign = function(keys) {
this._checkTx();
var tx = this.tx,
ins = tx.ins,
l = ins.length,
walletKeyMap = TransactionBuilder._mapKeys(keys);
var tx = this.tx,
ins = tx.ins,
l = ins.length,
walletKeyMap = TransactionBuilder._mapKeys(keys);
for (var i = 0; i < l; i++) {
var input = this.inputMap[i];
@ -751,7 +763,7 @@ TransactionBuilder.prototype.sign = function(keys) {
if (ret && ret.script) {
tx.ins[i].s = ret.script;
if (ret.inputFullySigned) this.inputsSigned++;
if (ret.signaturesAdded) this.signaturesAdded +=ret.signaturesAdded;
if (ret.signaturesAdded) this.signaturesAdded += ret.signaturesAdded;
}
}
return this;
@ -764,7 +776,7 @@ TransactionBuilder.prototype.sign = function(keys) {
// for generate the input for this call.
//
TransactionBuilder.prototype.setHashToScriptMap = function(hashToScriptMap) {
this.hashToScriptMap= hashToScriptMap;
this.hashToScriptMap = hashToScriptMap;
return this;
};
@ -792,23 +804,23 @@ TransactionBuilder.prototype.build = function() {
// See `.fromObj`
//
TransactionBuilder.prototype.toObj = function() {
var data = {
valueInSat : this.valueInSat.toString(),
valueOutSat : this.valueOutSat.toString(),
feeSat : this.feeSat.toString(),
remainderSat : this.remainderSat.toString(),
var data = {
valueInSat: this.valueInSat.toString(),
valueOutSat: this.valueOutSat.toString(),
feeSat: this.feeSat.toString(),
remainderSat: this.remainderSat.toString(),
hashToScriptMap : this.hashToScriptMap,
selectedUtxos : this.selectedUtxos,
hashToScriptMap: this.hashToScriptMap,
selectedUtxos: this.selectedUtxos,
inputsSigned : this.inputsSigned,
signaturesAdded : this.signaturesAdded,
inputsSigned: this.inputsSigned,
signaturesAdded: this.signaturesAdded,
signhash : this.signhash,
spendUnconfirmed : this.spendUnconfirmed,
signhash: this.signhash,
spendUnconfirmed: this.spendUnconfirmed,
};
if (this.tx) {
data.tx =this.tx.serialize().toString('hex');
data.tx = this.tx.serialize().toString('hex');
}
return data;
};
@ -821,18 +833,18 @@ TransactionBuilder.prototype.toObj = function() {
TransactionBuilder.fromObj = function(data) {
var b = new TransactionBuilder();
b.valueInSat = data.valueInSat.toString();
b.valueOutSat = data.valueOutSat.toString();
b.feeSat = data.feeSat.toString();
b.remainderSat = data.remainderSat.toString();
b.valueInSat = data.valueInSat.toString();
b.valueOutSat = data.valueOutSat.toString();
b.feeSat = data.feeSat.toString();
b.remainderSat = data.remainderSat.toString();
b.hashToScriptMap = data.hashToScriptMap;
b.selectedUtxos = data.selectedUtxos;
b.hashToScriptMap = data.hashToScriptMap;
b.selectedUtxos = data.selectedUtxos;
b.inputsSigned = data.inputsSigned;
b.signaturesAdded = data.signaturesAdded;
b.inputsSigned = data.inputsSigned;
b.signaturesAdded = data.signaturesAdded;
b.signhash = data.signhash;
b.signhash = data.signhash;
b.spendUnconfirmed = data.spendUnconfirmed;
b._setInputMap();
@ -840,7 +852,7 @@ TransactionBuilder.fromObj = function(data) {
if (data.tx) {
// Tx may have signatures, that are not on txobj
var t = new Transaction();
t.parse(new Buffer(data.tx,'hex'));
t.parse(new Buffer(data.tx, 'hex'));
b.tx = t;
}
return b;
@ -848,79 +860,80 @@ TransactionBuilder.fromObj = function(data) {
TransactionBuilder.prototype._checkMergeability = function(b) {
var self=this;
var self = this;
// Builder should have the same params
['valueInSat', 'valueOutSat', 'feeSat', 'remainderSat', 'signhash', 'spendUnconfirmed']
.forEach(function (k) {
.forEach(function(k) {
if (self[k].toString() !== b[k].toString()) {
throw new Error('mismatch at TransactionBuilder match: '
+ k + ': ' + self[k] + ' vs. ' + b[k]);
}
});
if (self[k].toString() !== b[k].toString()) {
throw new Error('mismatch at TransactionBuilder match: ' + k + ': ' + self[k] + ' vs. ' + b[k]);
}
});
if (self.hashToScriptMap) {
var err = 0;
if(! b.hashToScriptMap) err=1;
if (!b.hashToScriptMap) err = 1;
Object.keys(self.hashToScriptMap).forEach(function(k) {
if (!b.hashToScriptMap[k]) err=1;
if (self.hashToScriptMap[k] !== b.hashToScriptMap[k]) err=1;
if (!b.hashToScriptMap[k]) err = 1;
if (self.hashToScriptMap[k] !== b.hashToScriptMap[k]) err = 1;
});
if (err)
throw new Error('mismatch at TransactionBuilder hashToScriptMap');
}
var err = 0, i=0;;
var err = 0,
i = 0;;
self.selectedUtxos.forEach(function(u) {
if (!err) {
var v=b.selectedUtxos[i++];
if (!v) err=1;
var v = b.selectedUtxos[i++];
if (!v) err = 1;
// confirmations could differ
['address', 'hash', 'scriptPubKey', 'vout', 'amount'].forEach(function(k) {
if (u[k] !== v[k])
err=k;
err = k;
});
}
});
if (err)
throw new Error('mismatch at TransactionBuilder selectedUtxos #' + i-1+ ' Key:' + err);
throw new Error('mismatch at TransactionBuilder selectedUtxos #' + i - 1 + ' Key:' + err);
err = 0; i=0;;
err = 0;
i = 0;;
self.inputMap.forEach(function(u) {
if (!err) {
var v=b.inputMap[i++];
if (!v) err=1;
var v = b.inputMap[i++];
if (!v) err = 1;
// confirmations could differ
['address', 'scriptType', 'scriptPubKey', 'i'].forEach(function(k) {
if (u[k].toString() !== v[k].toString())
err=k;
err = k;
});
}
});
if (err)
throw new Error('mismatch at TransactionBuilder inputMap #' + i-1 + ' Key:' + err);
throw new Error('mismatch at TransactionBuilder inputMap #' + i - 1 + ' Key:' + err);
};
// TODO this could be on Script class
TransactionBuilder.prototype._mergeInputSigP2sh = function(input,s0,s1) {
var p2sh = this._p2shInput(input);
TransactionBuilder.prototype._mergeInputSigP2sh = function(input, s0, s1) {
var p2sh = this._p2shInput(input);
var redeemScript = new Script(p2sh.scriptBuf);
var pubkeys = redeemScript.capture();
// Look for differences
var s0keys = {};
var l = pubkeys.length;
for (var j=0; j<l; j++) {
if ( this._chunkSignedWithKey(s0, p2sh.txSigHash, pubkeys[j]))
for (var j = 0; j < l; j++) {
if (this._chunkSignedWithKey(s0, p2sh.txSigHash, pubkeys[j]))
s0keys[pubkeys[j].toString('hex')] = 1;
}
var diff = [];
for (var j=0; j<l; j++) {
for (var j = 0; j < l; j++) {
var chunk = this._chunkSignedWithKey(s1, p2sh.txSigHash, pubkeys[j]);
var pubHex = pubkeys[j].toString('hex');
if (chunk && !s0keys[pubHex]) {
@ -933,10 +946,10 @@ TransactionBuilder.prototype._mergeInputSigP2sh = function(input,s0,s1) {
}
// Add signatures
for(var j in diff) {
for (var j in diff) {
var newSig = diff[j];
var order = this._getNewSignatureOrder(newSig.prio,s0,p2sh.txSigHash,pubkeys);
s0.chunks.splice(order+1,0,newSig.chunk);
var order = this._getNewSignatureOrder(newSig.prio, s0, p2sh.txSigHash, pubkeys);
s0.chunks.splice(order + 1, 0, newSig.chunk);
this.signaturesAdded++;
}
s0.updateBuffer();
@ -945,7 +958,7 @@ TransactionBuilder.prototype._mergeInputSigP2sh = function(input,s0,s1) {
// TODO this could be on Script class
TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
if (buffertools.compare(s0buf,s1buf) === 0)
if (buffertools.compare(s0buf, s1buf) === 0)
return s0buf;
var s0 = new Script(s0buf);
@ -954,53 +967,52 @@ TransactionBuilder.prototype._mergeInputSig = function(index, s0buf, s1buf) {
var l1 = s1.chunks.length;
var s0map = {};
if (l0 && l1 && ((l0<2 && l1>2) || (l1<2 && l0>2 )))
if (l0 && l1 && ((l0 < 2 && l1 > 2) || (l1 < 2 && l0 > 2)))
throw new Error('TX sig types mismatch in merge');
if ((!l0 && !l1) || ( l0 && !l1) || (!l0 && l1))
if ((!l0 && !l1) || (l0 && !l1) || (!l0 && l1))
return s1buf;
// Get the pubkeys
var input = this.inputMap[index];
var type = input.scriptPubKey.classify();
var type = input.scriptPubKey.classify();
//p2pubkey or p2pubkeyhash
if (type === Script.TX_PUBKEYHASH || type === Script.TX_PUBKEY) {
log.debug('Merging two signed inputs type:' +
input.scriptPubKey.getRawOutType() + '. Signatures differs. Using the first version.');
return s0buf;
}
else if (type!== Script.TX_SCRIPTHASH) {
} else if (type !== Script.TX_SCRIPTHASH) {
// No support for normal multisig or strange txs.
throw new Error('Script type:'+input.scriptPubKey.getRawOutType()+'not supported at #merge');
throw new Error('Script type:' + input.scriptPubKey.getRawOutType() + 'not supported at #merge');
}
return this._mergeInputSigP2sh(input,s0, s1);
return this._mergeInputSigP2sh(input, s0, s1);
};
// TODO this could be on Transaction class
TransactionBuilder.prototype._mergeTx = function(tx) {
var v0 = this.tx;
var v1 = tx;
var v0 = this.tx;
var v1 = tx;
var l = v0.ins.length;
if (l !== v1.ins.length)
throw new Error('TX in length mismatch in merge');
var l = v0.ins.length;
if (l !== v1.ins.length)
throw new Error('TX in length mismatch in merge');
this.inputsSigned =0;
for(var i=0; i<l; i++) {
var i0 = v0.ins[i];
var i1 = v1.ins[i];
this.inputsSigned = 0;
for (var i = 0; i < l; i++) {
var i0 = v0.ins[i];
var i1 = v1.ins[i];
if (i0.q !== i1.q)
throw new Error('TX sequence ins mismatch in merge. Input:',i);
if (i0.q !== i1.q)
throw new Error('TX sequence ins mismatch in merge. Input:', i);
if (buffertools.compare(i0.o,i1.o) !== 0)
throw new Error('TX .o in mismatch in merge. Input:',i);
if (buffertools.compare(i0.o, i1.o) !== 0)
throw new Error('TX .o in mismatch in merge. Input:', i);
i0.s=this._mergeInputSig(i, i0.s,i1.s);
i0.s = this._mergeInputSig(i, i0.s, i1.s);
if (v0.isInputComplete(i)) this.inputsSigned++;
}
if (v0.isInputComplete(i)) this.inputsSigned++;
}
};
// merge
@ -1013,11 +1025,10 @@ TransactionBuilder.prototype.merge = function(b) {
// Does this tX have any signature already?
if (this.tx || b.tx) {
if (this.tx.getNormalizedHash().toString('hex')
!== b.tx.getNormalizedHash().toString('hex'))
if (this.tx.getNormalizedHash().toString('hex') !== b.tx.getNormalizedHash().toString('hex'))
throw new Error('mismatch at TransactionBuilder NTXID');
this._mergeTx(b.tx);
this._mergeTx(b.tx);
}
};

39
lib/Wallet.js

@ -1,12 +1,14 @@
var imports = require('soop').imports();
var hex = function(hex) {return new Buffer(hex, 'hex');};
var hex = function(hex) {
return new Buffer(hex, 'hex');
};
var fs = require('fs');
var EncFile = require('../util/EncFile');
var Address = require('./Address');
var networks = require('../networks');
var util = imports.util || require('../util');
var fs = require('fs');
var EncFile = require('../util/EncFile');
var Address = require('./Address');
var networks = require('../networks');
var util = imports.util || require('../util');
var ENC_METHOD = 'aes-256-cbc';
var skeleton = {
@ -37,7 +39,7 @@ function Wallet(cfg) {
Wallet.prototype.readSync = function(filename, passphrase) {
this.datastore = EncFile.readJFileSync(ENC_METHOD,
passphrase, filename);
passphrase, filename);
this.dirty = false;
};
@ -45,7 +47,7 @@ Wallet.prototype.writeSync = function(filename, passphrase) {
var tmp_fn = filename + ".tmp";
EncFile.writeJFileSync(ENC_METHOD, passphrase, tmp_fn,
this.datastore);
this.datastore);
fs.renameSync(tmp_fn, filename);
this.dirty = false;
@ -56,15 +58,15 @@ Wallet.prototype.setNetwork = function(netname) {
netname = this.datastore.network;
switch (netname) {
case "mainnet":
case "livenet":
this.network = networks.livenet;
break;
case "testnet":
this.network = networks.testnet;
break;
default:
throw new Error("Unsupported network");
case "mainnet":
case "livenet":
this.network = networks.livenet;
break;
case "testnet":
this.network = networks.testnet;
break;
default:
throw new Error("Unsupported network");
}
// store+canonicalize name
@ -105,7 +107,7 @@ Wallet.prototype.expandKey = function(key) {
var b = addr.payload();
var obj = this.findKeyHash(b);
key = obj.pub;
} catch(e) {
} catch (e) {
// do nothing
}
@ -137,4 +139,3 @@ Wallet.prototype.addScript = function(script) {
};
module.exports = require('soop')(Wallet);

2
lib/WalletKey.js

@ -39,7 +39,7 @@ WalletKey.prototype.fromObj = function(obj) {
this.privKey = new Key();
if (obj.priv.length == 64) {
this.privKey.private = new Buffer(obj.priv, 'hex');
this.privKey.compressed = typeof obj.compressed === 'undefined'? true: obj.compressed;
this.privKey.compressed = typeof obj.compressed === 'undefined' ? true : obj.compressed;
} else {
var priv = new PrivateKey(obj.priv);
priv.validate();

2620
lib/browser/Bignum.js

File diff suppressed because it is too large

22
lib/browser/ECIES.js

@ -9,7 +9,13 @@ ECIES.symmetricEncrypt = function(key, iv, message) {
var smessage = sjcl.codec.hex.toBits(message.toString('hex'));
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]();
var params = {iv: siv, ks: 256, ts: 128, iter: 1000, mode: 'cbc'};
var params = {
iv: siv,
ks: 256,
ts: 128,
iter: 1000,
mode: 'cbc'
};
var encrypted = sjcl.encrypt(skey, smessage, params);
var enchex = sjcl.codec.hex.fromBits(sjcl.codec.base64.toBits(JSON.parse(encrypted).ct));
@ -24,12 +30,22 @@ ECIES.symmetricDecrypt = function(key, encrypted) {
var skey = sjcl.codec.hex.toBits(key.toString('hex'));
var iv = encrypted.slice(0, 16);
var todecrypt = encrypted.slice(16, encrypted.length);
var siv = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(iv.toString('hex')));
var sct = sjcl.codec.base64.fromBits(sjcl.codec.hex.toBits(todecrypt.toString('hex')));
sjcl.beware["CBC mode is dangerous because it doesn't protect message integrity."]();
var obj = {iv: siv, v: 1, iter: 1000, ks: 256, ts: 128, mode: 'cbc', adata: '', cipher: 'aes', ct: sct};
var obj = {
iv: siv,
v: 1,
iter: 1000,
ks: 256,
ts: 128,
mode: 'cbc',
adata: '',
cipher: 'aes',
ct: sct
};
var str = JSON.stringify(obj);
var decrypted = sjcl.decrypt(skey, str);

26
lib/browser/Key.js

@ -12,7 +12,7 @@ var bufferToArray = Key.bufferToArray = function(buffer) {
var ret = [];
var l = buffer.length;
for(var i =0; i<l; i++) {
for (var i = 0; i < l; i++) {
ret.push(buffer.readUInt8(i));
}
@ -20,15 +20,15 @@ var bufferToArray = Key.bufferToArray = function(buffer) {
}
Object.defineProperty(Key.prototype, 'public', {
set: function(p){
if (!Buffer.isBuffer(p) ) {
set: function(p) {
if (!Buffer.isBuffer(p)) {
throw new Error('Arg should be a buffer');
}
var type = p[0];
this._compressed = type!==0x04;
this._compressed = type !== 0x04;
this._pub = p;
},
get: function(){
get: function() {
return this._pub;
}
});
@ -59,9 +59,11 @@ Object.defineProperty(Key.prototype, 'compressed', {
Key.generateSync = function() {
var privbuf;
while(true) {
while (true) {
privbuf = SecureRandom.getRandomBuffer(32);
if ((bignum.fromBuffer(privbuf, {size: 32})).cmp(Curve.getN()) < 0)
if ((bignum.fromBuffer(privbuf, {
size: 32
})).cmp(Curve.getN()) < 0)
break;
}
@ -104,13 +106,13 @@ Key.prototype.signSync = function(hash) {
}
};
var getBigRandom = function (limit) {
var getBigRandom = function(limit) {
return new BigInteger(limit.bitLength(), rng)
.mod(limit.subtract(BigInteger.ONE))
.add(BigInteger.ONE);
};
var sign = function (hash, priv) {
var sign = function(hash, priv) {
var d = priv;
var n = ecparams.getN();
var e = BigInteger.fromByteArrayUnsigned(hash);
@ -126,7 +128,7 @@ Key.prototype.signSync = function(hash) {
return serializeSig(r, s);
};
var serializeSig = function (r, s) {
var serializeSig = function(r, s) {
var rBa = r.toByteArraySigned();
var sBa = s.toByteArraySigned();
@ -185,7 +187,7 @@ Key.prototype.verifySignatureSync = function(hash, sig) {
eck.setPub(bufferToArray(self.public));
eck.setCompressed(self._compressed);
var sigA = bufferToArray(sig);
var ret = eck.verify(bufferToArray(hash),sigA);
var ret = eck.verify(bufferToArray(hash), sigA);
return ret;
};

58
lib/browser/Point.js

@ -1,7 +1,7 @@
"use strict";
var imports = require('soop').imports();
var Key = imports.Key || require('./Key');
var Key = imports.Key || require('./Key');
var bignum = imports.bignum || require('bignum');
var assert = require('assert');
var ECPointFp = require('../../browser/vendor-bundle.js').ECPointFp;
@ -19,17 +19,25 @@ var Point = function(x, y) {
Point.add = function(p1, p2) {
var ecparams = getSECCurveByName('secp256k1');
var p1xhex = p1.x.toBuffer({size: 32}).toString('hex');
var p1xhex = p1.x.toBuffer({
size: 32
}).toString('hex');
var p1x = new BigInteger(p1xhex, 16);
var p1yhex = p1.y.toBuffer({size: 32}).toString('hex');
var p1yhex = p1.y.toBuffer({
size: 32
}).toString('hex');
var p1y = new BigInteger(p1yhex, 16);
var p1px = new ECFieldElementFp(ecparams.getCurve().getQ(), p1x);
var p1py = new ECFieldElementFp(ecparams.getCurve().getQ(), p1y);
var p1p = new ECPointFp(ecparams.getCurve(), p1px, p1py);
var p2xhex = p2.x.toBuffer({size: 32}).toString('hex');
var p2xhex = p2.x.toBuffer({
size: 32
}).toString('hex');
var p2x = new BigInteger(p2xhex, 16);
var p2yhex = p2.y.toBuffer({size: 32}).toString('hex');
var p2yhex = p2.y.toBuffer({
size: 32
}).toString('hex');
var p2y = new BigInteger(p2yhex, 16);
var p2px = new ECFieldElementFp(ecparams.getCurve().getQ(), p2x);
var p2py = new ECFieldElementFp(ecparams.getCurve().getQ(), p2y);
@ -39,11 +47,15 @@ Point.add = function(p1, p2) {
var point = new Point();
var pointxbuf = new Buffer(p.getX().toBigInteger().toByteArrayUnsigned());
point.x = bignum.fromBuffer(pointxbuf, {size: pointxbuf.length});
point.x = bignum.fromBuffer(pointxbuf, {
size: pointxbuf.length
});
assert(pointxbuf.length <= 32);
var pointybuf = new Buffer(p.getY().toBigInteger().toByteArrayUnsigned());
assert(pointybuf.length <= 32);
point.y = bignum.fromBuffer(pointybuf, {size: pointybuf.length});
point.y = bignum.fromBuffer(pointybuf, {
size: pointybuf.length
});
return point;
};
@ -53,9 +65,13 @@ Point.multiply = function(p1, x) {
var ecparams = getSECCurveByName('secp256k1');
var p1xhex = p1.x.toBuffer({size: 32}).toString('hex');
var p1xhex = p1.x.toBuffer({
size: 32
}).toString('hex');
var p1x = new BigInteger(p1xhex, 16);
var p1yhex = p1.y.toBuffer({size: 32}).toString('hex');
var p1yhex = p1.y.toBuffer({
size: 32
}).toString('hex');
var p1y = new BigInteger(p1yhex, 16);
var p1px = new ECFieldElementFp(ecparams.getCurve().getQ(), p1x);
var p1py = new ECFieldElementFp(ecparams.getCurve().getQ(), p1y);
@ -65,11 +81,15 @@ Point.multiply = function(p1, x) {
var point = new Point();
var pointxbuf = new Buffer(p.getX().toBigInteger().toByteArrayUnsigned());
point.x = bignum.fromBuffer(pointxbuf, {size: pointxbuf.length});
point.x = bignum.fromBuffer(pointxbuf, {
size: pointxbuf.length
});
assert(pointxbuf.length <= 32);
var pointybuf = new Buffer(p.getY().toBigInteger().toByteArrayUnsigned());
assert(pointybuf.length <= 32);
point.y = bignum.fromBuffer(pointybuf, {size: pointybuf.length});
point.y = bignum.fromBuffer(pointybuf, {
size: pointybuf.length
});
return point;
};
@ -77,15 +97,23 @@ Point.multiply = function(p1, x) {
//convert the public key of a Key into a Point
Point.fromUncompressedPubKey = function(pubkey) {
var point = new Point();
point.x = bignum.fromBuffer((new Buffer(pubkey)).slice(1, 33), {size: 32});
point.y = bignum.fromBuffer((new Buffer(pubkey)).slice(33, 65), {size: 32});
point.x = bignum.fromBuffer((new Buffer(pubkey)).slice(1, 33), {
size: 32
});
point.y = bignum.fromBuffer((new Buffer(pubkey)).slice(33, 65), {
size: 32
});
return point;
};
//convert the Point into the Key containing a compressed public key
Point.prototype.toUncompressedPubKey = function() {
var xbuf = this.x.toBuffer({size: 32});
var ybuf = this.y.toBuffer({size: 32});
var xbuf = this.x.toBuffer({
size: 32
});
var ybuf = this.y.toBuffer({
size: 32
});
var prefix = new Buffer([0x04]);
var pub = Buffer.concat([prefix, xbuf, ybuf]);
return pub;

15
lib/common/ECIES.js

@ -6,8 +6,7 @@ var SecureRandom = imports.SecureRandom || require('../SecureRandom');
var Key = imports.Key || require('../Key');
// http://en.wikipedia.org/wiki/Integrated_Encryption_Scheme
var ECIES = function() {
};
var ECIES = function() {};
ECIES.encryptObj = function(pubkey, message, r, iv) {
var ecies = new ECIES();
@ -42,7 +41,9 @@ ECIES.decryptObj = function(ecies) {
var c = ecies.c;
var d = ecies.d;
var P = Point.multiply(R, kB);
var S = P.x.toBuffer({size: 32});
var S = P.x.toBuffer({
size: 32
});
var buf = ECIES.kdf(S);
var kE = ecies.kE = buf.slice(0, 32);
var kM = ecies.kM = buf.slice(32, 64);
@ -98,7 +99,9 @@ ECIES.prototype.getSfromPubkey = function() {
key2.compressed = false;
var KBP = Point.fromUncompressedPubKey(key2.public);
this.P = Point.multiply(KBP, this.r);
this.S = this.P.x.toBuffer({size: 32});
this.S = this.P.x.toBuffer({
size: 32
});
return this.S;
};
@ -106,7 +109,9 @@ ECIES.prototype.getSfromPrivkey = function() {
var R = this.R;
var kB = this.kB;
var SP = Point.multiply(R, kB);
var S = SP.x.toBuffer({size: 32});
var S = SP.x.toBuffer({
size: 32
});
return S;
};

3
lib/common/SecureRandom.js

@ -1,7 +1,6 @@
var imports = require('soop');
var SecureRandom = function() {
};
var SecureRandom = function() {};
/* secure random bytes that sometimes throws an error due to lack of entropy */
SecureRandom.getRandomBuffer = function() {};

4
networks.js

@ -1,6 +1,8 @@
var Put = require('bufferput');
var buffertools = require('buffertools');
var hex = function(hex) {return new Buffer(hex, 'hex');};
var hex = function(hex) {
return new Buffer(hex, 'hex');
};
exports.livenet = {
name: 'livenet',

73
util/BinaryParser.js

@ -2,15 +2,15 @@
* Simple synchronous parser based on node-binary.
*/
var imports = require('soop').imports();
function Parser(buffer)
{
var imports = require('soop').imports();
function Parser(buffer) {
this.subject = buffer;
this.pos = 0;
};
Parser.prototype.buffer = function buffer(len) {
var buf = this.subject.slice(this.pos, this.pos+len);
var buf = this.subject.slice(this.pos, this.pos + len);
this.pos += len;
return buf;
};
@ -32,7 +32,7 @@ Parser.prototype.search = function search(needle) {
for (var i = this.pos, l = this.subject.length; i < l; i++) {
if (this.subject[i] == needle) {
len = i - this.pos;
this.pos = i+1;
this.pos = i + 1;
return len;
}
}
@ -41,13 +41,13 @@ Parser.prototype.search = function search(needle) {
};
/**
* Like search(), but returns the skipped bytes
*/
* Like search(), but returns the skipped bytes
*/
Parser.prototype.scan = function scan(needle) {
var startPos = this.pos;
var len = this.search(needle);
if (len !== -1) {
return this.subject.slice(startPos, startPos+len);
return this.subject.slice(startPos, startPos + len);
} else {
throw new Error('No match');
}
@ -58,16 +58,16 @@ Parser.prototype.eof = function eof() {
};
// convert byte strings to unsigned little endian numbers
function decodeLEu (bytes) {
function decodeLEu(bytes) {
var acc = 0;
for (var i = 0; i < bytes.length; i++) {
acc += Math.pow(256,i) * bytes[i];
acc += Math.pow(256, i) * bytes[i];
}
return acc;
}
// convert byte strings to unsigned big endian numbers
function decodeBEu (bytes) {
function decodeBEu(bytes) {
var acc = 0;
for (var i = 0; i < bytes.length; i++) {
acc += Math.pow(256, bytes.length - i - 1) * bytes[i];
@ -76,7 +76,7 @@ function decodeBEu (bytes) {
}
// convert byte strings to signed big endian numbers
function decodeBEs (bytes) {
function decodeBEs(bytes) {
var val = decodeBEu(bytes);
if ((bytes[0] & 0x80) == 0x80) {
val -= Math.pow(256, bytes.length);
@ -85,7 +85,7 @@ function decodeBEs (bytes) {
}
// convert byte strings to signed little endian numbers
function decodeLEs (bytes) {
function decodeLEs(bytes) {
var val = decodeLEu(bytes);
if ((bytes[bytes.length - 1] & 0x80) == 0x80) {
val -= Math.pow(256, bytes.length);
@ -94,51 +94,44 @@ function decodeLEs (bytes) {
}
function getDecoder(len, fn) {
return function () {
return function() {
var buf = this.buffer(len);
return fn(buf);
};
};
[ 1, 2, 4, 8 ].forEach(function (bytes) {
[1, 2, 4, 8].forEach(function(bytes) {
var bits = bytes * 8;
Parser.prototype['word' + bits + 'le']
= Parser.prototype['word' + bits + 'lu']
= getDecoder(bytes, decodeLEu);
Parser.prototype['word' + bits + 'ls']
= getDecoder(bytes, decodeLEs);
Parser.prototype['word' + bits + 'be']
= Parser.prototype['word' + bits + 'bu']
= getDecoder(bytes, decodeBEu);
Parser.prototype['word' + bits + 'bs']
= getDecoder(bytes, decodeBEs);
Parser.prototype['word' + bits + 'le'] = Parser.prototype['word' + bits + 'lu'] = getDecoder(bytes, decodeLEu);
Parser.prototype['word' + bits + 'ls'] = getDecoder(bytes, decodeLEs);
Parser.prototype['word' + bits + 'be'] = Parser.prototype['word' + bits + 'bu'] = getDecoder(bytes, decodeBEu);
Parser.prototype['word' + bits + 'bs'] = getDecoder(bytes, decodeBEs);
Parser.prototype.word8 = Parser.prototype.word8u = Parser.prototype.word8be;
Parser.prototype.word8s = Parser.prototype.word8bs;
});
Parser.prototype.varInt = function ()
{
Parser.prototype.varInt = function() {
var firstByte = this.word8();
switch (firstByte) {
case 0xFD:
return this.word16le();
case 0xFD:
return this.word16le();
case 0xFE:
return this.word32le();
case 0xFE:
return this.word32le();
case 0xFF:
return this.word64le();
case 0xFF:
return this.word64le();
default:
return firstByte;
default:
return firstByte;
}
};
Parser.prototype.varStr = function () {
Parser.prototype.varStr = function() {
var len = this.varInt();
return this.buffer(len);
};

14
util/EncFile.js

@ -1,9 +1,7 @@
var fs = require('fs');
var crypto = require('crypto');
exports.readFileSync = function(enc_method, enc_passphrase, filename)
{
exports.readFileSync = function(enc_method, enc_passphrase, filename) {
// read entire file into memory
var fileData = fs.readFileSync(filename, 'binary');
if (fileData.length < 32)
@ -28,14 +26,12 @@ exports.readFileSync = function(enc_method, enc_passphrase, filename)
return dec;
};
exports.readJFileSync = function(enc_method, enc_passphrase, filename)
{
exports.readJFileSync = function(enc_method, enc_passphrase, filename) {
var raw = this.readFileSync(enc_method, enc_passphrase, filename);
return JSON.parse(raw);
};
exports.writeFileSync = function(enc_method, enc_passphrase, filename, data)
{
exports.writeFileSync = function(enc_method, enc_passphrase, filename, data) {
// encrypt to ciphertext
var cipher = crypto.createCipher(enc_method, enc_passphrase);
var crypted = cipher.update(data, 'binary', 'binary');
@ -51,9 +47,7 @@ exports.writeFileSync = function(enc_method, enc_passphrase, filename, data)
return true;
};
exports.writeJFileSync = function(enc_method, enc_passphrase, filename, obj)
{
exports.writeJFileSync = function(enc_method, enc_passphrase, filename, obj) {
var raw = JSON.stringify(obj);
return this.writeFileSync(enc_method, enc_passphrase, filename, raw);
};

25
util/EncodedData.js

@ -9,7 +9,7 @@ var base58 = imports.base58 || require('../lib/Base58').base58Check;
// new EncodedData(<version>, <20-byte-hash>)
function EncodedData(data, encoding) {
this.data = data;
if(!encoding && (typeof data == 'string')) {
if (!encoding && (typeof data == 'string')) {
this.__proto__ = this.encodings['base58'];
} else {
this.__proto__ = this.encodings[encoding || 'binary'];
@ -18,7 +18,7 @@ function EncodedData(data, encoding) {
// get or set the encoding used (transforms data)
EncodedData.prototype.encoding = function(encoding) {
if(encoding && (encoding != this._encoding)) {
if (encoding && (encoding != this._encoding)) {
this.data = this.as(encoding);
this.__proto__ = this.encodings[encoding];
}
@ -32,7 +32,7 @@ EncodedData.prototype.withEncoding = function(encoding) {
// answer the data in the given encoding
EncodedData.prototype.as = function(encoding) {
if(!encodings[encoding]) throw new Error('invalid encoding');
if (!encodings[encoding]) throw new Error('invalid encoding');
return this.converters[encoding].call(this);
};
@ -46,7 +46,7 @@ EncodedData.prototype.isValid = function() {
try {
this.validate();
return true;
} catch(e) {
} catch (e) {
return false;
}
};
@ -61,7 +61,7 @@ EncodedData.prototype.isValid = function() {
try {
this.validate();
return true;
} catch(e) {
} catch (e) {
return false;
}
};
@ -129,10 +129,12 @@ var encodings = {
},
};
var no_conversion = function() {return this.data;};
for(var k in encodings) {
if(encodings.hasOwnProperty(k)){
if(!encodings[k].converters[k])
var no_conversion = function() {
return this.data;
};
for (var k in encodings) {
if (encodings.hasOwnProperty(k)) {
if (!encodings[k].converters[k])
encodings[k].converters[k] = no_conversion;
encodings[k]._encoding = k;
}
@ -140,10 +142,10 @@ for(var k in encodings) {
EncodedData.applyEncodingsTo = function(aClass) {
var tmp = {};
for(var k in encodings) {
for (var k in encodings) {
var enc = encodings[k];
var obj = {};
for(var j in enc) {
for (var j in enc) {
obj[j] = enc[j];
}
obj.__proto__ = aClass.prototype;
@ -155,4 +157,3 @@ EncodedData.applyEncodingsTo = function(aClass) {
EncodedData.applyEncodingsTo(EncodedData);
module.exports = require('soop')(EncodedData);

20
util/VersionedData.js

@ -1,10 +1,10 @@
var imports = require('soop').imports();
var base58 = imports.base58 || require('../lib/Base58').base58Check;
var parent = imports.parent || require('./EncodedData');
var imports = require('soop').imports();
var base58 = imports.base58 || require('../lib/Base58').base58Check;
var parent = imports.parent || require('./EncodedData');
function VersionedData(version, payload) {
if(typeof version != 'number') {
if (typeof version != 'number') {
VersionedData.super(this, arguments);
return;
};
@ -19,8 +19,10 @@ parent.applyEncodingsTo(VersionedData);
// get or set the version data (the first byte of the address)
VersionedData.prototype.version = function(num) {
if(num || (num === 0)) {
this.doAsBinary(function() {this.data.writeUInt8(num, 0);});
if (num || (num === 0)) {
this.doAsBinary(function() {
this.data.writeUInt8(num, 0);
});
return num;
}
return this.as('binary').readUInt8(0);
@ -28,8 +30,10 @@ VersionedData.prototype.version = function(num) {
// get or set the payload data (as a Buffer object)
VersionedData.prototype.payload = function(data) {
if(data) {
this.doAsBinary(function() {data.copy(this.data,1);});
if (data) {
this.doAsBinary(function() {
data.copy(this.data, 1);
});
return data;
}
return this.as('binary').slice(1);

9
util/error.js

@ -1,4 +1,3 @@
/**
* Used during transcation verification when a source txout is missing.
*
@ -9,8 +8,8 @@ function MissingSourceError(msg, missingTxHash) {
// TODO: Since this happens in normal operation, perhaps we should
// avoid generating a whole stack trace.
Error.call(this);
// This is not compatible with firefox.
// Error.captureStackTrace(this, arguments.callee);
// This is not compatible with firefox.
// Error.captureStackTrace(this, arguments.callee);
this.message = msg;
this.missingTxHash = missingTxHash;
this.name = 'MissingSourceError';
@ -32,8 +31,8 @@ function VerificationError(msg, missingTxHash) {
// avoid generating a whole stack trace.
Error.call(this);
// This is not compatible with firefox.
// Error.captureStackTrace(this, arguments.callee);
// This is not compatible with firefox.
// Error.captureStackTrace(this, arguments.callee);
this.message = msg;
this.missingTxHash = missingTxHash;
this.name = 'VerificationError';

2
util/index.js

@ -1 +1 @@
module.exports = require('./util');
module.exports = require('./util');

23
util/log.js

@ -6,13 +6,28 @@ var cl = function() {
};
var loggers = {
none: {info: noop, warn: noop, err: noop, debug: noop},
normal: {info: cl, warn: cl, err: cl, debug: noop},
debug: {info: cl, warn: cl, err: cl, debug: cl},
none: {
info: noop,
warn: noop,
err: noop,
debug: noop
},
normal: {
info: cl,
warn: cl,
err: cl,
debug: noop
},
debug: {
info: cl,
warn: cl,
err: cl,
debug: cl
},
};
var config = require('../config');
if(config.log) {
if (config.log) {
module.exports = config.log;
} else {
module.exports = loggers[config.logger || 'normal'];

5
util/time.js

@ -1,7 +1,4 @@
// current time, in seconds
exports.curtime = function curtime()
{
exports.curtime = function curtime() {
return Math.round(Date.now() / 1000);
}

8
util/util.js

@ -26,7 +26,7 @@ var sha512 = exports.sha512 = function(data) {
return new Buffer(crypto.createHash('sha512').update(data).digest('binary'), 'binary');
};
var sha512hmac = exports.sha512hmac = function (data, key) {
var sha512hmac = exports.sha512hmac = function(data, key) {
if (inBrowser) {
var skey = sjcl.codec.hex.toBits(key.toString('hex'));
var sdata = sjcl.codec.hex.toBits(data.toString('hex'));
@ -41,7 +41,7 @@ var sha512hmac = exports.sha512hmac = function (data, key) {
return hash;
};
var ripe160 = exports.ripe160 = function (data) {
var ripe160 = exports.ripe160 = function(data) {
if (!Buffer.isBuffer(data)) {
throw new Error('arg should be a buffer');
}
@ -360,12 +360,12 @@ var decodeDiffBits = exports.decodeDiffBits = function(diffBits, asBigInt) {
var target = bignum(diffBits & 0xffffff);
/*
* shiftLeft is not implemented on the bignum browser
* shiftLeft is not implemented on the bignum browser
*
* target = target.shiftLeft(8*((diffBits >>> 24) - 3));
*/
var mov = 8*((diffBits >>> 24) - 3);
var mov = 8 * ((diffBits >>> 24) - 3);
while (mov-- > 0)
target = target.mul(2);

Loading…
Cancel
Save