all classes working with soop and test passing

This commit is contained in:
Matias Alejo Garcia 2014-03-05 16:11:16 -03:00
parent fa1e323d39
commit c0c325dabd
38 changed files with 4700 additions and 4763 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) { function Address() {
var superclass = b.superclass || require('./util/VersionedData').class();
function Address() {
Address.super(this, arguments); Address.super(this, arguments);
} }
Address.superclass = superclass; Address.parent = parent;
superclass.applyEncodingsTo(Address); parent.applyEncodingsTo(Address);
Address.prototype.validate = function() { Address.prototype.validate = function() {
this.doAsBinary(function() { this.doAsBinary(function() {
Address.super(this, 'validate', arguments); Address.super(this, 'validate', arguments);
if(this.data.length !== 21) throw new Error('invalid data length'); if(this.data.length !== 21) throw new Error('invalid data length');
}); });
}; };
return Address; module.exports = require('soop')(Address);
}
module.defineClass(ClassSpec);

193
Block.js
View File

@ -1,25 +1,24 @@
require('classtool'); var imports = require('soop').imports();
function spec(b) { var util = imports.util || require('./util/util');
var util = b.util || require('./util/util'); var Debug1 = imports.Debug1 || function() {};
var Debug1 = b.Debug1 || function() {}; var Script = imports.Script || require('./Script');
var Script = b.Script || require('./Script').class(); var Bignum = imports.Bignum || require('bignum');
var Bignum = b.Bignum || require('bignum'); var Binary = imports.Binary || require('binary');
var Binary = b.Binary || require('binary'); var Step = imports.Step || require('step');
var Step = b.Step || require('step'); var buffertools = imports.buffertools || require('buffertools');
var buffertools = b.buffertools || require('buffertools'); var Transaction = imports.Transaction || require('./Transaction');
var Transaction = b.Transaction || require('./Transaction').class(); var TransactionIn = Transaction.In;
var TransactionIn = Transaction.In; var TransactionOut = Transaction.Out;
var TransactionOut = Transaction.Out; var COINBASE_OP = Transaction.COINBASE_OP;
var COINBASE_OP = Transaction.COINBASE_OP; var VerificationError = imports.VerificationError || require('./util/error').VerificationError;
var VerificationError = b.VerificationError || require('./util/error').VerificationError; var BlockRules = {
var BlockRules = {
maxTimeOffset: 2 * 60 * 60, // How far block timestamps can be into the future maxTimeOffset: 2 * 60 * 60, // How far block timestamps can be into the future
largestHash: Bignum(2).pow(256) largestHash: Bignum(2).pow(256)
}; };
function Block(data) function Block(data)
{ {
if ("object" !== typeof data) { if ("object" !== typeof data) {
data = {}; data = {};
} }
@ -35,9 +34,9 @@ function spec(b) {
this.active = data.active || false; this.active = data.active || false;
this.chainWork = data.chainWork || util.EMPTY_BUFFER; this.chainWork = data.chainWork || util.EMPTY_BUFFER;
this.txs = data.txs || []; this.txs = data.txs || [];
} }
Block.prototype.getHeader = function getHeader() { Block.prototype.getHeader = function getHeader() {
var buf = new Buffer(80); var buf = new Buffer(80);
var ofs = 0; var ofs = 0;
buf.writeUInt32LE(this.version, ofs); ofs += 4; buf.writeUInt32LE(this.version, ofs); ofs += 4;
@ -47,9 +46,9 @@ function spec(b) {
buf.writeUInt32LE(this.bits, ofs); ofs += 4; buf.writeUInt32LE(this.bits, ofs); ofs += 4;
buf.writeUInt32LE(this.nonce, ofs); ofs += 4; buf.writeUInt32LE(this.nonce, ofs); ofs += 4;
return buf; return buf;
}; };
Block.prototype.parse = function parse(parser, headerOnly) { Block.prototype.parse = function parse(parser, headerOnly) {
this.version = parser.word32le(); this.version = parser.word32le();
this.prev_hash = parser.buffer(32); this.prev_hash = parser.buffer(32);
this.merkle_root = parser.buffer(32); this.merkle_root = parser.buffer(32);
@ -70,26 +69,26 @@ function spec(b) {
tx.parse(parser); tx.parse(parser);
this.txs.push(tx); this.txs.push(tx);
} }
}; };
Block.prototype.calcHash = function calcHash() { Block.prototype.calcHash = function calcHash() {
var header = this.getHeader(); var header = this.getHeader();
return util.twoSha256(header); return util.twoSha256(header);
}; };
Block.prototype.checkHash = function checkHash() { Block.prototype.checkHash = function checkHash() {
if (!this.hash || !this.hash.length) return false; if (!this.hash || !this.hash.length) return false;
return buffertools.compare(this.calcHash(), this.hash) == 0; 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(); if (!this.hash || !this.hash.length) this.hash = this.calcHash();
return this.hash; return this.hash;
}; };
Block.prototype.checkProofOfWork = function checkProofOfWork() { Block.prototype.checkProofOfWork = function checkProofOfWork() {
var target = util.decodeDiffBits(this.bits); var target = util.decodeDiffBits(this.bits);
// TODO: Create a compare method in node-buffertools that uses the correct // TODO: Create a compare method in node-buffertools that uses the correct
@ -104,30 +103,30 @@ function spec(b) {
buffertools.reverse(this.hash); buffertools.reverse(this.hash);
return true; return true;
}; };
/** /**
* Returns the amount of work that went into this block. * Returns the amount of work that went into this block.
* *
* Work is defined as the average number of tries required to meet this * 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% * 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. * 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); var target = util.decodeDiffBits(this.bits, true);
return BlockRules.largestHash.div(target.add(1)); return BlockRules.largestHash.div(target.add(1));
}; };
Block.prototype.checkTimestamp = function checkTimestamp() { Block.prototype.checkTimestamp = function checkTimestamp() {
var currentTime = new Date().getTime() / 1000; var currentTime = new Date().getTime() / 1000;
if (this.timestamp > currentTime + BlockRules.maxTimeOffset) { if (this.timestamp > currentTime + BlockRules.maxTimeOffset) {
throw new VerificationError('Timestamp too far into the future'); throw new VerificationError('Timestamp too far into the future');
} }
return true; return true;
}; };
Block.prototype.checkTransactions = function checkTransactions(txs) { Block.prototype.checkTransactions = function checkTransactions(txs) {
if (!Array.isArray(txs) || txs.length <= 0) { if (!Array.isArray(txs) || txs.length <= 0) {
throw new VerificationError('No transactions'); throw new VerificationError('No transactions');
} }
@ -141,15 +140,15 @@ function spec(b) {
} }
return true; return true;
}; };
/** /**
* Build merkle tree. * Build merkle tree.
* *
* Ported from Java. Original code: BitcoinJ by Mike Hearn * Ported from Java. Original code: BitcoinJ by Mike Hearn
* Copyright (c) 2011 Google Inc. * 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: // The merkle hash is based on a tree of hashes calculated from the transactions:
// //
// merkleHash // merkleHash
@ -188,14 +187,14 @@ function spec(b) {
} }
return tree; return tree;
}; };
Block.prototype.calcMerkleRoot = function calcMerkleRoot(txs) { Block.prototype.calcMerkleRoot = function calcMerkleRoot(txs) {
var tree = this.getMerkleTree(txs); var tree = this.getMerkleTree(txs);
return tree[tree.length - 1]; 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) { if (!this.merkle_root || !this.merkle_root.length) {
throw new VerificationError('No merkle root'); throw new VerificationError('No merkle root');
} }
@ -205,9 +204,9 @@ function spec(b) {
} }
return true; return true;
}; };
Block.prototype.checkBlock = function checkBlock(txs) { Block.prototype.checkBlock = function checkBlock(txs) {
if (!this.checkHash()) { if (!this.checkHash()) {
throw new VerificationError("Block hash invalid"); throw new VerificationError("Block hash invalid");
} }
@ -221,31 +220,31 @@ function spec(b) {
} }
} }
return true; return true;
}; };
Block.getBlockValue = function getBlockValue(height) { Block.getBlockValue = function getBlockValue(height) {
var subsidy = Bignum(50).mul(util.COIN); var subsidy = Bignum(50).mul(util.COIN);
subsidy = subsidy.div(Bignum(2).pow(Math.floor(height / 210000))); subsidy = subsidy.div(Bignum(2).pow(Math.floor(height / 210000)));
return subsidy; return subsidy;
}; };
Block.prototype.getBlockValue = function getBlockValue() { Block.prototype.getBlockValue = function getBlockValue() {
return Block.getBlockValue(this.height); return Block.getBlockValue(this.height);
}; };
Block.prototype.toString = function toString() { Block.prototype.toString = function toString() {
return "<Block " + util.formatHashAlt(this.hash) + " height="+this.height+">"; return "<Block " + util.formatHashAlt(this.hash) + " height="+this.height+">";
}; };
/** /**
* Initializes some properties based on information from the parent block. * 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.height = parent.height + 1;
this.setChainWork(parent.getChainWork().add(this.getWork())); this.setChainWork(parent.getChainWork().add(this.getWork()));
}; };
Block.prototype.setChainWork = function setChainWork(chainWork) { Block.prototype.setChainWork = function setChainWork(chainWork) {
if (Buffer.isBuffer(chainWork)) { if (Buffer.isBuffer(chainWork)) {
// Nothing to do // Nothing to do
} else if ("function" === typeof chainWork.toBuffer) { // duck-typing bignum } else if ("function" === typeof chainWork.toBuffer) { // duck-typing bignum
@ -255,24 +254,24 @@ function spec(b) {
} }
this.chainWork = chainWork; this.chainWork = chainWork;
}; };
Block.prototype.getChainWork = function getChainWork() { Block.prototype.getChainWork = function getChainWork() {
return Bignum.fromBuffer(this.chainWork); return Bignum.fromBuffer(this.chainWork);
}; };
/** /**
* Compares the chainWork of two blocks. * 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; return this.getChainWork().cmp(otherBlock.getChainWork()) > 0;
}; };
/** /**
* Returns the difficulty target for the next block after this one. * Returns the difficulty target for the next block after this one.
*/ */
Block.prototype.getNextWork = Block.prototype.getNextWork =
function getNextWork(blockChain, nextBlock, callback) { function getNextWork(blockChain, nextBlock, callback) {
var self = this; var self = this;
var powLimit = blockChain.getMinDiff(); var powLimit = blockChain.getMinDiff();
@ -371,13 +370,13 @@ function spec(b) {
} }
); );
} }
}; };
var medianTimeSpan = 11; var medianTimeSpan = 11;
Block.prototype.getMedianTimePast = Block.prototype.getMedianTimePast =
function getMedianTimePast(blockChain, callback) function getMedianTimePast(blockChain, callback)
{ {
var self = this; var self = this;
Step( Step(
@ -407,11 +406,11 @@ function spec(b) {
}, },
callback callback
); );
}; };
Block.prototype.verifyChild = Block.prototype.verifyChild =
function verifyChild(blockChain, child, callback) function verifyChild(blockChain, child, callback)
{ {
var self = this; var self = this;
Step( Step(
@ -444,11 +443,11 @@ function spec(b) {
}, },
callback callback
); );
}; };
Block.prototype.createCoinbaseTx = Block.prototype.createCoinbaseTx =
function createCoinbaseTx(beneficiary) function createCoinbaseTx(beneficiary)
{ {
var tx = new Transaction(); var tx = new Transaction();
tx.ins.push(new TransactionIn({ tx.ins.push(new TransactionIn({
s: util.EMPTY_BUFFER, s: util.EMPTY_BUFFER,
@ -460,11 +459,11 @@ function spec(b) {
s: Script.createPubKeyOut(beneficiary).getBuffer() s: Script.createPubKeyOut(beneficiary).getBuffer()
})); }));
return tx; return tx;
}; };
Block.prototype.prepareNextBlock = Block.prototype.prepareNextBlock =
function prepareNextBlock(blockChain, beneficiary, time, callback) function prepareNextBlock(blockChain, beneficiary, time, callback)
{ {
var self = this; var self = this;
var newBlock = new Block(); var newBlock = new Block();
@ -512,11 +511,11 @@ function spec(b) {
}, },
callback callback
); );
}; };
Block.prototype.mineNextBlock = Block.prototype.mineNextBlock =
function mineNextBlock(blockChain, beneficiary, time, miner, callback) function mineNextBlock(blockChain, beneficiary, time, miner, callback)
{ {
this.prepareNextBlock(blockChain, beneficiary, time, function (err, data) { this.prepareNextBlock(blockChain, beneficiary, time, function (err, data) {
try { try {
if (err) throw err; if (err) throw err;
@ -539,20 +538,20 @@ function spec(b) {
callback(e); callback(e);
} }
}); });
}; };
Block.prototype.solve = function solve(miner, callback) { Block.prototype.solve = function solve(miner, callback) {
var header = this.getHeader(); var header = this.getHeader();
var target = util.decodeDiffBits(this.bits); var target = util.decodeDiffBits(this.bits);
miner.solve(header, target, callback); miner.solve(header, target, callback);
}; };
/** /**
* Returns an object with the same field names as jgarzik's getblock patch. * Returns an object with the same field names as jgarzik's getblock patch.
*/ */
Block.prototype.getStandardizedObject = Block.prototype.getStandardizedObject =
function getStandardizedObject(txs) function getStandardizedObject(txs)
{ {
var block = { var block = {
hash: util.formatHashFull(this.getHash()), hash: util.formatHashFull(this.getHash()),
version: this.version, version: this.version,
@ -587,8 +586,6 @@ function spec(b) {
block.size = this.size; block.size = this.size;
} }
return block; 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) { function Bloom() {
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() {
this.data = ''; this.data = '';
this.hashFuncs = 0; this.hashFuncs = 0;
}; };
function ROTL32(x, r) { function ROTL32(x, r) {
return (x << r) | (x >> (32 - r)); return (x << r) | (x >> (32 - r));
}; };
function getBlockU32(blockIdx, data) { function getBlockU32(blockIdx, data) {
var idx = blockIdx * 4; var idx = blockIdx * 4;
var v = (data[idx + 0] << (0 * 8)) | var v = (data[idx + 0] << (0 * 8)) |
(data[idx + 1] << (1 * 8)) | (data[idx + 1] << (1 * 8)) |
(data[idx + 2] << (2 * 8)) | (data[idx + 2] << (2 * 8)) |
(data[idx + 3] << (3 * 8)); (data[idx + 3] << (3 * 8));
return v; return v;
}; };
Bloom.prototype.hash = function(hashNum, data) { Bloom.prototype.hash = function(hashNum, data) {
var h1 = hashNum * (0xffffffff / (this.hashFuncs - 1)); var h1 = hashNum * (0xffffffff / (this.hashFuncs - 1));
var c1 = 0xcc9e2d51; var c1 = 0xcc9e2d51;
var c2 = 0x1b873593; var c2 = 0x1b873593;
@ -68,16 +65,16 @@ function ClassSpec(b) {
h1 ^= h1 >> 16; h1 ^= h1 >> 16;
return h1 % (this.data.length * 8); return h1 % (this.data.length * 8);
}; };
Bloom.prototype.insert = function(data) { Bloom.prototype.insert = function(data) {
for (var i = 0; i < this.hashFuncs; i++) { for (var i = 0; i < this.hashFuncs; i++) {
var index = this.hash(i, data); var index = this.hash(i, data);
this.data[index >> 3] |= bit_mask[7 & index]; 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++) { for (var i = 0; i < this.hashFuncs; i++) {
var index = this.hash(i, data); var index = this.hash(i, data);
if (!(this.data[index >> 3] & bit_mask[7 & index])) if (!(this.data[index >> 3] & bit_mask[7 & index]))
@ -85,32 +82,30 @@ function ClassSpec(b) {
} }
return true; return true;
}; };
Bloom.prototype.sizeOk = function() { Bloom.prototype.sizeOk = function() {
return this.data.length <= MAX_BLOOM_FILTER_SIZE && return this.data.length <= MAX_BLOOM_FILTER_SIZE &&
this.hashFuncs <= MAX_HASH_FUNCS; this.hashFuncs <= MAX_HASH_FUNCS;
}; };
function toInt(v) { function toInt(v) {
return ~~v; return ~~v;
} }
function min(a, b) { function min(a, b) {
if (a < b) if (a < b)
return a; return a;
return b; 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)), var filterSize = min(toInt(-1.0 / LN2SQUARED * elements * Math.log(FPRate)),
MAX_BLOOM_FILTER_SIZE * 8) / 8; MAX_BLOOM_FILTER_SIZE * 8) / 8;
this.data[filterSize] = 0; this.data[filterSize] = 0;
this.hashFuncs = min(toInt(this.data.length * 8 / elements * LN2), this.hashFuncs = min(toInt(this.data.length * 8 / elements * LN2),
MAX_HASH_FUNCS); 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 = imports.config || require('./config');
var config = b.config || require('./config'); var log = imports.log || require('./util/log');
var log = b.log || require('./util/log'); var network = imports.network || require('./networks')[config.network];
var network = b.network || require('./networks')[config.network];
var MAX_RECEIVE_BUFFER = 10000000; var MAX_RECEIVE_BUFFER = 10000000;
var PROTOCOL_VERSION = 70000; var PROTOCOL_VERSION = 70000;
var Binary = b.Binary || require('binary'); var Binary = imports.Binary || require('binary');
var Put = b.Put || require('bufferput'); var Put = imports.Put || require('bufferput');
var Buffers = b.Buffers || require('buffers'); var Buffers = imports.Buffers || require('buffers');
require('./Buffers.monkey').patch(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 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); Connection.super(this, arguments);
this.socket = socket; this.socket = socket;
this.peer = peer; this.peer = peer;
@ -52,10 +51,10 @@ function spec(b) {
} }
this.setupHandlers(); 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('connect', this.handleConnect.bind(this));
this.socket.addListener('error', this.handleError.bind(this)); this.socket.addListener('error', this.handleError.bind(this));
this.socket.addListener('end', this.handleDisconnect.bind(this)); this.socket.addListener('end', this.handleDisconnect.bind(this));
@ -68,9 +67,9 @@ function spec(b) {
(data.length > dumpLen ? '...' : '')); (data.length > dumpLen ? '...' : ''));
}).bind(this)); }).bind(this));
this.socket.addListener('data', this.handleData.bind(this)); this.socket.addListener('data', this.handleData.bind(this));
}; };
Connection.prototype.handleConnect = function () { Connection.prototype.handleConnect = function () {
if (!this.inbound) { if (!this.inbound) {
this.sendVersion(); this.sendVersion();
} }
@ -79,9 +78,9 @@ function spec(b) {
socket: this.socket, socket: this.socket,
peer: this.peer peer: this.peer
}); });
}; };
Connection.prototype.handleError = function(err) { Connection.prototype.handleError = function(err) {
if (err.errno == 110 || err.errno == 'ETIMEDOUT') { if (err.errno == 110 || err.errno == 'ETIMEDOUT') {
log.info('connection timed out for '+this.peer); log.info('connection timed out for '+this.peer);
} else if (err.errno == 111 || err.errno == 'ECONNREFUSED') { } else if (err.errno == 111 || err.errno == 'ECONNREFUSED') {
@ -95,17 +94,17 @@ function spec(b) {
peer: this.peer, peer: this.peer,
err: err err: err
}); });
}; };
Connection.prototype.handleDisconnect = function () { Connection.prototype.handleDisconnect = function () {
this.emit('disconnect', { this.emit('disconnect', {
conn: this, conn: this,
socket: this.socket, socket: this.socket,
peer: this.peer peer: this.peer
}); });
}; };
Connection.prototype.handleMessage = function(message) { Connection.prototype.handleMessage = function(message) {
if (!message) { if (!message) {
// Parser was unable to make sense of the message, drop it // Parser was unable to make sense of the message, drop it
return; return;
@ -163,13 +162,13 @@ function spec(b) {
peer: this.peer, peer: this.peer,
message: message message: message
}); });
}; };
Connection.prototype.sendPong = function (nonce) { Connection.prototype.sendPong = function (nonce) {
this.sendMessage('pong', nonce); this.sendMessage('pong', nonce);
}; };
Connection.prototype.sendVersion = function () { Connection.prototype.sendVersion = function () {
var subversion = '/BitcoinX:0.1/'; var subversion = '/BitcoinX:0.1/';
var put = new Put(); var put = new Put();
@ -184,9 +183,9 @@ function spec(b) {
put.word32le(0); put.word32le(0);
this.sendMessage('version', put.buffer()); this.sendMessage('version', put.buffer());
}; };
Connection.prototype.sendGetBlocks = function (starts, stop, wantHeaders) { Connection.prototype.sendGetBlocks = function (starts, stop, wantHeaders) {
var put = new Put(); var put = new Put();
put.word32le(this.sendVer); put.word32le(this.sendVer);
@ -210,13 +209,13 @@ function spec(b) {
if (wantHeaders) if (wantHeaders)
command = 'getheaders'; command = 'getheaders';
this.sendMessage(command, put.buffer()); this.sendMessage(command, put.buffer());
}; };
Connection.prototype.sendGetHeaders = function(starts, stop) { Connection.prototype.sendGetHeaders = function(starts, stop) {
this.sendGetBlocks(starts, stop, true); this.sendGetBlocks(starts, stop, true);
}; };
Connection.prototype.sendGetData = function (invs) { Connection.prototype.sendGetData = function (invs) {
var put = new Put(); var put = new Put();
put.varint(invs.length); put.varint(invs.length);
for (var i = 0; i < invs.length; i++) { for (var i = 0; i < invs.length; i++) {
@ -224,14 +223,14 @@ function spec(b) {
put.put(invs[i].hash); put.put(invs[i].hash);
} }
this.sendMessage('getdata', put.buffer()); this.sendMessage('getdata', put.buffer());
}; };
Connection.prototype.sendGetAddr = function (invs) { Connection.prototype.sendGetAddr = function (invs) {
var put = new Put(); var put = new Put();
this.sendMessage('getaddr', put.buffer()); this.sendMessage('getaddr', put.buffer());
}; };
Connection.prototype.sendInv = function(data) { Connection.prototype.sendInv = function(data) {
if(!Array.isArray(data)) data = [data]; if(!Array.isArray(data)) data = [data];
var put = new Put(); var put = new Put();
put.varint(data.length); put.varint(data.length);
@ -246,9 +245,9 @@ function spec(b) {
put.put(value.getHash()); put.put(value.getHash());
}); });
this.sendMessage('inv', put.buffer()); this.sendMessage('inv', put.buffer());
}; };
Connection.prototype.sendHeaders = function (headers) { Connection.prototype.sendHeaders = function (headers) {
var put = new Put(); var put = new Put();
put.varint(headers.length); put.varint(headers.length);
headers.forEach(function (header) { headers.forEach(function (header) {
@ -258,13 +257,13 @@ function spec(b) {
put.word8(0); put.word8(0);
}); });
this.sendMessage('headers', put.buffer()); this.sendMessage('headers', put.buffer());
}; };
Connection.prototype.sendTx = function (tx) { Connection.prototype.sendTx = function (tx) {
this.sendMessage('tx', tx.serialize()); this.sendMessage('tx', tx.serialize());
}; };
Connection.prototype.sendBlock = function (block, txs) { Connection.prototype.sendBlock = function (block, txs) {
var put = new Put(); var put = new Put();
// Block header // Block header
@ -277,9 +276,9 @@ function spec(b) {
}); });
this.sendMessage('block', put.buffer()); this.sendMessage('block', put.buffer());
}; };
Connection.prototype.sendMessage = function (command, payload) { Connection.prototype.sendMessage = function (command, payload) {
try { try {
var magic = network.magic; var magic = network.magic;
var commandBuf = new Buffer(command, 'ascii'); var commandBuf = new Buffer(command, 'ascii');
@ -313,9 +312,9 @@ function spec(b) {
log.err("Error while sending message to peer "+this.peer+": "+ log.err("Error while sending message to peer "+this.peer+": "+
(err.stack ? err.stack : err.toString())); (err.stack ? err.stack : err.toString()));
} }
}; };
Connection.prototype.handleData = function (data) { Connection.prototype.handleData = function (data) {
this.buffers.push(data); this.buffers.push(data);
if (this.buffers.length > MAX_RECEIVE_BUFFER) { if (this.buffers.length > MAX_RECEIVE_BUFFER) {
@ -326,9 +325,9 @@ function spec(b) {
} }
this.processData(); 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 there are less than 20 bytes there can't be a message yet.
if (this.buffers.length < 20) return; if (this.buffers.length < 20) return;
@ -402,9 +401,9 @@ function spec(b) {
this.buffers.skip(endPos); this.buffers.skip(endPos);
this.processData(); this.processData();
}; };
Connection.prototype.parseMessage = function (command, payload) { Connection.prototype.parseMessage = function (command, payload) {
var parser = new Parser(payload); var parser = new Parser(payload);
var data = { var data = {
@ -444,8 +443,8 @@ function spec(b) {
data.headers = []; data.headers = [];
for (i = 0; i < data.count; i++) { for (i = 0; i < data.count; i++) {
var header = new Block(); var header = new Block();
header.parse(parser); header.parse(parser);
data.headers.push(header); data.headers.push(header);
} }
break; break;
@ -540,8 +539,6 @@ function spec(b) {
} }
return data; return data;
};
return Connection;
}; };
module.defineClass(spec);
module.exports = require('soop')(Connection);

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

35
Peer.js
View File

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

View File

@ -1,20 +1,19 @@
require('classtool');
function spec(b) { var imports = require('soop').imports();
var config = b.config || require('./config'); var config = imports.config || require('./config');
var log = b.log || require('./util/log'); var log = imports.log || require('./util/log');
var network = b.network || require('./networks')[config.network]; var network = imports.network || require('./networks')[config.network];
var Connection = b.Connection || require('./Connection').createClass( var Connection = imports.Connection ||
{config: config, network: network}); require('soop').load('./Connection', {config: config, network: network});
var Peer = b.Peer || require('./Peer').class();
var noop = function() {};
GetAdjustedTime = b.GetAdjustedTime || function () { var Peer = imports.Peer || require('./Peer');
GetAdjustedTime = imports.GetAdjustedTime || function () {
// TODO: Implement actual adjustment // TODO: Implement actual adjustment
return Math.floor(new Date().getTime() / 1000); return Math.floor(new Date().getTime() / 1000);
}; };
function PeerManager() { function PeerManager() {
this.active = false; this.active = false;
this.timer = null; this.timer = null;
@ -27,19 +26,19 @@ function spec(b) {
this.interval = 5000; this.interval = 5000;
this.minConnections = 8; this.minConnections = 8;
this.minKnownPeers = 10; 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; this.active = true;
if(!this.timer) { if(!this.timer) {
this.timer = setInterval(this.checkStatus.bind(this), this.interval); this.timer = setInterval(this.checkStatus.bind(this), this.interval);
} }
}; };
PeerManager.prototype.stop = function() { PeerManager.prototype.stop = function() {
this.active = false; this.active = false;
if(this.timer) { if(this.timer) {
clearInterval(this.timer); clearInterval(this.timer);
@ -48,9 +47,9 @@ function spec(b) {
for(var i=0; i<this.connections.length; i++) { for(var i=0; i<this.connections.length; i++) {
this.connections[i].socket.end(); this.connections[i].socket.end();
}; };
}; };
PeerManager.prototype.addPeer = function(peer, port) { PeerManager.prototype.addPeer = function(peer, port) {
if(peer instanceof Peer) { if(peer instanceof Peer) {
this.peers.push(peer); this.peers.push(peer);
} else if ("string" == typeof peer) { } else if ("string" == typeof peer) {
@ -60,9 +59,9 @@ function spec(b) {
{val: peer}); {val: peer});
throw 'Node.addPeer(): Invalid value provided for 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 // Make sure we are connected to all forcePeers
if(this.peers.length) { if(this.peers.length) {
var peerIndex = {}; var peerIndex = {};
@ -82,9 +81,9 @@ function spec(b) {
this.connectTo(peerIndex[i]); this.connectTo(peerIndex[i]);
}.bind(this)); }.bind(this));
} }
}; };
PeerManager.prototype.connectTo = function(peer) { PeerManager.prototype.connectTo = function(peer) {
log.info('connecting to '+peer); log.info('connecting to '+peer);
try { try {
return this.addConnection(peer.createConnection(), peer); return this.addConnection(peer.createConnection(), peer);
@ -92,9 +91,9 @@ function spec(b) {
log.err('creating connection',e); log.err('creating connection',e);
return null; return null;
} }
}; };
PeerManager.prototype.addConnection = function(socketConn, peer) { PeerManager.prototype.addConnection = function(socketConn, peer) {
var conn = new Connection(socketConn, peer); var conn = new Connection(socketConn, peer);
this.connections.push(conn); this.connections.push(conn);
this.emit('connection', conn); this.emit('connection', conn);
@ -107,9 +106,9 @@ function spec(b) {
conn.addListener('disconnect', this.handleDisconnect.bind(this)); conn.addListener('disconnect', this.handleDisconnect.bind(this));
return conn; return conn;
}; };
PeerManager.prototype.handleVersion = function(e) { PeerManager.prototype.handleVersion = function(e) {
if (!e.conn.inbound) { if (!e.conn.inbound) {
// TODO: Advertise our address (if listening) // TODO: Advertise our address (if listening)
} }
@ -119,9 +118,9 @@ function spec(b) {
e.conn.sendGetAddr(); e.conn.sendGetAddr();
e.conn.getaddr = true; 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); log.info('connected to '+e.conn.peer.host+':'+e.conn.peer.port);
this.emit('connect', { this.emit('connect', {
pm: this, pm: this,
@ -134,9 +133,9 @@ function spec(b) {
this.emit('netConnected'); this.emit('netConnected');
this.isConnected = true; this.isConnected = true;
} }
}; };
PeerManager.prototype.handleAddr = function (e) { PeerManager.prototype.handleAddr = function (e) {
if(!this.peerDiscovery) return; if(!this.peerDiscovery) return;
var now = GetAdjustedTime(); var now = GetAdjustedTime();
@ -160,18 +159,18 @@ function spec(b) {
if (e.message.addrs.length < 1000 ) { if (e.message.addrs.length < 1000 ) {
e.conn.getaddr = false; e.conn.getaddr = false;
} }
}; };
PeerManager.prototype.handleGetAddr = function(e) { PeerManager.prototype.handleGetAddr = function(e) {
// TODO: Reply with addr message. // 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); log.err('unkown error with peer '+e.peer+' (disconnecting): '+e.err);
this.handleDisconnect.apply(this, [].slice.call(arguments)); this.handleDisconnect.apply(this, [].slice.call(arguments));
}; };
PeerManager.prototype.handleDisconnect = function(e) { PeerManager.prototype.handleDisconnect = function(e) {
log.info('disconnected from peer '+e.peer); log.info('disconnected from peer '+e.peer);
var i = this.connections.indexOf(e.conn); var i = this.connections.indexOf(e.conn);
if(i != -1) this.connections.splice(i, 1); if(i != -1) this.connections.splice(i, 1);
@ -180,9 +179,9 @@ function spec(b) {
this.emit('netDisconnected'); this.emit('netDisconnected');
this.isConnected = false; this.isConnected = false;
} }
}; };
PeerManager.prototype.getActiveConnection = function () { PeerManager.prototype.getActiveConnection = function () {
var activeConnections = this.connections.filter(function (conn) { var activeConnections = this.connections.filter(function (conn) {
return conn.active; return conn.active;
}); });
@ -204,12 +203,10 @@ function spec(b) {
} else { } else {
return null; 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 parent = imports.parent || require('./util/VersionedData');
var superclass = b.superclass || require('./util/VersionedData').class();
//compressed is true if public key is compressed; false otherwise //compressed is true if public key is compressed; false otherwise
function PrivateKey(version, buf, compressed) { function PrivateKey(version, buf, compressed) {
PrivateKey.super(this, arguments); PrivateKey.super(this, arguments);
if (compressed !== undefined) if (compressed !== undefined)
this.compressed(compressed); this.compressed(compressed);
}; };
PrivateKey.superclass = superclass; PrivateKey.parent = parent;
superclass.applyEncodingsTo(PrivateKey); parent.applyEncodingsTo(PrivateKey);
PrivateKey.prototype.validate = function() { PrivateKey.prototype.validate = function() {
this.doAsBinary(function() { this.doAsBinary(function() {
PrivateKey.super(this, 'validate', arguments); PrivateKey.super(this, 'validate', arguments);
if (this.data.length < 32 || (this.data.length > 1+32 && !this.compressed()) || (this.data.length==1+32+1 && this.data[1+32+1-1]!=1) || this.data.length>1+32+1) if (this.data.length < 32 || (this.data.length > 1+32 && !this.compressed()) || (this.data.length==1+32+1 && this.data[1+32+1-1]!=1) || this.data.length>1+32+1)
throw new Error('invalid data length'); throw new Error('invalid data length');
}); });
}; };
// get or set the payload data (as a Buffer object) // get or set the payload data (as a Buffer object)
// overloaded from VersionedData // overloaded from VersionedData
PrivateKey.prototype.payload = function(data) { PrivateKey.prototype.payload = function(data) {
if(data) { if(data) {
this.doAsBinary(function() {data.copy(this.data,1);}); this.doAsBinary(function() {data.copy(this.data,1);});
return data; return data;
@ -33,10 +32,10 @@ function ClassSpec(b) {
return buf.slice(1,1+32); return buf.slice(1,1+32);
else if (buf.length==1+32) else if (buf.length==1+32)
return buf.slice(1); return buf.slice(1);
}; };
// get or set whether the corresponding public key is compressed // get or set whether the corresponding public key is compressed
PrivateKey.prototype.compressed = function(compressed) { PrivateKey.prototype.compressed = function(compressed) {
if (compressed !== undefined) { if (compressed !== undefined) {
this.doAsBinary(function(){ this.doAsBinary(function(){
var len=1+32+1; var len=1+32+1;
@ -60,8 +59,6 @@ function ClassSpec(b) {
else else
throw new Error('invalid private key'); throw new Error('invalid private key');
} }
};
return PrivateKey;
}; };
module.defineClass(ClassSpec);
module.exports = require('soop')(PrivateKey);

View File

@ -1,14 +1,13 @@
// RpcClient.js // RpcClient.js
// MIT/X11-like license. See LICENSE.txt. // MIT/X11-like license. See LICENSE.txt.
// Copyright 2013 BitPay, Inc. // 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) { function RpcClient(opts) {
var http = b.http || require('http');
var https = b.https || require('https');
var log = b.log || require('./util/log');
function RpcClient(opts) {
opts = opts || {}; opts = opts || {};
this.host = opts.host || '127.0.0.1'; this.host = opts.host || '127.0.0.1';
this.port = opts.port || 8332; this.port = opts.port || 8332;
@ -17,16 +16,16 @@ function ClassSpec(b) {
this.protocol = (opts.protocol == 'http') ? http : https; this.protocol = (opts.protocol == 'http') ? http : https;
this.batchedCalls = null; this.batchedCalls = null;
this.disableAgent = opts.disableAgent || false; this.disableAgent = opts.disableAgent || false;
} }
RpcClient.prototype.batch = function(batchCallback, resultCallback) { RpcClient.prototype.batch = function(batchCallback, resultCallback) {
this.batchedCalls = []; this.batchedCalls = [];
batchCallback(); batchCallback();
rpc.call(this, this.batchedCalls, resultCallback); rpc.call(this, this.batchedCalls, resultCallback);
this.batchedCalls = null; this.batchedCalls = null;
} }
var callspec = { var callspec = {
addMultiSigAddress: '', addMultiSigAddress: '',
addNode: '', addNode: '',
backupWallet: '', backupWallet: '',
@ -93,13 +92,13 @@ function ClassSpec(b) {
walletLock: '', walletLock: '',
walletPassPhrase: 'string int', walletPassPhrase: 'string int',
walletPassphraseChange: '', walletPassphraseChange: '',
}; };
var slice = function(arr, start, end) { var slice = function(arr, start, end) {
return Array.prototype.slice.call(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) { function createRPCMethod(methodName, argMap) {
return function() { return function() {
var limit = arguments.length - 1; var limit = arguments.length - 1;
@ -137,9 +136,9 @@ function ClassSpec(b) {
constructor.prototype[methodName] = constructor.prototype[k]; constructor.prototype[methodName] = constructor.prototype[k];
} }
} }
} }
function rpc(request, callback) { function rpc(request, callback) {
var self = this; var self = this;
var request; var request;
request = JSON.stringify(request); request = JSON.stringify(request);
@ -201,10 +200,9 @@ function ClassSpec(b) {
req.setHeader('Authorization', 'Basic ' + auth); req.setHeader('Authorization', 'Basic ' + auth);
req.write(request); req.write(request);
req.end(); 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) { function SIN(type, payload) {
var superclass = b.superclass || require('./util/VersionedData').class();
function SIN(type, payload) {
if (typeof type != 'number') { if (typeof type != 'number') {
SIN.super(this, arguments); SIN.super(this, arguments);
return; return;
@ -14,47 +11,45 @@ function ClassSpec(b) {
this.prefix(0x0F); // SIN magic number, in numberspace this.prefix(0x0F); // SIN magic number, in numberspace
this.type(type); this.type(type);
this.payload(payload); this.payload(payload);
}; };
SIN.superclass = superclass; SIN.parent = parent;
superclass.applyEncodingsTo(SIN); parent.applyEncodingsTo(SIN);
SIN.SIN_PERSIST_MAINNET = 0x01; // associated with sacrifice TX SIN.SIN_PERSIST_MAINNET = 0x01; // associated with sacrifice TX
SIN.SIN_PERSIST_TESTNET = 0x11; // associated with sacrifice TX SIN.SIN_PERSIST_TESTNET = 0x11; // associated with sacrifice TX
SIN.SIN_EPHEM = 0x02; // generate off-net at any time SIN.SIN_EPHEM = 0x02; // generate off-net at any time
// get or set the prefix data (the first byte of the address) // get or set the prefix data (the first byte of the address)
SIN.prototype.prefix = function(num) { SIN.prototype.prefix = function(num) {
if(num || (num === 0)) { if(num || (num === 0)) {
this.doAsBinary(function() {this.data.writeUInt8(num, 0);}); this.doAsBinary(function() {this.data.writeUInt8(num, 0);});
return num; return num;
} }
return this.as('binary').readUInt8(0); return this.as('binary').readUInt8(0);
}; };
// get or set the SIN-type data (the second byte of the address) // get or set the SIN-type data (the second byte of the address)
SIN.prototype.type = function(num) { SIN.prototype.type = function(num) {
if(num || (num === 0)) { if(num || (num === 0)) {
this.doAsBinary(function() {this.data.writeUInt8(num, 1);}); this.doAsBinary(function() {this.data.writeUInt8(num, 1);});
return num; return num;
} }
return this.as('binary').readUInt8(1); return this.as('binary').readUInt8(1);
}; };
// get or set the payload data (as a Buffer object) // get or set the payload data (as a Buffer object)
SIN.prototype.payload = function(data) { SIN.prototype.payload = function(data) {
if(data) { if(data) {
this.doAsBinary(function() {data.copy(this.data, 2);}); this.doAsBinary(function() {data.copy(this.data, 2);});
return data; return data;
} }
return this.as('binary').slice(1); return this.as('binary').slice(1);
}; };
SIN.prototype.validate = function() { SIN.prototype.validate = function() {
this.doAsBinary(function() { this.doAsBinary(function() {
SIN.super(this, 'validate', arguments); SIN.super(this, 'validate', arguments);
if (this.data.length != 22) throw new Error('invalid data length'); 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) { function SINKey(cfg) {
var coinUtil = require('./util/util');
var timeUtil = require('./util/time');
var KeyModule = require('./Key');
var SIN = require('./SIN').class();
function SINKey(cfg) {
if (typeof cfg != 'object') if (typeof cfg != 'object')
cfg = {}; cfg = {};
this.created = cfg.created; this.created = cfg.created;
this.privKey = cfg.privKey; this.privKey = cfg.privKey;
}; };
SINKey.prototype.generate = function() { SINKey.prototype.generate = function() {
this.privKey = KeyModule.Key.generateSync(); this.privKey = KeyModule.Key.generateSync();
this.created = timeUtil.curtime(); this.created = timeUtil.curtime();
}; };
SINKey.prototype.pubkeyHash = function() { SINKey.prototype.pubkeyHash = function() {
return coinUtil.sha256ripe160(this.privKey.public); return coinUtil.sha256ripe160(this.privKey.public);
}; };
SINKey.prototype.storeObj = function() { SINKey.prototype.storeObj = function() {
var pubKey = this.privKey.public.toString('hex'); var pubKey = this.privKey.public.toString('hex');
var pubKeyHash = this.pubkeyHash(); var pubKeyHash = this.pubkeyHash();
var sin = new SIN(SIN.SIN_EPHEM, pubKeyHash); var sin = new SIN(SIN.SIN_EPHEM, pubKeyHash);
@ -35,9 +32,6 @@ function ClassSpec(b) {
}; };
return obj; return obj;
};
return SINKey;
}; };
module.defineClass(ClassSpec);
module.exports = require('soop')(SINKey);

290
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) { // Make opcodes available as pseudo-constants
var config = b.config || require('./config'); for (var i in Opcode.map) {
var log = b.log || require('./util/log'); eval(i + ' = ' + Opcode.map[i] + ';');
}
var Opcode = b.Opcode || require('./Opcode').class(); var util = imports.util || require('./util/util');
var buffertools = b.buffertools || require('buffertools'); var Parser = imports.Parser || require('./util/BinaryParser');
var Put = imports.Put || require('bufferput');
// Make opcodes available as pseudo-constants var TX_UNKNOWN = 0;
for (var i in Opcode.map) { var TX_PUBKEY = 1;
eval(i + " = " + Opcode.map[i] + ";"); var TX_PUBKEYHASH = 2;
} var TX_MULTISIG = 3;
var TX_SCRIPTHASH = 4;
var util = b.util || require('./util/util'); var TX_TYPES = [
var Parser = b.Parser || require('./util/BinaryParser').class();
var Put = b.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_TYPES = [
'unknown', 'unknown',
'pubkey', 'pubkey',
'pubkeyhash', 'pubkeyhash',
'multisig', 'multisig',
'scripthash' 'scripthash'
]; ];
function Script(buffer) { function Script(buffer) {
if(buffer) { if(buffer) {
this.buffer = buffer; this.buffer = buffer;
} else { } else {
@ -38,16 +35,16 @@ function spec(b) {
} }
this.chunks = []; this.chunks = [];
this.parse(); this.parse();
}; };
this.class = Script; this.class = Script;
Script.TX_UNKNOWN=TX_UNKNOWN; Script.TX_UNKNOWN=TX_UNKNOWN;
Script.TX_PUBKEY=TX_PUBKEY; Script.TX_PUBKEY=TX_PUBKEY;
Script.TX_PUBKEYHASH=TX_PUBKEYHASH; Script.TX_PUBKEYHASH=TX_PUBKEYHASH;
Script.TX_MULTISIG=TX_MULTISIG; Script.TX_MULTISIG=TX_MULTISIG;
Script.TX_SCRIPTHASH=TX_SCRIPTHASH; Script.TX_SCRIPTHASH=TX_SCRIPTHASH;
Script.prototype.parse = function () { Script.prototype.parse = function () {
this.chunks = []; this.chunks = [];
var parser = new Parser(this.buffer); var parser = new Parser(this.buffer);
@ -71,35 +68,35 @@ function spec(b) {
this.chunks.push(opcode); this.chunks.push(opcode);
} }
} }
}; };
Script.prototype.isPushOnly = function () Script.prototype.isPushOnly = function ()
{ {
for (var i = 0; i < this.chunks.length; i++) for (var i = 0; i < this.chunks.length; i++)
if (!Buffer.isBuffer(this.chunks[i])) if (!Buffer.isBuffer(this.chunks[i]))
return false; return false;
return true; return true;
}; };
Script.prototype.isP2SH = function () Script.prototype.isP2SH = function ()
{ {
return (this.chunks.length == 3 && return (this.chunks.length == 3 &&
this.chunks[0] == OP_HASH160 && this.chunks[0] == OP_HASH160 &&
Buffer.isBuffer(this.chunks[1]) && Buffer.isBuffer(this.chunks[1]) &&
this.chunks[1].length == 20 && this.chunks[1].length == 20 &&
this.chunks[2] == OP_EQUAL); this.chunks[2] == OP_EQUAL);
}; };
Script.prototype.isPubkey = function () Script.prototype.isPubkey = function ()
{ {
return (this.chunks.length == 2 && return (this.chunks.length == 2 &&
Buffer.isBuffer(this.chunks[0]) && Buffer.isBuffer(this.chunks[0]) &&
this.chunks[1] == OP_CHECKSIG); this.chunks[1] == OP_CHECKSIG);
}; };
Script.prototype.isPubkeyHash = function () Script.prototype.isPubkeyHash = function ()
{ {
return (this.chunks.length == 5 && return (this.chunks.length == 5 &&
this.chunks[0] == OP_DUP && this.chunks[0] == OP_DUP &&
this.chunks[1] == OP_HASH160 && this.chunks[1] == OP_HASH160 &&
@ -107,24 +104,24 @@ function spec(b) {
this.chunks[2].length == 20 && this.chunks[2].length == 20 &&
this.chunks[3] == OP_EQUALVERIFY && this.chunks[3] == OP_EQUALVERIFY &&
this.chunks[4] == OP_CHECKSIG); this.chunks[4] == OP_CHECKSIG);
}; };
function isSmallIntOp(opcode) function isSmallIntOp(opcode)
{ {
return ((opcode == OP_0) || return ((opcode == OP_0) ||
((opcode >= OP_1) && (opcode <= OP_16))); ((opcode >= OP_1) && (opcode <= OP_16)));
}; };
Script.prototype.isMultiSig = function () Script.prototype.isMultiSig = function ()
{ {
return (this.chunks.length > 3 && return (this.chunks.length > 3 &&
isSmallIntOp(this.chunks[0]) && isSmallIntOp(this.chunks[0]) &&
isSmallIntOp(this.chunks[this.chunks.length-2]) && isSmallIntOp(this.chunks[this.chunks.length-2]) &&
this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG); this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG);
}; };
Script.prototype.finishedMultiSig = function() Script.prototype.finishedMultiSig = function()
{ {
var nsigs = 0; var nsigs = 0;
for (var i = 0; i < this.chunks.length-1; i++) for (var i = 0; i < this.chunks.length-1; i++)
if (this.chunks[i] !== 0) if (this.chunks[i] !== 0)
@ -138,10 +135,10 @@ function spec(b) {
return true; return true;
else else
return false; return false;
} }
Script.prototype.removePlaceHolders = function() Script.prototype.removePlaceHolders = function()
{ {
var chunks = []; var chunks = [];
for (var i in this.chunks) for (var i in this.chunks)
{ {
@ -154,10 +151,10 @@ function spec(b) {
this.chunks = chunks; this.chunks = chunks;
this.updateBuffer(); this.updateBuffer();
return this; return this;
} }
Script.prototype.prependOp0 = function() Script.prototype.prependOp0 = function()
{ {
var chunks = [0]; var chunks = [0];
for (i in this.chunks) { for (i in this.chunks) {
if (this.chunks.hasOwnProperty(i)) { if (this.chunks.hasOwnProperty(i)) {
@ -167,74 +164,74 @@ function spec(b) {
this.chunks = chunks; this.chunks = chunks;
this.updateBuffer(); this.updateBuffer();
return this; return this;
} }
// is this a script form we know? // is this a script form we know?
Script.prototype.classify = function () Script.prototype.classify = function ()
{ {
if (this.isPubkeyHash()) if (this.isPubkeyHash())
return TX_PUBKEYHASH; return TX_PUBKEYHASH;
if (this.isP2SH()) if (this.isP2SH())
return TX_SCRIPTHASH; return TX_SCRIPTHASH;
if (this.isMultiSig()) if (this.isMultiSig())
return TX_MULTISIG; return TX_MULTISIG;
if (this.isPubkey()) if (this.isPubkey())
return TX_PUBKEY; return TX_PUBKEY;
return TX_UNKNOWN; return TX_UNKNOWN;
}; };
// extract useful data items from known scripts // extract useful data items from known scripts
Script.prototype.capture = function () Script.prototype.capture = function ()
{ {
var txType = this.classify(); var txType = this.classify();
var res = []; var res = [];
switch (txType) { switch (txType) {
case TX_PUBKEY: case TX_PUBKEY:
res.push(this.chunks[0]); res.push(this.chunks[0]);
break; break;
case TX_PUBKEYHASH: case TX_PUBKEYHASH:
res.push(this.chunks[2]); res.push(this.chunks[2]);
break; break;
case TX_MULTISIG: case TX_MULTISIG:
for (var i = 1; i < (this.chunks.length - 2); i++) for (var i = 1; i < (this.chunks.length - 2); i++)
res.push(this.chunks[i]); res.push(this.chunks[i]);
break; break;
case TX_SCRIPTHASH: case TX_SCRIPTHASH:
res.push(this.chunks[1]); res.push(this.chunks[1]);
break; break;
case TX_UNKNOWN: case TX_UNKNOWN:
default: default:
// do nothing // do nothing
break; break;
} }
return res; return res;
}; };
// return first extracted data item from script // return first extracted data item from script
Script.prototype.captureOne = function () Script.prototype.captureOne = function ()
{ {
var arr = this.capture(); var arr = this.capture();
return arr[0]; return arr[0];
}; };
Script.prototype.getOutType = function () Script.prototype.getOutType = function ()
{ {
var txType = this.classify(); var txType = this.classify();
switch (txType) { switch (txType) {
case TX_PUBKEY: return 'Pubkey'; case TX_PUBKEY: return 'Pubkey';
case TX_PUBKEYHASH: return 'Address'; case TX_PUBKEYHASH: return 'Address';
default: return 'Strange'; default: return 'Strange';
} }
}; };
Script.prototype.getRawOutType = function() { Script.prototype.getRawOutType = function() {
return TX_TYPES[this.classify()]; return TX_TYPES[this.classify()];
}; };
Script.prototype.simpleOutHash = function () Script.prototype.simpleOutHash = function ()
{ {
switch (this.getOutType()) { switch (this.getOutType()) {
case 'Address': case 'Address':
return this.chunks[2]; return this.chunks[2];
@ -245,10 +242,10 @@ function spec(b) {
log.debug("Strange script was: " + this.toString()); log.debug("Strange script was: " + this.toString());
return null; return null;
} }
}; };
Script.prototype.getInType = function () Script.prototype.getInType = function ()
{ {
if (this.chunks.length == 1) { if (this.chunks.length == 1) {
// Direct IP to IP transactions only have the public key in their scriptSig. // Direct IP to IP transactions only have the public key in their scriptSig.
return 'Pubkey'; return 'Pubkey';
@ -259,10 +256,10 @@ function spec(b) {
} else { } else {
return 'Strange'; return 'Strange';
} }
}; };
Script.prototype.simpleInPubKey = function () Script.prototype.simpleInPubKey = function ()
{ {
switch (this.getInType()) { switch (this.getInType()) {
case 'Address': case 'Address':
return this.chunks[1]; return this.chunks[1];
@ -273,15 +270,15 @@ function spec(b) {
log.debug("Strange script was: " + this.toString()); log.debug("Strange script was: " + this.toString());
return null; return null;
} }
}; };
Script.prototype.getBuffer = function () Script.prototype.getBuffer = function ()
{ {
return this.buffer; return this.buffer;
}; };
Script.prototype.getStringContent = function (truncate, maxEl) Script.prototype.getStringContent = function (truncate, maxEl)
{ {
if (truncate === null) { if (truncate === null) {
truncate = true; truncate = true;
} }
@ -310,19 +307,19 @@ function spec(b) {
} }
} }
return script; return script;
}; };
Script.prototype.toString = function (truncate, maxEl) Script.prototype.toString = function (truncate, maxEl)
{ {
var script = "<Script "; var script = "<Script ";
script += this.getStringContent(truncate, maxEl); script += this.getStringContent(truncate, maxEl);
script += ">"; script += ">";
return script; return script;
}; };
Script.prototype.writeOp = function (opcode) Script.prototype.writeOp = function (opcode)
{ {
var buf = Buffer(this.buffer.length + 1); var buf = Buffer(this.buffer.length + 1);
this.buffer.copy(buf); this.buffer.copy(buf);
buf.writeUInt8(opcode, this.buffer.length); buf.writeUInt8(opcode, this.buffer.length);
@ -330,10 +327,10 @@ function spec(b) {
this.buffer = buf; this.buffer = buf;
this.chunks.push(opcode); this.chunks.push(opcode);
}; };
Script.prototype.writeN = function (n) Script.prototype.writeN = function (n)
{ {
if (n < 0 || n > 16) if (n < 0 || n > 16)
throw new Error("writeN: out of range value " + n); throw new Error("writeN: out of range value " + n);
@ -341,10 +338,10 @@ function spec(b) {
this.writeOp(OP_0); this.writeOp(OP_0);
else else
this.writeOp(OP_1 + n - 1); this.writeOp(OP_1 + n - 1);
}; };
function prefixSize(data_length) function prefixSize(data_length)
{ {
if (data_length < OP_PUSHDATA1) { if (data_length < OP_PUSHDATA1) {
return 1; return 1;
} else if (data_length <= 0xff) { } else if (data_length <= 0xff) {
@ -354,9 +351,9 @@ function spec(b) {
} else { } else {
return 1 + 4; return 1 + 4;
} }
}; };
function encodeLen(data_length) { function encodeLen(data_length) {
var buf = undefined; var buf = undefined;
if (data_length < OP_PUSHDATA1) { if (data_length < OP_PUSHDATA1) {
buf = new Buffer(1); buf = new Buffer(1);
@ -382,22 +379,22 @@ function spec(b) {
} }
return buf; return buf;
}; };
Script.prototype.writeBytes = function (data) Script.prototype.writeBytes = function (data)
{ {
var newSize = this.buffer.length + prefixSize(data.length) + data.length; var newSize = this.buffer.length + prefixSize(data.length) + data.length;
this.buffer = Buffer.concat([this.buffer, encodeLen(data.length), data]); this.buffer = Buffer.concat([this.buffer, encodeLen(data.length), data]);
this.chunks.push(data); this.chunks.push(data);
}; };
Script.prototype.updateBuffer = function () Script.prototype.updateBuffer = function ()
{ {
this.buffer = Script.chunksToBuffer(this.chunks); this.buffer = Script.chunksToBuffer(this.chunks);
}; };
Script.prototype.findAndDelete = function (chunk) Script.prototype.findAndDelete = function (chunk)
{ {
var dirty = false; var dirty = false;
if (Buffer.isBuffer(chunk)) { if (Buffer.isBuffer(chunk)) {
for (var i = 0, l = this.chunks.length; i < l; i++) { for (var i = 0, l = this.chunks.length; i < l; i++) {
@ -420,25 +417,25 @@ function spec(b) {
if (dirty) { if (dirty) {
this.updateBuffer(); this.updateBuffer();
} }
}; };
/** /**
* Creates a simple OP_CHECKSIG with pubkey output script. * Creates a simple OP_CHECKSIG with pubkey output script.
* *
* These are used for coinbase transactions and at some point were used for * These are used for coinbase transactions and at some point were used for
* IP-based transactions as well. * IP-based transactions as well.
*/ */
Script.createPubKeyOut = function (pubkey) { Script.createPubKeyOut = function (pubkey) {
var script = new Script(); var script = new Script();
script.writeBytes(pubkey); script.writeBytes(pubkey);
script.writeOp(OP_CHECKSIG); script.writeOp(OP_CHECKSIG);
return script; return script;
}; };
/** /**
* Creates a standard txout script. * Creates a standard txout script.
*/ */
Script.createPubKeyHashOut = function (pubKeyHash) { Script.createPubKeyHashOut = function (pubKeyHash) {
var script = new Script(); var script = new Script();
script.writeOp(OP_DUP); script.writeOp(OP_DUP);
script.writeOp(OP_HASH160); script.writeOp(OP_HASH160);
@ -446,9 +443,9 @@ function spec(b) {
script.writeOp(OP_EQUALVERIFY); script.writeOp(OP_EQUALVERIFY);
script.writeOp(OP_CHECKSIG); script.writeOp(OP_CHECKSIG);
return script; return script;
}; };
Script.createMultisig = function(n_required, keys) { Script.createMultisig = function(n_required, keys) {
var script = new Script(); var script = new Script();
script.writeN(n_required); script.writeN(n_required);
keys.forEach(function(key) { keys.forEach(function(key) {
@ -457,17 +454,17 @@ function spec(b) {
script.writeN(keys.length); script.writeN(keys.length);
script.writeOp(OP_CHECKMULTISIG); script.writeOp(OP_CHECKMULTISIG);
return script; return script;
}; };
Script.createP2SH = function(scriptHash) { Script.createP2SH = function(scriptHash) {
var script = new Script(); var script = new Script();
script.writeOp(OP_HASH160); script.writeOp(OP_HASH160);
script.writeBytes(scriptHash); script.writeBytes(scriptHash);
script.writeOp(OP_EQUAL); script.writeOp(OP_EQUAL);
return script; return script;
}; };
Script.fromTestData = function (testData) { Script.fromTestData = function (testData) {
testData = testData.map(function (chunk) { testData = testData.map(function (chunk) {
if ("string" === typeof chunk) { if ("string" === typeof chunk) {
return new Buffer(chunk, 'hex'); return new Buffer(chunk, 'hex');
@ -480,16 +477,16 @@ function spec(b) {
script.chunks = testData; script.chunks = testData;
script.updateBuffer(); script.updateBuffer();
return script; return script;
}; };
Script.fromChunks = function (chunks) { Script.fromChunks = function (chunks) {
var script = new Script(); var script = new Script();
script.chunks = chunks; script.chunks = chunks;
script.updateBuffer(); script.updateBuffer();
return script; return script;
}; };
Script.chunksToBuffer = function (chunks) { Script.chunksToBuffer = function (chunks) {
var buf = new Put(); var buf = new Put();
for (var i = 0, l = chunks.length; i < l; i++) { for (var i = 0, l = chunks.length; i < l; i++) {
@ -515,9 +512,6 @@ function spec(b) {
} }
} }
return buf.buffer(); return buf.buffer();
};
return Script;
}; };
module.defineClass(spec);
module.exports = require('soop')(Script);

View File

@ -1,29 +1,27 @@
require('classtool'); var imports = require('soop').imports();
function spec(b) { var assert = require('assert');
var assert = require('assert'); var config = imports.config || require('./config');
var config = b.config || require('./config'); var log = imports.log || require('./util/log');
var log = b.log || require('./util/log'); var Opcode = imports.Opcode || require('./Opcode');
var buffertools = imports.buffertools || require('buffertools');
var Opcode = b.Opcode || require('./Opcode').class(); // Make opcodes available as pseudo-constants
var buffertools = b.buffertools || require('buffertools'); for (var i in Opcode.map) {
// Make opcodes available as pseudo-constants
for (var i in Opcode.map) {
eval(i + " = " + Opcode.map[i] + ";"); eval(i + " = " + Opcode.map[i] + ";");
} }
var bignum = b.bignum || require('bignum'); var bignum = imports.bignum || require('bignum');
var Util = b.Util || require('./util/util'); var Util = imports.Util || require('./util/util');
var Script = require('./Script').class(); var Script = require('./Script');
function ScriptInterpreter() { function ScriptInterpreter() {
this.stack = []; this.stack = [];
this.disableUnsafeOpcodes = true; 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) { if ("function" !== typeof callback) {
throw new Error("ScriptInterpreter.eval() requires a callback"); throw new Error("ScriptInterpreter.eval() requires a callback");
} }
@ -726,11 +724,11 @@ function spec(b) {
cb(e); cb(e);
} }
} }
}; };
ScriptInterpreter.prototype.evalTwo = ScriptInterpreter.prototype.evalTwo =
function evalTwo(scriptSig, scriptPubkey, tx, n, hashType, callback) function evalTwo(scriptSig, scriptPubkey, tx, n, hashType, callback)
{ {
var self = this; var self = this;
self.eval(scriptSig, tx, n, hashType, function (e) { self.eval(scriptSig, tx, n, hashType, function (e) {
@ -741,15 +739,15 @@ function spec(b) {
self.eval(scriptPubkey, tx, n, hashType, callback); self.eval(scriptPubkey, tx, n, hashType, callback);
}); });
}; };
/** /**
* Get the top element of the stack. * Get the top element of the stack.
* *
* Using the offset parameter this function can also access lower elements * Using the offset parameter this function can also access lower elements
* from the stack. * from the stack.
*/ */
ScriptInterpreter.prototype.stackTop = function stackTop(offset) { ScriptInterpreter.prototype.stackTop = function stackTop(offset) {
offset = +offset || 1; offset = +offset || 1;
if (offset < 1) offset = 1; if (offset < 1) offset = 1;
@ -758,25 +756,25 @@ function spec(b) {
} }
return this.stack[this.stack.length-offset]; return this.stack[this.stack.length-offset];
}; };
ScriptInterpreter.prototype.stackBack = function stackBack() ScriptInterpreter.prototype.stackBack = function stackBack()
{ {
return this.stack[-1]; return this.stack[-1];
}; };
/** /**
* Pop the top element off the stack and return it. * 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) { if (this.stack.length < 1) {
throw new Error('ScriptInterpreter.stackTop(): Stack underrun'); throw new Error('ScriptInterpreter.stackTop(): Stack underrun');
} }
return this.stack.pop(); 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) { if (this.stack.length < a || this.stack.length < b) {
throw new Error('ScriptInterpreter.stackTop(): Stack underrun'); throw new Error('ScriptInterpreter.stackTop(): Stack underrun');
} }
@ -787,15 +785,15 @@ function spec(b) {
var tmp = s[l - a]; var tmp = s[l - a];
s[l - a] = s[l - b]; s[l - a] = s[l - b];
s[l - b] = tmp; s[l - b] = tmp;
}; };
/** /**
* Returns a version of the stack with only primitive types. * Returns a version of the stack with only primitive types.
* *
* The return value is an array. Any single byte buffer is converted to an * The return value is an array. Any single byte buffer is converted to an
* integer. Any longer Buffer is converted to a hex string. * 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) { return this.stack.map(function (entry) {
if (entry.length > 2) { if (entry.length > 2) {
return buffertools.toHex(entry.slice(0)); return buffertools.toHex(entry.slice(0));
@ -807,9 +805,9 @@ function spec(b) {
return buffertools.toHex(entry.slice(0)); 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++) { for (var i = 0, l = v.length; i < l; i++) {
if (v[i] != 0) { if (v[i] != 0) {
// Negative zero is still zero // Negative zero is still zero
@ -820,11 +818,11 @@ function spec(b) {
} }
} }
return false; return false;
}; };
var castInt = ScriptInterpreter.castInt = function castInt(v) { var castInt = ScriptInterpreter.castInt = function castInt(v) {
return castBigint(v).toNumber(); return castBigint(v).toNumber();
}; };
var castBigint = ScriptInterpreter.castBigint = function castBigint(v) { var castBigint = ScriptInterpreter.castBigint = function castBigint(v) {
if (!v.length) { if (!v.length) {
return bignum(0); return bignum(0);
} }
@ -844,8 +842,8 @@ function spec(b) {
// Positive number // Positive number
return bignum.fromBuffer(w); return bignum.fromBuffer(w);
} }
}; };
var bigintToBuffer = ScriptInterpreter.bigintToBuffer = function bigintToBuffer(v) { var bigintToBuffer = ScriptInterpreter.bigintToBuffer = function bigintToBuffer(v) {
if ("number" === typeof v) { if ("number" === typeof v) {
v = bignum(v); v = bignum(v);
} }
@ -877,19 +875,19 @@ function spec(b) {
return buffertools.reverse(b); return buffertools.reverse(b);
} }
} }
}; };
ScriptInterpreter.prototype.getResult = function getResult() { ScriptInterpreter.prototype.getResult = function getResult() {
if (this.stack.length === 0) { if (this.stack.length === 0) {
throw new Error("Empty stack after script evaluation"); throw new Error("Empty stack after script evaluation");
} }
return castBool(this.stack[this.stack.length-1]); return castBool(this.stack[this.stack.length-1]);
}; };
ScriptInterpreter.verify = ScriptInterpreter.verify =
function verify(scriptSig, scriptPubKey, txTo, n, hashType, callback) function verify(scriptSig, scriptPubKey, txTo, n, hashType, callback)
{ {
if ("function" !== typeof callback) { if ("function" !== typeof callback) {
throw new Error("ScriptInterpreter.verify() requires a callback"); throw new Error("ScriptInterpreter.verify() requires a callback");
} }
@ -916,92 +914,92 @@ function spec(b) {
}); });
return si; return si;
}; };
function verifyStep4(scriptSig, scriptPubKey, txTo, nIn, function verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy) hashType, opts, callback, si, siCopy)
{ {
if (siCopy.stack.length == 0) { if (siCopy.stack.length == 0) {
callback(null, false); callback(null, false);
return; return;
} }
callback(null, castBool(siCopy.stackBack())); callback(null, castBool(siCopy.stackBack()));
} }
function verifyStep3(scriptSig, scriptPubKey, txTo, nIn, function verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy) hashType, opts, callback, si, siCopy)
{ {
if (si.stack.length == 0) { if (si.stack.length == 0) {
callback(null, false); callback(null, false);
return; return;
} }
if (castBool(si.stackBack()) == false) { if (castBool(si.stackBack()) == false) {
callback(null, false); callback(null, false);
return; return;
} }
// if not P2SH, we're done // if not P2SH, we're done
if (!opts.verifyP2SH || !scriptPubKey.isP2SH()) { if (!opts.verifyP2SH || !scriptPubKey.isP2SH()) {
callback(null, true); callback(null, true);
return; return;
} }
if (!scriptSig.isPushOnly()) { if (!scriptSig.isPushOnly()) {
callback(null, false); callback(null, false);
return; return;
} }
assert.notEqual(siCopy.length, 0); assert.notEqual(siCopy.length, 0);
var subscript = new Script(siCopy.stackPop()); var subscript = new Script(siCopy.stackPop());
ok = true; ok = true;
siCopy.eval(subscript, txTo, nIn, hashType, function (err) { siCopy.eval(subscript, txTo, nIn, hashType, function (err) {
if (err) if (err)
callback(err); callback(err);
else else
verifyStep4(scriptSig, scriptPubKey, txTo, nIn, verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy); hashType, opts, callback, si, siCopy);
}); });
} }
function verifyStep2(scriptSig, scriptPubKey, txTo, nIn, function verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy) hashType, opts, callback, si, siCopy)
{ {
if (opts.verifyP2SH) { if (opts.verifyP2SH) {
si.stack.forEach(function(item) { si.stack.forEach(function(item) {
siCopy.stack.push(item); siCopy.stack.push(item);
}); });
} }
si.eval(scriptPubKey, txTo, nIn, hashType, function (err) { si.eval(scriptPubKey, txTo, nIn, hashType, function (err) {
if (err) if (err)
callback(err); callback(err);
else else
verifyStep3(scriptSig, scriptPubKey, txTo, nIn, verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy); hashType, opts, callback, si, siCopy);
}); });
} }
ScriptInterpreter.verifyFull = ScriptInterpreter.verifyFull =
function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType, function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType,
opts, callback) opts, callback)
{ {
var si = new ScriptInterpreter(); var si = new ScriptInterpreter();
var siCopy = new ScriptInterpreter(); var siCopy = new ScriptInterpreter();
si.eval(scriptSig, txTo, nIn, hashType, function (err) { si.eval(scriptSig, txTo, nIn, hashType, function (err) {
if (err) if (err)
callback(err); callback(err);
else else
verifyStep2(scriptSig, scriptPubKey, txTo, nIn, verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
hashType, opts, callback, si, siCopy); hashType, opts, callback, si, siCopy);
}); });
}; };
var checkSig = ScriptInterpreter.checkSig = var checkSig = ScriptInterpreter.checkSig =
function (sig, pubkey, scriptCode, tx, n, hashType, callback) { function (sig, pubkey, scriptCode, tx, n, hashType, callback) {
if (!sig.length) { if (!sig.length) {
callback(null, false); callback(null, false);
return; return;
@ -1026,8 +1024,6 @@ function spec(b) {
} catch (err) { } catch (err) {
callback(null, false); callback(null, false);
} }
};
return ScriptInterpreter;
}; };
module.defineClass(spec);
module.exports = require('soop')(ScriptInterpreter);

View File

@ -1,25 +1,23 @@
require('classtool'); var imports = require('soop').imports();
function spec(b) { var config = imports.config || require('./config');
var config = b.config || require('./config'); var log = imports.log || require('./util/log');
var log = b.log || require('./util/log'); var Address = imports.Address || require('./Address');
var Address = b.Address || require('./Address').class(); var Script = imports.Script || require('./Script');
var Script = b.Script || require('./Script').class(); var ScriptInterpreter = imports.ScriptInterpreter || require('./ScriptInterpreter');
var ScriptInterpreter = b.ScriptInterpreter || require('./ScriptInterpreter').class(); var util = imports.util || require('./util/util');
var util = b.util || require('./util/util'); var bignum = imports.bignum || require('bignum');
var bignum = b.bignum || require('bignum'); var Put = imports.Put || require('bufferput');
var Put = b.Put || require('bufferput'); var Parser = imports.Parser || require('./util/BinaryParser');
var Parser = b.Parser || require('./util/BinaryParser').class(); var Step = imports.Step || require('step');
var Step = b.Step || require('step'); var buffertools = imports.buffertools || require('buffertools');
var buffertools = b.buffertools || require('buffertools'); var error = imports.error || require('./util/error');
var VerificationError = error.VerificationError;
var MissingSourceError = error.MissingSourceError;
var error = b.error || require('./util/error'); var COINBASE_OP = Buffer.concat([util.NULL_HASH, new Buffer('FFFFFFFF', 'hex')]);
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) { if ("object" !== typeof data) {
data = {}; data = {};
} }
@ -29,69 +27,69 @@ function spec(b) {
this.s = Buffer.isBuffer(data.s) ? data.s : this.s = Buffer.isBuffer(data.s) ? data.s :
Buffer.isBuffer(data.script) ? data.script : util.EMPTY_BUFFER; Buffer.isBuffer(data.script) ? data.script : util.EMPTY_BUFFER;
this.q = data.q ? data.q : data.sequence; this.q = data.q ? data.q : data.sequence;
} }
TransactionIn.prototype.getScript = function getScript() { TransactionIn.prototype.getScript = function getScript() {
return new Script(this.s); return new Script(this.s);
}; };
TransactionIn.prototype.isCoinBase = function isCoinBase() { TransactionIn.prototype.isCoinBase = function isCoinBase() {
return buffertools.compare(this.o, COINBASE_OP) === 0; 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 slen = util.varIntBuf(this.s.length);
var qbuf = new Buffer(4); var qbuf = new Buffer(4);
qbuf.writeUInt32LE(this.q, 0); qbuf.writeUInt32LE(this.q, 0);
return Buffer.concat([this.o, slen, this.s, qbuf]); return Buffer.concat([this.o, slen, this.s, qbuf]);
}; };
TransactionIn.prototype.getOutpointHash = function getOutpointHash() { TransactionIn.prototype.getOutpointHash = function getOutpointHash() {
if ("undefined" !== typeof this.o.outHashCache) { if ("undefined" !== typeof this.o.outHashCache) {
return this.o.outHashCache; return this.o.outHashCache;
} }
return this.o.outHashCache = this.o.slice(0, 32); return this.o.outHashCache = this.o.slice(0, 32);
}; };
TransactionIn.prototype.getOutpointIndex = function getOutpointIndex() { TransactionIn.prototype.getOutpointIndex = function getOutpointIndex() {
return (this.o[32] ) + return (this.o[32] ) +
(this.o[33] << 8) + (this.o[33] << 8) +
(this.o[34] << 16) + (this.o[34] << 16) +
(this.o[35] << 24); (this.o[35] << 24);
}; };
TransactionIn.prototype.setOutpointIndex = function setOutpointIndex(n) { TransactionIn.prototype.setOutpointIndex = function setOutpointIndex(n) {
this.o[32] = n & 0xff; this.o[32] = n & 0xff;
this.o[33] = n >> 8 & 0xff; this.o[33] = n >> 8 & 0xff;
this.o[34] = n >> 16 & 0xff; this.o[34] = n >> 16 & 0xff;
this.o[35] = n >> 24 & 0xff; this.o[35] = n >> 24 & 0xff;
}; };
function TransactionOut(data) { function TransactionOut(data) {
if ("object" !== typeof data) { if ("object" !== typeof data) {
data = {}; data = {};
} }
this.v = data.v ? data.v : data.value; this.v = data.v ? data.v : data.value;
this.s = data.s ? data.s : data.script; this.s = data.s ? data.s : data.script;
}; };
TransactionOut.prototype.getValue = function getValue() { TransactionOut.prototype.getValue = function getValue() {
return new Parser(this.v).word64lu(); return new Parser(this.v).word64lu();
}; };
TransactionOut.prototype.getScript = function getScript() { TransactionOut.prototype.getScript = function getScript() {
return new Script(this.s); return new Script(this.s);
}; };
TransactionOut.prototype.serialize = function serialize() { TransactionOut.prototype.serialize = function serialize() {
var slen = util.varIntBuf(this.s.length); var slen = util.varIntBuf(this.s.length);
return Buffer.concat([this.v, slen, this.s]); return Buffer.concat([this.v, slen, this.s]);
}; };
function Transaction(data) { function Transaction(data) {
if ("object" !== typeof data) { if ("object" !== typeof data) {
data = {}; data = {};
} }
@ -112,16 +110,16 @@ function spec(b) {
return txout; return txout;
}) : []; }) : [];
if (data.buffer) this._buffer = data.buffer; if (data.buffer) this._buffer = data.buffer;
}; };
this.class = Transaction; this.class = Transaction;
Transaction.In = TransactionIn; Transaction.In = TransactionIn;
Transaction.Out = TransactionOut; Transaction.Out = TransactionOut;
Transaction.prototype.isCoinBase = function () { Transaction.prototype.isCoinBase = function () {
return this.ins.length == 1 && this.ins[0].isCoinBase(); return this.ins.length == 1 && this.ins[0].isCoinBase();
}; };
Transaction.prototype.isStandard = function isStandard() { Transaction.prototype.isStandard = function isStandard() {
var i; var i;
for (i = 0; i < this.ins.length; i++) { for (i = 0; i < this.ins.length; i++) {
if (this.ins[i].getScript().getInType() == "Strange") { if (this.ins[i].getScript().getInType() == "Strange") {
@ -134,9 +132,9 @@ function spec(b) {
} }
} }
return true; return true;
}; };
Transaction.prototype.serialize = function serialize() { Transaction.prototype.serialize = function serialize() {
var bufs = []; var bufs = [];
var buf = new Buffer(4); var buf = new Buffer(4);
@ -159,34 +157,34 @@ function spec(b) {
this._buffer = Buffer.concat(bufs); this._buffer = Buffer.concat(bufs);
return this._buffer; return this._buffer;
}; };
Transaction.prototype.getBuffer = function getBuffer() { Transaction.prototype.getBuffer = function getBuffer() {
if (this._buffer) return this._buffer; if (this._buffer) return this._buffer;
return this.serialize(); return this.serialize();
}; };
Transaction.prototype.calcHash = function calcHash() { Transaction.prototype.calcHash = function calcHash() {
this.hash = util.twoSha256(this.getBuffer()); this.hash = util.twoSha256(this.getBuffer());
return this.hash; return this.hash;
}; };
Transaction.prototype.checkHash = function checkHash() { Transaction.prototype.checkHash = function checkHash() {
if (!this.hash || !this.hash.length) return false; if (!this.hash || !this.hash.length) return false;
return buffertools.compare(this.calcHash(), this.hash) === 0; return buffertools.compare(this.calcHash(), this.hash) === 0;
}; };
Transaction.prototype.getHash = function getHash() { Transaction.prototype.getHash = function getHash() {
if (!this.hash || !this.hash.length) { if (!this.hash || !this.hash.length) {
this.hash = this.calcHash(); this.hash = this.calcHash();
} }
return this.hash; return this.hash;
}; };
// convert encoded list of inputs to easy-to-use JS list-of-lists // convert encoded list of inputs to easy-to-use JS list-of-lists
Transaction.prototype.inputs = function inputs() { Transaction.prototype.inputs = function inputs() {
var res = []; var res = [];
for (var i = 0; i < this.ins.length; i++) { for (var i = 0; i < this.ins.length; i++) {
var txin = this.ins[i]; var txin = this.ins[i];
@ -196,9 +194,9 @@ function spec(b) {
} }
return res; return res;
} }
/** /**
* Load and cache transaction inputs. * Load and cache transaction inputs.
* *
* This function will try to load the inputs for a transaction. * This function will try to load the inputs for a transaction.
@ -209,15 +207,15 @@ function spec(b) {
* met (or a timeout occurs.) * met (or a timeout occurs.)
* @param {Function} callback Function to call on completion. * @param {Function} callback Function to call on completion.
*/ */
Transaction.prototype.cacheInputs = Transaction.prototype.cacheInputs =
function cacheInputs(blockChain, txStore, wait, callback) { function cacheInputs(blockChain, txStore, wait, callback) {
var self = this; var self = this;
var txCache = new TransactionInputsCache(this); var txCache = new TransactionInputsCache(this);
txCache.buffer(blockChain, txStore, wait, callback); 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 self = this;
var txIndex = txCache.txIndex; var txIndex = txCache.txIndex;
@ -341,22 +339,22 @@ function spec(b) {
}, },
callback callback
); );
}; };
Transaction.prototype.verifyInput = function verifyInput(n, scriptPubKey, callback) { Transaction.prototype.verifyInput = function verifyInput(n, scriptPubKey, callback) {
return ScriptInterpreter.verify(this.ins[n].getScript(), return ScriptInterpreter.verify(this.ins[n].getScript(),
scriptPubKey, scriptPubKey,
this, n, 0, this, n, 0,
callback); callback);
}; };
/** /**
* Returns an object containing all pubkey hashes affected by this transaction. * Returns an object containing all pubkey hashes affected by this transaction.
* *
* The return object contains the base64-encoded pubKeyHash values as keys * The return object contains the base64-encoded pubKeyHash values as keys
* and the original pubKeyHash buffers as values. * 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 // TODO: Function won't consider results cached if there are no affected
// accounts. // accounts.
if (!(this.affects && this.affects.length)) { if (!(this.affects && this.affects.length)) {
@ -423,22 +421,22 @@ function spec(b) {
}); });
return affectedKeys; return affectedKeys;
}; };
var OP_CODESEPARATOR = 171; var OP_CODESEPARATOR = 171;
var SIGHASH_ALL = 1; var SIGHASH_ALL = 1;
var SIGHASH_NONE = 2; var SIGHASH_NONE = 2;
var SIGHASH_SINGLE = 3; var SIGHASH_SINGLE = 3;
var SIGHASH_ANYONECANPAY = 80; var SIGHASH_ANYONECANPAY = 80;
Transaction.SIGHASH_ALL=SIGHASH_ALL; Transaction.SIGHASH_ALL=SIGHASH_ALL;
Transaction.SIGHASH_NONE=SIGHASH_NONE; Transaction.SIGHASH_NONE=SIGHASH_NONE;
Transaction.SIGHASH_SINGLE=SIGHASH_SINGLE; Transaction.SIGHASH_SINGLE=SIGHASH_SINGLE;
Transaction.SIGHASH_ANYONECANPAY=SIGHASH_ANYONECANPAY; Transaction.SIGHASH_ANYONECANPAY=SIGHASH_ANYONECANPAY;
Transaction.prototype.hashForSignature = Transaction.prototype.hashForSignature =
function hashForSignature(script, inIndex, hashType) { function hashForSignature(script, inIndex, hashType) {
if (+inIndex !== inIndex || if (+inIndex !== inIndex ||
inIndex < 0 || inIndex >= this.ins.length) { inIndex < 0 || inIndex >= this.ins.length) {
throw new Error("Input index '"+inIndex+"' invalid or out of bounds "+ throw new Error("Input index '"+inIndex+"' invalid or out of bounds "+
@ -540,12 +538,12 @@ function spec(b) {
buffer = Buffer.concat([buffer, new Buffer([parseInt(hashType), 0, 0, 0])]); buffer = Buffer.concat([buffer, new Buffer([parseInt(hashType), 0, 0, 0])]);
return util.twoSha256(buffer); return util.twoSha256(buffer);
}; };
/** /**
* Returns an object with the same field names as jgarzik's getblock patch. * Returns an object with the same field names as jgarzik's getblock patch.
*/ */
Transaction.prototype.getStandardizedObject = function getStandardizedObject() { Transaction.prototype.getStandardizedObject = function getStandardizedObject() {
var tx = { var tx = {
hash: util.formatHashFull(this.getHash()), hash: util.formatHashFull(this.getHash()),
version: this.version, version: this.version,
@ -587,14 +585,14 @@ function spec(b) {
tx["out"] = outs; tx["out"] = outs;
return tx; return tx;
}; };
// Add some Mongoose compatibility functions to the plain object // Add some Mongoose compatibility functions to the plain object
Transaction.prototype.toObject = function toObject() { Transaction.prototype.toObject = function toObject() {
return this; return this;
}; };
Transaction.prototype.fromObj = function fromObj(obj) { Transaction.prototype.fromObj = function fromObj(obj) {
var txobj = {}; var txobj = {};
txobj.version = obj.version || 1; txobj.version = obj.version || 1;
txobj.lock_time = obj.lock_time || 0; txobj.lock_time = obj.lock_time || 0;
@ -636,9 +634,9 @@ function spec(b) {
this.version = txobj.version; this.version = txobj.version;
this.ins = txobj.ins; this.ins = txobj.ins;
this.outs = txobj.outs; this.outs = txobj.outs;
} }
Transaction.prototype.parse = function (parser) { Transaction.prototype.parse = function (parser) {
if (Buffer.isBuffer(parser)) { if (Buffer.isBuffer(parser)) {
parser = new Parser(parser); parser = new Parser(parser);
} }
@ -672,11 +670,11 @@ function spec(b) {
this.lock_time = parser.word32le(); this.lock_time = parser.word32le();
this.calcHash(); this.calcHash();
}; };
var TransactionInputsCache = exports.TransactionInputsCache = var TransactionInputsCache = exports.TransactionInputsCache =
function TransactionInputsCache(tx) function TransactionInputsCache(tx)
{ {
var txList = []; var txList = [];
var txList64 = []; var txList64 = [];
var reqOuts = {}; var reqOuts = {};
@ -703,10 +701,10 @@ function spec(b) {
this.txIndex = {}; this.txIndex = {};
this.requiredOuts = reqOuts; this.requiredOuts = reqOuts;
this.callbacks = []; this.callbacks = [];
}; };
TransactionInputsCache.prototype.buffer = function buffer(blockChain, txStore, wait, callback) TransactionInputsCache.prototype.buffer = function buffer(blockChain, txStore, wait, callback)
{ {
var self = this; var self = this;
var complete = false; var complete = false;
@ -789,11 +787,11 @@ function spec(b) {
}, },
self.callback.bind(self) self.callback.bind(self)
); );
}; };
TransactionInputsCache.prototype.callback = function callback(err) TransactionInputsCache.prototype.callback = function callback(err)
{ {
var args = Array.prototype.slice.apply(arguments); var args = Array.prototype.slice.apply(arguments);
// Empty the callback array first (because downstream functions could add new // Empty the callback array first (because downstream functions could add new
@ -809,8 +807,6 @@ function spec(b) {
log.err("Callback error after connecting tx inputs: "+ log.err("Callback error after connecting tx inputs: "+
(err.stack ? err.stack : err.toString())); (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');}; var hex = function(hex) {return new Buffer(hex, 'hex');};
function ClassSpec(b) { var fs = require('fs');
var fs = require('fs'); var EncFile = require('./util/EncFile');
var EncFile = require('./util/EncFile'); var Address = require('./Address');
var Address = require('./Address').class(); var networks = require('./networks');
var networks = require('./networks'); var util = imports.util || require('./util/util');
var util = b.util || require('./util/util'); var ENC_METHOD = 'aes-256-cbc';
var ENC_METHOD = 'aes-256-cbc';
var skeleton = { var skeleton = {
client: 'libcoin', client: 'libcoin',
client_version: '0.0.1', client_version: '0.0.1',
network: 'testnet', network: 'testnet',
@ -19,9 +19,9 @@ function ClassSpec(b) {
keys: [], keys: [],
sin: {}, sin: {},
scripts: {}, scripts: {},
}; };
function Wallet(cfg) { function Wallet(cfg) {
if (typeof cfg !== 'object') if (typeof cfg !== 'object')
cfg = {}; cfg = {};
@ -33,15 +33,15 @@ function ClassSpec(b) {
this.network = undefined; this.network = undefined;
this.dirty = cfg.dirty || true; this.dirty = cfg.dirty || true;
}; };
Wallet.prototype.readSync = function(filename, passphrase) { Wallet.prototype.readSync = function(filename, passphrase) {
this.datastore = EncFile.readJFileSync(ENC_METHOD, this.datastore = EncFile.readJFileSync(ENC_METHOD,
passphrase, filename); passphrase, filename);
this.dirty = false; this.dirty = false;
}; };
Wallet.prototype.writeSync = function(filename, passphrase) { Wallet.prototype.writeSync = function(filename, passphrase) {
var tmp_fn = filename + ".tmp"; var tmp_fn = filename + ".tmp";
EncFile.writeJFileSync(ENC_METHOD, passphrase, tmp_fn, EncFile.writeJFileSync(ENC_METHOD, passphrase, tmp_fn,
@ -49,9 +49,9 @@ function ClassSpec(b) {
fs.renameSync(tmp_fn, filename); fs.renameSync(tmp_fn, filename);
this.dirty = false; this.dirty = false;
}; };
Wallet.prototype.setNetwork = function(netname) { Wallet.prototype.setNetwork = function(netname) {
if (!netname) if (!netname)
netname = this.datastore.network; netname = this.datastore.network;
@ -70,19 +70,19 @@ function ClassSpec(b) {
// store+canonicalize name // store+canonicalize name
this.datastore['network'] = this.network.name; this.datastore['network'] = this.network.name;
this.dirty = true; this.dirty = true;
}; };
Wallet.prototype.addKey = function(wkey) { Wallet.prototype.addKey = function(wkey) {
this.datastore.keys.push(wkey); this.datastore.keys.push(wkey);
this.dirty = true; this.dirty = true;
}; };
Wallet.prototype.addSIN = function(sinObj) { Wallet.prototype.addSIN = function(sinObj) {
this.datastore.sin[sinObj.sin] = sinObj; this.datastore.sin[sinObj.sin] = sinObj;
this.dirty = true; this.dirty = true;
}; };
Wallet.prototype.findKeyHash = function(pubKeyHash) { Wallet.prototype.findKeyHash = function(pubKeyHash) {
var pkhStr = pubKeyHash.toString(); var pkhStr = pubKeyHash.toString();
for (var i = 0; i < this.datastore.keys.length; i++) { for (var i = 0; i < this.datastore.keys.length; i++) {
@ -94,9 +94,9 @@ function ClassSpec(b) {
} }
return undefined; return undefined;
}; };
Wallet.prototype.expandKey = function(key) { Wallet.prototype.expandKey = function(key) {
var addr = new Address(key); var addr = new Address(key);
var isAddr = true; var isAddr = true;
@ -113,9 +113,9 @@ function ClassSpec(b) {
if (!key.match(re)) if (!key.match(re))
throw new Error("Unknown key type"); throw new Error("Unknown key type");
return hex(key); return hex(key);
}; };
Wallet.prototype.expandKeys = function(keys) { Wallet.prototype.expandKeys = function(keys) {
var res = []; var res = [];
var us = this; var us = this;
keys.forEach(function(key) { keys.forEach(function(key) {
@ -123,9 +123,9 @@ function ClassSpec(b) {
res.push(expKey); res.push(expKey);
}); });
return res; return res;
}; };
Wallet.prototype.addScript = function(script) { Wallet.prototype.addScript = function(script) {
var buf = script.getBuffer(); var buf = script.getBuffer();
var hash = util.sha256ripe160(buf); var hash = util.sha256ripe160(buf);
var addr = new Address(this.network.addressScript, hash); var addr = new Address(this.network.addressScript, hash);
@ -134,9 +134,7 @@ function ClassSpec(b) {
this.dirty = true; this.dirty = true;
return addrStr; 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 coinUtil = require('./util/util'); var timeUtil = require('./util/time');
var timeUtil = require('./util/time'); var KeyModule = require('./Key');
var KeyModule = require('./Key'); var PrivateKey = require('./PrivateKey');
var PrivateKey = require('./PrivateKey').class(); var Address = require('./Address');
var Address = require('./Address').class();
function WalletKey(cfg) { function WalletKey(cfg) {
if (!cfg) cfg = {}; if (!cfg) cfg = {};
if (!cfg.network) throw new Error('network parameter is required'); if (!cfg.network) throw new Error('network parameter is required');
this.network = cfg.network; // required this.network = cfg.network; // required
this.created = cfg.created; this.created = cfg.created;
this.privKey = cfg.privKey; this.privKey = cfg.privKey;
}; };
WalletKey.prototype.generate = function() { WalletKey.prototype.generate = function() {
this.privKey = KeyModule.Key.generateSync(); this.privKey = KeyModule.Key.generateSync();
this.created = timeUtil.curtime(); this.created = timeUtil.curtime();
}; };
WalletKey.prototype.storeObj = function() { WalletKey.prototype.storeObj = function() {
var pubKey = this.privKey.public.toString('hex'); var pubKey = this.privKey.public.toString('hex');
var pubKeyHash = coinUtil.sha256ripe160(this.privKey.public); var pubKeyHash = coinUtil.sha256ripe160(this.privKey.public);
var addr = new Address(this.network.addressPubkey, pubKeyHash); var addr = new Address(this.network.addressPubkey, pubKeyHash);
@ -33,9 +32,9 @@ function ClassSpec(b) {
}; };
return obj; return obj;
}; };
WalletKey.prototype.fromObj = function(obj) { WalletKey.prototype.fromObj = function(obj) {
this.created = obj.created; this.created = obj.created;
this.privKey = new KeyModule.Key(); this.privKey = new KeyModule.Key();
if (obj.priv.length==64) { if (obj.priv.length==64) {
@ -48,8 +47,6 @@ function ClassSpec(b) {
this.privKey.compressed = priv.compressed(); this.privKey.compressed = priv.compressed();
} }
this.privKey.regenerateSync(); this.privKey.regenerateSync();
};
return WalletKey;
}; };
module.defineClass(ClassSpec);
module.exports = require('soop')(WalletKey);

View File

@ -13,7 +13,7 @@ describe('Address', function() {
should.exist(AddressModule); should.exist(AddressModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Address = AddressModule.class(); Address = AddressModule;
should.exist(Address); should.exist(Address);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -12,7 +12,7 @@ describe('Block', function() {
should.exist(BlockModule); should.exist(BlockModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Block = BlockModule.class(); Block = BlockModule;
should.exist(Block); should.exist(Block);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -13,7 +13,7 @@ describe('Bloom', function() {
should.exist(BloomModule); should.exist(BloomModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Bloom = BloomModule.class(); Bloom = BloomModule;
should.exist(Bloom); should.exist(Bloom);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -14,7 +14,7 @@ describe('Connection', function() {
should.exist(ConnectionModule); should.exist(ConnectionModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Connection = ConnectionModule.class(); Connection = ConnectionModule;
should.exist(Connection); should.exist(Connection);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -13,7 +13,7 @@ describe('EncodedData', function() {
should.exist(EncodedDataModule); should.exist(EncodedDataModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
EncodedData = EncodedDataModule.class(); EncodedData = EncodedDataModule;
should.exist(EncodedData); should.exist(EncodedData);
}); });
it('should be able to create an instance', function() { it('should be able to create an instance', function() {

View File

@ -13,7 +13,7 @@ describe('Opcode', function() {
should.exist(OpcodeModule); should.exist(OpcodeModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Opcode = OpcodeModule.class(); Opcode = OpcodeModule;
should.exist(Opcode); should.exist(Opcode);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -13,7 +13,7 @@ describe('Peer', function() {
should.exist(PeerModule); should.exist(PeerModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Peer = PeerModule.class(); Peer = PeerModule;
should.exist(Peer); should.exist(Peer);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -13,7 +13,7 @@ describe('PeerManager', function() {
should.exist(PeerManagerModule); should.exist(PeerManagerModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
PeerManager = PeerManagerModule.class(); PeerManager = PeerManagerModule;
should.exist(PeerManager); should.exist(PeerManager);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -15,7 +15,7 @@ describe('PrivateKey', function() {
should.exist(PrivateKeyModule); should.exist(PrivateKeyModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
PrivateKey = PrivateKeyModule.class(); PrivateKey = PrivateKeyModule;
should.exist(PrivateKey); should.exist(PrivateKey);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -7,7 +7,7 @@ var should = chai.should();
var RpcClientModule = bitcore.RpcClient; var RpcClientModule = bitcore.RpcClient;
var RpcClient; var RpcClient;
RpcClient = RpcClientModule.class(); RpcClient = RpcClientModule;
describe('RpcClient', function() { describe('RpcClient', function() {
it('should initialze the main object', function() { it('should initialze the main object', function() {

View File

@ -13,7 +13,7 @@ describe('SIN', function() {
should.exist(SINModule); should.exist(SINModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
SIN = SINModule.class(); SIN = SINModule;
should.exist(SIN); should.exist(SIN);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -16,7 +16,7 @@ describe('SINKey', function() {
should.exist(SINKeyModule); should.exist(SINKeyModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
SINKey = SINKeyModule.class(); SINKey = SINKeyModule;
should.exist(SINKey); should.exist(SINKey);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -6,7 +6,7 @@ var bitcore = require('../bitcore');
var should = chai.should(); var should = chai.should();
var ScriptModule = bitcore.Script; var ScriptModule = bitcore.Script;
var Address = bitcore.Address.class(); var Address = bitcore.Address;
var networks = bitcore.networks; var networks = bitcore.networks;
var Script; var Script;
@ -15,7 +15,7 @@ describe('Script', function() {
should.exist(ScriptModule); should.exist(ScriptModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Script = ScriptModule.class(); Script = ScriptModule;
should.exist(Script); should.exist(Script);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -13,7 +13,7 @@ describe('ScriptInterpreter', function() {
should.exist(ScriptInterpreterModule); should.exist(ScriptInterpreterModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
ScriptInterpreter = ScriptInterpreterModule.class(); ScriptInterpreter = ScriptInterpreterModule;
should.exist(ScriptInterpreter); should.exist(ScriptInterpreter);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -13,7 +13,7 @@ describe('Transaction', function() {
should.exist(TransactionModule); should.exist(TransactionModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Transaction = TransactionModule.class(); Transaction = TransactionModule;
should.exist(Transaction); should.exist(Transaction);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -13,7 +13,7 @@ describe('VersionedData', function() {
should.exist(VersionedDataModule); should.exist(VersionedDataModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
VersionedData = VersionedDataModule.class(); VersionedData = VersionedDataModule;
should.exist(VersionedData); should.exist(VersionedData);
}); });
it('should be able to create an instance', function() { it('should be able to create an instance', function() {

View File

@ -13,7 +13,7 @@ describe('Wallet', function() {
should.exist(WalletModule); should.exist(WalletModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
Wallet = WalletModule.class(); Wallet = WalletModule;
should.exist(Wallet); should.exist(Wallet);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -14,7 +14,7 @@ describe('WalletKey', function() {
should.exist(WalletKeyModule); should.exist(WalletKeyModule);
}); });
it('should be able to create class', function() { it('should be able to create class', function() {
WalletKey = WalletKeyModule.class(); WalletKey = WalletKeyModule;
should.exist(WalletKey); should.exist(WalletKey);
}); });
it('should be able to create instance', function() { it('should be able to create instance', function() {

View File

@ -4,8 +4,8 @@ var chai = require('chai');
var bitcore = require('../bitcore'); var bitcore = require('../bitcore');
var should = chai.should(); var should = chai.should();
var Address = bitcore.Address.class(); var Address = bitcore.Address;
var PrivateKey = bitcore.PrivateKey.class(); var PrivateKey = bitcore.PrivateKey;
var networks = bitcore.networks; var networks = bitcore.networks;
var KeyModule = bitcore.KeyModule; var KeyModule = bitcore.KeyModule;

View File

@ -2,20 +2,20 @@
* Simple synchronous parser based on node-binary. * Simple synchronous parser based on node-binary.
*/ */
function spec(b) { var imports = require('soop').imports();
function Parser(buffer) function Parser(buffer)
{ {
this.subject = buffer; this.subject = buffer;
this.pos = 0; 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); var buf = this.subject.slice(this.pos, this.pos+len);
this.pos += len; this.pos += len;
return buf; return buf;
}; };
Parser.prototype.search = function search(needle) { Parser.prototype.search = function search(needle) {
var len; var len;
if ("string" === typeof needle || Buffer.isBuffer(needle)) { if ("string" === typeof needle || Buffer.isBuffer(needle)) {
@ -38,12 +38,12 @@ function spec(b) {
} }
return -1; return -1;
} }
}; };
/** /**
* Like search(), but returns the skipped bytes * Like search(), but returns the skipped bytes
*/ */
Parser.prototype.scan = function scan(needle) { Parser.prototype.scan = function scan(needle) {
var startPos = this.pos; var startPos = this.pos;
var len = this.search(needle); var len = this.search(needle);
if (len !== -1) { if (len !== -1) {
@ -51,55 +51,55 @@ function spec(b) {
} else { } else {
throw new Error('No match'); throw new Error('No match');
} }
}; };
Parser.prototype.eof = function eof() { Parser.prototype.eof = function eof() {
return this.pos >= this.subject.length; return this.pos >= this.subject.length;
}; };
// convert byte strings to unsigned little endian numbers // convert byte strings to unsigned little endian numbers
function decodeLEu (bytes) { function decodeLEu (bytes) {
var acc = 0; var acc = 0;
for (var i = 0; i < bytes.length; i++) { for (var i = 0; i < bytes.length; i++) {
acc += Math.pow(256,i) * bytes[i]; acc += Math.pow(256,i) * bytes[i];
} }
return acc; return acc;
} }
// convert byte strings to unsigned big endian numbers // convert byte strings to unsigned big endian numbers
function decodeBEu (bytes) { function decodeBEu (bytes) {
var acc = 0; var acc = 0;
for (var i = 0; i < bytes.length; i++) { for (var i = 0; i < bytes.length; i++) {
acc += Math.pow(256, bytes.length - i - 1) * bytes[i]; acc += Math.pow(256, bytes.length - i - 1) * bytes[i];
} }
return acc; return acc;
} }
// convert byte strings to signed big endian numbers // convert byte strings to signed big endian numbers
function decodeBEs (bytes) { function decodeBEs (bytes) {
var val = decodeBEu(bytes); var val = decodeBEu(bytes);
if ((bytes[0] & 0x80) == 0x80) { if ((bytes[0] & 0x80) == 0x80) {
val -= Math.pow(256, bytes.length); val -= Math.pow(256, bytes.length);
} }
return val; return val;
} }
// convert byte strings to signed little endian numbers // convert byte strings to signed little endian numbers
function decodeLEs (bytes) { function decodeLEs (bytes) {
var val = decodeLEu(bytes); var val = decodeLEu(bytes);
if ((bytes[bytes.length - 1] & 0x80) == 0x80) { if ((bytes[bytes.length - 1] & 0x80) == 0x80) {
val -= Math.pow(256, bytes.length); val -= Math.pow(256, bytes.length);
} }
return val; return val;
} }
function getDecoder(len, fn) { function getDecoder(len, fn) {
return function () { return function () {
var buf = this.buffer(len); var buf = this.buffer(len);
return fn(buf); return fn(buf);
}; };
}; };
[ 1, 2, 4, 8 ].forEach(function (bytes) { [ 1, 2, 4, 8 ].forEach(function (bytes) {
var bits = bytes * 8; var bits = bytes * 8;
Parser.prototype['word' + bits + 'le'] Parser.prototype['word' + bits + 'le']
@ -118,10 +118,10 @@ function spec(b) {
Parser.prototype.word8 = Parser.prototype.word8u = Parser.prototype.word8be; Parser.prototype.word8 = Parser.prototype.word8u = Parser.prototype.word8be;
Parser.prototype.word8s = Parser.prototype.word8bs; Parser.prototype.word8s = Parser.prototype.word8bs;
}); });
Parser.prototype.varInt = function () Parser.prototype.varInt = function ()
{ {
var firstByte = this.word8(); var firstByte = this.word8();
switch (firstByte) { switch (firstByte) {
case 0xFD: case 0xFD:
@ -136,13 +136,11 @@ function spec(b) {
default: default:
return firstByte; return firstByte;
} }
}; };
Parser.prototype.varStr = function () { Parser.prototype.varStr = function () {
var len = this.varInt(); var len = this.varInt();
return this.buffer(len); 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: // Constructor. Takes the following forms:
// new EncodedData(<base58_address_string>) // new EncodedData(<base58_address_string>)
// new EncodedData(<binary_buffer>) // new EncodedData(<binary_buffer>)
// new EncodedData(<data>, <encoding>) // new EncodedData(<data>, <encoding>)
// new EncodedData(<version>, <20-byte-hash>) // new EncodedData(<version>, <20-byte-hash>)
function EncodedData(data, encoding) { function EncodedData(data, encoding) {
this.data = data; this.data = data;
if(!encoding && (typeof data == 'string')) { if(!encoding && (typeof data == 'string')) {
this.__proto__ = this.encodings['base58']; this.__proto__ = this.encodings['base58'];
} else { } else {
this.__proto__ = this.encodings[encoding || 'binary']; this.__proto__ = this.encodings[encoding || 'binary'];
} }
}; };
// get or set the encoding used (transforms data) // get or set the encoding used (transforms data)
EncodedData.prototype.encoding = function(encoding) { EncodedData.prototype.encoding = function(encoding) {
if(encoding && (encoding != this._encoding)) { if(encoding && (encoding != this._encoding)) {
this.data = this.as(encoding); this.data = this.as(encoding);
this.__proto__ = this.encodings[encoding]; this.__proto__ = this.encodings[encoding];
} }
return this._encoding; return this._encoding;
}; };
// answer a new instance having the given encoding // answer a new instance having the given encoding
EncodedData.prototype.withEncoding = function(encoding) { EncodedData.prototype.withEncoding = function(encoding) {
return new EncodedData(this.as(encoding), encoding); return new EncodedData(this.as(encoding), encoding);
}; };
// answer the data in the given encoding // answer the data in the given encoding
EncodedData.prototype.as = function(encoding) { EncodedData.prototype.as = function(encoding) {
if(!encodings[encoding]) throw new Error('invalid encoding'); if(!encodings[encoding]) throw new Error('invalid encoding');
return this.converters[encoding].call(this); return this.converters[encoding].call(this);
}; };
// validate that we can convert to binary // validate that we can convert to binary
EncodedData.prototype._validate = function() { EncodedData.prototype._validate = function() {
this.withEncoding('binary'); this.withEncoding('binary');
}; };
// Boolean protocol for testing if valid // Boolean protocol for testing if valid
EncodedData.prototype.isValid = function() { EncodedData.prototype.isValid = function() {
try { try {
this.validate(); this.validate();
return true; return true;
} catch(e) { } catch(e) {
return false; return false;
} }
}; };
// subclasses can override to do more stuff // subclasses can override to do more stuff
EncodedData.prototype.validate = function() { EncodedData.prototype.validate = function() {
this._validate(); this._validate();
}; };
// Boolean protocol for testing if valid // Boolean protocol for testing if valid
EncodedData.prototype.isValid = function() { EncodedData.prototype.isValid = function() {
try { try {
this.validate(); this.validate();
return true; return true;
} catch(e) { } catch(e) {
return false; return false;
} }
}; };
// convert to a string (in base58 form) // convert to a string (in base58 form)
EncodedData.prototype.toString = function() { EncodedData.prototype.toString = function() {
return this.as('base58'); return this.as('base58');
}; };
// utility // utility
EncodedData.prototype.doAsBinary = function(callback) { EncodedData.prototype.doAsBinary = function(callback) {
var oldEncoding = this.encoding(); var oldEncoding = this.encoding();
this.encoding('binary'); this.encoding('binary');
callback.apply(this); callback.apply(this);
this.encoding(oldEncoding); this.encoding(oldEncoding);
}; };
// Setup support for various address encodings. The object for // Setup support for various address encodings. The object for
// each encoding inherits from the EncodedData prototype. This // each encoding inherits from the EncodedData prototype. This
// allows any encoding to override any method...changing the encoding // allows any encoding to override any method...changing the encoding
// for an instance will change the encoding it inherits from. Note, // for an instance will change the encoding it inherits from. Note,
// this will present some problems for anyone wanting to inherit from // this will present some problems for anyone wanting to inherit from
// EncodedData (we'll deal with that when needed). // EncodedData (we'll deal with that when needed).
var encodings = { var encodings = {
'binary': { 'binary': {
converters: { converters: {
'binary': function() { 'binary': function() {
@ -128,18 +127,18 @@ function ClassSpec(b) {
}, },
}, },
}, },
}; };
var no_conversion = function() {return this.data;}; var no_conversion = function() {return this.data;};
for(var k in encodings) { for(var k in encodings) {
if(encodings.hasOwnProperty(k)){ if(encodings.hasOwnProperty(k)){
if(!encodings[k].converters[k]) if(!encodings[k].converters[k])
encodings[k].converters[k] = no_conversion; encodings[k].converters[k] = no_conversion;
encodings[k]._encoding = k; encodings[k]._encoding = k;
} }
} }
EncodedData.applyEncodingsTo = function(aClass) { EncodedData.applyEncodingsTo = function(aClass) {
var tmp = {}; var tmp = {};
for(var k in encodings) { for(var k in encodings) {
var enc = encodings[k]; var enc = encodings[k];
@ -151,9 +150,9 @@ function ClassSpec(b) {
tmp[k] = obj; tmp[k] = obj;
} }
aClass.prototype.encodings = tmp; 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,8 @@
require('classtool'); var imports = require('soop').imports();
var base58 = imports.base58 || require('base58-native').base58Check;
var superclass = imports.parent || require('./EncodedData');
function ClassSpec(b) { function VersionedData(version, payload) {
var superclass = b.superclass || require('./EncodedData').class();
function VersionedData(version, payload) {
if(typeof version != 'number') { if(typeof version != 'number') {
VersionedData.super(this, arguments); VersionedData.super(this, arguments);
return; return;
@ -12,28 +11,27 @@ function ClassSpec(b) {
this.__proto__ = this.encodings['binary']; this.__proto__ = this.encodings['binary'];
this.version(version); this.version(version);
this.payload(payload); this.payload(payload);
}; };
VersionedData.superclass = superclass;
superclass.applyEncodingsTo(VersionedData);
// get or set the version data (the first byte of the address) VersionedData.parent = superclass || require('./Person');
VersionedData.prototype.version = function(num) { superclass.applyEncodingsTo(VersionedData);
// get or set the version data (the first byte of the address)
VersionedData.prototype.version = function(num) {
if(num || (num === 0)) { if(num || (num === 0)) {
this.doAsBinary(function() {this.data.writeUInt8(num, 0);}); this.doAsBinary(function() {this.data.writeUInt8(num, 0);});
return num; return num;
} }
return this.as('binary').readUInt8(0); return this.as('binary').readUInt8(0);
}; };
// get or set the payload data (as a Buffer object) // get or set the payload data (as a Buffer object)
VersionedData.prototype.payload = function(data) { VersionedData.prototype.payload = function(data) {
if(data) { if(data) {
this.doAsBinary(function() {data.copy(this.data,1);}); this.doAsBinary(function() {data.copy(this.data,1);});
return data; return data;
} }
return this.as('binary').slice(1); return this.as('binary').slice(1);
};
return VersionedData;
}; };
module.defineClass(ClassSpec);
module.exports = require('soop')(VersionedData);