Merge remote-tracking branch 'matiu/feature/support-soop-browser'

Conflicts:
	Script.js
	ScriptInterpreter.js
	Transaction.js
	test/testdata.js

...conflicts resolved by taking Manuel's changes, and then manually including
Matias's changes on those same files. The conflicts resulted from differences
in indentation, which is because Matias' changes unindendented all the code
that had been but is not now inside a function.
This commit is contained in:
Ryan X. Charles 2014-03-08 19:30:21 -05:00
commit c19fb7a3ce
55 changed files with 5005 additions and 4932 deletions

View File

@ -1,22 +1,19 @@
require('classtool');
'use strict';
var imports = require('soop').imports();
var parent = imports.parent || require('./util/VersionedData');
function ClassSpec(b) {
var superclass = b.superclass || require('./util/VersionedData').class();
function Address() {
function Address() {
Address.super(this, arguments);
}
}
Address.superclass = superclass;
superclass.applyEncodingsTo(Address);
Address.parent = parent;
parent.applyEncodingsTo(Address);
Address.prototype.validate = function() {
Address.prototype.validate = function() {
this.doAsBinary(function() {
Address.super(this, 'validate', arguments);
if(this.data.length !== 21) throw new Error('invalid data length');
});
};
};
return Address;
}
module.defineClass(ClassSpec);
module.exports = require('soop')(Address);

193
Block.js
View File

@ -1,25 +1,24 @@
require('classtool');
var imports = require('soop').imports();
function spec(b) {
var util = b.util || require('./util/util');
var Debug1 = b.Debug1 || function() {};
var Script = b.Script || require('./Script').class();
var Bignum = b.Bignum || require('bignum');
var Binary = b.Binary || require('binary');
var Step = b.Step || require('step');
var buffertools = b.buffertools || require('buffertools');
var Transaction = b.Transaction || require('./Transaction').class();
var TransactionIn = Transaction.In;
var TransactionOut = Transaction.Out;
var COINBASE_OP = Transaction.COINBASE_OP;
var VerificationError = b.VerificationError || require('./util/error').VerificationError;
var BlockRules = {
var util = imports.util || require('./util/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
largestHash: Bignum(2).pow(256)
};
};
function Block(data)
{
function Block(data)
{
if ("object" !== typeof data) {
data = {};
}
@ -35,9 +34,9 @@ function spec(b) {
this.active = data.active || false;
this.chainWork = data.chainWork || util.EMPTY_BUFFER;
this.txs = data.txs || [];
}
}
Block.prototype.getHeader = function getHeader() {
Block.prototype.getHeader = function getHeader() {
var buf = new Buffer(80);
var ofs = 0;
buf.writeUInt32LE(this.version, ofs); ofs += 4;
@ -47,9 +46,9 @@ function spec(b) {
buf.writeUInt32LE(this.bits, ofs); ofs += 4;
buf.writeUInt32LE(this.nonce, ofs); ofs += 4;
return buf;
};
};
Block.prototype.parse = function parse(parser, headerOnly) {
Block.prototype.parse = function parse(parser, headerOnly) {
this.version = parser.word32le();
this.prev_hash = parser.buffer(32);
this.merkle_root = parser.buffer(32);
@ -70,26 +69,26 @@ function spec(b) {
tx.parse(parser);
this.txs.push(tx);
}
};
};
Block.prototype.calcHash = function calcHash() {
Block.prototype.calcHash = function calcHash() {
var header = this.getHeader();
return util.twoSha256(header);
};
};
Block.prototype.checkHash = function checkHash() {
Block.prototype.checkHash = function checkHash() {
if (!this.hash || !this.hash.length) return false;
return buffertools.compare(this.calcHash(), this.hash) == 0;
};
};
Block.prototype.getHash = function getHash() {
Block.prototype.getHash = function getHash() {
if (!this.hash || !this.hash.length) this.hash = this.calcHash();
return this.hash;
};
};
Block.prototype.checkProofOfWork = function checkProofOfWork() {
Block.prototype.checkProofOfWork = function checkProofOfWork() {
var target = util.decodeDiffBits(this.bits);
// TODO: Create a compare method in node-buffertools that uses the correct
@ -104,30 +103,30 @@ function spec(b) {
buffertools.reverse(this.hash);
return true;
};
};
/**
/**
* 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() {
Block.prototype.getWork = function getWork() {
var target = util.decodeDiffBits(this.bits, true);
return BlockRules.largestHash.div(target.add(1));
};
};
Block.prototype.checkTimestamp = function checkTimestamp() {
Block.prototype.checkTimestamp = function checkTimestamp() {
var currentTime = new Date().getTime() / 1000;
if (this.timestamp > currentTime + BlockRules.maxTimeOffset) {
throw new VerificationError('Timestamp too far into the future');
}
return true;
};
};
Block.prototype.checkTransactions = function checkTransactions(txs) {
Block.prototype.checkTransactions = function checkTransactions(txs) {
if (!Array.isArray(txs) || txs.length <= 0) {
throw new VerificationError('No transactions');
}
@ -141,15 +140,15 @@ function spec(b) {
}
return true;
};
};
/**
/**
* Build merkle tree.
*
* Ported from Java. Original code: BitcoinJ by Mike Hearn
* Copyright (c) 2011 Google Inc.
*/
Block.prototype.getMerkleTree = function getMerkleTree(txs) {
Block.prototype.getMerkleTree = function getMerkleTree(txs) {
// The merkle hash is based on a tree of hashes calculated from the transactions:
//
// merkleHash
@ -188,14 +187,14 @@ function spec(b) {
}
return tree;
};
};
Block.prototype.calcMerkleRoot = function calcMerkleRoot(txs) {
Block.prototype.calcMerkleRoot = function calcMerkleRoot(txs) {
var tree = this.getMerkleTree(txs);
return tree[tree.length - 1];
};
};
Block.prototype.checkMerkleRoot = function checkMerkleRoot(txs) {
Block.prototype.checkMerkleRoot = function checkMerkleRoot(txs) {
if (!this.merkle_root || !this.merkle_root.length) {
throw new VerificationError('No merkle root');
}
@ -205,9 +204,9 @@ function spec(b) {
}
return true;
};
};
Block.prototype.checkBlock = function checkBlock(txs) {
Block.prototype.checkBlock = function checkBlock(txs) {
if (!this.checkHash()) {
throw new VerificationError("Block hash invalid");
}
@ -221,31 +220,31 @@ function spec(b) {
}
}
return true;
};
};
Block.getBlockValue = function getBlockValue(height) {
Block.getBlockValue = function getBlockValue(height) {
var subsidy = Bignum(50).mul(util.COIN);
subsidy = subsidy.div(Bignum(2).pow(Math.floor(height / 210000)));
return subsidy;
};
};
Block.prototype.getBlockValue = function getBlockValue() {
Block.prototype.getBlockValue = function getBlockValue() {
return Block.getBlockValue(this.height);
};
};
Block.prototype.toString = function toString() {
Block.prototype.toString = function toString() {
return "<Block " + util.formatHashAlt(this.hash) + " height="+this.height+">";
};
};
/**
/**
* Initializes some properties based on information from the parent block.
*/
Block.prototype.attachTo = function attachTo(parent) {
Block.prototype.attachTo = function attachTo(parent) {
this.height = parent.height + 1;
this.setChainWork(parent.getChainWork().add(this.getWork()));
};
};
Block.prototype.setChainWork = function setChainWork(chainWork) {
Block.prototype.setChainWork = function setChainWork(chainWork) {
if (Buffer.isBuffer(chainWork)) {
// Nothing to do
} else if ("function" === typeof chainWork.toBuffer) { // duck-typing bignum
@ -255,24 +254,24 @@ function spec(b) {
}
this.chainWork = chainWork;
};
};
Block.prototype.getChainWork = function getChainWork() {
Block.prototype.getChainWork = function getChainWork() {
return Bignum.fromBuffer(this.chainWork);
};
};
/**
/**
* Compares the chainWork of two blocks.
*/
Block.prototype.moreWorkThan = function moreWorkThan(otherBlock) {
Block.prototype.moreWorkThan = function moreWorkThan(otherBlock) {
return this.getChainWork().cmp(otherBlock.getChainWork()) > 0;
};
};
/**
/**
* Returns the difficulty target for the next block after this one.
*/
Block.prototype.getNextWork =
function getNextWork(blockChain, nextBlock, callback) {
Block.prototype.getNextWork =
function getNextWork(blockChain, nextBlock, callback) {
var self = this;
var powLimit = blockChain.getMinDiff();
@ -371,13 +370,13 @@ function spec(b) {
}
);
}
};
};
var medianTimeSpan = 11;
var medianTimeSpan = 11;
Block.prototype.getMedianTimePast =
function getMedianTimePast(blockChain, callback)
{
Block.prototype.getMedianTimePast =
function getMedianTimePast(blockChain, callback)
{
var self = this;
Step(
@ -407,11 +406,11 @@ function spec(b) {
},
callback
);
};
};
Block.prototype.verifyChild =
function verifyChild(blockChain, child, callback)
{
Block.prototype.verifyChild =
function verifyChild(blockChain, child, callback)
{
var self = this;
Step(
@ -444,11 +443,11 @@ function spec(b) {
},
callback
);
};
};
Block.prototype.createCoinbaseTx =
function createCoinbaseTx(beneficiary)
{
Block.prototype.createCoinbaseTx =
function createCoinbaseTx(beneficiary)
{
var tx = new Transaction();
tx.ins.push(new TransactionIn({
s: util.EMPTY_BUFFER,
@ -460,11 +459,11 @@ function spec(b) {
s: Script.createPubKeyOut(beneficiary).getBuffer()
}));
return tx;
};
};
Block.prototype.prepareNextBlock =
function prepareNextBlock(blockChain, beneficiary, time, callback)
{
Block.prototype.prepareNextBlock =
function prepareNextBlock(blockChain, beneficiary, time, callback)
{
var self = this;
var newBlock = new Block();
@ -512,11 +511,11 @@ function spec(b) {
},
callback
);
};
};
Block.prototype.mineNextBlock =
function mineNextBlock(blockChain, beneficiary, time, miner, callback)
{
Block.prototype.mineNextBlock =
function mineNextBlock(blockChain, beneficiary, time, miner, callback)
{
this.prepareNextBlock(blockChain, beneficiary, time, function (err, data) {
try {
if (err) throw err;
@ -539,20 +538,20 @@ function spec(b) {
callback(e);
}
});
};
};
Block.prototype.solve = function solve(miner, callback) {
Block.prototype.solve = function solve(miner, callback) {
var header = this.getHeader();
var target = util.decodeDiffBits(this.bits);
miner.solve(header, target, callback);
};
};
/**
/**
* Returns an object with the same field names as jgarzik's getblock patch.
*/
Block.prototype.getStandardizedObject =
function getStandardizedObject(txs)
{
Block.prototype.getStandardizedObject =
function getStandardizedObject(txs)
{
var block = {
hash: util.formatHashFull(this.getHash()),
version: this.version,
@ -587,8 +586,6 @@ function spec(b) {
block.size = this.size;
}
return block;
};
return Block;
};
module.defineClass(spec);
module.exports = require('soop')(Block);

View File

@ -1,31 +1,28 @@
require('classtool');
var MAX_BLOOM_FILTER_SIZE = 36000; // bytes
var MAX_HASH_FUNCS = 50;
var LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455;
var LN2 = 0.6931471805599453094172321214581765680755001343602552;
var bit_mask = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80];
function ClassSpec(b) {
var MAX_BLOOM_FILTER_SIZE = 36000; // bytes
var MAX_HASH_FUNCS = 50;
var LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455;
var LN2 = 0.6931471805599453094172321214581765680755001343602552;
var bit_mask = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80];
function Bloom() {
function Bloom() {
this.data = '';
this.hashFuncs = 0;
};
};
function ROTL32(x, r) {
function ROTL32(x, r) {
return (x << r) | (x >> (32 - r));
};
};
function getBlockU32(blockIdx, data) {
function getBlockU32(blockIdx, data) {
var idx = blockIdx * 4;
var v = (data[idx + 0] << (0 * 8)) |
(data[idx + 1] << (1 * 8)) |
(data[idx + 2] << (2 * 8)) |
(data[idx + 3] << (3 * 8));
return v;
};
};
Bloom.prototype.hash = function(hashNum, data) {
Bloom.prototype.hash = function(hashNum, data) {
var h1 = hashNum * (0xffffffff / (this.hashFuncs - 1));
var c1 = 0xcc9e2d51;
var c2 = 0x1b873593;
@ -68,16 +65,16 @@ function ClassSpec(b) {
h1 ^= h1 >> 16;
return h1 % (this.data.length * 8);
};
};
Bloom.prototype.insert = function(data) {
Bloom.prototype.insert = function(data) {
for (var i = 0; i < this.hashFuncs; i++) {
var index = this.hash(i, data);
this.data[index >> 3] |= bit_mask[7 & index];
}
};
};
Bloom.prototype.contains = function(data) {
Bloom.prototype.contains = function(data) {
for (var i = 0; i < this.hashFuncs; i++) {
var index = this.hash(i, data);
if (!(this.data[index >> 3] & bit_mask[7 & index]))
@ -85,32 +82,30 @@ function ClassSpec(b) {
}
return true;
};
};
Bloom.prototype.sizeOk = function() {
Bloom.prototype.sizeOk = function() {
return this.data.length <= MAX_BLOOM_FILTER_SIZE &&
this.hashFuncs <= MAX_HASH_FUNCS;
};
};
function toInt(v) {
function toInt(v) {
return ~~v;
}
}
function min(a, b) {
function min(a, b) {
if (a < b)
return a;
return b;
}
}
Bloom.prototype.init = function(elements, FPRate) {
Bloom.prototype.init = function(elements, FPRate) {
var filterSize = min(toInt(-1.0 / LN2SQUARED * elements * Math.log(FPRate)),
MAX_BLOOM_FILTER_SIZE * 8) / 8;
this.data[filterSize] = 0;
this.hashFuncs = min(toInt(this.data.length * 8 / elements * LN2),
MAX_HASH_FUNCS);
};
return Bloom;
};
module.defineClass(ClassSpec);
module.exports = require('soop')(Bloom);

View File

@ -1,29 +1,28 @@
require('classtool');
var imports = require('soop').imports();
function spec(b) {
var config = b.config || require('./config');
var log = b.log || require('./util/log');
var network = b.network || require('./networks')[config.network];
var config = imports.config || require('./config');
var log = imports.log || require('./util/log');
var network = imports.network || require('./networks')[config.network];
var MAX_RECEIVE_BUFFER = 10000000;
var PROTOCOL_VERSION = 70000;
var MAX_RECEIVE_BUFFER = 10000000;
var PROTOCOL_VERSION = 70000;
var Binary = b.Binary || require('binary');
var Put = b.Put || require('bufferput');
var Buffers = b.Buffers || require('buffers');
require('./Buffers.monkey').patch(Buffers);
var noop = function() {};
var Block = require('./Block').class();
var Transaction = require('./Transaction').class();
var util = b.util || require('./util/util');
var Parser = b.Parser || require('./util/BinaryParser').class();
var buffertools = b.buffertools || require('buffertools');
var doubleSha256 = b.doubleSha256 || util.twoSha256;
var nonce = util.generateNonce();
var Binary = imports.Binary || require('binary');
var Put = imports.Put || require('bufferput');
var Buffers = imports.Buffers || require('buffers');
require('./Buffers.monkey').patch(Buffers);
var BIP0031_VERSION = 60000;
var Block = require('./Block');
var Transaction = require('./Transaction');
var util = imports.util || require('./util/util');
var Parser = imports.Parser || require('./util/BinaryParser');
var buffertools = imports.buffertools || require('buffertools');
var doubleSha256 = imports.doubleSha256 || util.twoSha256;
var nonce = util.generateNonce();
function Connection(socket, peer) {
var BIP0031_VERSION = 60000;
function Connection(socket, peer) {
Connection.super(this, arguments);
this.socket = socket;
this.peer = peer;
@ -52,10 +51,10 @@ function spec(b) {
}
this.setupHandlers();
}
Connection.superclass = b.superclass || require('events').EventEmitter;
}
Connection.parent = imports.parent || require('events').EventEmitter;
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));
@ -68,9 +67,9 @@ function spec(b) {
(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();
}
@ -79,9 +78,9 @@ function spec(b) {
socket: this.socket,
peer: this.peer
});
};
};
Connection.prototype.handleError = function(err) {
Connection.prototype.handleError = function(err) {
if (err.errno == 110 || err.errno == 'ETIMEDOUT') {
log.info('connection timed out for '+this.peer);
} else if (err.errno == 111 || err.errno == 'ECONNREFUSED') {
@ -95,17 +94,17 @@ function spec(b) {
peer: this.peer,
err: err
});
};
};
Connection.prototype.handleDisconnect = function () {
Connection.prototype.handleDisconnect = function () {
this.emit('disconnect', {
conn: this,
socket: this.socket,
peer: this.peer
});
};
};
Connection.prototype.handleMessage = function(message) {
Connection.prototype.handleMessage = function(message) {
if (!message) {
// Parser was unable to make sense of the message, drop it
return;
@ -163,13 +162,13 @@ function spec(b) {
peer: this.peer,
message: 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();
@ -184,9 +183,9 @@ function spec(b) {
put.word32le(0);
this.sendMessage('version', put.buffer());
};
};
Connection.prototype.sendGetBlocks = function (starts, stop, wantHeaders) {
Connection.prototype.sendGetBlocks = function (starts, stop, wantHeaders) {
var put = new Put();
put.word32le(this.sendVer);
@ -210,13 +209,13 @@ function spec(b) {
if (wantHeaders)
command = 'getheaders';
this.sendMessage(command, put.buffer());
};
};
Connection.prototype.sendGetHeaders = function(starts, stop) {
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++) {
@ -224,14 +223,14 @@ function spec(b) {
put.put(invs[i].hash);
}
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) {
Connection.prototype.sendInv = function(data) {
if(!Array.isArray(data)) data = [data];
var put = new Put();
put.varint(data.length);
@ -246,9 +245,9 @@ function spec(b) {
put.put(value.getHash());
});
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) {
@ -258,13 +257,13 @@ function spec(b) {
put.word8(0);
});
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
@ -277,9 +276,9 @@ function spec(b) {
});
this.sendMessage('block', put.buffer());
};
};
Connection.prototype.sendMessage = function (command, payload) {
Connection.prototype.sendMessage = function (command, payload) {
try {
var magic = network.magic;
var commandBuf = new Buffer(command, 'ascii');
@ -313,9 +312,9 @@ function spec(b) {
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) {
@ -326,9 +325,9 @@ function spec(b) {
}
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;
@ -402,9 +401,9 @@ function spec(b) {
this.buffers.skip(endPos);
this.processData();
};
};
Connection.prototype.parseMessage = function (command, payload) {
Connection.prototype.parseMessage = function (command, payload) {
var parser = new Parser(payload);
var data = {
@ -444,8 +443,8 @@ function spec(b) {
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;
@ -540,8 +539,6 @@ function spec(b) {
}
return data;
};
return Connection;
};
module.defineClass(spec);
module.exports = require('soop')(Connection);

View File

@ -3,26 +3,28 @@
module.exports = function(grunt) {
//Load NPM tasks
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-mocha-test');
grunt.loadNpmTasks('grunt-markdown');
grunt.loadNpmTasks('grunt-shell');
// Project Configuration
grunt.initConfig({
shell: {
browserify: {
client: {
src: ['bitcore.js'],
dest: 'browser/bundle.js',
options: {
debug: true,
alias: [
'browserify-bignum/bignumber.js:bignum',
'browserify-buffertools/buffertools.js:buffertools'
],
standalone: 'bitcore',
}
stdout: true
},
command: 'node ./browserify.js > browser/bundle.js',
},
browserifyData: {
options: {
stdout: true
},
command: 'browserify -t brfs test/testdata.js > browser/testdata.js'
},
},
browserify: {
test_data: {
src: ['test/testdata.js'],
dest: 'browser/testdata.js',
@ -40,7 +42,7 @@ module.exports = function(grunt) {
},
scripts: {
files: ['**/*.js', '**/*.html', '!**/node_modules/**', '!browser/bundle.js', '!browser/testdata.js'],
tasks: ['browserify' /*, 'mochaTest'*/ ],
tasks: ['shell' /*, 'mochaTest'*/ ],
},
},
mochaTest: {

View File

@ -1,15 +1,14 @@
require('classtool');
var imports = require('soop').imports();
function spec(b) {
function Opcode(num) {
function Opcode(num) {
this.code = num;
};
};
Opcode.prototype.toString = function () {
Opcode.prototype.toString = function () {
return Opcode.reverseMap[this.code];
};
};
Opcode.map = {
Opcode.map = {
// push value
OP_FALSE : 0,
OP_0 : 0,
@ -146,16 +145,14 @@ function spec(b) {
OP_PUBKEYHASH : 253,
OP_PUBKEY : 254,
OP_INVALIDOPCODE : 255
};
};
Opcode.reverseMap = [];
Opcode.reverseMap = [];
for (var k in Opcode.map) {
for (var k in Opcode.map) {
if(Opcode.map.hasOwnProperty(k)) {
Opcode.reverseMap[Opcode.map[k]] = k.substr(3);
}
}
}
return Opcode;
};
module.defineClass(spec);
module.exports = require('soop')(Opcode);

35
Peer.js
View File

@ -1,11 +1,10 @@
require('classtool');
var imports = require('soop').imports();
function spec(b) {
var Net = b.Net || require('net');
var Binary = b.Binary || require('binary');
var buffertools = b.buffertools || require('buffertools');
var Net = imports.Net || require('net');
var Binary = imports.Binary || require('binary');
var buffertools = imports.buffertools || require('buffertools');
function Peer(host, port, services) {
function Peer(host, port, services) {
if ("string" === typeof host) {
if (host.indexOf(':') && !port) {
var parts = host.split(':');
@ -30,32 +29,30 @@ function spec(b) {
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 () {
var c = Net.createConnection(this.port, this.host);
return c;
};
};
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);
put.put(this.getHostAsBuffer());
put.word16be(this.port);
return put.buffer();
};
return Peer;
};
module.defineClass(spec);
module.exports = require('soop')(Peer);

View File

@ -1,20 +1,21 @@
require('classtool');
function spec(b) {
var config = b.config || require('./config');
var log = b.log || require('./util/log');
var network = b.network || require('./networks')[config.network];
var Connection = b.Connection || require('./Connection').createClass(
{config: config, network: network});
var Peer = b.Peer || require('./Peer').class();
var noop = function() {};
var imports = require('soop').imports();
var config = imports.config || require('./config');
var log = imports.log || require('./util/log');
var network = imports.network || require('./networks')[config.network];
GetAdjustedTime = b.GetAdjustedTime || function () {
var Connection = imports.Connection ||
require('soop').load('Connection', {config: config, network: network}) ||
require ('./Connection');
var Peer = imports.Peer || require('./Peer');
GetAdjustedTime = imports.GetAdjustedTime || function () {
// TODO: Implement actual adjustment
return Math.floor(new Date().getTime() / 1000);
};
};
function PeerManager() {
function PeerManager() {
this.active = false;
this.timer = null;
@ -27,19 +28,19 @@ function spec(b) {
this.interval = 5000;
this.minConnections = 8;
this.minKnownPeers = 10;
};
PeerManager.superclass = b.superclass || require('events').EventEmitter;
};
PeerManager.Connection = Connection;
PeerManager.parent = imports.parent || require('events').EventEmitter;
PeerManager.Connection = Connection;
PeerManager.prototype.start = function() {
PeerManager.prototype.start = function() {
this.active = true;
if(!this.timer) {
this.timer = setInterval(this.checkStatus.bind(this), this.interval);
}
};
};
PeerManager.prototype.stop = function() {
PeerManager.prototype.stop = function() {
this.active = false;
if(this.timer) {
clearInterval(this.timer);
@ -48,9 +49,9 @@ function spec(b) {
for(var i=0; i<this.connections.length; i++) {
this.connections[i].socket.end();
};
};
};
PeerManager.prototype.addPeer = function(peer, port) {
PeerManager.prototype.addPeer = function(peer, port) {
if(peer instanceof Peer) {
this.peers.push(peer);
} else if ("string" == typeof peer) {
@ -60,9 +61,9 @@ function spec(b) {
{val: peer});
throw 'Node.addPeer(): Invalid value provided for peer.';
}
};
};
PeerManager.prototype.checkStatus = function checkStatus() {
PeerManager.prototype.checkStatus = function checkStatus() {
// Make sure we are connected to all forcePeers
if(this.peers.length) {
var peerIndex = {};
@ -82,9 +83,9 @@ function spec(b) {
this.connectTo(peerIndex[i]);
}.bind(this));
}
};
};
PeerManager.prototype.connectTo = function(peer) {
PeerManager.prototype.connectTo = function(peer) {
log.info('connecting to '+peer);
try {
return this.addConnection(peer.createConnection(), peer);
@ -92,9 +93,9 @@ function spec(b) {
log.err('creating connection',e);
return null;
}
};
};
PeerManager.prototype.addConnection = function(socketConn, peer) {
PeerManager.prototype.addConnection = function(socketConn, peer) {
var conn = new Connection(socketConn, peer);
this.connections.push(conn);
this.emit('connection', conn);
@ -107,9 +108,9 @@ function spec(b) {
conn.addListener('disconnect', this.handleDisconnect.bind(this));
return conn;
};
};
PeerManager.prototype.handleVersion = function(e) {
PeerManager.prototype.handleVersion = function(e) {
if (!e.conn.inbound) {
// TODO: Advertise our address (if listening)
}
@ -119,9 +120,9 @@ function spec(b) {
e.conn.sendGetAddr();
e.conn.getaddr = true;
}
};
};
PeerManager.prototype.handleReady = function (e) {
PeerManager.prototype.handleReady = function (e) {
log.info('connected to '+e.conn.peer.host+':'+e.conn.peer.port);
this.emit('connect', {
pm: this,
@ -134,9 +135,9 @@ function spec(b) {
this.emit('netConnected');
this.isConnected = true;
}
};
};
PeerManager.prototype.handleAddr = function (e) {
PeerManager.prototype.handleAddr = function (e) {
if(!this.peerDiscovery) return;
var now = GetAdjustedTime();
@ -160,18 +161,18 @@ function spec(b) {
if (e.message.addrs.length < 1000 ) {
e.conn.getaddr = false;
}
};
};
PeerManager.prototype.handleGetAddr = function(e) {
PeerManager.prototype.handleGetAddr = function(e) {
// TODO: Reply with addr message.
};
};
PeerManager.prototype.handleError = function(e) {
PeerManager.prototype.handleError = function(e) {
log.err('unkown error with peer '+e.peer+' (disconnecting): '+e.err);
this.handleDisconnect.apply(this, [].slice.call(arguments));
};
};
PeerManager.prototype.handleDisconnect = function(e) {
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);
@ -180,9 +181,9 @@ function spec(b) {
this.emit('netDisconnected');
this.isConnected = false;
}
};
};
PeerManager.prototype.getActiveConnection = function () {
PeerManager.prototype.getActiveConnection = function () {
var activeConnections = this.connections.filter(function (conn) {
return conn.active;
});
@ -204,12 +205,10 @@ function spec(b) {
} else {
return null;
}
};
PeerManager.prototype.getActiveConnections = function () {
return this.connections.slice(0);
};
return PeerManager;
};
module.defineClass(spec);
PeerManager.prototype.getActiveConnections = function () {
return this.connections.slice(0);
};
module.exports = require('soop')(PeerManager);

View File

@ -1,29 +1,28 @@
require('classtool');
var imports = require('soop').imports();
function ClassSpec(b) {
var superclass = b.superclass || require('./util/VersionedData').class();
var parent = imports.parent || require('./util/VersionedData');
//compressed is true if public key is compressed; false otherwise
function PrivateKey(version, buf, compressed) {
//compressed is true if public key is compressed; false otherwise
function PrivateKey(version, buf, compressed) {
PrivateKey.super(this, arguments);
if (compressed !== undefined)
this.compressed(compressed);
};
};
PrivateKey.superclass = superclass;
superclass.applyEncodingsTo(PrivateKey);
PrivateKey.parent = parent;
parent.applyEncodingsTo(PrivateKey);
PrivateKey.prototype.validate = function() {
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)
throw new Error('invalid data length');
});
};
};
// get or set the payload data (as a Buffer object)
// overloaded from VersionedData
PrivateKey.prototype.payload = function(data) {
// 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);});
return data;
@ -33,10 +32,10 @@ function ClassSpec(b) {
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) {
// 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;
@ -60,8 +59,6 @@ function ClassSpec(b) {
else
throw new Error('invalid private key');
}
};
return PrivateKey;
};
module.defineClass(ClassSpec);
module.exports = require('soop')(PrivateKey);

View File

@ -17,9 +17,9 @@ Bitcore runs on [node](http://nodejs.org/), and can be installed via [npm](https
npm install bitcore
```
It is a collection of objects useful to bitcoin applications; class-like idioms are enabled via [Classtool](https://github.com/gasteve/classtool). In most cases, a developer will require the object's class directly:
It is a collection of objects useful to bitcoin applications; class-like idioms are enabled via [Soop](https://github.com/gasteve/soop). In most cases, a developer will require the object's class directly:
```
var Address = require('bitcore/Address').class();
var Address = require('bitcore/Address');
```
#Examples
@ -29,7 +29,7 @@ Some examples are provided at the [examples](/examples) path. Here are some snip
## Validating an address
Validating a Bitcoin address:
```js
var Address = require('bitcore/Address').class();
var Address = require('bitcore/Address');
var addrStrings = [
"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
@ -57,10 +57,9 @@ For this example you need a running bitcoind instance with RPC enabled.
```js
var util = require('util');
var networks = require('bitcore/networks');
var Peer = require('bitcore/Peer').class();
var PeerManager = require('bitcore/PeerManager').createClass({
network: networks.testnet
});
var Peer = require('bitcore/Peer');
var PeerManager = require('soop').load('bitcore/PeerManager',
{network: networks.testnet});
var handleBlock = function(info) {
@ -109,14 +108,13 @@ PeerManager will emit the following events: 'version', 'verack', 'addr', 'getadd
For this example you need a running bitcoind instance with RPC enabled.
```js
var networks = require('bitcore/networks');
var Peer = require('bitcore/Peer').class();
var Transaction = require('bitcore/Transaction').class();
var Address = require('bitcore/Address').class();
var Script = require('bitcore/Script').class();
var Peer = require('bitcore/Peer');
var Transaction = require('bitcore/Transaction');
var Address = require('bitcore/Address');
var Script = require('bitcore/Script');
var coinUtil = require('bitcore/util/util');
var PeerManager = require('bitcore/PeerManager').createClass({
network: networks.testnet
});
var PeerManager = require('soop').load('bitcore/PeerManager',
{network: networks.testnet});
var createTx = function() {
@ -185,7 +183,7 @@ peerman.start();
For this example you need a running bitcoind instance with RPC enabled.
```js
var util = require('util');
var RpcClient = require('bitcore/RpcClient').class();
var RpcClient = require('bitcore/RpcClient');
var hash = process.argv[2] || '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4';
var config = {
@ -217,7 +215,7 @@ Check the list of all supported RPC call at [RpcClient.js](RpcClient.js)
Gets an address strings from a ScriptPubKey Buffer
```
var Address = require('bitcore/Address').class();
var Address = require('bitcore/Address');
var coinUtil= require('bitcore/util/util');
var getAddrStr = function(s) {

View File

@ -1,14 +1,13 @@
// RpcClient.js
// MIT/X11-like license. See LICENSE.txt.
// Copyright 2013 BitPay, Inc.
require('classtool');
//
var imports = require('soop').imports();
var http = imports.http || require('http');
var https = imports.https || require('https');
var log = imports.log || require('./util/log');
function ClassSpec(b) {
var http = b.http || require('http');
var https = b.https || require('https');
var log = b.log || require('./util/log');
function RpcClient(opts) {
function RpcClient(opts) {
opts = opts || {};
this.host = opts.host || '127.0.0.1';
this.port = opts.port || 8332;
@ -17,16 +16,16 @@ function ClassSpec(b) {
this.protocol = (opts.protocol == 'http') ? http : https;
this.batchedCalls = null;
this.disableAgent = opts.disableAgent || false;
}
}
RpcClient.prototype.batch = function(batchCallback, resultCallback) {
RpcClient.prototype.batch = function(batchCallback, resultCallback) {
this.batchedCalls = [];
batchCallback();
rpc.call(this, this.batchedCalls, resultCallback);
this.batchedCalls = null;
}
}
var callspec = {
var callspec = {
addMultiSigAddress: '',
addNode: '',
backupWallet: '',
@ -93,13 +92,13 @@ function ClassSpec(b) {
walletLock: '',
walletPassPhrase: 'string int',
walletPassphraseChange: '',
};
};
var slice = function(arr, start, end) {
var slice = function(arr, start, end) {
return Array.prototype.slice.call(arr, start, end);
};
};
function generateRPCMethods(constructor, apiCalls, rpc) {
function generateRPCMethods(constructor, apiCalls, rpc) {
function createRPCMethod(methodName, argMap) {
return function() {
var limit = arguments.length - 1;
@ -137,9 +136,9 @@ function ClassSpec(b) {
constructor.prototype[methodName] = constructor.prototype[k];
}
}
}
}
function rpc(request, callback) {
function rpc(request, callback) {
var self = this;
var request;
request = JSON.stringify(request);
@ -201,10 +200,9 @@ function ClassSpec(b) {
req.setHeader('Authorization', 'Basic ' + auth);
req.write(request);
req.end();
};
generateRPCMethods(RpcClient, callspec, rpc);
return RpcClient;
};
module.defineClass(ClassSpec);
generateRPCMethods(RpcClient, callspec, rpc);
module.exports = require('soop')(RpcClient);

45
SIN.js
View File

@ -1,10 +1,7 @@
require('classtool');
var imports = require('soop').imports();
var parent = imports.parent || require('./util/VersionedData');
function ClassSpec(b) {
var superclass = b.superclass || require('./util/VersionedData').class();
function SIN(type, payload) {
function SIN(type, payload) {
if (typeof type != 'number') {
SIN.super(this, arguments);
return;
@ -14,47 +11,45 @@ function ClassSpec(b) {
this.prefix(0x0F); // SIN magic number, in numberspace
this.type(type);
this.payload(payload);
};
SIN.superclass = superclass;
superclass.applyEncodingsTo(SIN);
};
SIN.parent = parent;
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_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
// get or set the prefix data (the first byte of the address)
SIN.prototype.prefix = function(num) {
// 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);});
return num;
}
return this.as('binary').readUInt8(0);
};
};
// get or set the SIN-type data (the second byte of the address)
SIN.prototype.type = 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);});
return num;
}
return this.as('binary').readUInt8(1);
};
};
// get or set the payload data (as a Buffer object)
SIN.prototype.payload = function(data) {
// 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);});
return data;
}
return this.as('binary').slice(1);
};
};
SIN.prototype.validate = function() {
SIN.prototype.validate = function() {
this.doAsBinary(function() {
SIN.super(this, 'validate', arguments);
if (this.data.length != 22) throw new Error('invalid data length');
});
};
return SIN;
};
module.defineClass(ClassSpec);
module.exports = require('soop')(SIN);

View File

@ -1,29 +1,26 @@
require('classtool');
var coinUtil = require('./util/util');
var timeUtil = require('./util/time');
var KeyModule = require('./Key');
var SIN = require('./SIN');
function ClassSpec(b) {
var coinUtil = require('./util/util');
var timeUtil = require('./util/time');
var KeyModule = require('./Key');
var SIN = require('./SIN').class();
function SINKey(cfg) {
function SINKey(cfg) {
if (typeof cfg != 'object')
cfg = {};
this.created = cfg.created;
this.privKey = cfg.privKey;
};
};
SINKey.prototype.generate = function() {
SINKey.prototype.generate = function() {
this.privKey = KeyModule.Key.generateSync();
this.created = timeUtil.curtime();
};
};
SINKey.prototype.pubkeyHash = function() {
SINKey.prototype.pubkeyHash = function() {
return coinUtil.sha256ripe160(this.privKey.public);
};
};
SINKey.prototype.storeObj = function() {
SINKey.prototype.storeObj = function() {
var pubKey = this.privKey.public.toString('hex');
var pubKeyHash = this.pubkeyHash();
var sin = new SIN(SIN.SIN_EPHEM, pubKeyHash);
@ -35,9 +32,6 @@ function ClassSpec(b) {
};
return obj;
};
return SINKey;
};
module.defineClass(ClassSpec);
module.exports = require('soop')(SINKey);

213
Script.js
View File

@ -1,36 +1,33 @@
require('classtool');
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');
function spec(b) {
var config = b.config || require('./config');
var log = b.log || require('./util/log');
var Opcode = b.Opcode || require('./Opcode').class();
var buffertools = b.buffertools || require('buffertools');
// Make opcodes available as pseudo-constants
for (var i in Opcode.map) {
// Make opcodes available as pseudo-constants
for (var i in Opcode.map) {
eval(i + " = " + Opcode.map[i] + ";");
}
}
var util = b.util || require('./util/util');
var Parser = b.Parser || require('./util/BinaryParser').class();
var Put = b.Put || require('bufferput');
var util = imports.util || require('./util/util');
var Parser = imports.Parser || require('./util/BinaryParser');
var Put = imports.Put || require('bufferput');
var TX_UNKNOWN = 0;
var TX_PUBKEY = 1;
var TX_PUBKEYHASH = 2;
var TX_MULTISIG = 3;
var TX_SCRIPTHASH = 4;
var TX_UNKNOWN = 0;
var TX_PUBKEY = 1;
var TX_PUBKEYHASH = 2;
var TX_MULTISIG = 3;
var TX_SCRIPTHASH = 4;
var TX_TYPES = [
var TX_TYPES = [
'unknown',
'pubkey',
'pubkeyhash',
'multisig',
'scripthash'
];
];
function Script(buffer) {
function Script(buffer) {
if (buffer) {
this.buffer = buffer;
} else {
@ -38,16 +35,16 @@ function spec(b) {
}
this.chunks = [];
this.parse();
};
this.class = Script;
};
this.class = Script;
Script.TX_UNKNOWN = TX_UNKNOWN;
Script.TX_PUBKEY = TX_PUBKEY;
Script.TX_PUBKEYHASH = TX_PUBKEYHASH;
Script.TX_MULTISIG = TX_MULTISIG;
Script.TX_SCRIPTHASH = TX_SCRIPTHASH;
Script.TX_UNKNOWN = TX_UNKNOWN;
Script.TX_PUBKEY = TX_PUBKEY;
Script.TX_PUBKEYHASH = TX_PUBKEYHASH;
Script.TX_MULTISIG = TX_MULTISIG;
Script.TX_SCRIPTHASH = TX_SCRIPTHASH;
Script.prototype.parse = function() {
Script.prototype.parse = function() {
this.chunks = [];
var parser = new Parser(this.buffer);
@ -71,31 +68,31 @@ function spec(b) {
this.chunks.push(opcode);
}
}
};
};
Script.prototype.isPushOnly = function() {
Script.prototype.isPushOnly = function() {
for (var i = 0; i < this.chunks.length; i++)
if (!Buffer.isBuffer(this.chunks[i]))
return false;
return true;
};
};
Script.prototype.isP2SH = function() {
Script.prototype.isP2SH = function() {
return (this.chunks.length == 3 &&
this.chunks[0] == OP_HASH160 &&
Buffer.isBuffer(this.chunks[1]) &&
this.chunks[1].length == 20 &&
this.chunks[2] == OP_EQUAL);
};
};
Script.prototype.isPubkey = function() {
Script.prototype.isPubkey = function() {
return (this.chunks.length == 2 &&
Buffer.isBuffer(this.chunks[0]) &&
this.chunks[1] == OP_CHECKSIG);
};
};
Script.prototype.isPubkeyHash = function() {
Script.prototype.isPubkeyHash = function() {
return (this.chunks.length == 5 &&
this.chunks[0] == OP_DUP &&
this.chunks[1] == OP_HASH160 &&
@ -103,21 +100,21 @@ function spec(b) {
this.chunks[2].length == 20 &&
this.chunks[3] == OP_EQUALVERIFY &&
this.chunks[4] == OP_CHECKSIG);
};
};
function isSmallIntOp(opcode) {
function isSmallIntOp(opcode) {
return ((opcode == OP_0) ||
((opcode >= OP_1) && (opcode <= OP_16)));
};
};
Script.prototype.isMultiSig = function() {
Script.prototype.isMultiSig = function() {
return (this.chunks.length > 3 &&
isSmallIntOp(this.chunks[0]) &&
isSmallIntOp(this.chunks[this.chunks.length - 2]) &&
this.chunks[this.chunks.length - 1] == OP_CHECKMULTISIG);
};
};
Script.prototype.finishedMultiSig = function() {
Script.prototype.finishedMultiSig = function() {
var nsigs = 0;
for (var i = 0; i < this.chunks.length - 1; i++)
if (this.chunks[i] !== 0)
@ -131,9 +128,9 @@ function spec(b) {
return true;
else
return false;
}
}
Script.prototype.removePlaceHolders = function() {
Script.prototype.removePlaceHolders = function() {
var chunks = [];
for (var i in this.chunks) {
if (this.chunks.hasOwnProperty(i)) {
@ -145,9 +142,9 @@ function spec(b) {
this.chunks = chunks;
this.updateBuffer();
return this;
}
}
Script.prototype.prependOp0 = function() {
Script.prototype.prependOp0 = function() {
var chunks = [0];
for (i in this.chunks) {
if (this.chunks.hasOwnProperty(i)) {
@ -157,10 +154,10 @@ function spec(b) {
this.chunks = chunks;
this.updateBuffer();
return this;
}
}
// is this a script form we know?
Script.prototype.classify = function() {
// is this a script form we know?
Script.prototype.classify = function() {
if (this.isPubkeyHash())
return TX_PUBKEYHASH;
if (this.isP2SH())
@ -170,10 +167,10 @@ function spec(b) {
if (this.isPubkey())
return TX_PUBKEY;
return TX_UNKNOWN;
};
};
// extract useful data items from known scripts
Script.prototype.capture = function() {
// extract useful data items from known scripts
Script.prototype.capture = function() {
var txType = this.classify();
var res = [];
switch (txType) {
@ -198,15 +195,15 @@ function spec(b) {
}
return res;
};
};
// return first extracted data item from script
Script.prototype.captureOne = function() {
// return first extracted data item from script
Script.prototype.captureOne = function() {
var arr = this.capture();
return arr[0];
};
};
Script.prototype.getOutType = function() {
Script.prototype.getOutType = function() {
var txType = this.classify();
switch (txType) {
case TX_PUBKEY:
@ -216,13 +213,13 @@ function spec(b) {
default:
return 'Strange';
}
};
};
Script.prototype.getRawOutType = function() {
Script.prototype.getRawOutType = function() {
return TX_TYPES[this.classify()];
};
};
Script.prototype.simpleOutHash = function() {
Script.prototype.simpleOutHash = function() {
switch (this.getOutType()) {
case 'Address':
return this.chunks[2];
@ -233,9 +230,9 @@ function spec(b) {
log.debug("Strange script was: " + this.toString());
return null;
}
};
};
Script.prototype.getInType = function() {
Script.prototype.getInType = function() {
if (this.chunks.length == 1) {
// Direct IP to IP transactions only have the public key in their scriptSig.
return 'Pubkey';
@ -246,9 +243,9 @@ function spec(b) {
} else {
return 'Strange';
}
};
};
Script.prototype.simpleInPubKey = function() {
Script.prototype.simpleInPubKey = function() {
switch (this.getInType()) {
case 'Address':
return this.chunks[1];
@ -259,13 +256,13 @@ function spec(b) {
log.debug("Strange script was: " + this.toString());
return null;
}
};
};
Script.prototype.getBuffer = function() {
Script.prototype.getBuffer = function() {
return this.buffer;
};
};
Script.fromStringContent = function(s) {
Script.fromStringContent = function(s) {
var chunks = [];
var split = s.split(' ');
for (var i = 0; i < split.length; i++) {
@ -287,9 +284,9 @@ function spec(b) {
}
}
return Script.fromChunks(chunks);
};
};
Script.prototype.getStringContent = function(truncate, maxEl) {
Script.prototype.getStringContent = function(truncate, maxEl) {
if (truncate === null) {
truncate = true;
}
@ -318,17 +315,17 @@ function spec(b) {
}
}
return s;
};
};
Script.prototype.toString = function(truncate, maxEl) {
Script.prototype.toString = function(truncate, maxEl) {
var script = "<Script ";
script += this.getStringContent(truncate, maxEl);
script += ">";
return script;
};
};
Script.prototype.writeOp = function(opcode) {
Script.prototype.writeOp = function(opcode) {
var buf = Buffer(this.buffer.length + 1);
this.buffer.copy(buf);
buf.writeUInt8(opcode, this.buffer.length);
@ -336,9 +333,9 @@ function spec(b) {
this.buffer = buf;
this.chunks.push(opcode);
};
};
Script.prototype.writeN = function(n) {
Script.prototype.writeN = function(n) {
if (n < 0 || n > 16)
throw new Error("writeN: out of range value " + n);
@ -346,9 +343,9 @@ function spec(b) {
this.writeOp(OP_0);
else
this.writeOp(OP_1 + n - 1);
};
};
function prefixSize(data_length) {
function prefixSize(data_length) {
if (data_length < OP_PUSHDATA1) {
return 1;
} else if (data_length <= 0xff) {
@ -358,9 +355,9 @@ function spec(b) {
} else {
return 1 + 4;
}
};
};
function encodeLen(data_length) {
function encodeLen(data_length) {
var buf = undefined;
if (data_length < OP_PUSHDATA1) {
buf = new Buffer(1);
@ -380,19 +377,19 @@ function spec(b) {
}
return buf;
};
};
Script.prototype.writeBytes = function(data) {
Script.prototype.writeBytes = function(data) {
var newSize = this.buffer.length + prefixSize(data.length) + data.length;
this.buffer = Buffer.concat([this.buffer, encodeLen(data.length), data]);
this.chunks.push(data);
};
};
Script.prototype.updateBuffer = function() {
Script.prototype.updateBuffer = function() {
this.buffer = Script.chunksToBuffer(this.chunks);
};
};
Script.prototype.findAndDelete = function(chunk) {
Script.prototype.findAndDelete = function(chunk) {
var dirty = false;
if (Buffer.isBuffer(chunk)) {
for (var i = 0, l = this.chunks.length; i < l; i++) {
@ -415,25 +412,25 @@ function spec(b) {
if (dirty) {
this.updateBuffer();
}
};
};
/**
/**
* Creates a simple OP_CHECKSIG with pubkey output script.
*
* These are used for coinbase transactions and at some point were used for
* IP-based transactions as well.
*/
Script.createPubKeyOut = function(pubkey) {
Script.createPubKeyOut = function(pubkey) {
var script = new Script();
script.writeBytes(pubkey);
script.writeOp(OP_CHECKSIG);
return script;
};
};
/**
/**
* Creates a standard txout script.
*/
Script.createPubKeyHashOut = function(pubKeyHash) {
Script.createPubKeyHashOut = function(pubKeyHash) {
var script = new Script();
script.writeOp(OP_DUP);
script.writeOp(OP_HASH160);
@ -441,9 +438,9 @@ function spec(b) {
script.writeOp(OP_EQUALVERIFY);
script.writeOp(OP_CHECKSIG);
return script;
};
};
Script.createMultisig = function(n_required, keys) {
Script.createMultisig = function(n_required, keys) {
var script = new Script();
script.writeN(n_required);
keys.forEach(function(key) {
@ -452,17 +449,17 @@ function spec(b) {
script.writeN(keys.length);
script.writeOp(OP_CHECKMULTISIG);
return script;
};
};
Script.createP2SH = function(scriptHash) {
Script.createP2SH = function(scriptHash) {
var script = new Script();
script.writeOp(OP_HASH160);
script.writeBytes(scriptHash);
script.writeOp(OP_EQUAL);
return script;
};
};
Script.fromTestData = function(testData) {
Script.fromTestData = function(testData) {
testData = testData.map(function(chunk) {
if ("string" === typeof chunk) {
return new Buffer(chunk, 'hex');
@ -475,16 +472,16 @@ function spec(b) {
script.chunks = testData;
script.updateBuffer();
return script;
};
};
Script.fromChunks = function(chunks) {
Script.fromChunks = function(chunks) {
var script = new Script();
script.chunks = chunks;
script.updateBuffer();
return script;
};
};
Script.chunksToBuffer = function(chunks) {
Script.chunksToBuffer = function(chunks) {
var buf = new Put();
for (var i = 0, l = chunks.length; i < l; i++) {
@ -510,8 +507,6 @@ function spec(b) {
}
}
return buf.buffer();
};
return Script;
};
module.defineClass(spec);
module.exports = require('soop')(Script);

View File

@ -1,28 +1,23 @@
require('classtool');
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 bignum = imports.bignum || require('bignum');
var Util = imports.Util || require('./util/util');
var Script = require('./Script');
function spec(b) {
var assert = require('assert');
var config = b.config || require('./config');
var log = b.log || require('./util/log');
var Opcode = b.Opcode || require('./Opcode').class();
var buffertools = b.buffertools || require('buffertools');
// Make opcodes available as pseudo-constants
for (var i in Opcode.map) {
// Make opcodes available as pseudo-constants
for (var i in Opcode.map) {
eval(i + " = " + Opcode.map[i] + ";");
}
}
var bignum = b.bignum || require('bignum');
var Util = b.Util || require('./util/util');
var Script = require('./Script').class();
function ScriptInterpreter() {
function ScriptInterpreter() {
this.stack = [];
this.disableUnsafeOpcodes = true;
};
};
ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, callback) {
ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, callback) {
if ("function" !== typeof callback) {
throw new Error("ScriptInterpreter.eval() requires a callback");
}
@ -767,9 +762,9 @@ function spec(b) {
cb(e);
}
}
};
};
ScriptInterpreter.prototype.evalTwo =
ScriptInterpreter.prototype.evalTwo =
function evalTwo(scriptSig, scriptPubkey, tx, n, hashType, callback) {
var self = this;
@ -781,15 +776,15 @@ function spec(b) {
self.eval(scriptPubkey, tx, n, hashType, callback);
});
};
};
/**
/**
* Get the top element of the stack.
*
* Using the offset parameter this function can also access lower elements
* from the stack.
*/
ScriptInterpreter.prototype.stackTop = function stackTop(offset) {
ScriptInterpreter.prototype.stackTop = function stackTop(offset) {
offset = +offset || 1;
if (offset < 1) offset = 1;
@ -798,24 +793,24 @@ function spec(b) {
}
return this.stack[this.stack.length - offset];
};
};
ScriptInterpreter.prototype.stackBack = function stackBack() {
ScriptInterpreter.prototype.stackBack = function stackBack() {
return this.stack[-1];
};
};
/**
/**
* Pop the top element off the stack and return it.
*/
ScriptInterpreter.prototype.stackPop = function stackPop() {
ScriptInterpreter.prototype.stackPop = function stackPop() {
if (this.stack.length < 1) {
throw new Error('ScriptInterpreter.stackTop(): Stack underrun');
}
return this.stack.pop();
};
};
ScriptInterpreter.prototype.stackSwap = function stackSwap(a, b) {
ScriptInterpreter.prototype.stackSwap = function stackSwap(a, b) {
if (this.stack.length < a || this.stack.length < b) {
throw new Error('ScriptInterpreter.stackTop(): Stack underrun');
}
@ -826,15 +821,15 @@ function spec(b) {
var tmp = s[l - a];
s[l - a] = s[l - b];
s[l - b] = tmp;
};
};
/**
/**
* Returns a version of the stack with only primitive types.
*
* The return value is an array. Any single byte buffer is converted to an
* integer. Any longer Buffer is converted to a hex string.
*/
ScriptInterpreter.prototype.getPrimitiveStack = function getPrimitiveStack() {
ScriptInterpreter.prototype.getPrimitiveStack = function getPrimitiveStack() {
return this.stack.map(function(entry) {
if (entry.length > 2) {
return buffertools.toHex(entry.slice(0));
@ -846,9 +841,9 @@ function spec(b) {
return buffertools.toHex(entry.slice(0));
}
});
};
};
var castBool = ScriptInterpreter.castBool = function castBool(v) {
var castBool = ScriptInterpreter.castBool = function castBool(v) {
for (var i = 0, l = v.length; i < l; i++) {
if (v[i] != 0) {
// Negative zero is still zero
@ -859,11 +854,11 @@ function spec(b) {
}
}
return false;
};
var castInt = ScriptInterpreter.castInt = function castInt(v) {
};
var castInt = ScriptInterpreter.castInt = function castInt(v) {
return castBigint(v).toNumber();
};
var castBigint = ScriptInterpreter.castBigint = function castBigint(v) {
};
var castBigint = ScriptInterpreter.castBigint = function castBigint(v) {
if (!v.length) {
return bignum(0);
}
@ -883,8 +878,8 @@ function spec(b) {
// Positive number
return bignum.fromBuffer(w);
}
};
var bigintToBuffer = ScriptInterpreter.bigintToBuffer = function bigintToBuffer(v) {
};
var bigintToBuffer = ScriptInterpreter.bigintToBuffer = function bigintToBuffer(v) {
if ("number" === typeof v) {
v = bignum(v);
}
@ -916,17 +911,17 @@ function spec(b) {
return buffertools.reverse(b);
}
}
};
};
ScriptInterpreter.prototype.getResult = function getResult() {
ScriptInterpreter.prototype.getResult = function getResult() {
if (this.stack.length === 0) {
throw new Error("Empty stack after script evaluation");
}
return castBool(this.stack[this.stack.length - 1]);
};
};
ScriptInterpreter.verify =
ScriptInterpreter.verify =
function verify(scriptSig, scriptPubKey, txTo, n, hashType, callback) {
if ("function" !== typeof callback) {
throw new Error("ScriptInterpreter.verify() requires a callback");
@ -954,9 +949,9 @@ function spec(b) {
});
return si;
};
};
function verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
function verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy) {
if (siCopy.stack.length == 0) {
callback(null, false);
@ -964,9 +959,9 @@ function spec(b) {
}
callback(null, castBool(siCopy.stackBack()));
}
}
function verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
function verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy) {
if (si.stack.length == 0) {
callback(null, false);
@ -1000,9 +995,9 @@ function spec(b) {
verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy);
});
}
}
function verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
function verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy) {
if (opts.verifyP2SH) {
si.stack.forEach(function(item) {
@ -1017,9 +1012,9 @@ function spec(b) {
verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy);
});
}
}
ScriptInterpreter.verifyFull =
ScriptInterpreter.verifyFull =
function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType,
opts, callback) {
var si = new ScriptInterpreter();
@ -1032,9 +1027,9 @@ function spec(b) {
verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy);
});
};
};
var checkSig = ScriptInterpreter.checkSig =
var checkSig = ScriptInterpreter.checkSig =
function(sig, pubkey, scriptCode, tx, n, hashType, callback) {
if (!sig.length) {
callback(null, false);
@ -1060,8 +1055,6 @@ function spec(b) {
} catch (err) {
callback(null, false);
}
};
return ScriptInterpreter;
};
module.defineClass(spec);
module.exports = require('soop')(ScriptInterpreter);

View File

@ -1,25 +1,20 @@
require('classtool');
var imports = require('soop').imports();
var config = imports.config || require('./config');
var log = imports.log || require('./util/log');
var Address = imports.Address || require('./Address');
var Script = imports.Script || require('./Script');
var ScriptInterpreter = imports.ScriptInterpreter || require('./ScriptInterpreter');
var util = imports.util || require('./util/util');
var bignum = imports.bignum || require('bignum');
var Put = imports.Put || require('bufferput');
var Parser = imports.Parser || require('./util/BinaryParser');
var Step = imports.Step || require('step');
var buffertools = imports.buffertools || require('buffertools');
var error = imports.error || require('./util/error');
function spec(b) {
var config = b.config || require('./config');
var log = b.log || require('./util/log');
var Address = b.Address || require('./Address').class();
var Script = b.Script || require('./Script').class();
var ScriptInterpreter = b.ScriptInterpreter || require('./ScriptInterpreter').class();
var util = b.util || require('./util/util');
var bignum = b.bignum || require('bignum');
var Put = b.Put || require('bufferput');
var Parser = b.Parser || require('./util/BinaryParser').class();
var Step = b.Step || require('step');
var buffertools = b.buffertools || require('buffertools');
var COINBASE_OP = Buffer.concat([util.NULL_HASH, new Buffer('FFFFFFFF', 'hex')]);
var error = b.error || require('./util/error');
var VerificationError = error.VerificationError;
var MissingSourceError = error.MissingSourceError;
var COINBASE_OP = Buffer.concat([util.NULL_HASH, new Buffer('FFFFFFFF', 'hex')]);
function TransactionIn(data) {
function TransactionIn(data) {
if ("object" !== typeof data) {
data = {};
}
@ -37,70 +32,70 @@ function spec(b) {
this.s = Buffer.isBuffer(data.s) ? data.s :
Buffer.isBuffer(data.script) ? data.script : util.EMPTY_BUFFER;
this.q = data.q ? data.q : data.sequence;
}
}
TransactionIn.prototype.getScript = function getScript() {
TransactionIn.prototype.getScript = function getScript() {
return new Script(this.s);
};
};
TransactionIn.prototype.isCoinBase = function isCoinBase() {
TransactionIn.prototype.isCoinBase = function isCoinBase() {
return buffertools.compare(this.o, COINBASE_OP) === 0;
};
};
TransactionIn.prototype.serialize = function serialize() {
TransactionIn.prototype.serialize = function serialize() {
var slen = util.varIntBuf(this.s.length);
var qbuf = new Buffer(4);
qbuf.writeUInt32LE(this.q, 0);
var ret = Buffer.concat([this.o, slen, this.s, qbuf]);
return ret;
};
};
TransactionIn.prototype.getOutpointHash = function getOutpointHash() {
TransactionIn.prototype.getOutpointHash = function getOutpointHash() {
if ("undefined" !== typeof this.o.outHashCache) {
return this.o.outHashCache;
}
return this.o.outHashCache = this.o.slice(0, 32);
};
};
TransactionIn.prototype.getOutpointIndex = function getOutpointIndex() {
TransactionIn.prototype.getOutpointIndex = function getOutpointIndex() {
return (this.o[32] ) +
(this.o[33] << 8) +
(this.o[34] << 16) +
(this.o[35] << 24);
};
};
TransactionIn.prototype.setOutpointIndex = function setOutpointIndex(n) {
TransactionIn.prototype.setOutpointIndex = function setOutpointIndex(n) {
this.o[32] = n & 0xff;
this.o[33] = n >> 8 & 0xff;
this.o[34] = n >> 16 & 0xff;
this.o[35] = n >> 24 & 0xff;
};
};
function TransactionOut(data) {
function TransactionOut(data) {
if ("object" !== typeof data) {
data = {};
}
this.v = data.v ? data.v : data.value;
this.s = data.s ? data.s : data.script;
};
};
TransactionOut.prototype.getValue = function getValue() {
TransactionOut.prototype.getValue = function getValue() {
return new Parser(this.v).word64lu();
};
};
TransactionOut.prototype.getScript = function getScript() {
TransactionOut.prototype.getScript = function getScript() {
return new Script(this.s);
};
};
TransactionOut.prototype.serialize = function serialize() {
TransactionOut.prototype.serialize = function serialize() {
var slen = util.varIntBuf(this.s.length);
return Buffer.concat([this.v, slen, this.s]);
};
};
function Transaction(data) {
function Transaction(data) {
if ("object" !== typeof data) {
data = {};
}
@ -121,16 +116,16 @@ function spec(b) {
return txout;
}) : [];
if (data.buffer) this._buffer = data.buffer;
};
this.class = Transaction;
Transaction.In = TransactionIn;
Transaction.Out = TransactionOut;
};
this.class = Transaction;
Transaction.In = TransactionIn;
Transaction.Out = TransactionOut;
Transaction.prototype.isCoinBase = function () {
Transaction.prototype.isCoinBase = function () {
return this.ins.length == 1 && this.ins[0].isCoinBase();
};
};
Transaction.prototype.isStandard = function isStandard() {
Transaction.prototype.isStandard = function isStandard() {
var i;
for (i = 0; i < this.ins.length; i++) {
if (this.ins[i].getScript().getInType() == "Strange") {
@ -143,9 +138,9 @@ function spec(b) {
}
}
return true;
};
};
Transaction.prototype.serialize = function serialize() {
Transaction.prototype.serialize = function serialize() {
var bufs = [];
var buf = new Buffer(4);
@ -168,34 +163,34 @@ function spec(b) {
this._buffer = Buffer.concat(bufs);
return this._buffer;
};
};
Transaction.prototype.getBuffer = function getBuffer() {
Transaction.prototype.getBuffer = function getBuffer() {
if (this._buffer) return this._buffer;
return this.serialize();
};
};
Transaction.prototype.calcHash = function calcHash() {
Transaction.prototype.calcHash = function calcHash() {
this.hash = util.twoSha256(this.getBuffer());
return this.hash;
};
};
Transaction.prototype.checkHash = function checkHash() {
Transaction.prototype.checkHash = function checkHash() {
if (!this.hash || !this.hash.length) return false;
return buffertools.compare(this.calcHash(), this.hash) === 0;
};
};
Transaction.prototype.getHash = function getHash() {
Transaction.prototype.getHash = function getHash() {
if (!this.hash || !this.hash.length) {
this.hash = this.calcHash();
}
return this.hash;
};
};
// convert encoded list of inputs to easy-to-use JS list-of-lists
Transaction.prototype.inputs = function inputs() {
// convert encoded list of inputs to easy-to-use JS list-of-lists
Transaction.prototype.inputs = function inputs() {
var res = [];
for (var i = 0; i < this.ins.length; i++) {
var txin = this.ins[i];
@ -205,9 +200,9 @@ function spec(b) {
}
return res;
}
}
/**
/**
* Load and cache transaction inputs.
*
* This function will try to load the inputs for a transaction.
@ -218,15 +213,15 @@ function spec(b) {
* met (or a timeout occurs.)
* @param {Function} callback Function to call on completion.
*/
Transaction.prototype.cacheInputs =
function cacheInputs(blockChain, txStore, wait, callback) {
Transaction.prototype.cacheInputs =
function cacheInputs(blockChain, txStore, wait, callback) {
var self = this;
var txCache = new TransactionInputsCache(this);
txCache.buffer(blockChain, txStore, wait, callback);
};
};
Transaction.prototype.verify = function verify(txCache, blockChain, callback) {
Transaction.prototype.verify = function verify(txCache, blockChain, callback) {
var self = this;
var txIndex = txCache.txIndex;
@ -350,22 +345,22 @@ function spec(b) {
},
callback
);
};
};
Transaction.prototype.verifyInput = function verifyInput(n, scriptPubKey, callback) {
Transaction.prototype.verifyInput = function verifyInput(n, scriptPubKey, callback) {
return ScriptInterpreter.verify(this.ins[n].getScript(),
scriptPubKey,
this, n, 0,
callback);
};
};
/**
/**
* Returns an object containing all pubkey hashes affected by this transaction.
*
* The return object contains the base64-encoded pubKeyHash values as keys
* and the original pubKeyHash buffers as values.
*/
Transaction.prototype.getAffectedKeys = function getAffectedKeys(txCache) {
Transaction.prototype.getAffectedKeys = function getAffectedKeys(txCache) {
// TODO: Function won't consider results cached if there are no affected
// accounts.
if (!(this.affects && this.affects.length)) {
@ -432,22 +427,22 @@ function spec(b) {
});
return affectedKeys;
};
};
var OP_CODESEPARATOR = 171;
var OP_CODESEPARATOR = 171;
var SIGHASH_ALL = 1;
var SIGHASH_NONE = 2;
var SIGHASH_SINGLE = 3;
var SIGHASH_ANYONECANPAY = 80;
var SIGHASH_ALL = 1;
var SIGHASH_NONE = 2;
var SIGHASH_SINGLE = 3;
var SIGHASH_ANYONECANPAY = 80;
Transaction.SIGHASH_ALL=SIGHASH_ALL;
Transaction.SIGHASH_NONE=SIGHASH_NONE;
Transaction.SIGHASH_SINGLE=SIGHASH_SINGLE;
Transaction.SIGHASH_ANYONECANPAY=SIGHASH_ANYONECANPAY;
Transaction.SIGHASH_ALL=SIGHASH_ALL;
Transaction.SIGHASH_NONE=SIGHASH_NONE;
Transaction.SIGHASH_SINGLE=SIGHASH_SINGLE;
Transaction.SIGHASH_ANYONECANPAY=SIGHASH_ANYONECANPAY;
Transaction.prototype.hashForSignature =
function hashForSignature(script, inIndex, hashType) {
Transaction.prototype.hashForSignature =
function hashForSignature(script, inIndex, hashType) {
if (+inIndex !== inIndex ||
inIndex < 0 || inIndex >= this.ins.length) {
throw new Error("Input index '"+inIndex+"' invalid or out of bounds "+
@ -549,12 +544,12 @@ function spec(b) {
buffer = Buffer.concat([buffer, new Buffer([parseInt(hashType), 0, 0, 0])]);
return util.twoSha256(buffer);
};
};
/**
/**
* Returns an object with the same field names as jgarzik's getblock patch.
*/
Transaction.prototype.getStandardizedObject = function getStandardizedObject() {
Transaction.prototype.getStandardizedObject = function getStandardizedObject() {
var tx = {
hash: util.formatHashFull(this.getHash()),
version: this.version,
@ -596,14 +591,14 @@ function spec(b) {
tx["out"] = outs;
return tx;
};
};
// Add some Mongoose compatibility functions to the plain object
Transaction.prototype.toObject = function toObject() {
// Add some Mongoose compatibility functions to the plain object
Transaction.prototype.toObject = function toObject() {
return this;
};
};
Transaction.prototype.fromObj = function fromObj(obj) {
Transaction.prototype.fromObj = function fromObj(obj) {
var txobj = {};
txobj.version = obj.version || 1;
txobj.lock_time = obj.lock_time || 0;
@ -645,9 +640,9 @@ function spec(b) {
this.version = txobj.version;
this.ins = txobj.ins;
this.outs = txobj.outs;
}
}
Transaction.prototype.parse = function (parser) {
Transaction.prototype.parse = function (parser) {
if (Buffer.isBuffer(parser)) {
this._buffer = parser;
parser = new Parser(parser);
@ -682,11 +677,11 @@ function spec(b) {
this.lock_time = parser.word32le();
this.calcHash();
};
};
var TransactionInputsCache = exports.TransactionInputsCache =
function TransactionInputsCache(tx)
{
var TransactionInputsCache = exports.TransactionInputsCache =
function TransactionInputsCache(tx)
{
var txList = [];
var txList64 = [];
var reqOuts = {};
@ -713,10 +708,10 @@ function spec(b) {
this.txIndex = {};
this.requiredOuts = reqOuts;
this.callbacks = [];
};
};
TransactionInputsCache.prototype.buffer = function buffer(blockChain, txStore, wait, callback)
{
TransactionInputsCache.prototype.buffer = function buffer(blockChain, txStore, wait, callback)
{
var self = this;
var complete = false;
@ -799,11 +794,11 @@ function spec(b) {
},
self.callback.bind(self)
);
};
};
TransactionInputsCache.prototype.callback = function callback(err)
{
TransactionInputsCache.prototype.callback = function callback(err)
{
var args = Array.prototype.slice.apply(arguments);
// Empty the callback array first (because downstream functions could add new
@ -819,8 +814,6 @@ function spec(b) {
log.err("Callback error after connecting tx inputs: "+
(err.stack ? err.stack : err.toString()));
}
};
return Transaction;
};
module.defineClass(spec);
module.exports = require('soop')(Transaction);

View File

@ -1,15 +1,15 @@
require('classtool');
var imports = require('soop').imports();
var hex = function(hex) {return new Buffer(hex, 'hex');};
function ClassSpec(b) {
var fs = require('fs');
var EncFile = require('./util/EncFile');
var Address = require('./Address').class();
var networks = require('./networks');
var util = b.util || require('./util/util');
var ENC_METHOD = 'aes-256-cbc';
var fs = require('fs');
var EncFile = require('./util/EncFile');
var Address = require('./Address');
var networks = require('./networks');
var util = imports.util || require('./util/util');
var ENC_METHOD = 'aes-256-cbc';
var skeleton = {
var skeleton = {
client: 'libcoin',
client_version: '0.0.1',
network: 'testnet',
@ -19,9 +19,9 @@ function ClassSpec(b) {
keys: [],
sin: {},
scripts: {},
};
};
function Wallet(cfg) {
function Wallet(cfg) {
if (typeof cfg !== 'object')
cfg = {};
@ -33,15 +33,15 @@ function ClassSpec(b) {
this.network = undefined;
this.dirty = cfg.dirty || true;
};
};
Wallet.prototype.readSync = function(filename, passphrase) {
Wallet.prototype.readSync = function(filename, passphrase) {
this.datastore = EncFile.readJFileSync(ENC_METHOD,
passphrase, filename);
this.dirty = false;
};
};
Wallet.prototype.writeSync = function(filename, passphrase) {
Wallet.prototype.writeSync = function(filename, passphrase) {
var tmp_fn = filename + ".tmp";
EncFile.writeJFileSync(ENC_METHOD, passphrase, tmp_fn,
@ -49,9 +49,9 @@ function ClassSpec(b) {
fs.renameSync(tmp_fn, filename);
this.dirty = false;
};
};
Wallet.prototype.setNetwork = function(netname) {
Wallet.prototype.setNetwork = function(netname) {
if (!netname)
netname = this.datastore.network;
@ -70,19 +70,19 @@ function ClassSpec(b) {
// store+canonicalize name
this.datastore['network'] = this.network.name;
this.dirty = true;
};
};
Wallet.prototype.addKey = function(wkey) {
Wallet.prototype.addKey = function(wkey) {
this.datastore.keys.push(wkey);
this.dirty = true;
};
};
Wallet.prototype.addSIN = function(sinObj) {
Wallet.prototype.addSIN = function(sinObj) {
this.datastore.sin[sinObj.sin] = sinObj;
this.dirty = true;
};
};
Wallet.prototype.findKeyHash = function(pubKeyHash) {
Wallet.prototype.findKeyHash = function(pubKeyHash) {
var pkhStr = pubKeyHash.toString();
for (var i = 0; i < this.datastore.keys.length; i++) {
@ -94,9 +94,9 @@ function ClassSpec(b) {
}
return undefined;
};
};
Wallet.prototype.expandKey = function(key) {
Wallet.prototype.expandKey = function(key) {
var addr = new Address(key);
var isAddr = true;
@ -113,9 +113,9 @@ function ClassSpec(b) {
if (!key.match(re))
throw new Error("Unknown key type");
return hex(key);
};
};
Wallet.prototype.expandKeys = function(keys) {
Wallet.prototype.expandKeys = function(keys) {
var res = [];
var us = this;
keys.forEach(function(key) {
@ -123,9 +123,9 @@ function ClassSpec(b) {
res.push(expKey);
});
return res;
};
};
Wallet.prototype.addScript = function(script) {
Wallet.prototype.addScript = function(script) {
var buf = script.getBuffer();
var hash = util.sha256ripe160(buf);
var addr = new Address(this.network.addressScript, hash);
@ -134,9 +134,7 @@ function ClassSpec(b) {
this.dirty = true;
return addrStr;
};
return Wallet;
};
module.defineClass(ClassSpec);
module.exports = require('soop')(Wallet);

View File

@ -1,26 +1,25 @@
require('classtool');
var imports = require('soop').imports();
function ClassSpec(b) {
var coinUtil = require('./util/util');
var timeUtil = require('./util/time');
var KeyModule = require('./Key');
var PrivateKey = require('./PrivateKey').class();
var Address = require('./Address').class();
var coinUtil = require('./util/util');
var timeUtil = require('./util/time');
var KeyModule = require('./Key');
var PrivateKey = require('./PrivateKey');
var Address = require('./Address');
function WalletKey(cfg) {
function WalletKey(cfg) {
if (!cfg) cfg = {};
if (!cfg.network) throw new Error('network parameter is required');
this.network = cfg.network; // required
this.created = cfg.created;
this.privKey = cfg.privKey;
};
};
WalletKey.prototype.generate = function() {
WalletKey.prototype.generate = function() {
this.privKey = KeyModule.Key.generateSync();
this.created = timeUtil.curtime();
};
};
WalletKey.prototype.storeObj = function() {
WalletKey.prototype.storeObj = function() {
var pubKey = this.privKey.public.toString('hex');
var pubKeyHash = coinUtil.sha256ripe160(this.privKey.public);
var addr = new Address(this.network.addressPubkey, pubKeyHash);
@ -33,9 +32,9 @@ function ClassSpec(b) {
};
return obj;
};
};
WalletKey.prototype.fromObj = function(obj) {
WalletKey.prototype.fromObj = function(obj) {
this.created = obj.created;
this.privKey = new KeyModule.Key();
if (obj.priv.length==64) {
@ -48,8 +47,6 @@ function ClassSpec(b) {
this.privKey.compressed = priv.compressed();
}
this.privKey.regenerateSync();
};
return WalletKey;
};
module.defineClass(ClassSpec);
module.exports = require('soop')(WalletKey);

View File

@ -3,25 +3,27 @@
*/
module.exports.bignum = require('bignum');
module.exports.base58 = require('base58-native');
module.exports.buffertools = require('buffertools');
module.exports.config = require('./config');
module.exports.const = require('./const');
module.exports.Deserialize = require('./Deserialize');
module.exports.log = require('./util/log');
module.exports.networks = require('./networks');
module.exports.util = require('./util/util');
module.exports.EncodedData = require('./util/EncodedData');
module.exports.VersionedData = require('./util/VersionedData');
module.exports.Address = require('./Address');
module.exports.Opcode = require('./Opcode');
module.exports.Script = require('./Script');
module.exports.Transaction = require('./Transaction');
module.exports.Peer = require('./Peer');
module.exports.PeerManager = require('./PeerManager');
module.exports.Block = require('./Block');
module.exports.Connection = require('./Connection');
module.exports.Peer = require('./Peer');
module.exports.Block = require('./Block');
module.exports.ScriptInterpreter = require('./ScriptInterpreter');
module.exports.Bloom = require('./Bloom');
module.exports.KeyModule = require('./Key');
@ -34,6 +36,14 @@ module.exports.WalletKey = require('./WalletKey');
module.exports.Buffer = Buffer;
if (typeof process.versions === 'undefined') {
// Browser specific
module.exports.bignum.config({EXPONENTIAL_AT: 9999999, DECIMAL_PLACES: 0, ROUNDING_MODE: 1});
// module.exports.PeerManager = function () {
// throw new Error('PeerManager not availabe in browser Bitcore, under .bitcore. Use it with: require(\'PeerManager\');');
// };
}
else {
// Nodejs specific
module.exports.PeerManager = require('./PeerManager');
}

6
browser/bignum_config.js Normal file
View File

@ -0,0 +1,6 @@
require('bignum').config({
EXPONENTIAL_AT: 9999999,
DECIMAL_PLACES: 0,
ROUNDING_MODE: 1,
});

88
browserify.js Normal file
View File

@ -0,0 +1,88 @@
'use strict';
/*
* Example for usage of browserify with soop
*
* The key parameter 'pack'
* The supplied 'custom_prelude.js' file is needed for
* .load function of soop.
*/
var fs = require('fs');
var browserify = require('browserify');
var browserPack = require('browser-pack');
var opts = {};
var preludePath = 'node_modules/soop/example/custom_prelude.js';
var pack = function (params) {
params.raw = true;
params.sourceMapPrefix = '//#';
params.prelude= fs.readFileSync(preludePath, 'utf8');
params.preludePath= preludePath;
return browserPack(params);
};
opts.pack = pack;
opts.debug = true;
var modules = [
'Address',
'Block',
'Bloom',
'Buffers.monkey',
'Connection',
'Deserialize',
'Gruntfile',
'Number.monkey',
'Opcode',
'Peer',
'PeerManager',
'PrivateKey',
'RpcClient',
'SIN',
'SINKey',
'Script',
'ScriptInterpreter',
'Sign',
'Transaction',
'Wallet',
'WalletKey',
'config',
'const',
'networks',
'bitcore',
];
var b = browserify(opts);
b.require('browserify-bignum/bignumber.js', {expose: 'bignum'} );
b.require('browserify-buffertools/buffertools.js', {expose:'buffertools'});
b.require('buffer', {expose: 'buffer'});
b.require('base58-native');
b.require('./Key.js', {expose: 'KeyModule'});
b.require('./util/log');
b.require('./util/util');
b.require('./util/EncodedData');
b.require('./util/VersionedData');
b.add('./browser/bignum_config.js');
modules.forEach(function(m) {
b.require('./' + m + '.js' ,{expose:m} );
});
var bopts = {
// detectGlobals: true,
// insertGlobals: 'Buffer',
// insertGlobalVars: {
// Buffer: function () {
// return 'require("buffer").Buffer';
// },
// },
};
b.bundle(bopts).pipe(process.stdout);

View File

@ -2,7 +2,7 @@
// Replace '..' with 'bitcore' if you plan on using this code elsewhere.
var Address = require('../Address').class();
var Address = require('../Address');
var addrStrings = [
"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",

View File

@ -4,10 +4,9 @@
var util = require('util');
var networks = require('../networks');
var Peer = require('../Peer').class();
var PeerManager = require('../PeerManager').createClass({
network: networks.testnet
});
var Peer = require('../Peer');
var PeerManager = require('soop').load('../PeerManager',
{network: networks.testnet});
var handleBlock = function(info) {

View File

@ -3,7 +3,7 @@
// Replace '..' with 'bitcore' if you plan on using this code elsewhere.
var util = require('util');
var RpcClient = require('../RpcClient').class();
var RpcClient = require('../RpcClient');
var hash = process.argv[2] || '0000000000b6288775bbd326bedf324ca8717a15191da58391535408205aada4';
var config = {

View File

@ -2,14 +2,13 @@
// Replace '..' with 'bitcore' if you plan on using this code elsewhere.
var networks = require('../networks');
var Peer = require('../Peer').class();
var Transaction = require('../Transaction').class();
var Address = require('../Address').class();
var Script = require('../Script').class();
var Peer = require('../Peer');
var Transaction = require('../Transaction');
var Address = require('../Address');
var Script = require('../Script');
var coinUtil = require('../util/util');
var PeerManager = require('../PeerManager').createClass({
network: networks.testnet
});
var PeerManager = require('soop').load('../PeerManager',
{network: networks.testnet});
var createTx = function() {

View File

@ -6,18 +6,19 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<pre>
<div id='content'></div>
</pre>
<script src="../browser/bundle.js"></script>
<script type="text/javascript">
var Address = require('Address');
print = function(s){
var div = document.getElementById('content');
div.innerHTML += s + '<br />';
};
var Address = bitcore.Address.class();
var addrStrings = [
"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
"1A1zP1eP5QGefi2DMPTfTL5SLmv7Dixxxx",
@ -37,15 +38,33 @@
}
});
print('<hr>');
var Key = bitcore.KeyModule.Key;
var Key = require('KeyModule').Key;
var buffertools = require('buffertools');
var k = Key.generateSync();
print ('Generated Key Pair:');
print ('Private:' + bitcore.buffertools.toHex(k.private));
print ('Public:' + bitcore.buffertools.toHex(k.public));
print ('Generate Key Pair:');
print ('Private:' + buffertools.toHex(k.private));
print ('Public:' + buffertools.toHex(k.public));
print('<hr>');
/*
Using bitcore root module
*/
var bitcore = require('bitcore');
var k = bitcore.KeyModule.Key.generateSync();
print ('Generate Key Pair:');
print ('Private:' + buffertools.toHex(k.private));
print ('Public:' + buffertools.toHex(k.public));
print('<hr>');
console.log('[example.html.65:PeerManager:]'); //TODO
var pm = require('PeerManager');
</script>
</body>

View File

@ -44,7 +44,7 @@
"test": "mocha test -R spec"
},
"dependencies": {
"classtool": "git://github.com/bitpay/classtool.git",
"soop": "git://github.com/matiu/node-soop.git#feature/browser-support",
"base58-native": "=0.1.3",
"bindings": "=1.1.1",
"bufferput": "git://github.com/bitpay/node-bufferput.git",
@ -57,7 +57,8 @@
"devDependencies": {
"grunt-contrib-watch": "~0.5.3",
"grunt-mocha-test": "~0.8.2",
"grunt-browserify": "~1.3.0",
"grunt-shell": "~0.6.4",
"browser-pack": "*",
"grunt-markdown": "~0.5.0",
"mocha": ">=1.15.1",
"browserify-bignum": "git://github.com/maraoz/browserify-bignum.git",

View File

@ -13,7 +13,14 @@
<script>mocha.setup('bdd')</script>
<script src="../browser/bundle.js"></script>
<script src="../browser/testdata.js"></script>
<script src="adapter.js"></script>
<script>
var bitcore = require('bitcore');
this.Buffer = require('buffer').Buffer;
</script>
<!-- <script src="adapter.js"></script> -->
<script src="test.Address.js"></script>
<script src="test.basic.js"></script>

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('Address', function() {
should.exist(AddressModule);
});
it('should be able to create class', function() {
Address = AddressModule.class();
Address = AddressModule;
should.exist(Address);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
var BlockModule = bitcore.Block;
@ -12,7 +12,7 @@ describe('Block', function() {
should.exist(BlockModule);
});
it('should be able to create class', function() {
Block = BlockModule.class();
Block = BlockModule;
should.exist(Block);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('Bloom', function() {
should.exist(BloomModule);
});
it('should be able to create class', function() {
Bloom = BloomModule.class();
Bloom = BloomModule;
should.exist(Bloom);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -14,7 +14,7 @@ describe('Connection', function() {
should.exist(ConnectionModule);
});
it('should be able to create class', function() {
Connection = ConnectionModule.class();
Connection = ConnectionModule;
should.exist(Connection);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('EncodedData', function() {
should.exist(EncodedDataModule);
});
it('should be able to create class', function() {
EncodedData = EncodedDataModule.class();
EncodedData = EncodedDataModule;
should.exist(EncodedData);
});
it('should be able to create an instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var buffertools = require('buffertools');

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('Opcode', function() {
should.exist(OpcodeModule);
});
it('should be able to create class', function() {
Opcode = OpcodeModule.class();
Opcode = OpcodeModule;
should.exist(Opcode);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('Peer', function() {
should.exist(PeerModule);
});
it('should be able to create class', function() {
Peer = PeerModule.class();
Peer = PeerModule;
should.exist(Peer);
});
it('should be able to create instance', function() {

View File

@ -1,11 +1,12 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
var PeerManagerModule = bitcore.PeerManager;
var PeerManagerModule = bitcore.PeerManager || require('PeerManager');
var PeerManager;
describe('PeerManager', function() {
@ -13,7 +14,7 @@ describe('PeerManager', function() {
should.exist(PeerManagerModule);
});
it('should be able to create class', function() {
PeerManager = PeerManagerModule.class();
PeerManager = PeerManagerModule;
should.exist(PeerManager);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -15,7 +15,7 @@ describe('PrivateKey', function() {
should.exist(PrivateKeyModule);
});
it('should be able to create class', function() {
PrivateKey = PrivateKeyModule.class();
PrivateKey = PrivateKeyModule;
should.exist(PrivateKey);
});
it('should be able to create instance', function() {

View File

@ -1,13 +1,13 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
var RpcClientModule = bitcore.RpcClient;
var RpcClient;
RpcClient = RpcClientModule.class();
RpcClient = RpcClientModule;
describe('RpcClient', function() {
it('should initialze the main object', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('SIN', function() {
should.exist(SINModule);
});
it('should be able to create class', function() {
SIN = SINModule.class();
SIN = SINModule;
should.exist(SIN);
});
it('should be able to create instance', function() {

View File

@ -1,10 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
var SINKeyModule = bitcore.SINKey;
@ -16,7 +13,7 @@ describe('SINKey', function() {
should.exist(SINKeyModule);
});
it('should be able to create class', function() {
SINKey = SINKeyModule.class();
SINKey = SINKeyModule;
should.exist(SINKey);
});
it('should be able to create instance', function() {

View File

@ -1,12 +1,12 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
var ScriptModule = bitcore.Script;
var Address = bitcore.Address.class();
var Address = bitcore.Address;
var networks = bitcore.networks;
var Script;
var test_data = require('./testdata');
@ -16,7 +16,7 @@ describe('Script', function() {
should.exist(ScriptModule);
});
it('should be able to create class', function() {
Script = ScriptModule.class();
Script = ScriptModule;
should.exist(Script);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('ScriptInterpreter', function() {
should.exist(ScriptInterpreterModule);
});
it('should be able to create class', function() {
ScriptInterpreter = ScriptInterpreterModule.class();
ScriptInterpreter = ScriptInterpreterModule;
should.exist(ScriptInterpreter);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -9,7 +9,7 @@ var TransactionModule = bitcore.Transaction;
var Transaction;
var In;
var Out;
var Script = bitcore.Script.class();
var Script = bitcore.Script;
var buffertools = require('buffertools');
var test_data = require('./testdata');
@ -18,7 +18,7 @@ describe('Transaction', function() {
should.exist(TransactionModule);
});
it('should be able to create class', function() {
Transaction = TransactionModule.class();
Transaction = TransactionModule;
should.exist(Transaction);
In = Transaction.In;
Out = Transaction.Out;

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('VersionedData', function() {
should.exist(VersionedDataModule);
});
it('should be able to create class', function() {
VersionedData = VersionedDataModule.class();
VersionedData = VersionedDataModule;
should.exist(VersionedData);
});
it('should be able to create an instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -13,7 +13,7 @@ describe('Wallet', function() {
should.exist(WalletModule);
});
it('should be able to create class', function() {
Wallet = WalletModule.class();
Wallet = WalletModule;
should.exist(Wallet);
});
it('should be able to create instance', function() {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();
@ -14,7 +14,7 @@ describe('WalletKey', function() {
should.exist(WalletKeyModule);
});
it('should be able to create class', function() {
WalletKey = WalletKeyModule.class();
WalletKey = WalletKeyModule;
should.exist(WalletKey);
});
it('should be able to create instance', function() {

View File

@ -1,15 +1,27 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var test_data;
if (typeof dataValid !== 'undefined' ) {
test_data = {
dataValid: dataValid,
dataInvalid: dataInvalid,
};
}
else {
test_data = require('./testdata');
}
var should = chai.should();
var Address = bitcore.Address.class();
var PrivateKey = bitcore.PrivateKey.class();
var Address = bitcore.Address;
var PrivateKey = bitcore.PrivateKey;
var networks = bitcore.networks;
var KeyModule = bitcore.KeyModule;
var test_data = require('./testdata');
function test_encode_priv(b58, payload, isTestnet, isCompressed) {

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var expect = chai.expect;
var should = chai.should();

View File

@ -1,7 +1,7 @@
'use strict';
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var should = chai.should();

View File

@ -1,5 +1,6 @@
var chai = require('chai');
var bitcore = require('../bitcore');
var chai = chai || require('chai');
var bitcore = bitcore || require('../bitcore');
var coinUtil = bitcore.util;
var should = chai.should();
var buffertools = require('buffertools');

View File

@ -1,5 +1,3 @@
var fs = require('fs');
var dataValid = JSON.parse(fs.readFileSync('test/data/base58_keys_valid.json'));

View File

@ -2,20 +2,20 @@
* Simple synchronous parser based on node-binary.
*/
function spec(b) {
function Parser(buffer)
{
var imports = require('soop').imports();
function Parser(buffer)
{
this.subject = buffer;
this.pos = 0;
};
};
Parser.prototype.buffer = function buffer(len) {
Parser.prototype.buffer = function buffer(len) {
var buf = this.subject.slice(this.pos, this.pos+len);
this.pos += len;
return buf;
};
};
Parser.prototype.search = function search(needle) {
Parser.prototype.search = function search(needle) {
var len;
if ("string" === typeof needle || Buffer.isBuffer(needle)) {
@ -38,12 +38,12 @@ function spec(b) {
}
return -1;
}
};
};
/**
/**
* Like search(), but returns the skipped bytes
*/
Parser.prototype.scan = function scan(needle) {
Parser.prototype.scan = function scan(needle) {
var startPos = this.pos;
var len = this.search(needle);
if (len !== -1) {
@ -51,55 +51,55 @@ function spec(b) {
} else {
throw new Error('No match');
}
};
};
Parser.prototype.eof = function eof() {
Parser.prototype.eof = function eof() {
return this.pos >= this.subject.length;
};
};
// convert byte strings to unsigned little endian numbers
function decodeLEu (bytes) {
// convert byte strings to unsigned little endian numbers
function decodeLEu (bytes) {
var acc = 0;
for (var i = 0; i < bytes.length; i++) {
acc += Math.pow(256,i) * bytes[i];
}
return acc;
}
}
// convert byte strings to unsigned big endian numbers
function decodeBEu (bytes) {
// convert byte strings to unsigned big endian numbers
function decodeBEu (bytes) {
var acc = 0;
for (var i = 0; i < bytes.length; i++) {
acc += Math.pow(256, bytes.length - i - 1) * bytes[i];
}
return acc;
}
}
// convert byte strings to signed big endian numbers
function decodeBEs (bytes) {
// convert byte strings to signed big endian numbers
function decodeBEs (bytes) {
var val = decodeBEu(bytes);
if ((bytes[0] & 0x80) == 0x80) {
val -= Math.pow(256, bytes.length);
}
return val;
}
}
// convert byte strings to signed little endian numbers
function decodeLEs (bytes) {
// convert byte strings to signed little endian numbers
function decodeLEs (bytes) {
var val = decodeLEu(bytes);
if ((bytes[bytes.length - 1] & 0x80) == 0x80) {
val -= Math.pow(256, bytes.length);
}
return val;
}
}
function getDecoder(len, fn) {
function getDecoder(len, fn) {
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']
@ -118,10 +118,10 @@ function spec(b) {
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:
@ -136,13 +136,11 @@ function spec(b) {
default:
return firstByte;
}
};
};
Parser.prototype.varStr = function () {
Parser.prototype.varStr = function () {
var len = this.varInt();
return this.buffer(len);
};
return Parser;
};
module.defineClass(spec);
module.exports = require('soop')(Parser);

View File

@ -1,92 +1,91 @@
require('classtool');
var imports = require('soop').imports();
var base58 = imports.base58 || require('base58-native').base58Check;
function ClassSpec(b) {
var base58 = b.base58 || require('base58-native').base58Check;
// Constructor. Takes the following forms:
// new EncodedData(<base58_address_string>)
// new EncodedData(<binary_buffer>)
// new EncodedData(<data>, <encoding>)
// new EncodedData(<version>, <20-byte-hash>)
function EncodedData(data, encoding) {
// Constructor. Takes the following forms:
// new EncodedData(<base58_address_string>)
// new EncodedData(<binary_buffer>)
// new EncodedData(<data>, <encoding>)
// new EncodedData(<version>, <20-byte-hash>)
function EncodedData(data, encoding) {
this.data = data;
if(!encoding && (typeof data == 'string')) {
this.__proto__ = this.encodings['base58'];
} else {
this.__proto__ = this.encodings[encoding || 'binary'];
}
};
};
// get or set the encoding used (transforms data)
EncodedData.prototype.encoding = function(encoding) {
// get or set the encoding used (transforms data)
EncodedData.prototype.encoding = function(encoding) {
if(encoding && (encoding != this._encoding)) {
this.data = this.as(encoding);
this.__proto__ = this.encodings[encoding];
}
return this._encoding;
};
};
// answer a new instance having the given encoding
EncodedData.prototype.withEncoding = function(encoding) {
// answer a new instance having the given encoding
EncodedData.prototype.withEncoding = function(encoding) {
return new EncodedData(this.as(encoding), encoding);
};
};
// answer the data in the given encoding
EncodedData.prototype.as = function(encoding) {
// answer the data in the given encoding
EncodedData.prototype.as = function(encoding) {
if(!encodings[encoding]) throw new Error('invalid encoding');
return this.converters[encoding].call(this);
};
};
// validate that we can convert to binary
EncodedData.prototype._validate = function() {
// validate that we can convert to binary
EncodedData.prototype._validate = function() {
this.withEncoding('binary');
};
};
// Boolean protocol for testing if valid
EncodedData.prototype.isValid = function() {
// Boolean protocol for testing if valid
EncodedData.prototype.isValid = function() {
try {
this.validate();
return true;
} catch(e) {
return false;
}
};
};
// subclasses can override to do more stuff
EncodedData.prototype.validate = function() {
// subclasses can override to do more stuff
EncodedData.prototype.validate = function() {
this._validate();
};
};
// Boolean protocol for testing if valid
EncodedData.prototype.isValid = function() {
// Boolean protocol for testing if valid
EncodedData.prototype.isValid = function() {
try {
this.validate();
return true;
} catch(e) {
return false;
}
};
};
// convert to a string (in base58 form)
EncodedData.prototype.toString = function() {
// convert to a string (in base58 form)
EncodedData.prototype.toString = function() {
return this.as('base58');
};
};
// utility
EncodedData.prototype.doAsBinary = function(callback) {
// utility
EncodedData.prototype.doAsBinary = function(callback) {
var oldEncoding = this.encoding();
this.encoding('binary');
callback.apply(this);
this.encoding(oldEncoding);
};
};
// Setup support for various address encodings. The object for
// each encoding inherits from the EncodedData prototype. This
// allows any encoding to override any method...changing the encoding
// for an instance will change the encoding it inherits from. Note,
// this will present some problems for anyone wanting to inherit from
// EncodedData (we'll deal with that when needed).
var encodings = {
// Setup support for various address encodings. The object for
// each encoding inherits from the EncodedData prototype. This
// allows any encoding to override any method...changing the encoding
// for an instance will change the encoding it inherits from. Note,
// this will present some problems for anyone wanting to inherit from
// EncodedData (we'll deal with that when needed).
var encodings = {
'binary': {
converters: {
'binary': function() {
@ -128,18 +127,18 @@ function ClassSpec(b) {
},
},
},
};
};
var no_conversion = function() {return this.data;};
for(var k in encodings) {
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;
}
}
}
EncodedData.applyEncodingsTo = function(aClass) {
EncodedData.applyEncodingsTo = function(aClass) {
var tmp = {};
for(var k in encodings) {
var enc = encodings[k];
@ -151,9 +150,9 @@ function ClassSpec(b) {
tmp[k] = obj;
}
aClass.prototype.encodings = tmp;
};
};
EncodedData.applyEncodingsTo(EncodedData);
module.exports = require('soop')(EncodedData);
EncodedData.applyEncodingsTo(EncodedData);
return EncodedData;
}
module.defineClass(ClassSpec);

View File

@ -1,9 +1,9 @@
require('classtool');
var imports = require('soop').imports();
var base58 = imports.base58 || require('base58-native').base58Check;
var parent = imports.parent || require('./EncodedData');
function ClassSpec(b) {
var superclass = b.superclass || require('./EncodedData').class();
function VersionedData(version, payload) {
function VersionedData(version, payload) {
if(typeof version != 'number') {
VersionedData.super(this, arguments);
return;
@ -12,28 +12,27 @@ function ClassSpec(b) {
this.__proto__ = this.encodings['binary'];
this.version(version);
this.payload(payload);
};
VersionedData.superclass = superclass;
superclass.applyEncodingsTo(VersionedData);
};
// get or set the version data (the first byte of the address)
VersionedData.prototype.version = function(num) {
VersionedData.parent = parent;
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);});
return num;
}
return this.as('binary').readUInt8(0);
};
};
// get or set the payload data (as a Buffer object)
VersionedData.prototype.payload = function(data) {
// 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);});
return data;
}
return this.as('binary').slice(1);
};
return VersionedData;
};
module.defineClass(ClassSpec);
module.exports = require('soop')(VersionedData);