This commit is contained in:
dthorpe 2014-04-09 23:01:59 -07:00
commit dd5ef29831
19 changed files with 305 additions and 19 deletions

5
.travis.yml Normal file
View File

@ -0,0 +1,5 @@
language: node_js
node_js:
- "0.10"
script: "mocha"

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

@ -186,10 +186,15 @@ Connection.prototype.sendVersion = function () {
};
Connection.prototype.sendGetBlocks = function (starts, stop, wantHeaders) {
var put = new Put();
put.word32le(this.sendVer);
// Default value for stop is 0 to get as many blocks as possible (500)
stop = stop || util.NULL_HASH;
var put = new Put();
// https://en.bitcoin.it/wiki/Protocol_specification#getblocks
put.word32le(this.sendVer);
put.varint(starts.length);
for (var i = 0; i < starts.length; i++) {
if (starts[i].length != 32) {
throw new Error('Invalid hash length');
@ -443,8 +448,8 @@ Connection.prototype.parseMessage = function (command, payload) {
data.headers = [];
for (i = 0; i < data.count; i++) {
var header = new Block();
header.parse(parser);
data.headers.push(header);
header.parse(parser);
data.headers.push(header);
}
break;

View File

@ -111,6 +111,9 @@ PeerManager.prototype.addConnection = function(socketConn, peer) {
};
PeerManager.prototype.handleVersion = function(e) {
e.peer.version = e.message.version;
e.peer.start_height = e.message.start_height;
if (!e.conn.inbound) {
// TODO: Advertise our address (if listening)
}
@ -132,7 +135,7 @@ PeerManager.prototype.handleReady = function (e) {
});
if(this.isConnected == false) {
this.emit('netConnected');
this.emit('netConnected', e);
this.isConnected = true;
}
};

View File

@ -1,6 +1,8 @@
Bitcore
=======
[![Build Status](https://travis-ci.org/bitpay/bitcore.svg?branch=master)](https://travis-ci.org/bitpay/bitcore)
A pure, powerful core for your bitcoin project.
Bitcore is a complete, native interface to the Bitcoin network, and provides the core functionality needed to develop apps for bitcoin.

View File

@ -64,7 +64,10 @@ var createBitcore = function(opts) {
opts.dir = opts.dir || '';
// concat browser vendor files
exec('cd ' + opts.dir + 'browser; sh concat.sh', puts);
var cwd = process.cwd();
process.chdir(opts.dir + 'browser');
exec('sh concat.sh', puts);
process.chdir(cwd);
if (!opts.includeall && (!opts.submodules || opts.submodules.length === 0)) {
if (!opts.stdout) console.log('Must use either -s or -a option. For more info use the --help option');

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

@ -0,0 +1,17 @@
var bitcore = require('../bitcore');
var Address = bitcore.Address;
var bitcoreUtil = bitcore.util;
var Script = bitcore.Script;
var network = bitcore.networks.livenet;
var script = ''; // write down your script here
var s = Script.fromHumanReadable(script);
var hash = bitcoreUtil.sha256ripe160(s.getBuffer());
var version = network.addressScript;
var addr = new Address(version, hash);
var addrStr = addr.as('base58');
// This outputs the "address" of thescript
console.log(addrStr);

View File

@ -0,0 +1,72 @@
/**
* This is a simple script that will display network messages.
* It users the Peer / Connection classes * directly instead of
* relying on PeerManager.
*/
// replace by require('bitcore') if you use somewhere else
var bitcore = require('../');
//bitcore.config.logger = 'debug';
var Peer = bitcore.Peer,
Connection = bitcore.Connection;
var peer = new Peer('127.0.0.1', 8333);
var socket = peer.createConnection();
var con = new Connection(socket, peer);
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) {
console.log('disconnect: ', msg);
});
con.on('connect', function (msg) {
console.log('Connected to %s', msg.peer.host + ':' + msg.peer.port);
});
/* Listen P2P messages */
// 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 () {
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);
console.log.apply(console, args);
});
});
}
listen('getaddr', function (event, log) {
log('Received message getaddr');
log(event);
});
listen('verack', function (event, log) {
log('Received message verack');
});
listen('version', function (event, log) {
log('Received message version (%s)', event.message.version);
});
listen('addr', function (event, log) {
log('Received message addr (%s addresses)', event.message.addrs.length);
});
listen('inv', function (event, log) {
log('Received message inv (%s invs)', event.message.count);
console.log(event.message.invs);
});

View File

@ -0,0 +1 @@
Run `node browser/build.js -a` in the repository's root directory before using those examples.

View File

@ -9,12 +9,12 @@
<pre>
<div id='content'></div>
</pre>
<script src="../browser/bundle.js"></script>
<script src="../../browser/bundle.js"></script>
<script type="text/javascript">
var Address = require('bitcore').Address;
print = function(s,s2,s3){
var print = function (s,s2,s3) {
var div = document.getElementById('content');
div.innerHTML += s + (s2||'') + (s3||'') + '<br />';
};
@ -90,6 +90,6 @@
print('<hr><h1>TransactionBuilder</h1>');
console.log = print;
</script>
<script src="./CreateAndSignTx.js"></script>
<script src="../CreateAndSignTx-PayToPubkeyHash.js"></script>
</body>
</html>

View File

@ -1,12 +1,13 @@
<!DOCTYPE html>
<html>
<body>
<script src="../browser/bundle.js"></script>
<script src="../../browser/bundle.js"></script>
<pre id="console"></pre>
<script>
var bitcore = require('bitcore');
var Address = bitcore.Address;
var a = new Address('1KerhGhLn3SYBEQwby7VyVMWf16fXQUj5d');
console.log('1KerhGhLn3SYBEQwby7VyVMWf16fXQUj5d is valid? '+a.isValid());
document.getElementById('console').innerHTML = '1KerhGhLn3SYBEQwby7VyVMWf16fXQUj5d is valid? '+a.isValid();
</script>
</body>
</html>

View File

@ -79,6 +79,20 @@
"browser-pack": "~2.0.1",
"istanbul": "~0.2.6"
},
"testling": {
"harness": "mocha-tdd",
"html": "test/index-testling.html",
"browsers": [
"ie/6..latest",
"chrome/22..latest",
"firefox/16..latest",
"safari/latest",
"opera/11.0..latest",
"iphone/6",
"ipad/6",
"android-browser/latest"
]
},
"license": "MIT",
"engines": {
"node": ">=0.10"

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

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

@ -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 || [{
@ -644,7 +644,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

@ -187,4 +187,17 @@ describe('util', function() {
});
});
});
describe('#calcDifficulty', function() {
var bitsgenesis = 486604799;
it('should work for the bits from the genesis block; ' + bitsgenesis, function() {
var difficulty = coinUtil.calcDifficulty(bitsgenesis);
difficulty.should.equal(1);
});
var randomotherbits = 419476394;
it('should work for the bits in a randomly chosen block, eg [00000000000000001fef2bbc6da9b65e16f9187b7d88f15a308490bf2c9b8e1d] ' + randomotherbits, function() {
var difficulty = coinUtil.calcDifficulty(randomotherbits);
difficulty.should.equal(6119726089);
});
});
});

View File

@ -510,4 +510,4 @@ exports.INT64_MAX = INT64_MAX;
// makes 1 BTC
exports.COIN = 100000000;
exports.MAX_TARGET = new Buffer('00000000FFFF0000000000000000000000000000000000000000000000000000', 'hex');
var MAX_TARGET = exports.MAX_TARGET = new Buffer('00000000FFFF0000000000000000000000000000000000000000000000000000', 'hex');