optimize sighashing. default values for every constructor.
This commit is contained in:
parent
05b83fe1c8
commit
b6ce94cec3
@ -39,8 +39,8 @@ function AbstractBlock(options) {
|
||||
return new AbstractBlock(options);
|
||||
|
||||
this.version = 1;
|
||||
this.prevBlock = null;
|
||||
this.merkleRoot = null;
|
||||
this.prevBlock = constants.NULL_HASH;
|
||||
this.merkleRoot = constants.NULL_HASH;
|
||||
this.ts = 0;
|
||||
this.bits = 0;
|
||||
this.nonce = 0;
|
||||
@ -80,16 +80,19 @@ AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
||||
this.ts = options.ts;
|
||||
this.bits = options.bits;
|
||||
this.nonce = options.nonce;
|
||||
this.totalTX = options.totalTX || 0;
|
||||
this.height = options.height != null ? options.height : -1;
|
||||
|
||||
this.txs = null;
|
||||
this.mutable = !!options.mutable;
|
||||
if (options.totalTX != null) {
|
||||
assert(utils.isNumber(options.totalTX));
|
||||
this.totalTX = options.totalTX;
|
||||
}
|
||||
|
||||
this._valid = null;
|
||||
this._hash = null;
|
||||
this._size = null;
|
||||
this._witnessSize = null;
|
||||
if (options.height != null) {
|
||||
assert(utils.isNumber(options.height));
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
if (options.mutable != null)
|
||||
this.mutable = !!options.mutable;
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -102,7 +105,6 @@ AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
||||
|
||||
AbstractBlock.prototype.parseJSON = function parseJSON(json) {
|
||||
assert(json, 'Block data is required.');
|
||||
assert(utils.isNumber(json.height));
|
||||
assert(utils.isNumber(json.version));
|
||||
assert(typeof json.prevBlock === 'string');
|
||||
assert(typeof json.merkleRoot === 'string');
|
||||
@ -110,8 +112,8 @@ AbstractBlock.prototype.parseJSON = function parseJSON(json) {
|
||||
assert(utils.isNumber(json.bits));
|
||||
assert(utils.isNumber(json.nonce));
|
||||
assert(utils.isNumber(json.totalTX));
|
||||
assert(utils.isNumber(json.height));
|
||||
|
||||
this.height = json.height;
|
||||
this.version = json.version;
|
||||
this.prevBlock = utils.revHex(json.prevBlock);
|
||||
this.merkleRoot = utils.revHex(json.merkleRoot);
|
||||
@ -119,6 +121,7 @@ AbstractBlock.prototype.parseJSON = function parseJSON(json) {
|
||||
this.bits = json.bits;
|
||||
this.nonce = json.nonce;
|
||||
this.totalTX = json.totalTX;
|
||||
this.height = json.height;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
var bcoin = require('./env');
|
||||
var networks = bcoin.protocol.network;
|
||||
var constants = bcoin.protocol.constants;
|
||||
var utils = require('./utils');
|
||||
var assert = utils.assert;
|
||||
var BufferWriter = require('./writer');
|
||||
@ -35,10 +36,10 @@ function Address(options) {
|
||||
if (!(this instanceof Address))
|
||||
return new Address(options);
|
||||
|
||||
this.hash = null;
|
||||
this.type = null;
|
||||
this.version = null;
|
||||
this.network = null;
|
||||
this.hash = constants.ZERO_HASH160;
|
||||
this.type = 'pubkeyhash';
|
||||
this.version = -1;
|
||||
this.network = bcoin.network.get().type;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
@ -51,13 +52,23 @@ function Address(options) {
|
||||
*/
|
||||
|
||||
Address.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options.hash);
|
||||
|
||||
this.hash = options.hash;
|
||||
this.type = options.type || 'pubkeyhash';
|
||||
this.version = options.version == null ? -1 : options.version;
|
||||
this.network = bcoin.network.get(options.network).type;
|
||||
|
||||
if (options.type)
|
||||
this.type = options.type;
|
||||
|
||||
if (options.version != null)
|
||||
this.version = options.version;
|
||||
|
||||
if (options.network)
|
||||
this.network = bcoin.network.get(options.network).type;
|
||||
|
||||
if (typeof this.hash === 'string')
|
||||
this.hash = new Buffer(this.hash, 'hex');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -49,12 +49,23 @@ CompactBlock.prototype._verify = function _verify(ret) {
|
||||
};
|
||||
|
||||
CompactBlock.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(bn.isBN(options.keyNonce));
|
||||
assert(Array.isArray(options.ids));
|
||||
assert(Array.isArray(options.ptx));
|
||||
|
||||
this.keyNonce = options.keyNonce;
|
||||
this.ids = options.ids || [];
|
||||
this.ptx = options.ptx || [];
|
||||
this.available = options.available || [];
|
||||
this.idMap = options.idMap || {};
|
||||
this.count = options.count || 0;
|
||||
this.ids = options.ids;
|
||||
this.ptx = options.ptx;
|
||||
|
||||
if (options.available)
|
||||
this.available = options.available;
|
||||
|
||||
if (options.idMap)
|
||||
this.idMap = options.idMap;
|
||||
|
||||
if (options.count)
|
||||
this.count = options.count;
|
||||
|
||||
this.k0 = options.k0;
|
||||
this.k1 = options.k1;
|
||||
|
||||
@ -358,7 +369,10 @@ function BlockTXRequest(options) {
|
||||
|
||||
BlockTXRequest.prototype.fromOptions = function fromOptions(options) {
|
||||
this.hash = options.hash;
|
||||
this.indexes = options.indexes || [];
|
||||
|
||||
if (options.indexes)
|
||||
this.indexes = options.indexes;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -452,7 +466,10 @@ function BlockTX(options) {
|
||||
|
||||
BlockTX.prototype.fromOptions = function fromOptions(options) {
|
||||
this.hash = options.hash;
|
||||
this.txs = options.txs || [];
|
||||
|
||||
if (options.txs)
|
||||
this.txs = options.txs;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
@ -27,11 +27,13 @@ function Block(options) {
|
||||
bcoin.abstractblock.call(this, options);
|
||||
|
||||
this.txs = [];
|
||||
|
||||
this._cbHeight = null;
|
||||
this._commitmentHash = null;
|
||||
|
||||
this._raw = null;
|
||||
this._size = null;
|
||||
this._witnessSize = null;
|
||||
this._size = -1;
|
||||
this._witnessSize = -1;
|
||||
this._lastWitnessSize = 0;
|
||||
|
||||
if (options)
|
||||
@ -49,15 +51,6 @@ utils.inherits(Block, bcoin.abstractblock);
|
||||
Block.prototype.fromOptions = function fromOptions(options) {
|
||||
var i;
|
||||
|
||||
this._cbHeight = null;
|
||||
this._commitmentHash = null;
|
||||
|
||||
this._raw = options._raw || null;
|
||||
this._size = options._size || null;
|
||||
this._witnessSize = options._witnessSize != null
|
||||
? options._witnessSize
|
||||
: null;
|
||||
|
||||
if (options.txs) {
|
||||
for (i = 0; i < options.txs.length; i++)
|
||||
this.addTX(options.txs[i]);
|
||||
@ -150,7 +143,7 @@ Block.prototype.getRaw = function getRaw() {
|
||||
Block.prototype.getSizes = function getSizes() {
|
||||
var writer;
|
||||
|
||||
if (this._size != null) {
|
||||
if (this._size !== -1) {
|
||||
return {
|
||||
size: this._size,
|
||||
witnessSize: this._witnessSize
|
||||
@ -224,7 +217,7 @@ Block.prototype.getBaseSize = function getBaseSize() {
|
||||
Block.prototype.hasWitness = function hasWitness() {
|
||||
var i;
|
||||
|
||||
if (this._witnessSize != null)
|
||||
if (this._witnessSize !== -1)
|
||||
return this._witnessSize !== 0;
|
||||
|
||||
for (i = 0; i < this.txs.length; i++) {
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
|
||||
var bcoin = require('./env');
|
||||
var utils = require('./utils');
|
||||
var constants = bcoin.protocol.constants;
|
||||
var assert = utils.assert;
|
||||
|
||||
/**
|
||||
@ -34,13 +35,13 @@ function Coin(options) {
|
||||
if (!(this instanceof Coin))
|
||||
return new Coin(options);
|
||||
|
||||
this.version = null;
|
||||
this.height = null;
|
||||
this.value = null;
|
||||
this.script = null;
|
||||
this.coinbase = null;
|
||||
this.hash = null;
|
||||
this.index = null;
|
||||
this.version = 1;
|
||||
this.height = -1;
|
||||
this.value = 0;
|
||||
this.script = new bcoin.script();
|
||||
this.coinbase = true;
|
||||
this.hash = constants.NULL_HASH;
|
||||
this.index = 0;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
@ -66,7 +67,10 @@ Coin.prototype.fromOptions = function fromOptions(options) {
|
||||
this.version = options.version;
|
||||
this.height = options.height;
|
||||
this.value = options.value;
|
||||
this.script = bcoin.script(options.script);
|
||||
|
||||
if (options.script)
|
||||
this.script.fromOptions(options.script);
|
||||
|
||||
this.coinbase = options.coinbase;
|
||||
this.hash = options.hash;
|
||||
this.index = options.index;
|
||||
@ -195,7 +199,7 @@ Coin.prototype.fromJSON = function fromJSON(json) {
|
||||
this.version = json.version;
|
||||
this.height = json.height;
|
||||
this.value = utils.satoshi(json.value);
|
||||
this.script = bcoin.script.fromJSON(json.script);
|
||||
this.script.fromJSON(json.script);
|
||||
this.coinbase = json.coinbase;
|
||||
this.hash = json.hash ? utils.revHex(json.hash) : null;
|
||||
this.index = json.index;
|
||||
@ -240,7 +244,7 @@ Coin.prototype.fromRaw = function fromRaw(data) {
|
||||
this.version = p.readU32();
|
||||
this.height = p.readU32();
|
||||
this.value = p.read64N();
|
||||
this.script = bcoin.script.fromRaw(p.readVarBytes());
|
||||
this.script.fromRaw(p.readVarBytes());
|
||||
this.coinbase = p.readU8() === 1;
|
||||
|
||||
if (this.height === 0x7fffffff)
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
var bcoin = require('./env');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.protocol.constants;
|
||||
var BufferReader = require('./reader');
|
||||
var BufferWriter = require('./writer');
|
||||
|
||||
@ -30,10 +31,10 @@ function Coins(options) {
|
||||
if (!(this instanceof Coins))
|
||||
return new Coins(options);
|
||||
|
||||
this.version = -1;
|
||||
this.hash = null;
|
||||
this.version = 1;
|
||||
this.hash = constants.NULL_HASH;
|
||||
this.height = -1;
|
||||
this.coinbase = false;
|
||||
this.coinbase = true;
|
||||
this.outputs = [];
|
||||
|
||||
if (options)
|
||||
@ -47,10 +48,17 @@ function Coins(options) {
|
||||
*/
|
||||
|
||||
Coins.prototype.fromOptions = function fromOptions(options) {
|
||||
this.version = options.version != null ? options.version : -1;
|
||||
this.hash = options.hash || null;
|
||||
this.height = options.height != null ? options.height : -1;
|
||||
this.coinbase = options.coinbase || false;
|
||||
if (options.version != null)
|
||||
this.version = options.version;
|
||||
|
||||
if (options.hash)
|
||||
this.hash = options.hash;
|
||||
|
||||
if (options.height != null)
|
||||
this.height = options.height;
|
||||
|
||||
if (options.coinbase != null)
|
||||
this.coinbase = options.coinbase;
|
||||
|
||||
if (options.outputs)
|
||||
this.outputs = options.outputs;
|
||||
@ -74,13 +82,16 @@ Coins.fromOptions = function fromOptions(options) {
|
||||
*/
|
||||
|
||||
Coins.prototype.add = function add(coin) {
|
||||
if (this.version === -1) {
|
||||
if (this.outputs.length === 0) {
|
||||
this.version = coin.version;
|
||||
this.hash = coin.hash;
|
||||
this.height = coin.height;
|
||||
this.coinbase = coin.coinbase;
|
||||
}
|
||||
|
||||
while (this.outputs.length <= coin.index)
|
||||
this.outputs.push(null);
|
||||
|
||||
if (coin.script.isUnspendable()) {
|
||||
this.outputs[coin.index] = null;
|
||||
return;
|
||||
|
||||
155
lib/bcoin/hd.js
155
lib/bcoin/hd.js
@ -91,6 +91,16 @@ var BufferWriter = require('./writer');
|
||||
var BufferReader = require('./reader');
|
||||
var unorm;
|
||||
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
|
||||
var PUBLIC_KEY = new Buffer(33);
|
||||
PUBLIC_KEY.fill(0);
|
||||
|
||||
var FINGER_PRINT = new Buffer(4);
|
||||
FINGER_PRINT.fill(0);
|
||||
|
||||
/**
|
||||
* HD Mnemonic
|
||||
* @exports Mnemonic
|
||||
@ -112,12 +122,6 @@ function Mnemonic(options) {
|
||||
if (!(this instanceof Mnemonic))
|
||||
return new Mnemonic(options);
|
||||
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
if (typeof options === 'string')
|
||||
options = { phrase: options };
|
||||
|
||||
this.bits = 128;
|
||||
this.entropy = null;
|
||||
this.phrase = null;
|
||||
@ -136,17 +140,21 @@ function Mnemonic(options) {
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.fromOptions = function fromOptions(options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
if (typeof options === 'string')
|
||||
options = { phrase: options };
|
||||
|
||||
this.bits = options.bits || 128;
|
||||
if (options.bits != null)
|
||||
this.bits = options.bits;
|
||||
|
||||
this.entropy = options.entropy;
|
||||
this.phrase = options.phrase;
|
||||
this.passphrase = options.passphrase || '';
|
||||
this.language = options.language || 'english';
|
||||
|
||||
if (options.passphrase)
|
||||
this.passphrase = options.passphrase;
|
||||
|
||||
if (options.language)
|
||||
this.language = options.language;
|
||||
|
||||
this.seed = options.seed;
|
||||
|
||||
assert(this.bits >= 128);
|
||||
@ -280,12 +288,27 @@ Mnemonic.prototype.toJSON = function toJSON() {
|
||||
*/
|
||||
|
||||
Mnemonic.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(utils.isNumber(json.bits));
|
||||
assert(!json.entropy || typeof json.entropy === 'string');
|
||||
assert(!json.phrase || typeof json.phrase === 'string');
|
||||
assert(typeof json.passphrase === 'string');
|
||||
assert(typeof json.language === 'string');
|
||||
assert(!json.seed || typeof json.seed === 'string');
|
||||
|
||||
this.bits = json.bits;
|
||||
this.entropy = new Buffer(json.entropy, 'hex');
|
||||
this.phrase = json.phrase;
|
||||
|
||||
if (json.entry)
|
||||
this.entropy = new Buffer(json.entropy, 'hex');
|
||||
|
||||
if (json.phrase)
|
||||
this.phrase = json.phrase;
|
||||
|
||||
this.passphrase = json.passphrase;
|
||||
this.language = json.language;
|
||||
this.seed = new Buffer(json.seed, 'hex');
|
||||
|
||||
if (json.seed)
|
||||
this.seed = new Buffer(json.seed, 'hex');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -308,11 +331,30 @@ Mnemonic.prototype.toRaw = function toRaw(writer) {
|
||||
var p = new BufferWriter(writer);
|
||||
|
||||
p.writeU16(this.bits);
|
||||
p.writeBytes(this.entropy);
|
||||
p.writeVarString(this.phrase, 'utf8');
|
||||
|
||||
if (this.entropy) {
|
||||
p.writeU8(1);
|
||||
p.writeBytes(this.entropy);
|
||||
} else {
|
||||
p.writeU8(0);
|
||||
}
|
||||
|
||||
if (this.phrase) {
|
||||
p.writeU8(1);
|
||||
p.writeVarString(this.phrase, 'utf8');
|
||||
} else {
|
||||
p.writeU8(0);
|
||||
}
|
||||
|
||||
p.writeVarString(this.passphrase, 'utf8');
|
||||
p.writeVarString(this.language, 'utf8');
|
||||
p.writeBytes(this.seed);
|
||||
|
||||
if (this.seed) {
|
||||
p.writeU8(1);
|
||||
p.writeBytes(this.seed);
|
||||
} else {
|
||||
p.writeU8(0);
|
||||
}
|
||||
|
||||
if (!writer)
|
||||
p = p.render();
|
||||
@ -328,12 +370,21 @@ Mnemonic.prototype.toRaw = function toRaw(writer) {
|
||||
|
||||
Mnemonic.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
|
||||
this.bits = p.readU16();
|
||||
this.entropy = p.readBytes(this.bits / 8);
|
||||
this.phrase = p.readVarString('utf8');
|
||||
|
||||
if (p.readU8() === 1)
|
||||
this.entropy = p.readBytes(this.bits / 8);
|
||||
|
||||
if (p.readU8() === 1)
|
||||
this.phrase = p.readVarString('utf8');
|
||||
|
||||
this.passphrase = p.readVarString('utf8');
|
||||
this.language = p.readVarString('utf8');
|
||||
this.seed = p.readBytes(64);
|
||||
|
||||
if (p.readU8() === 1)
|
||||
this.seed = p.readBytes(64);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -607,14 +658,14 @@ function HDPrivateKey(options) {
|
||||
if (!(this instanceof HDPrivateKey))
|
||||
return new HDPrivateKey(options);
|
||||
|
||||
this.network = null;
|
||||
this.depth = null;
|
||||
this.parentFingerPrint = null;
|
||||
this.childIndex = null;
|
||||
this.chainCode = null;
|
||||
this.privateKey = null;
|
||||
this.network = bcoin.network.get().type;
|
||||
this.depth = 0;
|
||||
this.parentFingerPrint = FINGER_PRINT;
|
||||
this.childIndex = 0;
|
||||
this.chainCode = constants.ZERO_HASH;
|
||||
this.privateKey = constants.ZERO_HASH;
|
||||
|
||||
this.publicKey = null;
|
||||
this.publicKey = PUBLIC_KEY;
|
||||
this.fingerPrint = null;
|
||||
|
||||
this.mnemonic = null;
|
||||
@ -638,9 +689,16 @@ utils.inherits(HDPrivateKey, HD);
|
||||
|
||||
HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'No options for HD private key.');
|
||||
assert(utils.isNumber(options.depth));
|
||||
assert(Buffer.isBuffer(options.parentFingerPrint));
|
||||
assert(utils.isNumber(options.childIndex));
|
||||
assert(Buffer.isBuffer(options.chainCode));
|
||||
assert(Buffer.isBuffer(options.privateKey));
|
||||
assert(options.depth <= 0xff, 'Depth is too high.');
|
||||
|
||||
this.network = bcoin.network.get(options.network).type;
|
||||
if (options.network)
|
||||
this.network = bcoin.network.get(options.network).type;
|
||||
|
||||
this.depth = options.depth;
|
||||
this.parentFingerPrint = options.parentFingerPrint;
|
||||
this.childIndex = options.childIndex;
|
||||
@ -649,8 +707,15 @@ HDPrivateKey.prototype.fromOptions = function fromOptions(options) {
|
||||
|
||||
this.publicKey = ec.publicKeyCreate(options.privateKey, true);
|
||||
|
||||
this.mnemonic = options.mnemonic || null;
|
||||
this._xprivkey = options.xprivkey || null;
|
||||
if (options.mnemonic) {
|
||||
assert(options.mnemonic instanceof Mnemonic);
|
||||
this.mnemonic = options.mnemonic;
|
||||
}
|
||||
|
||||
if (options.xprivkey) {
|
||||
assert(typeof options.xprivkey === 'string');
|
||||
this._xprivkey = options.xprivkey;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -1291,14 +1356,13 @@ function HDPublicKey(options) {
|
||||
if (!(this instanceof HDPublicKey))
|
||||
return new HDPublicKey(options);
|
||||
|
||||
this.network = null;
|
||||
this.depth = null;
|
||||
this.parentFingerPrint = null;
|
||||
this.childIndex = null;
|
||||
this.chainCode = null;
|
||||
this.publicKey = null;
|
||||
this.network = bcoin.network.get().type;
|
||||
this.depth = 0;
|
||||
this.parentFingerPrint = FINGER_PRINT;
|
||||
this.childIndex = 0;
|
||||
this.chainCode = constants.ZERO_HASH;
|
||||
this.publicKey = PUBLIC_KEY;
|
||||
|
||||
this.privateKey = null;
|
||||
this.fingerPrint = null;
|
||||
|
||||
this._xpubkey = null;
|
||||
@ -1320,16 +1384,25 @@ utils.inherits(HDPublicKey, HD);
|
||||
|
||||
HDPublicKey.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(options, 'No options for HDPublicKey');
|
||||
assert(options.depth <= 0xff, 'Depth is too high.');
|
||||
assert(utils.isNumber(options.depth));
|
||||
assert(Buffer.isBuffer(options.parentFingerPrint));
|
||||
assert(utils.isNumber(options.childIndex));
|
||||
assert(Buffer.isBuffer(options.chainCode));
|
||||
assert(Buffer.isBuffer(options.publicKey));
|
||||
|
||||
if (options.network)
|
||||
this.network = bcoin.network.get(options.network).type;
|
||||
|
||||
this.network = bcoin.network.get(options.network).type;
|
||||
this.depth = options.depth;
|
||||
this.parentFingerPrint = options.parentFingerPrint;
|
||||
this.childIndex = options.childIndex;
|
||||
this.chainCode = options.chainCode;
|
||||
this.publicKey = options.publicKey;
|
||||
|
||||
this._xpubkey = options.xpubkey;
|
||||
if (options.xpubkey) {
|
||||
assert(typeof options.xpubkey === 'string');
|
||||
this._xpubkey = options.xpubkey;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -26,8 +26,8 @@ function Outpoint(hash, index) {
|
||||
if (!(this instanceof Outpoint))
|
||||
return new Outpoint(hash, index);
|
||||
|
||||
this.hash = hash || null;
|
||||
this.index = index != null ? index : null;
|
||||
this.hash = hash || constants.NULL_HASH;
|
||||
this.index = index != null ? index : 0xffffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -200,10 +200,10 @@ function Input(options, mutable) {
|
||||
return new Input(options, mutable);
|
||||
|
||||
this.mutable = false;
|
||||
this.prevout = null;
|
||||
this.script = null;
|
||||
this.sequence = null;
|
||||
this.witness = null;
|
||||
this.prevout = new Outpoint();
|
||||
this.script = new bcoin.script();
|
||||
this.sequence = 0xffffffff;
|
||||
this.witness = new bcoin.witness();
|
||||
this.coin = null;
|
||||
|
||||
if (options)
|
||||
@ -219,14 +219,22 @@ function Input(options, mutable) {
|
||||
|
||||
Input.prototype.fromOptions = function fromOptions(options, mutable) {
|
||||
assert(options, 'Input data is required.');
|
||||
assert(options.sequence == null || utils.isNumber(options.sequence));
|
||||
|
||||
this.mutable = !!mutable;
|
||||
this.prevout = Outpoint.fromOptions(options.prevout);
|
||||
this.script = bcoin.script(options.script);
|
||||
this.sequence = options.sequence == null ? 0xffffffff : options.sequence;
|
||||
this.witness = bcoin.witness(options.witness);
|
||||
this.coin = null;
|
||||
|
||||
if (options.prevout)
|
||||
this.prevout.fromOptions(options.prevout);
|
||||
|
||||
if (options.script)
|
||||
this.script.fromOptions(options.script);
|
||||
|
||||
if (options.sequence != null) {
|
||||
assert(utils.isNumber(options.sequence));
|
||||
this.sequence = options.sequence;
|
||||
}
|
||||
|
||||
if (options.witness)
|
||||
this.witness.fromOptions(options.witness);
|
||||
|
||||
if (options.coin)
|
||||
this.coin = bcoin.coin(options.coin);
|
||||
@ -496,10 +504,10 @@ Input.prototype.toJSON = function toJSON() {
|
||||
Input.prototype.fromJSON = function fromJSON(json) {
|
||||
assert(json, 'Input data is required.');
|
||||
assert(utils.isNumber(json.sequence));
|
||||
this.prevout = Outpoint.fromJSON(json.prevout);
|
||||
this.prevout.fromJSON(json.prevout);
|
||||
this.coin = json.coin ? bcoin.coin.fromJSON(json.coin) : null;
|
||||
this.script = bcoin.script.fromJSON(json.script);
|
||||
this.witness = bcoin.witness.fromJSON(json.witness);
|
||||
this.script.fromJSON(json.script);
|
||||
this.witness.fromJSON(json.witness);
|
||||
this.sequence = json.sequence;
|
||||
return this;
|
||||
};
|
||||
@ -541,8 +549,8 @@ Input.prototype.toRaw = function toRaw(writer) {
|
||||
Input.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
|
||||
this.prevout = Outpoint.fromRaw(p);
|
||||
this.script = bcoin.script.fromRaw(p.readVarBytes());
|
||||
this.prevout.fromRaw(p);
|
||||
this.script.fromRaw(p.readVarBytes());
|
||||
this.sequence = p.readU32();
|
||||
|
||||
return this;
|
||||
@ -589,7 +597,7 @@ Input.prototype.toExtended = function toExtended(writer) {
|
||||
Input.prototype.fromExtended = function fromExtended(data) {
|
||||
var p = bcoin.reader(data);
|
||||
this.fromRaw(p);
|
||||
this.witness = bcoin.witness.fromRaw(p);
|
||||
this.witness.fromRaw(p);
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -616,10 +624,8 @@ Input.fromExtended = function fromExtended(data, enc) {
|
||||
Input.prototype.fromCoin = function fromCoin(coin) {
|
||||
assert(typeof coin.hash === 'string');
|
||||
assert(typeof coin.index === 'number');
|
||||
this.prevout = new Outpoint(coin.hash, coin.index);
|
||||
this.script = new bcoin.script();
|
||||
this.sequence = 0xffffffff;
|
||||
this.witness = new bcoin.witness();
|
||||
this.prevout.hash = coin.hash;
|
||||
this.prevout.index = coin.index;
|
||||
this.coin = coin;
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -29,10 +29,10 @@ function KeyPair(options) {
|
||||
if (!(this instanceof KeyPair))
|
||||
return new KeyPair(options);
|
||||
|
||||
this.network = null;
|
||||
this.network = bcoin.network.get().type;
|
||||
this.compressed = true;
|
||||
this.privateKey = null;
|
||||
this._publicKey = null;
|
||||
this.publicKey = null;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
@ -45,20 +45,24 @@ function KeyPair(options) {
|
||||
*/
|
||||
|
||||
KeyPair.prototype.fromOptions = function fromOptions(options) {
|
||||
if (!options)
|
||||
options = {};
|
||||
|
||||
this.compressed = options.compressed !== false;
|
||||
this.network = bcoin.network.get(options.network);
|
||||
|
||||
if (!options.privateKey && !options.publicKey)
|
||||
throw new Error('No options for keypair');
|
||||
|
||||
assert(options.privateKey || options.publicKey);
|
||||
assert(!options.privateKey || Buffer.isBuffer(options.privateKey));
|
||||
assert(!options.publicKey || Buffer.isBuffer(options.publicKey));
|
||||
|
||||
if (options.compressed != null)
|
||||
this.compressed = options.compressed;
|
||||
|
||||
if (options.network)
|
||||
this.network = bcoin.network.get(options.network);
|
||||
|
||||
this.privateKey = options.privateKey;
|
||||
this._publicKey = options.publicKey;
|
||||
this.publicKey = options.publicKey;
|
||||
|
||||
if (!this.publicKey) {
|
||||
this.publicKey = bcoin.ec.publicKeyCreate(
|
||||
this.privateKey, this.compressed
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -83,6 +87,7 @@ KeyPair.generate = function(network) {
|
||||
var key = new KeyPair();
|
||||
key.network = bcoin.network.get(network);
|
||||
key.privateKey = bcoin.ec.generatePrivateKey();
|
||||
key.publicKey = bcoin.ec.publicKeyCreate(key.privateKey, true);
|
||||
return key;
|
||||
};
|
||||
|
||||
@ -107,19 +112,6 @@ KeyPair.prototype.verify = function verify(msg, sig) {
|
||||
return bcoin.ec.verify(msg, sig, this.getPublicKey());
|
||||
};
|
||||
|
||||
KeyPair.prototype.__defineGetter__('publicKey', function() {
|
||||
if (!this._publicKey) {
|
||||
if (!this.privateKey)
|
||||
return;
|
||||
|
||||
this._publicKey = bcoin.ec.publicKeyCreate(
|
||||
this.privateKey, this.compressed
|
||||
);
|
||||
}
|
||||
|
||||
return this._publicKey;
|
||||
});
|
||||
|
||||
/**
|
||||
* Get private key.
|
||||
* @param {String?} enc - Can be `"hex"`, `"base58"`, or `null`.
|
||||
@ -220,10 +212,16 @@ KeyPair.prototype.fromRaw = function fromRaw(data) {
|
||||
if (p.left() > 4) {
|
||||
assert(p.readU8() === 1, 'Bad compression flag.');
|
||||
this.compressed = true;
|
||||
} else {
|
||||
this.compressed = false;
|
||||
}
|
||||
|
||||
p.verifyChecksum();
|
||||
|
||||
this.publicKey = bcoin.ec.publicKeyCreate(
|
||||
this.privateKey, this.compressed
|
||||
);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -312,7 +310,7 @@ KeyPair.fromJSON = function fromJSON(json) {
|
||||
|
||||
KeyPair.isKeyPair = function isKeyPair(obj) {
|
||||
return obj
|
||||
&& obj._privateKey !== undefined
|
||||
&& obj.privateKey !== undefined
|
||||
&& typeof obj.fromSecret === 'function';
|
||||
};
|
||||
|
||||
|
||||
@ -34,8 +34,8 @@ function KeyRing(options) {
|
||||
if (!(this instanceof KeyRing))
|
||||
return new KeyRing(options);
|
||||
|
||||
this.network = null;
|
||||
this.type = null;
|
||||
this.network = bcoin.network.get();
|
||||
this.type = 'pubkeyhash';
|
||||
this.m = 1;
|
||||
this.n = 1;
|
||||
this.witness = false;
|
||||
@ -71,18 +71,37 @@ function KeyRing(options) {
|
||||
KeyRing.prototype.fromOptions = function fromOptions(options) {
|
||||
var i;
|
||||
|
||||
this.network = bcoin.network.get(options.network);
|
||||
this.type = options.type || 'pubkeyhash';
|
||||
this.m = options.m || 1;
|
||||
this.n = options.n || 1;
|
||||
this.witness = options.witness || false;
|
||||
this.id = options.id;
|
||||
this.name = options.name;
|
||||
this.account = options.account;
|
||||
this.change = options.change;
|
||||
this.index = options.index;
|
||||
if (options.network)
|
||||
this.network = bcoin.network.get(options.network);
|
||||
|
||||
if (options.type)
|
||||
this.type = options.type;
|
||||
|
||||
if (options.m)
|
||||
this.m = options.m;
|
||||
|
||||
if (options.n)
|
||||
this.n = options.n;
|
||||
|
||||
if (options.witness != null)
|
||||
this.witness = options.witness;
|
||||
|
||||
if (options.id)
|
||||
this.id = options.id;
|
||||
|
||||
if (options.name)
|
||||
this.name = options.name;
|
||||
|
||||
if (options.account != null)
|
||||
this.account = options.account;
|
||||
|
||||
if (options.change != null)
|
||||
this.change = options.change;
|
||||
|
||||
if (options.index != null)
|
||||
this.index = options.index;
|
||||
|
||||
this.key = options.key;
|
||||
this.keys = [];
|
||||
|
||||
if (this.n > 1)
|
||||
this.type = 'multisig';
|
||||
|
||||
@ -29,25 +29,11 @@ var utils = require('./utils');
|
||||
* @exports MemBlock
|
||||
* @constructor
|
||||
* @param {NakedBlock} options
|
||||
* @param {Buffer} options.raw
|
||||
* @param {Number} options.coinbaseHeight
|
||||
* @property {Number} version - Block version. Note
|
||||
* that BCoin reads versions as unsigned despite
|
||||
* them being signed on the protocol level. This
|
||||
* number will never be negative.
|
||||
* @property {Hash} prevBlock - Previous block hash.
|
||||
* @property {Hash} merkleRoot - Merkle root hash.
|
||||
* @property {Number} ts - Timestamp.
|
||||
* @property {Number} bits
|
||||
* @property {Number} nonce
|
||||
* @property {Number} totalTX - Transaction count.
|
||||
* @property {Number} height - Block height (-1 if not present).
|
||||
* @property {Boolean} memory - Always true.
|
||||
* @property {Number} coinbaseHeight - The coinbase height which
|
||||
* was extracted by the parser (the coinbase is the only
|
||||
* transaction we parse ahead of time).
|
||||
* @property {Buffer} raw - The raw block data.
|
||||
* @property {ReversedHash} rhash - Reversed block hash (uint256le).
|
||||
*/
|
||||
|
||||
function MemBlock(options) {
|
||||
@ -57,7 +43,7 @@ function MemBlock(options) {
|
||||
bcoin.abstractblock.call(this, options);
|
||||
|
||||
this.memory = true;
|
||||
this.coinbaseHeight = null;
|
||||
this.coinbaseHeight = -1;
|
||||
this.raw = null;
|
||||
|
||||
if (options)
|
||||
@ -199,7 +185,7 @@ MemBlock.prototype.toBlock = function toBlock() {
|
||||
*/
|
||||
|
||||
MemBlock.isMemBlock = function isMemBlock(obj) {
|
||||
return obj && typeof obj.toBlock === 'function';
|
||||
return obj && obj.memory && typeof obj.toBlock === 'function';
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -1876,6 +1876,30 @@ function MempoolEntry(options) {
|
||||
if (!(this instanceof MempoolEntry))
|
||||
return new MempoolEntry(options);
|
||||
|
||||
this.tx = null;
|
||||
this.height = -1;
|
||||
this.size = 0;
|
||||
this.priority = 0;
|
||||
this.fee = 0;
|
||||
this.ts = 0;
|
||||
|
||||
this.chainValue = 0;
|
||||
this.count = 0;
|
||||
this.sizes = 0;
|
||||
this.fees = 0;
|
||||
this.dependencies = false;
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject properties from options object.
|
||||
* @private
|
||||
* @param {Object} options
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.fromOptions = function fromOptions(options) {
|
||||
this.tx = options.tx;
|
||||
this.height = options.height;
|
||||
this.size = options.size;
|
||||
@ -1888,16 +1912,28 @@ function MempoolEntry(options) {
|
||||
this.sizes = options.sizes;
|
||||
this.fees = options.fees;
|
||||
this.dependencies = options.dependencies;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a mempool entry from a TX.
|
||||
* @param {TX} tx
|
||||
* @param {Number} height - Entry height.
|
||||
* Instantiate mempool entry from options.
|
||||
* @param {Object} options
|
||||
* @returns {MempoolEntry}
|
||||
*/
|
||||
|
||||
MempoolEntry.fromTX = function fromTX(tx, height) {
|
||||
MempoolEntry.fromOptions = function fromOptions(options) {
|
||||
return new MempoolEntry().fromOptions(options);
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from transaction.
|
||||
* @private
|
||||
* @param {TX} tx
|
||||
* @param {Number} height
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.fromTX = function fromTX(tx, height) {
|
||||
var data = tx.getPriority(height);
|
||||
var dependencies = false;
|
||||
var size = tx.getVirtualSize();
|
||||
@ -1911,19 +1947,30 @@ MempoolEntry.fromTX = function fromTX(tx, height) {
|
||||
}
|
||||
}
|
||||
|
||||
return new MempoolEntry({
|
||||
tx: tx,
|
||||
height: height,
|
||||
size: size,
|
||||
priority: data.priority,
|
||||
fee: fee,
|
||||
chainValue: data.value,
|
||||
ts: utils.now(),
|
||||
count: 1,
|
||||
sizes: size,
|
||||
fees: fee,
|
||||
dependencies: dependencies
|
||||
});
|
||||
this.tx = tx;
|
||||
this.height = height;
|
||||
this.size = size;
|
||||
this.priority = data.priority;
|
||||
this.fee = fee;
|
||||
this.chainValue = data.value;
|
||||
this.ts = utils.now();
|
||||
this.count = 1;
|
||||
this.sizes = size;
|
||||
this.fees = fee;
|
||||
this.dependencies = dependencies;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a mempool entry from a TX.
|
||||
* @param {TX} tx
|
||||
* @param {Number} height - Entry height.
|
||||
* @returns {MempoolEntry}
|
||||
*/
|
||||
|
||||
MempoolEntry.fromTX = function fromTX(tx, height) {
|
||||
return new MempoolEntry().fromTX(tx, height);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1957,6 +2004,28 @@ MempoolEntry.prototype.toRaw = function toRaw(writer) {
|
||||
return p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Inject properties from serialized data.
|
||||
* @private
|
||||
* @param {Buffer} data
|
||||
*/
|
||||
|
||||
MempoolEntry.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
this.tx = bcoin.tx.fromRaw(p);
|
||||
this.height = p.readU32();
|
||||
this.size = p.readU32();
|
||||
this.priority = p.readDouble();
|
||||
this.fee = p.readVarint();
|
||||
this.chainValue = p.readVarint();
|
||||
this.ts = p.readU32();
|
||||
this.count = p.readU32();
|
||||
this.sizes = p.readU32();
|
||||
this.fees = p.readVarint();
|
||||
this.dependencies = p.readU8() === 1;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a mempool entry from serialized data.
|
||||
* @param {Buffer|BufferReader} data
|
||||
@ -1964,20 +2033,7 @@ MempoolEntry.prototype.toRaw = function toRaw(writer) {
|
||||
*/
|
||||
|
||||
MempoolEntry.fromRaw = function fromRaw(data) {
|
||||
var p = new BufferReader(data);
|
||||
return new MempoolEntry({
|
||||
tx: bcoin.tx.fromRaw(p),
|
||||
height: p.readU32(),
|
||||
size: p.readU32(),
|
||||
priority: p.readDouble(),
|
||||
fee: p.readVarint(),
|
||||
chainValue: p.readVarint(),
|
||||
ts: p.readU32(),
|
||||
count: p.readU32(),
|
||||
sizes: p.readU32(),
|
||||
fees: p.readVarint(),
|
||||
dependencies: p.readU8() === 1
|
||||
});
|
||||
return new MempoolEntry().fromRaw(data);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -11,6 +11,7 @@ var bcoin = require('./env');
|
||||
var utils = require('./utils');
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.protocol.constants;
|
||||
var DUMMY = new Buffer([0]);
|
||||
|
||||
/**
|
||||
* Represents a merkle (filtered) block.
|
||||
@ -26,8 +27,8 @@ function MerkleBlock(options) {
|
||||
|
||||
bcoin.abstractblock.call(this, options);
|
||||
|
||||
this.hashes = null;
|
||||
this.flags = null;
|
||||
this.hashes = [];
|
||||
this.flags = DUMMY;
|
||||
|
||||
// List of matched TXs
|
||||
this.map = {};
|
||||
@ -54,8 +55,11 @@ MerkleBlock.prototype.fromOptions = function fromOptions(options) {
|
||||
assert(Array.isArray(options.hashes));
|
||||
assert(Buffer.isBuffer(options.flags));
|
||||
|
||||
this.hashes = options.hashes;
|
||||
this.flags = options.flags;
|
||||
if (options.hashes)
|
||||
this.hashes = options.hashes;
|
||||
|
||||
if (options.flags)
|
||||
this.flags = options.flags;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -79,15 +79,17 @@ function MTX(options) {
|
||||
|
||||
this._hash = null;
|
||||
this._whash = null;
|
||||
|
||||
this._raw = null;
|
||||
this._size = null;
|
||||
this._witnessSize = null;
|
||||
this._outputValue = null;
|
||||
this._inputValue = null;
|
||||
this._size = -1;
|
||||
this._witnessSize = -1;
|
||||
this._lastWitnessSize = 0;
|
||||
|
||||
this._outputValue = -1;
|
||||
this._inputValue = -1;
|
||||
this._hashPrevouts = null;
|
||||
this._hashSequence = null;
|
||||
this._hashOutputs = null;
|
||||
this._lastWitnessSize = 0;
|
||||
|
||||
if (options.inputs) {
|
||||
for (i = 0; i < options.inputs.length; i++)
|
||||
|
||||
@ -30,8 +30,8 @@ function Output(options, mutable) {
|
||||
return new Output(options, mutable);
|
||||
|
||||
this.mutable = false;
|
||||
this.value = null;
|
||||
this.script = null;
|
||||
this.value = 0;
|
||||
this.script = new bcoin.script();
|
||||
|
||||
if (options)
|
||||
this.fromOptions(options, mutable);
|
||||
@ -51,7 +51,8 @@ Output.prototype.fromOptions = function fromOptions(options, mutable) {
|
||||
|
||||
this.mutable = !!mutable;
|
||||
this.value = options.value || 0;
|
||||
this.script = bcoin.script(options.script);
|
||||
if (options.script)
|
||||
this.script.fromOptions(options.script);
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -232,7 +233,7 @@ Output.prototype.isDust = function isDust(rate) {
|
||||
|
||||
Output.prototype.fromJSON = function fromJSON(json) {
|
||||
this.value = utils.satoshi(json.value);
|
||||
this.script = bcoin.script.fromJSON(json.script);
|
||||
this.script.fromJSON(json.script);
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -274,7 +275,7 @@ Output.prototype.fromRaw = function fromRaw(data) {
|
||||
var p = bcoin.reader(data);
|
||||
|
||||
this.value = p.read64N();
|
||||
this.script = bcoin.script.fromRaw(p.readVarBytes());
|
||||
this.script.fromRaw(p.readVarBytes());
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -611,6 +611,25 @@ exports.MAX_HASH = new Buffer(
|
||||
exports.NULL_HASH =
|
||||
'0000000000000000000000000000000000000000000000000000000000000000';
|
||||
|
||||
/**
|
||||
* A hash of all zeroes.
|
||||
* @const {Buffer}
|
||||
* @default
|
||||
*/
|
||||
|
||||
exports.ZERO_HASH160 = new Buffer(
|
||||
'0000000000000000000000000000000000000000',
|
||||
'hex'
|
||||
);
|
||||
|
||||
/**
|
||||
* A hash of all zeroes.
|
||||
* @const {String}
|
||||
* @default
|
||||
*/
|
||||
|
||||
exports.NULL_HASH160 = '0000000000000000000000000000000000000000';
|
||||
|
||||
/**
|
||||
* BCoin version.
|
||||
* @const {String}
|
||||
|
||||
@ -47,10 +47,10 @@ function VersionPacket(options) {
|
||||
|
||||
this.version = constants.VERSION;
|
||||
this.services = constants.LOCAL_SERVICES;
|
||||
this.ts = 0;
|
||||
this.recv = null;
|
||||
this.from = null;
|
||||
this.nonce = null;
|
||||
this.ts = bcoin.now();
|
||||
this.recv = new NetworkAddress();
|
||||
this.from = new NetworkAddress();
|
||||
this.nonce = new bn(0);
|
||||
this.agent = constants.USER_AGENT;
|
||||
this.height = 0;
|
||||
this.relay = true;
|
||||
@ -66,21 +66,33 @@ function VersionPacket(options) {
|
||||
*/
|
||||
|
||||
VersionPacket.prototype.fromOptions = function fromOptions(options) {
|
||||
this.version = options.version != null
|
||||
? options.version
|
||||
: constants.VERSION;
|
||||
this.services = options.services != null
|
||||
? options.services
|
||||
: constants.LOCAL_SERVICES;
|
||||
this.ts = options.ts != null
|
||||
? options.ts
|
||||
: bcoin.now();
|
||||
this.recv = options.recv || new NetworkAddress();
|
||||
this.from = options.from || new NetworkAddress();
|
||||
this.nonce = options.nonce || utils.nonce();
|
||||
this.agent = options.agent || constants.USER_AGENT;
|
||||
this.height = options.height || 0;
|
||||
this.relay = options.relay != null ? options.relay : true;
|
||||
if (options.version != null)
|
||||
this.version = options.version;
|
||||
|
||||
if (options.services != null)
|
||||
this.services = options.services;
|
||||
|
||||
if (options.ts != null)
|
||||
this.ts = options.ts;
|
||||
|
||||
if (options.recv)
|
||||
this.recv.fromOptions(options.recv);
|
||||
|
||||
if (options.from)
|
||||
this.from.fromOptions(options.from);
|
||||
|
||||
if (options.nonce)
|
||||
this.nonce = options.nonce;
|
||||
|
||||
if (options.agent)
|
||||
this.agent = options.agent;
|
||||
|
||||
if (options.height != null)
|
||||
this.height = options.height;
|
||||
|
||||
if (options.relay != null)
|
||||
this.relay = options.relay;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -176,30 +188,21 @@ VersionPacket.prototype.fromRaw = function fromRaw(data) {
|
||||
this.version = p.read32();
|
||||
this.services = p.readU53();
|
||||
this.ts = p.read53();
|
||||
this.recv = NetworkAddress.fromRaw(p, false);
|
||||
this.recv.fromRaw(p, false);
|
||||
|
||||
if (p.left() > 0) {
|
||||
this.from = NetworkAddress.fromRaw(p, false);
|
||||
this.from.fromRaw(p, false);
|
||||
this.nonce = p.readU64();
|
||||
} else {
|
||||
this.from = new NetworkAddress();
|
||||
this.nonce = new bn(0);
|
||||
}
|
||||
|
||||
if (p.left() > 0)
|
||||
this.agent = p.readVarString('ascii', 256);
|
||||
else
|
||||
this.agent = '';
|
||||
|
||||
if (p.left() > 0)
|
||||
this.height = p.read32();
|
||||
else
|
||||
this.height = 0;
|
||||
|
||||
if (p.left() > 0)
|
||||
this.relay = p.readU8() === 1;
|
||||
else
|
||||
this.relay = true;
|
||||
|
||||
if (this.version === 10300)
|
||||
this.version = 300;
|
||||
@ -393,19 +396,23 @@ GetBlocksPacket.fromRaw = function fromRaw(data, enc) {
|
||||
*/
|
||||
|
||||
function AlertPacket(options) {
|
||||
var time;
|
||||
|
||||
if (!(this instanceof AlertPacket))
|
||||
return new AlertPacket(options);
|
||||
|
||||
this.version = 0;
|
||||
this.relayUntil = 0;
|
||||
this.expiration = 0;
|
||||
this.id = 0;
|
||||
time = bcoin.now() + 7 * 86400;
|
||||
|
||||
this.version = 1;
|
||||
this.relayUntil = time;
|
||||
this.expiration = time;
|
||||
this.id = 1;
|
||||
this.cancel = 0;
|
||||
this.cancels = [];
|
||||
this.minVer = 0;
|
||||
this.minVer = 10000;
|
||||
this.maxVer = constants.VERSION;
|
||||
this.subVers = [];
|
||||
this.priority = 0;
|
||||
this.priority = 100;
|
||||
this.comment = '';
|
||||
this.statusBar = '';
|
||||
this.reserved = '';
|
||||
@ -425,21 +432,45 @@ function AlertPacket(options) {
|
||||
*/
|
||||
|
||||
AlertPacket.prototype.fromOptions = function fromOptions(options) {
|
||||
var time = bcoin.now() + 7 * 86400;
|
||||
if (options.version != null)
|
||||
this.version = options.version;
|
||||
|
||||
if (options.relayUntil != null)
|
||||
this.relayUntil = options.relayUntil;
|
||||
|
||||
if (options.expiration != null)
|
||||
this.expiration = options.expiration;
|
||||
|
||||
if (options.id != null)
|
||||
this.id = options.id;
|
||||
|
||||
if (options.cancel != null)
|
||||
this.cancel = options.cancel;
|
||||
|
||||
if (options.cancels)
|
||||
this.cancels = options.cancels;
|
||||
|
||||
if (options.minVer != null)
|
||||
this.minVer = options.minVer;
|
||||
|
||||
if (options.maxVer != null)
|
||||
this.maxVer = options.maxVer;
|
||||
|
||||
if (options.subVers)
|
||||
this.subVers = options.subVers;
|
||||
|
||||
if (options.priority != null)
|
||||
this.priority = options.priority;
|
||||
|
||||
if (options.comment != null)
|
||||
this.comment = options.comment;
|
||||
|
||||
if (options.statusBar != null)
|
||||
this.statusBar = options.statusBar;
|
||||
|
||||
if (options.reserved != null)
|
||||
this.reserved = options.reserved;
|
||||
|
||||
this.version = options.version != null ? options.version : 1;
|
||||
this.relayUntil = options.relayUntil != null ? options.relayUntil : time;
|
||||
this.expiration = options.expiration != null ? options.expiration : time;
|
||||
this.id = options.id != null ? options.id : 0;
|
||||
this.cancel = options.cancel != null ? options.cancel : 0;
|
||||
this.cancels = options.cancels || [];
|
||||
this.minVer = options.minVer != null ? options.minVer : 10000;
|
||||
this.maxVer = options.maxVer != null ? options.maxVer : constants.VERSION;
|
||||
this.subVers = options.subVers || [];
|
||||
this.priority = options.priority != null ? options.priority : 100;
|
||||
this.comment = options.comment || '';
|
||||
this.statusBar = options.statusBar || '';
|
||||
this.reserved = options.reserved || '';
|
||||
this.signature = options.signature;
|
||||
|
||||
return this;
|
||||
@ -639,19 +670,24 @@ function RejectPacket(options) {
|
||||
RejectPacket.prototype.fromOptions = function fromOptions(options) {
|
||||
var code = options.code;
|
||||
|
||||
if (typeof code === 'string')
|
||||
code = constants.reject[code.toUpperCase()];
|
||||
if (options.message)
|
||||
this.message = options.message;
|
||||
|
||||
if (!code)
|
||||
code = constants.reject.INVALID;
|
||||
if (code != null) {
|
||||
if (typeof code === 'string')
|
||||
code = constants.reject[code.toUpperCase()];
|
||||
|
||||
if (code >= constants.reject.INTERNAL)
|
||||
code = constants.reject.INVALID;
|
||||
if (code >= constants.reject.INTERNAL)
|
||||
code = constants.reject.INVALID;
|
||||
|
||||
this.message = options.message || '';
|
||||
this.code = code;
|
||||
this.reason = options.reason || '';
|
||||
this.data = options.data || null;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
if (options.reason)
|
||||
this.reason = options.reason;
|
||||
|
||||
if (options.data)
|
||||
this.data = options.data;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -3587,7 +3587,7 @@ Script.isHashType = function isHashType(sig) {
|
||||
|
||||
type = sig[sig.length - 1] & ~constants.hashType.ANYONECANPAY;
|
||||
|
||||
if (!constants.hashTypeByVal[type])
|
||||
if (!(type >= constants.hashType.ALL && type <= constants.hashType.SINGLE))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
219
lib/bcoin/tx.js
219
lib/bcoin/tx.js
@ -69,12 +69,12 @@ function TX(options) {
|
||||
this._whash = null;
|
||||
|
||||
this._raw = null;
|
||||
this._size = null;
|
||||
this._witnessSize = null;
|
||||
this._size = -1;
|
||||
this._witnessSize = -1;
|
||||
this._lastWitnessSize = 0;
|
||||
|
||||
this._outputValue = null;
|
||||
this._inputValue = null;
|
||||
this._outputValue = -1;
|
||||
this._inputValue = -1;
|
||||
this._hashPrevouts = null;
|
||||
this._hashSequence = null;
|
||||
this._hashOutputs = null;
|
||||
@ -93,42 +93,63 @@ TX.prototype.fromOptions = function fromOptions(options) {
|
||||
var i;
|
||||
|
||||
assert(options, 'TX data is required.');
|
||||
assert(utils.isNumber(options.version));
|
||||
assert(utils.isNumber(options.flag));
|
||||
assert(Array.isArray(options.inputs));
|
||||
assert(Array.isArray(options.outputs));
|
||||
assert(utils.isNumber(options.locktime));
|
||||
|
||||
this.version = options.version;
|
||||
this.flag = options.flag;
|
||||
if (options.version != null) {
|
||||
assert(utils.isNumber(options.version));
|
||||
this.version = options.version;
|
||||
}
|
||||
|
||||
for (i = 0; i < options.inputs.length; i++)
|
||||
this.inputs.push(new bcoin.input(options.inputs[i]));
|
||||
if (options.flag != null) {
|
||||
assert(utils.isNumber(options.flag));
|
||||
this.flag = options.flag;
|
||||
}
|
||||
|
||||
for (i = 0; i < options.outputs.length; i++)
|
||||
this.outputs.push(new bcoin.output(options.outputs[i]));
|
||||
if (options.inputs) {
|
||||
assert(Array.isArray(options.inputs));
|
||||
for (i = 0; i < options.inputs.length; i++)
|
||||
this.inputs.push(new bcoin.input(options.inputs[i]));
|
||||
}
|
||||
|
||||
this.locktime = options.locktime;
|
||||
if (options.outputs) {
|
||||
assert(Array.isArray(options.outputs));
|
||||
for (i = 0; i < options.outputs.length; i++)
|
||||
this.outputs.push(new bcoin.output(options.outputs[i]));
|
||||
}
|
||||
|
||||
this.ts = options.ts || 0;
|
||||
this.block = options.block || null;
|
||||
this.index = options.index != null
|
||||
? options.index
|
||||
: -1;
|
||||
this.ps = this.ts === 0
|
||||
? (options.ps != null ? options.ps : utils.now())
|
||||
: 0;
|
||||
this.height = options.height != null
|
||||
? options.height
|
||||
: -1;
|
||||
if (options.locktime != null) {
|
||||
assert(utils.isNumber(options.locktime));
|
||||
this.locktime = options.locktime;
|
||||
}
|
||||
|
||||
this._raw = options._raw || null;
|
||||
this._size = options._size != null
|
||||
? options._size
|
||||
: 0;
|
||||
this._witnessSize = options._witnessSize != null
|
||||
? options._witnessSize
|
||||
: null;
|
||||
if (options.ts != null)
|
||||
assert(utils.isNumber(options.locktime));
|
||||
this.ts = options.ts;
|
||||
|
||||
if (options.block !== undefined) {
|
||||
assert(options.block === null || typeof options.block === 'string');
|
||||
this.block = options.block;
|
||||
}
|
||||
|
||||
if (options.index != null) {
|
||||
assert(utils.isNumber(options.index));
|
||||
this.index = options.index;
|
||||
}
|
||||
|
||||
if (options.ps != null) {
|
||||
assert(utils.isNumber(options.ps));
|
||||
this.ps = this.ts === 0
|
||||
? options.ps
|
||||
: 0;
|
||||
}
|
||||
|
||||
if (options.height != null) {
|
||||
assert(utils.isNumber(options.height));
|
||||
this.height = options.height;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@ -416,7 +437,7 @@ TX.prototype.getBaseSize = function getBaseSize() {
|
||||
TX.prototype.hasWitness = function hasWitness() {
|
||||
var i;
|
||||
|
||||
if (this._witnessSize != null)
|
||||
if (this._witnessSize !== -1)
|
||||
return this._witnessSize !== 0;
|
||||
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
@ -459,10 +480,9 @@ TX.prototype.signatureHash = function signatureHash(index, prev, type, version)
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
|
||||
TX.prototype.signatureHashCopy = function signatureHashV0(index, prev, type) {
|
||||
var p = new BufferWriter();
|
||||
var empty = new Script();
|
||||
var witness = new bcoin.witness();
|
||||
var i, copy, input, output;
|
||||
|
||||
if (typeof index !== 'number')
|
||||
@ -484,7 +504,6 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
|
||||
input.prevout = this.inputs[i].prevout;
|
||||
input.script = this.inputs[i].script;
|
||||
input.sequence = this.inputs[i].sequence;
|
||||
input.witness = witness;
|
||||
copy.inputs.push(input);
|
||||
}
|
||||
|
||||
@ -553,6 +572,134 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
|
||||
return utils.hash256(p.render());
|
||||
};
|
||||
|
||||
/**
|
||||
* Legacy sighashing -- O(n^2).
|
||||
* Note: Optimized version. No
|
||||
* transaction copy necessary.
|
||||
* @private
|
||||
* @param {Number} index
|
||||
* @param {Script} prev
|
||||
* @param {SighashType} type
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
|
||||
TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
|
||||
var i, input, output;
|
||||
var p = new BufferWriter();
|
||||
var hashType;
|
||||
|
||||
if (typeof index !== 'number')
|
||||
index = this.inputs.indexOf(index);
|
||||
|
||||
if (typeof type === 'string')
|
||||
type = constants.hashType[type.toUpperCase()];
|
||||
|
||||
assert(index >= 0 && index < this.inputs.length);
|
||||
assert(prev instanceof Script);
|
||||
|
||||
// Get the unmasked hash type.
|
||||
hashType = type & 0x1f;
|
||||
|
||||
if (hashType === constants.hashType.SINGLE) {
|
||||
// Bitcoind used to return 1 as an error code:
|
||||
// it ended up being treated like a hash.
|
||||
if (index >= this.outputs.length)
|
||||
return utils.copy(constants.ONE_HASH);
|
||||
}
|
||||
|
||||
// Remove all code separators.
|
||||
prev = prev.removeSeparators();
|
||||
|
||||
p.write32(this.version);
|
||||
|
||||
if (type & constants.hashType.ANYONECANPAY) {
|
||||
p.writeVarint(1);
|
||||
|
||||
// Serialize only the current
|
||||
// input if ANYONECANPAY.
|
||||
input = this.inputs[index];
|
||||
|
||||
// Outpoint.
|
||||
p.writeHash(input.prevout.hash);
|
||||
p.writeU32(input.prevout.index);
|
||||
|
||||
// Replace script with previous
|
||||
// output script if current index.
|
||||
p.writeVarBytes(prev.toRaw());
|
||||
p.writeU32(input.sequence);
|
||||
} else {
|
||||
p.writeVarint(this.inputs.length);
|
||||
for (i = 0; i < this.inputs.length; i++) {
|
||||
input = this.inputs[i];
|
||||
|
||||
// Outpoint.
|
||||
p.writeHash(input.prevout.hash);
|
||||
p.writeU32(input.prevout.index);
|
||||
|
||||
// Replace script with previous
|
||||
// output script if current index.
|
||||
if (i === index) {
|
||||
p.writeVarBytes(prev.toRaw());
|
||||
p.writeU32(input.sequence);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Script is null.
|
||||
p.writeVarint(0);
|
||||
|
||||
// Sequences are 0 if NONE or SINGLE.
|
||||
if (hashType === constants.hashType.NONE
|
||||
|| hashType === constants.hashType.SINGLE) {
|
||||
p.writeU32(0);
|
||||
} else {
|
||||
p.writeU32(input.sequence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hashType === constants.hashType.NONE) {
|
||||
// No outputs if NONE.
|
||||
p.writeVarint(0);
|
||||
} else if (hashType === constants.hashType.SINGLE) {
|
||||
// Drop all outputs after the
|
||||
// current input index if SINGLE.
|
||||
p.writeVarint(index + 1);
|
||||
|
||||
for (i = 0; i < index + 1; i++) {
|
||||
output = this.outputs[i];
|
||||
|
||||
// Regular serialization if
|
||||
// at current input index.
|
||||
if (i === index) {
|
||||
p.write64(output.value);
|
||||
p.writeVarBytes(output.script.toRaw());
|
||||
continue;
|
||||
}
|
||||
|
||||
// Null all outputs not at
|
||||
// current input index.
|
||||
p.write64(-1);
|
||||
p.writeVarint(0);
|
||||
}
|
||||
} else {
|
||||
// Regular output serialization if ALL.
|
||||
p.writeVarint(this.outputs.length);
|
||||
|
||||
for (i = 0; i < this.outputs.length; i++) {
|
||||
output = this.outputs[i];
|
||||
p.write64(output.value);
|
||||
p.writeVarBytes(output.script.toRaw());
|
||||
}
|
||||
}
|
||||
|
||||
p.writeU32(this.locktime);
|
||||
|
||||
// Append the hash type.
|
||||
p.writeU32(type);
|
||||
|
||||
return utils.hash256(p.render());
|
||||
};
|
||||
|
||||
/**
|
||||
* Witness sighashing -- O(n).
|
||||
* @private
|
||||
@ -777,7 +924,7 @@ TX.prototype.getInputValue = function getInputValue() {
|
||||
var total = 0;
|
||||
var i;
|
||||
|
||||
if (this._inputValue != null)
|
||||
if (this._inputValue !== -1)
|
||||
return this._inputValue;
|
||||
|
||||
if (!this.hasCoins())
|
||||
@ -801,7 +948,7 @@ TX.prototype.getOutputValue = function getOutputValue() {
|
||||
var total = 0;
|
||||
var i;
|
||||
|
||||
if (this._outputValue != null)
|
||||
if (this._outputValue !== -1)
|
||||
return this._outputValue;
|
||||
|
||||
for (i = 0; i < this.outputs.length; i++)
|
||||
|
||||
@ -1677,7 +1677,7 @@ function WalletMap() {
|
||||
this.inputs = [];
|
||||
this.outputs = [];
|
||||
this.accounts = [];
|
||||
this.table = null;
|
||||
this.table = {};
|
||||
}
|
||||
|
||||
WalletMap.prototype.fromTX = function fromTX(table, tx) {
|
||||
|
||||
@ -1731,6 +1731,7 @@ utils.readVarint2 = function readVarint2(data, off, big) {
|
||||
}
|
||||
|
||||
if (bnum) {
|
||||
assert(bnum.bitLength() <= 256);
|
||||
bnum.iushln(7).iaddn(ch & 0x7f);
|
||||
if ((ch & 0x80) === 0)
|
||||
break;
|
||||
|
||||
@ -1565,15 +1565,15 @@ function Account(db, options) {
|
||||
|
||||
this.id = null;
|
||||
this.name = null;
|
||||
this.witness = false;
|
||||
this.witness = this.network.witness;
|
||||
this.accountKey = null;
|
||||
this.accountIndex = 0;
|
||||
this.receiveDepth = 0;
|
||||
this.changeDepth = 0;
|
||||
this.type = null;
|
||||
this.keys = [];
|
||||
this.type = 'pubkeyhash';
|
||||
this.m = 1;
|
||||
this.n = 1;
|
||||
this.keys = [];
|
||||
this.initialized = false;
|
||||
|
||||
if (options)
|
||||
@ -1598,18 +1598,32 @@ Account.prototype.fromOptions = function fromOptions(options) {
|
||||
|
||||
this.id = options.id;
|
||||
this.name = options.name;
|
||||
this.witness = options.witness != null
|
||||
? options.witness
|
||||
: this.network.witness;
|
||||
|
||||
if (options.witness != null)
|
||||
this.witness = options.witness;
|
||||
|
||||
this.accountKey = options.accountKey;
|
||||
this.accountIndex = options.accountIndex;
|
||||
this.receiveDepth = options.receiveDepth || 0;
|
||||
this.changeDepth = options.changeDepth || 0;
|
||||
this.type = options.type || 'pubkeyhash';
|
||||
this.keys = [];
|
||||
this.m = options.m || 1;
|
||||
this.n = options.n || 1;
|
||||
this.initialized = options.initialized || false;
|
||||
|
||||
if (options.accountIndex != null)
|
||||
this.accountIndex = options.accountIndex;
|
||||
|
||||
if (options.receiveDepth != null)
|
||||
this.receiveDepth = options.receiveDepth;
|
||||
|
||||
if (options.changeDepth != null)
|
||||
this.changeDepth = options.changeDepth;
|
||||
|
||||
if (options.type)
|
||||
this.type = options.type;
|
||||
|
||||
if (options.m)
|
||||
this.m = options.m;
|
||||
|
||||
if (options.n)
|
||||
this.n = options.n;
|
||||
|
||||
if (options.initialized != null)
|
||||
this.initialized = options.initialized;
|
||||
|
||||
if (this.n > 1)
|
||||
this.type = 'multisig';
|
||||
@ -1673,11 +1687,11 @@ Account.prototype.init = function init(callback) {
|
||||
return this.save(callback);
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
assert(this.receiveDepth === 0);
|
||||
assert(this.changeDepth === 0);
|
||||
|
||||
this.initialized = true;
|
||||
|
||||
this.setDepth(1, 1, callback);
|
||||
};
|
||||
|
||||
@ -2236,7 +2250,8 @@ Account.prototype.toJSON = function toJSON() {
|
||||
Account.prototype.fromJSON = function fromJSON(json) {
|
||||
var i;
|
||||
|
||||
this.network = bcoin.network.get(json.network);
|
||||
assert.equal(json.network, this.network.type);
|
||||
|
||||
this.id = json.id;
|
||||
this.name = json.name;
|
||||
this.initialized = json.initialized;
|
||||
|
||||
@ -344,23 +344,23 @@ describe('Script', function() {
|
||||
});
|
||||
if (nocache) {
|
||||
tx._raw = null;
|
||||
tx._size = null;
|
||||
tx._witnessSize = null;
|
||||
tx._size = -1;
|
||||
tx._witnessSize = -1;
|
||||
tx._lastWitnessSize = 0;
|
||||
tx._hash = null;
|
||||
tx._inputValue = null;
|
||||
tx._outputValue = null;
|
||||
tx._inputValue = -1;
|
||||
tx._outputValue = -1;
|
||||
tx._hashPrevouts = null;
|
||||
tx._hashSequence = null;
|
||||
tx._hashOutputs = null;
|
||||
|
||||
coin._raw = null;
|
||||
coin._size = null;
|
||||
coin._witnessSize = null;
|
||||
coin._size = -1;
|
||||
coin._witnessSize = -1;
|
||||
coin._lastWitnessSize = 0;
|
||||
coin._hash = null;
|
||||
coin._inputValue = null;
|
||||
coin._outputValue = null;
|
||||
coin._inputValue = -1;
|
||||
coin._outputValue = -1;
|
||||
coin._hashPrevouts = null;
|
||||
coin._hashSequence = null;
|
||||
coin._hashOutputs = null;
|
||||
|
||||
@ -48,12 +48,12 @@ function clearCache(tx, nocache) {
|
||||
}
|
||||
|
||||
tx._raw = null;
|
||||
tx._size = null;
|
||||
tx._witnessSize = null;
|
||||
tx._size = -1;
|
||||
tx._witnessSize = -1;
|
||||
tx._lastWitnessSize = 0;
|
||||
tx._hash = null;
|
||||
tx._inputValue = null;
|
||||
tx._outputValue = null;
|
||||
tx._inputValue = -1;
|
||||
tx._outputValue = -1;
|
||||
tx._hashPrevouts = null;
|
||||
tx._hashSequence = null;
|
||||
tx._hashOutputs = null;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user