primitives: classify primitives.
This commit is contained in:
parent
ca08d6d97e
commit
daa55a05bc
File diff suppressed because it is too large
Load Diff
@ -19,18 +19,15 @@ const InvItem = require('../primitives/invitem');
|
|||||||
const ZERO = new BN(0);
|
const ZERO = new BN(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Chain Entry
|
||||||
* Represents an entry in the chain. Unlike
|
* Represents an entry in the chain. Unlike
|
||||||
* other bitcoin fullnodes, we store the
|
* other bitcoin fullnodes, we store the
|
||||||
* chainwork _with_ the entry in order to
|
* chainwork _with_ the entry in order to
|
||||||
* avoid reading the entire chain index on
|
* avoid reading the entire chain index on
|
||||||
* boot and recalculating the chainworks.
|
* boot and recalculating the chainworks.
|
||||||
* @alias module:blockchain.ChainEntry
|
* @alias module:blockchain.ChainEntry
|
||||||
* @constructor
|
|
||||||
* @param {Object?} options
|
|
||||||
* @property {Hash} hash
|
* @property {Hash} hash
|
||||||
* @property {Number} version - Transaction version. Note that Bcoin reads
|
* @property {Number} version
|
||||||
* versions as unsigned even though they are signed at the protocol level.
|
|
||||||
* This value will never be negative.
|
|
||||||
* @property {Hash} prevBlock
|
* @property {Hash} prevBlock
|
||||||
* @property {Hash} merkleRoot
|
* @property {Hash} merkleRoot
|
||||||
* @property {Number} time
|
* @property {Number} time
|
||||||
@ -38,13 +35,17 @@ const ZERO = new BN(0);
|
|||||||
* @property {Number} nonce
|
* @property {Number} nonce
|
||||||
* @property {Number} height
|
* @property {Number} height
|
||||||
* @property {BN} chainwork
|
* @property {BN} chainwork
|
||||||
* @property {ReversedHash} rhash - Reversed block hash (uint256le).
|
* @property {ReversedHash} rhash
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function ChainEntry(options) {
|
class ChainEntry {
|
||||||
if (!(this instanceof ChainEntry))
|
/**
|
||||||
return new ChainEntry(options);
|
* Create a chain entry.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
this.hash = encoding.NULL_HASH;
|
this.hash = encoding.NULL_HASH;
|
||||||
this.version = 1;
|
this.version = 1;
|
||||||
this.prevBlock = encoding.NULL_HASH;
|
this.prevBlock = encoding.NULL_HASH;
|
||||||
@ -59,20 +60,13 @@ function ChainEntry(options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The max chainwork (1 << 256).
|
|
||||||
* @const {BN}
|
|
||||||
*/
|
|
||||||
|
|
||||||
ChainEntry.MAX_CHAINWORK = new BN(1).ushln(256);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options.
|
* Inject properties from options.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
assert(options, 'Block data is required.');
|
assert(options, 'Block data is required.');
|
||||||
assert(typeof options.hash === 'string');
|
assert(typeof options.hash === 'string');
|
||||||
assert((options.version >>> 0) === options.version);
|
assert((options.version >>> 0) === options.version);
|
||||||
@ -95,7 +89,7 @@ ChainEntry.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.chainwork = options.chainwork || ZERO;
|
this.chainwork = options.chainwork || ZERO;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate chainentry from options.
|
* Instantiate chainentry from options.
|
||||||
@ -104,23 +98,23 @@ ChainEntry.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {ChainEntry}
|
* @returns {ChainEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.fromOptions = function fromOptions(options, prev) {
|
static fromOptions(options, prev) {
|
||||||
return new ChainEntry().fromOptions(options, prev);
|
return new this().fromOptions(options, prev);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the proof: (1 << 256) / (target + 1)
|
* Calculate the proof: (1 << 256) / (target + 1)
|
||||||
* @returns {BN} proof
|
* @returns {BN} proof
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.getProof = function getProof() {
|
getProof() {
|
||||||
const target = consensus.fromCompact(this.bits);
|
const target = consensus.fromCompact(this.bits);
|
||||||
|
|
||||||
if (target.isNeg() || target.isZero())
|
if (target.isNeg() || target.isZero())
|
||||||
return new BN(0);
|
return new BN(0);
|
||||||
|
|
||||||
return ChainEntry.MAX_CHAINWORK.div(target.iaddn(1));
|
return ChainEntry.MAX_CHAINWORK.div(target.iaddn(1));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the chainwork by
|
* Calculate the chainwork by
|
||||||
@ -128,23 +122,23 @@ ChainEntry.prototype.getProof = function getProof() {
|
|||||||
* @returns {BN} chainwork
|
* @returns {BN} chainwork
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.getChainwork = function getChainwork(prev) {
|
getChainwork(prev) {
|
||||||
const proof = this.getProof();
|
const proof = this.getProof();
|
||||||
|
|
||||||
if (!prev)
|
if (!prev)
|
||||||
return proof;
|
return proof;
|
||||||
|
|
||||||
return proof.iadd(prev.chainwork);
|
return proof.iadd(prev.chainwork);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test against the genesis block.
|
* Test against the genesis block.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.isGenesis = function isGenesis() {
|
isGenesis() {
|
||||||
return this.height === 0;
|
return this.height === 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the entry contains an unknown version bit.
|
* Test whether the entry contains an unknown version bit.
|
||||||
@ -152,7 +146,7 @@ ChainEntry.prototype.isGenesis = function isGenesis() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.hasUnknown = function hasUnknown(network) {
|
hasUnknown(network) {
|
||||||
const TOP_MASK = consensus.VERSION_TOP_MASK;
|
const TOP_MASK = consensus.VERSION_TOP_MASK;
|
||||||
const TOP_BITS = consensus.VERSION_TOP_BITS;
|
const TOP_BITS = consensus.VERSION_TOP_BITS;
|
||||||
const bits = (this.version & TOP_MASK) >>> 0;
|
const bits = (this.version & TOP_MASK) >>> 0;
|
||||||
@ -161,7 +155,7 @@ ChainEntry.prototype.hasUnknown = function hasUnknown(network) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (this.version & network.unknownBits) !== 0;
|
return (this.version & network.unknownBits) !== 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the entry contains a version bit.
|
* Test whether the entry contains a version bit.
|
||||||
@ -169,18 +163,18 @@ ChainEntry.prototype.hasUnknown = function hasUnknown(network) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.hasBit = function hasBit(bit) {
|
hasBit(bit) {
|
||||||
return consensus.hasBit(this.version, bit);
|
return consensus.hasBit(this.version, bit);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get little-endian block hash.
|
* Get little-endian block hash.
|
||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.rhash = function rhash() {
|
rhash() {
|
||||||
return encoding.revHex(this.hash);
|
return encoding.revHex(this.hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from block.
|
* Inject properties from block.
|
||||||
@ -189,7 +183,7 @@ ChainEntry.prototype.rhash = function rhash() {
|
|||||||
* @param {ChainEntry} prev - Previous entry.
|
* @param {ChainEntry} prev - Previous entry.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.fromBlock = function fromBlock(block, prev) {
|
fromBlock(block, prev) {
|
||||||
this.hash = block.hash('hex');
|
this.hash = block.hash('hex');
|
||||||
this.version = block.version;
|
this.version = block.version;
|
||||||
this.prevBlock = block.prevBlock;
|
this.prevBlock = block.prevBlock;
|
||||||
@ -200,7 +194,7 @@ ChainEntry.prototype.fromBlock = function fromBlock(block, prev) {
|
|||||||
this.height = prev ? prev.height + 1: 0;
|
this.height = prev ? prev.height + 1: 0;
|
||||||
this.chainwork = this.getChainwork(prev);
|
this.chainwork = this.getChainwork(prev);
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate chainentry from block.
|
* Instantiate chainentry from block.
|
||||||
@ -209,16 +203,16 @@ ChainEntry.prototype.fromBlock = function fromBlock(block, prev) {
|
|||||||
* @returns {ChainEntry}
|
* @returns {ChainEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.fromBlock = function fromBlock(block, prev) {
|
static fromBlock(block, prev) {
|
||||||
return new ChainEntry().fromBlock(block, prev);
|
return new this().fromBlock(block, prev);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the entry to internal database format.
|
* Serialize the entry to internal database format.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const bw = new StaticWriter(116);
|
const bw = new StaticWriter(116);
|
||||||
|
|
||||||
bw.writeU32(this.version);
|
bw.writeU32(this.version);
|
||||||
@ -231,7 +225,7 @@ ChainEntry.prototype.toRaw = function toRaw() {
|
|||||||
bw.writeBytes(this.chainwork.toArrayLike(Buffer, 'le', 32));
|
bw.writeBytes(this.chainwork.toArrayLike(Buffer, 'le', 32));
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -239,7 +233,7 @@ ChainEntry.prototype.toRaw = function toRaw() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = new BufferReader(data, true);
|
const br = new BufferReader(data, true);
|
||||||
const hash = hash256.digest(br.readBytes(80));
|
const hash = hash256.digest(br.readBytes(80));
|
||||||
|
|
||||||
@ -256,7 +250,7 @@ ChainEntry.prototype.fromRaw = function fromRaw(data) {
|
|||||||
this.chainwork = new BN(br.readBytes(32), 'le');
|
this.chainwork = new BN(br.readBytes(32), 'le');
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize the entry.
|
* Deserialize the entry.
|
||||||
@ -264,9 +258,9 @@ ChainEntry.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {ChainEntry}
|
* @returns {ChainEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new ChainEntry().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the entry to an object more
|
* Serialize the entry to an object more
|
||||||
@ -274,7 +268,7 @@ ChainEntry.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return {
|
return {
|
||||||
hash: encoding.revHex(this.hash),
|
hash: encoding.revHex(this.hash),
|
||||||
version: this.version,
|
version: this.version,
|
||||||
@ -286,7 +280,7 @@ ChainEntry.prototype.toJSON = function toJSON() {
|
|||||||
height: this.height,
|
height: this.height,
|
||||||
chainwork: this.chainwork.toString('hex', 64)
|
chainwork: this.chainwork.toString('hex', 64)
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from json object.
|
* Inject properties from json object.
|
||||||
@ -294,7 +288,7 @@ ChainEntry.prototype.toJSON = function toJSON() {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert(json, 'Block data is required.');
|
assert(json, 'Block data is required.');
|
||||||
assert(typeof json.hash === 'string');
|
assert(typeof json.hash === 'string');
|
||||||
assert((json.version >>> 0) === json.version);
|
assert((json.version >>> 0) === json.version);
|
||||||
@ -316,7 +310,7 @@ ChainEntry.prototype.fromJSON = function fromJSON(json) {
|
|||||||
this.chainwork = new BN(json.chainwork, 'hex');
|
this.chainwork = new BN(json.chainwork, 'hex');
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate block from jsonified object.
|
* Instantiate block from jsonified object.
|
||||||
@ -324,38 +318,38 @@ ChainEntry.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {ChainEntry}
|
* @returns {ChainEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new ChainEntry().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the entry to a headers object.
|
* Convert the entry to a headers object.
|
||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.toHeaders = function toHeaders() {
|
toHeaders() {
|
||||||
return Headers.fromEntry(this);
|
return Headers.fromEntry(this);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the entry to an inv item.
|
* Convert the entry to an inv item.
|
||||||
* @returns {InvItem}
|
* @returns {InvItem}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.toInv = function toInv() {
|
toInv() {
|
||||||
return new InvItem(InvItem.types.BLOCK, this.hash);
|
return new InvItem(InvItem.types.BLOCK, this.hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a more user-friendly object.
|
* Return a more user-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
const json = this.toJSON();
|
const json = this.toJSON();
|
||||||
json.version = json.version.toString(16);
|
json.version = json.version.toString(16);
|
||||||
return json;
|
return json;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an object is a {@link ChainEntry}.
|
* Test whether an object is a {@link ChainEntry}.
|
||||||
@ -363,9 +357,17 @@ ChainEntry.prototype.inspect = function inspect() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ChainEntry.isChainEntry = function isChainEntry(obj) {
|
static isChainEntry(obj) {
|
||||||
return obj instanceof ChainEntry;
|
return obj instanceof ChainEntry;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The max chainwork (1 << 256).
|
||||||
|
* @const {BN}
|
||||||
|
*/
|
||||||
|
|
||||||
|
ChainEntry.MAX_CHAINWORK = new BN(1).ushln(256);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -22,9 +22,9 @@ const NUM_FLAGS = 1;
|
|||||||
const MAX_HEIGHT = ((1 << (32 - NUM_FLAGS)) >>> 0) - 1;
|
const MAX_HEIGHT = ((1 << (32 - NUM_FLAGS)) >>> 0) - 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Coin Entry
|
||||||
* Represents an unspent output.
|
* Represents an unspent output.
|
||||||
* @alias module:coins.CoinEntry
|
* @alias module:coins.CoinEntry
|
||||||
* @constructor
|
|
||||||
* @property {Number} version - Transaction version.
|
* @property {Number} version - Transaction version.
|
||||||
* @property {Number} height - Transaction height (-1 if unconfirmed).
|
* @property {Number} height - Transaction height (-1 if unconfirmed).
|
||||||
* @property {Boolean} coinbase - Whether the containing
|
* @property {Boolean} coinbase - Whether the containing
|
||||||
@ -34,10 +34,13 @@ const MAX_HEIGHT = ((1 << (32 - NUM_FLAGS)) >>> 0) - 1;
|
|||||||
* @property {Buffer} raw
|
* @property {Buffer} raw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function CoinEntry() {
|
class CoinEntry {
|
||||||
if (!(this instanceof CoinEntry))
|
/**
|
||||||
return new CoinEntry();
|
* Create a coin entry.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor() {
|
||||||
this.version = 1;
|
this.version = 1;
|
||||||
this.height = -1;
|
this.height = -1;
|
||||||
this.coinbase = false;
|
this.coinbase = false;
|
||||||
@ -51,9 +54,9 @@ function CoinEntry() {
|
|||||||
* @returns {Output}
|
* @returns {Output}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.toOutput = function toOutput() {
|
toOutput() {
|
||||||
return this.output;
|
return this.output;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert coin entry to a coin.
|
* Convert coin entry to a coin.
|
||||||
@ -61,7 +64,7 @@ CoinEntry.prototype.toOutput = function toOutput() {
|
|||||||
* @returns {Coin}
|
* @returns {Coin}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.toCoin = function toCoin(prevout) {
|
toCoin(prevout) {
|
||||||
const coin = new Coin();
|
const coin = new Coin();
|
||||||
coin.version = this.version;
|
coin.version = this.version;
|
||||||
coin.height = this.height;
|
coin.height = this.height;
|
||||||
@ -71,7 +74,7 @@ CoinEntry.prototype.toCoin = function toCoin(prevout) {
|
|||||||
coin.hash = prevout.hash;
|
coin.hash = prevout.hash;
|
||||||
coin.index = prevout.index;
|
coin.index = prevout.index;
|
||||||
return coin;
|
return coin;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from TX.
|
* Inject properties from TX.
|
||||||
@ -79,10 +82,10 @@ CoinEntry.prototype.toCoin = function toCoin(prevout) {
|
|||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.fromOutput = function fromOutput(output) {
|
fromOutput(output) {
|
||||||
this.output = output;
|
this.output = output;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coin from a TX
|
* Instantiate a coin from a TX
|
||||||
@ -91,9 +94,9 @@ CoinEntry.prototype.fromOutput = function fromOutput(output) {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.fromOutput = function fromOutput(output) {
|
static fromOutput(output) {
|
||||||
return new CoinEntry().fromOutput(output);
|
return new this().fromOutput(output);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from TX.
|
* Inject properties from TX.
|
||||||
@ -101,14 +104,14 @@ CoinEntry.fromOutput = function fromOutput(output) {
|
|||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.fromCoin = function fromCoin(coin) {
|
fromCoin(coin) {
|
||||||
this.version = coin.version;
|
this.version = coin.version;
|
||||||
this.height = coin.height;
|
this.height = coin.height;
|
||||||
this.coinbase = coin.coinbase;
|
this.coinbase = coin.coinbase;
|
||||||
this.output.script = coin.script;
|
this.output.script = coin.script;
|
||||||
this.output.value = coin.value;
|
this.output.value = coin.value;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coin from a TX
|
* Instantiate a coin from a TX
|
||||||
@ -117,9 +120,9 @@ CoinEntry.prototype.fromCoin = function fromCoin(coin) {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.fromCoin = function fromCoin(coin) {
|
static fromCoin(coin) {
|
||||||
return new CoinEntry().fromCoin(coin);
|
return new this().fromCoin(coin);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from TX.
|
* Inject properties from TX.
|
||||||
@ -127,7 +130,7 @@ CoinEntry.fromCoin = function fromCoin(coin) {
|
|||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.fromTX = function fromTX(tx, index, height) {
|
fromTX(tx, index, height) {
|
||||||
assert(typeof index === 'number');
|
assert(typeof index === 'number');
|
||||||
assert(typeof height === 'number');
|
assert(typeof height === 'number');
|
||||||
assert(index >= 0 && index < tx.outputs.length);
|
assert(index >= 0 && index < tx.outputs.length);
|
||||||
@ -136,7 +139,7 @@ CoinEntry.prototype.fromTX = function fromTX(tx, index, height) {
|
|||||||
this.coinbase = tx.isCoinbase();
|
this.coinbase = tx.isCoinbase();
|
||||||
this.output = tx.outputs[index];
|
this.output = tx.outputs[index];
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coin from a TX
|
* Instantiate a coin from a TX
|
||||||
@ -145,16 +148,16 @@ CoinEntry.prototype.fromTX = function fromTX(tx, index, height) {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.fromTX = function fromTX(tx, index, height) {
|
static fromTX(tx, index, height) {
|
||||||
return new CoinEntry().fromTX(tx, index, height);
|
return new this().fromTX(tx, index, height);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate size of coin.
|
* Calculate size of coin.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
if (this.raw)
|
if (this.raw)
|
||||||
return this.raw.length;
|
return this.raw.length;
|
||||||
|
|
||||||
@ -164,14 +167,14 @@ CoinEntry.prototype.getSize = function getSize() {
|
|||||||
size += compress.size(this.output);
|
size += compress.size(this.output);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the coin to a buffer writer.
|
* Write the coin to a buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
if (this.raw) {
|
if (this.raw) {
|
||||||
bw.writeBytes(this.raw);
|
bw.writeBytes(this.raw);
|
||||||
return bw;
|
return bw;
|
||||||
@ -193,14 +196,14 @@ CoinEntry.prototype.toWriter = function toWriter(bw) {
|
|||||||
compress.pack(this.output, bw);
|
compress.pack(this.output, bw);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the coin.
|
* Serialize the coin.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
if (this.raw)
|
if (this.raw)
|
||||||
return this.raw;
|
return this.raw;
|
||||||
|
|
||||||
@ -212,7 +215,7 @@ CoinEntry.prototype.toRaw = function toRaw() {
|
|||||||
this.raw = bw.render();
|
this.raw = bw.render();
|
||||||
|
|
||||||
return this.raw;
|
return this.raw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized buffer writer.
|
* Inject properties from serialized buffer writer.
|
||||||
@ -220,7 +223,7 @@ CoinEntry.prototype.toRaw = function toRaw() {
|
|||||||
* @param {BufferReader} br
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
const version = br.readVarint();
|
const version = br.readVarint();
|
||||||
const field = br.readU32();
|
const field = br.readU32();
|
||||||
|
|
||||||
@ -236,7 +239,7 @@ CoinEntry.prototype.fromReader = function fromReader(br) {
|
|||||||
compress.unpack(this.output, br);
|
compress.unpack(this.output, br);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coin from a serialized Buffer.
|
* Instantiate a coin from a serialized Buffer.
|
||||||
@ -244,9 +247,9 @@ CoinEntry.prototype.fromReader = function fromReader(br) {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.fromReader = function fromReader(data) {
|
static fromReader(data) {
|
||||||
return new CoinEntry().fromReader(data);
|
return new this().fromReader(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -254,11 +257,11 @@ CoinEntry.fromReader = function fromReader(data) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
this.fromReader(new BufferReader(data));
|
this.fromReader(new BufferReader(data));
|
||||||
this.raw = data;
|
this.raw = data;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coin from a serialized Buffer.
|
* Instantiate a coin from a serialized Buffer.
|
||||||
@ -266,9 +269,10 @@ CoinEntry.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinEntry.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new CoinEntry().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -10,16 +10,19 @@ const assert = require('assert');
|
|||||||
const CoinEntry = require('./coinentry');
|
const CoinEntry = require('./coinentry');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Coins
|
||||||
* Represents the outputs for a single transaction.
|
* Represents the outputs for a single transaction.
|
||||||
* @alias module:coins.Coins
|
* @alias module:coins.Coins
|
||||||
* @constructor
|
|
||||||
* @property {Map[]} outputs - Coins.
|
* @property {Map[]} outputs - Coins.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Coins() {
|
class Coins {
|
||||||
if (!(this instanceof Coins))
|
/**
|
||||||
return new Coins();
|
* Create coins.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor() {
|
||||||
this.outputs = new Map();
|
this.outputs = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,12 +33,12 @@ function Coins() {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.add = function add(index, coin) {
|
add(index, coin) {
|
||||||
assert((index >>> 0) === index);
|
assert((index >>> 0) === index);
|
||||||
assert(coin);
|
assert(coin);
|
||||||
this.outputs.set(index, coin);
|
this.outputs.set(index, coin);
|
||||||
return coin;
|
return coin;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single output to the collection.
|
* Add a single output to the collection.
|
||||||
@ -44,9 +47,9 @@ Coins.prototype.add = function add(index, coin) {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.addOutput = function addOutput(index, output) {
|
addOutput(index, output) {
|
||||||
return this.add(index, CoinEntry.fromOutput(output));
|
return this.add(index, CoinEntry.fromOutput(output));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an output to the collection by output index.
|
* Add an output to the collection by output index.
|
||||||
@ -56,9 +59,9 @@ Coins.prototype.addOutput = function addOutput(index, output) {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.addIndex = function addIndex(tx, index, height) {
|
addIndex(tx, index, height) {
|
||||||
return this.add(index, CoinEntry.fromTX(tx, index, height));
|
return this.add(index, CoinEntry.fromTX(tx, index, height));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a single coin to the collection.
|
* Add a single coin to the collection.
|
||||||
@ -66,9 +69,9 @@ Coins.prototype.addIndex = function addIndex(tx, index, height) {
|
|||||||
* @returns {CoinEntry}
|
* @returns {CoinEntry}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.addCoin = function addCoin(coin) {
|
addCoin(coin) {
|
||||||
return this.add(coin.index, CoinEntry.fromCoin(coin));
|
return this.add(coin.index, CoinEntry.fromCoin(coin));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the collection has a coin.
|
* Test whether the collection has a coin.
|
||||||
@ -76,9 +79,9 @@ Coins.prototype.addCoin = function addCoin(coin) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.has = function has(index) {
|
has(index) {
|
||||||
return this.outputs.has(index);
|
return this.outputs.has(index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the collection has an unspent coin.
|
* Test whether the collection has an unspent coin.
|
||||||
@ -86,14 +89,14 @@ Coins.prototype.has = function has(index) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.isUnspent = function isUnspent(index) {
|
isUnspent(index) {
|
||||||
const coin = this.outputs.get(index);
|
const coin = this.outputs.get(index);
|
||||||
|
|
||||||
if (!coin || coin.spent)
|
if (!coin || coin.spent)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a coin entry.
|
* Get a coin entry.
|
||||||
@ -101,9 +104,9 @@ Coins.prototype.isUnspent = function isUnspent(index) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.get = function get(index) {
|
get(index) {
|
||||||
return this.outputs.get(index) || null;
|
return this.outputs.get(index) || null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an output.
|
* Get an output.
|
||||||
@ -111,14 +114,14 @@ Coins.prototype.get = function get(index) {
|
|||||||
* @returns {Output|null}
|
* @returns {Output|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.getOutput = function getOutput(index) {
|
getOutput(index) {
|
||||||
const coin = this.outputs.get(index);
|
const coin = this.outputs.get(index);
|
||||||
|
|
||||||
if (!coin)
|
if (!coin)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return coin.output;
|
return coin.output;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a coin.
|
* Get a coin.
|
||||||
@ -126,14 +129,14 @@ Coins.prototype.getOutput = function getOutput(index) {
|
|||||||
* @returns {Coin|null}
|
* @returns {Coin|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.getCoin = function getCoin(prevout) {
|
getCoin(prevout) {
|
||||||
const coin = this.outputs.get(prevout.index);
|
const coin = this.outputs.get(prevout.index);
|
||||||
|
|
||||||
if (!coin)
|
if (!coin)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return coin.toCoin(prevout);
|
return coin.toCoin(prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spend a coin entry and return it.
|
* Spend a coin entry and return it.
|
||||||
@ -141,7 +144,7 @@ Coins.prototype.getCoin = function getCoin(prevout) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.spend = function spend(index) {
|
spend(index) {
|
||||||
const coin = this.get(index);
|
const coin = this.get(index);
|
||||||
|
|
||||||
if (!coin || coin.spent)
|
if (!coin || coin.spent)
|
||||||
@ -150,7 +153,7 @@ Coins.prototype.spend = function spend(index) {
|
|||||||
coin.spent = true;
|
coin.spent = true;
|
||||||
|
|
||||||
return coin;
|
return coin;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a coin entry and return it.
|
* Remove a coin entry and return it.
|
||||||
@ -158,7 +161,7 @@ Coins.prototype.spend = function spend(index) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.remove = function remove(index) {
|
remove(index) {
|
||||||
const coin = this.get(index);
|
const coin = this.get(index);
|
||||||
|
|
||||||
if (!coin)
|
if (!coin)
|
||||||
@ -167,16 +170,16 @@ Coins.prototype.remove = function remove(index) {
|
|||||||
this.outputs.delete(index);
|
this.outputs.delete(index);
|
||||||
|
|
||||||
return coin;
|
return coin;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the coins are fully spent.
|
* Test whether the coins are fully spent.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.isEmpty = function isEmpty() {
|
isEmpty() {
|
||||||
return this.outputs.size === 0;
|
return this.outputs.size === 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from tx.
|
* Inject properties from tx.
|
||||||
@ -186,7 +189,7 @@ Coins.prototype.isEmpty = function isEmpty() {
|
|||||||
* @returns {Coins}
|
* @returns {Coins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.prototype.fromTX = function fromTX(tx, height) {
|
fromTX(tx, height) {
|
||||||
assert(typeof height === 'number');
|
assert(typeof height === 'number');
|
||||||
|
|
||||||
for (let i = 0; i < tx.outputs.length; i++) {
|
for (let i = 0; i < tx.outputs.length; i++) {
|
||||||
@ -201,7 +204,7 @@ Coins.prototype.fromTX = function fromTX(tx, height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coins object from a transaction.
|
* Instantiate a coins object from a transaction.
|
||||||
@ -210,9 +213,10 @@ Coins.prototype.fromTX = function fromTX(tx, height) {
|
|||||||
* @returns {Coins}
|
* @returns {Coins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coins.fromTX = function fromTX(tx, height) {
|
static fromTX(tx, height) {
|
||||||
return new Coins().fromTX(tx, height);
|
return new this().fromTX(tx, height);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -11,18 +11,21 @@ const UndoCoins = require('./undocoins');
|
|||||||
const CoinEntry = require('./coinentry');
|
const CoinEntry = require('./coinentry');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Coin View
|
||||||
* Represents a coin viewpoint:
|
* Represents a coin viewpoint:
|
||||||
* a snapshot of {@link Coins} objects.
|
* a snapshot of {@link Coins} objects.
|
||||||
* @alias module:coins.CoinView
|
* @alias module:coins.CoinView
|
||||||
* @constructor
|
|
||||||
* @property {Object} map
|
* @property {Object} map
|
||||||
* @property {UndoCoins} undo
|
* @property {UndoCoins} undo
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function CoinView() {
|
class CoinView {
|
||||||
if (!(this instanceof CoinView))
|
/**
|
||||||
return new CoinView();
|
* Create a coin view.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor() {
|
||||||
this.map = new Map();
|
this.map = new Map();
|
||||||
this.undo = new UndoCoins();
|
this.undo = new UndoCoins();
|
||||||
}
|
}
|
||||||
@ -33,9 +36,9 @@ function CoinView() {
|
|||||||
* @returns {Coins} coins
|
* @returns {Coins} coins
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.get = function get(hash) {
|
get(hash) {
|
||||||
return this.map.get(hash);
|
return this.map.get(hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the view has an entry.
|
* Test whether the view has an entry.
|
||||||
@ -43,9 +46,9 @@ CoinView.prototype.get = function get(hash) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.has = function has(hash) {
|
has(hash) {
|
||||||
return this.map.has(hash);
|
return this.map.has(hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add coins to the collection.
|
* Add coins to the collection.
|
||||||
@ -54,10 +57,10 @@ CoinView.prototype.has = function has(hash) {
|
|||||||
* @returns {Coins}
|
* @returns {Coins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.add = function add(hash, coins) {
|
add(hash, coins) {
|
||||||
this.map.set(hash, coins);
|
this.map.set(hash, coins);
|
||||||
return coins;
|
return coins;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure existence of coins object in the collection.
|
* Ensure existence of coins object in the collection.
|
||||||
@ -65,14 +68,14 @@ CoinView.prototype.add = function add(hash, coins) {
|
|||||||
* @returns {Coins}
|
* @returns {Coins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.ensure = function ensure(hash) {
|
ensure(hash) {
|
||||||
const coins = this.map.get(hash);
|
const coins = this.map.get(hash);
|
||||||
|
|
||||||
if (coins)
|
if (coins)
|
||||||
return coins;
|
return coins;
|
||||||
|
|
||||||
return this.add(hash, new Coins());
|
return this.add(hash, new Coins());
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove coins from the collection.
|
* Remove coins from the collection.
|
||||||
@ -80,7 +83,7 @@ CoinView.prototype.ensure = function ensure(hash) {
|
|||||||
* @returns {Coins|null}
|
* @returns {Coins|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.remove = function remove(hash) {
|
remove(hash) {
|
||||||
const coins = this.map.get(hash);
|
const coins = this.map.get(hash);
|
||||||
|
|
||||||
if (!coins)
|
if (!coins)
|
||||||
@ -89,7 +92,7 @@ CoinView.prototype.remove = function remove(hash) {
|
|||||||
this.map.delete(hash);
|
this.map.delete(hash);
|
||||||
|
|
||||||
return coins;
|
return coins;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a tx to the collection.
|
* Add a tx to the collection.
|
||||||
@ -98,11 +101,11 @@ CoinView.prototype.remove = function remove(hash) {
|
|||||||
* @returns {Coins}
|
* @returns {Coins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.addTX = function addTX(tx, height) {
|
addTX(tx, height) {
|
||||||
const hash = tx.hash('hex');
|
const hash = tx.hash('hex');
|
||||||
const coins = Coins.fromTX(tx, height);
|
const coins = Coins.fromTX(tx, height);
|
||||||
return this.add(hash, coins);
|
return this.add(hash, coins);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a tx from the collection.
|
* Remove a tx from the collection.
|
||||||
@ -111,7 +114,7 @@ CoinView.prototype.addTX = function addTX(tx, height) {
|
|||||||
* @returns {Coins}
|
* @returns {Coins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.removeTX = function removeTX(tx, height) {
|
removeTX(tx, height) {
|
||||||
const hash = tx.hash('hex');
|
const hash = tx.hash('hex');
|
||||||
const coins = Coins.fromTX(tx, height);
|
const coins = Coins.fromTX(tx, height);
|
||||||
|
|
||||||
@ -119,7 +122,7 @@ CoinView.prototype.removeTX = function removeTX(tx, height) {
|
|||||||
coin.spent = true;
|
coin.spent = true;
|
||||||
|
|
||||||
return this.add(hash, coins);
|
return this.add(hash, coins);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an entry to the collection.
|
* Add an entry to the collection.
|
||||||
@ -128,11 +131,11 @@ CoinView.prototype.removeTX = function removeTX(tx, height) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.addEntry = function addEntry(prevout, coin) {
|
addEntry(prevout, coin) {
|
||||||
const {hash, index} = prevout;
|
const {hash, index} = prevout;
|
||||||
const coins = this.ensure(hash);
|
const coins = this.ensure(hash);
|
||||||
return coins.add(index, coin);
|
return coins.add(index, coin);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a coin to the collection.
|
* Add a coin to the collection.
|
||||||
@ -140,10 +143,10 @@ CoinView.prototype.addEntry = function addEntry(prevout, coin) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.addCoin = function addCoin(coin) {
|
addCoin(coin) {
|
||||||
const coins = this.ensure(coin.hash);
|
const coins = this.ensure(coin.hash);
|
||||||
return coins.addCoin(coin);
|
return coins.addCoin(coin);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an output to the collection.
|
* Add an output to the collection.
|
||||||
@ -152,11 +155,11 @@ CoinView.prototype.addCoin = function addCoin(coin) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.addOutput = function addOutput(prevout, output) {
|
addOutput(prevout, output) {
|
||||||
const {hash, index} = prevout;
|
const {hash, index} = prevout;
|
||||||
const coins = this.ensure(hash);
|
const coins = this.ensure(hash);
|
||||||
return coins.addOutput(index, output);
|
return coins.addOutput(index, output);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an output to the collection by output index.
|
* Add an output to the collection by output index.
|
||||||
@ -166,11 +169,11 @@ CoinView.prototype.addOutput = function addOutput(prevout, output) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.addIndex = function addIndex(tx, index, height) {
|
addIndex(tx, index, height) {
|
||||||
const hash = tx.hash('hex');
|
const hash = tx.hash('hex');
|
||||||
const coins = this.ensure(hash);
|
const coins = this.ensure(hash);
|
||||||
return coins.addIndex(tx, index, height);
|
return coins.addIndex(tx, index, height);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spend an output.
|
* Spend an output.
|
||||||
@ -178,7 +181,7 @@ CoinView.prototype.addIndex = function addIndex(tx, index, height) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.spendEntry = function spendEntry(prevout) {
|
spendEntry(prevout) {
|
||||||
const {hash, index} = prevout;
|
const {hash, index} = prevout;
|
||||||
const coins = this.get(hash);
|
const coins = this.get(hash);
|
||||||
|
|
||||||
@ -193,7 +196,7 @@ CoinView.prototype.spendEntry = function spendEntry(prevout) {
|
|||||||
this.undo.push(coin);
|
this.undo.push(coin);
|
||||||
|
|
||||||
return coin;
|
return coin;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove an output.
|
* Remove an output.
|
||||||
@ -201,7 +204,7 @@ CoinView.prototype.spendEntry = function spendEntry(prevout) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.removeEntry = function removeEntry(prevout) {
|
removeEntry(prevout) {
|
||||||
const {hash, index} = prevout;
|
const {hash, index} = prevout;
|
||||||
const coins = this.get(hash);
|
const coins = this.get(hash);
|
||||||
|
|
||||||
@ -209,7 +212,7 @@ CoinView.prototype.removeEntry = function removeEntry(prevout) {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
return coins.remove(index);
|
return coins.remove(index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the view has an entry by prevout.
|
* Test whether the view has an entry by prevout.
|
||||||
@ -217,7 +220,7 @@ CoinView.prototype.removeEntry = function removeEntry(prevout) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.hasEntry = function hasEntry(prevout) {
|
hasEntry(prevout) {
|
||||||
const {hash, index} = prevout;
|
const {hash, index} = prevout;
|
||||||
const coins = this.get(hash);
|
const coins = this.get(hash);
|
||||||
|
|
||||||
@ -225,7 +228,7 @@ CoinView.prototype.hasEntry = function hasEntry(prevout) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return coins.has(index);
|
return coins.has(index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single entry by prevout.
|
* Get a single entry by prevout.
|
||||||
@ -233,7 +236,7 @@ CoinView.prototype.hasEntry = function hasEntry(prevout) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getEntry = function getEntry(prevout) {
|
getEntry(prevout) {
|
||||||
const {hash, index} = prevout;
|
const {hash, index} = prevout;
|
||||||
const coins = this.get(hash);
|
const coins = this.get(hash);
|
||||||
|
|
||||||
@ -241,7 +244,7 @@ CoinView.prototype.getEntry = function getEntry(prevout) {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
return coins.get(index);
|
return coins.get(index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an entry has been spent by prevout.
|
* Test whether an entry has been spent by prevout.
|
||||||
@ -249,7 +252,7 @@ CoinView.prototype.getEntry = function getEntry(prevout) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.isUnspent = function isUnspent(prevout) {
|
isUnspent(prevout) {
|
||||||
const {hash, index} = prevout;
|
const {hash, index} = prevout;
|
||||||
const coins = this.get(hash);
|
const coins = this.get(hash);
|
||||||
|
|
||||||
@ -257,7 +260,7 @@ CoinView.prototype.isUnspent = function isUnspent(prevout) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return coins.isUnspent(index);
|
return coins.isUnspent(index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single coin by prevout.
|
* Get a single coin by prevout.
|
||||||
@ -265,14 +268,14 @@ CoinView.prototype.isUnspent = function isUnspent(prevout) {
|
|||||||
* @returns {Coin|null}
|
* @returns {Coin|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getCoin = function getCoin(prevout) {
|
getCoin(prevout) {
|
||||||
const coins = this.get(prevout.hash);
|
const coins = this.get(prevout.hash);
|
||||||
|
|
||||||
if (!coins)
|
if (!coins)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return coins.getCoin(prevout);
|
return coins.getCoin(prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single output by prevout.
|
* Get a single output by prevout.
|
||||||
@ -280,7 +283,7 @@ CoinView.prototype.getCoin = function getCoin(prevout) {
|
|||||||
* @returns {Output|null}
|
* @returns {Output|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getOutput = function getOutput(prevout) {
|
getOutput(prevout) {
|
||||||
const {hash, index} = prevout;
|
const {hash, index} = prevout;
|
||||||
const coins = this.get(hash);
|
const coins = this.get(hash);
|
||||||
|
|
||||||
@ -288,7 +291,7 @@ CoinView.prototype.getOutput = function getOutput(prevout) {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
return coins.getOutput(index);
|
return coins.getOutput(index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get coins height by prevout.
|
* Get coins height by prevout.
|
||||||
@ -296,14 +299,14 @@ CoinView.prototype.getOutput = function getOutput(prevout) {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getHeight = function getHeight(prevout) {
|
getHeight(prevout) {
|
||||||
const coin = this.getEntry(prevout);
|
const coin = this.getEntry(prevout);
|
||||||
|
|
||||||
if (!coin)
|
if (!coin)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return coin.height;
|
return coin.height;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get coins coinbase flag by prevout.
|
* Get coins coinbase flag by prevout.
|
||||||
@ -311,14 +314,14 @@ CoinView.prototype.getHeight = function getHeight(prevout) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.isCoinbase = function isCoinbase(prevout) {
|
isCoinbase(prevout) {
|
||||||
const coin = this.getEntry(prevout);
|
const coin = this.getEntry(prevout);
|
||||||
|
|
||||||
if (!coin)
|
if (!coin)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return coin.coinbase;
|
return coin.coinbase;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the view has an entry by input.
|
* Test whether the view has an entry by input.
|
||||||
@ -326,9 +329,9 @@ CoinView.prototype.isCoinbase = function isCoinbase(prevout) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.hasEntryFor = function hasEntryFor(input) {
|
hasEntryFor(input) {
|
||||||
return this.hasEntry(input.prevout);
|
return this.hasEntry(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single entry by input.
|
* Get a single entry by input.
|
||||||
@ -336,9 +339,9 @@ CoinView.prototype.hasEntryFor = function hasEntryFor(input) {
|
|||||||
* @returns {CoinEntry|null}
|
* @returns {CoinEntry|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getEntryFor = function getEntryFor(input) {
|
getEntryFor(input) {
|
||||||
return this.getEntry(input.prevout);
|
return this.getEntry(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an entry has been spent by input.
|
* Test whether an entry has been spent by input.
|
||||||
@ -346,9 +349,9 @@ CoinView.prototype.getEntryFor = function getEntryFor(input) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.isUnspentFor = function isUnspentFor(input) {
|
isUnspentFor(input) {
|
||||||
return this.isUnspent(input.prevout);
|
return this.isUnspent(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single coin by input.
|
* Get a single coin by input.
|
||||||
@ -356,9 +359,9 @@ CoinView.prototype.isUnspentFor = function isUnspentFor(input) {
|
|||||||
* @returns {Coin|null}
|
* @returns {Coin|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getCoinFor = function getCoinFor(input) {
|
getCoinFor(input) {
|
||||||
return this.getCoin(input.prevout);
|
return this.getCoin(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a single output by input.
|
* Get a single output by input.
|
||||||
@ -366,9 +369,9 @@ CoinView.prototype.getCoinFor = function getCoinFor(input) {
|
|||||||
* @returns {Output|null}
|
* @returns {Output|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getOutputFor = function getOutputFor(input) {
|
getOutputFor(input) {
|
||||||
return this.getOutput(input.prevout);
|
return this.getOutput(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get coins height by input.
|
* Get coins height by input.
|
||||||
@ -376,9 +379,9 @@ CoinView.prototype.getOutputFor = function getOutputFor(input) {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getHeightFor = function getHeightFor(input) {
|
getHeightFor(input) {
|
||||||
return this.getHeight(input.prevout);
|
return this.getHeight(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get coins coinbase flag by input.
|
* Get coins coinbase flag by input.
|
||||||
@ -386,9 +389,9 @@ CoinView.prototype.getHeightFor = function getHeightFor(input) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.isCoinbaseFor = function isCoinbaseFor(input) {
|
isCoinbaseFor(input) {
|
||||||
return this.isCoinbase(input.prevout);
|
return this.isCoinbase(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve coins from database.
|
* Retrieve coins from database.
|
||||||
@ -398,7 +401,7 @@ CoinView.prototype.isCoinbaseFor = function isCoinbaseFor(input) {
|
|||||||
* @returns {Promise} - Returns {@link CoinEntry}.
|
* @returns {Promise} - Returns {@link CoinEntry}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.readCoin = async function readCoin(db, prevout) {
|
async readCoin(db, prevout) {
|
||||||
const cache = this.getEntry(prevout);
|
const cache = this.getEntry(prevout);
|
||||||
|
|
||||||
if (cache)
|
if (cache)
|
||||||
@ -410,7 +413,7 @@ CoinView.prototype.readCoin = async function readCoin(db, prevout) {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
return this.addEntry(prevout, coin);
|
return this.addEntry(prevout, coin);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read all input coins into unspent map.
|
* Read all input coins into unspent map.
|
||||||
@ -420,7 +423,7 @@ CoinView.prototype.readCoin = async function readCoin(db, prevout) {
|
|||||||
* @returns {Promise} - Returns {Boolean}.
|
* @returns {Promise} - Returns {Boolean}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.readInputs = async function readInputs(db, tx) {
|
async readInputs(db, tx) {
|
||||||
let found = true;
|
let found = true;
|
||||||
|
|
||||||
for (const {prevout} of tx.inputs) {
|
for (const {prevout} of tx.inputs) {
|
||||||
@ -429,7 +432,7 @@ CoinView.prototype.readInputs = async function readInputs(db, tx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spend coins for transaction.
|
* Spend coins for transaction.
|
||||||
@ -439,7 +442,7 @@ CoinView.prototype.readInputs = async function readInputs(db, tx) {
|
|||||||
* @returns {Promise} - Returns {Boolean}.
|
* @returns {Promise} - Returns {Boolean}.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.spendInputs = async function spendInputs(db, tx) {
|
async spendInputs(db, tx) {
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
||||||
while (i < tx.inputs.length) {
|
while (i < tx.inputs.length) {
|
||||||
@ -463,14 +466,14 @@ CoinView.prototype.spendInputs = async function spendInputs(db, tx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate serialization size.
|
* Calculate serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.getSize = function getSize(tx) {
|
getSize(tx) {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += tx.inputs.length;
|
size += tx.inputs.length;
|
||||||
@ -485,7 +488,7 @@ CoinView.prototype.getSize = function getSize(tx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write coin data to buffer writer
|
* Write coin data to buffer writer
|
||||||
@ -494,7 +497,7 @@ CoinView.prototype.getSize = function getSize(tx) {
|
|||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.toWriter = function toWriter(bw, tx) {
|
toWriter(bw, tx) {
|
||||||
for (const {prevout} of tx.inputs) {
|
for (const {prevout} of tx.inputs) {
|
||||||
const coin = this.getEntry(prevout);
|
const coin = this.getEntry(prevout);
|
||||||
|
|
||||||
@ -508,7 +511,7 @@ CoinView.prototype.toWriter = function toWriter(bw, tx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read serialized view data from a buffer
|
* Read serialized view data from a buffer
|
||||||
@ -518,7 +521,7 @@ CoinView.prototype.toWriter = function toWriter(bw, tx) {
|
|||||||
* @param {TX} tx
|
* @param {TX} tx
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.prototype.fromReader = function fromReader(br, tx) {
|
fromReader(br, tx) {
|
||||||
for (const {prevout} of tx.inputs) {
|
for (const {prevout} of tx.inputs) {
|
||||||
if (br.readU8() === 0)
|
if (br.readU8() === 0)
|
||||||
continue;
|
continue;
|
||||||
@ -529,7 +532,7 @@ CoinView.prototype.fromReader = function fromReader(br, tx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read serialized view data from a buffer
|
* Read serialized view data from a buffer
|
||||||
@ -539,9 +542,10 @@ CoinView.prototype.fromReader = function fromReader(br, tx) {
|
|||||||
* @returns {CoinView}
|
* @returns {CoinView}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CoinView.fromReader = function fromReader(br, tx) {
|
static fromReader(br, tx) {
|
||||||
return new CoinView().fromReader(br, tx);
|
return new this().fromReader(br, tx);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -18,14 +18,16 @@ const CoinEntry = require('../coins/coinentry');
|
|||||||
* spent coins in a single record per block
|
* spent coins in a single record per block
|
||||||
* (in a compressed format).
|
* (in a compressed format).
|
||||||
* @alias module:coins.UndoCoins
|
* @alias module:coins.UndoCoins
|
||||||
* @constructor
|
|
||||||
* @property {UndoCoin[]} items
|
* @property {UndoCoin[]} items
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function UndoCoins() {
|
class UndoCoins {
|
||||||
if (!(this instanceof UndoCoins))
|
/**
|
||||||
return new UndoCoins();
|
* Create undo coins.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor() {
|
||||||
this.items = [];
|
this.items = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,16 +37,16 @@ function UndoCoins() {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UndoCoins.prototype.push = function push(coin) {
|
push(coin) {
|
||||||
return this.items.push(coin);
|
return this.items.push(coin);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate undo coins size.
|
* Calculate undo coins size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UndoCoins.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += 4;
|
size += 4;
|
||||||
@ -53,14 +55,14 @@ UndoCoins.prototype.getSize = function getSize() {
|
|||||||
size += coin.getSize();
|
size += coin.getSize();
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize all undo coins.
|
* Serialize all undo coins.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UndoCoins.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const bw = new StaticWriter(size);
|
const bw = new StaticWriter(size);
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ UndoCoins.prototype.toRaw = function toRaw() {
|
|||||||
coin.toWriter(bw);
|
coin.toWriter(bw);
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -79,7 +81,7 @@ UndoCoins.prototype.toRaw = function toRaw() {
|
|||||||
* @returns {UndoCoins}
|
* @returns {UndoCoins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UndoCoins.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = new BufferReader(data);
|
const br = new BufferReader(data);
|
||||||
const count = br.readU32();
|
const count = br.readU32();
|
||||||
|
|
||||||
@ -87,7 +89,7 @@ UndoCoins.prototype.fromRaw = function fromRaw(data) {
|
|||||||
this.items.push(CoinEntry.fromReader(br));
|
this.items.push(CoinEntry.fromReader(br));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate undo coins from serialized data.
|
* Instantiate undo coins from serialized data.
|
||||||
@ -95,29 +97,29 @@ UndoCoins.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {UndoCoins}
|
* @returns {UndoCoins}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UndoCoins.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new UndoCoins().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the undo coins have any members.
|
* Test whether the undo coins have any members.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UndoCoins.prototype.isEmpty = function isEmpty() {
|
isEmpty() {
|
||||||
return this.items.length === 0;
|
return this.items.length === 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the undo coins.
|
* Render the undo coins.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UndoCoins.prototype.commit = function commit() {
|
commit() {
|
||||||
const raw = this.toRaw();
|
const raw = this.toRaw();
|
||||||
this.items.length = 0;
|
this.items.length = 0;
|
||||||
return raw;
|
return raw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-apply undo coins to a view, effectively unspending them.
|
* Re-apply undo coins to a view, effectively unspending them.
|
||||||
@ -125,13 +127,14 @@ UndoCoins.prototype.commit = function commit() {
|
|||||||
* @param {Outpoint} prevout
|
* @param {Outpoint} prevout
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UndoCoins.prototype.apply = function apply(view, prevout) {
|
apply(view, prevout) {
|
||||||
const undo = this.items.pop();
|
const undo = this.items.pop();
|
||||||
|
|
||||||
assert(undo);
|
assert(undo);
|
||||||
|
|
||||||
view.addEntry(prevout, undo);
|
view.addEntry(prevout, undo);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -221,7 +221,7 @@ Miner.prototype.mineBlock = function mineBlock(tip, address) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Miner.prototype.addAddress = function addAddress(address) {
|
Miner.prototype.addAddress = function addAddress(address) {
|
||||||
this.addresses.push(Address(address));
|
this.addresses.push(new Address(address));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -512,7 +512,7 @@ BlockTemplate.prototype.getDifficulty = function getDifficulty() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
BlockTemplate.prototype.setAddress = function setAddress(address) {
|
BlockTemplate.prototype.setAddress = function setAddress(address) {
|
||||||
this.address = Address(address);
|
this.address = new Address(address);
|
||||||
this.refresh();
|
this.refresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -24,11 +24,10 @@ const Block = require('../primitives/block');
|
|||||||
const common = require('./common');
|
const common = require('./common');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Compact Block
|
||||||
* Represents a compact block (bip152): `cmpctblock` packet.
|
* Represents a compact block (bip152): `cmpctblock` packet.
|
||||||
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
|
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
|
||||||
* @constructor
|
|
||||||
* @extends AbstractBlock
|
* @extends AbstractBlock
|
||||||
* @param {Object} options
|
|
||||||
* @property {Buffer|null} keyNonce - Nonce for siphash key.
|
* @property {Buffer|null} keyNonce - Nonce for siphash key.
|
||||||
* @property {Number[]} ids - Short IDs.
|
* @property {Number[]} ids - Short IDs.
|
||||||
* @property {Object[]} ptx - Prefilled transactions.
|
* @property {Object[]} ptx - Prefilled transactions.
|
||||||
@ -38,11 +37,15 @@ const common = require('./common');
|
|||||||
* @property {Buffer|null} sipKey - Siphash key.
|
* @property {Buffer|null} sipKey - Siphash key.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function CompactBlock(options) {
|
class CompactBlock extends AbstractBlock {
|
||||||
if (!(this instanceof CompactBlock))
|
/**
|
||||||
return new CompactBlock(options);
|
* Create a compact block.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
AbstractBlock.call(this);
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
|
||||||
this.keyNonce = null;
|
this.keyNonce = null;
|
||||||
this.ids = [];
|
this.ids = [];
|
||||||
@ -59,15 +62,13 @@ function CompactBlock(options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(CompactBlock.prototype, AbstractBlock.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
this.parseOptions(options);
|
this.parseOptions(options);
|
||||||
|
|
||||||
assert(Buffer.isBuffer(options.keyNonce));
|
assert(Buffer.isBuffer(options.keyNonce));
|
||||||
@ -93,7 +94,7 @@ CompactBlock.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.sipKey = this.getKey();
|
this.sipKey = this.getKey();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate compact block from options.
|
* Instantiate compact block from options.
|
||||||
@ -101,18 +102,18 @@ CompactBlock.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {CompactBlock}
|
* @returns {CompactBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new CompactBlock().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the block.
|
* Verify the block.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.verifyBody = function verifyBody() {
|
verifyBody() {
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -120,7 +121,7 @@ CompactBlock.prototype.verifyBody = function verifyBody() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = new BufferReader(data);
|
const br = new BufferReader(data);
|
||||||
|
|
||||||
this.readHead(br);
|
this.readHead(br);
|
||||||
@ -154,7 +155,7 @@ CompactBlock.prototype.fromRaw = function fromRaw(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a block from serialized data.
|
* Instantiate a block from serialized data.
|
||||||
@ -163,29 +164,29 @@ CompactBlock.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {CompactBlock}
|
* @returns {CompactBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.fromRaw = function fromRaw(data, enc) {
|
static fromRaw(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new CompactBlock().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize compact block with witness data.
|
* Serialize compact block with witness data.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
return this.frameRaw(true);
|
return this.frameRaw(true);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize compact block without witness data.
|
* Serialize compact block without witness data.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.toNormal = function toNormal() {
|
toNormal() {
|
||||||
return this.frameRaw(false);
|
return this.frameRaw(false);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write serialized block to a buffer
|
* Write serialized block to a buffer
|
||||||
@ -193,9 +194,9 @@ CompactBlock.prototype.toNormal = function toNormal() {
|
|||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
return this.writeRaw(bw, true);
|
return this.writeRaw(bw, true);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write serialized block to a buffer
|
* Write serialized block to a buffer
|
||||||
@ -203,9 +204,9 @@ CompactBlock.prototype.toWriter = function toWriter(bw) {
|
|||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.toNormalWriter = function toNormalWriter(bw) {
|
toNormalWriter(bw) {
|
||||||
return this.writeRaw(bw, false);
|
return this.writeRaw(bw, false);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize compact block.
|
* Serialize compact block.
|
||||||
@ -214,10 +215,10 @@ CompactBlock.prototype.toNormalWriter = function toNormalWriter(bw) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.frameRaw = function frameRaw(witness) {
|
frameRaw(witness) {
|
||||||
const size = this.getSize(witness);
|
const size = this.getSize(witness);
|
||||||
return this.writeRaw(new StaticWriter(size), witness).render();
|
return this.writeRaw(new StaticWriter(size), witness).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate block serialization size.
|
* Calculate block serialization size.
|
||||||
@ -225,7 +226,7 @@ CompactBlock.prototype.frameRaw = function frameRaw(witness) {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.getSize = function getSize(witness) {
|
getSize(witness) {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += 80;
|
size += 80;
|
||||||
@ -244,7 +245,7 @@ CompactBlock.prototype.getSize = function getSize(witness) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize block to buffer writer.
|
* Serialize block to buffer writer.
|
||||||
@ -253,7 +254,7 @@ CompactBlock.prototype.getSize = function getSize(witness) {
|
|||||||
* @param {Boolean} witness
|
* @param {Boolean} witness
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.writeRaw = function writeRaw(bw, witness) {
|
writeRaw(bw, witness) {
|
||||||
this.writeHead(bw);
|
this.writeHead(bw);
|
||||||
|
|
||||||
bw.writeBytes(this.keyNonce);
|
bw.writeBytes(this.keyNonce);
|
||||||
@ -280,7 +281,7 @@ CompactBlock.prototype.writeRaw = function writeRaw(bw, witness) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert block to a TXRequest
|
* Convert block to a TXRequest
|
||||||
@ -288,9 +289,9 @@ CompactBlock.prototype.writeRaw = function writeRaw(bw, witness) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.toRequest = function toRequest() {
|
toRequest() {
|
||||||
return TXRequest.fromCompact(this);
|
return TXRequest.fromCompact(this);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to fill missing transactions from mempool.
|
* Attempt to fill missing transactions from mempool.
|
||||||
@ -299,7 +300,7 @@ CompactBlock.prototype.toRequest = function toRequest() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
|
fillMempool(witness, mempool) {
|
||||||
if (this.count === this.totalTX)
|
if (this.count === this.totalTX)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -320,13 +321,13 @@ CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
|
|||||||
if (set.has(index)) {
|
if (set.has(index)) {
|
||||||
// Siphash collision, just request it.
|
// Siphash collision, just request it.
|
||||||
this.available[index] = null;
|
this.available[index] = null;
|
||||||
this.count--;
|
this.count -= 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.available[index] = tx;
|
this.available[index] = tx;
|
||||||
set.add(index);
|
set.add(index);
|
||||||
this.count++;
|
this.count += 1;
|
||||||
|
|
||||||
// We actually may have a siphash collision
|
// We actually may have a siphash collision
|
||||||
// here, but exit early anyway for perf.
|
// here, but exit early anyway for perf.
|
||||||
@ -335,7 +336,7 @@ CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to fill missing transactions from TXResponse.
|
* Attempt to fill missing transactions from TXResponse.
|
||||||
@ -343,7 +344,7 @@ CompactBlock.prototype.fillMempool = function fillMempool(witness, mempool) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.fillMissing = function fillMissing(res) {
|
fillMissing(res) {
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
|
|
||||||
for (let i = 0; i < this.available.length; i++) {
|
for (let i = 0; i < this.available.length; i++) {
|
||||||
@ -357,7 +358,7 @@ CompactBlock.prototype.fillMissing = function fillMissing(res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return offset === res.txs.length;
|
return offset === res.txs.length;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate a transaction short ID.
|
* Calculate a transaction short ID.
|
||||||
@ -365,14 +366,14 @@ CompactBlock.prototype.fillMissing = function fillMissing(res) {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.sid = function sid(hash) {
|
sid(hash) {
|
||||||
if (typeof hash === 'string')
|
if (typeof hash === 'string')
|
||||||
hash = Buffer.from(hash, 'hex');
|
hash = Buffer.from(hash, 'hex');
|
||||||
|
|
||||||
const [hi, lo] = siphash256(hash, this.sipKey);
|
const [hi, lo] = siphash256(hash, this.sipKey);
|
||||||
|
|
||||||
return (hi & 0xffff) * 0x100000000 + (lo >>> 0);
|
return (hi & 0xffff) * 0x100000000 + (lo >>> 0);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an index is available.
|
* Test whether an index is available.
|
||||||
@ -380,9 +381,9 @@ CompactBlock.prototype.sid = function sid(hash) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.hasIndex = function hasIndex(index) {
|
hasIndex(index) {
|
||||||
return this.available[index] != null;
|
return this.available[index] != null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the siphash key.
|
* Initialize the siphash key.
|
||||||
@ -390,18 +391,18 @@ CompactBlock.prototype.hasIndex = function hasIndex(index) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.getKey = function getKey() {
|
getKey() {
|
||||||
const data = Buffer.concat([this.toHead(), this.keyNonce]);
|
const data = Buffer.concat([this.toHead(), this.keyNonce]);
|
||||||
const hash = sha256.digest(data);
|
const hash = sha256.digest(data);
|
||||||
return hash.slice(0, 16);
|
return hash.slice(0, 16);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize compact block and short id map.
|
* Initialize compact block and short id map.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.init = function init() {
|
init() {
|
||||||
if (this.totalTX === 0)
|
if (this.totalTX === 0)
|
||||||
throw new Error('Empty vectors.');
|
throw new Error('Empty vectors.');
|
||||||
|
|
||||||
@ -428,14 +429,14 @@ CompactBlock.prototype.init = function init() {
|
|||||||
assert(last <= 0xffff);
|
assert(last <= 0xffff);
|
||||||
assert(last <= this.ids.length + i);
|
assert(last <= this.ids.length + i);
|
||||||
this.available[last] = tx;
|
this.available[last] = tx;
|
||||||
this.count++;
|
this.count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < this.ids.length; i++) {
|
for (let i = 0; i < this.ids.length; i++) {
|
||||||
const id = this.ids[i];
|
const id = this.ids[i];
|
||||||
|
|
||||||
while (this.available[i + offset])
|
while (this.available[i + offset])
|
||||||
offset++;
|
offset += 1;
|
||||||
|
|
||||||
// Fails on siphash collision.
|
// Fails on siphash collision.
|
||||||
if (this.idMap.has(id))
|
if (this.idMap.has(id))
|
||||||
@ -445,7 +446,7 @@ CompactBlock.prototype.init = function init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert completely filled compact
|
* Convert completely filled compact
|
||||||
@ -453,7 +454,7 @@ CompactBlock.prototype.init = function init() {
|
|||||||
* @returns {Block}
|
* @returns {Block}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.toBlock = function toBlock() {
|
toBlock() {
|
||||||
const block = new Block();
|
const block = new Block();
|
||||||
|
|
||||||
block.version = this.version;
|
block.version = this.version;
|
||||||
@ -471,7 +472,7 @@ CompactBlock.prototype.toBlock = function toBlock() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from block.
|
* Inject properties from block.
|
||||||
@ -482,7 +483,7 @@ CompactBlock.prototype.toBlock = function toBlock() {
|
|||||||
* @returns {CompactBlock}
|
* @returns {CompactBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
|
fromBlock(block, witness, nonce) {
|
||||||
this.version = block.version;
|
this.version = block.version;
|
||||||
this.prevBlock = block.prevBlock;
|
this.prevBlock = block.prevBlock;
|
||||||
this.merkleRoot = block.merkleRoot;
|
this.merkleRoot = block.merkleRoot;
|
||||||
@ -514,7 +515,7 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
|
|||||||
this.ptx.push([0, block.txs[0]]);
|
this.ptx.push([0, block.txs[0]]);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate compact block from a block.
|
* Instantiate compact block from a block.
|
||||||
@ -524,32 +525,36 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
|
|||||||
* @returns {CompactBlock}
|
* @returns {CompactBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.fromBlock = function fromBlock(block, witness, nonce) {
|
static fromBlock(block, witness, nonce) {
|
||||||
return new CompactBlock().fromBlock(block, witness, nonce);
|
return new this().fromBlock(block, witness, nonce);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert block to headers.
|
* Convert block to headers.
|
||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CompactBlock.prototype.toHeaders = function toHeaders() {
|
toHeaders() {
|
||||||
return Headers.fromBlock(this);
|
return Headers.fromBlock(this);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* TX Request
|
||||||
* Represents a BlockTransactionsRequest (bip152): `getblocktxn` packet.
|
* Represents a BlockTransactionsRequest (bip152): `getblocktxn` packet.
|
||||||
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
|
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
|
||||||
* @constructor
|
|
||||||
* @param {Object} options
|
|
||||||
* @property {Hash} hash
|
* @property {Hash} hash
|
||||||
* @property {Number[]} indexes
|
* @property {Number[]} indexes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function TXRequest(options) {
|
class TXRequest {
|
||||||
if (!(this instanceof TXRequest))
|
/**
|
||||||
return new TXRequest(options);
|
* TX Request
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
this.hash = encoding.NULL_HASH;
|
this.hash = encoding.NULL_HASH;
|
||||||
this.indexes = [];
|
this.indexes = [];
|
||||||
|
|
||||||
@ -564,14 +569,14 @@ function TXRequest(options) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
this.hash = options.hash;
|
this.hash = options.hash;
|
||||||
|
|
||||||
if (options.indexes)
|
if (options.indexes)
|
||||||
this.indexes = options.indexes;
|
this.indexes = options.indexes;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate request from options.
|
* Instantiate request from options.
|
||||||
@ -579,9 +584,9 @@ TXRequest.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new TXRequest().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from compact block.
|
* Inject properties from compact block.
|
||||||
@ -590,7 +595,7 @@ TXRequest.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.prototype.fromCompact = function fromCompact(block) {
|
fromCompact(block) {
|
||||||
this.hash = block.hash('hex');
|
this.hash = block.hash('hex');
|
||||||
|
|
||||||
for (let i = 0; i < block.available.length; i++) {
|
for (let i = 0; i < block.available.length; i++) {
|
||||||
@ -599,7 +604,7 @@ TXRequest.prototype.fromCompact = function fromCompact(block) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate request from compact block.
|
* Instantiate request from compact block.
|
||||||
@ -607,9 +612,9 @@ TXRequest.prototype.fromCompact = function fromCompact(block) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.fromCompact = function fromCompact(block) {
|
static fromCompact(block) {
|
||||||
return new TXRequest().fromCompact(block);
|
return new this().fromCompact(block);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -618,7 +623,7 @@ TXRequest.fromCompact = function fromCompact(block) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
this.hash = br.readHash('hex');
|
this.hash = br.readHash('hex');
|
||||||
|
|
||||||
const count = br.readVarint();
|
const count = br.readVarint();
|
||||||
@ -640,7 +645,7 @@ TXRequest.prototype.fromReader = function fromReader(br) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -649,9 +654,9 @@ TXRequest.prototype.fromReader = function fromReader(br) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate request from buffer reader.
|
* Instantiate request from buffer reader.
|
||||||
@ -659,9 +664,9 @@ TXRequest.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new TXRequest().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate request from serialized data.
|
* Instantiate request from serialized data.
|
||||||
@ -669,16 +674,16 @@ TXRequest.fromReader = function fromReader(br) {
|
|||||||
* @returns {TXRequest}
|
* @returns {TXRequest}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new TXRequest().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate request serialization size.
|
* Calculate request serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += 32;
|
size += 32;
|
||||||
@ -694,14 +699,14 @@ TXRequest.prototype.getSize = function getSize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write serialized request to buffer writer.
|
* Write serialized request to buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
bw.writeHash(this.hash);
|
bw.writeHash(this.hash);
|
||||||
|
|
||||||
bw.writeVarint(this.indexes.length);
|
bw.writeVarint(this.indexes.length);
|
||||||
@ -716,31 +721,35 @@ TXRequest.prototype.toWriter = function toWriter(bw) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize request.
|
* Serialize request.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXRequest.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
return this.toWriter(new StaticWriter(size)).render();
|
return this.toWriter(new StaticWriter(size)).render();
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* TX Response
|
||||||
* Represents BlockTransactions (bip152): `blocktxn` packet.
|
* Represents BlockTransactions (bip152): `blocktxn` packet.
|
||||||
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
|
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
|
||||||
* @constructor
|
|
||||||
* @param {Object} options
|
|
||||||
* @property {Hash} hash
|
* @property {Hash} hash
|
||||||
* @property {TX[]} txs
|
* @property {TX[]} txs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function TXResponse(options) {
|
class TXResponse {
|
||||||
if (!(this instanceof TXResponse))
|
/**
|
||||||
return new TXResponse(options);
|
* Create a tx response.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
this.hash = encoding.NULL_HASH;
|
this.hash = encoding.NULL_HASH;
|
||||||
this.txs = [];
|
this.txs = [];
|
||||||
|
|
||||||
@ -755,14 +764,14 @@ function TXResponse(options) {
|
|||||||
* @returns {TXResponse}
|
* @returns {TXResponse}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
this.hash = options.hash;
|
this.hash = options.hash;
|
||||||
|
|
||||||
if (options.txs)
|
if (options.txs)
|
||||||
this.txs = options.txs;
|
this.txs = options.txs;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate response from options.
|
* Instantiate response from options.
|
||||||
@ -770,9 +779,9 @@ TXResponse.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {TXResponse}
|
* @returns {TXResponse}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new TXResponse().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -781,7 +790,7 @@ TXResponse.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {TXResponse}
|
* @returns {TXResponse}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
this.hash = br.readHash('hex');
|
this.hash = br.readHash('hex');
|
||||||
|
|
||||||
const count = br.readVarint();
|
const count = br.readVarint();
|
||||||
@ -790,7 +799,7 @@ TXResponse.prototype.fromReader = function fromReader(br) {
|
|||||||
this.txs.push(TX.fromReader(br));
|
this.txs.push(TX.fromReader(br));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -799,9 +808,9 @@ TXResponse.prototype.fromReader = function fromReader(br) {
|
|||||||
* @returns {TXResponse}
|
* @returns {TXResponse}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate response from buffer reader.
|
* Instantiate response from buffer reader.
|
||||||
@ -809,9 +818,9 @@ TXResponse.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {TXResponse}
|
* @returns {TXResponse}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new TXResponse().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate response from serialized data.
|
* Instantiate response from serialized data.
|
||||||
@ -819,9 +828,9 @@ TXResponse.fromReader = function fromReader(br) {
|
|||||||
* @returns {TXResponse}
|
* @returns {TXResponse}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new TXResponse().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from block.
|
* Inject properties from block.
|
||||||
@ -830,7 +839,7 @@ TXResponse.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {TXResponse}
|
* @returns {TXResponse}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.fromBlock = function fromBlock(block, req) {
|
fromBlock(block, req) {
|
||||||
this.hash = req.hash;
|
this.hash = req.hash;
|
||||||
|
|
||||||
for (const index of req.indexes) {
|
for (const index of req.indexes) {
|
||||||
@ -841,7 +850,7 @@ TXResponse.prototype.fromBlock = function fromBlock(block, req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate response from block.
|
* Instantiate response from block.
|
||||||
@ -849,27 +858,27 @@ TXResponse.prototype.fromBlock = function fromBlock(block, req) {
|
|||||||
* @returns {TXResponse}
|
* @returns {TXResponse}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.fromBlock = function fromBlock(block, req) {
|
static fromBlock(block, req) {
|
||||||
return new TXResponse().fromBlock(block, req);
|
return new this().fromBlock(block, req);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize response with witness data.
|
* Serialize response with witness data.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
return this.frameRaw(true);
|
return this.frameRaw(true);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize response without witness data.
|
* Serialize response without witness data.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.toNormal = function toNormal() {
|
toNormal() {
|
||||||
return this.frameRaw(false);
|
return this.frameRaw(false);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write serialized response to a buffer
|
* Write serialized response to a buffer
|
||||||
@ -877,9 +886,9 @@ TXResponse.prototype.toNormal = function toNormal() {
|
|||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
return this.writeRaw(bw, true);
|
return this.writeRaw(bw, true);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write serialized response to a buffer
|
* Write serialized response to a buffer
|
||||||
@ -887,16 +896,16 @@ TXResponse.prototype.toWriter = function toWriter(bw) {
|
|||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.toNormalWriter = function toNormalWriter(bw) {
|
toNormalWriter(bw) {
|
||||||
return this.writeRaw(bw, false);
|
return this.writeRaw(bw, false);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate request serialization size.
|
* Calculate request serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.getSize = function getSize(witness) {
|
getSize(witness) {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += 32;
|
size += 32;
|
||||||
@ -910,7 +919,7 @@ TXResponse.prototype.getSize = function getSize(witness) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write serialized response to buffer writer.
|
* Write serialized response to buffer writer.
|
||||||
@ -919,7 +928,7 @@ TXResponse.prototype.getSize = function getSize(witness) {
|
|||||||
* @param {Boolean} witness
|
* @param {Boolean} witness
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.writeRaw = function writeRaw(bw, witness) {
|
writeRaw(bw, witness) {
|
||||||
bw.writeHash(this.hash);
|
bw.writeHash(this.hash);
|
||||||
|
|
||||||
bw.writeVarint(this.txs.length);
|
bw.writeVarint(this.txs.length);
|
||||||
@ -932,7 +941,7 @@ TXResponse.prototype.writeRaw = function writeRaw(bw, witness) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize response with witness data.
|
* Serialize response with witness data.
|
||||||
@ -941,10 +950,11 @@ TXResponse.prototype.writeRaw = function writeRaw(bw, witness) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXResponse.prototype.frameRaw = function frameRaw(witness) {
|
frameRaw(witness) {
|
||||||
const size = this.getSize(witness);
|
const size = this.getSize(witness);
|
||||||
return this.writeRaw(new StaticWriter(size), witness).render();
|
return this.writeRaw(new StaticWriter(size), witness).render();
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -11,30 +11,30 @@ const assert = require('assert');
|
|||||||
const hash256 = require('bcrypto/lib/hash256');
|
const hash256 = require('bcrypto/lib/hash256');
|
||||||
const BufferReader = require('bufio/lib/reader');
|
const BufferReader = require('bufio/lib/reader');
|
||||||
const StaticWriter = require('bufio/lib/staticwriter');
|
const StaticWriter = require('bufio/lib/staticwriter');
|
||||||
const InvItem = require('./invitem');
|
|
||||||
const encoding = require('bufio/lib/encoding');
|
const encoding = require('bufio/lib/encoding');
|
||||||
|
const InvItem = require('./invitem');
|
||||||
const consensus = require('../protocol/consensus');
|
const consensus = require('../protocol/consensus');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Abstract Block
|
||||||
* The class which all block-like objects inherit from.
|
* The class which all block-like objects inherit from.
|
||||||
* @alias module:primitives.AbstractBlock
|
* @alias module:primitives.AbstractBlock
|
||||||
* @constructor
|
|
||||||
* @abstract
|
* @abstract
|
||||||
* @property {Number} version - Block version. Note
|
* @property {Number} version
|
||||||
* that Bcoin reads versions as unsigned despite
|
* @property {Hash} prevBlock
|
||||||
* them being signed on the protocol level. This
|
* @property {Hash} merkleRoot
|
||||||
* number will never be negative.
|
* @property {Number} time
|
||||||
* @property {Hash} prevBlock - Previous block hash.
|
|
||||||
* @property {Hash} merkleRoot - Merkle root hash.
|
|
||||||
* @property {Number} time - Timestamp.
|
|
||||||
* @property {Number} bits
|
* @property {Number} bits
|
||||||
* @property {Number} nonce
|
* @property {Number} nonce
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function AbstractBlock() {
|
class AbstractBlock {
|
||||||
if (!(this instanceof AbstractBlock))
|
/**
|
||||||
return new AbstractBlock();
|
* Create an abstract block.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor() {
|
||||||
this.version = 1;
|
this.version = 1;
|
||||||
this.prevBlock = encoding.NULL_HASH;
|
this.prevBlock = encoding.NULL_HASH;
|
||||||
this.merkleRoot = encoding.NULL_HASH;
|
this.merkleRoot = encoding.NULL_HASH;
|
||||||
@ -54,7 +54,7 @@ function AbstractBlock() {
|
|||||||
* @param {NakedBlock} options
|
* @param {NakedBlock} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
parseOptions(options) {
|
||||||
assert(options, 'Block data is required.');
|
assert(options, 'Block data is required.');
|
||||||
assert((options.version >>> 0) === options.version);
|
assert((options.version >>> 0) === options.version);
|
||||||
assert(typeof options.prevBlock === 'string');
|
assert(typeof options.prevBlock === 'string');
|
||||||
@ -70,11 +70,13 @@ AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
|||||||
this.bits = options.bits;
|
this.bits = options.bits;
|
||||||
this.nonce = options.nonce;
|
this.nonce = options.nonce;
|
||||||
|
|
||||||
if (options.mutable != null)
|
if (options.mutable != null) {
|
||||||
this.mutable = Boolean(options.mutable);
|
assert(typeof options.mutable === 'boolean');
|
||||||
|
this.mutable = options.mutable;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from json object.
|
* Inject properties from json object.
|
||||||
@ -82,7 +84,7 @@ AbstractBlock.prototype.parseOptions = function parseOptions(options) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.parseJSON = function parseJSON(json) {
|
parseJSON(json) {
|
||||||
assert(json, 'Block data is required.');
|
assert(json, 'Block data is required.');
|
||||||
assert((json.version >>> 0) === json.version);
|
assert((json.version >>> 0) === json.version);
|
||||||
assert(typeof json.prevBlock === 'string');
|
assert(typeof json.prevBlock === 'string');
|
||||||
@ -99,33 +101,33 @@ AbstractBlock.prototype.parseJSON = function parseJSON(json) {
|
|||||||
this.nonce = json.nonce;
|
this.nonce = json.nonce;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the block is a memblock.
|
* Test whether the block is a memblock.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.isMemory = function isMemory() {
|
isMemory() {
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear any cached values (abstract).
|
* Clear any cached values (abstract).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype._refresh = function _refresh() {
|
_refresh() {
|
||||||
this._hash = null;
|
this._hash = null;
|
||||||
this._hhash = null;
|
this._hhash = null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear any cached values.
|
* Clear any cached values.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.refresh = function refresh() {
|
refresh() {
|
||||||
return this._refresh();
|
return this._refresh();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash the block headers.
|
* Hash the block headers.
|
||||||
@ -133,7 +135,7 @@ AbstractBlock.prototype.refresh = function refresh() {
|
|||||||
* @returns {Hash|Buffer} hash
|
* @returns {Hash|Buffer} hash
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.hash = function hash(enc) {
|
hash(enc) {
|
||||||
let h = this._hash;
|
let h = this._hash;
|
||||||
|
|
||||||
if (!h) {
|
if (!h) {
|
||||||
@ -153,16 +155,16 @@ AbstractBlock.prototype.hash = function hash(enc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return h;
|
return h;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the block headers.
|
* Serialize the block headers.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.toHead = function toHead() {
|
toHead() {
|
||||||
return this.writeHead(new StaticWriter(80)).render();
|
return this.writeHead(new StaticWriter(80)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -170,16 +172,16 @@ AbstractBlock.prototype.toHead = function toHead() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.fromHead = function fromHead(data) {
|
fromHead(data) {
|
||||||
return this.readHead(new BufferReader(data));
|
return this.readHead(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the block headers.
|
* Serialize the block headers.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.writeHead = function writeHead(bw) {
|
writeHead(bw) {
|
||||||
bw.writeU32(this.version);
|
bw.writeU32(this.version);
|
||||||
bw.writeHash(this.prevBlock);
|
bw.writeHash(this.prevBlock);
|
||||||
bw.writeHash(this.merkleRoot);
|
bw.writeHash(this.merkleRoot);
|
||||||
@ -187,14 +189,14 @@ AbstractBlock.prototype.writeHead = function writeHead(bw) {
|
|||||||
bw.writeU32(this.bits);
|
bw.writeU32(this.bits);
|
||||||
bw.writeU32(this.nonce);
|
bw.writeU32(this.nonce);
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the block headers.
|
* Parse the block headers.
|
||||||
* @param {BufferReader} br
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.readHead = function readHead(br) {
|
readHead(br) {
|
||||||
this.version = br.readU32();
|
this.version = br.readU32();
|
||||||
this.prevBlock = br.readHash('hex');
|
this.prevBlock = br.readHash('hex');
|
||||||
this.merkleRoot = br.readHash('hex');
|
this.merkleRoot = br.readHash('hex');
|
||||||
@ -202,14 +204,14 @@ AbstractBlock.prototype.readHead = function readHead(br) {
|
|||||||
this.bits = br.readU32();
|
this.bits = br.readU32();
|
||||||
this.nonce = br.readU32();
|
this.nonce = br.readU32();
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the block.
|
* Verify the block.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.verify = function verify() {
|
verify() {
|
||||||
if (!this.verifyPOW())
|
if (!this.verifyPOW())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -217,43 +219,44 @@ AbstractBlock.prototype.verify = function verify() {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify proof-of-work.
|
* Verify proof-of-work.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.verifyPOW = function verifyPOW() {
|
verifyPOW() {
|
||||||
return consensus.verifyPOW(this.hash(), this.bits);
|
return consensus.verifyPOW(this.hash(), this.bits);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the block.
|
* Verify the block.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.verifyBody = function verifyBody() {
|
verifyBody() {
|
||||||
throw new Error('Abstract method.');
|
throw new Error('Abstract method.');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get little-endian block hash.
|
* Get little-endian block hash.
|
||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.rhash = function rhash() {
|
rhash() {
|
||||||
return encoding.revHex(this.hash('hex'));
|
return encoding.revHex(this.hash('hex'));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to an inv item.
|
* Convert the block to an inv item.
|
||||||
* @returns {InvItem}
|
* @returns {InvItem}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
AbstractBlock.prototype.toInv = function toInv() {
|
toInv() {
|
||||||
return new InvItem(InvItem.types.BLOCK, this.hash('hex'));
|
return new InvItem(InvItem.types.BLOCK, this.hash('hex'));
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -8,30 +8,32 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const Network = require('../protocol/network');
|
const {base58, bech32} = require('bstring');
|
||||||
const encoding = require('bufio/lib/encoding');
|
const encoding = require('bufio/lib/encoding');
|
||||||
const sha256 = require('bcrypto/lib/sha256');
|
const sha256 = require('bcrypto/lib/sha256');
|
||||||
const hash160 = require('bcrypto/lib/hash160');
|
const hash160 = require('bcrypto/lib/hash160');
|
||||||
const hash256 = require('bcrypto/lib/hash256');
|
const hash256 = require('bcrypto/lib/hash256');
|
||||||
const BufferReader = require('bufio/lib/reader');
|
const BufferReader = require('bufio/lib/reader');
|
||||||
const StaticWriter = require('bufio/lib/staticwriter');
|
const StaticWriter = require('bufio/lib/staticwriter');
|
||||||
const base58 = require('bstring/lib/base58');
|
const Network = require('../protocol/network');
|
||||||
const bech32 = require('bstring/lib/bech32');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Address
|
||||||
* Represents an address.
|
* Represents an address.
|
||||||
* @alias module:primitives.Address
|
* @alias module:primitives.Address
|
||||||
* @constructor
|
|
||||||
* @param {Object?} options
|
|
||||||
* @property {Buffer} hash
|
* @property {Buffer} hash
|
||||||
* @property {AddressPrefix} type
|
* @property {AddressPrefix} type
|
||||||
* @property {Number} version
|
* @property {Number} version
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Address(options, network) {
|
class Address {
|
||||||
if (!(this instanceof Address))
|
/**
|
||||||
return new Address(options, network);
|
* Create an address.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options, network) {
|
||||||
this.type = Address.types.PUBKEYHASH;
|
this.type = Address.types.PUBKEYHASH;
|
||||||
this.version = -1;
|
this.version = -1;
|
||||||
this.hash = encoding.ZERO_HASH160;
|
this.hash = encoding.ZERO_HASH160;
|
||||||
@ -40,42 +42,22 @@ function Address(options, network) {
|
|||||||
this.fromOptions(options, network);
|
this.fromOptions(options, network);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Address types.
|
|
||||||
* @enum {Number}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Address.types = {
|
|
||||||
PUBKEYHASH: 2,
|
|
||||||
SCRIPTHASH: 3,
|
|
||||||
WITNESS: 4
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Address types by value.
|
|
||||||
* @const {RevMap}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Address.typesByVal = [
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
'PUBKEYHASH',
|
|
||||||
'SCRIPTHASH',
|
|
||||||
'WITNESS'
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromOptions = function fromOptions(options, network) {
|
fromOptions(options, network) {
|
||||||
if (typeof options === 'string')
|
if (typeof options === 'string')
|
||||||
return this.fromString(options, network);
|
return this.fromString(options, network);
|
||||||
|
|
||||||
return this.fromHash(options.hash, options.type, options.version);
|
assert(options);
|
||||||
};
|
|
||||||
|
const {hash, type, version} = options;
|
||||||
|
|
||||||
|
return this.fromHash(hash, type, version);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insantiate address from options.
|
* Insantiate address from options.
|
||||||
@ -83,9 +65,9 @@ Address.prototype.fromOptions = function fromOptions(options, network) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromOptions = function fromOptions(options, network) {
|
static fromOptions(options, network) {
|
||||||
return new Address().fromOptions(options, network);
|
return new this().fromOptions(options, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the address hash.
|
* Get the address hash.
|
||||||
@ -93,18 +75,18 @@ Address.fromOptions = function fromOptions(options, network) {
|
|||||||
* @returns {Hash|Buffer}
|
* @returns {Hash|Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.getHash = function getHash(enc) {
|
getHash(enc) {
|
||||||
if (enc === 'hex')
|
if (enc === 'hex')
|
||||||
return this.hash.toString(enc);
|
return this.hash.toString(enc);
|
||||||
return this.hash;
|
return this.hash;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is null.
|
* Test whether the address is null.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.isNull = function isNull() {
|
isNull() {
|
||||||
if (this.hash.length === 20)
|
if (this.hash.length === 20)
|
||||||
return this.hash.equals(encoding.ZERO_HASH160);
|
return this.hash.equals(encoding.ZERO_HASH160);
|
||||||
|
|
||||||
@ -117,7 +99,7 @@ Address.prototype.isNull = function isNull() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test equality against another address.
|
* Test equality against another address.
|
||||||
@ -125,22 +107,22 @@ Address.prototype.isNull = function isNull() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.equals = function equals(addr) {
|
equals(addr) {
|
||||||
assert(addr instanceof Address);
|
assert(addr instanceof Address);
|
||||||
|
|
||||||
return this.type === addr.type
|
return this.type === addr.type
|
||||||
&& this.version === addr.version
|
&& this.version === addr.version
|
||||||
&& this.hash.equals(addr.hash);
|
&& this.hash.equals(addr.hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the address type as a string.
|
* Get the address type as a string.
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.getType = function getType() {
|
getType() {
|
||||||
return Address.typesByVal[this.type].toLowerCase();
|
return Address.typesByVal[this.type].toLowerCase();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a network address prefix for the address.
|
* Get a network address prefix for the address.
|
||||||
@ -148,7 +130,7 @@ Address.prototype.getType = function getType() {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.getPrefix = function getPrefix(network) {
|
getPrefix(network) {
|
||||||
network = Network.get(network);
|
network = Network.get(network);
|
||||||
|
|
||||||
const prefixes = network.addressPrefix;
|
const prefixes = network.addressPrefix;
|
||||||
@ -169,21 +151,21 @@ Address.prototype.getPrefix = function getPrefix(network) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate size of serialized address.
|
* Calculate size of serialized address.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 5 + this.hash.length;
|
let size = 5 + this.hash.length;
|
||||||
|
|
||||||
if (this.version !== -1)
|
if (this.version !== -1)
|
||||||
size += 2;
|
size += 2;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the address object to its raw serialization.
|
* Compile the address object to its raw serialization.
|
||||||
@ -192,7 +174,7 @@ Address.prototype.getSize = function getSize() {
|
|||||||
* @throws Error on bad hash/prefix.
|
* @throws Error on bad hash/prefix.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.toRaw = function toRaw(network) {
|
toRaw(network) {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const bw = new StaticWriter(size);
|
const bw = new StaticWriter(size);
|
||||||
const prefix = this.getPrefix(network);
|
const prefix = this.getPrefix(network);
|
||||||
@ -210,7 +192,7 @@ Address.prototype.toRaw = function toRaw(network) {
|
|||||||
bw.writeChecksum(hash256.digest);
|
bw.writeChecksum(hash256.digest);
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the address object to a base58 address.
|
* Compile the address object to a base58 address.
|
||||||
@ -219,9 +201,9 @@ Address.prototype.toRaw = function toRaw(network) {
|
|||||||
* @throws Error on bad hash/prefix.
|
* @throws Error on bad hash/prefix.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.toBase58 = function toBase58(network) {
|
toBase58(network) {
|
||||||
return base58.encode(this.toRaw(network));
|
return base58.encode(this.toRaw(network));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compile the address object to a bech32 address.
|
* Compile the address object to a bech32 address.
|
||||||
@ -230,7 +212,7 @@ Address.prototype.toBase58 = function toBase58(network) {
|
|||||||
* @throws Error on bad hash/prefix.
|
* @throws Error on bad hash/prefix.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.toBech32 = function toBech32(network) {
|
toBech32(network) {
|
||||||
const version = this.version;
|
const version = this.version;
|
||||||
const hash = this.hash;
|
const hash = this.hash;
|
||||||
|
|
||||||
@ -242,7 +224,7 @@ Address.prototype.toBech32 = function toBech32(network) {
|
|||||||
const hrp = network.addressPrefix.bech32;
|
const hrp = network.addressPrefix.bech32;
|
||||||
|
|
||||||
return bech32.encode(hrp, version, hash);
|
return bech32.encode(hrp, version, hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from string.
|
* Inject properties from string.
|
||||||
@ -252,7 +234,7 @@ Address.prototype.toBech32 = function toBech32(network) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromString = function fromString(addr, network) {
|
fromString(addr, network) {
|
||||||
assert(typeof addr === 'string');
|
assert(typeof addr === 'string');
|
||||||
assert(addr.length > 0);
|
assert(addr.length > 0);
|
||||||
assert(addr.length <= 100);
|
assert(addr.length <= 100);
|
||||||
@ -268,7 +250,7 @@ Address.prototype.fromString = function fromString(addr, network) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
return this.fromBase58(addr, network);
|
return this.fromBase58(addr, network);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate address from string.
|
* Instantiate address from string.
|
||||||
@ -277,9 +259,9 @@ Address.prototype.fromString = function fromString(addr, network) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromString = function fromString(addr, network) {
|
static fromString(addr, network) {
|
||||||
return new Address().fromString(addr, network);
|
return new this().fromString(addr, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the Address to a string.
|
* Convert the Address to a string.
|
||||||
@ -287,24 +269,24 @@ Address.fromString = function fromString(addr, network) {
|
|||||||
* @returns {Base58Address}
|
* @returns {Base58Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.toString = function toString(network) {
|
toString(network) {
|
||||||
if (this.version !== -1)
|
if (this.version !== -1)
|
||||||
return this.toBech32(network);
|
return this.toBech32(network);
|
||||||
return this.toBase58(network);
|
return this.toBase58(network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the Address.
|
* Inspect the Address.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return '<Address:'
|
return '<Address:'
|
||||||
+ ` type=${this.getType()}`
|
+ ` type=${this.getType()}`
|
||||||
+ ` version=${this.version}`
|
+ ` version=${this.version}`
|
||||||
+ ` str=${this.toString()}`
|
+ ` str=${this.toString()}`
|
||||||
+ '>';
|
+ '>';
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -313,7 +295,7 @@ Address.prototype.inspect = function inspect() {
|
|||||||
* @throws Parse error
|
* @throws Parse error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromRaw = function fromRaw(data, network) {
|
fromRaw(data, network) {
|
||||||
const br = new BufferReader(data, true);
|
const br = new BufferReader(data, true);
|
||||||
const prefix = br.readU8();
|
const prefix = br.readU8();
|
||||||
|
|
||||||
@ -340,7 +322,7 @@ Address.prototype.fromRaw = function fromRaw(data, network) {
|
|||||||
br.verifyChecksum(hash256.digest);
|
br.verifyChecksum(hash256.digest);
|
||||||
|
|
||||||
return this.fromHash(hash, type, version);
|
return this.fromHash(hash, type, version);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an address object from a serialized address.
|
* Create an address object from a serialized address.
|
||||||
@ -349,9 +331,9 @@ Address.prototype.fromRaw = function fromRaw(data, network) {
|
|||||||
* @throws Parse error.
|
* @throws Parse error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromRaw = function fromRaw(data, network) {
|
static fromRaw(data, network) {
|
||||||
return new Address().fromRaw(data, network);
|
return new this().fromRaw(data, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from base58 address.
|
* Inject properties from base58 address.
|
||||||
@ -361,14 +343,14 @@ Address.fromRaw = function fromRaw(data, network) {
|
|||||||
* @throws Parse error
|
* @throws Parse error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromBase58 = function fromBase58(data, network) {
|
fromBase58(data, network) {
|
||||||
assert(typeof data === 'string');
|
assert(typeof data === 'string');
|
||||||
|
|
||||||
if (data.length > 55)
|
if (data.length > 55)
|
||||||
throw new Error('Address is too long.');
|
throw new Error('Address is too long.');
|
||||||
|
|
||||||
return this.fromRaw(base58.decode(data), network);
|
return this.fromRaw(base58.decode(data), network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an address object from a base58 address.
|
* Create an address object from a base58 address.
|
||||||
@ -378,9 +360,9 @@ Address.prototype.fromBase58 = function fromBase58(data, network) {
|
|||||||
* @throws Parse error.
|
* @throws Parse error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromBase58 = function fromBase58(data, network) {
|
static fromBase58(data, network) {
|
||||||
return new Address().fromBase58(data, network);
|
return new this().fromBase58(data, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from bech32 address.
|
* Inject properties from bech32 address.
|
||||||
@ -390,7 +372,7 @@ Address.fromBase58 = function fromBase58(data, network) {
|
|||||||
* @throws Parse error
|
* @throws Parse error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromBech32 = function fromBech32(data, network) {
|
fromBech32(data, network) {
|
||||||
const type = Address.types.WITNESS;
|
const type = Address.types.WITNESS;
|
||||||
|
|
||||||
assert(typeof data === 'string');
|
assert(typeof data === 'string');
|
||||||
@ -400,7 +382,7 @@ Address.prototype.fromBech32 = function fromBech32(data, network) {
|
|||||||
Network.fromBech32(addr.hrp, network);
|
Network.fromBech32(addr.hrp, network);
|
||||||
|
|
||||||
return this.fromHash(addr.hash, type, addr.version);
|
return this.fromHash(addr.hash, type, addr.version);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an address object from a bech32 address.
|
* Create an address object from a bech32 address.
|
||||||
@ -410,9 +392,9 @@ Address.prototype.fromBech32 = function fromBech32(data, network) {
|
|||||||
* @throws Parse error.
|
* @throws Parse error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromBech32 = function fromBech32(data, network) {
|
static fromBech32(data, network) {
|
||||||
return new Address().fromBech32(data, network);
|
return new this().fromBech32(data, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from output script.
|
* Inject properties from output script.
|
||||||
@ -420,7 +402,7 @@ Address.fromBech32 = function fromBech32(data, network) {
|
|||||||
* @param {Script} script
|
* @param {Script} script
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromScript = function fromScript(script) {
|
fromScript(script) {
|
||||||
const pk = script.getPubkey();
|
const pk = script.getPubkey();
|
||||||
|
|
||||||
if (pk) {
|
if (pk) {
|
||||||
@ -466,7 +448,7 @@ Address.prototype.fromScript = function fromScript(script) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from witness.
|
* Inject properties from witness.
|
||||||
@ -474,7 +456,7 @@ Address.prototype.fromScript = function fromScript(script) {
|
|||||||
* @param {Witness} witness
|
* @param {Witness} witness
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromWitness = function fromWitness(witness) {
|
fromWitness(witness) {
|
||||||
const [, pk] = witness.getPubkeyhashInput();
|
const [, pk] = witness.getPubkeyhashInput();
|
||||||
|
|
||||||
// We're pretty much screwed here
|
// We're pretty much screwed here
|
||||||
@ -496,7 +478,7 @@ Address.prototype.fromWitness = function fromWitness(witness) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from input script.
|
* Inject properties from input script.
|
||||||
@ -504,7 +486,7 @@ Address.prototype.fromWitness = function fromWitness(witness) {
|
|||||||
* @param {Script} script
|
* @param {Script} script
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromInputScript = function fromInputScript(script) {
|
fromInputScript(script) {
|
||||||
const [, pk] = script.getPubkeyhashInput();
|
const [, pk] = script.getPubkeyhashInput();
|
||||||
|
|
||||||
if (pk) {
|
if (pk) {
|
||||||
@ -524,7 +506,7 @@ Address.prototype.fromInputScript = function fromInputScript(script) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an Address from a witness.
|
* Create an Address from a witness.
|
||||||
@ -534,9 +516,9 @@ Address.prototype.fromInputScript = function fromInputScript(script) {
|
|||||||
* @returns {Address|null}
|
* @returns {Address|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromWitness = function fromWitness(witness) {
|
static fromWitness(witness) {
|
||||||
return new Address().fromWitness(witness);
|
return new this().fromWitness(witness);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an Address from an input script.
|
* Create an Address from an input script.
|
||||||
@ -546,9 +528,9 @@ Address.fromWitness = function fromWitness(witness) {
|
|||||||
* @returns {Address|null}
|
* @returns {Address|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromInputScript = function fromInputScript(script) {
|
static fromInputScript(script) {
|
||||||
return new Address().fromInputScript(script);
|
return new this().fromInputScript(script);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an Address from an output script.
|
* Create an Address from an output script.
|
||||||
@ -559,9 +541,9 @@ Address.fromInputScript = function fromInputScript(script) {
|
|||||||
* @returns {Address|null}
|
* @returns {Address|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromScript = function fromScript(script) {
|
static fromScript(script) {
|
||||||
return new Address().fromScript(script);
|
return new this().fromScript(script);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from a hash.
|
* Inject properties from a hash.
|
||||||
@ -572,7 +554,7 @@ Address.fromScript = function fromScript(script) {
|
|||||||
* @throws on bad hash size
|
* @throws on bad hash size
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromHash = function fromHash(hash, type, version) {
|
fromHash(hash, type, version) {
|
||||||
if (typeof hash === 'string')
|
if (typeof hash === 'string')
|
||||||
hash = Buffer.from(hash, 'hex');
|
hash = Buffer.from(hash, 'hex');
|
||||||
|
|
||||||
@ -612,7 +594,7 @@ Address.prototype.fromHash = function fromHash(hash, type, version) {
|
|||||||
this.version = version;
|
this.version = version;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a naked address from hash/type/version.
|
* Create a naked address from hash/type/version.
|
||||||
@ -623,9 +605,9 @@ Address.prototype.fromHash = function fromHash(hash, type, version) {
|
|||||||
* @throws on bad hash size
|
* @throws on bad hash size
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromHash = function fromHash(hash, type, version) {
|
static fromHash(hash, type, version) {
|
||||||
return new Address().fromHash(hash, type, version);
|
return new this().fromHash(hash, type, version);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from pubkeyhash.
|
* Inject properties from pubkeyhash.
|
||||||
@ -634,11 +616,11 @@ Address.fromHash = function fromHash(hash, type, version) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromPubkeyhash = function fromPubkeyhash(hash) {
|
fromPubkeyhash(hash) {
|
||||||
const type = Address.types.PUBKEYHASH;
|
const type = Address.types.PUBKEYHASH;
|
||||||
assert(hash.length === 20, 'P2PKH must be 20 bytes.');
|
assert(hash.length === 20, 'P2PKH must be 20 bytes.');
|
||||||
return this.fromHash(hash, type, -1);
|
return this.fromHash(hash, type, -1);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate address from pubkeyhash.
|
* Instantiate address from pubkeyhash.
|
||||||
@ -646,9 +628,9 @@ Address.prototype.fromPubkeyhash = function fromPubkeyhash(hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromPubkeyhash = function fromPubkeyhash(hash) {
|
static fromPubkeyhash(hash) {
|
||||||
return new Address().fromPubkeyhash(hash);
|
return new this().fromPubkeyhash(hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from scripthash.
|
* Inject properties from scripthash.
|
||||||
@ -657,11 +639,11 @@ Address.fromPubkeyhash = function fromPubkeyhash(hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromScripthash = function fromScripthash(hash) {
|
fromScripthash(hash) {
|
||||||
const type = Address.types.SCRIPTHASH;
|
const type = Address.types.SCRIPTHASH;
|
||||||
assert(hash && hash.length === 20, 'P2SH must be 20 bytes.');
|
assert(hash && hash.length === 20, 'P2SH must be 20 bytes.');
|
||||||
return this.fromHash(hash, type, -1);
|
return this.fromHash(hash, type, -1);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate address from scripthash.
|
* Instantiate address from scripthash.
|
||||||
@ -669,9 +651,9 @@ Address.prototype.fromScripthash = function fromScripthash(hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromScripthash = function fromScripthash(hash) {
|
static fromScripthash(hash) {
|
||||||
return new Address().fromScripthash(hash);
|
return new this().fromScripthash(hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from witness pubkeyhash.
|
* Inject properties from witness pubkeyhash.
|
||||||
@ -680,11 +662,11 @@ Address.fromScripthash = function fromScripthash(hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash) {
|
fromWitnessPubkeyhash(hash) {
|
||||||
const type = Address.types.WITNESS;
|
const type = Address.types.WITNESS;
|
||||||
assert(hash && hash.length === 20, 'P2WPKH must be 20 bytes.');
|
assert(hash && hash.length === 20, 'P2WPKH must be 20 bytes.');
|
||||||
return this.fromHash(hash, type, 0);
|
return this.fromHash(hash, type, 0);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate address from witness pubkeyhash.
|
* Instantiate address from witness pubkeyhash.
|
||||||
@ -692,9 +674,9 @@ Address.prototype.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash) {
|
static fromWitnessPubkeyhash(hash) {
|
||||||
return new Address().fromWitnessPubkeyhash(hash);
|
return new this().fromWitnessPubkeyhash(hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from witness scripthash.
|
* Inject properties from witness scripthash.
|
||||||
@ -703,11 +685,11 @@ Address.fromWitnessPubkeyhash = function fromWitnessPubkeyhash(hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromWitnessScripthash = function fromWitnessScripthash(hash) {
|
fromWitnessScripthash(hash) {
|
||||||
const type = Address.types.WITNESS;
|
const type = Address.types.WITNESS;
|
||||||
assert(hash && hash.length === 32, 'P2WPKH must be 32 bytes.');
|
assert(hash && hash.length === 32, 'P2WPKH must be 32 bytes.');
|
||||||
return this.fromHash(hash, type, 0);
|
return this.fromHash(hash, type, 0);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate address from witness scripthash.
|
* Instantiate address from witness scripthash.
|
||||||
@ -715,9 +697,9 @@ Address.prototype.fromWitnessScripthash = function fromWitnessScripthash(hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromWitnessScripthash = function fromWitnessScripthash(hash) {
|
static fromWitnessScripthash(hash) {
|
||||||
return new Address().fromWitnessScripthash(hash);
|
return new this().fromWitnessScripthash(hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from witness program.
|
* Inject properties from witness program.
|
||||||
@ -727,7 +709,7 @@ Address.fromWitnessScripthash = function fromWitnessScripthash(hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.fromProgram = function fromProgram(version, hash) {
|
fromProgram(version, hash) {
|
||||||
const type = Address.types.WITNESS;
|
const type = Address.types.WITNESS;
|
||||||
|
|
||||||
assert(version >= 0, 'Bad version for witness program.');
|
assert(version >= 0, 'Bad version for witness program.');
|
||||||
@ -736,7 +718,7 @@ Address.prototype.fromProgram = function fromProgram(version, hash) {
|
|||||||
hash = Buffer.from(hash, 'hex');
|
hash = Buffer.from(hash, 'hex');
|
||||||
|
|
||||||
return this.fromHash(hash, type, version);
|
return this.fromHash(hash, type, version);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate address from witness program.
|
* Instantiate address from witness program.
|
||||||
@ -745,70 +727,70 @@ Address.prototype.fromProgram = function fromProgram(version, hash) {
|
|||||||
* @returns {Address}
|
* @returns {Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.fromProgram = function fromProgram(version, hash) {
|
static fromProgram(version, hash) {
|
||||||
return new Address().fromProgram(version, hash);
|
return new this().fromProgram(version, hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is pubkeyhash.
|
* Test whether the address is pubkeyhash.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.isPubkeyhash = function isPubkeyhash() {
|
isPubkeyhash() {
|
||||||
return this.type === Address.types.PUBKEYHASH;
|
return this.type === Address.types.PUBKEYHASH;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is scripthash.
|
* Test whether the address is scripthash.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.isScripthash = function isScripthash() {
|
isScripthash() {
|
||||||
return this.type === Address.types.SCRIPTHASH;
|
return this.type === Address.types.SCRIPTHASH;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is witness pubkeyhash.
|
* Test whether the address is witness pubkeyhash.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.isWitnessPubkeyhash = function isWitnessPubkeyhash() {
|
isWitnessPubkeyhash() {
|
||||||
return this.version === 0 && this.hash.length === 20;
|
return this.version === 0 && this.hash.length === 20;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is witness scripthash.
|
* Test whether the address is witness scripthash.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.isWitnessScripthash = function isWitnessScripthash() {
|
isWitnessScripthash() {
|
||||||
return this.version === 0 && this.hash.length === 32;
|
return this.version === 0 && this.hash.length === 32;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is witness masthash.
|
* Test whether the address is witness masthash.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.isWitnessMasthash = function isWitnessMasthash() {
|
isWitnessMasthash() {
|
||||||
return this.version === 1 && this.hash.length === 32;
|
return this.version === 1 && this.hash.length === 32;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is a witness program.
|
* Test whether the address is a witness program.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.isProgram = function isProgram() {
|
isProgram() {
|
||||||
return this.version !== -1;
|
return this.version !== -1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is an unknown witness program.
|
* Test whether the address is an unknown witness program.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.prototype.isUnknown = function isUnknown() {
|
isUnknown() {
|
||||||
if (this.version === -1)
|
if (this.version === -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -816,7 +798,7 @@ Address.prototype.isUnknown = function isUnknown() {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
return this.hash.length !== 20 && this.hash.length !== 32;
|
return this.hash.length !== 20 && this.hash.length !== 32;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the hash of a base58 address or address-related object.
|
* Get the hash of a base58 address or address-related object.
|
||||||
@ -826,7 +808,7 @@ Address.prototype.isUnknown = function isUnknown() {
|
|||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.getHash = function getHash(data, enc, network) {
|
static getHash(data, enc, network) {
|
||||||
if (!data)
|
if (!data)
|
||||||
throw new Error('Object is not an address.');
|
throw new Error('Object is not an address.');
|
||||||
|
|
||||||
@ -850,7 +832,7 @@ Address.getHash = function getHash(data, enc, network) {
|
|||||||
return enc === 'hex'
|
return enc === 'hex'
|
||||||
? hash.toString('hex')
|
? hash.toString('hex')
|
||||||
: hash;
|
: hash;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an address type for a specified network address prefix.
|
* Get an address type for a specified network address prefix.
|
||||||
@ -859,8 +841,9 @@ Address.getHash = function getHash(data, enc, network) {
|
|||||||
* @returns {AddressType}
|
* @returns {AddressType}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Address.getType = function getType(prefix, network) {
|
static getType(prefix, network) {
|
||||||
const prefixes = network.addressPrefix;
|
const prefixes = network.addressPrefix;
|
||||||
|
|
||||||
switch (prefix) {
|
switch (prefix) {
|
||||||
case prefixes.pubkeyhash:
|
case prefixes.pubkeyhash:
|
||||||
return Address.types.PUBKEYHASH;
|
return Address.types.PUBKEYHASH;
|
||||||
@ -872,8 +855,33 @@ Address.getType = function getType(prefix, network) {
|
|||||||
default:
|
default:
|
||||||
throw new Error('Unknown address prefix.');
|
throw new Error('Unknown address prefix.');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address types.
|
||||||
|
* @enum {Number}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Address.types = {
|
||||||
|
PUBKEYHASH: 2,
|
||||||
|
SCRIPTHASH: 3,
|
||||||
|
WITNESS: 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address types by value.
|
||||||
|
* @const {RevMap}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Address.typesByVal = [
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
'PUBKEYHASH',
|
||||||
|
'SCRIPTHASH',
|
||||||
|
'WITNESS'
|
||||||
|
];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -22,18 +22,21 @@ const Headers = require('./headers');
|
|||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Block
|
||||||
* Represents a full block.
|
* Represents a full block.
|
||||||
* @alias module:primitives.Block
|
* @alias module:primitives.Block
|
||||||
* @constructor
|
|
||||||
* @extends AbstractBlock
|
* @extends AbstractBlock
|
||||||
* @param {NakedBlock} options
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Block(options) {
|
class Block extends AbstractBlock {
|
||||||
if (!(this instanceof Block))
|
/**
|
||||||
return new Block(options);
|
* Create a block.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
|
||||||
AbstractBlock.call(this);
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
|
||||||
this.txs = [];
|
this.txs = [];
|
||||||
|
|
||||||
@ -45,15 +48,13 @@ function Block(options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Block.prototype, AbstractBlock.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
this.parseOptions(options);
|
this.parseOptions(options);
|
||||||
|
|
||||||
if (options.txs) {
|
if (options.txs) {
|
||||||
@ -63,7 +64,7 @@ Block.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.txs.push(tx);
|
this.txs.push(tx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate block from options.
|
* Instantiate block from options.
|
||||||
@ -71,16 +72,16 @@ Block.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Block}
|
* @returns {Block}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new Block().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear any cached values.
|
* Clear any cached values.
|
||||||
* @param {Boolean?} all - Clear transactions.
|
* @param {Boolean?} all - Clear transactions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.refresh = function refresh(all) {
|
refresh(all) {
|
||||||
this._refresh();
|
this._refresh();
|
||||||
|
|
||||||
this._raw = null;
|
this._raw = null;
|
||||||
@ -92,34 +93,34 @@ Block.prototype.refresh = function refresh(all) {
|
|||||||
|
|
||||||
for (const tx of this.txs)
|
for (const tx of this.txs)
|
||||||
tx.refresh();
|
tx.refresh();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the block. Include witnesses if present.
|
* Serialize the block. Include witnesses if present.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
return this.frame().data;
|
return this.frame().data;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the block, do not include witnesses.
|
* Serialize the block, do not include witnesses.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.toNormal = function toNormal() {
|
toNormal() {
|
||||||
if (this.hasWitness())
|
if (this.hasWitness())
|
||||||
return this.frameNormal().data;
|
return this.frameNormal().data;
|
||||||
return this.toRaw();
|
return this.toRaw();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the block. Include witnesses if present.
|
* Serialize the block. Include witnesses if present.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
if (this.mutable)
|
if (this.mutable)
|
||||||
return this.writeWitness(bw);
|
return this.writeWitness(bw);
|
||||||
|
|
||||||
@ -127,20 +128,20 @@ Block.prototype.toWriter = function toWriter(bw) {
|
|||||||
bw.writeBytes(raw.data);
|
bw.writeBytes(raw.data);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the block, do not include witnesses.
|
* Serialize the block, do not include witnesses.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.toNormalWriter = function toNormalWriter(bw) {
|
toNormalWriter(bw) {
|
||||||
if (this.hasWitness()) {
|
if (this.hasWitness()) {
|
||||||
this.writeNormal(bw);
|
this.writeNormal(bw);
|
||||||
return bw;
|
return bw;
|
||||||
}
|
}
|
||||||
return this.toWriter(bw);
|
return this.toWriter(bw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the raw block serialization.
|
* Get the raw block serialization.
|
||||||
@ -149,7 +150,7 @@ Block.prototype.toNormalWriter = function toNormalWriter(bw) {
|
|||||||
* @returns {RawBlock}
|
* @returns {RawBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.frame = function frame() {
|
frame() {
|
||||||
if (this.mutable) {
|
if (this.mutable) {
|
||||||
assert(!this._raw);
|
assert(!this._raw);
|
||||||
return this.frameWitness();
|
return this.frameWitness();
|
||||||
@ -170,58 +171,58 @@ Block.prototype.frame = function frame() {
|
|||||||
this._witness = raw.witness;
|
this._witness = raw.witness;
|
||||||
|
|
||||||
return raw;
|
return raw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate real size and size of the witness bytes.
|
* Calculate real size and size of the witness bytes.
|
||||||
* @returns {Object} Contains `size` and `witness`.
|
* @returns {Object} Contains `size` and `witness`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getSizes = function getSizes() {
|
getSizes() {
|
||||||
if (this.mutable)
|
if (this.mutable)
|
||||||
return this.getWitnessSizes();
|
return this.getWitnessSizes();
|
||||||
return this.frame();
|
return this.frame();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate virtual block size.
|
* Calculate virtual block size.
|
||||||
* @returns {Number} Virtual size.
|
* @returns {Number} Virtual size.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getVirtualSize = function getVirtualSize() {
|
getVirtualSize() {
|
||||||
const scale = consensus.WITNESS_SCALE_FACTOR;
|
const scale = consensus.WITNESS_SCALE_FACTOR;
|
||||||
return (this.getWeight() + scale - 1) / scale | 0;
|
return (this.getWeight() + scale - 1) / scale | 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate block weight.
|
* Calculate block weight.
|
||||||
* @returns {Number} weight
|
* @returns {Number} weight
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getWeight = function getWeight() {
|
getWeight() {
|
||||||
const raw = this.getSizes();
|
const raw = this.getSizes();
|
||||||
const base = raw.size - raw.witness;
|
const base = raw.size - raw.witness;
|
||||||
return base * (consensus.WITNESS_SCALE_FACTOR - 1) + raw.size;
|
return base * (consensus.WITNESS_SCALE_FACTOR - 1) + raw.size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get real block size.
|
* Get real block size.
|
||||||
* @returns {Number} size
|
* @returns {Number} size
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
return this.getSizes().size;
|
return this.getSizes().size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get base block size (without witness).
|
* Get base block size (without witness).
|
||||||
* @returns {Number} size
|
* @returns {Number} size
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getBaseSize = function getBaseSize() {
|
getBaseSize() {
|
||||||
const raw = this.getSizes();
|
const raw = this.getSizes();
|
||||||
return raw.size - raw.witness;
|
return raw.size - raw.witness;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the block contains a
|
* Test whether the block contains a
|
||||||
@ -229,7 +230,7 @@ Block.prototype.getBaseSize = function getBaseSize() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.hasWitness = function hasWitness() {
|
hasWitness() {
|
||||||
if (this._witness !== -1)
|
if (this._witness !== -1)
|
||||||
return this._witness !== 0;
|
return this._witness !== 0;
|
||||||
|
|
||||||
@ -239,7 +240,7 @@ Block.prototype.hasWitness = function hasWitness() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the block's transaction vector against a hash.
|
* Test the block's transaction vector against a hash.
|
||||||
@ -247,9 +248,9 @@ Block.prototype.hasWitness = function hasWitness() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.hasTX = function hasTX(hash) {
|
hasTX(hash) {
|
||||||
return this.indexOf(hash) !== -1;
|
return this.indexOf(hash) !== -1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the index of a transaction in the block.
|
* Find the index of a transaction in the block.
|
||||||
@ -257,7 +258,7 @@ Block.prototype.hasTX = function hasTX(hash) {
|
|||||||
* @returns {Number} index (-1 if not present).
|
* @returns {Number} index (-1 if not present).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.indexOf = function indexOf(hash) {
|
indexOf(hash) {
|
||||||
for (let i = 0; i < this.txs.length; i++) {
|
for (let i = 0; i < this.txs.length; i++) {
|
||||||
const tx = this.txs[i];
|
const tx = this.txs[i];
|
||||||
if (tx.hash('hex') === hash)
|
if (tx.hash('hex') === hash)
|
||||||
@ -265,7 +266,7 @@ Block.prototype.indexOf = function indexOf(hash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate merkle root. Returns null
|
* Calculate merkle root. Returns null
|
||||||
@ -274,7 +275,7 @@ Block.prototype.indexOf = function indexOf(hash) {
|
|||||||
* @returns {Hash|null}
|
* @returns {Hash|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.createMerkleRoot = function createMerkleRoot(enc) {
|
createMerkleRoot(enc) {
|
||||||
const leaves = [];
|
const leaves = [];
|
||||||
|
|
||||||
for (const tx of this.txs)
|
for (const tx of this.txs)
|
||||||
@ -286,16 +287,16 @@ Block.prototype.createMerkleRoot = function createMerkleRoot(enc) {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
return enc === 'hex' ? root.toString('hex') : root;
|
return enc === 'hex' ? root.toString('hex') : root;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a witness nonce (for mining).
|
* Create a witness nonce (for mining).
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.createWitnessNonce = function createWitnessNonce() {
|
createWitnessNonce() {
|
||||||
return Buffer.from(encoding.ZERO_HASH);
|
return Buffer.from(encoding.ZERO_HASH);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate commitment hash (the root of the
|
* Calculate commitment hash (the root of the
|
||||||
@ -304,7 +305,7 @@ Block.prototype.createWitnessNonce = function createWitnessNonce() {
|
|||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.createCommitmentHash = function createCommitmentHash(enc) {
|
createCommitmentHash(enc) {
|
||||||
const nonce = this.getWitnessNonce();
|
const nonce = this.getWitnessNonce();
|
||||||
const leaves = [];
|
const leaves = [];
|
||||||
|
|
||||||
@ -327,7 +328,7 @@ Block.prototype.createCommitmentHash = function createCommitmentHash(enc) {
|
|||||||
return enc === 'hex'
|
return enc === 'hex'
|
||||||
? hash.toString('hex')
|
? hash.toString('hex')
|
||||||
: hash;
|
: hash;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the merkle root from the block header.
|
* Retrieve the merkle root from the block header.
|
||||||
@ -335,11 +336,11 @@ Block.prototype.createCommitmentHash = function createCommitmentHash(enc) {
|
|||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getMerkleRoot = function getMerkleRoot(enc) {
|
getMerkleRoot(enc) {
|
||||||
if (enc === 'hex')
|
if (enc === 'hex')
|
||||||
return this.merkleRoot;
|
return this.merkleRoot;
|
||||||
return Buffer.from(this.merkleRoot, 'hex');
|
return Buffer.from(this.merkleRoot, 'hex');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the witness nonce from the
|
* Retrieve the witness nonce from the
|
||||||
@ -347,7 +348,7 @@ Block.prototype.getMerkleRoot = function getMerkleRoot(enc) {
|
|||||||
* @returns {Buffer|null}
|
* @returns {Buffer|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getWitnessNonce = function getWitnessNonce() {
|
getWitnessNonce() {
|
||||||
if (this.txs.length === 0)
|
if (this.txs.length === 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -365,7 +366,7 @@ Block.prototype.getWitnessNonce = function getWitnessNonce() {
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
return input.witness.items[0];
|
return input.witness.items[0];
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the commitment hash
|
* Retrieve the commitment hash
|
||||||
@ -374,7 +375,7 @@ Block.prototype.getWitnessNonce = function getWitnessNonce() {
|
|||||||
* @returns {Hash|null}
|
* @returns {Hash|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
|
getCommitmentHash(enc) {
|
||||||
if (this.txs.length === 0)
|
if (this.txs.length === 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -395,7 +396,7 @@ Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
|
|||||||
return enc === 'hex'
|
return enc === 'hex'
|
||||||
? hash.toString('hex')
|
? hash.toString('hex')
|
||||||
: hash;
|
: hash;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do non-contextual verification on the block. Including checking the block
|
* Do non-contextual verification on the block. Including checking the block
|
||||||
@ -403,10 +404,10 @@ Block.prototype.getCommitmentHash = function getCommitmentHash(enc) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.verifyBody = function verifyBody() {
|
verifyBody() {
|
||||||
const [valid] = this.checkBody();
|
const [valid] = this.checkBody();
|
||||||
return valid;
|
return valid;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do non-contextual verification on the block. Including checking the block
|
* Do non-contextual verification on the block. Including checking the block
|
||||||
@ -414,7 +415,7 @@ Block.prototype.verifyBody = function verifyBody() {
|
|||||||
* @returns {Array} [valid, reason, score]
|
* @returns {Array} [valid, reason, score]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.checkBody = function checkBody() {
|
checkBody() {
|
||||||
// Check merkle root.
|
// Check merkle root.
|
||||||
const root = this.createMerkleRoot('hex');
|
const root = this.createMerkleRoot('hex');
|
||||||
|
|
||||||
@ -461,14 +462,14 @@ Block.prototype.checkBody = function checkBody() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [true, 'valid', 0];
|
return [true, 'valid', 0];
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the coinbase height from the coinbase input script.
|
* Retrieve the coinbase height from the coinbase input script.
|
||||||
* @returns {Number} height (-1 if not present).
|
* @returns {Number} height (-1 if not present).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
getCoinbaseHeight() {
|
||||||
if (this.version < 2)
|
if (this.version < 2)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -481,18 +482,18 @@ Block.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return coinbase.inputs[0].script.getCoinbaseHeight();
|
return coinbase.inputs[0].script.getCoinbaseHeight();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the "claimed" reward by the coinbase.
|
* Get the "claimed" reward by the coinbase.
|
||||||
* @returns {Amount} claimed
|
* @returns {Amount} claimed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getClaimed = function getClaimed() {
|
getClaimed() {
|
||||||
assert(this.txs.length > 0);
|
assert(this.txs.length > 0);
|
||||||
assert(this.txs[0].isCoinbase());
|
assert(this.txs[0].isCoinbase());
|
||||||
return this.txs[0].getOutputValue();
|
return this.txs[0].getOutputValue();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all unique outpoint hashes in the
|
* Get all unique outpoint hashes in the
|
||||||
@ -500,7 +501,7 @@ Block.prototype.getClaimed = function getClaimed() {
|
|||||||
* @returns {Hash[]} Outpoint hashes.
|
* @returns {Hash[]} Outpoint hashes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getPrevout = function getPrevout() {
|
getPrevout() {
|
||||||
const prevout = Object.create(null);
|
const prevout = Object.create(null);
|
||||||
|
|
||||||
for (let i = 1; i < this.txs.length; i++) {
|
for (let i = 1; i < this.txs.length; i++) {
|
||||||
@ -511,7 +512,7 @@ Block.prototype.getPrevout = function getPrevout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Object.keys(prevout);
|
return Object.keys(prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the block and return a more
|
* Inspect the block and return a more
|
||||||
@ -519,9 +520,9 @@ Block.prototype.getPrevout = function getPrevout() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return this.format();
|
return this.format();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the block and return a more
|
* Inspect the block and return a more
|
||||||
@ -531,7 +532,7 @@ Block.prototype.inspect = function inspect() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.format = function format(view, height) {
|
format(view, height) {
|
||||||
const commitmentHash = this.getCommitmentHash('hex');
|
const commitmentHash = this.getCommitmentHash('hex');
|
||||||
return {
|
return {
|
||||||
hash: this.rhash(),
|
hash: this.rhash(),
|
||||||
@ -552,7 +553,7 @@ Block.prototype.format = function format(view, height) {
|
|||||||
return tx.format(view, null, i);
|
return tx.format(view, null, i);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to an object suitable
|
* Convert the block to an object suitable
|
||||||
@ -560,9 +561,9 @@ Block.prototype.format = function format(view, height) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return this.getJSON();
|
return this.getJSON();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to an object suitable
|
* Convert the block to an object suitable
|
||||||
@ -576,7 +577,7 @@ Block.prototype.toJSON = function toJSON() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getJSON = function getJSON(network, view, height, depth) {
|
getJSON(network, view, height, depth) {
|
||||||
network = Network.get(network);
|
network = Network.get(network);
|
||||||
return {
|
return {
|
||||||
hash: this.rhash(),
|
hash: this.rhash(),
|
||||||
@ -592,7 +593,7 @@ Block.prototype.getJSON = function getJSON(network, view, height, depth) {
|
|||||||
return tx.getJSON(network, view, null, i);
|
return tx.getJSON(network, view, null, i);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from json object.
|
* Inject properties from json object.
|
||||||
@ -600,7 +601,7 @@ Block.prototype.getJSON = function getJSON(network, view, height, depth) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert(json, 'Block data is required.');
|
assert(json, 'Block data is required.');
|
||||||
assert(Array.isArray(json.txs));
|
assert(Array.isArray(json.txs));
|
||||||
|
|
||||||
@ -610,7 +611,7 @@ Block.prototype.fromJSON = function fromJSON(json) {
|
|||||||
this.txs.push(TX.fromJSON(tx));
|
this.txs.push(TX.fromJSON(tx));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a block from a jsonified block object.
|
* Instantiate a block from a jsonified block object.
|
||||||
@ -618,9 +619,9 @@ Block.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {Block}
|
* @returns {Block}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new Block().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -628,7 +629,7 @@ Block.fromJSON = function fromJSON(json) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
br.start();
|
br.start();
|
||||||
|
|
||||||
this.readHead(br);
|
this.readHead(br);
|
||||||
@ -649,7 +650,7 @@ Block.prototype.fromReader = function fromReader(br) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -657,9 +658,9 @@ Block.prototype.fromReader = function fromReader(br) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a block from a serialized Buffer.
|
* Instantiate a block from a serialized Buffer.
|
||||||
@ -668,9 +669,9 @@ Block.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Block}
|
* @returns {Block}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.fromReader = function fromReader(data) {
|
static fromReader(data) {
|
||||||
return new Block().fromReader(data);
|
return new this().fromReader(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a block from a serialized Buffer.
|
* Instantiate a block from a serialized Buffer.
|
||||||
@ -679,11 +680,11 @@ Block.fromReader = function fromReader(data) {
|
|||||||
* @returns {Block}
|
* @returns {Block}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.fromRaw = function fromRaw(data, enc) {
|
static fromRaw(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new Block().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the Block to a MerkleBlock.
|
* Convert the Block to a MerkleBlock.
|
||||||
@ -693,9 +694,9 @@ Block.fromRaw = function fromRaw(data, enc) {
|
|||||||
* @returns {MerkleBlock}
|
* @returns {MerkleBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.toMerkle = function toMerkle(filter) {
|
toMerkle(filter) {
|
||||||
return MerkleBlock.fromBlock(this, filter);
|
return MerkleBlock.fromBlock(this, filter);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialze block with or without witness data.
|
* Serialze block with or without witness data.
|
||||||
@ -705,7 +706,7 @@ Block.prototype.toMerkle = function toMerkle(filter) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.writeNormal = function writeNormal(bw) {
|
writeNormal(bw) {
|
||||||
this.writeHead(bw);
|
this.writeHead(bw);
|
||||||
|
|
||||||
bw.writeVarint(this.txs.length);
|
bw.writeVarint(this.txs.length);
|
||||||
@ -714,7 +715,7 @@ Block.prototype.writeNormal = function writeNormal(bw) {
|
|||||||
tx.toNormalWriter(bw);
|
tx.toNormalWriter(bw);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialze block with or without witness data.
|
* Serialze block with or without witness data.
|
||||||
@ -724,7 +725,7 @@ Block.prototype.writeNormal = function writeNormal(bw) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.writeWitness = function writeWitness(bw) {
|
writeWitness(bw) {
|
||||||
this.writeHead(bw);
|
this.writeHead(bw);
|
||||||
|
|
||||||
bw.writeVarint(this.txs.length);
|
bw.writeVarint(this.txs.length);
|
||||||
@ -733,7 +734,7 @@ Block.prototype.writeWitness = function writeWitness(bw) {
|
|||||||
tx.toWriter(bw);
|
tx.toWriter(bw);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialze block with or without witness data.
|
* Serialze block with or without witness data.
|
||||||
@ -743,13 +744,13 @@ Block.prototype.writeWitness = function writeWitness(bw) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.frameNormal = function frameNormal() {
|
frameNormal() {
|
||||||
const raw = this.getNormalSizes();
|
const raw = this.getNormalSizes();
|
||||||
const bw = new StaticWriter(raw.size);
|
const bw = new StaticWriter(raw.size);
|
||||||
this.writeNormal(bw);
|
this.writeNormal(bw);
|
||||||
raw.data = bw.render();
|
raw.data = bw.render();
|
||||||
return raw;
|
return raw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialze block without witness data.
|
* Serialze block without witness data.
|
||||||
@ -758,29 +759,29 @@ Block.prototype.frameNormal = function frameNormal() {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.frameWitness = function frameWitness() {
|
frameWitness() {
|
||||||
const raw = this.getWitnessSizes();
|
const raw = this.getWitnessSizes();
|
||||||
const bw = new StaticWriter(raw.size);
|
const bw = new StaticWriter(raw.size);
|
||||||
this.writeWitness(bw);
|
this.writeWitness(bw);
|
||||||
raw.data = bw.render();
|
raw.data = bw.render();
|
||||||
return raw;
|
return raw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to a headers object.
|
* Convert the block to a headers object.
|
||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.toHeaders = function toHeaders() {
|
toHeaders() {
|
||||||
return Headers.fromBlock(this);
|
return Headers.fromBlock(this);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get real block size without witness.
|
* Get real block size without witness.
|
||||||
* @returns {RawBlock}
|
* @returns {RawBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getNormalSizes = function getNormalSizes() {
|
getNormalSizes() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += 80;
|
size += 80;
|
||||||
@ -790,14 +791,14 @@ Block.prototype.getNormalSizes = function getNormalSizes() {
|
|||||||
size += tx.getBaseSize();
|
size += tx.getBaseSize();
|
||||||
|
|
||||||
return new RawBlock(size, 0);
|
return new RawBlock(size, 0);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get real block size with witness.
|
* Get real block size with witness.
|
||||||
* @returns {RawBlock}
|
* @returns {RawBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.prototype.getWitnessSizes = function getWitnessSizes() {
|
getWitnessSizes() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
let witness = 0;
|
let witness = 0;
|
||||||
|
|
||||||
@ -811,7 +812,7 @@ Block.prototype.getWitnessSizes = function getWitnessSizes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new RawBlock(size, witness);
|
return new RawBlock(size, witness);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an object is a Block.
|
* Test whether an object is a Block.
|
||||||
@ -819,19 +820,22 @@ Block.prototype.getWitnessSizes = function getWitnessSizes() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Block.isBlock = function isBlock(obj) {
|
static isBlock(obj) {
|
||||||
return obj instanceof Block;
|
return obj instanceof Block;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function RawBlock(size, witness) {
|
class RawBlock {
|
||||||
|
constructor(size, witness) {
|
||||||
this.data = null;
|
this.data = null;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.witness = witness;
|
this.witness = witness;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -8,38 +8,40 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
|
const BufferReader = require('bufio/lib/reader');
|
||||||
|
const StaticWriter = require('bufio/lib/staticwriter');
|
||||||
|
const encoding = require('bufio/lib/encoding');
|
||||||
const Amount = require('../btc/amount');
|
const Amount = require('../btc/amount');
|
||||||
const Output = require('./output');
|
const Output = require('./output');
|
||||||
const Script = require('../script/script');
|
const Script = require('../script/script');
|
||||||
const Network = require('../protocol/network');
|
const Network = require('../protocol/network');
|
||||||
const BufferReader = require('bufio/lib/reader');
|
|
||||||
const StaticWriter = require('bufio/lib/staticwriter');
|
|
||||||
const encoding = require('bufio/lib/encoding');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Coin
|
||||||
* Represents an unspent output.
|
* Represents an unspent output.
|
||||||
* @alias module:primitives.Coin
|
* @alias module:primitives.Coin
|
||||||
* @constructor
|
|
||||||
* @extends Output
|
* @extends Output
|
||||||
* @param {NakedCoin|Coin} options
|
* @property {Number} version
|
||||||
* @property {Number} version - Transaction version.
|
* @property {Number} height
|
||||||
* @property {Number} height - Transaction height (-1 if unconfirmed).
|
* @property {Amount} value
|
||||||
* @property {Amount} value - Output value in satoshis.
|
* @property {Script} script
|
||||||
* @property {Script} script - Output script.
|
* @property {Boolean} coinbase
|
||||||
* @property {Boolean} coinbase - Whether the containing
|
* @property {Hash} hash
|
||||||
* transaction is a coinbase.
|
* @property {Number} index
|
||||||
* @property {Hash} hash - Transaction hash.
|
|
||||||
* @property {Number} index - Output index.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Coin(options) {
|
class Coin extends Output {
|
||||||
if (!(this instanceof Coin))
|
/**
|
||||||
return new Coin(options);
|
* Create a coin.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
|
||||||
this.version = 1;
|
this.version = 1;
|
||||||
this.height = -1;
|
this.height = -1;
|
||||||
this.value = 0;
|
|
||||||
this.script = new Script();
|
|
||||||
this.coinbase = false;
|
this.coinbase = false;
|
||||||
this.hash = encoding.NULL_HASH;
|
this.hash = encoding.NULL_HASH;
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
@ -48,15 +50,13 @@ function Coin(options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Coin.prototype, Output.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject options into coin.
|
* Inject options into coin.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
assert(options, 'Coin data is required.');
|
assert(options, 'Coin data is required.');
|
||||||
|
|
||||||
if (options.version != null) {
|
if (options.version != null) {
|
||||||
@ -96,12 +96,13 @@ Coin.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.index != null) {
|
if (options.index != null) {
|
||||||
assert((options.index >>> 0) === options.index, 'Index must be a uint32.');
|
assert((options.index >>> 0) === options.index,
|
||||||
|
'Index must be a uint32.');
|
||||||
this.index = options.index;
|
this.index = options.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate Coin from options object.
|
* Instantiate Coin from options object.
|
||||||
@ -109,9 +110,9 @@ Coin.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new Coin().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone the coin.
|
* Clone the coin.
|
||||||
@ -119,9 +120,9 @@ Coin.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Coin}
|
* @returns {Coin}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.clone = function clone() {
|
clone() {
|
||||||
assert(false, 'Coins are not cloneable.');
|
assert(false, 'Coins are not cloneable.');
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate number of confirmations since coin was created.
|
* Calculate number of confirmations since coin was created.
|
||||||
@ -130,7 +131,7 @@ Coin.prototype.clone = function clone() {
|
|||||||
* @return {Number}
|
* @return {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.getDepth = function getDepth(height) {
|
getDepth(height) {
|
||||||
assert(typeof height === 'number', 'Must pass a height.');
|
assert(typeof height === 'number', 'Must pass a height.');
|
||||||
|
|
||||||
if (this.height === -1)
|
if (this.height === -1)
|
||||||
@ -143,7 +144,7 @@ Coin.prototype.getDepth = function getDepth(height) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return height - this.height + 1;
|
return height - this.height + 1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize coin to a key
|
* Serialize coin to a key
|
||||||
@ -151,9 +152,9 @@ Coin.prototype.getDepth = function getDepth(height) {
|
|||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.toKey = function toKey() {
|
toKey() {
|
||||||
return this.hash + this.index;
|
return this.hash + this.index;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from hash table key.
|
* Inject properties from hash table key.
|
||||||
@ -162,12 +163,12 @@ Coin.prototype.toKey = function toKey() {
|
|||||||
* @returns {Coin}
|
* @returns {Coin}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.fromKey = function fromKey(key) {
|
fromKey(key) {
|
||||||
assert(key.length > 64);
|
assert(key.length > 64);
|
||||||
this.hash = key.slice(0, 64);
|
this.hash = key.slice(0, 64);
|
||||||
this.index = parseInt(key.slice(64), 10);
|
this.index = parseInt(key.slice(64), 10);
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate coin from hash table key.
|
* Instantiate coin from hash table key.
|
||||||
@ -175,34 +176,34 @@ Coin.prototype.fromKey = function fromKey(key) {
|
|||||||
* @returns {Coin}
|
* @returns {Coin}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.fromKey = function fromKey(key) {
|
static fromKey(key) {
|
||||||
return new Coin().fromKey(key);
|
return new this().fromKey(key);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get little-endian hash.
|
* Get little-endian hash.
|
||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.rhash = function rhash() {
|
rhash() {
|
||||||
return encoding.revHex(this.hash);
|
return encoding.revHex(this.hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get little-endian hash.
|
* Get little-endian hash.
|
||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.txid = function txid() {
|
txid() {
|
||||||
return this.rhash();
|
return this.rhash();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the coin to a more user-friendly object.
|
* Convert the coin to a more user-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return {
|
return {
|
||||||
type: this.getType(),
|
type: this.getType(),
|
||||||
version: this.version,
|
version: this.version,
|
||||||
@ -214,7 +215,7 @@ Coin.prototype.inspect = function inspect() {
|
|||||||
index: this.index,
|
index: this.index,
|
||||||
address: this.getAddress()
|
address: this.getAddress()
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the coin to an object suitable
|
* Convert the coin to an object suitable
|
||||||
@ -222,9 +223,9 @@ Coin.prototype.inspect = function inspect() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return this.getJSON();
|
return this.getJSON();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the coin to an object suitable
|
* Convert the coin to an object suitable
|
||||||
@ -236,7 +237,7 @@ Coin.prototype.toJSON = function toJSON() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.getJSON = function getJSON(network, minimal) {
|
getJSON(network, minimal) {
|
||||||
let addr = this.getAddress();
|
let addr = this.getAddress();
|
||||||
|
|
||||||
network = Network.get(network);
|
network = Network.get(network);
|
||||||
@ -254,7 +255,7 @@ Coin.prototype.getJSON = function getJSON(network, minimal) {
|
|||||||
hash: !minimal ? this.rhash() : undefined,
|
hash: !minimal ? this.rhash() : undefined,
|
||||||
index: !minimal ? this.index : undefined
|
index: !minimal ? this.index : undefined
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject JSON properties into coin.
|
* Inject JSON properties into coin.
|
||||||
@ -262,7 +263,7 @@ Coin.prototype.getJSON = function getJSON(network, minimal) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert(json, 'Coin data required.');
|
assert(json, 'Coin data required.');
|
||||||
assert((json.version >>> 0) === json.version, 'Version must be a uint32.');
|
assert((json.version >>> 0) === json.version, 'Version must be a uint32.');
|
||||||
assert(json.height === -1 || (json.height >>> 0) === json.height,
|
assert(json.height === -1 || (json.height >>> 0) === json.height,
|
||||||
@ -286,7 +287,7 @@ Coin.prototype.fromJSON = function fromJSON(json) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an Coin from a jsonified coin object.
|
* Instantiate an Coin from a jsonified coin object.
|
||||||
@ -294,25 +295,25 @@ Coin.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {Coin}
|
* @returns {Coin}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new Coin().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate size of coin.
|
* Calculate size of coin.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
return 17 + this.script.getVarSize();
|
return 17 + this.script.getVarSize();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the coin to a buffer writer.
|
* Write the coin to a buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
let height = this.height;
|
let height = this.height;
|
||||||
|
|
||||||
if (height === -1)
|
if (height === -1)
|
||||||
@ -325,17 +326,17 @@ Coin.prototype.toWriter = function toWriter(bw) {
|
|||||||
bw.writeU8(this.coinbase ? 1 : 0);
|
bw.writeU8(this.coinbase ? 1 : 0);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the coin.
|
* Serialize the coin.
|
||||||
* @returns {Buffer|String}
|
* @returns {Buffer|String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
return this.toWriter(new StaticWriter(size)).render();
|
return this.toWriter(new StaticWriter(size)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized buffer writer.
|
* Inject properties from serialized buffer writer.
|
||||||
@ -343,7 +344,7 @@ Coin.prototype.toRaw = function toRaw() {
|
|||||||
* @param {BufferReader} br
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
this.version = br.readU32();
|
this.version = br.readU32();
|
||||||
this.height = br.readU32();
|
this.height = br.readU32();
|
||||||
this.value = br.readI64();
|
this.value = br.readI64();
|
||||||
@ -354,7 +355,7 @@ Coin.prototype.fromReader = function fromReader(br) {
|
|||||||
this.height = -1;
|
this.height = -1;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -362,9 +363,9 @@ Coin.prototype.fromReader = function fromReader(br) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coin from a buffer reader.
|
* Instantiate a coin from a buffer reader.
|
||||||
@ -372,9 +373,9 @@ Coin.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Coin}
|
* @returns {Coin}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new Coin().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coin from a serialized Buffer.
|
* Instantiate a coin from a serialized Buffer.
|
||||||
@ -383,11 +384,11 @@ Coin.fromReader = function fromReader(br) {
|
|||||||
* @returns {Coin}
|
* @returns {Coin}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.fromRaw = function fromRaw(data, enc) {
|
static fromRaw(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new Coin().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from TX.
|
* Inject properties from TX.
|
||||||
@ -395,7 +396,7 @@ Coin.fromRaw = function fromRaw(data, enc) {
|
|||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.prototype.fromTX = function fromTX(tx, index, height) {
|
fromTX(tx, index, height) {
|
||||||
assert(typeof index === 'number');
|
assert(typeof index === 'number');
|
||||||
assert(typeof height === 'number');
|
assert(typeof height === 'number');
|
||||||
assert(index >= 0 && index < tx.outputs.length);
|
assert(index >= 0 && index < tx.outputs.length);
|
||||||
@ -407,7 +408,7 @@ Coin.prototype.fromTX = function fromTX(tx, index, height) {
|
|||||||
this.hash = tx.hash('hex');
|
this.hash = tx.hash('hex');
|
||||||
this.index = index;
|
this.index = index;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a coin from a TX
|
* Instantiate a coin from a TX
|
||||||
@ -416,9 +417,9 @@ Coin.prototype.fromTX = function fromTX(tx, index, height) {
|
|||||||
* @returns {Coin}
|
* @returns {Coin}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.fromTX = function fromTX(tx, index, height) {
|
static fromTX(tx, index, height) {
|
||||||
return new Coin().fromTX(tx, index, height);
|
return new this().fromTX(tx, index, height);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an object to see if it is a Coin.
|
* Test an object to see if it is a Coin.
|
||||||
@ -426,9 +427,10 @@ Coin.fromTX = function fromTX(tx, index, height) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Coin.isCoin = function isCoin(obj) {
|
static isCoin(obj) {
|
||||||
return obj instanceof Coin;
|
return obj instanceof Coin;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -14,65 +14,66 @@ const BufferReader = require('bufio/lib/reader');
|
|||||||
const encoding = require('bufio/lib/encoding');
|
const encoding = require('bufio/lib/encoding');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents block headers obtained from the network via `headers`.
|
* Headers
|
||||||
|
* Represents block headers obtained
|
||||||
|
* from the network via `headers`.
|
||||||
* @alias module:primitives.Headers
|
* @alias module:primitives.Headers
|
||||||
* @constructor
|
|
||||||
* @extends AbstractBlock
|
* @extends AbstractBlock
|
||||||
* @param {NakedBlock} options
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Headers(options) {
|
class Headers extends AbstractBlock {
|
||||||
if (!(this instanceof Headers))
|
/**
|
||||||
return new Headers(options);
|
* Create headers.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
|
||||||
AbstractBlock.call(this);
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
|
||||||
if (options)
|
if (options)
|
||||||
this.parseOptions(options);
|
this.parseOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(Headers.prototype, AbstractBlock.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do non-contextual verification on the headers.
|
* Perform non-contextual
|
||||||
* @param {Object?} ret - Return object, may be
|
* verification on the headers.
|
||||||
* set with properties `reason` and `score`.
|
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.verifyBody = function verifyBody(ret) {
|
verifyBody() {
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get size of the headers.
|
* Get size of the headers.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
return 81;
|
return 81;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the headers to a buffer writer.
|
* Serialize the headers to a buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
this.writeHead(bw);
|
this.writeHead(bw);
|
||||||
bw.writeVarint(0);
|
bw.writeVarint(0);
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the headers.
|
* Serialize the headers.
|
||||||
* @returns {Buffer|String}
|
* @returns {Buffer|String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
return this.toWriter(new StaticWriter(size)).render();
|
return this.toWriter(new StaticWriter(size)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -80,11 +81,11 @@ Headers.prototype.toRaw = function toRaw() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
this.readHead(br);
|
this.readHead(br);
|
||||||
br.readVarint();
|
br.readVarint();
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -92,9 +93,9 @@ Headers.prototype.fromReader = function fromReader(br) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate headers from buffer reader.
|
* Instantiate headers from buffer reader.
|
||||||
@ -102,9 +103,9 @@ Headers.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new Headers().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate headers from serialized data.
|
* Instantiate headers from serialized data.
|
||||||
@ -113,11 +114,11 @@ Headers.fromReader = function fromReader(br) {
|
|||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.fromRaw = function fromRaw(data, enc) {
|
static fromRaw(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new Headers().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate headers from serialized data.
|
* Instantiate headers from serialized data.
|
||||||
@ -126,11 +127,11 @@ Headers.fromRaw = function fromRaw(data, enc) {
|
|||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.fromHead = function fromHead(data, enc) {
|
static fromHead(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new Headers().fromHead(data);
|
return new this().fromHead(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate headers from a chain entry.
|
* Instantiate headers from a chain entry.
|
||||||
@ -138,8 +139,8 @@ Headers.fromHead = function fromHead(data, enc) {
|
|||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.fromEntry = function fromEntry(entry) {
|
static fromEntry(entry) {
|
||||||
const headers = new Headers();
|
const headers = new this();
|
||||||
headers.version = entry.version;
|
headers.version = entry.version;
|
||||||
headers.prevBlock = entry.prevBlock;
|
headers.prevBlock = entry.prevBlock;
|
||||||
headers.merkleRoot = entry.merkleRoot;
|
headers.merkleRoot = entry.merkleRoot;
|
||||||
@ -149,16 +150,16 @@ Headers.fromEntry = function fromEntry(entry) {
|
|||||||
headers._hash = Buffer.from(entry.hash, 'hex');
|
headers._hash = Buffer.from(entry.hash, 'hex');
|
||||||
headers._hhash = entry.hash;
|
headers._hhash = entry.hash;
|
||||||
return headers;
|
return headers;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to a headers object.
|
* Convert the block to a headers object.
|
||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.toHeaders = function toHeaders() {
|
toHeaders() {
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to a headers object.
|
* Convert the block to a headers object.
|
||||||
@ -166,12 +167,12 @@ Headers.prototype.toHeaders = function toHeaders() {
|
|||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.fromBlock = function fromBlock(block) {
|
static fromBlock(block) {
|
||||||
const headers = new Headers(block);
|
const headers = new this(block);
|
||||||
headers._hash = block._hash;
|
headers._hash = block._hash;
|
||||||
headers._hhash = block._hhash;
|
headers._hhash = block._hhash;
|
||||||
return headers;
|
return headers;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to an object suitable
|
* Convert the block to an object suitable
|
||||||
@ -179,9 +180,9 @@ Headers.fromBlock = function fromBlock(block) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return this.getJSON();
|
return this.getJSON();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to an object suitable
|
* Convert the block to an object suitable
|
||||||
@ -194,7 +195,7 @@ Headers.prototype.toJSON = function toJSON() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.getJSON = function getJSON(network, view, height) {
|
getJSON(network, view, height) {
|
||||||
return {
|
return {
|
||||||
hash: this.rhash(),
|
hash: this.rhash(),
|
||||||
height: height,
|
height: height,
|
||||||
@ -205,7 +206,7 @@ Headers.prototype.getJSON = function getJSON(network, view, height) {
|
|||||||
bits: this.bits,
|
bits: this.bits,
|
||||||
nonce: this.nonce
|
nonce: this.nonce
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from json object.
|
* Inject properties from json object.
|
||||||
@ -213,10 +214,10 @@ Headers.prototype.getJSON = function getJSON(network, view, height) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
this.parseJSON(json);
|
this.parseJSON(json);
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a merkle block from a jsonified block object.
|
* Instantiate a merkle block from a jsonified block object.
|
||||||
@ -224,9 +225,9 @@ Headers.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new Headers().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the headers and return a more
|
* Inspect the headers and return a more
|
||||||
@ -234,9 +235,9 @@ Headers.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return this.format();
|
return this.format();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the headers and return a more
|
* Inspect the headers and return a more
|
||||||
@ -246,7 +247,7 @@ Headers.prototype.inspect = function inspect() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.prototype.format = function format(view, height) {
|
format(view, height) {
|
||||||
return {
|
return {
|
||||||
hash: this.rhash(),
|
hash: this.rhash(),
|
||||||
height: height != null ? height : -1,
|
height: height != null ? height : -1,
|
||||||
@ -258,7 +259,7 @@ Headers.prototype.format = function format(view, height) {
|
|||||||
bits: this.bits,
|
bits: this.bits,
|
||||||
nonce: this.nonce
|
nonce: this.nonce
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an object to see if it is a Headers object.
|
* Test an object to see if it is a Headers object.
|
||||||
@ -266,9 +267,10 @@ Headers.prototype.format = function format(view, height) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Headers.isHeaders = function isHeaders(obj) {
|
static isHeaders(obj) {
|
||||||
return obj instanceof Headers;
|
return obj instanceof Headers;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -16,20 +16,23 @@ const StaticWriter = require('bufio/lib/staticwriter');
|
|||||||
const BufferReader = require('bufio/lib/reader');
|
const BufferReader = require('bufio/lib/reader');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Input
|
||||||
* Represents a transaction input.
|
* Represents a transaction input.
|
||||||
* @alias module:primitives.Input
|
* @alias module:primitives.Input
|
||||||
* @constructor
|
|
||||||
* @param {NakedInput} options
|
|
||||||
* @property {Outpoint} prevout - Outpoint.
|
* @property {Outpoint} prevout - Outpoint.
|
||||||
* @property {Script} script - Input script / scriptSig.
|
* @property {Script} script - Input script / scriptSig.
|
||||||
* @property {Number} sequence - nSequence.
|
* @property {Number} sequence - nSequence.
|
||||||
* @property {Witness} witness - Witness (empty if not present).
|
* @property {Witness} witness - Witness (empty if not present).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Input(options) {
|
class Input {
|
||||||
if (!(this instanceof Input))
|
/**
|
||||||
return new Input(options);
|
* Create transaction input.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
this.prevout = new Outpoint();
|
this.prevout = new Outpoint();
|
||||||
this.script = new Script();
|
this.script = new Script();
|
||||||
this.sequence = 0xffffffff;
|
this.sequence = 0xffffffff;
|
||||||
@ -45,7 +48,7 @@ function Input(options) {
|
|||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
assert(options, 'Input data is required.');
|
assert(options, 'Input data is required.');
|
||||||
|
|
||||||
this.prevout.fromOptions(options.prevout);
|
this.prevout.fromOptions(options.prevout);
|
||||||
@ -63,7 +66,7 @@ Input.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.witness.fromOptions(options.witness);
|
this.witness.fromOptions(options.witness);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an Input from options object.
|
* Instantiate an Input from options object.
|
||||||
@ -71,23 +74,23 @@ Input.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Input}
|
* @returns {Input}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new Input().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone the input.
|
* Clone the input.
|
||||||
* @returns {Input}
|
* @returns {Input}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.clone = function clone() {
|
clone() {
|
||||||
const input = new Input();
|
const input = new this.constructor();
|
||||||
input.prevout = this.prevout;
|
input.prevout = this.prevout;
|
||||||
input.script.inject(this.script);
|
input.script.inject(this.script);
|
||||||
input.sequence = this.sequence;
|
input.sequence = this.sequence;
|
||||||
input.witness.inject(this.witness);
|
input.witness.inject(this.witness);
|
||||||
return input;
|
return input;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test equality against another input.
|
* Test equality against another input.
|
||||||
@ -95,10 +98,10 @@ Input.prototype.clone = function clone() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.equals = function equals(input) {
|
equals(input) {
|
||||||
assert(Input.isInput(input));
|
assert(Input.isInput(input));
|
||||||
return this.prevout.equals(input.prevout);
|
return this.prevout.equals(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare against another input (BIP69).
|
* Compare against another input (BIP69).
|
||||||
@ -106,10 +109,10 @@ Input.prototype.equals = function equals(input) {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.compare = function compare(input) {
|
compare(input) {
|
||||||
assert(Input.isInput(input));
|
assert(Input.isInput(input));
|
||||||
return this.prevout.compare(input.prevout);
|
return this.prevout.compare(input.prevout);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the previous output script type as a string.
|
* Get the previous output script type as a string.
|
||||||
@ -119,7 +122,7 @@ Input.prototype.compare = function compare(input) {
|
|||||||
* @returns {ScriptType} type
|
* @returns {ScriptType} type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.getType = function getType(coin) {
|
getType(coin) {
|
||||||
if (this.isCoinbase())
|
if (this.isCoinbase())
|
||||||
return 'coinbase';
|
return 'coinbase';
|
||||||
|
|
||||||
@ -134,7 +137,7 @@ Input.prototype.getType = function getType(coin) {
|
|||||||
type = this.script.getInputType();
|
type = this.script.getInputType();
|
||||||
|
|
||||||
return Script.typesByVal[type].toLowerCase();
|
return Script.typesByVal[type].toLowerCase();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the redeem script. Will attempt to resolve nested
|
* Get the redeem script. Will attempt to resolve nested
|
||||||
@ -143,7 +146,7 @@ Input.prototype.getType = function getType(coin) {
|
|||||||
* @returns {Script?} Redeem script.
|
* @returns {Script?} Redeem script.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.getRedeem = function getRedeem(coin) {
|
getRedeem(coin) {
|
||||||
if (this.isCoinbase())
|
if (this.isCoinbase())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -171,7 +174,7 @@ Input.prototype.getRedeem = function getRedeem(coin) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return redeem;
|
return redeem;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the redeem script type.
|
* Get the redeem script type.
|
||||||
@ -179,7 +182,7 @@ Input.prototype.getRedeem = function getRedeem(coin) {
|
|||||||
* @returns {String} subtype
|
* @returns {String} subtype
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.getSubtype = function getSubtype(coin) {
|
getSubtype(coin) {
|
||||||
if (this.isCoinbase())
|
if (this.isCoinbase())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -191,7 +194,7 @@ Input.prototype.getSubtype = function getSubtype(coin) {
|
|||||||
const type = redeem.getType();
|
const type = redeem.getType();
|
||||||
|
|
||||||
return Script.typesByVal[type].toLowerCase();
|
return Script.typesByVal[type].toLowerCase();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the previous output script's address. Will "guess"
|
* Get the previous output script's address. Will "guess"
|
||||||
@ -201,7 +204,7 @@ Input.prototype.getSubtype = function getSubtype(coin) {
|
|||||||
* @returns {Address?} addr
|
* @returns {Address?} addr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.getAddress = function getAddress(coin) {
|
getAddress(coin) {
|
||||||
if (this.isCoinbase())
|
if (this.isCoinbase())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -212,7 +215,7 @@ Input.prototype.getAddress = function getAddress(coin) {
|
|||||||
return this.witness.getInputAddress();
|
return this.witness.getInputAddress();
|
||||||
|
|
||||||
return this.script.getInputAddress();
|
return this.script.getInputAddress();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the address hash.
|
* Get the address hash.
|
||||||
@ -220,50 +223,50 @@ Input.prototype.getAddress = function getAddress(coin) {
|
|||||||
* @returns {Hash} hash
|
* @returns {Hash} hash
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.getHash = function getHash(enc) {
|
getHash(enc) {
|
||||||
const addr = this.getAddress();
|
const addr = this.getAddress();
|
||||||
|
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return addr.getHash(enc);
|
return addr.getHash(enc);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test to see if nSequence is equal to uint32max.
|
* Test to see if nSequence is equal to uint32max.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.isFinal = function isFinal() {
|
isFinal() {
|
||||||
return this.sequence === 0xffffffff;
|
return this.sequence === 0xffffffff;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test to see if nSequence is less than 0xfffffffe.
|
* Test to see if nSequence is less than 0xfffffffe.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.isRBF = function isRBF() {
|
isRBF() {
|
||||||
return this.sequence < 0xfffffffe;
|
return this.sequence < 0xfffffffe;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test to see if outpoint is null.
|
* Test to see if outpoint is null.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.isCoinbase = function isCoinbase() {
|
isCoinbase() {
|
||||||
return this.prevout.isNull();
|
return this.prevout.isNull();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the input to a more user-friendly object.
|
* Convert the input to a more user-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return this.format();
|
return this.format();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the input to a more user-friendly object.
|
* Convert the input to a more user-friendly object.
|
||||||
@ -271,7 +274,7 @@ Input.prototype.inspect = function inspect() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.format = function format(coin) {
|
format(coin) {
|
||||||
return {
|
return {
|
||||||
type: this.getType(coin),
|
type: this.getType(coin),
|
||||||
subtype: this.getSubtype(coin),
|
subtype: this.getSubtype(coin),
|
||||||
@ -283,7 +286,7 @@ Input.prototype.format = function format(coin) {
|
|||||||
prevout: this.prevout,
|
prevout: this.prevout,
|
||||||
coin: coin || null
|
coin: coin || null
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the input to an object suitable
|
* Convert the input to an object suitable
|
||||||
@ -291,9 +294,9 @@ Input.prototype.format = function format(coin) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.toJSON = function toJSON(network, coin) {
|
toJSON(network, coin) {
|
||||||
return this.getJSON();
|
return this.getJSON();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the input to an object suitable
|
* Convert the input to an object suitable
|
||||||
@ -305,7 +308,7 @@ Input.prototype.toJSON = function toJSON(network, coin) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.getJSON = function getJSON(network, coin) {
|
getJSON(network, coin) {
|
||||||
network = Network.get(network);
|
network = Network.get(network);
|
||||||
|
|
||||||
let addr;
|
let addr;
|
||||||
@ -323,7 +326,7 @@ Input.prototype.getJSON = function getJSON(network, coin) {
|
|||||||
address: addr,
|
address: addr,
|
||||||
coin: coin ? coin.getJSON(network, true) : undefined
|
coin: coin ? coin.getJSON(network, true) : undefined
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from a JSON object.
|
* Inject properties from a JSON object.
|
||||||
@ -331,15 +334,16 @@ Input.prototype.getJSON = function getJSON(network, coin) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert(json, 'Input data is required.');
|
assert(json, 'Input data is required.');
|
||||||
assert((json.sequence >>> 0) === json.sequence, 'Sequence must be a uint32.');
|
assert((json.sequence >>> 0) === json.sequence,
|
||||||
|
'Sequence must be a uint32.');
|
||||||
this.prevout.fromJSON(json.prevout);
|
this.prevout.fromJSON(json.prevout);
|
||||||
this.script.fromJSON(json.script);
|
this.script.fromJSON(json.script);
|
||||||
this.witness.fromJSON(json.witness);
|
this.witness.fromJSON(json.witness);
|
||||||
this.sequence = json.sequence;
|
this.sequence = json.sequence;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an Input from a jsonified input object.
|
* Instantiate an Input from a jsonified input object.
|
||||||
@ -347,18 +351,18 @@ Input.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {Input}
|
* @returns {Input}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new Input().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate size of serialized input.
|
* Calculate size of serialized input.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
return 40 + this.script.getVarSize();
|
return 40 + this.script.getVarSize();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the input.
|
* Serialize the input.
|
||||||
@ -366,22 +370,22 @@ Input.prototype.getSize = function getSize() {
|
|||||||
* @returns {Buffer|String}
|
* @returns {Buffer|String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
return this.toWriter(new StaticWriter(size)).render();
|
return this.toWriter(new StaticWriter(size)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the input to a buffer writer.
|
* Write the input to a buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
this.prevout.toWriter(bw);
|
this.prevout.toWriter(bw);
|
||||||
bw.writeVarBytes(this.script.toRaw());
|
bw.writeVarBytes(this.script.toRaw());
|
||||||
bw.writeU32(this.sequence);
|
bw.writeU32(this.sequence);
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -389,21 +393,21 @@ Input.prototype.toWriter = function toWriter(bw) {
|
|||||||
* @param {BufferReader} br
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
this.prevout.fromReader(br);
|
this.prevout.fromReader(br);
|
||||||
this.script.fromRaw(br.readVarBytes());
|
this.script.fromRaw(br.readVarBytes());
|
||||||
this.sequence = br.readU32();
|
this.sequence = br.readU32();
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an input from a buffer reader.
|
* Instantiate an input from a buffer reader.
|
||||||
@ -411,9 +415,9 @@ Input.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Input}
|
* @returns {Input}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new Input().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an input from a serialized Buffer.
|
* Instantiate an input from a serialized Buffer.
|
||||||
@ -422,11 +426,11 @@ Input.fromReader = function fromReader(br) {
|
|||||||
* @returns {Input}
|
* @returns {Input}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.fromRaw = function fromRaw(data, enc) {
|
static fromRaw(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new Input().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from outpoint.
|
* Inject properties from outpoint.
|
||||||
@ -434,13 +438,13 @@ Input.fromRaw = function fromRaw(data, enc) {
|
|||||||
* @param {Outpoint} outpoint
|
* @param {Outpoint} outpoint
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.fromOutpoint = function fromOutpoint(outpoint) {
|
fromOutpoint(outpoint) {
|
||||||
assert(typeof outpoint.hash === 'string');
|
assert(typeof outpoint.hash === 'string');
|
||||||
assert(typeof outpoint.index === 'number');
|
assert(typeof outpoint.index === 'number');
|
||||||
this.prevout.hash = outpoint.hash;
|
this.prevout.hash = outpoint.hash;
|
||||||
this.prevout.index = outpoint.index;
|
this.prevout.index = outpoint.index;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate input from outpoint.
|
* Instantiate input from outpoint.
|
||||||
@ -448,9 +452,9 @@ Input.prototype.fromOutpoint = function fromOutpoint(outpoint) {
|
|||||||
* @returns {Input}
|
* @returns {Input}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.fromOutpoint = function fromOutpoint(outpoint) {
|
static fromOutpoint(outpoint) {
|
||||||
return new Input().fromOutpoint(outpoint);
|
return new this().fromOutpoint(outpoint);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from coin.
|
* Inject properties from coin.
|
||||||
@ -458,13 +462,13 @@ Input.fromOutpoint = function fromOutpoint(outpoint) {
|
|||||||
* @param {Coin} coin
|
* @param {Coin} coin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.fromCoin = function fromCoin(coin) {
|
fromCoin(coin) {
|
||||||
assert(typeof coin.hash === 'string');
|
assert(typeof coin.hash === 'string');
|
||||||
assert(typeof coin.index === 'number');
|
assert(typeof coin.index === 'number');
|
||||||
this.prevout.hash = coin.hash;
|
this.prevout.hash = coin.hash;
|
||||||
this.prevout.index = coin.index;
|
this.prevout.index = coin.index;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate input from coin.
|
* Instantiate input from coin.
|
||||||
@ -472,9 +476,9 @@ Input.prototype.fromCoin = function fromCoin(coin) {
|
|||||||
* @returns {Input}
|
* @returns {Input}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.fromCoin = function fromCoin(coin) {
|
static fromCoin(coin) {
|
||||||
return new Input().fromCoin(coin);
|
return new this().fromCoin(coin);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from transaction.
|
* Inject properties from transaction.
|
||||||
@ -483,14 +487,14 @@ Input.fromCoin = function fromCoin(coin) {
|
|||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.prototype.fromTX = function fromTX(tx, index) {
|
fromTX(tx, index) {
|
||||||
assert(tx);
|
assert(tx);
|
||||||
assert(typeof index === 'number');
|
assert(typeof index === 'number');
|
||||||
assert(index >= 0 && index < tx.outputs.length);
|
assert(index >= 0 && index < tx.outputs.length);
|
||||||
this.prevout.hash = tx.hash('hex');
|
this.prevout.hash = tx.hash('hex');
|
||||||
this.prevout.index = index;
|
this.prevout.index = index;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate input from tx.
|
* Instantiate input from tx.
|
||||||
@ -499,9 +503,9 @@ Input.prototype.fromTX = function fromTX(tx, index) {
|
|||||||
* @returns {Input}
|
* @returns {Input}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.fromTX = function fromTX(tx, index) {
|
static fromTX(tx, index) {
|
||||||
return new Input().fromTX(tx, index);
|
return new this().fromTX(tx, index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an object to see if it is an Input.
|
* Test an object to see if it is an Input.
|
||||||
@ -509,9 +513,10 @@ Input.fromTX = function fromTX(tx, index) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Input.isInput = function isInput(obj) {
|
static isInput(obj) {
|
||||||
return obj instanceof Input;
|
return obj instanceof Input;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -15,20 +15,148 @@ const encoding = require('bufio/lib/encoding');
|
|||||||
* Inv Item
|
* Inv Item
|
||||||
* @alias module:primitives.InvItem
|
* @alias module:primitives.InvItem
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Number} type
|
|
||||||
* @param {Hash} hash
|
|
||||||
* @property {InvType} type
|
* @property {InvType} type
|
||||||
* @property {Hash} hash
|
* @property {Hash} hash
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function InvItem(type, hash) {
|
class InvItem {
|
||||||
if (!(this instanceof InvItem))
|
/**
|
||||||
return new InvItem(type, hash);
|
* Create an inv item.
|
||||||
|
* @constructor
|
||||||
|
* @param {Number} type
|
||||||
|
* @param {Hash} hash
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(type, hash) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.hash = hash;
|
this.hash = hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write inv item to buffer writer.
|
||||||
|
* @param {BufferWriter} bw
|
||||||
|
*/
|
||||||
|
|
||||||
|
getSize() {
|
||||||
|
return 36;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write inv item to buffer writer.
|
||||||
|
* @param {BufferWriter} bw
|
||||||
|
*/
|
||||||
|
|
||||||
|
toWriter(bw) {
|
||||||
|
bw.writeU32(this.type);
|
||||||
|
bw.writeHash(this.hash);
|
||||||
|
return bw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize inv item.
|
||||||
|
* @returns {Buffer}
|
||||||
|
*/
|
||||||
|
|
||||||
|
toRaw() {
|
||||||
|
return this.toWriter(new StaticWriter(36)).render();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject properties from buffer reader.
|
||||||
|
* @private
|
||||||
|
* @param {BufferReader} br
|
||||||
|
*/
|
||||||
|
|
||||||
|
fromReader(br) {
|
||||||
|
this.type = br.readU32();
|
||||||
|
this.hash = br.readHash('hex');
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject properties from serialized data.
|
||||||
|
* @param {Buffer} data
|
||||||
|
*/
|
||||||
|
|
||||||
|
fromRaw(data) {
|
||||||
|
return this.fromReader(new BufferReader(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate inv item from buffer reader.
|
||||||
|
* @param {BufferReader} br
|
||||||
|
* @returns {InvItem}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static fromReader(br) {
|
||||||
|
return new this().fromReader(br);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate inv item from serialized data.
|
||||||
|
* @param {Buffer} data
|
||||||
|
* @param {String?} enc
|
||||||
|
* @returns {InvItem}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static fromRaw(data, enc) {
|
||||||
|
if (typeof data === 'string')
|
||||||
|
data = Buffer.from(data, enc);
|
||||||
|
return new this().fromRaw(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the inv item is a block.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
isBlock() {
|
||||||
|
switch (this.type) {
|
||||||
|
case InvItem.types.BLOCK:
|
||||||
|
case InvItem.types.WITNESS_BLOCK:
|
||||||
|
case InvItem.types.FILTERED_BLOCK:
|
||||||
|
case InvItem.types.WITNESS_FILTERED_BLOCK:
|
||||||
|
case InvItem.types.CMPCT_BLOCK:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the inv item is a tx.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
isTX() {
|
||||||
|
switch (this.type) {
|
||||||
|
case InvItem.types.TX:
|
||||||
|
case InvItem.types.WITNESS_TX:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the inv item has the witness bit set.
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
|
||||||
|
hasWitness() {
|
||||||
|
return (this.type & InvItem.WITNESS_FLAG) !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get little-endian hash.
|
||||||
|
* @returns {Hash}
|
||||||
|
*/
|
||||||
|
|
||||||
|
rhash() {
|
||||||
|
return encoding.revHex(this.hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inv types.
|
* Inv types.
|
||||||
* @enum {Number}
|
* @enum {Number}
|
||||||
@ -36,7 +164,6 @@ function InvItem(type, hash) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
InvItem.types = {
|
InvItem.types = {
|
||||||
ERROR: 0,
|
|
||||||
TX: 1,
|
TX: 1,
|
||||||
BLOCK: 2,
|
BLOCK: 2,
|
||||||
FILTERED_BLOCK: 3,
|
FILTERED_BLOCK: 3,
|
||||||
@ -52,7 +179,6 @@ InvItem.types = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
InvItem.typesByVal = {
|
InvItem.typesByVal = {
|
||||||
0: 'ERROR',
|
|
||||||
1: 'TX',
|
1: 'TX',
|
||||||
2: 'BLOCK',
|
2: 'BLOCK',
|
||||||
3: 'FILTERED_BLOCK',
|
3: 'FILTERED_BLOCK',
|
||||||
@ -70,130 +196,6 @@ InvItem.typesByVal = {
|
|||||||
|
|
||||||
InvItem.WITNESS_FLAG = 1 << 30;
|
InvItem.WITNESS_FLAG = 1 << 30;
|
||||||
|
|
||||||
/**
|
|
||||||
* Write inv item to buffer writer.
|
|
||||||
* @param {BufferWriter} bw
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.getSize = function getSize() {
|
|
||||||
return 36;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write inv item to buffer writer.
|
|
||||||
* @param {BufferWriter} bw
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.toWriter = function toWriter(bw) {
|
|
||||||
bw.writeU32(this.type);
|
|
||||||
bw.writeHash(this.hash);
|
|
||||||
return bw;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialize inv item.
|
|
||||||
* @returns {Buffer}
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.toRaw = function toRaw() {
|
|
||||||
return this.toWriter(new StaticWriter(36)).render();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject properties from buffer reader.
|
|
||||||
* @private
|
|
||||||
* @param {BufferReader} br
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.fromReader = function fromReader(br) {
|
|
||||||
this.type = br.readU32();
|
|
||||||
this.hash = br.readHash('hex');
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject properties from serialized data.
|
|
||||||
* @param {Buffer} data
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.fromRaw = function fromRaw(data) {
|
|
||||||
return this.fromReader(new BufferReader(data));
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate inv item from buffer reader.
|
|
||||||
* @param {BufferReader} br
|
|
||||||
* @returns {InvItem}
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.fromReader = function fromReader(br) {
|
|
||||||
return new InvItem().fromReader(br);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate inv item from serialized data.
|
|
||||||
* @param {Buffer} data
|
|
||||||
* @param {String?} enc
|
|
||||||
* @returns {InvItem}
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.fromRaw = function fromRaw(data, enc) {
|
|
||||||
if (typeof data === 'string')
|
|
||||||
data = Buffer.from(data, enc);
|
|
||||||
return new InvItem().fromRaw(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the inv item is a block.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.isBlock = function isBlock() {
|
|
||||||
switch (this.type) {
|
|
||||||
case InvItem.types.BLOCK:
|
|
||||||
case InvItem.types.WITNESS_BLOCK:
|
|
||||||
case InvItem.types.FILTERED_BLOCK:
|
|
||||||
case InvItem.types.WITNESS_FILTERED_BLOCK:
|
|
||||||
case InvItem.types.CMPCT_BLOCK:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the inv item is a tx.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.isTX = function isTX() {
|
|
||||||
switch (this.type) {
|
|
||||||
case InvItem.types.TX:
|
|
||||||
case InvItem.types.WITNESS_TX:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether the inv item has the witness bit set.
|
|
||||||
* @returns {Boolean}
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.hasWitness = function hasWitness() {
|
|
||||||
return (this.type & InvItem.WITNESS_FLAG) !== 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get little-endian hash.
|
|
||||||
* @returns {Hash}
|
|
||||||
*/
|
|
||||||
|
|
||||||
InvItem.prototype.rhash = function rhash() {
|
|
||||||
return encoding.revHex(this.hash);
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -21,16 +21,19 @@ const Output = require('./output');
|
|||||||
const secp256k1 = require('bcrypto/lib/secp256k1');
|
const secp256k1 = require('bcrypto/lib/secp256k1');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Key Ring
|
||||||
* Represents a key ring which amounts to an address.
|
* Represents a key ring which amounts to an address.
|
||||||
* @alias module:primitives.KeyRing
|
* @alias module:primitives.KeyRing
|
||||||
|
*/
|
||||||
|
|
||||||
|
class KeyRing {
|
||||||
|
/**
|
||||||
|
* Create a key ring.
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function KeyRing(options) {
|
constructor(options) {
|
||||||
if (!(this instanceof KeyRing))
|
|
||||||
return new KeyRing(options);
|
|
||||||
|
|
||||||
this.witness = false;
|
this.witness = false;
|
||||||
this.nested = false;
|
this.nested = false;
|
||||||
this.publicKey = encoding.ZERO_KEY;
|
this.publicKey = encoding.ZERO_KEY;
|
||||||
@ -56,7 +59,7 @@ function KeyRing(options) {
|
|||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
let key = toKey(options);
|
let key = toKey(options);
|
||||||
|
|
||||||
if (options.witness != null) {
|
if (options.witness != null) {
|
||||||
@ -87,7 +90,7 @@ KeyRing.prototype.fromOptions = function fromOptions(options) {
|
|||||||
return this.fromScript(key, script, compress);
|
return this.fromScript(key, script, compress);
|
||||||
|
|
||||||
return this.fromKey(key, compress);
|
return this.fromKey(key, compress);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate key ring from options.
|
* Instantiate key ring from options.
|
||||||
@ -95,15 +98,15 @@ KeyRing.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new KeyRing().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear cached key/script hashes.
|
* Clear cached key/script hashes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.refresh = function refresh() {
|
refresh() {
|
||||||
this._keyHash = null;
|
this._keyHash = null;
|
||||||
this._keyAddress = null;
|
this._keyAddress = null;
|
||||||
this._program = null;
|
this._program = null;
|
||||||
@ -112,7 +115,7 @@ KeyRing.prototype.refresh = function refresh() {
|
|||||||
this._scriptHash160 = null;
|
this._scriptHash160 = null;
|
||||||
this._scriptHash256 = null;
|
this._scriptHash256 = null;
|
||||||
this._scriptAddress = null;
|
this._scriptAddress = null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject data from private key.
|
* Inject data from private key.
|
||||||
@ -121,7 +124,7 @@ KeyRing.prototype.refresh = function refresh() {
|
|||||||
* @param {Boolean?} compress
|
* @param {Boolean?} compress
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromPrivate = function fromPrivate(key, compress) {
|
fromPrivate(key, compress) {
|
||||||
assert(Buffer.isBuffer(key), 'Private key must be a buffer.');
|
assert(Buffer.isBuffer(key), 'Private key must be a buffer.');
|
||||||
assert(secp256k1.privateKeyVerify(key), 'Not a valid private key.');
|
assert(secp256k1.privateKeyVerify(key), 'Not a valid private key.');
|
||||||
|
|
||||||
@ -129,7 +132,7 @@ KeyRing.prototype.fromPrivate = function fromPrivate(key, compress) {
|
|||||||
this.publicKey = secp256k1.publicKeyCreate(key, compress !== false);
|
this.publicKey = secp256k1.publicKeyCreate(key, compress !== false);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate keyring from a private key.
|
* Instantiate keyring from a private key.
|
||||||
@ -138,9 +141,9 @@ KeyRing.prototype.fromPrivate = function fromPrivate(key, compress) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromPrivate = function fromPrivate(key, compress) {
|
static fromPrivate(key, compress) {
|
||||||
return new KeyRing().fromPrivate(key, compress);
|
return new this().fromPrivate(key, compress);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject data from public key.
|
* Inject data from public key.
|
||||||
@ -148,12 +151,12 @@ KeyRing.fromPrivate = function fromPrivate(key, compress) {
|
|||||||
* @param {Buffer} key
|
* @param {Buffer} key
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromPublic = function fromPublic(key) {
|
fromPublic(key) {
|
||||||
assert(Buffer.isBuffer(key), 'Public key must be a buffer.');
|
assert(Buffer.isBuffer(key), 'Public key must be a buffer.');
|
||||||
assert(secp256k1.publicKeyVerify(key), 'Not a valid public key.');
|
assert(secp256k1.publicKeyVerify(key), 'Not a valid public key.');
|
||||||
this.publicKey = key;
|
this.publicKey = key;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a keyring.
|
* Generate a keyring.
|
||||||
@ -162,10 +165,10 @@ KeyRing.prototype.fromPublic = function fromPublic(key) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.generate = function generate(compress) {
|
generate(compress) {
|
||||||
const key = secp256k1.generatePrivateKey();
|
const key = secp256k1.generatePrivateKey();
|
||||||
return this.fromKey(key, compress);
|
return this.fromKey(key, compress);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a keyring.
|
* Generate a keyring.
|
||||||
@ -173,9 +176,9 @@ KeyRing.prototype.generate = function generate(compress) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.generate = function generate(compress) {
|
static generate(compress) {
|
||||||
return new KeyRing().generate(compress);
|
return new this().generate(compress);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate keyring from a public key.
|
* Instantiate keyring from a public key.
|
||||||
@ -183,9 +186,9 @@ KeyRing.generate = function generate(compress) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromPublic = function fromPublic(key) {
|
static fromPublic(key) {
|
||||||
return new KeyRing().fromPublic(key);
|
return new this().fromPublic(key);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject data from public key.
|
* Inject data from public key.
|
||||||
@ -194,14 +197,14 @@ KeyRing.fromPublic = function fromPublic(key) {
|
|||||||
* @param {Boolean?} compress
|
* @param {Boolean?} compress
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromKey = function fromKey(key, compress) {
|
fromKey(key, compress) {
|
||||||
assert(Buffer.isBuffer(key), 'Key must be a buffer.');
|
assert(Buffer.isBuffer(key), 'Key must be a buffer.');
|
||||||
|
|
||||||
if (key.length === 32)
|
if (key.length === 32)
|
||||||
return this.fromPrivate(key, compress !== false);
|
return this.fromPrivate(key, compress !== false);
|
||||||
|
|
||||||
return this.fromPublic(key);
|
return this.fromPublic(key);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate keyring from a public key.
|
* Instantiate keyring from a public key.
|
||||||
@ -210,9 +213,9 @@ KeyRing.prototype.fromKey = function fromKey(key, compress) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromKey = function fromKey(key, compress) {
|
static fromKey(key, compress) {
|
||||||
return new KeyRing().fromKey(key, compress);
|
return new this().fromKey(key, compress);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject data from script.
|
* Inject data from script.
|
||||||
@ -222,14 +225,14 @@ KeyRing.fromKey = function fromKey(key, compress) {
|
|||||||
* @param {Boolean?} compress
|
* @param {Boolean?} compress
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromScript = function fromScript(key, script, compress) {
|
fromScript(key, script, compress) {
|
||||||
assert(script instanceof Script, 'Non-script passed into KeyRing.');
|
assert(script instanceof Script, 'Non-script passed into KeyRing.');
|
||||||
|
|
||||||
this.fromKey(key, compress);
|
this.fromKey(key, compress);
|
||||||
this.script = script;
|
this.script = script;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate keyring from script.
|
* Instantiate keyring from script.
|
||||||
@ -239,16 +242,16 @@ KeyRing.prototype.fromScript = function fromScript(key, script, compress) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromScript = function fromScript(key, script, compress) {
|
static fromScript(key, script, compress) {
|
||||||
return new KeyRing().fromScript(key, script, compress);
|
return new this().fromScript(key, script, compress);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate WIF serialization size.
|
* Calculate WIF serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getSecretSize = function getSecretSize() {
|
getSecretSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += 1;
|
size += 1;
|
||||||
@ -260,7 +263,7 @@ KeyRing.prototype.getSecretSize = function getSecretSize() {
|
|||||||
size += 4;
|
size += 4;
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert key to a CBitcoinSecret.
|
* Convert key to a CBitcoinSecret.
|
||||||
@ -268,7 +271,7 @@ KeyRing.prototype.getSecretSize = function getSecretSize() {
|
|||||||
* @returns {Base58String}
|
* @returns {Base58String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.toSecret = function toSecret(network) {
|
toSecret(network) {
|
||||||
const size = this.getSecretSize();
|
const size = this.getSecretSize();
|
||||||
const bw = new StaticWriter(size);
|
const bw = new StaticWriter(size);
|
||||||
|
|
||||||
@ -285,7 +288,7 @@ KeyRing.prototype.toSecret = function toSecret(network) {
|
|||||||
bw.writeChecksum(hash256.digest);
|
bw.writeChecksum(hash256.digest);
|
||||||
|
|
||||||
return base58.encode(bw.render());
|
return base58.encode(bw.render());
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized CBitcoinSecret.
|
* Inject properties from serialized CBitcoinSecret.
|
||||||
@ -294,7 +297,7 @@ KeyRing.prototype.toSecret = function toSecret(network) {
|
|||||||
* @param {(Network|NetworkType)?} network
|
* @param {(Network|NetworkType)?} network
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromSecret = function fromSecret(data, network) {
|
fromSecret(data, network) {
|
||||||
const br = new BufferReader(base58.decode(data), true);
|
const br = new BufferReader(base58.decode(data), true);
|
||||||
|
|
||||||
const version = br.readU8();
|
const version = br.readU8();
|
||||||
@ -313,7 +316,7 @@ KeyRing.prototype.fromSecret = function fromSecret(data, network) {
|
|||||||
br.verifyChecksum(hash256.digest);
|
br.verifyChecksum(hash256.digest);
|
||||||
|
|
||||||
return this.fromPrivate(key, compress);
|
return this.fromPrivate(key, compress);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a keyring from a serialized CBitcoinSecret.
|
* Instantiate a keyring from a serialized CBitcoinSecret.
|
||||||
@ -322,9 +325,9 @@ KeyRing.prototype.fromSecret = function fromSecret(data, network) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromSecret = function fromSecret(data, network) {
|
static fromSecret(data, network) {
|
||||||
return new KeyRing().fromSecret(data, network);
|
return new this().fromSecret(data, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get private key.
|
* Get private key.
|
||||||
@ -332,7 +335,7 @@ KeyRing.fromSecret = function fromSecret(data, network) {
|
|||||||
* @returns {Buffer} Private key.
|
* @returns {Buffer} Private key.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getPrivateKey = function getPrivateKey(enc, network) {
|
getPrivateKey(enc, network) {
|
||||||
if (!this.privateKey)
|
if (!this.privateKey)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -343,7 +346,7 @@ KeyRing.prototype.getPrivateKey = function getPrivateKey(enc, network) {
|
|||||||
return this.privateKey.toString('hex');
|
return this.privateKey.toString('hex');
|
||||||
|
|
||||||
return this.privateKey;
|
return this.privateKey;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get public key.
|
* Get public key.
|
||||||
@ -351,7 +354,7 @@ KeyRing.prototype.getPrivateKey = function getPrivateKey(enc, network) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getPublicKey = function getPublicKey(enc) {
|
getPublicKey(enc) {
|
||||||
if (enc === 'base58')
|
if (enc === 'base58')
|
||||||
return base58.encode(this.publicKey);
|
return base58.encode(this.publicKey);
|
||||||
|
|
||||||
@ -359,23 +362,23 @@ KeyRing.prototype.getPublicKey = function getPublicKey(enc) {
|
|||||||
return this.publicKey.toString('hex');
|
return this.publicKey.toString('hex');
|
||||||
|
|
||||||
return this.publicKey;
|
return this.publicKey;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get redeem script.
|
* Get redeem script.
|
||||||
* @returns {Script}
|
* @returns {Script}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getScript = function getScript() {
|
getScript() {
|
||||||
return this.script;
|
return this.script;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get witness program.
|
* Get witness program.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getProgram = function getProgram() {
|
getProgram() {
|
||||||
if (!this.witness)
|
if (!this.witness)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -392,7 +395,7 @@ KeyRing.prototype.getProgram = function getProgram() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this._program;
|
return this._program;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get address' ripemd160 program scripthash
|
* Get address' ripemd160 program scripthash
|
||||||
@ -401,7 +404,7 @@ KeyRing.prototype.getProgram = function getProgram() {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getNestedHash = function getNestedHash(enc) {
|
getNestedHash(enc) {
|
||||||
if (!this.witness)
|
if (!this.witness)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -411,7 +414,7 @@ KeyRing.prototype.getNestedHash = function getNestedHash(enc) {
|
|||||||
return enc === 'hex'
|
return enc === 'hex'
|
||||||
? this._nestedHash.toString('hex')
|
? this._nestedHash.toString('hex')
|
||||||
: this._nestedHash;
|
: this._nestedHash;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get address' scripthash address for witness program.
|
* Get address' scripthash address for witness program.
|
||||||
@ -419,7 +422,7 @@ KeyRing.prototype.getNestedHash = function getNestedHash(enc) {
|
|||||||
* @returns {Address|Base58Address}
|
* @returns {Address|Base58Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getNestedAddress = function getNestedAddress(enc, network) {
|
getNestedAddress(enc, network) {
|
||||||
if (!this.witness)
|
if (!this.witness)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -436,7 +439,7 @@ KeyRing.prototype.getNestedAddress = function getNestedAddress(enc, network) {
|
|||||||
return this._nestedAddress.toString(network);
|
return this._nestedAddress.toString(network);
|
||||||
|
|
||||||
return this._nestedAddress;
|
return this._nestedAddress;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get scripthash.
|
* Get scripthash.
|
||||||
@ -444,11 +447,11 @@ KeyRing.prototype.getNestedAddress = function getNestedAddress(enc, network) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getScriptHash = function getScriptHash(enc) {
|
getScriptHash(enc) {
|
||||||
if (this.witness)
|
if (this.witness)
|
||||||
return this.getScriptHash256(enc);
|
return this.getScriptHash256(enc);
|
||||||
return this.getScriptHash160(enc);
|
return this.getScriptHash160(enc);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get ripemd160 scripthash.
|
* Get ripemd160 scripthash.
|
||||||
@ -456,7 +459,7 @@ KeyRing.prototype.getScriptHash = function getScriptHash(enc) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getScriptHash160 = function getScriptHash160(enc) {
|
getScriptHash160(enc) {
|
||||||
if (!this.script)
|
if (!this.script)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -466,7 +469,7 @@ KeyRing.prototype.getScriptHash160 = function getScriptHash160(enc) {
|
|||||||
return enc === 'hex'
|
return enc === 'hex'
|
||||||
? this._scriptHash160.toString('hex')
|
? this._scriptHash160.toString('hex')
|
||||||
: this._scriptHash160;
|
: this._scriptHash160;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get sha256 scripthash.
|
* Get sha256 scripthash.
|
||||||
@ -474,7 +477,7 @@ KeyRing.prototype.getScriptHash160 = function getScriptHash160(enc) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getScriptHash256 = function getScriptHash256(enc) {
|
getScriptHash256(enc) {
|
||||||
if (!this.script)
|
if (!this.script)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -484,7 +487,7 @@ KeyRing.prototype.getScriptHash256 = function getScriptHash256(enc) {
|
|||||||
return enc === 'hex'
|
return enc === 'hex'
|
||||||
? this._scriptHash256.toString('hex')
|
? this._scriptHash256.toString('hex')
|
||||||
: this._scriptHash256;
|
: this._scriptHash256;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get scripthash address.
|
* Get scripthash address.
|
||||||
@ -492,7 +495,7 @@ KeyRing.prototype.getScriptHash256 = function getScriptHash256(enc) {
|
|||||||
* @returns {Address|Base58Address}
|
* @returns {Address|Base58Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getScriptAddress = function getScriptAddress(enc, network) {
|
getScriptAddress(enc, network) {
|
||||||
if (!this.script)
|
if (!this.script)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@ -515,7 +518,7 @@ KeyRing.prototype.getScriptAddress = function getScriptAddress(enc, network) {
|
|||||||
return this._scriptAddress.toString(network);
|
return this._scriptAddress.toString(network);
|
||||||
|
|
||||||
return this._scriptAddress;
|
return this._scriptAddress;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get public key hash.
|
* Get public key hash.
|
||||||
@ -523,14 +526,14 @@ KeyRing.prototype.getScriptAddress = function getScriptAddress(enc, network) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getKeyHash = function getKeyHash(enc) {
|
getKeyHash(enc) {
|
||||||
if (!this._keyHash)
|
if (!this._keyHash)
|
||||||
this._keyHash = hash160.digest(this.publicKey);
|
this._keyHash = hash160.digest(this.publicKey);
|
||||||
|
|
||||||
return enc === 'hex'
|
return enc === 'hex'
|
||||||
? this._keyHash.toString('hex')
|
? this._keyHash.toString('hex')
|
||||||
: this._keyHash;
|
: this._keyHash;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get pubkeyhash address.
|
* Get pubkeyhash address.
|
||||||
@ -538,7 +541,7 @@ KeyRing.prototype.getKeyHash = function getKeyHash(enc) {
|
|||||||
* @returns {Address|Base58Address}
|
* @returns {Address|Base58Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getKeyAddress = function getKeyAddress(enc, network) {
|
getKeyAddress(enc, network) {
|
||||||
if (!this._keyAddress) {
|
if (!this._keyAddress) {
|
||||||
const hash = this.getKeyHash();
|
const hash = this.getKeyHash();
|
||||||
|
|
||||||
@ -558,7 +561,7 @@ KeyRing.prototype.getKeyAddress = function getKeyAddress(enc, network) {
|
|||||||
return this._keyAddress.toString(network);
|
return this._keyAddress.toString(network);
|
||||||
|
|
||||||
return this._keyAddress;
|
return this._keyAddress;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get hash.
|
* Get hash.
|
||||||
@ -566,7 +569,7 @@ KeyRing.prototype.getKeyAddress = function getKeyAddress(enc, network) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getHash = function getHash(enc) {
|
getHash(enc) {
|
||||||
if (this.nested)
|
if (this.nested)
|
||||||
return this.getNestedHash(enc);
|
return this.getNestedHash(enc);
|
||||||
|
|
||||||
@ -574,7 +577,7 @@ KeyRing.prototype.getHash = function getHash(enc) {
|
|||||||
return this.getScriptHash(enc);
|
return this.getScriptHash(enc);
|
||||||
|
|
||||||
return this.getKeyHash(enc);
|
return this.getKeyHash(enc);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get base58 address.
|
* Get base58 address.
|
||||||
@ -582,7 +585,7 @@ KeyRing.prototype.getHash = function getHash(enc) {
|
|||||||
* @returns {Address|Base58Address}
|
* @returns {Address|Base58Address}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getAddress = function getAddress(enc, network) {
|
getAddress(enc, network) {
|
||||||
if (this.nested)
|
if (this.nested)
|
||||||
return this.getNestedAddress(enc, network);
|
return this.getNestedAddress(enc, network);
|
||||||
|
|
||||||
@ -590,7 +593,7 @@ KeyRing.prototype.getAddress = function getAddress(enc, network) {
|
|||||||
return this.getScriptAddress(enc, network);
|
return this.getScriptAddress(enc, network);
|
||||||
|
|
||||||
return this.getKeyAddress(enc, network);
|
return this.getKeyAddress(enc, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an address hash against hash and program hash.
|
* Test an address hash against hash and program hash.
|
||||||
@ -598,7 +601,7 @@ KeyRing.prototype.getAddress = function getAddress(enc, network) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.ownHash = function ownHash(hash) {
|
ownHash(hash) {
|
||||||
if (!hash)
|
if (!hash)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -616,7 +619,7 @@ KeyRing.prototype.ownHash = function ownHash(hash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether transaction output belongs to this address.
|
* Check whether transaction output belongs to this address.
|
||||||
@ -625,7 +628,7 @@ KeyRing.prototype.ownHash = function ownHash(hash) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.ownOutput = function ownOutput(tx, index) {
|
ownOutput(tx, index) {
|
||||||
let output;
|
let output;
|
||||||
|
|
||||||
if (tx instanceof Output) {
|
if (tx instanceof Output) {
|
||||||
@ -636,7 +639,7 @@ KeyRing.prototype.ownOutput = function ownOutput(tx, index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this.ownHash(output.getHash());
|
return this.ownHash(output.getHash());
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test a hash against script hashes to
|
* Test a hash against script hashes to
|
||||||
@ -645,7 +648,7 @@ KeyRing.prototype.ownOutput = function ownOutput(tx, index) {
|
|||||||
* @returns {Script|null}
|
* @returns {Script|null}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getRedeem = function getRedeem(hash) {
|
getRedeem(hash) {
|
||||||
if (this.witness) {
|
if (this.witness) {
|
||||||
if (hash.equals(this.getNestedHash()))
|
if (hash.equals(this.getNestedHash()))
|
||||||
return this.getProgram();
|
return this.getProgram();
|
||||||
@ -660,7 +663,7 @@ KeyRing.prototype.getRedeem = function getRedeem(hash) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign a message.
|
* Sign a message.
|
||||||
@ -668,10 +671,10 @@ KeyRing.prototype.getRedeem = function getRedeem(hash) {
|
|||||||
* @returns {Buffer} Signature in DER format.
|
* @returns {Buffer} Signature in DER format.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.sign = function sign(msg) {
|
sign(msg) {
|
||||||
assert(this.privateKey, 'Cannot sign without private key.');
|
assert(this.privateKey, 'Cannot sign without private key.');
|
||||||
return secp256k1.sign(msg, this.privateKey);
|
return secp256k1.sign(msg, this.privateKey);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify a message.
|
* Verify a message.
|
||||||
@ -680,16 +683,16 @@ KeyRing.prototype.sign = function sign(msg) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.verify = function verify(msg, sig) {
|
verify(msg, sig) {
|
||||||
return secp256k1.verify(msg, sig, this.publicKey);
|
return secp256k1.verify(msg, sig, this.publicKey);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get witness program version.
|
* Get witness program version.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getVersion = function getVersion() {
|
getVersion() {
|
||||||
if (!this.witness)
|
if (!this.witness)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -697,14 +700,14 @@ KeyRing.prototype.getVersion = function getVersion() {
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get address type.
|
* Get address type.
|
||||||
* @returns {ScriptType}
|
* @returns {ScriptType}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getType = function getType() {
|
getType() {
|
||||||
if (this.nested)
|
if (this.nested)
|
||||||
return Address.types.SCRIPTHASH;
|
return Address.types.SCRIPTHASH;
|
||||||
|
|
||||||
@ -715,23 +718,23 @@ KeyRing.prototype.getType = function getType() {
|
|||||||
return Address.types.SCRIPTHASH;
|
return Address.types.SCRIPTHASH;
|
||||||
|
|
||||||
return Address.types.PUBKEYHASH;
|
return Address.types.PUBKEYHASH;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect keyring.
|
* Inspect keyring.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return this.toJSON();
|
return this.toJSON();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an KeyRing to a more json-friendly object.
|
* Convert an KeyRing to a more json-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.toJSON = function toJSON(network) {
|
toJSON(network) {
|
||||||
return {
|
return {
|
||||||
witness: this.witness,
|
witness: this.witness,
|
||||||
nested: this.nested,
|
nested: this.nested,
|
||||||
@ -741,7 +744,7 @@ KeyRing.prototype.toJSON = function toJSON(network) {
|
|||||||
type: Address.typesByVal[this.getType()].toLowerCase(),
|
type: Address.typesByVal[this.getType()].toLowerCase(),
|
||||||
address: this.getAddress('string', network)
|
address: this.getAddress('string', network)
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from json object.
|
* Inject properties from json object.
|
||||||
@ -749,7 +752,7 @@ KeyRing.prototype.toJSON = function toJSON(network) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert(json);
|
assert(json);
|
||||||
assert(typeof json.witness === 'boolean');
|
assert(typeof json.witness === 'boolean');
|
||||||
assert(typeof json.nested === 'boolean');
|
assert(typeof json.nested === 'boolean');
|
||||||
@ -764,7 +767,7 @@ KeyRing.prototype.fromJSON = function fromJSON(json) {
|
|||||||
this.script = Buffer.from(json.script, 'hex');
|
this.script = Buffer.from(json.script, 'hex');
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an KeyRing from a jsonified transaction object.
|
* Instantiate an KeyRing from a jsonified transaction object.
|
||||||
@ -772,16 +775,16 @@ KeyRing.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new KeyRing().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate serialization size.
|
* Calculate serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
size += 1;
|
size += 1;
|
||||||
if (this.privateKey) {
|
if (this.privateKey) {
|
||||||
@ -792,14 +795,14 @@ KeyRing.prototype.getSize = function getSize() {
|
|||||||
}
|
}
|
||||||
size += this.script ? this.script.getVarSize() : 1;
|
size += this.script ? this.script.getVarSize() : 1;
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the keyring to a buffer writer.
|
* Write the keyring to a buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
let field = 0;
|
let field = 0;
|
||||||
|
|
||||||
if (this.witness)
|
if (this.witness)
|
||||||
@ -823,17 +826,17 @@ KeyRing.prototype.toWriter = function toWriter(bw) {
|
|||||||
bw.writeVarint(0);
|
bw.writeVarint(0);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the keyring.
|
* Serialize the keyring.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
return this.toWriter(new StaticWriter(size)).render();
|
return this.toWriter(new StaticWriter(size)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -841,7 +844,7 @@ KeyRing.prototype.toRaw = function toRaw() {
|
|||||||
* @param {BufferReader} br
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
const field = br.readU8();
|
const field = br.readU8();
|
||||||
|
|
||||||
this.witness = (field & 1) !== 0;
|
this.witness = (field & 1) !== 0;
|
||||||
@ -864,7 +867,7 @@ KeyRing.prototype.fromReader = function fromReader(br) {
|
|||||||
this.script = Script.fromRaw(script);
|
this.script = Script.fromRaw(script);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -872,9 +875,9 @@ KeyRing.prototype.fromReader = function fromReader(br) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a keyring from buffer reader.
|
* Instantiate a keyring from buffer reader.
|
||||||
@ -882,9 +885,9 @@ KeyRing.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new KeyRing().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a keyring from serialized data.
|
* Instantiate a keyring from serialized data.
|
||||||
@ -892,9 +895,9 @@ KeyRing.fromReader = function fromReader(br) {
|
|||||||
* @returns {KeyRing}
|
* @returns {KeyRing}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new KeyRing().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an object is a KeyRing.
|
* Test whether an object is a KeyRing.
|
||||||
@ -902,9 +905,10 @@ KeyRing.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
KeyRing.isKeyRing = function isKeyRing(obj) {
|
static isKeyRing(obj) {
|
||||||
return obj instanceof KeyRing;
|
return obj instanceof KeyRing;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
|
|||||||
@ -15,6 +15,7 @@ const BufferReader = require('bufio/lib/reader');
|
|||||||
const DUMMY = Buffer.alloc(0);
|
const DUMMY = Buffer.alloc(0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Mem Block
|
||||||
* A block object which is essentially a "placeholder"
|
* A block object which is essentially a "placeholder"
|
||||||
* for a full {@link Block} object. The v8 garbage
|
* for a full {@link Block} object. The v8 garbage
|
||||||
* collector's head will explode if there is too much
|
* collector's head will explode if there is too much
|
||||||
@ -31,56 +32,56 @@ const DUMMY = Buffer.alloc(0);
|
|||||||
* 500mb of blocks on the js heap would not be a good
|
* 500mb of blocks on the js heap would not be a good
|
||||||
* thing.
|
* thing.
|
||||||
* @alias module:primitives.MemBlock
|
* @alias module:primitives.MemBlock
|
||||||
* @constructor
|
* @extends AbstractBlock
|
||||||
* @param {NakedBlock} options
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function MemBlock() {
|
class MemBlock extends AbstractBlock {
|
||||||
if (!(this instanceof MemBlock))
|
/**
|
||||||
return new MemBlock();
|
* Create a mem block.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
AbstractBlock.call(this);
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
this._raw = DUMMY;
|
this._raw = DUMMY;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(MemBlock.prototype, AbstractBlock.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the block is a memblock.
|
* Test whether the block is a memblock.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.isMemory = function isMemory() {
|
isMemory() {
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the block headers.
|
* Serialize the block headers.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.toHead = function toHead() {
|
toHead() {
|
||||||
return this._raw.slice(0, 80);
|
return this._raw.slice(0, 80);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the full block size.
|
* Get the full block size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
return this._raw.length;
|
return this._raw.length;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the block.
|
* Verify the block.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.verifyBody = function verifyBody() {
|
verifyBody() {
|
||||||
return true;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the coinbase height
|
* Retrieve the coinbase height
|
||||||
@ -88,7 +89,7 @@ MemBlock.prototype.verifyBody = function verifyBody() {
|
|||||||
* @returns {Number} height (-1 if not present).
|
* @returns {Number} height (-1 if not present).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
getCoinbaseHeight() {
|
||||||
if (this.version < 2)
|
if (this.version < 2)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ MemBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the coinbase height
|
* Parse the coinbase height
|
||||||
@ -106,7 +107,7 @@ MemBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
|||||||
* @returns {Number} height (-1 if not present).
|
* @returns {Number} height (-1 if not present).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.parseCoinbaseHeight = function parseCoinbaseHeight() {
|
parseCoinbaseHeight() {
|
||||||
const br = new BufferReader(this._raw, true);
|
const br = new BufferReader(this._raw, true);
|
||||||
|
|
||||||
br.seek(80);
|
br.seek(80);
|
||||||
@ -133,7 +134,7 @@ MemBlock.prototype.parseCoinbaseHeight = function parseCoinbaseHeight() {
|
|||||||
const script = br.readVarBytes();
|
const script = br.readVarBytes();
|
||||||
|
|
||||||
return Script.getCoinbaseHeight(script);
|
return Script.getCoinbaseHeight(script);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -141,7 +142,7 @@ MemBlock.prototype.parseCoinbaseHeight = function parseCoinbaseHeight() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = new BufferReader(data, true);
|
const br = new BufferReader(data, true);
|
||||||
|
|
||||||
this.readHead(br);
|
this.readHead(br);
|
||||||
@ -149,7 +150,7 @@ MemBlock.prototype.fromRaw = function fromRaw(data) {
|
|||||||
this._raw = br.data;
|
this._raw = br.data;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insantiate a memblock from serialized data.
|
* Insantiate a memblock from serialized data.
|
||||||
@ -157,27 +158,27 @@ MemBlock.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {MemBlock}
|
* @returns {MemBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new MemBlock().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return serialized block data.
|
* Return serialized block data.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
return this._raw;
|
return this._raw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return serialized block data.
|
* Return serialized block data.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.toNormal = function toNormal() {
|
toNormal() {
|
||||||
return this._raw;
|
return this._raw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the serialized block data
|
* Parse the serialized block data
|
||||||
@ -186,23 +187,23 @@ MemBlock.prototype.toNormal = function toNormal() {
|
|||||||
* @throws Parse error
|
* @throws Parse error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.toBlock = function toBlock() {
|
toBlock() {
|
||||||
const block = Block.fromRaw(this._raw);
|
const block = Block.fromRaw(this._raw);
|
||||||
|
|
||||||
block._hash = this._hash;
|
block._hash = this._hash;
|
||||||
block._hhash = this._hhash;
|
block._hhash = this._hhash;
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to a headers object.
|
* Convert the block to a headers object.
|
||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.prototype.toHeaders = function toHeaders() {
|
toHeaders() {
|
||||||
return Headers.fromBlock(this);
|
return Headers.fromBlock(this);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an object is a MemBlock.
|
* Test whether an object is a MemBlock.
|
||||||
@ -210,9 +211,10 @@ MemBlock.prototype.toHeaders = function toHeaders() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MemBlock.isMemBlock = function isMemBlock(obj) {
|
static isMemBlock(obj) {
|
||||||
return obj instanceof MemBlock;
|
return obj instanceof MemBlock;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -19,18 +19,21 @@ const Headers = require('./headers');
|
|||||||
const DUMMY = Buffer.from([0]);
|
const DUMMY = Buffer.from([0]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Merkle Block
|
||||||
* Represents a merkle (filtered) block.
|
* Represents a merkle (filtered) block.
|
||||||
* @alias module:primitives.MerkleBlock
|
* @alias module:primitives.MerkleBlock
|
||||||
* @constructor
|
|
||||||
* @extends AbstractBlock
|
* @extends AbstractBlock
|
||||||
* @param {NakedBlock} options
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function MerkleBlock(options) {
|
class MerkleBlock extends AbstractBlock {
|
||||||
if (!(this instanceof MerkleBlock))
|
/**
|
||||||
return new MerkleBlock(options);
|
* Create a merkle block.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
*/
|
||||||
|
|
||||||
AbstractBlock.call(this);
|
constructor(options) {
|
||||||
|
super();
|
||||||
|
|
||||||
this.txs = [];
|
this.txs = [];
|
||||||
this.hashes = [];
|
this.hashes = [];
|
||||||
@ -43,15 +46,13 @@ function MerkleBlock(options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(MerkleBlock.prototype, AbstractBlock.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
* @private
|
* @private
|
||||||
* @param {NakedBlock} options
|
* @param {NakedBlock} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
this.parseOptions(options);
|
this.parseOptions(options);
|
||||||
|
|
||||||
assert(options, 'MerkleBlock data is required.');
|
assert(options, 'MerkleBlock data is required.');
|
||||||
@ -79,7 +80,7 @@ MerkleBlock.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate merkle block from options object.
|
* Instantiate merkle block from options object.
|
||||||
@ -87,16 +88,16 @@ MerkleBlock.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {MerkleBlock}
|
* @returns {MerkleBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.fromOptions = function fromOptions(data) {
|
static fromOptions(data) {
|
||||||
return new MerkleBlock().fromOptions(data);
|
return new this().fromOptions(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear any cached values.
|
* Clear any cached values.
|
||||||
* @param {Boolean?} all - Clear transactions.
|
* @param {Boolean?} all - Clear transactions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.refresh = function refresh(all) {
|
refresh(all) {
|
||||||
this._refresh();
|
this._refresh();
|
||||||
this._tree = null;
|
this._tree = null;
|
||||||
|
|
||||||
@ -105,7 +106,7 @@ MerkleBlock.prototype.refresh = function refresh(all) {
|
|||||||
|
|
||||||
for (const tx of this.txs)
|
for (const tx of this.txs)
|
||||||
tx.refresh();
|
tx.refresh();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the block's _matched_ transaction vector against a hash.
|
* Test the block's _matched_ transaction vector against a hash.
|
||||||
@ -113,9 +114,9 @@ MerkleBlock.prototype.refresh = function refresh(all) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.hasTX = function hasTX(hash) {
|
hasTX(hash) {
|
||||||
return this.indexOf(hash) !== -1;
|
return this.indexOf(hash) !== -1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the block's _matched_ transaction vector against a hash.
|
* Test the block's _matched_ transaction vector against a hash.
|
||||||
@ -123,7 +124,7 @@ MerkleBlock.prototype.hasTX = function hasTX(hash) {
|
|||||||
* @returns {Number} Index.
|
* @returns {Number} Index.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.indexOf = function indexOf(hash) {
|
indexOf(hash) {
|
||||||
const tree = this.getTree();
|
const tree = this.getTree();
|
||||||
const index = tree.map.get(hash);
|
const index = tree.map.get(hash);
|
||||||
|
|
||||||
@ -131,7 +132,7 @@ MerkleBlock.prototype.indexOf = function indexOf(hash) {
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the partial merkletree.
|
* Verify the partial merkletree.
|
||||||
@ -139,10 +140,10 @@ MerkleBlock.prototype.indexOf = function indexOf(hash) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.verifyBody = function verifyBody() {
|
verifyBody() {
|
||||||
const [valid] = this.checkBody();
|
const [valid] = this.checkBody();
|
||||||
return valid;
|
return valid;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the partial merkletree.
|
* Verify the partial merkletree.
|
||||||
@ -150,14 +151,14 @@ MerkleBlock.prototype.verifyBody = function verifyBody() {
|
|||||||
* @returns {Array} [valid, reason, score]
|
* @returns {Array} [valid, reason, score]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.checkBody = function checkBody() {
|
checkBody() {
|
||||||
const tree = this.getTree();
|
const tree = this.getTree();
|
||||||
|
|
||||||
if (tree.root !== this.merkleRoot)
|
if (tree.root !== this.merkleRoot)
|
||||||
return [false, 'bad-txnmrklroot', 100];
|
return [false, 'bad-txnmrklroot', 100];
|
||||||
|
|
||||||
return [true, 'valid', 0];
|
return [true, 'valid', 0];
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the matches from partial merkle
|
* Extract the matches from partial merkle
|
||||||
@ -165,7 +166,7 @@ MerkleBlock.prototype.checkBody = function checkBody() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.getTree = function getTree() {
|
getTree() {
|
||||||
if (!this._tree) {
|
if (!this._tree) {
|
||||||
try {
|
try {
|
||||||
this._tree = this.extractTree();
|
this._tree = this.extractTree();
|
||||||
@ -174,7 +175,7 @@ MerkleBlock.prototype.getTree = function getTree() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this._tree;
|
return this._tree;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the matches from partial merkle
|
* Extract the matches from partial merkle
|
||||||
@ -183,13 +184,14 @@ MerkleBlock.prototype.getTree = function getTree() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.extractTree = function extractTree() {
|
extractTree() {
|
||||||
const matches = [];
|
const matches = [];
|
||||||
const indexes = [];
|
const indexes = [];
|
||||||
const map = new Map();
|
const map = new Map();
|
||||||
const hashes = this.hashes;
|
const hashes = this.hashes;
|
||||||
const flags = this.flags;
|
const flags = this.flags;
|
||||||
const totalTX = this.totalTX;
|
const totalTX = this.totalTX;
|
||||||
|
|
||||||
let bitsUsed = 0;
|
let bitsUsed = 0;
|
||||||
let hashUsed = 0;
|
let hashUsed = 0;
|
||||||
let failed = false;
|
let failed = false;
|
||||||
@ -207,7 +209,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
|
|||||||
|
|
||||||
const parent = (flags[bitsUsed / 8 | 0] >>> (bitsUsed % 8)) & 1;
|
const parent = (flags[bitsUsed / 8 | 0] >>> (bitsUsed % 8)) & 1;
|
||||||
|
|
||||||
bitsUsed++;
|
bitsUsed += 1;
|
||||||
|
|
||||||
if (height === 0 || !parent) {
|
if (height === 0 || !parent) {
|
||||||
if (hashUsed >= hashes.length) {
|
if (hashUsed >= hashes.length) {
|
||||||
@ -215,7 +217,9 @@ MerkleBlock.prototype.extractTree = function extractTree() {
|
|||||||
return encoding.ZERO_HASH;
|
return encoding.ZERO_HASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hash = hashes[hashUsed++];
|
const hash = hashes[hashUsed];
|
||||||
|
|
||||||
|
hashUsed += 1;
|
||||||
|
|
||||||
if (height === 0 && parent) {
|
if (height === 0 && parent) {
|
||||||
const txid = hash.toString('hex');
|
const txid = hash.toString('hex');
|
||||||
@ -254,7 +258,7 @@ MerkleBlock.prototype.extractTree = function extractTree() {
|
|||||||
throw new Error('Flags too small.');
|
throw new Error('Flags too small.');
|
||||||
|
|
||||||
while (width(height) > 1)
|
while (width(height) > 1)
|
||||||
height++;
|
height += 1;
|
||||||
|
|
||||||
const root = traverse(height, 0);
|
const root = traverse(height, 0);
|
||||||
|
|
||||||
@ -268,16 +272,16 @@ MerkleBlock.prototype.extractTree = function extractTree() {
|
|||||||
throw new Error('Incorrect number of hashes.');
|
throw new Error('Incorrect number of hashes.');
|
||||||
|
|
||||||
return new PartialTree(root, matches, indexes, map);
|
return new PartialTree(root, matches, indexes, map);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the coinbase height (always -1).
|
* Extract the coinbase height (always -1).
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
getCoinbaseHeight() {
|
||||||
return -1;
|
return -1;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the block and return a more
|
* Inspect the block and return a more
|
||||||
@ -285,9 +289,9 @@ MerkleBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return this.format();
|
return this.format();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the block and return a more
|
* Inspect the block and return a more
|
||||||
@ -297,7 +301,7 @@ MerkleBlock.prototype.inspect = function inspect() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.format = function format(view, height) {
|
format(view, height) {
|
||||||
return {
|
return {
|
||||||
hash: this.rhash(),
|
hash: this.rhash(),
|
||||||
height: height != null ? height : -1,
|
height: height != null ? height : -1,
|
||||||
@ -316,14 +320,14 @@ MerkleBlock.prototype.format = function format(view, height) {
|
|||||||
map: this.getTree().map,
|
map: this.getTree().map,
|
||||||
txs: this.txs.length
|
txs: this.txs.length
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get merkleblock size.
|
* Get merkleblock size.
|
||||||
* @returns {Number} Size.
|
* @returns {Number} Size.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
size += 80;
|
size += 80;
|
||||||
size += 4;
|
size += 4;
|
||||||
@ -332,14 +336,14 @@ MerkleBlock.prototype.getSize = function getSize() {
|
|||||||
size += encoding.sizeVarint(this.flags.length);
|
size += encoding.sizeVarint(this.flags.length);
|
||||||
size += this.flags.length;
|
size += this.flags.length;
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the merkleblock to a buffer writer.
|
* Write the merkleblock to a buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
this.writeHead(bw);
|
this.writeHead(bw);
|
||||||
|
|
||||||
bw.writeU32(this.totalTX);
|
bw.writeU32(this.totalTX);
|
||||||
@ -352,7 +356,7 @@ MerkleBlock.prototype.toWriter = function toWriter(bw) {
|
|||||||
bw.writeVarBytes(this.flags);
|
bw.writeVarBytes(this.flags);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the merkleblock.
|
* Serialize the merkleblock.
|
||||||
@ -360,10 +364,10 @@ MerkleBlock.prototype.toWriter = function toWriter(bw) {
|
|||||||
* @returns {Buffer|String}
|
* @returns {Buffer|String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
return this.toWriter(new StaticWriter(size)).render();
|
return this.toWriter(new StaticWriter(size)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -371,7 +375,7 @@ MerkleBlock.prototype.toRaw = function toRaw() {
|
|||||||
* @param {BufferReader} br
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
this.readHead(br);
|
this.readHead(br);
|
||||||
|
|
||||||
this.totalTX = br.readU32();
|
this.totalTX = br.readU32();
|
||||||
@ -384,7 +388,7 @@ MerkleBlock.prototype.fromReader = function fromReader(br) {
|
|||||||
this.flags = br.readVarBytes();
|
this.flags = br.readVarBytes();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -392,9 +396,9 @@ MerkleBlock.prototype.fromReader = function fromReader(br) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a merkleblock from a buffer reader.
|
* Instantiate a merkleblock from a buffer reader.
|
||||||
@ -402,9 +406,9 @@ MerkleBlock.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {MerkleBlock}
|
* @returns {MerkleBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new MerkleBlock().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a merkleblock from a serialized data.
|
* Instantiate a merkleblock from a serialized data.
|
||||||
@ -413,11 +417,11 @@ MerkleBlock.fromReader = function fromReader(br) {
|
|||||||
* @returns {MerkleBlock}
|
* @returns {MerkleBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.fromRaw = function fromRaw(data, enc) {
|
static fromRaw(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new MerkleBlock().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to an object suitable
|
* Convert the block to an object suitable
|
||||||
@ -425,9 +429,9 @@ MerkleBlock.fromRaw = function fromRaw(data, enc) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return this.getJSON();
|
return this.getJSON();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to an object suitable
|
* Convert the block to an object suitable
|
||||||
@ -440,7 +444,7 @@ MerkleBlock.prototype.toJSON = function toJSON() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.getJSON = function getJSON(network, view, height) {
|
getJSON(network, view, height) {
|
||||||
return {
|
return {
|
||||||
hash: this.rhash(),
|
hash: this.rhash(),
|
||||||
height: height,
|
height: height,
|
||||||
@ -456,7 +460,7 @@ MerkleBlock.prototype.getJSON = function getJSON(network, view, height) {
|
|||||||
}),
|
}),
|
||||||
flags: this.flags.toString('hex')
|
flags: this.flags.toString('hex')
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from json object.
|
* Inject properties from json object.
|
||||||
@ -464,7 +468,7 @@ MerkleBlock.prototype.getJSON = function getJSON(network, view, height) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert(json, 'MerkleBlock data is required.');
|
assert(json, 'MerkleBlock data is required.');
|
||||||
assert(Array.isArray(json.hashes));
|
assert(Array.isArray(json.hashes));
|
||||||
assert(typeof json.flags === 'string');
|
assert(typeof json.flags === 'string');
|
||||||
@ -482,7 +486,7 @@ MerkleBlock.prototype.fromJSON = function fromJSON(json) {
|
|||||||
this.totalTX = json.totalTX;
|
this.totalTX = json.totalTX;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a merkle block from a jsonified block object.
|
* Instantiate a merkle block from a jsonified block object.
|
||||||
@ -490,9 +494,9 @@ MerkleBlock.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {MerkleBlock}
|
* @returns {MerkleBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new MerkleBlock().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a merkleblock from a {@link Block} object, passing
|
* Create a merkleblock from a {@link Block} object, passing
|
||||||
@ -503,14 +507,14 @@ MerkleBlock.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {MerkleBlock}
|
* @returns {MerkleBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.fromBlock = function fromBlock(block, filter) {
|
static fromBlock(block, filter) {
|
||||||
const matches = [];
|
const matches = [];
|
||||||
|
|
||||||
for (const tx of block.txs)
|
for (const tx of block.txs)
|
||||||
matches.push(tx.isWatched(filter) ? 1 : 0);
|
matches.push(tx.isWatched(filter) ? 1 : 0);
|
||||||
|
|
||||||
return MerkleBlock.fromMatches(block, matches);
|
return this.fromMatches(block, matches);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a merkleblock from an array of txids.
|
* Create a merkleblock from an array of txids.
|
||||||
@ -520,7 +524,7 @@ MerkleBlock.fromBlock = function fromBlock(block, filter) {
|
|||||||
* @returns {MerkleBlock}
|
* @returns {MerkleBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.fromHashes = function fromHashes(block, hashes) {
|
static fromHashes(block, hashes) {
|
||||||
const filter = new Set();
|
const filter = new Set();
|
||||||
|
|
||||||
for (let hash of hashes) {
|
for (let hash of hashes) {
|
||||||
@ -536,8 +540,8 @@ MerkleBlock.fromHashes = function fromHashes(block, hashes) {
|
|||||||
matches.push(filter.has(hash) ? 1 : 0);
|
matches.push(filter.has(hash) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MerkleBlock.fromMatches(block, matches);
|
return this.fromMatches(block, matches);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a merkleblock from an array of matches.
|
* Create a merkleblock from an array of matches.
|
||||||
@ -547,7 +551,7 @@ MerkleBlock.fromHashes = function fromHashes(block, hashes) {
|
|||||||
* @returns {MerkleBlock}
|
* @returns {MerkleBlock}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
static fromMatches(block, matches) {
|
||||||
const txs = [];
|
const txs = [];
|
||||||
const leaves = [];
|
const leaves = [];
|
||||||
const bits = [];
|
const bits = [];
|
||||||
@ -577,7 +581,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
|||||||
const traverse = (height, pos, leaves, matches) => {
|
const traverse = (height, pos, leaves, matches) => {
|
||||||
let parent = 0;
|
let parent = 0;
|
||||||
|
|
||||||
for (let p = (pos << height); p < ((pos + 1) << height) && p < totalTX; p++)
|
for (let p = pos << height; p < ((pos + 1) << height) && p < totalTX; p++)
|
||||||
parent |= matches[p];
|
parent |= matches[p];
|
||||||
|
|
||||||
bits.push(parent);
|
bits.push(parent);
|
||||||
@ -603,7 +607,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (width(height) > 1)
|
while (width(height) > 1)
|
||||||
height++;
|
height += 1;
|
||||||
|
|
||||||
traverse(height, 0, leaves, matches);
|
traverse(height, 0, leaves, matches);
|
||||||
|
|
||||||
@ -613,7 +617,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
|||||||
for (let p = 0; p < bits.length; p++)
|
for (let p = 0; p < bits.length; p++)
|
||||||
flags[p / 8 | 0] |= bits[p] << (p % 8);
|
flags[p / 8 | 0] |= bits[p] << (p % 8);
|
||||||
|
|
||||||
const merkle = new MerkleBlock();
|
const merkle = new this();
|
||||||
merkle._hash = block._hash;
|
merkle._hash = block._hash;
|
||||||
merkle._hhash = block._hhash;
|
merkle._hhash = block._hhash;
|
||||||
merkle.version = block.version;
|
merkle.version = block.version;
|
||||||
@ -628,7 +632,7 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
|||||||
merkle.txs = txs;
|
merkle.txs = txs;
|
||||||
|
|
||||||
return merkle;
|
return merkle;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an object is a MerkleBlock.
|
* Test whether an object is a MerkleBlock.
|
||||||
@ -636,29 +640,32 @@ MerkleBlock.fromMatches = function fromMatches(block, matches) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.isMerkleBlock = function isMerkleBlock(obj) {
|
static isMerkleBlock(obj) {
|
||||||
return obj instanceof MerkleBlock;
|
return obj instanceof MerkleBlock;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the block to a headers object.
|
* Convert the block to a headers object.
|
||||||
* @returns {Headers}
|
* @returns {Headers}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MerkleBlock.prototype.toHeaders = function toHeaders() {
|
toHeaders() {
|
||||||
return Headers.fromBlock(this);
|
return Headers.fromBlock(this);
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function PartialTree(root, matches, indexes, map) {
|
class PartialTree {
|
||||||
|
constructor(root, matches, indexes, map) {
|
||||||
this.root = root ? root.toString('hex') : encoding.NULL_HASH;
|
this.root = root ? root.toString('hex') : encoding.NULL_HASH;
|
||||||
this.matches = matches || [];
|
this.matches = matches || [];
|
||||||
this.indexes = indexes || [];
|
this.indexes = indexes || [];
|
||||||
this.map = map || new Map();
|
this.map = map || new Map();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -15,24 +15,27 @@ const StaticWriter = require('bufio/lib/staticwriter');
|
|||||||
const BufferReader = require('bufio/lib/reader');
|
const BufferReader = require('bufio/lib/reader');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Net Address
|
||||||
* Represents a network address.
|
* Represents a network address.
|
||||||
* @alias module:primitives.NetAddress
|
* @alias module:primitives.NetAddress
|
||||||
* @constructor
|
|
||||||
* @param {Object} options
|
|
||||||
* @param {Number?} options.time - Timestamp.
|
|
||||||
* @param {Number?} options.services - Service bits.
|
|
||||||
* @param {String?} options.host - IP address (IPv6 or IPv4).
|
|
||||||
* @param {Number?} options.port - Port.
|
|
||||||
* @property {Host} host
|
* @property {Host} host
|
||||||
* @property {Number} port
|
* @property {Number} port
|
||||||
* @property {Number} services
|
* @property {Number} services
|
||||||
* @property {Number} time
|
* @property {Number} time
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function NetAddress(options) {
|
class NetAddress {
|
||||||
if (!(this instanceof NetAddress))
|
/**
|
||||||
return new NetAddress(options);
|
* Create a network address.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {Number?} options.time - Timestamp.
|
||||||
|
* @param {Number?} options.services - Service bits.
|
||||||
|
* @param {String?} options.host - IP address (IPv6 or IPv4).
|
||||||
|
* @param {Number?} options.port - Port.
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
this.host = '0.0.0.0';
|
this.host = '0.0.0.0';
|
||||||
this.port = 0;
|
this.port = 0;
|
||||||
this.services = 0;
|
this.services = 0;
|
||||||
@ -44,25 +47,13 @@ function NetAddress(options) {
|
|||||||
this.fromOptions(options);
|
this.fromOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Default services for
|
|
||||||
* unknown outbound peers.
|
|
||||||
* @const {Number}
|
|
||||||
* @default
|
|
||||||
*/
|
|
||||||
|
|
||||||
NetAddress.DEFAULT_SERVICES = 0
|
|
||||||
| common.services.NETWORK
|
|
||||||
| common.services.WITNESS
|
|
||||||
| common.services.BLOOM;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
assert(typeof options.host === 'string');
|
assert(typeof options.host === 'string');
|
||||||
assert(typeof options.port === 'number');
|
assert(typeof options.port === 'number');
|
||||||
|
|
||||||
@ -83,7 +74,7 @@ NetAddress.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.hostname = IP.toHostname(this.host, this.port);
|
this.hostname = IP.toHostname(this.host, this.port);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate network address from options.
|
* Instantiate network address from options.
|
||||||
@ -91,9 +82,9 @@ NetAddress.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {NetAddress}
|
* @returns {NetAddress}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new NetAddress().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether required services are available.
|
* Test whether required services are available.
|
||||||
@ -101,95 +92,95 @@ NetAddress.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.hasServices = function hasServices(services) {
|
hasServices(services) {
|
||||||
return (this.services & services) === services;
|
return (this.services & services) === services;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is IPv4.
|
* Test whether the address is IPv4.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.isIPv4 = function isIPv4() {
|
static isIPv4() {
|
||||||
return IP.isIPv4(this.raw);
|
return IP.isIPv4(this.raw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the address is IPv6.
|
* Test whether the address is IPv6.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.isIPv6 = function isIPv6() {
|
static isIPv6() {
|
||||||
return IP.isIPv6(this.raw);
|
return IP.isIPv6(this.raw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the host is null.
|
* Test whether the host is null.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.isNull = function isNull() {
|
isNull() {
|
||||||
return IP.isNull(this.raw);
|
return IP.isNull(this.raw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the host is a local address.
|
* Test whether the host is a local address.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.isLocal = function isLocal() {
|
isLocal() {
|
||||||
return IP.isLocal(this.raw);
|
return IP.isLocal(this.raw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the host is valid.
|
* Test whether the host is valid.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.isValid = function isValid() {
|
isValid() {
|
||||||
return IP.isValid(this.raw);
|
return IP.isValid(this.raw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the host is routable.
|
* Test whether the host is routable.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.isRoutable = function isRoutable() {
|
isRoutable() {
|
||||||
return IP.isRoutable(this.raw);
|
return IP.isRoutable(this.raw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the host is an onion address.
|
* Test whether the host is an onion address.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.isOnion = function isOnion() {
|
isOnion() {
|
||||||
return IP.isOnion(this.raw);
|
return IP.isOnion(this.raw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare against another network address.
|
* Compare against another network address.
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.equal = function equal(addr) {
|
equal(addr) {
|
||||||
return this.compare(addr) === 0;
|
return this.compare(addr) === 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare against another network address.
|
* Compare against another network address.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.compare = function compare(addr) {
|
compare(addr) {
|
||||||
const cmp = this.raw.compare(addr.raw);
|
const cmp = this.raw.compare(addr.raw);
|
||||||
|
|
||||||
if (cmp !== 0)
|
if (cmp !== 0)
|
||||||
return cmp;
|
return cmp;
|
||||||
|
|
||||||
return this.port - addr.port;
|
return this.port - addr.port;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get reachable score to destination.
|
* Get reachable score to destination.
|
||||||
@ -197,41 +188,41 @@ NetAddress.prototype.compare = function compare(addr) {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.getReachability = function getReachability(dest) {
|
getReachability(dest) {
|
||||||
return IP.getReachability(this.raw, dest.raw);
|
return IP.getReachability(this.raw, dest.raw);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set null host.
|
* Set null host.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.setNull = function setNull() {
|
setNull() {
|
||||||
this.raw = IP.ZERO_IP;
|
this.raw = IP.ZERO_IP;
|
||||||
this.host = '0.0.0.0';
|
this.host = '0.0.0.0';
|
||||||
this.hostname = IP.toHostname(this.host, this.port);
|
this.hostname = IP.toHostname(this.host, this.port);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set host.
|
* Set host.
|
||||||
* @param {String} host
|
* @param {String} host
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.setHost = function setHost(host) {
|
setHost(host) {
|
||||||
this.raw = IP.toBuffer(host);
|
this.raw = IP.toBuffer(host);
|
||||||
this.host = IP.toString(this.raw);
|
this.host = IP.toString(this.raw);
|
||||||
this.hostname = IP.toHostname(this.host, this.port);
|
this.hostname = IP.toHostname(this.host, this.port);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set port.
|
* Set port.
|
||||||
* @param {Number} port
|
* @param {Number} port
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.setPort = function setPort(port) {
|
setPort(port) {
|
||||||
assert(port >= 0 && port <= 0xffff);
|
assert(port >= 0 && port <= 0xffff);
|
||||||
this.port = port;
|
this.port = port;
|
||||||
this.hostname = IP.toHostname(this.host, port);
|
this.hostname = IP.toHostname(this.host, port);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from host, port, and network.
|
* Inject properties from host, port, and network.
|
||||||
@ -241,7 +232,7 @@ NetAddress.prototype.setPort = function setPort(port) {
|
|||||||
* @param {(Network|NetworkType)?} network
|
* @param {(Network|NetworkType)?} network
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.fromHost = function fromHost(host, port, network) {
|
fromHost(host, port, network) {
|
||||||
network = Network.get(network);
|
network = Network.get(network);
|
||||||
|
|
||||||
assert(port >= 0 && port <= 0xffff);
|
assert(port >= 0 && port <= 0xffff);
|
||||||
@ -255,7 +246,7 @@ NetAddress.prototype.fromHost = function fromHost(host, port, network) {
|
|||||||
this.hostname = IP.toHostname(this.host, this.port);
|
this.hostname = IP.toHostname(this.host, this.port);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a network address
|
* Instantiate a network address
|
||||||
@ -266,9 +257,9 @@ NetAddress.prototype.fromHost = function fromHost(host, port, network) {
|
|||||||
* @returns {NetAddress}
|
* @returns {NetAddress}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.fromHost = function fromHost(host, port, network) {
|
static fromHost(host, port, network) {
|
||||||
return new NetAddress().fromHost(host, port, network);
|
return new this().fromHost(host, port, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from hostname and network.
|
* Inject properties from hostname and network.
|
||||||
@ -277,13 +268,13 @@ NetAddress.fromHost = function fromHost(host, port, network) {
|
|||||||
* @param {(Network|NetworkType)?} network
|
* @param {(Network|NetworkType)?} network
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.fromHostname = function fromHostname(hostname, network) {
|
fromHostname(hostname, network) {
|
||||||
network = Network.get(network);
|
network = Network.get(network);
|
||||||
|
|
||||||
const addr = IP.fromHostname(hostname, network.port);
|
const addr = IP.fromHostname(hostname, network.port);
|
||||||
|
|
||||||
return this.fromHost(addr.host, addr.port, network);
|
return this.fromHost(addr.host, addr.port, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a network address
|
* Instantiate a network address
|
||||||
@ -293,9 +284,9 @@ NetAddress.prototype.fromHostname = function fromHostname(hostname, network) {
|
|||||||
* @returns {NetAddress}
|
* @returns {NetAddress}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.fromHostname = function fromHostname(hostname, network) {
|
static fromHostname(hostname, network) {
|
||||||
return new NetAddress().fromHostname(hostname, network);
|
return new this().fromHostname(hostname, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from socket.
|
* Inject properties from socket.
|
||||||
@ -303,13 +294,13 @@ NetAddress.fromHostname = function fromHostname(hostname, network) {
|
|||||||
* @param {net.Socket} socket
|
* @param {net.Socket} socket
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.fromSocket = function fromSocket(socket, network) {
|
fromSocket(socket, network) {
|
||||||
const host = socket.remoteAddress;
|
const host = socket.remoteAddress;
|
||||||
const port = socket.remotePort;
|
const port = socket.remotePort;
|
||||||
assert(typeof host === 'string');
|
assert(typeof host === 'string');
|
||||||
assert(typeof port === 'number');
|
assert(typeof port === 'number');
|
||||||
return this.fromHost(IP.normalize(host), port, network);
|
return this.fromHost(IP.normalize(host), port, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a network address
|
* Instantiate a network address
|
||||||
@ -318,9 +309,9 @@ NetAddress.prototype.fromSocket = function fromSocket(socket, network) {
|
|||||||
* @returns {NetAddress}
|
* @returns {NetAddress}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.fromSocket = function fromSocket(hostname, network) {
|
static fromSocket(hostname, network) {
|
||||||
return new NetAddress().fromSocket(hostname, network);
|
return new this().fromSocket(hostname, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -329,7 +320,7 @@ NetAddress.fromSocket = function fromSocket(hostname, network) {
|
|||||||
* @param {Boolean?} full - Include timestamp.
|
* @param {Boolean?} full - Include timestamp.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.fromReader = function fromReader(br, full) {
|
fromReader(br, full) {
|
||||||
this.time = full ? br.readU32() : 0;
|
this.time = full ? br.readU32() : 0;
|
||||||
this.services = br.readU32();
|
this.services = br.readU32();
|
||||||
|
|
||||||
@ -343,7 +334,7 @@ NetAddress.prototype.fromReader = function fromReader(br, full) {
|
|||||||
this.hostname = IP.toHostname(this.host, this.port);
|
this.hostname = IP.toHostname(this.host, this.port);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -352,9 +343,9 @@ NetAddress.prototype.fromReader = function fromReader(br, full) {
|
|||||||
* @param {Boolean?} full - Include timestamp.
|
* @param {Boolean?} full - Include timestamp.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.fromRaw = function fromRaw(data, full) {
|
fromRaw(data, full) {
|
||||||
return this.fromReader(new BufferReader(data), full);
|
return this.fromReader(new BufferReader(data), full);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insantiate a network address from buffer reader.
|
* Insantiate a network address from buffer reader.
|
||||||
@ -363,9 +354,9 @@ NetAddress.prototype.fromRaw = function fromRaw(data, full) {
|
|||||||
* @returns {NetAddress}
|
* @returns {NetAddress}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.fromReader = function fromReader(br, full) {
|
static fromReader(br, full) {
|
||||||
return new NetAddress().fromReader(br, full);
|
return new this().fromReader(br, full);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insantiate a network address from serialized data.
|
* Insantiate a network address from serialized data.
|
||||||
@ -374,9 +365,9 @@ NetAddress.fromReader = function fromReader(br, full) {
|
|||||||
* @returns {NetAddress}
|
* @returns {NetAddress}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.fromRaw = function fromRaw(data, full) {
|
static fromRaw(data, full) {
|
||||||
return new NetAddress().fromRaw(data, full);
|
return new this().fromRaw(data, full);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write network address to a buffer writer.
|
* Write network address to a buffer writer.
|
||||||
@ -385,7 +376,7 @@ NetAddress.fromRaw = function fromRaw(data, full) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.toWriter = function toWriter(bw, full) {
|
toWriter(bw, full) {
|
||||||
if (full)
|
if (full)
|
||||||
bw.writeU32(this.time);
|
bw.writeU32(this.time);
|
||||||
|
|
||||||
@ -395,16 +386,16 @@ NetAddress.prototype.toWriter = function toWriter(bw, full) {
|
|||||||
bw.writeU16BE(this.port);
|
bw.writeU16BE(this.port);
|
||||||
|
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate serialization size of address.
|
* Calculate serialization size of address.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.getSize = function getSize(full) {
|
getSize(full) {
|
||||||
return 26 + (full ? 4 : 0);
|
return 26 + (full ? 4 : 0);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize network address.
|
* Serialize network address.
|
||||||
@ -412,24 +403,24 @@ NetAddress.prototype.getSize = function getSize(full) {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.toRaw = function toRaw(full) {
|
toRaw(full) {
|
||||||
const size = this.getSize(full);
|
const size = this.getSize(full);
|
||||||
return this.toWriter(new StaticWriter(size), full).render();
|
return this.toWriter(new StaticWriter(size), full).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert net address to json-friendly object.
|
* Convert net address to json-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return {
|
return {
|
||||||
host: this.host,
|
host: this.host,
|
||||||
port: this.port,
|
port: this.port,
|
||||||
services: this.services,
|
services: this.services,
|
||||||
time: this.time
|
time: this.time
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from json object.
|
* Inject properties from json object.
|
||||||
@ -438,7 +429,7 @@ NetAddress.prototype.toJSON = function toJSON() {
|
|||||||
* @returns {NetAddress}
|
* @returns {NetAddress}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert((json.port & 0xffff) === json.port);
|
assert((json.port & 0xffff) === json.port);
|
||||||
assert((json.services >>> 0) === json.services);
|
assert((json.services >>> 0) === json.services);
|
||||||
assert((json.time >>> 0) === json.time);
|
assert((json.time >>> 0) === json.time);
|
||||||
@ -449,7 +440,7 @@ NetAddress.prototype.fromJSON = function fromJSON(json) {
|
|||||||
this.time = json.time;
|
this.time = json.time;
|
||||||
this.hostname = IP.toHostname(this.host, this.port);
|
this.hostname = IP.toHostname(this.host, this.port);
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate net address from json object.
|
* Instantiate net address from json object.
|
||||||
@ -457,22 +448,35 @@ NetAddress.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {NetAddress}
|
* @returns {NetAddress}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new NetAddress().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the network address.
|
* Inspect the network address.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
NetAddress.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return '<NetAddress:'
|
return '<NetAddress:'
|
||||||
+ ` hostname=${this.hostname}`
|
+ ` hostname=${this.hostname}`
|
||||||
+ ` services=${this.services.toString(2)}`
|
+ ` services=${this.services.toString(2)}`
|
||||||
+ ` date=${util.date(this.time)}`
|
+ ` date=${util.date(this.time)}`
|
||||||
+ '>';
|
+ '>';
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default services for
|
||||||
|
* unknown outbound peers.
|
||||||
|
* @const {Number}
|
||||||
|
* @default
|
||||||
|
*/
|
||||||
|
|
||||||
|
NetAddress.DEFAULT_SERVICES = 0
|
||||||
|
| common.services.NETWORK
|
||||||
|
| common.services.WITNESS
|
||||||
|
| common.services.BLOOM;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -12,19 +12,22 @@ const BufferReader = require('bufio/lib/reader');
|
|||||||
const encoding = require('bufio/lib/encoding');
|
const encoding = require('bufio/lib/encoding');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Outpoint
|
||||||
* Represents a COutPoint.
|
* Represents a COutPoint.
|
||||||
* @alias module:primitives.Outpoint
|
* @alias module:primitives.Outpoint
|
||||||
* @constructor
|
|
||||||
* @param {Hash?} hash
|
|
||||||
* @param {Number?} index
|
|
||||||
* @property {Hash} hash
|
* @property {Hash} hash
|
||||||
* @property {Number} index
|
* @property {Number} index
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Outpoint(hash, index) {
|
class Outpoint {
|
||||||
if (!(this instanceof Outpoint))
|
/**
|
||||||
return new Outpoint(hash, index);
|
* Create an outpoint.
|
||||||
|
* @constructor
|
||||||
|
* @param {Hash?} hash
|
||||||
|
* @param {Number?} index
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(hash, index) {
|
||||||
this.hash = encoding.NULL_HASH;
|
this.hash = encoding.NULL_HASH;
|
||||||
this.index = 0xffffffff;
|
this.index = 0xffffffff;
|
||||||
|
|
||||||
@ -42,14 +45,14 @@ function Outpoint(hash, index) {
|
|||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
assert(options, 'Outpoint data is required.');
|
assert(options, 'Outpoint data is required.');
|
||||||
assert(typeof options.hash === 'string', 'Hash must be a string.');
|
assert(typeof options.hash === 'string', 'Hash must be a string.');
|
||||||
assert((options.index >>> 0) === options.index, 'Index must be a uint32.');
|
assert((options.index >>> 0) === options.index, 'Index must be a uint32.');
|
||||||
this.hash = options.hash;
|
this.hash = options.hash;
|
||||||
this.index = options.index;
|
this.index = options.index;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantate outpoint from options object.
|
* Instantate outpoint from options object.
|
||||||
@ -57,21 +60,21 @@ Outpoint.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Outpoint}
|
* @returns {Outpoint}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new Outpoint().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone the outpoint.
|
* Clone the outpoint.
|
||||||
* @returns {Outpoint}
|
* @returns {Outpoint}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.clone = function clone() {
|
clone() {
|
||||||
const outpoint = new Outpoint();
|
const outpoint = new this.constructor();
|
||||||
outpoint.hash = this.value;
|
outpoint.hash = this.value;
|
||||||
outpoint.index = this.index;
|
outpoint.index = this.index;
|
||||||
return outpoint;
|
return outpoint;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test equality against another outpoint.
|
* Test equality against another outpoint.
|
||||||
@ -79,11 +82,11 @@ Outpoint.prototype.clone = function clone() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.equals = function equals(prevout) {
|
equals(prevout) {
|
||||||
assert(Outpoint.isOutpoint(prevout));
|
assert(Outpoint.isOutpoint(prevout));
|
||||||
return this.hash === prevout.hash
|
return this.hash === prevout.hash
|
||||||
&& this.index === prevout.index;
|
&& this.index === prevout.index;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare against another outpoint (BIP69).
|
* Compare against another outpoint (BIP69).
|
||||||
@ -91,7 +94,7 @@ Outpoint.prototype.equals = function equals(prevout) {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.compare = function compare(prevout) {
|
compare(prevout) {
|
||||||
assert(Outpoint.isOutpoint(prevout));
|
assert(Outpoint.isOutpoint(prevout));
|
||||||
|
|
||||||
const cmp = strcmp(this.txid(), prevout.txid());
|
const cmp = strcmp(this.txid(), prevout.txid());
|
||||||
@ -100,7 +103,7 @@ Outpoint.prototype.compare = function compare(prevout) {
|
|||||||
return cmp;
|
return cmp;
|
||||||
|
|
||||||
return this.index - prevout.index;
|
return this.index - prevout.index;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the outpoint is null (hash of zeroes
|
* Test whether the outpoint is null (hash of zeroes
|
||||||
@ -108,27 +111,27 @@ Outpoint.prototype.compare = function compare(prevout) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.isNull = function isNull() {
|
isNull() {
|
||||||
return this.index === 0xffffffff && this.hash === encoding.NULL_HASH;
|
return this.index === 0xffffffff && this.hash === encoding.NULL_HASH;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get little-endian hash.
|
* Get little-endian hash.
|
||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.rhash = function rhash() {
|
rhash() {
|
||||||
return encoding.revHex(this.hash);
|
return encoding.revHex(this.hash);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get little-endian hash.
|
* Get little-endian hash.
|
||||||
* @returns {Hash}
|
* @returns {Hash}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.txid = function txid() {
|
txid() {
|
||||||
return this.rhash();
|
return this.rhash();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize outpoint to a key
|
* Serialize outpoint to a key
|
||||||
@ -136,9 +139,9 @@ Outpoint.prototype.txid = function txid() {
|
|||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.toKey = function toKey() {
|
toKey() {
|
||||||
return Outpoint.toKey(this.hash, this.index);
|
return Outpoint.toKey(this.hash, this.index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from hash table key.
|
* Inject properties from hash table key.
|
||||||
@ -147,12 +150,12 @@ Outpoint.prototype.toKey = function toKey() {
|
|||||||
* @returns {Outpoint}
|
* @returns {Outpoint}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.fromKey = function fromKey(key) {
|
fromKey(key) {
|
||||||
assert(key.length > 64);
|
assert(key.length > 64);
|
||||||
this.hash = key.slice(0, 64);
|
this.hash = key.slice(0, 64);
|
||||||
this.index = parseInt(key.slice(64), 10);
|
this.index = parseInt(key.slice(64), 10);
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate outpoint from hash table key.
|
* Instantiate outpoint from hash table key.
|
||||||
@ -160,38 +163,38 @@ Outpoint.prototype.fromKey = function fromKey(key) {
|
|||||||
* @returns {Outpoint}
|
* @returns {Outpoint}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.fromKey = function fromKey(key) {
|
static fromKey(key) {
|
||||||
return new Outpoint().fromKey(key);
|
return new this().fromKey(key);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write outpoint to a buffer writer.
|
* Write outpoint to a buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
bw.writeHash(this.hash);
|
bw.writeHash(this.hash);
|
||||||
bw.writeU32(this.index);
|
bw.writeU32(this.index);
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate size of outpoint.
|
* Calculate size of outpoint.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
return 36;
|
return 36;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize outpoint.
|
* Serialize outpoint.
|
||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
return this.toWriter(new StaticWriter(36)).render();
|
return this.toWriter(new StaticWriter(36)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -199,11 +202,11 @@ Outpoint.prototype.toRaw = function toRaw() {
|
|||||||
* @param {BufferReader} br
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
this.hash = br.readHash('hex');
|
this.hash = br.readHash('hex');
|
||||||
this.index = br.readU32();
|
this.index = br.readU32();
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -211,9 +214,9 @@ Outpoint.prototype.fromReader = function fromReader(br) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate outpoint from a buffer reader.
|
* Instantiate outpoint from a buffer reader.
|
||||||
@ -221,9 +224,9 @@ Outpoint.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Outpoint}
|
* @returns {Outpoint}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new Outpoint().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate outpoint from serialized data.
|
* Instantiate outpoint from serialized data.
|
||||||
@ -231,9 +234,9 @@ Outpoint.fromReader = function fromReader(br) {
|
|||||||
* @returns {Outpoint}
|
* @returns {Outpoint}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new Outpoint().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from json object.
|
* Inject properties from json object.
|
||||||
@ -241,14 +244,14 @@ Outpoint.fromRaw = function fromRaw(data) {
|
|||||||
* @params {Object} json
|
* @params {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert(json, 'Outpoint data is required.');
|
assert(json, 'Outpoint data is required.');
|
||||||
assert(typeof json.hash === 'string', 'Hash must be a string.');
|
assert(typeof json.hash === 'string', 'Hash must be a string.');
|
||||||
assert((json.index >>> 0) === json.index, 'Index must be a uint32.');
|
assert((json.index >>> 0) === json.index, 'Index must be a uint32.');
|
||||||
this.hash = encoding.revHex(json.hash);
|
this.hash = encoding.revHex(json.hash);
|
||||||
this.index = json.index;
|
this.index = json.index;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the outpoint to an object suitable
|
* Convert the outpoint to an object suitable
|
||||||
@ -258,12 +261,12 @@ Outpoint.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return {
|
return {
|
||||||
hash: encoding.revHex(this.hash),
|
hash: encoding.revHex(this.hash),
|
||||||
index: this.index
|
index: this.index
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate outpoint from json object.
|
* Instantiate outpoint from json object.
|
||||||
@ -271,9 +274,9 @@ Outpoint.prototype.toJSON = function toJSON() {
|
|||||||
* @returns {Outpoint}
|
* @returns {Outpoint}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new Outpoint().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from tx.
|
* Inject properties from tx.
|
||||||
@ -282,14 +285,14 @@ Outpoint.fromJSON = function fromJSON(json) {
|
|||||||
* @param {Number} index
|
* @param {Number} index
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.fromTX = function fromTX(tx, index) {
|
fromTX(tx, index) {
|
||||||
assert(tx);
|
assert(tx);
|
||||||
assert(typeof index === 'number');
|
assert(typeof index === 'number');
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
this.hash = tx.hash('hex');
|
this.hash = tx.hash('hex');
|
||||||
this.index = index;
|
this.index = index;
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate outpoint from tx.
|
* Instantiate outpoint from tx.
|
||||||
@ -298,9 +301,9 @@ Outpoint.prototype.fromTX = function fromTX(tx, index) {
|
|||||||
* @returns {Outpoint}
|
* @returns {Outpoint}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.fromTX = function fromTX(tx, index) {
|
static fromTX(tx, index) {
|
||||||
return new Outpoint().fromTX(tx, index);
|
return new this().fromTX(tx, index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize outpoint to a key
|
* Serialize outpoint to a key
|
||||||
@ -310,21 +313,21 @@ Outpoint.fromTX = function fromTX(tx, index) {
|
|||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.toKey = function toKey(hash, index) {
|
static toKey(hash, index) {
|
||||||
assert(typeof hash === 'string');
|
assert(typeof hash === 'string');
|
||||||
assert(hash.length === 64);
|
assert(hash.length === 64);
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
return hash + index;
|
return hash + index;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the outpoint to a user-friendly string.
|
* Convert the outpoint to a user-friendly string.
|
||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return `<Outpoint: ${this.rhash()}/${this.index}>`;
|
return `<Outpoint: ${this.rhash()}/${this.index}>`;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an object to see if it is an outpoint.
|
* Test an object to see if it is an outpoint.
|
||||||
@ -332,9 +335,10 @@ Outpoint.prototype.inspect = function inspect() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Outpoint.isOutpoint = function isOutpoint(obj) {
|
static isOutpoint(obj) {
|
||||||
return obj instanceof Outpoint;
|
return obj instanceof Outpoint;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers
|
* Helpers
|
||||||
|
|||||||
@ -20,16 +20,18 @@ const policy = require('../protocol/policy');
|
|||||||
/**
|
/**
|
||||||
* Represents a transaction output.
|
* Represents a transaction output.
|
||||||
* @alias module:primitives.Output
|
* @alias module:primitives.Output
|
||||||
* @constructor
|
* @property {Amount} value
|
||||||
* @param {NakedOutput} options
|
|
||||||
* @property {Amount} value - Value in satoshis.
|
|
||||||
* @property {Script} script
|
* @property {Script} script
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function Output(options) {
|
class Output {
|
||||||
if (!(this instanceof Output))
|
/**
|
||||||
return new Output(options);
|
* Create an output.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
this.value = 0;
|
this.value = 0;
|
||||||
this.script = new Script();
|
this.script = new Script();
|
||||||
|
|
||||||
@ -43,7 +45,7 @@ function Output(options) {
|
|||||||
* @param {NakedOutput} options
|
* @param {NakedOutput} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
assert(options, 'Output data is required.');
|
assert(options, 'Output data is required.');
|
||||||
|
|
||||||
if (options.value) {
|
if (options.value) {
|
||||||
@ -59,7 +61,7 @@ Output.prototype.fromOptions = function fromOptions(options) {
|
|||||||
this.script.fromAddress(options.address);
|
this.script.fromAddress(options.address);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate output from options object.
|
* Instantiate output from options object.
|
||||||
@ -67,9 +69,9 @@ Output.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Output}
|
* @returns {Output}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new Output().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from script/value pair.
|
* Inject properties from script/value pair.
|
||||||
@ -79,7 +81,7 @@ Output.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {Output}
|
* @returns {Output}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.fromScript = function fromScript(script, value) {
|
fromScript(script, value) {
|
||||||
if (typeof script === 'string')
|
if (typeof script === 'string')
|
||||||
script = Address.fromString(script);
|
script = Address.fromString(script);
|
||||||
|
|
||||||
@ -93,7 +95,7 @@ Output.prototype.fromScript = function fromScript(script, value) {
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate output from script/value pair.
|
* Instantiate output from script/value pair.
|
||||||
@ -102,21 +104,21 @@ Output.prototype.fromScript = function fromScript(script, value) {
|
|||||||
* @returns {Output}
|
* @returns {Output}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.fromScript = function fromScript(script, value) {
|
static fromScript(script, value) {
|
||||||
return new Output().fromScript(script, value);
|
return new this().fromScript(script, value);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clone the output.
|
* Clone the output.
|
||||||
* @returns {Output}
|
* @returns {Output}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.clone = function clone() {
|
clone() {
|
||||||
const output = new Output();
|
const output = new this.constructor();
|
||||||
output.value = this.value;
|
output.value = this.value;
|
||||||
output.script.inject(this.script);
|
output.script.inject(this.script);
|
||||||
return output;
|
return output;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test equality against another output.
|
* Test equality against another output.
|
||||||
@ -124,11 +126,11 @@ Output.prototype.clone = function clone() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.equals = function equals(output) {
|
equals(output) {
|
||||||
assert(Output.isOutput(output));
|
assert(Output.isOutput(output));
|
||||||
return this.value === output.value
|
return this.value === output.value
|
||||||
&& this.script.equals(output.script);
|
&& this.script.equals(output.script);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare against another output (BIP69).
|
* Compare against another output (BIP69).
|
||||||
@ -136,7 +138,7 @@ Output.prototype.equals = function equals(output) {
|
|||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.compare = function compare(output) {
|
compare(output) {
|
||||||
assert(Output.isOutput(output));
|
assert(Output.isOutput(output));
|
||||||
|
|
||||||
const cmp = this.value - output.value;
|
const cmp = this.value - output.value;
|
||||||
@ -145,25 +147,25 @@ Output.prototype.compare = function compare(output) {
|
|||||||
return cmp;
|
return cmp;
|
||||||
|
|
||||||
return this.script.compare(output.script);
|
return this.script.compare(output.script);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the script type as a string.
|
* Get the script type as a string.
|
||||||
* @returns {ScriptType} type
|
* @returns {ScriptType} type
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.getType = function getType() {
|
getType() {
|
||||||
return Script.typesByVal[this.script.getType()].toLowerCase();
|
return Script.typesByVal[this.script.getType()].toLowerCase();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the address.
|
* Get the address.
|
||||||
* @returns {Address} address
|
* @returns {Address} address
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.getAddress = function getAddress() {
|
getAddress() {
|
||||||
return this.script.getAddress();
|
return this.script.getAddress();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the address hash.
|
* Get the address hash.
|
||||||
@ -171,28 +173,28 @@ Output.prototype.getAddress = function getAddress() {
|
|||||||
* @returns {Hash} hash
|
* @returns {Hash} hash
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.getHash = function getHash(enc) {
|
getHash(enc) {
|
||||||
const addr = this.getAddress();
|
const addr = this.getAddress();
|
||||||
|
|
||||||
if (!addr)
|
if (!addr)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return addr.getHash(enc);
|
return addr.getHash(enc);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the input to a more user-friendly object.
|
* Convert the input to a more user-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return {
|
return {
|
||||||
type: this.getType(),
|
type: this.getType(),
|
||||||
value: Amount.btc(this.value),
|
value: Amount.btc(this.value),
|
||||||
script: this.script,
|
script: this.script,
|
||||||
address: this.getAddress()
|
address: this.getAddress()
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the output to an object suitable
|
* Convert the output to an object suitable
|
||||||
@ -200,9 +202,9 @@ Output.prototype.inspect = function inspect() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return this.getJSON();
|
return this.getJSON();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the output to an object suitable
|
* Convert the output to an object suitable
|
||||||
@ -211,7 +213,7 @@ Output.prototype.toJSON = function toJSON() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.getJSON = function getJSON(network) {
|
getJSON(network) {
|
||||||
let addr = this.getAddress();
|
let addr = this.getAddress();
|
||||||
|
|
||||||
network = Network.get(network);
|
network = Network.get(network);
|
||||||
@ -224,7 +226,7 @@ Output.prototype.getJSON = function getJSON(network) {
|
|||||||
script: this.script.toJSON(),
|
script: this.script.toJSON(),
|
||||||
address: addr
|
address: addr
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the dust threshold for this
|
* Calculate the dust threshold for this
|
||||||
@ -233,7 +235,7 @@ Output.prototype.getJSON = function getJSON(network) {
|
|||||||
* @returns {Amount}
|
* @returns {Amount}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.getDustThreshold = function getDustThreshold(rate) {
|
getDustThreshold(rate) {
|
||||||
const scale = consensus.WITNESS_SCALE_FACTOR;
|
const scale = consensus.WITNESS_SCALE_FACTOR;
|
||||||
|
|
||||||
if (this.script.isUnspendable())
|
if (this.script.isUnspendable())
|
||||||
@ -249,16 +251,16 @@ Output.prototype.getDustThreshold = function getDustThreshold(rate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 3 * policy.getMinFee(size, rate);
|
return 3 * policy.getMinFee(size, rate);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate size of serialized output.
|
* Calculate size of serialized output.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
return 8 + this.script.getVarSize();
|
return 8 + this.script.getVarSize();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether the output should be considered dust.
|
* Test whether the output should be considered dust.
|
||||||
@ -266,9 +268,9 @@ Output.prototype.getSize = function getSize() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.isDust = function isDust(rate) {
|
isDust(rate) {
|
||||||
return this.value < this.getDustThreshold(rate);
|
return this.value < this.getDustThreshold(rate);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from a JSON object.
|
* Inject properties from a JSON object.
|
||||||
@ -276,14 +278,14 @@ Output.prototype.isDust = function isDust(rate) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
assert(json, 'Output data is required.');
|
assert(json, 'Output data is required.');
|
||||||
assert(Number.isSafeInteger(json.value) && json.value >= 0,
|
assert(Number.isSafeInteger(json.value) && json.value >= 0,
|
||||||
'Value must be a uint64.');
|
'Value must be a uint64.');
|
||||||
this.value = json.value;
|
this.value = json.value;
|
||||||
this.script.fromJSON(json.script);
|
this.script.fromJSON(json.script);
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an Output from a jsonified output object.
|
* Instantiate an Output from a jsonified output object.
|
||||||
@ -291,20 +293,20 @@ Output.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {Output}
|
* @returns {Output}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new Output().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write the output to a buffer writer.
|
* Write the output to a buffer writer.
|
||||||
* @param {BufferWriter} bw
|
* @param {BufferWriter} bw
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.toWriter = function toWriter(bw) {
|
toWriter(bw) {
|
||||||
bw.writeI64(this.value);
|
bw.writeI64(this.value);
|
||||||
bw.writeVarBytes(this.script.toRaw());
|
bw.writeVarBytes(this.script.toRaw());
|
||||||
return bw;
|
return bw;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize the output.
|
* Serialize the output.
|
||||||
@ -312,10 +314,10 @@ Output.prototype.toWriter = function toWriter(bw) {
|
|||||||
* @returns {Buffer|String}
|
* @returns {Buffer|String}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
return this.toWriter(new StaticWriter(size)).render();
|
return this.toWriter(new StaticWriter(size)).render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from buffer reader.
|
* Inject properties from buffer reader.
|
||||||
@ -323,11 +325,11 @@ Output.prototype.toRaw = function toRaw() {
|
|||||||
* @param {BufferReader} br
|
* @param {BufferReader} br
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.fromReader = function fromReader(br) {
|
fromReader(br) {
|
||||||
this.value = br.readI64();
|
this.value = br.readI64();
|
||||||
this.script.fromRaw(br.readVarBytes());
|
this.script.fromRaw(br.readVarBytes());
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from serialized data.
|
* Inject properties from serialized data.
|
||||||
@ -335,9 +337,9 @@ Output.prototype.fromReader = function fromReader(br) {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
return this.fromReader(new BufferReader(data));
|
return this.fromReader(new BufferReader(data));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an output from a buffer reader.
|
* Instantiate an output from a buffer reader.
|
||||||
@ -345,9 +347,9 @@ Output.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {Output}
|
* @returns {Output}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.fromReader = function fromReader(br) {
|
static fromReader(br) {
|
||||||
return new Output().fromReader(br);
|
return new this().fromReader(br);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an output from a serialized Buffer.
|
* Instantiate an output from a serialized Buffer.
|
||||||
@ -356,11 +358,11 @@ Output.fromReader = function fromReader(br) {
|
|||||||
* @returns {Output}
|
* @returns {Output}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.fromRaw = function fromRaw(data, enc) {
|
static fromRaw(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new Output().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test an object to see if it is an Output.
|
* Test an object to see if it is an Output.
|
||||||
@ -368,9 +370,10 @@ Output.fromRaw = function fromRaw(data, enc) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Output.isOutput = function isOutput(obj) {
|
static isOutput(obj) {
|
||||||
return obj instanceof Output;
|
return obj instanceof Output;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -14,16 +14,19 @@ const BufferReader = require('bufio/lib/reader');
|
|||||||
const encoding = require('bufio/lib/encoding');
|
const encoding = require('bufio/lib/encoding');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* TXMeta
|
||||||
* An extended transaction object.
|
* An extended transaction object.
|
||||||
* @alias module:primitives.TXMeta
|
* @alias module:primitives.TXMeta
|
||||||
* @constructor
|
|
||||||
* @param {Object} options
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function TXMeta(options) {
|
class TXMeta {
|
||||||
if (!(this instanceof TXMeta))
|
/**
|
||||||
return new TXMeta(options);
|
* Create an extended transaction.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
|
constructor(options) {
|
||||||
this.tx = new TX();
|
this.tx = new TX();
|
||||||
this.mtime = util.now();
|
this.mtime = util.now();
|
||||||
this.height = -1;
|
this.height = -1;
|
||||||
@ -41,7 +44,7 @@ function TXMeta(options) {
|
|||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.fromOptions = function fromOptions(options) {
|
fromOptions(options) {
|
||||||
if (options.tx) {
|
if (options.tx) {
|
||||||
assert(options.tx instanceof TX);
|
assert(options.tx instanceof TX);
|
||||||
this.tx = options.tx;
|
this.tx = options.tx;
|
||||||
@ -73,7 +76,7 @@ TXMeta.prototype.fromOptions = function fromOptions(options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate TXMeta from options.
|
* Instantiate TXMeta from options.
|
||||||
@ -81,9 +84,9 @@ TXMeta.prototype.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {TXMeta}
|
* @returns {TXMeta}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new TXMeta().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from options object.
|
* Inject properties from options object.
|
||||||
@ -91,7 +94,7 @@ TXMeta.fromOptions = function fromOptions(options) {
|
|||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.fromTX = function fromTX(tx, entry, index) {
|
fromTX(tx, entry, index) {
|
||||||
this.tx = tx;
|
this.tx = tx;
|
||||||
if (entry) {
|
if (entry) {
|
||||||
this.height = entry.height;
|
this.height = entry.height;
|
||||||
@ -100,7 +103,7 @@ TXMeta.prototype.fromTX = function fromTX(tx, entry, index) {
|
|||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate TXMeta from options.
|
* Instantiate TXMeta from options.
|
||||||
@ -108,41 +111,41 @@ TXMeta.prototype.fromTX = function fromTX(tx, entry, index) {
|
|||||||
* @returns {TXMeta}
|
* @returns {TXMeta}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.fromTX = function fromTX(tx, entry, index) {
|
static fromTX(tx, entry, index) {
|
||||||
return new TXMeta().fromTX(tx, entry, index);
|
return new this().fromTX(tx, entry, index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the transaction.
|
* Inspect the transaction.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.inspect = function inspect() {
|
inspect() {
|
||||||
return this.format();
|
return this.format();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect the transaction.
|
* Inspect the transaction.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.format = function format(view) {
|
format(view) {
|
||||||
const data = this.tx.format(view, null, this.index);
|
const data = this.tx.format(view, null, this.index);
|
||||||
data.mtime = this.mtime;
|
data.mtime = this.mtime;
|
||||||
data.height = this.height;
|
data.height = this.height;
|
||||||
data.block = this.block ? encoding.revHex(this.block) : null;
|
data.block = this.block ? encoding.revHex(this.block) : null;
|
||||||
data.time = this.time;
|
data.time = this.time;
|
||||||
return data;
|
return data;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert transaction to JSON.
|
* Convert transaction to JSON.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.toJSON = function toJSON() {
|
toJSON() {
|
||||||
return this.getJSON();
|
return this.getJSON();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the transaction to an object suitable
|
* Convert the transaction to an object suitable
|
||||||
@ -152,7 +155,7 @@ TXMeta.prototype.toJSON = function toJSON() {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.getJSON = function getJSON(network, view, chainHeight) {
|
getJSON(network, view, chainHeight) {
|
||||||
const json = this.tx.getJSON(network, view, null, this.index);
|
const json = this.tx.getJSON(network, view, null, this.index);
|
||||||
json.mtime = this.mtime;
|
json.mtime = this.mtime;
|
||||||
json.height = this.height;
|
json.height = this.height;
|
||||||
@ -164,7 +167,7 @@ TXMeta.prototype.getJSON = function getJSON(network, view, chainHeight) {
|
|||||||
json.confirmations = chainHeight - this.height + 1;
|
json.confirmations = chainHeight - this.height + 1;
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from a json object.
|
* Inject properties from a json object.
|
||||||
@ -172,7 +175,7 @@ TXMeta.prototype.getJSON = function getJSON(network, view, chainHeight) {
|
|||||||
* @param {Object} json
|
* @param {Object} json
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.fromJSON = function fromJSON(json) {
|
fromJSON(json) {
|
||||||
this.tx.fromJSON(json);
|
this.tx.fromJSON(json);
|
||||||
|
|
||||||
assert((json.mtime >>> 0) === json.mtime);
|
assert((json.mtime >>> 0) === json.mtime);
|
||||||
@ -187,7 +190,7 @@ TXMeta.prototype.fromJSON = function fromJSON(json) {
|
|||||||
this.index = json.index;
|
this.index = json.index;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a transaction from a
|
* Instantiate a transaction from a
|
||||||
@ -196,16 +199,16 @@ TXMeta.prototype.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {TX}
|
* @returns {TX}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new TXMeta().fromJSON(JSON);
|
return new this().fromJSON(JSON);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate serialization size.
|
* Calculate serialization size.
|
||||||
* @returns {Number}
|
* @returns {Number}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.getSize = function getSize() {
|
getSize() {
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
size += this.tx.getSize();
|
size += this.tx.getSize();
|
||||||
@ -220,7 +223,7 @@ TXMeta.prototype.getSize = function getSize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize a transaction to "extended format".
|
* Serialize a transaction to "extended format".
|
||||||
@ -231,7 +234,7 @@ TXMeta.prototype.getSize = function getSize() {
|
|||||||
* @returns {Buffer}
|
* @returns {Buffer}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.toRaw = function toRaw() {
|
toRaw() {
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const bw = new StaticWriter(size);
|
const bw = new StaticWriter(size);
|
||||||
|
|
||||||
@ -250,7 +253,7 @@ TXMeta.prototype.toRaw = function toRaw() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return bw.render();
|
return bw.render();
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from "extended" serialization format.
|
* Inject properties from "extended" serialization format.
|
||||||
@ -258,7 +261,7 @@ TXMeta.prototype.toRaw = function toRaw() {
|
|||||||
* @param {Buffer} data
|
* @param {Buffer} data
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.prototype.fromRaw = function fromRaw(data) {
|
fromRaw(data) {
|
||||||
const br = new BufferReader(data);
|
const br = new BufferReader(data);
|
||||||
|
|
||||||
this.tx.fromReader(br);
|
this.tx.fromReader(br);
|
||||||
@ -275,7 +278,7 @@ TXMeta.prototype.fromRaw = function fromRaw(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a transaction from a Buffer
|
* Instantiate a transaction from a Buffer
|
||||||
@ -285,11 +288,11 @@ TXMeta.prototype.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {TX}
|
* @returns {TX}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.fromRaw = function fromRaw(data, enc) {
|
static fromRaw(data, enc) {
|
||||||
if (typeof data === 'string')
|
if (typeof data === 'string')
|
||||||
data = Buffer.from(data, enc);
|
data = Buffer.from(data, enc);
|
||||||
return new TXMeta().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an object is an TXMeta.
|
* Test whether an object is an TXMeta.
|
||||||
@ -297,9 +300,10 @@ TXMeta.fromRaw = function fromRaw(data, enc) {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TXMeta.isTXMeta = function isTXMeta(obj) {
|
static isTXMeta(obj) {
|
||||||
return obj instanceof TXMeta;
|
return obj instanceof TXMeta;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -12,17 +12,21 @@ const KeyRing = require('../primitives/keyring');
|
|||||||
const Path = require('./path');
|
const Path = require('./path');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Wallet Key
|
||||||
* Represents a key ring which amounts to an address.
|
* Represents a key ring which amounts to an address.
|
||||||
* @alias module:wallet.WalletKey
|
* @alias module:wallet.WalletKey
|
||||||
* @constructor
|
* @extends KeyRing
|
||||||
* @param {Object} options
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function WalletKey(options) {
|
class WalletKey extends KeyRing {
|
||||||
if (!(this instanceof WalletKey))
|
/**
|
||||||
return new WalletKey(options);
|
* Create a wallet key.
|
||||||
|
* @constructor
|
||||||
|
* @param {Object?} options
|
||||||
|
*/
|
||||||
|
|
||||||
KeyRing.call(this, options);
|
constructor(options) {
|
||||||
|
super(options);
|
||||||
|
|
||||||
this.keyType = Path.types.HD;
|
this.keyType = Path.types.HD;
|
||||||
|
|
||||||
@ -32,17 +36,15 @@ function WalletKey(options) {
|
|||||||
this.index = -1;
|
this.index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.setPrototypeOf(WalletKey.prototype, KeyRing.prototype);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate key ring from options.
|
* Instantiate key ring from options.
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromOptions = function fromOptions(options) {
|
static fromOptions(options) {
|
||||||
return new WalletKey().fromOptions(options);
|
return new this().fromOptions(options);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate wallet key from a private key.
|
* Instantiate wallet key from a private key.
|
||||||
@ -51,9 +53,9 @@ WalletKey.fromOptions = function fromOptions(options) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromPrivate = function fromPrivate(key, compressed) {
|
static fromPrivate(key, compressed) {
|
||||||
return new WalletKey().fromPrivate(key, compressed);
|
return new this().fromPrivate(key, compressed);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a wallet key.
|
* Generate a wallet key.
|
||||||
@ -61,9 +63,9 @@ WalletKey.fromPrivate = function fromPrivate(key, compressed) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.generate = function generate(compressed) {
|
static generate(compressed) {
|
||||||
return new WalletKey().generate(compressed);
|
return new this().generate(compressed);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate wallet key from a public key.
|
* Instantiate wallet key from a public key.
|
||||||
@ -71,9 +73,9 @@ WalletKey.generate = function generate(compressed) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromPublic = function fromPublic(key) {
|
static fromPublic(key) {
|
||||||
return new WalletKey().fromPublic(key);
|
return new this().fromPublic(key);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate wallet key from a public key.
|
* Instantiate wallet key from a public key.
|
||||||
@ -81,9 +83,9 @@ WalletKey.fromPublic = function fromPublic(key) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromKey = function fromKey(key, compressed) {
|
static fromKey(key, compressed) {
|
||||||
return new WalletKey().fromKey(key, compressed);
|
return new this().fromKey(key, compressed);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate wallet key from script.
|
* Instantiate wallet key from script.
|
||||||
@ -92,9 +94,9 @@ WalletKey.fromKey = function fromKey(key, compressed) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromScript = function fromScript(key, script, compressed) {
|
static fromScript(key, script, compressed) {
|
||||||
return new WalletKey().fromScript(key, script, compressed);
|
return new this().fromScript(key, script, compressed);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a wallet key from a serialized CBitcoinSecret.
|
* Instantiate a wallet key from a serialized CBitcoinSecret.
|
||||||
@ -103,16 +105,16 @@ WalletKey.fromScript = function fromScript(key, script, compressed) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromSecret = function fromSecret(data, network) {
|
static fromSecret(data, network) {
|
||||||
return new WalletKey().fromSecret(data, network);
|
return new this().fromSecret(data, network);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an WalletKey to a more json-friendly object.
|
* Convert an WalletKey to a more json-friendly object.
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.prototype.toJSON = function toJSON(network) {
|
toJSON(network) {
|
||||||
return {
|
return {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
account: this.account,
|
account: this.account,
|
||||||
@ -126,7 +128,7 @@ WalletKey.prototype.toJSON = function toJSON(network) {
|
|||||||
type: Address.typesByVal[this.getType()].toLowerCase(),
|
type: Address.typesByVal[this.getType()].toLowerCase(),
|
||||||
address: this.getAddress('string', network)
|
address: this.getAddress('string', network)
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate an WalletKey from a jsonified transaction object.
|
* Instantiate an WalletKey from a jsonified transaction object.
|
||||||
@ -134,9 +136,9 @@ WalletKey.prototype.toJSON = function toJSON(network) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromJSON = function fromJSON(json) {
|
static fromJSON(json) {
|
||||||
return new WalletKey().fromJSON(json);
|
return new this().fromJSON(json);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a wallet key from serialized data.
|
* Instantiate a wallet key from serialized data.
|
||||||
@ -144,9 +146,9 @@ WalletKey.fromJSON = function fromJSON(json) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromRaw = function fromRaw(data) {
|
static fromRaw(data) {
|
||||||
return new WalletKey().fromRaw(data);
|
return new this().fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from hd key.
|
* Inject properties from hd key.
|
||||||
@ -158,7 +160,7 @@ WalletKey.fromRaw = function fromRaw(data) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.prototype.fromHD = function fromHD(account, key, branch, index) {
|
fromHD(account, key, branch, index) {
|
||||||
this.keyType = Path.types.HD;
|
this.keyType = Path.types.HD;
|
||||||
this.name = account.name;
|
this.name = account.name;
|
||||||
this.account = account.accountIndex;
|
this.account = account.accountIndex;
|
||||||
@ -171,7 +173,7 @@ WalletKey.prototype.fromHD = function fromHD(account, key, branch, index) {
|
|||||||
return this.fromPrivate(key.privateKey);
|
return this.fromPrivate(key.privateKey);
|
||||||
|
|
||||||
return this.fromPublic(key.publicKey);
|
return this.fromPublic(key.publicKey);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a wallet key from hd key.
|
* Instantiate a wallet key from hd key.
|
||||||
@ -182,9 +184,9 @@ WalletKey.prototype.fromHD = function fromHD(account, key, branch, index) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromHD = function fromHD(account, key, branch, index) {
|
static fromHD(account, key, branch, index) {
|
||||||
return new WalletKey().fromHD(account, key, branch, index);
|
return new this().fromHD(account, key, branch, index);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from imported data.
|
* Inject properties from imported data.
|
||||||
@ -194,13 +196,13 @@ WalletKey.fromHD = function fromHD(account, key, branch, index) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.prototype.fromImport = function fromImport(account, data) {
|
fromImport(account, data) {
|
||||||
this.keyType = Path.types.KEY;
|
this.keyType = Path.types.KEY;
|
||||||
this.name = account.name;
|
this.name = account.name;
|
||||||
this.account = account.accountIndex;
|
this.account = account.accountIndex;
|
||||||
this.witness = account.witness;
|
this.witness = account.witness;
|
||||||
return this.fromRaw(data);
|
return this.fromRaw(data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a wallet key from imported data.
|
* Instantiate a wallet key from imported data.
|
||||||
@ -209,9 +211,9 @@ WalletKey.prototype.fromImport = function fromImport(account, data) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromImport = function fromImport(account, data) {
|
static fromImport(account, data) {
|
||||||
return new WalletKey().fromImport(account, data);
|
return new this().fromImport(account, data);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inject properties from key.
|
* Inject properties from key.
|
||||||
@ -221,13 +223,13 @@ WalletKey.fromImport = function fromImport(account, data) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.prototype.fromRing = function fromRing(account, ring) {
|
fromRing(account, ring) {
|
||||||
this.keyType = Path.types.KEY;
|
this.keyType = Path.types.KEY;
|
||||||
this.name = account.name;
|
this.name = account.name;
|
||||||
this.account = account.accountIndex;
|
this.account = account.accountIndex;
|
||||||
this.witness = account.witness;
|
this.witness = account.witness;
|
||||||
return this.fromOptions(ring);
|
return this.fromOptions(ring);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiate a wallet key from regular key.
|
* Instantiate a wallet key from regular key.
|
||||||
@ -236,16 +238,16 @@ WalletKey.prototype.fromRing = function fromRing(account, ring) {
|
|||||||
* @returns {WalletKey}
|
* @returns {WalletKey}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.fromRing = function fromRing(account, ring) {
|
static fromRing(account, ring) {
|
||||||
return new WalletKey().fromRing(account, ring);
|
return new this().fromRing(account, ring);
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert wallet key to a path.
|
* Convert wallet key to a path.
|
||||||
* @returns {Path}
|
* @returns {Path}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.prototype.toPath = function toPath() {
|
toPath() {
|
||||||
const path = new Path();
|
const path = new Path();
|
||||||
|
|
||||||
path.name = this.name;
|
path.name = this.name;
|
||||||
@ -268,7 +270,7 @@ WalletKey.prototype.toPath = function toPath() {
|
|||||||
path.hash = this.getHash('hex');
|
path.hash = this.getHash('hex');
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether an object is a WalletKey.
|
* Test whether an object is a WalletKey.
|
||||||
@ -276,9 +278,10 @@ WalletKey.prototype.toPath = function toPath() {
|
|||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
WalletKey.isWalletKey = function isWalletKey(obj) {
|
static isWalletKey(obj) {
|
||||||
return obj instanceof WalletKey;
|
return obj instanceof WalletKey;
|
||||||
};
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Expose
|
* Expose
|
||||||
|
|||||||
@ -168,7 +168,7 @@ MemWallet.prototype.getUndo = function getUndo(key) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
MemWallet.prototype.addCoin = function addCoin(coin) {
|
MemWallet.prototype.addCoin = function addCoin(coin) {
|
||||||
const op = Outpoint(coin.hash, coin.index);
|
const op = new Outpoint(coin.hash, coin.index);
|
||||||
const key = op.toKey();
|
const key = op.toKey();
|
||||||
|
|
||||||
this.filter.add(op.toRaw());
|
this.filter.add(op.toRaw());
|
||||||
@ -301,7 +301,7 @@ MemWallet.prototype.removeTX = function removeTX(tx, height) {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (let i = 0; i < tx.outputs.length; i++) {
|
for (let i = 0; i < tx.outputs.length; i++) {
|
||||||
const op = Outpoint(hash, i).toKey();
|
const op = new Outpoint(hash, i).toKey();
|
||||||
const coin = this.getCoin(op);
|
const coin = this.getCoin(op);
|
||||||
|
|
||||||
if (!coin)
|
if (!coin)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user