replace tabs with 2 spaces using "expand"
This commit is contained in:
parent
c24ae73cf5
commit
f35c03544b
12
Block.js
12
Block.js
|
@ -39,12 +39,12 @@ function spec(b) {
|
|||
Block.prototype.getHeader = function getHeader() {
|
||||
var buf = new Buffer(80);
|
||||
var ofs = 0;
|
||||
buf.writeUInt32LE(this.version, ofs); ofs += 4;
|
||||
this.prev_hash.copy(buf, ofs); ofs += 32;
|
||||
this.merkle_root.copy(buf, ofs); ofs += 32;
|
||||
buf.writeUInt32LE(this.timestamp, ofs); ofs += 4;
|
||||
buf.writeUInt32LE(this.bits, ofs); ofs += 4;
|
||||
buf.writeUInt32LE(this.nonce, ofs); ofs += 4;
|
||||
buf.writeUInt32LE(this.version, ofs); ofs += 4;
|
||||
this.prev_hash.copy(buf, ofs); ofs += 32;
|
||||
this.merkle_root.copy(buf, ofs); ofs += 32;
|
||||
buf.writeUInt32LE(this.timestamp, ofs); ofs += 4;
|
||||
buf.writeUInt32LE(this.bits, ofs); ofs += 4;
|
||||
buf.writeUInt32LE(this.nonce, ofs); ofs += 4;
|
||||
return buf;
|
||||
};
|
||||
|
||||
|
|
180
Bloom.js
180
Bloom.js
|
@ -1,116 +1,116 @@
|
|||
require('classtool');
|
||||
|
||||
function ClassSpec(b) {
|
||||
var MAX_BLOOM_FILTER_SIZE = 36000; // bytes
|
||||
var MAX_HASH_FUNCS = 50;
|
||||
var LN2SQUARED = 0.4804530139182014246671025263266649717305529515945455;
|
||||
var LN2 = 0.6931471805599453094172321214581765680755001343602552;
|
||||
var bit_mask = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80];
|
||||
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.hashFuncs = 0;
|
||||
};
|
||||
function Bloom() {
|
||||
this.data = '';
|
||||
this.hashFuncs = 0;
|
||||
};
|
||||
|
||||
function ROTL32(x, r) {
|
||||
return (x << r) | (x >> (32 - r));
|
||||
};
|
||||
function ROTL32(x, r) {
|
||||
return (x << r) | (x >> (32 - r));
|
||||
};
|
||||
|
||||
function getBlockU32(blockIdx, data) {
|
||||
var idx = blockIdx * 4;
|
||||
var v = (data[idx + 0] << (0 * 8)) |
|
||||
(data[idx + 1] << (1 * 8)) |
|
||||
(data[idx + 2] << (2 * 8)) |
|
||||
(data[idx + 3] << (3 * 8));
|
||||
return v;
|
||||
};
|
||||
function getBlockU32(blockIdx, data) {
|
||||
var idx = blockIdx * 4;
|
||||
var v = (data[idx + 0] << (0 * 8)) |
|
||||
(data[idx + 1] << (1 * 8)) |
|
||||
(data[idx + 2] << (2 * 8)) |
|
||||
(data[idx + 3] << (3 * 8));
|
||||
return v;
|
||||
};
|
||||
|
||||
Bloom.prototype.hash = function(hashNum, data) {
|
||||
var h1 = hashNum * (0xffffffff / (this.hashFuncs - 1));
|
||||
var c1 = 0xcc9e2d51;
|
||||
var c2 = 0x1b873593;
|
||||
var nBlocks = data.length / 4;
|
||||
Bloom.prototype.hash = function(hashNum, data) {
|
||||
var h1 = hashNum * (0xffffffff / (this.hashFuncs - 1));
|
||||
var c1 = 0xcc9e2d51;
|
||||
var c2 = 0x1b873593;
|
||||
var nBlocks = data.length / 4;
|
||||
|
||||
// data body
|
||||
for (var i = -nBlocks; i; i++) {
|
||||
var k1 = getBlockU32(i);
|
||||
// data body
|
||||
for (var i = -nBlocks; i; i++) {
|
||||
var k1 = getBlockU32(i);
|
||||
|
||||
k1 *= c1;
|
||||
k1 = ROTLF32(k1, 15);
|
||||
k1 *= c2;
|
||||
k1 *= c1;
|
||||
k1 = ROTLF32(k1, 15);
|
||||
k1 *= c2;
|
||||
|
||||
h1 ^= k1;
|
||||
h1 = ROTFL(h1, 13);
|
||||
h1 = h1 * 5 + 0xe6546b64;
|
||||
}
|
||||
h1 ^= k1;
|
||||
h1 = ROTFL(h1, 13);
|
||||
h1 = h1 * 5 + 0xe6546b64;
|
||||
}
|
||||
|
||||
// tail (trailing 1-3 bytes)
|
||||
var tail = data.slice(nBlocks * 4);
|
||||
// tail (trailing 1-3 bytes)
|
||||
var tail = data.slice(nBlocks * 4);
|
||||
|
||||
var k1 = 0;
|
||||
var k1 = 0;
|
||||
|
||||
switch (data.length & 3) {
|
||||
case 3: k1 ^= tail[2] << 16;
|
||||
case 2: k1 ^= tail[1] << 8;
|
||||
case 1: k1 ^= tail[0];
|
||||
k1 *= c1;
|
||||
k1 = ROTL32(k1, 15);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
}
|
||||
switch (data.length & 3) {
|
||||
case 3: k1 ^= tail[2] << 16;
|
||||
case 2: k1 ^= tail[1] << 8;
|
||||
case 1: k1 ^= tail[0];
|
||||
k1 *= c1;
|
||||
k1 = ROTL32(k1, 15);
|
||||
k1 *= c2;
|
||||
h1 ^= k1;
|
||||
}
|
||||
|
||||
// finalize
|
||||
h1 ^= data.length;
|
||||
h1 ^= h1 >> 16;
|
||||
h1 *= 0x85ebca6b;
|
||||
h1 ^= h1 >> 13;
|
||||
h1 *= 0xc2b2ae35;
|
||||
h1 ^= h1 >> 16;
|
||||
// finalize
|
||||
h1 ^= data.length;
|
||||
h1 ^= h1 >> 16;
|
||||
h1 *= 0x85ebca6b;
|
||||
h1 ^= h1 >> 13;
|
||||
h1 *= 0xc2b2ae35;
|
||||
h1 ^= h1 >> 16;
|
||||
|
||||
return h1 % (this.data.length * 8);
|
||||
};
|
||||
return h1 % (this.data.length * 8);
|
||||
};
|
||||
|
||||
Bloom.prototype.insert = function(data) {
|
||||
for (var i = 0; i < this.hashFuncs; i++) {
|
||||
var index = this.hash(i, data);
|
||||
this.data[index >> 3] |= bit_mask[7 & index];
|
||||
}
|
||||
};
|
||||
Bloom.prototype.insert = function(data) {
|
||||
for (var i = 0; i < this.hashFuncs; i++) {
|
||||
var index = this.hash(i, data);
|
||||
this.data[index >> 3] |= bit_mask[7 & index];
|
||||
}
|
||||
};
|
||||
|
||||
Bloom.prototype.contains = function(data) {
|
||||
for (var i = 0; i < this.hashFuncs; i++) {
|
||||
var index = this.hash(i, data);
|
||||
if (!(this.data[index >> 3] & bit_mask[7 & index]))
|
||||
return false;
|
||||
}
|
||||
Bloom.prototype.contains = function(data) {
|
||||
for (var i = 0; i < this.hashFuncs; i++) {
|
||||
var index = this.hash(i, data);
|
||||
if (!(this.data[index >> 3] & bit_mask[7 & index]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
return true;
|
||||
};
|
||||
|
||||
Bloom.prototype.sizeOk = function() {
|
||||
return this.data.length <= MAX_BLOOM_FILTER_SIZE &&
|
||||
this.hashFuncs <= MAX_HASH_FUNCS;
|
||||
};
|
||||
Bloom.prototype.sizeOk = function() {
|
||||
return this.data.length <= MAX_BLOOM_FILTER_SIZE &&
|
||||
this.hashFuncs <= MAX_HASH_FUNCS;
|
||||
};
|
||||
|
||||
function toInt(v) {
|
||||
return ~~v;
|
||||
}
|
||||
function toInt(v) {
|
||||
return ~~v;
|
||||
}
|
||||
|
||||
function min(a, b) {
|
||||
if (a < b)
|
||||
return a;
|
||||
return b;
|
||||
}
|
||||
function min(a, b) {
|
||||
if (a < b)
|
||||
return a;
|
||||
return b;
|
||||
}
|
||||
|
||||
Bloom.prototype.init = function(elements, FPRate) {
|
||||
var filterSize = min(toInt(-1.0 / LN2SQUARED * elements * Math.log(FPRate)),
|
||||
MAX_BLOOM_FILTER_SIZE * 8) / 8;
|
||||
this.data[filterSize] = 0;
|
||||
this.hashFuncs = min(toInt(this.data.length * 8 / elements * LN2),
|
||||
MAX_HASH_FUNCS);
|
||||
};
|
||||
Bloom.prototype.init = function(elements, FPRate) {
|
||||
var filterSize = min(toInt(-1.0 / LN2SQUARED * elements * Math.log(FPRate)),
|
||||
MAX_BLOOM_FILTER_SIZE * 8) / 8;
|
||||
this.data[filterSize] = 0;
|
||||
this.hashFuncs = min(toInt(this.data.length * 8 / elements * LN2),
|
||||
MAX_HASH_FUNCS);
|
||||
};
|
||||
|
||||
return Bloom;
|
||||
return Bloom;
|
||||
};
|
||||
module.defineClass(ClassSpec);
|
||||
|
||||
|
|
|
@ -443,8 +443,8 @@ function spec(b) {
|
|||
data.headers = [];
|
||||
for (i = 0; i < data.count; i++) {
|
||||
var header = new Block();
|
||||
header.parse(parser);
|
||||
data.headers.push(header);
|
||||
header.parse(parser);
|
||||
data.headers.push(header);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -474,7 +474,7 @@ function spec(b) {
|
|||
lock_time: tx.lock_time,
|
||||
ins: tx.ins,
|
||||
outs: tx.outs,
|
||||
tx: tx,
|
||||
tx: tx,
|
||||
};
|
||||
|
||||
case 'getblocks':
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
exports.intFromCompact = function(c)
|
||||
{
|
||||
var bytes = ((c >>> 24) & 0xff) >>> 0;
|
||||
var v = ((c & 0xffffff) << (8 * (bytes - 3))) >>> 0;
|
||||
return v;
|
||||
var bytes = ((c >>> 24) & 0xff) >>> 0;
|
||||
var v = ((c & 0xffffff) << (8 * (bytes - 3))) >>> 0;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
8
SIN.js
8
SIN.js
|
@ -11,16 +11,16 @@ function ClassSpec(b) {
|
|||
};
|
||||
this.data = new Buffer(1 + 1 + payload.length);
|
||||
this.__proto__ = this.encodings['binary'];
|
||||
this.prefix(0x0F); // SIN magic number, in numberspace
|
||||
this.prefix(0x0F); // SIN magic number, in numberspace
|
||||
this.type(type);
|
||||
this.payload(payload);
|
||||
};
|
||||
SIN.superclass = superclass;
|
||||
superclass.applyEncodingsTo(SIN);
|
||||
|
||||
SIN.SIN_PERSIST_MAINNET = 0x01; // associated with sacrifice TX
|
||||
SIN.SIN_PERSIST_TESTNET = 0x11; // associated with sacrifice TX
|
||||
SIN.SIN_EPHEM = 0x02; // generate off-net at any time
|
||||
SIN.SIN_PERSIST_MAINNET = 0x01; // associated with sacrifice TX
|
||||
SIN.SIN_PERSIST_TESTNET = 0x11; // associated with sacrifice TX
|
||||
SIN.SIN_EPHEM = 0x02; // generate off-net at any time
|
||||
|
||||
// get or set the prefix data (the first byte of the address)
|
||||
SIN.prototype.prefix = function(num) {
|
||||
|
|
60
SINKey.js
60
SINKey.js
|
@ -1,43 +1,43 @@
|
|||
require('classtool');
|
||||
|
||||
function ClassSpec(b) {
|
||||
var coinUtil = require('./util/util');
|
||||
var timeUtil = require('./util/time');
|
||||
var KeyModule = require('./Key');
|
||||
var SIN = require('./SIN').class();
|
||||
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')
|
||||
cfg = {};
|
||||
function SINKey(cfg) {
|
||||
if (typeof cfg != 'object')
|
||||
cfg = {};
|
||||
|
||||
this.created = cfg.created;
|
||||
this.privKey = cfg.privKey;
|
||||
};
|
||||
this.created = cfg.created;
|
||||
this.privKey = cfg.privKey;
|
||||
};
|
||||
|
||||
SINKey.prototype.generate = function() {
|
||||
this.privKey = KeyModule.Key.generateSync();
|
||||
this.created = timeUtil.curtime();
|
||||
};
|
||||
SINKey.prototype.generate = function() {
|
||||
this.privKey = KeyModule.Key.generateSync();
|
||||
this.created = timeUtil.curtime();
|
||||
};
|
||||
|
||||
SINKey.prototype.pubkeyHash = function() {
|
||||
return coinUtil.sha256ripe160(this.privKey.public);
|
||||
};
|
||||
SINKey.prototype.pubkeyHash = function() {
|
||||
return coinUtil.sha256ripe160(this.privKey.public);
|
||||
};
|
||||
|
||||
SINKey.prototype.storeObj = function() {
|
||||
var pubKey = this.privKey.public.toString('hex');
|
||||
var pubKeyHash = this.pubkeyHash();
|
||||
var sin = new SIN(SIN.SIN_EPHEM, pubKeyHash);
|
||||
var obj = {
|
||||
created: this.created,
|
||||
priv: this.privKey.private.toString('hex'),
|
||||
pub: pubKey,
|
||||
sin: sin.toString(),
|
||||
};
|
||||
SINKey.prototype.storeObj = function() {
|
||||
var pubKey = this.privKey.public.toString('hex');
|
||||
var pubKeyHash = this.pubkeyHash();
|
||||
var sin = new SIN(SIN.SIN_EPHEM, pubKeyHash);
|
||||
var obj = {
|
||||
created: this.created,
|
||||
priv: this.privKey.private.toString('hex'),
|
||||
pub: pubKey,
|
||||
sin: sin.toString(),
|
||||
};
|
||||
|
||||
return obj;
|
||||
};
|
||||
return obj;
|
||||
};
|
||||
|
||||
return SINKey;
|
||||
return SINKey;
|
||||
};
|
||||
module.defineClass(ClassSpec);
|
||||
|
||||
|
|
106
Script.js
106
Script.js
|
@ -84,42 +84,42 @@ function spec(b) {
|
|||
Script.prototype.isP2SH = function ()
|
||||
{
|
||||
return (this.chunks.length == 3 &&
|
||||
this.chunks[0] == OP_HASH160 &&
|
||||
Buffer.isBuffer(this.chunks[1]) &&
|
||||
this.chunks[1].length == 20 &&
|
||||
this.chunks[2] == OP_EQUAL);
|
||||
this.chunks[0] == OP_HASH160 &&
|
||||
Buffer.isBuffer(this.chunks[1]) &&
|
||||
this.chunks[1].length == 20 &&
|
||||
this.chunks[2] == OP_EQUAL);
|
||||
};
|
||||
|
||||
Script.prototype.isPubkey = function ()
|
||||
{
|
||||
return (this.chunks.length == 2 &&
|
||||
Buffer.isBuffer(this.chunks[0]) &&
|
||||
this.chunks[1] == OP_CHECKSIG);
|
||||
Buffer.isBuffer(this.chunks[0]) &&
|
||||
this.chunks[1] == OP_CHECKSIG);
|
||||
};
|
||||
|
||||
Script.prototype.isPubkeyHash = function ()
|
||||
{
|
||||
return (this.chunks.length == 5 &&
|
||||
this.chunks[0] == OP_DUP &&
|
||||
this.chunks[1] == OP_HASH160 &&
|
||||
Buffer.isBuffer(this.chunks[2]) &&
|
||||
this.chunks[2].length == 20 &&
|
||||
this.chunks[3] == OP_EQUALVERIFY &&
|
||||
this.chunks[4] == OP_CHECKSIG);
|
||||
this.chunks[0] == OP_DUP &&
|
||||
this.chunks[1] == OP_HASH160 &&
|
||||
Buffer.isBuffer(this.chunks[2]) &&
|
||||
this.chunks[2].length == 20 &&
|
||||
this.chunks[3] == OP_EQUALVERIFY &&
|
||||
this.chunks[4] == OP_CHECKSIG);
|
||||
};
|
||||
|
||||
function isSmallIntOp(opcode)
|
||||
{
|
||||
return ((opcode == OP_0) ||
|
||||
((opcode >= OP_1) && (opcode <= OP_16)));
|
||||
((opcode >= OP_1) && (opcode <= OP_16)));
|
||||
};
|
||||
|
||||
Script.prototype.isMultiSig = function ()
|
||||
{
|
||||
return (this.chunks.length > 3 &&
|
||||
isSmallIntOp(this.chunks[0]) &&
|
||||
isSmallIntOp(this.chunks[this.chunks.length-2]) &&
|
||||
this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG);
|
||||
isSmallIntOp(this.chunks[0]) &&
|
||||
isSmallIntOp(this.chunks[this.chunks.length-2]) &&
|
||||
this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG);
|
||||
};
|
||||
|
||||
Script.prototype.finishedMultiSig = function()
|
||||
|
@ -166,60 +166,60 @@ function spec(b) {
|
|||
// is this a script form we know?
|
||||
Script.prototype.classify = function ()
|
||||
{
|
||||
if (this.isPubkeyHash())
|
||||
return TX_PUBKEYHASH;
|
||||
if (this.isP2SH())
|
||||
return TX_SCRIPTHASH;
|
||||
if (this.isMultiSig())
|
||||
return TX_MULTISIG;
|
||||
if (this.isPubkey())
|
||||
return TX_PUBKEY;
|
||||
return TX_UNKNOWN;
|
||||
if (this.isPubkeyHash())
|
||||
return TX_PUBKEYHASH;
|
||||
if (this.isP2SH())
|
||||
return TX_SCRIPTHASH;
|
||||
if (this.isMultiSig())
|
||||
return TX_MULTISIG;
|
||||
if (this.isPubkey())
|
||||
return TX_PUBKEY;
|
||||
return TX_UNKNOWN;
|
||||
};
|
||||
|
||||
// extract useful data items from known scripts
|
||||
Script.prototype.capture = function ()
|
||||
{
|
||||
var txType = this.classify();
|
||||
var res = [];
|
||||
switch (txType) {
|
||||
case TX_PUBKEY:
|
||||
res.push(this.chunks[0]);
|
||||
break;
|
||||
case TX_PUBKEYHASH:
|
||||
res.push(this.chunks[2]);
|
||||
break;
|
||||
case TX_MULTISIG:
|
||||
for (var i = 1; i < (this.chunks.length - 2); i++)
|
||||
res.push(this.chunks[i]);
|
||||
break;
|
||||
case TX_SCRIPTHASH:
|
||||
res.push(this.chunks[1]);
|
||||
break;
|
||||
var txType = this.classify();
|
||||
var res = [];
|
||||
switch (txType) {
|
||||
case TX_PUBKEY:
|
||||
res.push(this.chunks[0]);
|
||||
break;
|
||||
case TX_PUBKEYHASH:
|
||||
res.push(this.chunks[2]);
|
||||
break;
|
||||
case TX_MULTISIG:
|
||||
for (var i = 1; i < (this.chunks.length - 2); i++)
|
||||
res.push(this.chunks[i]);
|
||||
break;
|
||||
case TX_SCRIPTHASH:
|
||||
res.push(this.chunks[1]);
|
||||
break;
|
||||
|
||||
case TX_UNKNOWN:
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
case TX_UNKNOWN:
|
||||
default:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
return res;
|
||||
};
|
||||
|
||||
// return first extracted data item from script
|
||||
Script.prototype.captureOne = function ()
|
||||
{
|
||||
var arr = this.capture();
|
||||
return arr[0];
|
||||
var arr = this.capture();
|
||||
return arr[0];
|
||||
};
|
||||
|
||||
Script.prototype.getOutType = function ()
|
||||
{
|
||||
var txType = this.classify();
|
||||
switch (txType) {
|
||||
case TX_PUBKEY: return 'Pubkey';
|
||||
case TX_PUBKEYHASH: return 'Address';
|
||||
default: return 'Strange';
|
||||
case TX_PUBKEY: return 'Pubkey';
|
||||
case TX_PUBKEYHASH: return 'Address';
|
||||
default: return 'Strange';
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -446,7 +446,7 @@ function spec(b) {
|
|||
var script = new Script();
|
||||
script.writeN(n_required);
|
||||
keys.forEach(function(key) {
|
||||
script.writeBytes(key);
|
||||
script.writeBytes(key);
|
||||
});
|
||||
script.writeN(keys.length);
|
||||
script.writeOp(OP_CHECKMULTISIG);
|
||||
|
|
|
@ -918,85 +918,85 @@ function spec(b) {
|
|||
};
|
||||
|
||||
function verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy)
|
||||
hashType, opts, callback, si, siCopy)
|
||||
{
|
||||
if (siCopy.stack.length == 0) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
if (siCopy.stack.length == 0) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, castBool(siCopy.stackBack()));
|
||||
callback(null, castBool(siCopy.stackBack()));
|
||||
}
|
||||
|
||||
function verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy)
|
||||
hashType, opts, callback, si, siCopy)
|
||||
{
|
||||
if (si.stack.length == 0) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
if (castBool(si.stackBack()) == false) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
if (si.stack.length == 0) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
if (castBool(si.stackBack()) == false) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// if not P2SH, we're done
|
||||
if (!opts.verifyP2SH || !scriptPubKey.isP2SH()) {
|
||||
callback(null, true);
|
||||
return;
|
||||
}
|
||||
// if not P2SH, we're done
|
||||
if (!opts.verifyP2SH || !scriptPubKey.isP2SH()) {
|
||||
callback(null, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scriptSig.isPushOnly()) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
if (!scriptSig.isPushOnly()) {
|
||||
callback(null, false);
|
||||
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;
|
||||
siCopy.eval(subscript, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
ok = true;
|
||||
siCopy.eval(subscript, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
}
|
||||
|
||||
function verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy)
|
||||
hashType, opts, callback, si, siCopy)
|
||||
{
|
||||
if (opts.verifyP2SH) {
|
||||
si.stack.forEach(function(item) {
|
||||
siCopy.stack.push(item);
|
||||
});
|
||||
}
|
||||
if (opts.verifyP2SH) {
|
||||
si.stack.forEach(function(item) {
|
||||
siCopy.stack.push(item);
|
||||
});
|
||||
}
|
||||
|
||||
si.eval(scriptPubKey, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
si.eval(scriptPubKey, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
}
|
||||
|
||||
ScriptInterpreter.verifyFull =
|
||||
function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType,
|
||||
opts, callback)
|
||||
opts, callback)
|
||||
{
|
||||
var si = new ScriptInterpreter();
|
||||
var siCopy = new ScriptInterpreter();
|
||||
var si = new ScriptInterpreter();
|
||||
var siCopy = new ScriptInterpreter();
|
||||
|
||||
si.eval(scriptSig, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
si.eval(scriptSig, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
};
|
||||
|
||||
var checkSig = ScriptInterpreter.checkSig =
|
||||
|
|
202
Sign.js
202
Sign.js
|
@ -1,133 +1,133 @@
|
|||
|
||||
function signOne(hash, addrStr, keys)
|
||||
{
|
||||
var keyObj = keys[addrStr];
|
||||
var rawPrivKey = new Buffer(keyObj.priv, 'hex');
|
||||
var key = new KeyModule.Key();
|
||||
key.private = rawPrivKey;
|
||||
var signature = key.signSync(hash);
|
||||
var keyObj = keys[addrStr];
|
||||
var rawPrivKey = new Buffer(keyObj.priv, 'hex');
|
||||
var key = new KeyModule.Key();
|
||||
key.private = rawPrivKey;
|
||||
var signature = key.signSync(hash);
|
||||
|
||||
return signature;
|
||||
return signature;
|
||||
}
|
||||
|
||||
function signTxIn(nIn, tx, txInputs, network, keys, scripts)
|
||||
{
|
||||
// locate TX input needing a signature
|
||||
var txin = tx.ins[nIn];
|
||||
var scriptSig = txin.getScript();
|
||||
// locate TX input needing a signature
|
||||
var txin = tx.ins[nIn];
|
||||
var scriptSig = txin.getScript();
|
||||
|
||||
// locate TX output, within txInputs
|
||||
var txoutHash = txin.getOutpointHash();
|
||||
if (!(txoutHash in txInputs))
|
||||
throw new Error("signTxIn missing input hash");
|
||||
var txFrom = txInputs[txoutHash];
|
||||
var txoutIndex = txin.getOutpointIndex();
|
||||
if (txFrom.outs.length >= txoutIndex)
|
||||
throw new Error("signTxIn missing input index");
|
||||
var txout = txFrom.outs[txoutIndex];
|
||||
var scriptPubKey = txout.getScript();
|
||||
// locate TX output, within txInputs
|
||||
var txoutHash = txin.getOutpointHash();
|
||||
if (!(txoutHash in txInputs))
|
||||
throw new Error("signTxIn missing input hash");
|
||||
var txFrom = txInputs[txoutHash];
|
||||
var txoutIndex = txin.getOutpointIndex();
|
||||
if (txFrom.outs.length >= txoutIndex)
|
||||
throw new Error("signTxIn missing input index");
|
||||
var txout = txFrom.outs[txoutIndex];
|
||||
var scriptPubKey = txout.getScript();
|
||||
|
||||
// detect type of transaction, and extract useful elements
|
||||
var txType = scriptPubKey.classify();
|
||||
if (txType == TX_UNKNOWN)
|
||||
throw new Error("unknown TX type");
|
||||
var scriptData = scriptPubKey.capture();
|
||||
// detect type of transaction, and extract useful elements
|
||||
var txType = scriptPubKey.classify();
|
||||
if (txType == TX_UNKNOWN)
|
||||
throw new Error("unknown TX type");
|
||||
var scriptData = scriptPubKey.capture();
|
||||
|
||||
// if P2SH, lookup the script
|
||||
var subscriptRaw = undefined;
|
||||
var subscript = undefined;
|
||||
var subType = undefined;
|
||||
var subData = undefined;
|
||||
if (txType == TX_SCRIPTHASH) {
|
||||
var addr = new Address(network.addressScript, scriptData[0]);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in scripts))
|
||||
throw new Error("unknown script hash address");
|
||||
// if P2SH, lookup the script
|
||||
var subscriptRaw = undefined;
|
||||
var subscript = undefined;
|
||||
var subType = undefined;
|
||||
var subData = undefined;
|
||||
if (txType == TX_SCRIPTHASH) {
|
||||
var addr = new Address(network.addressScript, scriptData[0]);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in scripts))
|
||||
throw new Error("unknown script hash address");
|
||||
|
||||
subscriptRaw = new Buffer(scripts[addrStr], 'hex');
|
||||
subscript = new Script(subscriptRaw);
|
||||
subType = subscript.classify();
|
||||
if (subType == TX_UNKNOWN)
|
||||
throw new Error("unknown subscript TX type");
|
||||
subData = subscript.capture();
|
||||
}
|
||||
subscriptRaw = new Buffer(scripts[addrStr], 'hex');
|
||||
subscript = new Script(subscriptRaw);
|
||||
subType = subscript.classify();
|
||||
if (subType == TX_UNKNOWN)
|
||||
throw new Error("unknown subscript TX type");
|
||||
subData = subscript.capture();
|
||||
}
|
||||
|
||||
var hash = tx.hashForSignature(scriptPubKey, i, 0);
|
||||
var hash = tx.hashForSignature(scriptPubKey, i, 0);
|
||||
|
||||
switch (txType) {
|
||||
case TX_PUBKEY:
|
||||
// already signed
|
||||
if (scriptSig.chunks.length > 0)
|
||||
return;
|
||||
switch (txType) {
|
||||
case TX_PUBKEY:
|
||||
// already signed
|
||||
if (scriptSig.chunks.length > 0)
|
||||
return;
|
||||
|
||||
var pubkeyhash = util.sha256ripe160(scriptData[0]);
|
||||
var addr = new Address(network.addressPubkey, pubkeyhash);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in keys))
|
||||
throw new Error("unknown pubkey");
|
||||
var pubkeyhash = util.sha256ripe160(scriptData[0]);
|
||||
var addr = new Address(network.addressPubkey, pubkeyhash);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in keys))
|
||||
throw new Error("unknown pubkey");
|
||||
|
||||
var signature = signOne(hash, addrStr, keys);
|
||||
scriptSig.writeBytes(signature);
|
||||
break;
|
||||
var signature = signOne(hash, addrStr, keys);
|
||||
scriptSig.writeBytes(signature);
|
||||
break;
|
||||
|
||||
case TX_PUBKEYHASH:
|
||||
// already signed
|
||||
if (scriptSig.chunks.length > 0)
|
||||
return;
|
||||
case TX_PUBKEYHASH:
|
||||
// already signed
|
||||
if (scriptSig.chunks.length > 0)
|
||||
return;
|
||||
|
||||
var addr = new Address(network.addressPubkey, scriptData[0]);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in keys))
|
||||
throw new Error("unknown pubkey hash address");
|
||||
var addr = new Address(network.addressPubkey, scriptData[0]);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in keys))
|
||||
throw new Error("unknown pubkey hash address");
|
||||
|
||||
var signature = signOne(hash, addrStr, keys);
|
||||
scriptSig.writeBytes(signature);
|
||||
scriptSig.writeBytes(key.public);
|
||||
break;
|
||||
var signature = signOne(hash, addrStr, keys);
|
||||
scriptSig.writeBytes(signature);
|
||||
scriptSig.writeBytes(key.public);
|
||||
break;
|
||||
|
||||
case TX_SCRIPTHASH:
|
||||
// already signed
|
||||
if (scriptSig.chunks.length > 0)
|
||||
return;
|
||||
case TX_SCRIPTHASH:
|
||||
// already signed
|
||||
if (scriptSig.chunks.length > 0)
|
||||
return;
|
||||
|
||||
var addr = new Address(network.addressPubkey, subData[0]);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in keys))
|
||||
throw new Error("unknown script(pubkey hash) address");
|
||||
var addr = new Address(network.addressPubkey, subData[0]);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in keys))
|
||||
throw new Error("unknown script(pubkey hash) address");
|
||||
|
||||
var signature = signOne(hash, addrStr, keys);
|
||||
scriptSig.writeBytes(signature);
|
||||
scriptSig.writeBytes(key.public);
|
||||
break;
|
||||
var signature = signOne(hash, addrStr, keys);
|
||||
scriptSig.writeBytes(signature);
|
||||
scriptSig.writeBytes(key.public);
|
||||
break;
|
||||
|
||||
case TX_MULTISIG:
|
||||
while (scriptSig.chunks.length < scriptData.length) {
|
||||
scriptSig.writeBytes(util.EMPTY_BUFFER);
|
||||
}
|
||||
for (var i = 0; i < scriptData.length; i++) {
|
||||
// skip already signed
|
||||
if (scriptSig.chunks[i].length > 0)
|
||||
continue;
|
||||
case TX_MULTISIG:
|
||||
while (scriptSig.chunks.length < scriptData.length) {
|
||||
scriptSig.writeBytes(util.EMPTY_BUFFER);
|
||||
}
|
||||
for (var i = 0; i < scriptData.length; i++) {
|
||||
// skip already signed
|
||||
if (scriptSig.chunks[i].length > 0)
|
||||
continue;
|
||||
|
||||
var pubkeyhash = util.sha256ripe160(scriptSig.chunks[i]);
|
||||
var addr = new Address(network.addressPubkey, pubkeyhash);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in keys))
|
||||
continue;
|
||||
var pubkeyhash = util.sha256ripe160(scriptSig.chunks[i]);
|
||||
var addr = new Address(network.addressPubkey, pubkeyhash);
|
||||
var addrStr = addr.toString();
|
||||
if (!(addrStr in keys))
|
||||
continue;
|
||||
|
||||
var signature = signOne(hash, addrStr, keys);
|
||||
scriptSig.chunks[i] = signature;
|
||||
}
|
||||
break;
|
||||
}
|
||||
var signature = signOne(hash, addrStr, keys);
|
||||
scriptSig.chunks[i] = signature;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (txtype == TX_SCRIPTHASH)
|
||||
scriptSig.writeBytes(subscriptRaw);
|
||||
if (txtype == TX_SCRIPTHASH)
|
||||
scriptSig.writeBytes(subscriptRaw);
|
||||
}
|
||||
|
||||
exports.Transaction = function Transaction(tx, txInputs, network, keys, scripts)
|
||||
{
|
||||
for (var i = 0; i < tx.ins.length; i++)
|
||||
signTxIn(i, tx, txInputs, network, keys, scripts);
|
||||
for (var i = 0; i < tx.ins.length; i++)
|
||||
signTxIn(i, tx, txInputs, network, keys, scripts);
|
||||
};
|
||||
|
||||
|
|
224
Wallet.js
224
Wallet.js
|
@ -2,141 +2,141 @@ require('classtool');
|
|||
var hex = function(hex) {return new Buffer(hex, 'hex');};
|
||||
|
||||
function ClassSpec(b) {
|
||||
var fs = require('fs');
|
||||
var EncFile = require('./util/EncFile');
|
||||
var Address = require('./Address').class();
|
||||
var networks = require('./networks');
|
||||
var util = b.util || require('./util/util');
|
||||
var ENC_METHOD = 'aes-256-cbc';
|
||||
var fs = require('fs');
|
||||
var EncFile = require('./util/EncFile');
|
||||
var Address = require('./Address').class();
|
||||
var networks = require('./networks');
|
||||
var util = b.util || require('./util/util');
|
||||
var ENC_METHOD = 'aes-256-cbc';
|
||||
|
||||
var skeleton = {
|
||||
client: 'libcoin',
|
||||
client_version: '0.0.1',
|
||||
network: 'testnet',
|
||||
version: 1,
|
||||
best_hash: null,
|
||||
best_height: -1,
|
||||
keys: [],
|
||||
sin: {},
|
||||
scripts: {},
|
||||
};
|
||||
var skeleton = {
|
||||
client: 'libcoin',
|
||||
client_version: '0.0.1',
|
||||
network: 'testnet',
|
||||
version: 1,
|
||||
best_hash: null,
|
||||
best_height: -1,
|
||||
keys: [],
|
||||
sin: {},
|
||||
scripts: {},
|
||||
};
|
||||
|
||||
function Wallet(cfg) {
|
||||
if (typeof cfg !== 'object')
|
||||
cfg = {};
|
||||
function Wallet(cfg) {
|
||||
if (typeof cfg !== 'object')
|
||||
cfg = {};
|
||||
|
||||
// deep copy (no references)
|
||||
if (cfg.datastore)
|
||||
this.datastore = JSON.parse(JSON.stringify(cfg.datastore));
|
||||
else
|
||||
this.datastore = JSON.parse(JSON.stringify(skeleton));
|
||||
// deep copy (no references)
|
||||
if (cfg.datastore)
|
||||
this.datastore = JSON.parse(JSON.stringify(cfg.datastore));
|
||||
else
|
||||
this.datastore = JSON.parse(JSON.stringify(skeleton));
|
||||
|
||||
this.network = undefined;
|
||||
this.dirty = cfg.dirty || true;
|
||||
};
|
||||
this.network = undefined;
|
||||
this.dirty = cfg.dirty || true;
|
||||
};
|
||||
|
||||
Wallet.prototype.readSync = function(filename, passphrase) {
|
||||
this.datastore = EncFile.readJFileSync(ENC_METHOD,
|
||||
passphrase, filename);
|
||||
this.dirty = false;
|
||||
};
|
||||
Wallet.prototype.readSync = function(filename, passphrase) {
|
||||
this.datastore = EncFile.readJFileSync(ENC_METHOD,
|
||||
passphrase, filename);
|
||||
this.dirty = false;
|
||||
};
|
||||
|
||||
Wallet.prototype.writeSync = function(filename, passphrase) {
|
||||
var tmp_fn = filename + ".tmp";
|
||||
Wallet.prototype.writeSync = function(filename, passphrase) {
|
||||
var tmp_fn = filename + ".tmp";
|
||||
|
||||
EncFile.writeJFileSync(ENC_METHOD, passphrase, tmp_fn,
|
||||
this.datastore);
|
||||
fs.renameSync(tmp_fn, filename);
|
||||
EncFile.writeJFileSync(ENC_METHOD, passphrase, tmp_fn,
|
||||
this.datastore);
|
||||
fs.renameSync(tmp_fn, filename);
|
||||
|
||||
this.dirty = false;
|
||||
};
|
||||
this.dirty = false;
|
||||
};
|
||||
|
||||
Wallet.prototype.setNetwork = function(netname) {
|
||||
if (!netname)
|
||||
netname = this.datastore.network;
|
||||
Wallet.prototype.setNetwork = function(netname) {
|
||||
if (!netname)
|
||||
netname = this.datastore.network;
|
||||
|
||||
switch (netname) {
|
||||
case "mainnet":
|
||||
case "livenet":
|
||||
this.network = networks.livenet;
|
||||
break;
|
||||
case "testnet":
|
||||
this.network = networks.testnet;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported network");
|
||||
}
|
||||
switch (netname) {
|
||||
case "mainnet":
|
||||
case "livenet":
|
||||
this.network = networks.livenet;
|
||||
break;
|
||||
case "testnet":
|
||||
this.network = networks.testnet;
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unsupported network");
|
||||
}
|
||||
|
||||
// store+canonicalize name
|
||||
this.datastore['network'] = this.network.name;
|
||||
this.dirty = true;
|
||||
};
|
||||
// store+canonicalize name
|
||||
this.datastore['network'] = this.network.name;
|
||||
this.dirty = true;
|
||||
};
|
||||
|
||||
Wallet.prototype.addKey = function(wkey) {
|
||||
this.datastore.keys.push(wkey);
|
||||
this.dirty = true;
|
||||
};
|
||||
Wallet.prototype.addKey = function(wkey) {
|
||||
this.datastore.keys.push(wkey);
|
||||
this.dirty = true;
|
||||
};
|
||||
|
||||
Wallet.prototype.addSIN = function(sinObj) {
|
||||
this.datastore.sin[sinObj.sin] = sinObj;
|
||||
this.dirty = true;
|
||||
};
|
||||
Wallet.prototype.addSIN = function(sinObj) {
|
||||
this.datastore.sin[sinObj.sin] = sinObj;
|
||||
this.dirty = true;
|
||||
};
|
||||
|
||||
Wallet.prototype.findKeyHash = function(pubKeyHash) {
|
||||
var pkhStr = pubKeyHash.toString();
|
||||
Wallet.prototype.findKeyHash = function(pubKeyHash) {
|
||||
var pkhStr = pubKeyHash.toString();
|
||||
|
||||
for (var i = 0; i < this.datastore.keys.length; i++) {
|
||||
var obj = this.datastore.keys[i];
|
||||
var addrStr = obj.addr;
|
||||
var addr = new Address(addrStr);
|
||||
if (addr.payload().toString() == pkhStr)
|
||||
return obj;
|
||||
}
|
||||
for (var i = 0; i < this.datastore.keys.length; i++) {
|
||||
var obj = this.datastore.keys[i];
|
||||
var addrStr = obj.addr;
|
||||
var addr = new Address(addrStr);
|
||||
if (addr.payload().toString() == pkhStr)
|
||||
return obj;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
};
|
||||
return undefined;
|
||||
};
|
||||
|
||||
Wallet.prototype.expandKey = function(key) {
|
||||
var addr = new Address(key);
|
||||
var isAddr = true;
|
||||
Wallet.prototype.expandKey = function(key) {
|
||||
var addr = new Address(key);
|
||||
var isAddr = true;
|
||||
|
||||
try {
|
||||
addr.validate();
|
||||
var b = addr.payload();
|
||||
var obj = this.findKeyHash(b);
|
||||
key = obj.pub;
|
||||
} catch(e) {
|
||||
// do nothing
|
||||
}
|
||||
try {
|
||||
addr.validate();
|
||||
var b = addr.payload();
|
||||
var obj = this.findKeyHash(b);
|
||||
key = obj.pub;
|
||||
} catch(e) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
var re = /^[a-fA-F0-9]+$/;
|
||||
if (!key.match(re))
|
||||
throw new Error("Unknown key type");
|
||||
return hex(key);
|
||||
};
|
||||
var re = /^[a-fA-F0-9]+$/;
|
||||
if (!key.match(re))
|
||||
throw new Error("Unknown key type");
|
||||
return hex(key);
|
||||
};
|
||||
|
||||
Wallet.prototype.expandKeys = function(keys) {
|
||||
var res = [];
|
||||
var us = this;
|
||||
keys.forEach(function(key) {
|
||||
var expKey = us.expandKey(key);
|
||||
res.push(expKey);
|
||||
});
|
||||
return res;
|
||||
};
|
||||
Wallet.prototype.expandKeys = function(keys) {
|
||||
var res = [];
|
||||
var us = this;
|
||||
keys.forEach(function(key) {
|
||||
var expKey = us.expandKey(key);
|
||||
res.push(expKey);
|
||||
});
|
||||
return res;
|
||||
};
|
||||
|
||||
Wallet.prototype.addScript = function(script) {
|
||||
var buf = script.getBuffer();
|
||||
var hash = util.sha256ripe160(buf);
|
||||
var addr = new Address(this.network.addressScript, hash);
|
||||
var addrStr = addr.as('base58');
|
||||
this.datastore.scripts[addrStr] = buf.toString('hex');
|
||||
this.dirty = true;
|
||||
Wallet.prototype.addScript = function(script) {
|
||||
var buf = script.getBuffer();
|
||||
var hash = util.sha256ripe160(buf);
|
||||
var addr = new Address(this.network.addressScript, hash);
|
||||
var addrStr = addr.as('base58');
|
||||
this.datastore.scripts[addrStr] = buf.toString('hex');
|
||||
this.dirty = true;
|
||||
|
||||
return addrStr;
|
||||
};
|
||||
return addrStr;
|
||||
};
|
||||
|
||||
return Wallet;
|
||||
return Wallet;
|
||||
};
|
||||
module.defineClass(ClassSpec);
|
||||
|
||||
|
|
84
WalletKey.js
84
WalletKey.js
|
@ -1,53 +1,53 @@
|
|||
require('classtool');
|
||||
|
||||
function ClassSpec(b) {
|
||||
var coinUtil = require('./util/util');
|
||||
var timeUtil = require('./util/time');
|
||||
var KeyModule = require('./Key');
|
||||
var PrivateKey = require('./PrivateKey').class();
|
||||
var Address = require('./Address').class();
|
||||
var coinUtil = require('./util/util');
|
||||
var timeUtil = require('./util/time');
|
||||
var KeyModule = require('./Key');
|
||||
var PrivateKey = require('./PrivateKey').class();
|
||||
var Address = require('./Address').class();
|
||||
|
||||
function WalletKey(cfg) {
|
||||
this.network = cfg.network; // required
|
||||
this.created = cfg.created;
|
||||
this.privKey = cfg.privKey;
|
||||
};
|
||||
function WalletKey(cfg) {
|
||||
this.network = cfg.network; // required
|
||||
this.created = cfg.created;
|
||||
this.privKey = cfg.privKey;
|
||||
};
|
||||
|
||||
WalletKey.prototype.generate = function() {
|
||||
this.privKey = KeyModule.Key.generateSync();
|
||||
this.created = timeUtil.curtime();
|
||||
};
|
||||
WalletKey.prototype.generate = function() {
|
||||
this.privKey = KeyModule.Key.generateSync();
|
||||
this.created = timeUtil.curtime();
|
||||
};
|
||||
|
||||
WalletKey.prototype.storeObj = function() {
|
||||
var pubKey = this.privKey.public.toString('hex');
|
||||
var pubKeyHash = coinUtil.sha256ripe160(this.privKey.public);
|
||||
var addr = new Address(this.network.addressPubkey, pubKeyHash);
|
||||
var priv = new PrivateKey(this.network.keySecret, this.privKey.private, this.privKey.compressed);
|
||||
var obj = {
|
||||
created: this.created,
|
||||
priv: priv.toString(),
|
||||
pub: pubKey,
|
||||
addr: addr.toString(),
|
||||
};
|
||||
WalletKey.prototype.storeObj = function() {
|
||||
var pubKey = this.privKey.public.toString('hex');
|
||||
var pubKeyHash = coinUtil.sha256ripe160(this.privKey.public);
|
||||
var addr = new Address(this.network.addressPubkey, pubKeyHash);
|
||||
var priv = new PrivateKey(this.network.keySecret, this.privKey.private, this.privKey.compressed);
|
||||
var obj = {
|
||||
created: this.created,
|
||||
priv: priv.toString(),
|
||||
pub: pubKey,
|
||||
addr: addr.toString(),
|
||||
};
|
||||
|
||||
return obj;
|
||||
};
|
||||
return obj;
|
||||
};
|
||||
|
||||
WalletKey.prototype.fromObj = function(obj) {
|
||||
this.created = obj.created;
|
||||
this.privKey = new KeyModule.Key();
|
||||
if (obj.priv.length==64) {
|
||||
this.privKey.private = new Buffer(obj.priv,'hex');
|
||||
this.privKey.compressed = true;
|
||||
}
|
||||
else {
|
||||
var priv = new PrivateKey(obj.priv);
|
||||
this.privKey.private = new Buffer(priv.payload());
|
||||
this.privKey.compressed = priv.compressed();
|
||||
}
|
||||
this.privKey.regenerateSync();
|
||||
};
|
||||
WalletKey.prototype.fromObj = function(obj) {
|
||||
this.created = obj.created;
|
||||
this.privKey = new KeyModule.Key();
|
||||
if (obj.priv.length==64) {
|
||||
this.privKey.private = new Buffer(obj.priv,'hex');
|
||||
this.privKey.compressed = true;
|
||||
}
|
||||
else {
|
||||
var priv = new PrivateKey(obj.priv);
|
||||
this.privKey.private = new Buffer(priv.payload());
|
||||
this.privKey.compressed = priv.compressed();
|
||||
}
|
||||
this.privKey.regenerateSync();
|
||||
};
|
||||
|
||||
return WalletKey;
|
||||
return WalletKey;
|
||||
};
|
||||
module.defineClass(ClassSpec);
|
||||
|
|
6
const.js
6
const.js
|
@ -1,8 +1,8 @@
|
|||
|
||||
MSG = {
|
||||
TX: 1,
|
||||
BLOCK: 2,
|
||||
FILTERED_BLOCK: 3,
|
||||
TX: 1,
|
||||
BLOCK: 2,
|
||||
FILTERED_BLOCK: 3,
|
||||
};
|
||||
|
||||
MSG.to_str = function(t) {
|
||||
|
|
138
test/basic.js
138
test/basic.js
|
@ -10,104 +10,104 @@ suite('basic');
|
|||
|
||||
function test_encode_priv(b58, payload, isTestnet, isCompressed)
|
||||
{
|
||||
var network = isTestnet ? networks.testnet : networks.livenet;
|
||||
var version = network.keySecret;
|
||||
var network = isTestnet ? networks.testnet : networks.livenet;
|
||||
var version = network.keySecret;
|
||||
|
||||
var buf_pl = new Buffer(payload, 'hex');
|
||||
var buf;
|
||||
if (isCompressed) {
|
||||
buf = new Buffer(buf_pl.length + 1);
|
||||
buf_pl.copy(buf);
|
||||
buf[buf_pl.length] = 1;
|
||||
} else
|
||||
buf = buf_pl;
|
||||
var buf_pl = new Buffer(payload, 'hex');
|
||||
var buf;
|
||||
if (isCompressed) {
|
||||
buf = new Buffer(buf_pl.length + 1);
|
||||
buf_pl.copy(buf);
|
||||
buf[buf_pl.length] = 1;
|
||||
} else
|
||||
buf = buf_pl;
|
||||
|
||||
var key = new KeyModule.Key();
|
||||
key.private = buf;
|
||||
key.compressed = isCompressed;
|
||||
var key = new KeyModule.Key();
|
||||
key.private = buf;
|
||||
key.compressed = isCompressed;
|
||||
|
||||
var privkey = new PrivateKey(version, buf);
|
||||
assert.equal(privkey.toString(), b58);
|
||||
var privkey = new PrivateKey(version, buf);
|
||||
assert.equal(privkey.toString(), b58);
|
||||
}
|
||||
|
||||
function test_encode_pub(b58, payload, isTestnet, addrType)
|
||||
{
|
||||
var isScript = (addrType == 'script');
|
||||
var network = isTestnet ? networks.testnet : networks.livenet;
|
||||
var version = isScript ? network.addressScript : network.addressPubkey;
|
||||
var buf = new Buffer(payload, 'hex');
|
||||
var addr = new Address(version, buf);
|
||||
assert.equal(addr.toString(), b58);
|
||||
var isScript = (addrType == 'script');
|
||||
var network = isTestnet ? networks.testnet : networks.livenet;
|
||||
var version = isScript ? network.addressScript : network.addressPubkey;
|
||||
var buf = new Buffer(payload, 'hex');
|
||||
var addr = new Address(version, buf);
|
||||
assert.equal(addr.toString(), b58);
|
||||
}
|
||||
|
||||
function test_decode_priv(b58, payload, isTestnet, isCompressed)
|
||||
{
|
||||
var network = isTestnet ? networks.testnet : networks.livenet;
|
||||
var version = network.keySecret;
|
||||
var network = isTestnet ? networks.testnet : networks.livenet;
|
||||
var version = network.keySecret;
|
||||
|
||||
var buf_pl = new Buffer(payload, 'hex');
|
||||
var buf;
|
||||
if (isCompressed) {
|
||||
buf = new Buffer(buf_pl.length + 1);
|
||||
buf_pl.copy(buf);
|
||||
buf[buf_pl.length] = 1;
|
||||
} else
|
||||
buf = buf_pl;
|
||||
var buf_pl = new Buffer(payload, 'hex');
|
||||
var buf;
|
||||
if (isCompressed) {
|
||||
buf = new Buffer(buf_pl.length + 1);
|
||||
buf_pl.copy(buf);
|
||||
buf[buf_pl.length] = 1;
|
||||
} else
|
||||
buf = buf_pl;
|
||||
|
||||
var privkey = new PrivateKey(b58);
|
||||
assert.equal(version, privkey.version());
|
||||
assert.equal(buf_pl.toString(), privkey.payload().toString());
|
||||
var privkey = new PrivateKey(b58);
|
||||
assert.equal(version, privkey.version());
|
||||
assert.equal(buf_pl.toString(), privkey.payload().toString());
|
||||
}
|
||||
|
||||
function test_decode_pub(b58, payload, isTestnet, addrType)
|
||||
{
|
||||
var isScript = (addrType == 'script');
|
||||
var network = isTestnet ? networks.testnet : networks.livenet;
|
||||
var version = isScript ? network.addressScript : network.addressPubkey;
|
||||
var buf = new Buffer(payload, 'hex');
|
||||
var addr = new Address(b58);
|
||||
var isScript = (addrType == 'script');
|
||||
var network = isTestnet ? networks.testnet : networks.livenet;
|
||||
var version = isScript ? network.addressScript : network.addressPubkey;
|
||||
var buf = new Buffer(payload, 'hex');
|
||||
var addr = new Address(b58);
|
||||
|
||||
assert.equal(version, addr.version());
|
||||
assert.equal(buf.toString(), addr.payload().toString());
|
||||
assert.equal(version, addr.version());
|
||||
assert.equal(buf.toString(), addr.payload().toString());
|
||||
}
|
||||
|
||||
function is_valid(datum)
|
||||
{
|
||||
var b58 = datum[0];
|
||||
var payload = datum[1];
|
||||
var obj = datum[2];
|
||||
var isPrivkey = obj['isPrivkey'];
|
||||
var isTestnet = obj['isTestnet'];
|
||||
var b58 = datum[0];
|
||||
var payload = datum[1];
|
||||
var obj = datum[2];
|
||||
var isPrivkey = obj['isPrivkey'];
|
||||
var isTestnet = obj['isTestnet'];
|
||||
|
||||
if (isPrivkey) {
|
||||
var isCompressed = obj['isCompressed'];
|
||||
test_encode_priv(b58, payload, isTestnet, isCompressed);
|
||||
test_decode_priv(b58, payload, isTestnet, isCompressed);
|
||||
} else {
|
||||
var addrType = obj['addrType'];
|
||||
test_encode_pub(b58, payload, isTestnet, addrType);
|
||||
test_decode_pub(b58, payload, isTestnet, addrType);
|
||||
}
|
||||
if (isPrivkey) {
|
||||
var isCompressed = obj['isCompressed'];
|
||||
test_encode_priv(b58, payload, isTestnet, isCompressed);
|
||||
test_decode_priv(b58, payload, isTestnet, isCompressed);
|
||||
} else {
|
||||
var addrType = obj['addrType'];
|
||||
test_encode_pub(b58, payload, isTestnet, addrType);
|
||||
test_decode_pub(b58, payload, isTestnet, addrType);
|
||||
}
|
||||
}
|
||||
|
||||
function is_invalid(datum)
|
||||
{
|
||||
if (datum.length < 1)
|
||||
throw new Error("Bad test");
|
||||
if (datum.length < 1)
|
||||
throw new Error("Bad test");
|
||||
|
||||
// ignore succeeding elements, as comments
|
||||
var b58 = datum[0];
|
||||
var privkey = new PrivateKey(b58);
|
||||
var addr = new Address(b58);
|
||||
// ignore succeeding elements, as comments
|
||||
var b58 = datum[0];
|
||||
var privkey = new PrivateKey(b58);
|
||||
var addr = new Address(b58);
|
||||
|
||||
var valid = true;
|
||||
try {
|
||||
privkey.validate();
|
||||
addr.validate();
|
||||
} catch(e) {
|
||||
valid = false;
|
||||
}
|
||||
assert.equal(valid, false);
|
||||
var valid = true;
|
||||
try {
|
||||
privkey.validate();
|
||||
addr.validate();
|
||||
} catch(e) {
|
||||
valid = false;
|
||||
}
|
||||
assert.equal(valid, false);
|
||||
}
|
||||
|
||||
var dataValid = JSON.parse(fs.readFileSync('test/base58_keys_valid.json'));
|
||||
|
|
|
@ -4,56 +4,56 @@ var crypto = require('crypto');
|
|||
|
||||
exports.readFileSync = function(enc_method, enc_passphrase, filename)
|
||||
{
|
||||
// read entire file into memory
|
||||
var fileData = fs.readFileSync(filename, 'binary');
|
||||
if (fileData.length < 32)
|
||||
throw new Error("Crypted file " + filename + " truncated");
|
||||
// read entire file into memory
|
||||
var fileData = fs.readFileSync(filename, 'binary');
|
||||
if (fileData.length < 32)
|
||||
throw new Error("Crypted file " + filename + " truncated");
|
||||
|
||||
// separate into data, hmac parts
|
||||
var fileCrypted = fileData.slice(0, -32);
|
||||
var fileHmac = fileData.slice(-32);
|
||||
// separate into data, hmac parts
|
||||
var fileCrypted = fileData.slice(0, -32);
|
||||
var fileHmac = fileData.slice(-32);
|
||||
|
||||
// generate and verify HMAC
|
||||
var hmac = crypto.createHmac('sha256', enc_passphrase);
|
||||
hmac.update(fileCrypted);
|
||||
var digest = hmac.digest('binary');
|
||||
// generate and verify HMAC
|
||||
var hmac = crypto.createHmac('sha256', enc_passphrase);
|
||||
hmac.update(fileCrypted);
|
||||
var digest = hmac.digest('binary');
|
||||
|
||||
if (digest.toString() != fileHmac.toString())
|
||||
throw new Error("Crypted file " + filename + " failed HMAC checksum verification");
|
||||
if (digest.toString() != fileHmac.toString())
|
||||
throw new Error("Crypted file " + filename + " failed HMAC checksum verification");
|
||||
|
||||
// decrypt to plaintext
|
||||
var decipher = crypto.createDecipher(enc_method, enc_passphrase);
|
||||
var dec = decipher.update(fileCrypted, 'binary', 'binary');
|
||||
dec += decipher.final('binary');
|
||||
return dec;
|
||||
// decrypt to plaintext
|
||||
var decipher = crypto.createDecipher(enc_method, enc_passphrase);
|
||||
var dec = decipher.update(fileCrypted, 'binary', 'binary');
|
||||
dec += decipher.final('binary');
|
||||
return dec;
|
||||
};
|
||||
|
||||
exports.readJFileSync = function(enc_method, enc_passphrase, filename)
|
||||
{
|
||||
var raw = this.readFileSync(enc_method, enc_passphrase, filename);
|
||||
return JSON.parse(raw);
|
||||
var raw = this.readFileSync(enc_method, enc_passphrase, filename);
|
||||
return JSON.parse(raw);
|
||||
};
|
||||
|
||||
exports.writeFileSync = function(enc_method, enc_passphrase, filename, data)
|
||||
{
|
||||
// encrypt to ciphertext
|
||||
var cipher = crypto.createCipher(enc_method, enc_passphrase);
|
||||
var crypted = cipher.update(data, 'binary', 'binary');
|
||||
crypted += cipher.final('binary');
|
||||
// encrypt to ciphertext
|
||||
var cipher = crypto.createCipher(enc_method, enc_passphrase);
|
||||
var crypted = cipher.update(data, 'binary', 'binary');
|
||||
crypted += cipher.final('binary');
|
||||
|
||||
// compute HMAC
|
||||
var hmac = crypto.createHmac('sha256', enc_passphrase);
|
||||
hmac.update(crypted);
|
||||
var digest = hmac.digest('binary');
|
||||
// compute HMAC
|
||||
var hmac = crypto.createHmac('sha256', enc_passphrase);
|
||||
hmac.update(crypted);
|
||||
var digest = hmac.digest('binary');
|
||||
|
||||
fs.writeFileSync(filename, crypted + digest, 'binary');
|
||||
fs.writeFileSync(filename, crypted + digest, 'binary');
|
||||
|
||||
return true;
|
||||
return true;
|
||||
};
|
||||
|
||||
exports.writeJFileSync = function(enc_method, enc_passphrase, filename, obj)
|
||||
{
|
||||
var raw = JSON.stringify(obj);
|
||||
return this.writeFileSync(enc_method, enc_passphrase, filename, raw);
|
||||
var raw = JSON.stringify(obj);
|
||||
return this.writeFileSync(enc_method, enc_passphrase, filename, raw);
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
// current time, in seconds
|
||||
exports.curtime = function curtime()
|
||||
{
|
||||
return Math.round(Date.now() / 1000);
|
||||
return Math.round(Date.now() / 1000);
|
||||
}
|
||||
|
||||
|
|
34
util/util.js
34
util/util.js
|
@ -113,42 +113,42 @@ var reWholeVal = /^\s*(\d+)/;
|
|||
|
||||
function padFrac(frac)
|
||||
{
|
||||
frac=frac.substr(0,8); //truncate to 8 decimal places
|
||||
while (frac.length < 8)
|
||||
frac = frac + '0';
|
||||
return frac;
|
||||
frac=frac.substr(0,8); //truncate to 8 decimal places
|
||||
while (frac.length < 8)
|
||||
frac = frac + '0';
|
||||
return frac;
|
||||
}
|
||||
|
||||
function parseFullValue(res)
|
||||
{
|
||||
return bignum(res[1]).mul('100000000').add(padFrac(res[2]));
|
||||
return bignum(res[1]).mul('100000000').add(padFrac(res[2]));
|
||||
}
|
||||
|
||||
function parseFracValue(res)
|
||||
{
|
||||
return bignum(padFrac(res[1]));
|
||||
return bignum(padFrac(res[1]));
|
||||
}
|
||||
|
||||
function parseWholeValue(res)
|
||||
{
|
||||
return bignum(res[1]).mul('100000000');
|
||||
return bignum(res[1]).mul('100000000');
|
||||
}
|
||||
|
||||
exports.parseValue = function parseValue(valueStr)
|
||||
{
|
||||
var res = valueStr.match(reFullVal);
|
||||
if (res)
|
||||
return parseFullValue(res);
|
||||
var res = valueStr.match(reFullVal);
|
||||
if (res)
|
||||
return parseFullValue(res);
|
||||
|
||||
res = valueStr.match(reFracVal);
|
||||
if (res)
|
||||
return parseFracValue(res);
|
||||
res = valueStr.match(reFracVal);
|
||||
if (res)
|
||||
return parseFracValue(res);
|
||||
|
||||
res = valueStr.match(reWholeVal);
|
||||
if (res)
|
||||
return parseWholeValue(res);
|
||||
res = valueStr.match(reWholeVal);
|
||||
if (res)
|
||||
return parseWholeValue(res);
|
||||
|
||||
return undefined;
|
||||
return undefined;
|
||||
};
|
||||
|
||||
// Utility that synchronizes function calls based on a key
|
||||
|
|
Loading…
Reference in New Issue