merged in upstream changes, resolved conflict in package.json, add test for SOCKS5 Connection instantiation

This commit is contained in:
Gordon Hall 2014-04-11 14:01:55 -04:00
commit 3ba4352f7f
21 changed files with 297 additions and 38 deletions

View File

@ -1,7 +1,9 @@
'use strict';
var imports = require('soop').imports();
var parent = imports.parent || require('./util/VersionedData');
var networks= imports.networks || require('./networks');
var coinUtil = imports.coinUtil || require('./util/util');
var parent = imports.parent || require('./util/VersionedData');
var networks = imports.networks || require('./networks');
var Script = imports.Script || require('./Script');
function Address() {
Address.super(this, arguments);
@ -10,6 +12,47 @@ function Address() {
Address.parent = parent;
parent.applyEncodingsTo(Address);
//create a pubKeyHash address
Address.fromPubKey = function(pubKey, network) {
if (!network)
network = 'livenet';
if (pubKey.length != 33 && pubKey.length != 65)
throw new Error('Invalid public key');
var version = networks[network].addressVersion;
var hash = coinUtil.sha256ripe160(pubKey);
return new Address(version, hash);
};
//create a p2sh m-of-n multisig address
Address.fromPubKeys = function(mReq, pubKeys, network, opts) {
if (!network)
network = 'livenet';
for (var i in pubKeys) {
var pubKey = pubKeys[i];
if (pubKey.length != 33 && pubKey.length != 65)
throw new Error('Invalid public key');
}
var script = Script.createMultisig(mReq, pubKeys, opts);
return Address.fromScript(script, network);
};
//create a p2sh address from redeemScript
Address.fromScript = function(script, network) {
if (!network)
network = 'livenet';
var version = networks[network].P2SHVersion;
var buf = script.getBuffer();
var hash = coinUtil.sha256ripe160(buf);
return new Address(version, hash);
};
Address.prototype.validate = function() {
this.doAsBinary(function() {

View File

@ -9,8 +9,7 @@ exports.patch = function(Buffers) {
}
var pos = this.pos(i);
this.buffers = this.buffers.slice(pos.buf);
this.buffers[0].length -= pos.offset;
this.buffers[0].offset += pos.offset;
this.buffers[0] = new Buffer(this.buffers[0].slice(pos.offset));
this.length -= i;
};
};

View File

@ -176,7 +176,7 @@ peerman.on('connect', function() {
var conn = peerman.getActiveConnection();
if (conn) {
var outs = [{address:toAddress, amount:amt}];
var opts = {remainderAddress: changeAddressString};
var opts = {remainderOut: {address: changeAddressString}};
var Builder = bitcore.TransactionBuilder;
var tx = new Builder(opts)

View File

@ -36,7 +36,6 @@ function Script(buffer) {
this.chunks = [];
this.parse();
}
this.class = Script;
Script.TX_UNKNOWN = TX_UNKNOWN;
Script.TX_PUBKEY = TX_PUBKEY;

View File

@ -40,6 +40,8 @@ function TransactionIn(data) {
this.q = data.q ? data.q : data.sequence;
}
TransactionIn.MAX_SEQUENCE = 0xffffffff;
TransactionIn.prototype.getScript = function getScript() {
return new Script(this.s);
};
@ -125,7 +127,6 @@ function Transaction(data) {
}) : [];
if (data.buffer) this._buffer = data.buffer;
};
this.class = Transaction;
Transaction.In = TransactionIn;
Transaction.Out = TransactionOut;
@ -197,6 +198,22 @@ Transaction.prototype.getHash = function getHash() {
return this.hash;
};
Transaction.prototype.calcNormalizedHash = function () {
this.normalizedHash = this.hashForSignature(new Script(),0, SIGHASH_ALL);
return this.normalizedHash;
};
Transaction.prototype.getNormalizedHash = function () {
if (!this.normalizedHash || !this.normalizedHash.length) {
this.normalizedHash = this.calcNormalizedHash();
}
return this.normalizedHash;
};
// convert encoded list of inputs to easy-to-use JS list-of-lists
Transaction.prototype.inputs = function inputs() {
var res = [];
@ -432,7 +449,8 @@ Transaction.prototype.getStandardizedObject = function getStandardizedObject() {
prev_out: {
hash: buffertools.reverse(new Buffer(txin.getOutpointHash())).toString('hex'),
n: txin.getOutpointIndex()
}
},
sequence: txin.q
};
if (txin.isCoinBase()) {
txinObj.coinbase = txin.s.toString('hex');
@ -568,7 +586,7 @@ Transaction.prototype.calcSize = function() {
return totalSize;
};
Transaction.prototype.getSize = function getHash() {
Transaction.prototype.getSize = function () {
if (!this.size) {
this.size = this.calcSize();
}

View File

@ -110,6 +110,7 @@ function TransactionBuilder(opts) {
this.tx = {};
this.inputsSigned= 0;
this.signaturesAdded= 0;
return this;
}
@ -482,7 +483,7 @@ TransactionBuilder.prototype._signPubKey = function(walletKeyMap, input, txSigHa
var scriptSig = new Script();
scriptSig.chunks.push(sig);
scriptSig.updateBuffer();
return {isFullySigned: true, signaturesAdded: true, script: scriptSig.getBuffer()};
return {isFullySigned: true, signaturesAdded: 1, script: scriptSig.getBuffer()};
};
TransactionBuilder.prototype._signPubKeyHash = function(walletKeyMap, input, txSigHash) {
@ -501,7 +502,7 @@ TransactionBuilder.prototype._signPubKeyHash = function(walletKeyMap, input, txS
scriptSig.chunks.push(sig);
scriptSig.chunks.push(wk.privKey.public);
scriptSig.updateBuffer();
return {isFullySigned: true, signaturesAdded: true, script: scriptSig.getBuffer()};
return {isFullySigned: true, signaturesAdded: 1, script: scriptSig.getBuffer()};
};
// FOR TESTING
@ -577,7 +578,7 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig
originalScriptBuf = this.tx.ins[input.i].s;
var scriptSig = new Script (originalScriptBuf);
var signaturesAdded = false;
var signaturesAdded = 0;
for(var j=0; j<l && scriptSig.countMissingSignatures(); j++) {
var wk = this._findWalletKey(walletKeyMap, {pubKeyBuf: pubkeys[j]});
@ -586,7 +587,7 @@ TransactionBuilder.prototype._signMultiSig = function(walletKeyMap, input, txSig
var newScriptSig = this._updateMultiSig(wk, scriptSig, txSigHash, nreq);
if (newScriptSig) {
scriptSig = newScriptSig;
signaturesAdded = true;
signaturesAdded++;
}
}
@ -694,6 +695,7 @@ TransactionBuilder.prototype.sign = function(keys) {
if (ret && ret.script) {
tx.ins[i].s = ret.script;
if (ret.isFullySigned) this.inputsSigned++;
if (ret.signaturesAdded) this.signaturesAdded +=ret.signaturesAdded;
}
}
return this;

View File

@ -14,6 +14,7 @@ requireWhenAccessed('bignum', 'bignum');
requireWhenAccessed('base58', 'base58-native');
requireWhenAccessed('bufferput', 'bufferput');
requireWhenAccessed('buffertools', 'buffertools');
requireWhenAccessed('Buffers.monkey', './Buffers.monkey');
requireWhenAccessed('config', './config');
requireWhenAccessed('const', './const');
requireWhenAccessed('Deserialize', './Deserialize');

View File

@ -101,6 +101,9 @@ var createBitcore = function(opts) {
b.require(opts.dir + 'base58-native', {
expose: 'base58-native'
});
b.require(opts.dir + 'buffers', {
expose: 'buffers'
});
b.require('./' + opts.dir + 'bitcore', {
expose: 'bitcore'
});

View File

@ -25,7 +25,7 @@ var run = function() {
var outs = [{address:toAddress, amount:amt}];
var keys = [priv];
var opts = {remainderAddress: changeAddressString};
var opts = {remainderOut: {address: changeAddressString}};
var Builder = bitcore.TransactionBuilder;
var tx = new Builder(opts)

View File

@ -41,10 +41,10 @@ var run = function() {
});
// multisig p2sh
var opts = {nreq:3, pubkeys:pubkeys, amount:0.05};
var opts = {nreq:3, pubkeys:pubkeys};
// p2scriphash p2sh
//var opts = [{address: an_address, amount:0.05}];
//var opts = [{address: an_address}];
var info = Builder.infoForP2sh(opts, 'testnet');
var p2shScript = info.scriptBufHex;

View File

@ -60,16 +60,17 @@
"binary": "=0.3.0",
"step": "=0.0.4",
"buffers": "=0.1.1",
"buffertools": "~2.0.1",
"browserify": "~3.32.1",
"browser-pack": "~2.0.1",
"commander": "~2.1.0",
"buffertools": "=2.1.2",
"browserify": "=3.40.0",
"browser-pack": "=2.0.1",
"commander": "=2.1.0",
"browserify-bignum": "git://github.com/maraoz/browserify-bignum.git",
"browserify-buffertools": "git://github.com/maraoz/browserify-buffertools.git",
"brfs": "~1.0.0",
"socks5-client": "~0.3.6",
"chai": "~1.9.0",
"uglifyify": "~1.2.3"
"brfs": "=1.0.0",
"chai": "=1.9.1",
"uglifyify": "=1.2.3"
},
"devDependencies": {
"grunt-contrib-watch": "~0.5.3",
@ -85,7 +86,8 @@
"istanbul": "~0.2.6"
},
"testling": {
"files": "test/test*.js",
"harness": "mocha-bdd",
"html": "test/index-testling.html",
"browsers": [
"ie/6..latest",
"chrome/22..latest",

View File

@ -160,20 +160,24 @@ Key::New()
Handle<Value>
Key::New(const Arguments& args)
{
if (!args.IsConstructCall()) {
return FromConstructorTemplate(s_ct, args);
}
HandleScope scope;
Key* key = new Key();
if (key->lastError != NULL) {
return VException(key->lastError);
// this was invoked as Key() not new Key()
if (!args.IsConstructCall()) {
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
return scope.Close(s_ct->GetFunction()->NewInstance(argc, argv));
}
else{
Key* key = new Key();
if (key->lastError != NULL) {
return VException(key->lastError);
}
key->Wrap(args.Holder());
key->Wrap(args.Holder());
return scope.Close(args.This());
return scope.Close(args.This());
}
}
Handle<Value>

52
test/index-testling.html Normal file
View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html>
<head>
<title>Mocha</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./node_modules/mocha/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="./node_modules/mocha/mocha.js"></script>
<script src="./node_modules/chai/chai.js"></script>
<script>mocha.setup('bdd')</script>
<script>mocha.reporter('tap')</script>
<script src="./browser/bundle.js"></script>
<script src="./browser/testdata.js"></script>
<script src="test/adapter.js"></script>
<script src="test/test.Address.js"></script>
<script src="test/test.basic.js"></script>
<script src="test/test.BIP32.js"></script>
<script src="test/test.Block.js"></script>
<script src="test/test.Bloom.js"></script>
<script src="test/test.Connection.js"></script>
<script src="test/test.EncodedData.js"></script>
<script src="test/test.Key.js"></script>
<script src="test/test.main.js"></script>
<script src="test/test.misc.js"></script>
<script src="test/test.Opcode.js"></script>
<script src="test/test.Peer.js"></script>
<script src="test/test.PeerManager.js"></script>
<script src="test/test.Point.js"></script>
<script src="test/test.PrivateKey.js"></script>
<script src="test/test.RpcClient.js"></script>
<script src="test/test.Script.js"></script>
<script src="test/test.ScriptInterpreter.js"></script>
<script src="test/test.sighash.js"></script>
<script src="test/test.SIN.js"></script>
<script src="test/test.SINKey.js"></script>
<script src="test/test.Transaction.js"></script>
<script src="test/test.TransactionBuilder.js"></script>
<script src="test/test.util.js"></script>
<script src="test/test.VersionedData.js"></script>
<script src="test/test.Wallet.js"></script>
<script src="test/test.WalletKey.js"></script>
<!--
-->
<script>
mocha.run();
</script>
</body>
</html>

View File

@ -82,5 +82,60 @@ describe('Address', function() {
// script testnet
new Address('2NBSBcf2KfjPEEqVusmrWdmUeNHRiUTS3Li').isScript().should.equal(true);
});
describe('#fromPubKey', function() {
it('should make this pubkeyhash address from uncompressed this public key', function() {
var pubkey = new Buffer('04fa05ce8b25010cb6e17a30e0b66668bf083c40687547748ec330ee77adf53a42abd3d26148cbacfcf79c907ddefeb2c37f8bebc0a695ba79d634449d871de218', 'hex');
var hash = bitcore.util.sha256ripe160(pubkey);
var addr = new Address(0, hash);
addr.toString().should.equal(Address.fromPubKey(pubkey).toString());
});
});
describe('#fromPubKeys', function() {
it('should make this p2sh multisig address from these pubkeys', function() {
var pubkey1 = new Buffer('03e0973263b4e0d5f5f56d25d430e777ab3838ff644db972c0bf32c31da5686c27', 'hex');
var pubkey2 = new Buffer('0371f94c57cc013507101e30794161f4e6b9efd58a9ea68838daf429b7feac8cb2', 'hex');
var pubkey3 = new Buffer('032c0d2e394541e2efdc7ac3500e16e7e69df541f38670402e95aa477202fa06bb', 'hex');
var sortedPubKeys = [pubkey3, pubkey2, pubkey1];
var mReq = 2;
var script = bitcore.Script.createMultisig(mReq, sortedPubKeys, {noSorting: true});
var hash = bitcore.util.sha256ripe160(script.getBuffer());
var version = bitcore.networks['livenet'].P2SHVersion;
var addr = new Address(version, hash);
var addr2 = Address.fromPubKeys(mReq, sortedPubKeys);
addr.toString().should.equal(addr2.toString());
});
});
describe('#fromScript', function() {
it('should make this p2sh multisig address from these pubkeys', function() {
var pubkey1 = new Buffer('03e0973263b4e0d5f5f56d25d430e777ab3838ff644db972c0bf32c31da5686c27', 'hex');
var pubkey2 = new Buffer('0371f94c57cc013507101e30794161f4e6b9efd58a9ea68838daf429b7feac8cb2', 'hex');
var pubkey3 = new Buffer('032c0d2e394541e2efdc7ac3500e16e7e69df541f38670402e95aa477202fa06bb', 'hex');
var pubKeys = [pubkey1, pubkey2, pubkey3];
var mReq = 2;
var script = bitcore.Script.createMultisig(mReq, pubKeys);
var addr = Address.fromScript(script);
var addr2 = Address.fromPubKeys(mReq, pubKeys);
addr.toString().should.equal(addr2.toString());
});
it('it should make this hand-crafted address', function() {
var pubkey1 = new Buffer('03e0973263b4e0d5f5f56d25d430e777ab3838ff644db972c0bf32c31da5686c27', 'hex');
var pubkey2 = new Buffer('0371f94c57cc013507101e30794161f4e6b9efd58a9ea68838daf429b7feac8cb2', 'hex');
var pubkey3 = new Buffer('032c0d2e394541e2efdc7ac3500e16e7e69df541f38670402e95aa477202fa06bb', 'hex');
var pubKeys = [pubkey1, pubkey2, pubkey3];
var mReq = 2;
var script = bitcore.Script.createMultisig(mReq, pubKeys);
var addr = Address.fromScript(script);
var hash = bitcore.util.sha256ripe160(script.getBuffer());
var version = bitcore.networks['livenet'].P2SHVersion;
var addr2 = new Address(version, hash);
addr.toString().should.equal(addr2.toString());
});
});
});

View File

@ -24,6 +24,7 @@ describe('Connection', function() {
should.exist(c);
});
it('should create a proxied socket if instructed', function() {
var mPeer;
var c = new Connection(null, mPeer, {
proxy: { host: 'localhost', port: 9050 }
});

View File

@ -16,6 +16,21 @@ describe('Key', function() {
var k = new Key();
should.exist(k);
});
it('should not fail when called as Key() without "new"', function() {
var key = Key();
should.exist(key);
});
it('should not fail when called as Key() without "new" with some args', function() {
var key = Key(1, 2, 3, 4, 5);
should.exist(key);
});
it('should have correct properties when called with Key() without "new"', function() {
var key = Key();
key.compressed.should.equal(true);
should.not.exist(key.public);
should.not.exist(key.private);
should.exist(key);
});
it('should be able to generateSync instance', function() {
var k = Key.generateSync();
should.exist(k);

View File

@ -5,7 +5,7 @@ var bitcore = bitcore || require('../bitcore');
var should = chai.should();
var PeerManagerModule = bitcore.PeerManager || require('./PeerManager');
var PeerManagerModule = bitcore.PeerManager;
var PeerManager;

View File

@ -48,5 +48,12 @@ describe('PrivateKey', function() {
var a = new PrivateKey('5JZsbYcnYN8Dz2YeSLZr6aswrVevedMUSFWxpie6SPpYRb2E4Gi');
a.network().name.should.equal('livenet');
});
describe('#isValid', function() {
it('should detect this private key as valid', function() {
var privKey = new PrivateKey('5JQkUX6RNQC91xv4Www6Cgbxb6Eri6WBJjtPGqwfXVKBzT37cAf');
privKey.isValid().should.equal(true);
});
});
});

View File

@ -1,7 +1,7 @@
'use strict';
var chai = chai || require('chai');
chai.Assertion.includeStack = true;
chai.config.includeStack = true;
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -121,4 +121,20 @@ describe('Transaction', function() {
coreTest(testdata.dataTxValid, true);
coreTest(testdata.dataTxInvalid, false);
it('#normalized hash', function() {
// string output generated from: bitcoind createrawtransaction '[{"txid": "2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc1","vout":1},{"txid":"2ac165fa7a3a2b535d106a0041c7568d03b531e58aeccdd3199d7289ab12cfc2","vout":0} ]' '{"mrPnbY1yKDBsdgbHbS7kJ8GVm8F66hWHLE":0.08}'
//
var Parser = bitcore.BinaryParser;
var tx = new Transaction();
tx.parse(new Buffer('0100000002c1cf12ab89729d19d3cdec8ae531b5038d56c741006a105d532b3a7afa65c12a0100000000ffffffffc2cf12ab89729d19d3cdec8ae531b5038d56c741006a105d532b3a7afa65c12a0000000000ffffffff0100127a00000000001976a914774e603bafb717bd3f070e68bbcccfd907c77d1388ac00000000','hex'));
tx.getNormalizedHash().toString('hex').should.equal('1f7d2666e2d0d663e098abb76db6ba392da972d21c14b6ea6f4336171d29966b');
var tx2 = new Transaction();
tx2.parse(new Buffer('0100000001c1cf12ab89729d19d3cdec8ae531b5038d56c741006a105d532b3a7afa65c12a010000004b00473044022059085ff1b8ad03033e60969b1c770aa29ba5d74c28a9992c514b100d860792f1022057a307f77f91f4563651eefc0a959aa916d275c58525320309b6aeeff43d0d8a010000ffffffff0215cd5b07000000001976a91434f8e0c5be216025a52addf18a987543cad23f7a88acdbd53e340000000017a9147a769913c0721b1e0aa6bf8a93f4ef810c60587a8700000000','hex'));
tx2.getNormalizedHash().toString('hex').should.equal('e298bbf3734898581b8e342f2064236abf0acca6ac7e9a3009a16ef7b64d4983');
});
});

View File

@ -1,7 +1,7 @@
'use strict';
var chai = chai || require('chai');
chai.Assertion.includeStack = true;
chai.config.includeStack = true;
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -563,7 +563,7 @@ describe('TransactionBuilder', function() {
};
var data = getInfoForP2sh();
// multisig p2sh
var p2shOpts = {nreq:3, pubkeys:data.pubkeys, amount:0.05};
var p2shOpts = {nreq:3, pubkeys:data.pubkeys};
var info = TransactionBuilder.infoForP2sh(p2shOpts, network);
var outs = outs || [{
@ -605,36 +605,43 @@ describe('TransactionBuilder', function() {
var k2 = testdata.dataUnspentSign.keyStringsP2sh.slice(1,2);
var k5 = testdata.dataUnspentSign.keyStringsP2sh.slice(4,5);
b.isFullySigned().should.equal(false);
b.signaturesAdded.should.equal(0);
b.sign(k1);
b.isFullySigned().should.equal(false);
b.signaturesAdded.should.equal(1);
var tx = b.build();
tx.ins.length.should.equal(1);
tx.outs.length.should.equal(2);
tx.isComplete().should.equal(false);
b.signaturesAdded.should.equal(1);
// Sign with the same
b.sign(k1);
b.isFullySigned().should.equal(false);
tx.isComplete().should.equal(false);
b.signaturesAdded.should.equal(1);
// Sign with k5
b.sign(k5);
///
b.isFullySigned().should.equal(false);
tx.isComplete().should.equal(false);
b.signaturesAdded.should.equal(2);
// Sign with same
b.sign(k5);
b.isFullySigned().should.equal(false);
tx.isComplete().should.equal(false);
b.signaturesAdded.should.equal(2);
// Sign k2
b.sign(k2);
b.isFullySigned().should.equal(true);
tx.isComplete().should.equal(true);
b.signaturesAdded.should.equal(3);
});
it('should sign in steps a p2sh/p2pubkeyhash tx', function() {
@ -644,7 +651,7 @@ describe('TransactionBuilder', function() {
remainderOut: {address: 'mwZabyZXg8JzUtFX1pkGygsMJjnuqiNhgd'},
};
// p2hash/ p2sh
var p2shOpts = {address:'mgwqzy6pF5BSc72vxHBFSnnhNEBcV4TJzV', amount:0.05};
var p2shOpts = {address:'mgwqzy6pF5BSc72vxHBFSnnhNEBcV4TJzV'};
var info = TransactionBuilder.infoForP2sh(p2shOpts, network);
//addr: 2NAwCQ1jPYPrSsyBQvfP6AJ6d6SSxnHsZ4e

View File

@ -3,6 +3,7 @@
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var buffertools = require('buffertools');
buffertools.extend();
var should = chai.should();
@ -15,6 +16,9 @@ var base58Check = base58.base58Check;
var Address = bitcore.Address;
var networks = bitcore.networks;
var WalletKey = bitcore.WalletKey;
var Buffers = require('buffers');
var m = bitcore['Buffers.monkey'] || require('../Buffers.monkey');
m.patch(Buffers);
describe('Miscelaneous stuff', function() {
it('should initialze the config object', function() {
@ -26,7 +30,7 @@ describe('Miscelaneous stuff', function() {
it('should initialze the network object', function() {
should.exist(networks);
var nets = [networks.livenet, networks.testnet];
for (var i=0; i<2; i++) {
for (var i = 0; i < 2; i++) {
var net = nets[i];
should.exist(net.addressVersion);
should.exist(net.privKeyVersion);
@ -42,8 +46,39 @@ describe('Miscelaneous stuff', function() {
should.exist(bitcore.Deserialize);
should.exist(bitcore.Deserialize.intFromCompact);
});
it('should initialze the Buffer class', function() {
should.exist(bitcore.Buffer);
});
describe('Buffers monkey patch', function() {
var bufs;
beforeEach(function() {
bufs = new Buffers();
bufs.push(new Buffer('aaaaaa', 'hex'));
bufs.push(new Buffer('bbbb', 'hex'));
bufs.push(new Buffer('cc', 'hex'));
});
it('should monkey patch the Buffers class', function() {
should.exist(bufs.skip);
});
it('should work for 0', function() {
bufs.skip(0);
bufs.toBuffer().toHex().should.equal('aaaaaabbbbcc');
});
it('should work for length', function() {
bufs.skip(bufs.length);
bufs.toBuffer().toHex().should.equal('');
});
it('should work for middle values', function() {
bufs.skip(4);
bufs.toBuffer().toHex().should.equal('bbcc');
bufs.skip(1);
bufs.toBuffer().toHex().should.equal('cc');
bufs.skip(1);
bufs.toBuffer().toHex().should.equal('');
});
});
// bignum
it('should initialze the bignum object', function() {
should.exist(bitcore.bignum);