serialization: less polymorphism.

This commit is contained in:
Christopher Jeffrey 2016-12-03 18:02:10 -08:00
parent ba88ffab01
commit a95aba92fb
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
49 changed files with 1894 additions and 1422 deletions

View File

@ -95,8 +95,8 @@ Payment.fromRaw = function fromRaw(data, enc) {
return new Payment().fromRaw(data);
};
Payment.prototype.toRaw = function toRaw(writer) {
var bw = new ProtoWriter(writer);
Payment.prototype.toRaw = function toRaw() {
var bw = new ProtoWriter();
var i, tx, op, output;
if (this.merchantData)
@ -118,10 +118,7 @@ Payment.prototype.toRaw = function toRaw(writer) {
if (this.memo != null)
bw.writeFieldString(4, this.memo);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
module.exports = Payment;

View File

@ -54,18 +54,15 @@ PaymentACK.fromRaw = function fromRaw(data, enc) {
return new PaymentACK().fromRaw(data);
};
PaymentACK.prototype.toRaw = function toRaw(writer) {
var bw = new ProtoWriter(writer);
PaymentACK.prototype.toRaw = function toRaw() {
var bw = new ProtoWriter();
bw.writeFieldBytes(1, this.payment.toRaw());
if (this.memo != null)
bw.writeFieldString(2, this.memo);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
module.exports = PaymentACK;

View File

@ -147,8 +147,8 @@ PaymentDetails.fromRaw = function fromRaw(data, enc) {
return new PaymentDetails().fromRaw(data);
};
PaymentDetails.prototype.toRaw = function toRaw(writer) {
var bw = new ProtoWriter(writer);
PaymentDetails.prototype.toRaw = function toRaw() {
var bw = new ProtoWriter();
var i, op, output;
if (this.network != null)
@ -176,10 +176,7 @@ PaymentDetails.prototype.toRaw = function toRaw(writer) {
if (this.merchantData)
bw.writeFieldString(7, this.merchantData);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
module.exports = PaymentDetails;

View File

@ -83,8 +83,8 @@ PaymentRequest.fromRaw = function fromRaw(data, enc) {
return new PaymentRequest().fromRaw(data);
};
PaymentRequest.prototype.toRaw = function toRaw(writer) {
var bw = new ProtoWriter(writer);
PaymentRequest.prototype.toRaw = function toRaw() {
var bw = new ProtoWriter();
if (this.version !== -1)
bw.writeFieldU32(1, this.version);
@ -100,10 +100,7 @@ PaymentRequest.prototype.toRaw = function toRaw(writer) {
if (this.signature)
bw.writeFieldBytes(5, this.signature);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
PaymentRequest.prototype.getAlgorithm = function getAlgorithm() {

View File

@ -432,8 +432,8 @@ ChainEntry.fromBlock = function fromBlock(chain, block, prev) {
* @returns {Buffer}
*/
ChainEntry.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
ChainEntry.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeU32(this.version);
bw.writeHash(this.prevBlock);
@ -444,10 +444,7 @@ ChainEntry.prototype.toRaw = function toRaw(writer) {
bw.writeU32(this.height);
bw.writeBytes(this.chainwork.toArrayLike(Buffer, 'le', 32));
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -56,7 +56,7 @@ UndoCoins.prototype.toRaw = function toRaw() {
for (i = 0; i < this.items.length; i++) {
coin = this.items[i];
coin.toRaw(bw);
coin.toWriter(bw);
}
return bw.render();
@ -75,7 +75,7 @@ UndoCoins.prototype.fromRaw = function fromRaw(data) {
var i;
for (i = 0; i < count; i++)
this.items.push(UndoCoin.fromRaw(br));
this.items.push(UndoCoin.fromReader(br));
return this;
};
@ -187,12 +187,11 @@ UndoCoin.prototype.toOutput = function toOutput() {
};
/**
* Serialize the undo coin.
* @returns {Buffer}
* Write the undo coin to a buffer writer.
* @param {BufferWriter} bw
*/
UndoCoin.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
UndoCoin.prototype.toWriter = function toWriter(bw) {
var height = this.height;
assert(height !== 0);
@ -214,21 +213,26 @@ UndoCoin.prototype.toRaw = function toRaw(writer) {
compress.output(this.output, bw);
}
if (!writer)
bw = bw.render();
return bw;
};
/**
* Inject properties from serialized data.
* Serialize the undo coin.
* @returns {Buffer}
*/
UndoCoin.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
/**
* Inject properties from buffer reader.
* @private
* @param {Buffer} data
* @param {BufferReader} br
* @returns {UndoCoin}
*/
UndoCoin.prototype.fromRaw = function fromRaw(data) {
var br = new BufferReader(data);
UndoCoin.prototype.fromReader = function fromReader(br) {
var code = br.readVarint();
this.output = new Output();
@ -248,6 +252,27 @@ UndoCoin.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* @returns {UndoCoin}
*/
UndoCoin.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate undo coin from serialized data.
* @param {Buffer} data
* @returns {UndoCoin}
*/
UndoCoin.fromReader = function fromReader(br) {
return new UndoCoin().fromReader(br);
};
/**
* Instantiate undo coin from serialized data.
* @param {Buffer} data

View File

@ -414,12 +414,11 @@ Mnemonic.fromJSON = function fromJSON(json) {
};
/**
* Serialize mnemonic.
* @returns {Buffer}
* Write the mnemonic to a buffer writer.
* @params {BufferWriter} bw
*/
Mnemonic.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
Mnemonic.prototype.toWriter = function toWriter(bw) {
var lang = Mnemonic.languages.indexOf(this.language);
assert(lang !== -1);
@ -430,21 +429,25 @@ Mnemonic.prototype.toRaw = function toRaw(writer) {
bw.writeVarString(this.getPhrase(), 'utf8');
bw.writeVarString(this.passphrase, 'utf8');
if (!writer)
bw = bw.render();
return bw;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* Serialize mnemonic.
* @returns {Buffer}
*/
Mnemonic.prototype.fromRaw = function fromRaw(data) {
var br = new BufferReader(data);
Mnemonic.prototype.toRaw = function toRaw(writer) {
return this.toWriter(new BufferWriter()).render();
};
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
Mnemonic.prototype.fromReader = function fromReader(br) {
this.bits = br.readU16();
this.language = Mnemonic.languages[br.readU8()];
this.entropy = br.readBytes(this.bits / 8);
@ -459,6 +462,26 @@ Mnemonic.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
Mnemonic.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate mnemonic from buffer reader.
* @param {BufferReader} br
* @returns {Mnemonic}
*/
Mnemonic.fromReader = function fromReader(br) {
return new Mnemonic().fromReader(br);
};
/**
* Instantiate mnemonic from serialized data.
* @param {Buffer} data

View File

@ -623,8 +623,7 @@ HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) {
* @param {Buffer} raw
*/
HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
var br = new BufferReader(raw);
HDPrivateKey.prototype.fromReader = function fromReader(br) {
var i, version, type, prefix;
version = br.readU32BE();
@ -651,6 +650,16 @@ HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} raw
*/
HDPrivateKey.prototype.fromRaw = function fromRaw(raw) {
return this.fromReader(new BufferReader(raw));
};
/**
* Serialize key to a base58 string.
* @param {(Network|NetworkType)?} network
@ -662,14 +671,12 @@ HDPrivateKey.prototype.toBase58 = function toBase58(network) {
};
/**
* Serialize the key.
* Write the key to a buffer writer.
* @param {BufferWriter} bw
* @param {(Network|NetworkType)?} network
* @returns {Buffer}
*/
HDPrivateKey.prototype.toRaw = function toRaw(network, writer) {
var bw = new BufferWriter(writer);
HDPrivateKey.prototype.toWriter = function toWriter(bw, network) {
if (!network)
network = this.network;
@ -684,8 +691,35 @@ HDPrivateKey.prototype.toRaw = function toRaw(network, writer) {
bw.writeBytes(this.privateKey);
bw.writeChecksum();
if (!writer)
bw = bw.render();
return bw;
};
/**
* Serialize the key.
* @param {(Network|NetworkType)?} network
* @returns {Buffer}
*/
HDPrivateKey.prototype.toRaw = function toRaw(network) {
return this.toWriter(new BufferWriter(), network).render();
};
/**
* Write the key in "extended"
* format to a buffer writer.
* @param {BufferWriter} bw
* @param {(Network|NetworkType)?} network
*/
HDPrivateKey.prototype.toExtendedWriter = function toExtendedWriter(bw, network) {
this.toWriter(bw, network);
if (this.mnemonic) {
bw.writeU8(1);
this.mnemonic.toWriter(bw);
} else {
bw.writeU8(0);
}
return bw;
};
@ -697,22 +731,21 @@ HDPrivateKey.prototype.toRaw = function toRaw(network, writer) {
* @returns {Buffer}
*/
HDPrivateKey.prototype.toExtended = function toExtended(network, writer) {
var bw = new BufferWriter(writer);
HDPrivateKey.prototype.toExtended = function toExtended(network) {
return this.toExtendedWriter(new BufferWriter(), network).render();
};
this.toRaw(network, bw);
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
if (this.mnemonic) {
bw.writeU8(1);
this.mnemonic.toRaw(bw);
} else {
bw.writeU8(0);
}
if (!writer)
bw = bw.render();
return bw;
HDPrivateKey.prototype.fromExtendedReader = function fromExtendedReader(br) {
this.fromReader(br);
if (br.readU8() === 1)
this.mnemonic = Mnemonic.fromReader(br);
return this;
};
/**
@ -722,11 +755,17 @@ HDPrivateKey.prototype.toExtended = function toExtended(network, writer) {
*/
HDPrivateKey.prototype.fromExtended = function fromExtended(data) {
var br = new BufferReader(data);
this.fromRaw(br);
if (br.readU8() === 1)
this.mnemonic = Mnemonic.fromRaw(br);
return this;
return this.fromExtendedReader(new BufferReader(data));
};
/**
* Instantiate key from "extended" buffer reader.
* @param {BufferReader} br
* @returns {HDPrivateKey}
*/
HDPrivateKey.fromExtendedReader = function fromExtendedReader(br) {
return new HDPrivateKey().fromExtendedReader(br);
};
/**
@ -749,6 +788,16 @@ HDPrivateKey.fromBase58 = function fromBase58(xkey) {
return new HDPrivateKey().fromBase58(xkey);
};
/**
* Instantiate key from buffer reader.
* @param {BufferReader} br
* @returns {HDPrivateKey}
*/
HDPrivateKey.fromReader = function fromReader(br) {
return new HDPrivateKey().fromReader(br);
};
/**
* Instantiate key from serialized data.
* @param {Buffer} raw

View File

@ -485,8 +485,7 @@ HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) {
* @param {Buffer} raw
*/
HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
var br = new BufferReader(raw);
HDPublicKey.prototype.fromReader = function fromReader(br) {
var i, version, type, prefix;
version = br.readU32BE();
@ -511,6 +510,16 @@ HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} raw
*/
HDPublicKey.prototype.fromRaw = function fromRaw(raw) {
return this.fromReader(new BufferReader(raw));
};
/**
* Serialize key data to base58 extended key.
* @param {Network|String} network
@ -522,14 +531,12 @@ HDPublicKey.prototype.toBase58 = function toBase58(network) {
};
/**
* Serialize the key.
* Write the key to a buffer writer.
* @param {BufferWriter} bw
* @param {Network|NetworkType} network
* @returns {Buffer}
*/
HDPublicKey.prototype.toRaw = function toRaw(network, writer) {
var bw = new BufferWriter(writer);
HDPublicKey.prototype.toWriter = function toWriter(bw, network) {
if (!network)
network = this.network;
@ -543,12 +550,19 @@ HDPublicKey.prototype.toRaw = function toRaw(network, writer) {
bw.writeBytes(this.publicKey);
bw.writeChecksum();
if (!writer)
bw = bw.render();
return bw;
};
/**
* Serialize the key.
* @param {Network|NetworkType} network
* @returns {Buffer}
*/
HDPublicKey.prototype.toRaw = function toRaw(network) {
return this.toWriter(new BufferWriter(), network).render();
};
/**
* Instantiate an HD public key from a base58 string.
* @param {Base58String} xkey
@ -559,6 +573,16 @@ HDPublicKey.fromBase58 = function fromBase58(xkey) {
return new HDPublicKey().fromBase58(xkey);
};
/**
* Instantiate key from serialized data.
* @param {BufferReader} br
* @returns {HDPublicKey}
*/
HDPublicKey.fromReader = function fromReader(br) {
return new HDPublicKey().fromReader(br);
};
/**
* Instantiate key from serialized data.
* @param {Buffer} raw

View File

@ -2163,7 +2163,7 @@ RPC.prototype.signrawtransaction = co(function* signrawtransaction(args) {
txs = [];
while (br.left())
txs.push(MTX.fromRaw(br));
txs.push(MTX.fromReader(br));
merged = txs[0];

View File

@ -320,8 +320,8 @@ ConfirmStats.prototype.removeTX = function removeTX(entryHeight, bestHeight, buc
* @returns {Buffer}
*/
ConfirmStats.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
ConfirmStats.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i;
function writeArray(buckets) {
@ -342,10 +342,7 @@ ConfirmStats.prototype.toRaw = function toRaw(writer) {
for (i = 0; i < this.maxConfirms; i++)
writeArray(this.confAvg[i]);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -805,18 +802,15 @@ PolicyEstimator.prototype.estimatePriority = function estimatePriority(target, s
* @returns {Buffer}
*/
PolicyEstimator.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
PolicyEstimator.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeU32(this.network.magic);
bw.writeU32(this.bestHeight);
bw.writeVarBytes(this.feeStats.toRaw());
bw.writeVarBytes(this.priStats.toRaw());
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -116,8 +116,8 @@ CompactBlock.prototype.fromRaw = function fromRaw(data) {
index = br.readVarint();
assert(index <= 0xffff);
assert(index < this.totalTX);
tx = TX.fromRaw(br);
this.ptx.push([index, tx]);
tx = TX.fromReader(br);
this.ptx.push(new PrefilledTX(index, tx));
}
this.init();
@ -131,16 +131,27 @@ CompactBlock.fromRaw = function fromRaw(data, enc) {
return new CompactBlock().fromRaw(data);
};
CompactBlock.prototype.toRaw = function toRaw(writer) {
return this.frame(true, writer);
CompactBlock.prototype.toRaw = function toRaw() {
return this.frame(true);
};
CompactBlock.prototype.toNormal = function toNormal(writer) {
return this.frame(false, writer);
CompactBlock.prototype.toNormal = function toNormal() {
return this.frame(false);
};
CompactBlock.prototype.frame = function frame(witness, writer) {
var bw = BufferWriter(writer);
CompactBlock.prototype.toWriter = function toWriter(bw) {
return this.frameWriter(bw, true);
};
CompactBlock.prototype.toNormalWriter = function toNormalWriter(bw) {
return this.frameWriter(bw, false);
};
CompactBlock.prototype.frame = function frame(witness) {
return this.frameWriter(new BufferWriter(), witness).render();
};
CompactBlock.prototype.frameWriter = function frameWriter(bw, witness) {
var i, id, lo, hi, ptx;
bw.writeU32(this.version);
@ -167,16 +178,13 @@ CompactBlock.prototype.frame = function frame(witness, writer) {
for (i = 0; i < this.ptx.length; i++) {
ptx = this.ptx[i];
bw.writeVarint(ptx[0]);
bw.writeVarint(ptx.index);
if (witness)
ptx[1].toRaw(bw);
ptx.tx.toWriter(bw);
else
ptx[1].toNormal(bw);
ptx.tx.toNormalWriter(bw);
}
if (!writer)
bw = bw.render();
return bw;
};
@ -286,10 +294,10 @@ CompactBlock.prototype.init = function init() {
for (i = 0; i < this.ptx.length; i++) {
ptx = this.ptx[i];
assert(ptx);
last += ptx[0] + 1;
last += ptx.index + 1;
assert(last <= 0xffff);
assert(last <= this.ids.length + i);
this.available[last] = ptx[1];
this.available[last] = ptx.tx;
this.count++;
}
@ -364,7 +372,7 @@ CompactBlock.prototype.fromBlock = function fromBlock(block, witness, nonce) {
this.ids.push(id);
}
this.ptx.push([0, block.txs[0]]);
this.ptx.push(new PrefilledTX(0, block.txs[0]));
return this;
};
@ -455,8 +463,7 @@ TXRequest.fromCompact = function fromCompact(block) {
return new TXRequest().fromCompact(block);
};
TXRequest.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
TXRequest.prototype.fromReader = function fromReader(br) {
var i, count, index, offset;
this.hash = br.readHash('hex');
@ -482,12 +489,19 @@ TXRequest.prototype.fromRaw = function fromRaw(data) {
return this;
};
TXRequest.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
TXRequest.fromReader = function fromReader(br) {
return new TXRequest().fromReader(br);
};
TXRequest.fromRaw = function fromRaw(data) {
return new TXRequest().fromRaw(data);
};
TXRequest.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
TXRequest.prototype.toWriter = function toWriter(bw) {
var i, index;
bw.writeHash(this.hash);
@ -499,12 +513,13 @@ TXRequest.prototype.toRaw = function toRaw(writer) {
bw.writeVarint(index);
}
if (!writer)
bw = bw.render();
return bw;
};
TXRequest.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
/**
* Represents BlockTransactions (bip152): `blocktxn` packet.
* @see https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki
@ -535,8 +550,7 @@ TXResponse.fromOptions = function fromOptions(options) {
return new TXResponse().fromOptions(options);
};
TXResponse.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
TXResponse.prototype.fromReader = function fromReader(br) {
var i, count;
this.hash = br.readHash('hex');
@ -544,11 +558,19 @@ TXResponse.prototype.fromRaw = function fromRaw(data) {
count = br.readVarint();
for (i = 0; i < count; i++)
this.txs.push(TX.fromRaw(br));
this.txs.push(TX.fromReader(br));
return this;
};
TXResponse.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
TXResponse.fromReader = function fromReader(br) {
return new TXResponse().fromReader(br);
};
TXResponse.fromRaw = function fromRaw(data) {
return new TXResponse().fromRaw(data);
};
@ -572,16 +594,23 @@ TXResponse.fromBlock = function fromBlock(block, req) {
return new TXResponse().fromBlock(block, req);
};
TXResponse.prototype.toRaw = function toRaw(writer) {
return this.frame(true, writer);
TXResponse.prototype.toRaw = function toRaw() {
return this.frame(true);
};
TXResponse.prototype.toNormal = function toNormal(writer) {
return this.frame(false, writer);
TXResponse.prototype.toNormal = function toNormal() {
return this.frame(false);
};
TXResponse.prototype.frame = function frame(witness, writer) {
var bw = BufferWriter(writer);
TXResponse.prototype.toWriter = function toWriter(bw) {
return this.frameWriter(bw, true);
};
TXResponse.prototype.toNormalWriter = function toNormalWriter(bw) {
return this.frameWriter(bw, false);
};
TXResponse.prototype.frameWriter = function frameWriter(bw, witness) {
var i, tx;
bw.writeHash(this.hash);
@ -591,17 +620,27 @@ TXResponse.prototype.frame = function frame(witness, writer) {
for (i = 0; i < this.txs.length; i++) {
tx = this.txs[i];
if (witness)
tx.toRaw(bw);
tx.toWriter(bw);
else
tx.toNormal(bw);
tx.toNormalWriter(bw);
}
if (!writer)
bw = bw.render();
return bw;
};
TXResponse.prototype.frame = function frame(witness) {
return this.frameWriter(new BufferWriter(), witness).render();
};
/*
* Helpers
*/
function PrefilledTX(index, tx) {
this.index = index;
this.tx = tx;
}
/*
* Expose
*/

View File

@ -186,23 +186,20 @@ VersionPacket.fromOptions = function fromOptions(options) {
* @returns {Buffer}
*/
VersionPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
VersionPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.write32(this.version);
bw.writeU64(this.services);
bw.write64(this.ts);
this.recv.toRaw(false, bw);
this.from.toRaw(false, bw);
this.recv.toWriter(bw, false);
this.from.toWriter(bw, false);
bw.writeBytes(this.nonce);
bw.writeVarString(this.agent, 'ascii');
bw.write32(this.height);
bw.writeU8(this.relay ? 1 : 0);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -272,10 +269,10 @@ VersionPacket.prototype.fromRaw = function fromRaw(data) {
this.version = br.read32();
this.services = br.readU53();
this.ts = br.read53();
this.recv.fromRaw(br, false);
this.recv.fromReader(br, false);
if (br.left() > 0) {
this.from.fromRaw(br, false);
this.from.fromReader(br, false);
this.nonce = br.readBytes(8);
}
@ -332,8 +329,8 @@ VerackPacket.prototype.type = exports.types.VERACK;
* @returns {Buffer}
*/
VerackPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
VerackPacket.prototype.toRaw = function toRaw() {
return DUMMY;
};
/**
@ -386,16 +383,13 @@ PingPacket.prototype.type = exports.types.PING;
* @returns {Buffer}
*/
PingPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
PingPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
if (this.nonce)
bw.writeBytes(this.nonce);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -451,15 +445,10 @@ PongPacket.prototype.type = exports.types.PONG;
* @returns {Buffer}
*/
PongPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
PongPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeBytes(this.nonce);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -650,20 +639,24 @@ AlertPacket.prototype.verify = function verify(key) {
};
/**
* Serialize the alert packet (includes payload _and_ signature).
* Write the alert packet to a buffer writer.
* @param {BufferWriter} bw
*/
AlertPacket.prototype.toWriter = function toWriter(bw) {
bw.writeVarBytes(this.toPayload());
bw.writeVarBytes(this.signature);
return bw;
};
/**
* Serialize the alert packet (includes
* payload _and_ signature).
* @returns {Buffer}
*/
AlertPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
bw.writeVarBytes(this.toPayload());
bw.writeVarBytes(this.signature);
if (!writer)
bw = bw.render();
return bw;
AlertPacket.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
/**
@ -672,8 +665,8 @@ AlertPacket.prototype.toRaw = function toRaw(writer) {
* @returns {Buffer}
*/
AlertPacket.prototype.framePayload = function framePayload(writer) {
var bw = BufferWriter(writer);
AlertPacket.prototype.framePayload = function framePayload() {
var bw = new BufferWriter();
var i;
bw.write32(this.version);
@ -698,26 +691,22 @@ AlertPacket.prototype.framePayload = function framePayload(writer) {
bw.writeVarString(this.statusBar, 'ascii');
bw.writeVarString(this.reserved, 'ascii');
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
* Inject properties from serialized data.
* Inject properties from buffer reader.
* @private
* @param {Buffer} data
* @param {BufferReader} br
*/
AlertPacket.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
AlertPacket.prototype.fromReader = function fromReader(br) {
var i, count;
this._payload = br.readVarBytes();
this.signature = br.readVarBytes();
br = BufferReader(this._payload);
br = new BufferReader(this._payload);
this.version = br.read32();
this.relayUntil = br.read53();
@ -744,6 +733,26 @@ AlertPacket.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
AlertPacket.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate alert packet from buffer reader.
* @param {BufferReader} br
* @returns {AlertPacket}
*/
AlertPacket.fromReader = function fromReader(br) {
return new AlertPacket().fromReader(br);
};
/**
* Instantiate alert packet from serialized data.
* @param {Buffer} data
@ -780,8 +789,8 @@ GetAddrPacket.prototype.type = exports.types.GETADDR;
* @returns {Buffer}
*/
GetAddrPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
GetAddrPacket.prototype.toRaw = function toRaw() {
return DUMMY;
};
/**
@ -834,19 +843,16 @@ AddrPacket.prototype.type = exports.types.ADDR;
* @returns {Buffer}
*/
AddrPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
AddrPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i;
bw.writeVarint(this.items.length);
for (i = 0; i < this.items.length; i++)
this.items[i].toRaw(true, bw);
this.items[i].toWriter(bw, true);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -862,7 +868,7 @@ AddrPacket.prototype.fromRaw = function fromRaw(data) {
count = br.readVarint();
for (i = 0; i < count; i++)
this.items.push(NetworkAddress.fromRaw(br, true));
this.items.push(NetworkAddress.fromReader(br, true));
return this;
};
@ -907,19 +913,16 @@ InvPacket.prototype.type = exports.types.INV;
* @returns {Buffer}
*/
InvPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
InvPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i;
bw.writeVarint(this.items.length);
for (i = 0; i < this.items.length; i++)
this.items[i].toRaw(bw);
this.items[i].toWriter(bw);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -929,13 +932,13 @@ InvPacket.prototype.toRaw = function toRaw(writer) {
*/
InvPacket.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
var br = new BufferReader(data);
var i, count;
count = br.readVarint();
for (i = 0; i < count; i++)
this.items.push(InvItem.fromRaw(br));
this.items.push(InvItem.fromReader(br));
return this;
};
@ -1050,8 +1053,8 @@ GetBlocksPacket.prototype.type = exports.types.GETBLOCKS;
* @returns {Buffer}
*/
GetBlocksPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
GetBlocksPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i;
bw.writeU32(this.version);
@ -1062,10 +1065,7 @@ GetBlocksPacket.prototype.toRaw = function toRaw(writer) {
bw.writeHash(this.stop || constants.ZERO_HASH);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -1167,19 +1167,16 @@ HeadersPacket.prototype.type = exports.types.HEADERS;
* @returns {Buffer}
*/
HeadersPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
HeadersPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i;
bw.writeVarint(this.items.length);
for (i = 0; i < this.items.length; i++)
this.items[i].toRaw(bw);
this.items[i].toWriter(bw);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -1195,7 +1192,7 @@ HeadersPacket.prototype.fromRaw = function fromRaw(data) {
count = br.readVarint();
for (i = 0; i < count; i++)
this.items.push(Headers.fromRaw(br));
this.items.push(Headers.fromReader(br));
return this;
};
@ -1236,8 +1233,8 @@ SendHeadersPacket.prototype.type = exports.types.SENDHEADERS;
* @returns {Buffer}
*/
SendHeadersPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
SendHeadersPacket.prototype.toRaw = function toRaw() {
return DUMMY;
};
/**
@ -1293,10 +1290,10 @@ BlockPacket.prototype.type = exports.types.BLOCK;
* @returns {Buffer}
*/
BlockPacket.prototype.toRaw = function toRaw(writer) {
BlockPacket.prototype.toRaw = function toRaw() {
if (this.witness)
return this.block.toRaw(writer);
return this.block.toNormal(writer);
return this.block.toRaw();
return this.block.toNormal();
};
/**
@ -1353,10 +1350,10 @@ TXPacket.prototype.type = exports.types.TX;
* @returns {Buffer}
*/
TXPacket.prototype.toRaw = function toRaw(writer) {
TXPacket.prototype.toRaw = function toRaw() {
if (this.witness)
return this.tx.toRaw(writer);
return this.tx.toNormal(writer);
return this.tx.toRaw();
return this.tx.toNormal();
};
/**
@ -1460,8 +1457,8 @@ RejectPacket.fromOptions = function fromOptions(options) {
* @returns {Buffer}
*/
RejectPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
RejectPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
assert(this.message.length <= 12);
assert(this.reason.length <= 111);
@ -1473,10 +1470,7 @@ RejectPacket.prototype.toRaw = function toRaw(writer) {
if (this.data)
bw.writeHash(this.data);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -1603,8 +1597,8 @@ MempoolPacket.prototype.type = exports.types.MEMPOOL;
* @returns {Buffer}
*/
MempoolPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
MempoolPacket.prototype.toRaw = function toRaw() {
return DUMMY;
};
/**
@ -1656,8 +1650,8 @@ FilterLoadPacket.prototype.type = exports.types.FILTERLOAD;
* @returns {Buffer}
*/
FilterLoadPacket.prototype.toRaw = function toRaw(writer) {
return this.filter.toRaw(writer);
FilterLoadPacket.prototype.toRaw = function toRaw() {
return this.filter.toRaw();
};
/**
@ -1726,15 +1720,10 @@ FilterAddPacket.prototype.type = exports.types.FILTERADD;
* @returns {Buffer}
*/
FilterAddPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
FilterAddPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeVarBytes(this.data);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -1785,8 +1774,8 @@ FilterClearPacket.prototype.type = exports.types.FILTERCLEAR;
* @returns {Buffer}
*/
FilterClearPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
FilterClearPacket.prototype.toRaw = function toRaw() {
return DUMMY;
};
/**
@ -1839,8 +1828,8 @@ MerkleBlockPacket.prototype.type = exports.types.MERKLEBLOCK;
* @returns {Buffer}
*/
MerkleBlockPacket.prototype.toRaw = function toRaw(writer) {
return this.block.toRaw(writer);
MerkleBlockPacket.prototype.toRaw = function toRaw() {
return this.block.toRaw();
};
/**
@ -1897,20 +1886,17 @@ GetUTXOsPacket.prototype.type = exports.types.GETUTXOS;
* @returns {Buffer}
*/
GetUTXOsPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
GetUTXOsPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i;
bw.writeU8(this.mempool ? 1 : 0);
bw.writeVarint(this.prevout.length);
for (i = 0; i < this.prevout.length; i++)
this.prevout[i].toRaw(bw);
this.prevout[i].toWriter(bw);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -1928,7 +1914,7 @@ GetUTXOsPacket.prototype.fromRaw = function fromRaw(data) {
count = br.readVarint();
for (i = 0; i < count; i++)
this.prevout.push(Outpoint.fromRaw(br));
this.prevout.push(Outpoint.fromReader(br));
return this;
};
@ -2023,8 +2009,8 @@ UTXOsPacket.fromOptions = function fromOptions(options) {
* @returns {Buffer}
*/
UTXOsPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
UTXOsPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var map = new Buffer((this.hits.length + 7) / 8 | 0);
var i, bit, oct, coin, height;
@ -2052,10 +2038,7 @@ UTXOsPacket.prototype.toRaw = function toRaw(writer) {
bw.writeVarBytes(coin.script.toRaw());
}
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2089,7 +2072,7 @@ UTXOsPacket.prototype.fromRaw = function fromRaw(data) {
if (height === 0x7fffffff)
height = -1;
output = Output.fromRaw(br);
output = Output.fromReader(br);
coin.version = version;
coin.height = height;
@ -2138,8 +2121,8 @@ HaveWitnessPacket.prototype.type = exports.types.HAVEWITNESS;
* @returns {Buffer}
*/
HaveWitnessPacket.prototype.toRaw = function toRaw(writer) {
return writer || DUMMY;
HaveWitnessPacket.prototype.toRaw = function toRaw() {
return DUMMY;
};
/**
@ -2192,15 +2175,10 @@ FeeFilterPacket.prototype.type = exports.types.FEEFILTER;
* @returns {Buffer}
*/
FeeFilterPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
FeeFilterPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.write64(this.rate);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2258,16 +2236,11 @@ SendCmpctPacket.prototype.type = exports.types.SENDCMPCT;
* @returns {Buffer}
*/
SendCmpctPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
SendCmpctPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeU8(this.mode);
bw.writeU64(this.version);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2326,10 +2299,10 @@ CmpctBlockPacket.prototype.type = exports.types.CMPCTBLOCK;
* @returns {Buffer}
*/
CmpctBlockPacket.prototype.toRaw = function toRaw(writer) {
CmpctBlockPacket.prototype.toRaw = function toRaw() {
if (this.witness)
return this.block.toRaw(writer);
return this.block.toNormal(writer);
return this.block.toRaw();
return this.block.toNormal();
};
/**
@ -2383,8 +2356,8 @@ GetBlockTxnPacket.prototype.type = exports.types.GETBLOCKTXN;
* @returns {Buffer}
*/
GetBlockTxnPacket.prototype.toRaw = function toRaw(writer) {
return this.request.toRaw(writer);
GetBlockTxnPacket.prototype.toRaw = function toRaw() {
return this.request.toRaw();
};
/**
@ -2441,10 +2414,10 @@ BlockTxnPacket.prototype.type = exports.types.BLOCKTXN;
* @returns {Buffer}
*/
BlockTxnPacket.prototype.toRaw = function toRaw(writer) {
BlockTxnPacket.prototype.toRaw = function toRaw() {
if (this.witness)
return this.response.toRaw(writer);
return this.response.toNormal(writer);
return this.response.toRaw();
return this.response.toNormal();
};
/**
@ -2501,16 +2474,11 @@ EncinitPacket.prototype.type = exports.types.ENCINIT;
* @returns {Buffer}
*/
EncinitPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
EncinitPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeBytes(this.publicKey);
bw.writeU8(this.cipher);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2566,15 +2534,10 @@ EncackPacket.prototype.type = exports.types.ENCACK;
* @returns {Buffer}
*/
EncackPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
EncackPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeBytes(this.publicKey);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2629,15 +2592,10 @@ AuthChallengePacket.prototype.type = exports.types.AUTHCHALLENGE;
* @returns {Buffer}
*/
AuthChallengePacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
AuthChallengePacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeBytes(this.hash);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2692,15 +2650,10 @@ AuthReplyPacket.prototype.type = exports.types.AUTHREPLY;
* @returns {Buffer}
*/
AuthReplyPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
AuthReplyPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeBytes(this.signature);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2755,15 +2708,10 @@ AuthProposePacket.prototype.type = exports.types.AUTHPROPOSE;
* @returns {Buffer}
*/
AuthProposePacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
AuthProposePacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeBytes(this.hash);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2820,15 +2768,10 @@ UnknownPacket.prototype.type = exports.types.UNKNOWN;
* @returns {Buffer}
*/
UnknownPacket.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
UnknownPacket.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeBytes(this.data);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -52,6 +52,7 @@ function AbstractBlock(options) {
this.txs = null;
this.mutable = false;
this.memory = false;
this._valid = null;
this._validHeaders = null;
@ -165,20 +166,15 @@ AbstractBlock.prototype.hash = function hash(enc) {
* @returns {Buffer}
*/
AbstractBlock.prototype.abbr = function abbr(writer) {
var bw = BufferWriter(writer);
AbstractBlock.prototype.abbr = function abbr() {
var bw = new BufferWriter();
bw.writeU32(this.version);
bw.writeHash(this.prevBlock);
bw.writeHash(this.merkleRoot);
bw.writeU32(this.ts);
bw.writeU32(this.bits);
bw.writeU32(this.nonce);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -176,11 +176,9 @@ Address.prototype.inspect = function inspect() {
*/
Address.prototype.fromRaw = function fromRaw(data) {
var i, br, prefix, network, type, version, hash;
var br = new BufferReader(data, true);
var i, prefix, network, type, version, hash;
assert(Buffer.isBuffer(data));
br = new BufferReader(data, true);
prefix = br.readU8();
for (i = 0; i < networks.types.length; i++) {

View File

@ -43,7 +43,6 @@ function Block(options) {
this._raw = null;
this._size = -1;
this._witnessSize = -1;
this._lastWitnessSize = 0;
if (options)
this.fromOptions(options);
@ -81,13 +80,8 @@ Block.fromOptions = function fromOptions(options) {
* @returns {Buffer}
*/
Block.prototype.toRaw = function toRaw(writer) {
var raw = this.getRaw();
if (writer) {
writer.writeBytes(raw);
return writer;
}
return raw;
Block.prototype.toRaw = function toRaw() {
return this.getRaw().data;
};
/**
@ -95,51 +89,82 @@ Block.prototype.toRaw = function toRaw(writer) {
* @returns {Buffer}
*/
Block.prototype.toNormal = function toNormal(writer) {
var raw;
if (!this.hasWitness()) {
raw = this.getRaw();
if (writer) {
writer.writeBytes(raw);
return writer;
}
return raw;
}
return this.frameNormal(writer);
Block.prototype.toNormal = function toNormal() {
if (this.hasWitness())
return this.frameNormal().data;
return this.toRaw();
};
/**
* Serialize the block. Include witnesses if present.
* @returns {Buffer}
* @param {BufferWriter} bw
*/
Block.prototype.toWitness = function toWitness(writer) {
return this.toRaw(writer);
Block.prototype.toWriter = function toWriter(bw) {
this.writeRaw(bw);
return bw;
};
/**
* Serialize the block, do not include witnesses.
* @param {BufferWriter} bw
*/
Block.prototype.toNormalWriter = function toNormalWriter(bw) {
if (this.hasWitness()) {
this.frameNormalWriter(bw);
return bw;
}
return this.toWriter(bw);
};
/**
* Get the raw block serialization.
* Include witnesses if present.
* @returns {Buffer}
* @private
* @returns {RawBlock}
*/
Block.prototype.getRaw = function getRaw() {
var raw;
if (this.mutable) {
assert(!this._raw);
return this.frameNormal();
}
if (this._raw) {
assert(this._size > 0);
assert(this._witnessSize >= 0);
this._lastWitnessSize = this._witnessSize;
return this._raw;
raw = new RawBlock(this._size, this._witnessSize);
raw.data = this._raw;
return raw;
}
raw = this.frameWitness();
if (!this.mutable) {
this._size = raw.length;
this._witnessSize = this._lastWitnessSize;
this._raw = raw;
}
this._raw = raw.data;
this._size = raw.total;
this._witnessSize = raw.witness;
return raw;
};
/**
* Write the raw block serialization
* to a buffer writer. Include the
* witnesses if present.
* @returns {RawBlock}
*/
Block.prototype.writeRaw = function writeRaw(bw) {
var raw;
if (this.mutable)
return this.frameWitnessWriter(bw);
raw = this.getRaw();
bw.writeBytes(raw.data);
return raw;
};
@ -150,31 +175,9 @@ Block.prototype.getRaw = function getRaw() {
*/
Block.prototype.getSizes = function getSizes() {
var sizes = new BlockSizes();
var writer;
if (this._size !== -1) {
sizes.total = this._size;
sizes.witness = this._witnessSize;
return sizes;
}
if (!this.mutable) {
assert(!this._raw);
this.getRaw();
sizes.total = this._size;
sizes.witness = this._witnessSize;
return sizes;
}
writer = new BufferWriter();
this.toRaw(writer);
sizes.total = writer.written;
sizes.witness = this._lastWitnessSize;
return sizes;
if (this.mutable)
return this.writeRaw(new BufferWriter());
return this.getRaw();
};
/**
@ -224,13 +227,14 @@ Block.prototype.getBaseSize = function getBaseSize() {
*/
Block.prototype.hasWitness = function hasWitness() {
var i;
var i, tx;
if (this._witnessSize !== -1)
return this._witnessSize !== 0;
for (i = 0; i < this.txs.length; i++) {
if (this.txs[i].hasWitness())
tx = this.txs[i];
if (tx.hasWitness())
return true;
}
@ -239,7 +243,7 @@ Block.prototype.hasWitness = function hasWitness() {
/**
* Add a transaction to the block's tx vector.
* @param {TX|NakedTX} tx
* @param {TX} tx
* @returns {TX}
*/
@ -443,7 +447,7 @@ Block.prototype._verify = function _verify(ret) {
if (!this.verifyHeaders(ret))
return false;
// Check merkle root
// Check merkle root.
merkle = this.createMerkleRoot('hex');
// If the merkle is mutated,
@ -460,6 +464,7 @@ Block.prototype._verify = function _verify(ret) {
return false;
}
// Check base size.
if (this.txs.length === 0
|| this.txs.length > constants.block.MAX_SIZE
|| this.getBaseSize() > constants.block.MAX_SIZE) {
@ -468,29 +473,29 @@ Block.prototype._verify = function _verify(ret) {
return false;
}
// First TX must be a coinbase
// First TX must be a coinbase.
if (this.txs.length === 0 || !this.txs[0].isCoinbase()) {
ret.reason = 'bad-cb-missing';
ret.score = 100;
return false;
}
// Test all txs
// Test all transactions.
for (i = 0; i < this.txs.length; i++) {
tx = this.txs[i];
// The rest of the txs must not be coinbases
// The rest of the txs must not be coinbases.
if (i > 0 && tx.isCoinbase()) {
ret.reason = 'bad-cb-multiple';
ret.score = 100;
return false;
}
// Sanity checks
// Sanity checks.
if (!tx.isSane(ret))
return false;
// Count legacy sigops (do not count scripthash or witness)
// Count legacy sigops (do not count scripthash or witness).
sigops += tx.getLegacySigops();
if (sigops * scale > constants.block.MAX_SIGOPS_WEIGHT) {
ret.reason = 'bad-blk-sigops';
@ -685,9 +690,9 @@ Block.fromJSON = function fromJSON(json) {
* @param {Buffer} data
*/
Block.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
var i, tx, witnessSize;
Block.prototype.fromReader = function fromReader(br) {
var witnessSize = 0;
var i, tx;
br.start();
@ -699,10 +704,8 @@ Block.prototype.fromRaw = function fromRaw(data) {
this.nonce = br.readU32();
this.totalTX = br.readVarint();
witnessSize = 0;
for (i = 0; i < this.totalTX; i++) {
tx = TX.fromRaw(br);
tx = TX.fromReader(br);
witnessSize += tx._witnessSize;
this.addTX(tx);
}
@ -716,6 +719,27 @@ Block.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
Block.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate a block from a serialized Buffer.
* @param {Buffer} data
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {Block}
*/
Block.fromReader = function fromReader(data) {
return new Block().fromReader(data);
};
/**
* Instantiate a block from a serialized Buffer.
* @param {Buffer} data
@ -749,9 +773,7 @@ Block.prototype.toMerkle = function toMerkle(filter) {
* @returns {Buffer}
*/
Block.prototype.frame = function frame(witness, writer) {
var bw = BufferWriter(writer);
var witnessSize = 0;
Block.prototype.frameNormalWriter = function frameNormalWriter(bw) {
var i, tx;
bw.writeU32(this.version);
@ -764,20 +786,54 @@ Block.prototype.frame = function frame(witness, writer) {
for (i = 0; i < this.txs.length; i++) {
tx = this.txs[i];
if (witness) {
tx.toRaw(bw);
witnessSize += tx._lastWitnessSize;
} else {
tx.toNormal(bw);
}
tx.toNormalWriter(bw);
}
this._lastWitnessSize = witnessSize;
return new RawBlock(bw.written, 0);
};
if (!writer)
bw = bw.render();
/**
* Serialze block with or without witness data.
* @private
* @param {Boolean} witness
* @param {BufferWriter?} writer
* @returns {Buffer}
*/
return bw;
Block.prototype.frameWitnessWriter = function frameWitnessWriter(bw) {
var witnessSize = 0;
var i, tx, raw;
bw.writeU32(this.version);
bw.writeHash(this.prevBlock);
bw.writeHash(this.merkleRoot);
bw.writeU32(this.ts);
bw.writeU32(this.bits);
bw.writeU32(this.nonce);
bw.writeVarint(this.txs.length);
for (i = 0; i < this.txs.length; i++) {
tx = this.txs[i];
raw = tx.writeRaw(bw);
witnessSize += raw.witness;
}
return new RawBlock(bw.written, witnessSize);
};
/**
* Serialze block with or without witness data.
* @private
* @param {Boolean} witness
* @param {BufferWriter?} writer
* @returns {Buffer}
*/
Block.prototype.frameNormal = function frameNormal() {
var bw = new BufferWriter();
var raw = this.frameNormalWriter(bw);
raw.data = bw.render();
return raw;
};
/**
@ -787,19 +843,11 @@ Block.prototype.frame = function frame(witness, writer) {
* @returns {Buffer}
*/
Block.prototype.frameNormal = function frameNormal(writer) {
return this.frame(false, writer);
};
/**
* Serialze block with witness data.
* @private
* @param {BufferWriter?} writer
* @returns {Buffer}
*/
Block.prototype.frameWitness = function frameWitness(writer) {
return this.frame(true, writer);
Block.prototype.frameWitness = function frameWitness() {
var bw = new BufferWriter();
var raw = this.frameWitnessWriter(bw);
raw.data = bw.render();
return raw;
};
/**
@ -827,9 +875,10 @@ Block.isBlock = function isBlock(obj) {
* Helpers
*/
function BlockSizes() {
this.total = 0;
this.witness = 0;
function RawBlock(total, witness) {
this.data = null;
this.total = total;
this.witness = witness;
}
/*

View File

@ -194,13 +194,11 @@ Coin.prototype.fromJSON = function fromJSON(json) {
};
/**
* Serialize the coin.
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {Buffer|String}
* Write the coin to a buffer writer.
* @param {BufferWriter} bw
*/
Coin.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
Coin.prototype.toWriter = function toWriter(bw) {
var height = this.height;
if (height === -1)
@ -212,21 +210,25 @@ Coin.prototype.toRaw = function toRaw(writer) {
bw.writeVarBytes(this.script.toRaw());
bw.writeU8(this.coinbase ? 1 : 0);
if (!writer)
bw = bw.render();
return bw;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* Serialize the coin.
* @returns {Buffer|String}
*/
Coin.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
Coin.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
/**
* Inject properties from serialized buffer writer.
* @private
* @param {BufferReader} br
*/
Coin.prototype.fromReader = function fromReader(br) {
this.version = br.readU32();
this.height = br.readU32();
this.value = br.read64();
@ -240,7 +242,27 @@ Coin.prototype.fromRaw = function fromRaw(data) {
};
/**
* Instantiate an coin from a serialized Buffer.
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
Coin.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate a coin from a buffer reader.
* @param {BufferReader} br
* @returns {Coin}
*/
Coin.fromReader = function fromReader(br) {
return new Coin().fromReader(br);
};
/**
* Instantiate a coin from a serialized Buffer.
* @param {Buffer} data
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {Coin}
@ -260,6 +282,7 @@ Coin.fromRaw = function fromRaw(data, enc) {
Coin.prototype.fromTX = function fromTX(tx, index) {
assert(util.isNumber(index));
assert(index < tx.outputs.length);
this.version = tx.version;
this.height = tx.height;
this.value = tx.outputs[index].value;

View File

@ -47,42 +47,15 @@ Headers.prototype._verify = function _verify(ret) {
*/
Headers.prototype.getSize = function getSize() {
var writer = new BufferWriter();
this.toRaw(writer);
return writer.written;
return this.toWriter(new BufferWriter()).written;
};
/**
* Inspect the headers and return a more
* user-friendly representation of the data.
* @returns {Object}
* Serialize the headers to a buffer writer.
* @param {BufferWriter} bw
*/
Headers.prototype.inspect = function inspect() {
return {
type: 'headers',
hash: this.rhash(),
height: this.height,
date: util.date(this.ts),
version: util.hex32(this.version),
prevBlock: util.revHex(this.prevBlock),
merkleRoot: util.revHex(this.merkleRoot),
ts: this.ts,
bits: this.bits,
nonce: this.nonce,
totalTX: this.totalTX
};
};
/**
* Serialize the headers.
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {Buffer|String}
*/
Headers.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
Headers.prototype.toWriter = function toWriter(bw) {
bw.writeU32(this.version);
bw.writeHash(this.prevBlock);
bw.writeHash(this.merkleRoot);
@ -90,13 +63,35 @@ Headers.prototype.toRaw = function toRaw(writer) {
bw.writeU32(this.bits);
bw.writeU32(this.nonce);
bw.writeVarint(this.totalTX);
if (!writer)
bw = bw.render();
return bw;
};
/**
* Serialize the headers.
* @returns {Buffer|String}
*/
Headers.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
/**
* Inject properties from buffer reader.
* @private
* @param {Buffer} data
*/
Headers.prototype.fromReader = function fromReader(br) {
this.version = br.readU32(); // Technically signed
this.prevBlock = br.readHash('hex');
this.merkleRoot = br.readHash('hex');
this.ts = br.readU32();
this.bits = br.readU32();
this.nonce = br.readU32();
this.totalTX = br.readVarint();
return this;
};
/**
* Inject properties from serialized data.
* @private
@ -104,17 +99,17 @@ Headers.prototype.toRaw = function toRaw(writer) {
*/
Headers.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
return this.fromReader(new BufferReader(data));
};
this.version = br.readU32(); // Technically signed
this.prevBlock = br.readHash('hex');
this.merkleRoot = br.readHash('hex');
this.ts = br.readU32();
this.bits = br.readU32();
this.nonce = br.readU32();
this.totalTX = br.readVarint();
/**
* Instantiate headers from buffer reader.
* @param {BufferReader} br
* @returns {Headers}
*/
return this;
Headers.fromReader = function fromReader(br) {
return new Headers().fromReader(br);
};
/**
@ -131,24 +126,41 @@ Headers.fromRaw = function fromRaw(data, enc) {
};
/**
* Inject properties from serialized data.
* Inject properties from buffer reader.
* @private
* @param {Buffer} data
* @param {BufferReader} br
*/
Headers.prototype.fromAbbr = function fromAbbr(data) {
var br = BufferReader(data);
Headers.prototype.fromAbbrReader = function fromAbbrReader(br) {
this.version = br.readU32(); // Technically signed
this.prevBlock = br.readHash('hex');
this.merkleRoot = br.readHash('hex');
this.ts = br.readU32();
this.bits = br.readU32();
this.nonce = br.readU32();
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
Headers.prototype.fromAbbr = function fromAbbr(data) {
return this.fromAbbrReader(new BufferReader(data));
};
/**
* Instantiate headers from buffer reader.
* @param {BufferReader} br
* @returns {Headers}
*/
Headers.fromAbbrReader = function fromAbbrReader(br) {
return new Headers().fromAbbrReader(br);
};
/**
* Instantiate headers from serialized data.
* @param {Buffer} data
@ -197,6 +209,27 @@ Headers.fromBlock = function fromBlock(block) {
return headers;
};
/**
* Inspect the headers and return a more
* user-friendly representation of the data.
* @returns {Object}
*/
Headers.prototype.inspect = function inspect() {
return {
hash: this.rhash(),
height: this.height,
date: util.date(this.ts),
version: util.hex32(this.version),
prevBlock: util.revHex(this.prevBlock),
merkleRoot: util.revHex(this.merkleRoot),
ts: this.ts,
bits: this.bits,
nonce: this.nonce,
totalTX: this.totalTX
};
};
/**
* Test an object to see if it is a Headers object.
* @param {Object} obj

View File

@ -316,32 +316,52 @@ Input.fromJSON = function fromJSON(json) {
* @returns {Buffer|String}
*/
Input.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
Input.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
this.prevout.toRaw(bw);
/**
* Write the input to a buffer writer.
* @param {BufferWriter} bw
*/
Input.prototype.toWriter = function toWriter(bw) {
this.prevout.toWriter(bw);
bw.writeVarBytes(this.script.toRaw());
bw.writeU32(this.sequence);
if (!writer)
bw = bw.render();
return bw;
};
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
Input.prototype.fromReader = function fromReader(br) {
this.prevout.fromReader(br);
this.script.fromRaw(br.readVarBytes());
this.sequence = br.readU32();
return this;
};
/**
* Inject properties from serialized data.
* @param {Buffer} data
*/
Input.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
return this.fromReader(new BufferReader(data));
};
this.prevout.fromRaw(br);
this.script.fromRaw(br.readVarBytes());
this.sequence = br.readU32();
/**
* Instantiate an input from a buffer reader.
* @param {BufferReader} br
* @returns {Input}
*/
return this;
Input.fromReader = function fromReader(br) {
return new Input().fromReader(br);
};
/**
@ -357,52 +377,6 @@ Input.fromRaw = function fromRaw(data, enc) {
return new Input().fromRaw(data);
};
/**
* Serialize the input to an "extended" format,
* including both the input and the witness.
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {Buffer|String}
*/
Input.prototype.toExtended = function toExtended(writer) {
var bw = BufferWriter(writer);
this.toRaw(bw);
this.witness.toRaw(bw);
if (!writer)
bw = bw.render();
return bw;
};
/**
* Inject properties from extended serialized data.
* @private
* @param {Buffer} data
*/
Input.prototype.fromExtended = function fromExtended(data) {
var br = BufferReader(data);
this.fromRaw(br);
this.witness.fromRaw(br);
return this;
};
/**
* Instantiate an input from a Buffer
* in "extended" serialization format.
* @param {Buffer} data
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {TX}
*/
Input.fromExtended = function fromExtended(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new Input().fromExtended(data);
};
/**
* Inject properties from coin.
* @private

View File

@ -27,21 +27,36 @@ function InvItem(type, hash) {
this.hash = hash;
}
/**
* 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(writer) {
var bw = BufferWriter(writer);
InvItem.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
bw.writeU32(this.type);
bw.writeHash(this.hash);
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
if (!writer)
bw = bw.render();
return bw;
InvItem.prototype.fromReader = function fromReader(br) {
this.type = br.readU32();
this.hash = br.readHash('hex');
return this;
};
/**
@ -50,10 +65,17 @@ InvItem.prototype.toRaw = function toRaw(writer) {
*/
InvItem.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
this.type = br.readU32();
this.hash = br.readHash('hex');
return this;
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);
};
/**

View File

@ -811,12 +811,11 @@ KeyRing.fromJSON = function fromJSON(json) {
};
/**
* Serialize the keyring.
* @returns {Buffer}
* Write the keyring to a buffer writer.
* @param {BufferWriter} bw
*/
KeyRing.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
KeyRing.prototype.toWriter = function toWriter(bw) {
var field = 0;
if (this.witness)
@ -839,20 +838,26 @@ KeyRing.prototype.toRaw = function toRaw(writer) {
else
bw.writeVarint(0);
if (!writer)
bw = bw.render();
return bw;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* Serialize the keyring.
* @returns {Buffer}
*/
KeyRing.prototype.fromRaw = function fromRaw(data, network) {
var br = new BufferReader(data);
KeyRing.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
* @param {Network?} network
*/
KeyRing.prototype.fromReader = function fromReader(br, network) {
var field, compressed, key, script;
this.network = Network.get(network);
@ -881,6 +886,27 @@ KeyRing.prototype.fromRaw = function fromRaw(data, network) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* @param {Network?} network
*/
KeyRing.prototype.fromRaw = function fromRaw(data, network) {
return this.fromReader(new BufferReader(data), network);
};
/**
* Instantiate a keyring from buffer reader.
* @param {BufferReader} br
* @returns {KeyRing}
*/
KeyRing.fromReader = function fromReader(br) {
return new KeyRing().fromReader(br);
};
/**
* Instantiate a keyring from serialized data.
* @param {Buffer} data

View File

@ -83,15 +83,8 @@ MemBlock.fromOptions = function fromOptions(options) {
* @returns {Buffer}
*/
MemBlock.prototype.abbr = function abbr(writer) {
var data = this.raw.slice(0, 80);
if (writer) {
writer.writeBytes(data);
return writer;
}
return data;
MemBlock.prototype.abbr = function abbr() {
return this.raw.slice(0, 80);
};
/**
@ -132,7 +125,7 @@ MemBlock.prototype.getCoinbaseHeight = function getCoinbaseHeight() {
*/
MemBlock.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data, true);
var br = new BufferReader(data, true);
var height = -1;
var inCount, input;

View File

@ -94,14 +94,12 @@ MerkleBlock.fromOptions = function fromOptions(data) {
*/
MerkleBlock.prototype.getSize = function getSize() {
var writer = new BufferWriter();
this.toRaw(writer);
return writer.written;
return this.toWriter(new BufferWriter()).written;
};
/**
* Add a transaction to the block's tx vector.
* @param {TX|NakedTX} tx
* @param {TX} tx
* @returns {TX}
*/
@ -338,13 +336,11 @@ MerkleBlock.prototype.inspect = function inspect() {
};
/**
* Serialize the merkleblock.
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {Buffer|String}
* Write the merkleblock to a buffer writer.
* @param {BufferWriter} bw
*/
MerkleBlock.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
MerkleBlock.prototype.toWriter = function toWriter(bw) {
var i;
bw.writeU32(this.version);
@ -362,20 +358,26 @@ MerkleBlock.prototype.toRaw = function toRaw(writer) {
bw.writeVarBytes(this.flags);
if (!writer)
bw = bw.render();
return bw;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* Serialize the merkleblock.
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {Buffer|String}
*/
MerkleBlock.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
MerkleBlock.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
MerkleBlock.prototype.fromReader = function fromReader(br) {
var i, count;
this.version = br.readU32();
@ -396,6 +398,26 @@ MerkleBlock.prototype.fromRaw = function fromRaw(data) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
MerkleBlock.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate a merkleblock from a buffer reader.
* @param {BufferReader} br
* @returns {MerkleBlock}
*/
MerkleBlock.fromReader = function fromReader(br) {
return new MerkleBlock().fromReader(br);
};
/**
* Instantiate a merkleblock from a serialized data.
* @param {Buffer} data

View File

@ -1386,6 +1386,14 @@ MTX.fromJSON = function fromJSON(json) {
return new MTX().fromJSON(JSON)._mutable();
};
/**
* @see TX.fromReader
*/
MTX.fromReader = function fromReader(br) {
return new MTX().fromReader(br)._mutable();
};
/**
* @see TX.fromRaw
*/

View File

@ -247,15 +247,13 @@ NetworkAddress.fromSocket = function fromSocket(hostname, network) {
};
/**
* Inject properties from serialized data.
* Inject properties from buffer reader.
* @private
* @param {Buffer} data
* @param {BufferReader} br
* @param {Boolean?} full - Include timestamp.
*/
NetworkAddress.prototype.fromRaw = function fromRaw(data, full) {
var br = BufferReader(data);
NetworkAddress.prototype.fromReader = function fromReader(br, full) {
// only version >= 31402
this.ts = full ? br.readU32() : 0;
this.services = br.readU53();
@ -267,6 +265,28 @@ NetworkAddress.prototype.fromRaw = function fromRaw(data, full) {
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* @param {Boolean?} full - Include timestamp.
*/
NetworkAddress.prototype.fromRaw = function fromRaw(data, full) {
return this.fromReader(new BufferReader(data), full);
};
/**
* Insantiate a network address from buffer reader.
* @param {BufferReader} br
* @param {Boolean?} full - Include timestamp.
* @returns {NetworkAddress}
*/
NetworkAddress.fromReader = function fromReader(br, full) {
return new NetworkAddress().fromReader(br, full);
};
/**
* Insantiate a network address from serialized data.
* @param {Buffer} data
@ -279,14 +299,13 @@ NetworkAddress.fromRaw = function fromRaw(data, full) {
};
/**
* Serialize network address.
* @param {Boolean} full - Include timestamp.
* Write network address to a buffer writer.
* @param {BufferWriter} bw
* @param {Boolean?} full - Include timestamp.
* @returns {Buffer}
*/
NetworkAddress.prototype.toRaw = function toRaw(full, writer) {
var bw = BufferWriter(writer);
NetworkAddress.prototype.toWriter = function toWriter(bw, full) {
if (full)
bw.writeU32(this.ts);
@ -294,12 +313,19 @@ NetworkAddress.prototype.toRaw = function toRaw(full, writer) {
bw.writeBytes(IP.toBuffer(this.host));
bw.writeU16BE(this.port);
if (!writer)
bw = bw.render();
return bw;
};
/**
* Serialize network address.
* @param {Boolean?} full - Include timestamp.
* @returns {Buffer}
*/
NetworkAddress.prototype.toRaw = function toRaw(full) {
return this.toWriter(new BufferWriter(), full).render();
};
/*
* Expose
*/

View File

@ -64,21 +64,36 @@ Outpoint.prototype.isNull = function isNull() {
return this.index === 0xffffffff && this.hash === constants.NULL_HASH;
};
/**
* Write outpoint to a buffer writer.
* @param {BufferWriter} bw
*/
Outpoint.prototype.toWriter = function toWriter(bw) {
bw.writeHash(this.hash);
bw.writeU32(this.index);
return bw;
};
/**
* Serialize outpoint.
* @returns {Buffer}
*/
Outpoint.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
Outpoint.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
bw.writeHash(this.hash);
bw.writeU32(this.index);
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
if (!writer)
bw = bw.render();
return bw;
Outpoint.prototype.fromReader = function fromReader(br) {
this.hash = br.readHash('hex');
this.index = br.readU32();
return this;
};
/**
@ -88,10 +103,17 @@ Outpoint.prototype.toRaw = function toRaw(writer) {
*/
Outpoint.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
this.hash = br.readHash('hex');
this.index = br.readU32();
return this;
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate outpoint from a buffer reader.
* @param {BufferReader} br
* @returns {Outpoint}
*/
Outpoint.fromReader = function fromReader(br) {
return new Outpoint().fromReader(br);
};
/**

View File

@ -181,7 +181,7 @@ Output.prototype.getDustThreshold = function getDustThreshold(rate) {
*/
Output.prototype.getSize = function getSize() {
return this.toRaw(BufferWriter()).written;
return this.toWriter(new BufferWriter()).written;
};
/**
@ -217,22 +217,37 @@ Output.fromJSON = function fromJSON(json) {
return new Output().fromJSON(json);
};
/**
* Write the output to a buffer writer.
* @param {BufferWriter} bw
*/
Output.prototype.toWriter = function toWriter(bw) {
bw.write64(this.value);
bw.writeVarBytes(this.script.toRaw());
return bw;
};
/**
* Serialize the output.
* @param {String?} enc - Encoding, can be `'hex'` or null.
* @returns {Buffer|String}
*/
Output.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
Output.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
bw.write64(this.value);
bw.writeVarBytes(this.script.toRaw());
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
if (!writer)
bw = bw.render();
return bw;
Output.prototype.fromReader = function fromReader(br) {
this.value = br.read64();
this.script.fromRaw(br.readVarBytes());
return this;
};
/**
@ -242,12 +257,17 @@ Output.prototype.toRaw = function toRaw(writer) {
*/
Output.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
return this.fromReader(new BufferReader(data));
};
this.value = br.read64();
this.script.fromRaw(br.readVarBytes());
/**
* Instantiate an output from a buffer reader.
* @param {BufferReader} br
* @returns {Output}
*/
return this;
Output.fromReader = function fromReader(br) {
return new Output().fromReader(br);
};
/**
@ -260,7 +280,6 @@ Output.prototype.fromRaw = function fromRaw(data) {
Output.fromRaw = function fromRaw(data, enc) {
if (typeof data === 'string')
data = new Buffer(data, enc);
return new Output().fromRaw(data);
};

View File

@ -9,13 +9,13 @@
var assert = require('assert');
var util = require('../utils/util');
var co = require('../utils/co');
var crypto = require('../crypto/crypto');
var btcutils = require('../btc/utils');
var Amount = require('../btc/amount');
var constants = require('../protocol/constants');
var Network = require('../protocol/network');
var Script = require('../script/script');
var Stack = require('../script/stack');
var BufferWriter = require('../utils/writer');
var VerifyResult = require('../btc/errors').VerifyResult;
var Input = require('./input');
@ -92,7 +92,6 @@ function TX(options) {
this._raw = null;
this._size = -1;
this._witnessSize = -1;
this._lastWitnessSize = 0;
this._outputValue = -1;
this._inputValue = -1;
@ -253,17 +252,11 @@ TX.prototype.hash = function _hash(enc) {
TX.prototype.witnessHash = function witnessHash(enc) {
var hash = this._whash;
if (this.isCoinbase()) {
return enc === 'hex'
? constants.NULL_HASH
: util.copy(constants.ZERO_HASH);
}
if (!this.hasWitness())
return this.hash(enc);
if (!hash) {
hash = crypto.hash256(this.toWitness());
hash = crypto.hash256(this.toRaw());
if (!this.mutable)
this._whash = hash;
}
@ -279,13 +272,8 @@ TX.prototype.witnessHash = function witnessHash(enc) {
* @returns {Buffer} Serialized transaction.
*/
TX.prototype.toRaw = function toRaw(writer) {
var raw = this.getRaw();
if (writer) {
writer.writeBytes(raw);
return writer;
}
return raw;
TX.prototype.toRaw = function toRaw() {
return this.getRaw().data;
};
/**
@ -295,27 +283,34 @@ TX.prototype.toRaw = function toRaw(writer) {
* @returns {Buffer} Serialized transaction.
*/
TX.prototype.toNormal = function toNormal(writer) {
var raw = this.getRaw();
if (!TX.isWitness(raw)) {
if (writer) {
writer.writeBytes(raw);
return writer;
}
return raw;
}
return this.frameNormal(writer);
TX.prototype.toNormal = function toNormal() {
if (this.hasWitness())
return this.frameNormal().data;
return this.toRaw();
};
/**
* Serialize the transaction with the
* witness vector. Will use normal
* serialization if witness vector is empty.
* @returns {Buffer} Serialized transaction.
* Write the transaction to a buffer writer.
* @param {BufferWriter} bw
*/
TX.prototype.toWitness = function toWitness(writer) {
return this.toRaw(writer);
TX.prototype.toWriter = function toWriter(bw) {
this.writeRaw(bw);
return bw;
};
/**
* Write the transaction to a buffer writer.
* Uses non-witness serialization.
* @param {BufferWriter} bw
*/
TX.prototype.toNormalWriter = function toNormalWriter(bw) {
if (this.hasWitness()) {
this.frameNormalWriter(bw);
return bw;
}
return this.toWriter(bw);
};
/**
@ -323,17 +318,26 @@ TX.prototype.toWitness = function toWitness(writer) {
* that this is cached. This will use
* the witness serialization if a
* witness is present.
* @returns {Buffer} Serialized transaction.
* @private
* @returns {RawTX}
*/
TX.prototype.getRaw = function getRaw() {
var raw;
if (this.mutable) {
assert(!this._raw);
if (this.hasWitness())
return this.frameWitness();
return this.frameNormal();
}
if (this._raw) {
assert(this._size > 0);
assert(this._witnessSize >= 0);
this._lastWitnessSize = this._witnessSize;
return this._raw;
raw = new RawTX(this._size, this._witnessSize);
raw.data = this._raw;
return raw;
}
if (this.hasWitness())
@ -341,39 +345,43 @@ TX.prototype.getRaw = function getRaw() {
else
raw = this.frameNormal();
if (!this.mutable) {
this._raw = raw;
this._size = raw.length;
this._witnessSize = this._lastWitnessSize;
}
this._raw = raw.data;
this._size = raw.total;
this._witnessSize = raw.witness;
return raw;
};
/**
* Calculate real size and size of the witness bytes.
* @returns {Object} Contains `size` and `witnessSize`.
* Write raw transaction to buffer writer.
* Cache if possible.
* @returns {RawTX}
*/
TX.prototype.writeRaw = function writeRaw(bw) {
var raw;
if (this.mutable) {
if (this.hasWitness())
return this.frameWitnessWriter(bw);
return this.frameNormalWriter(bw);
}
raw = this.getRaw();
bw.writeBytes(raw.data);
return raw;
};
/**
* Calculate total size and size of the witness bytes.
* @returns {Object} Contains `total` and `witness`.
*/
TX.prototype.getSizes = function getSizes() {
var sizes = new TXSizes();
var writer;
if (this.mutable) {
assert(!this._raw);
writer = new BufferWriter();
this.toRaw(writer);
sizes.total = writer.written;
sizes.witness = this._lastWitnessSize;
return sizes;
}
this.getRaw();
sizes.total = this._size;
sizes.witness = this._witnessSize;
return sizes;
if (this.mutable)
return this.writeRaw(new BufferWriter());
return this.getRaw();
};
/**
@ -394,9 +402,9 @@ TX.prototype.getVirtualSize = function getVirtualSize() {
*/
TX.prototype.getWeight = function getWeight() {
var sizes = this.getSizes();
var base = sizes.total - sizes.witness;
return base * (constants.WITNESS_SCALE_FACTOR - 1) + sizes.total;
var raw = this.getSizes();
var base = raw.total - raw.witness;
return base * (constants.WITNESS_SCALE_FACTOR - 1) + raw.total;
};
/**
@ -417,8 +425,8 @@ TX.prototype.getSize = function getSize() {
*/
TX.prototype.getBaseSize = function getBaseSize() {
var sizes = this.getSizes();
return sizes.total - sizes.witness;
var raw = this.getSizes();
return raw.total - raw.witness;
};
/**
@ -427,13 +435,14 @@ TX.prototype.getBaseSize = function getBaseSize() {
*/
TX.prototype.hasWitness = function hasWitness() {
var i;
var i, input;
if (this._witnessSize !== -1)
return this._witnessSize !== 0;
for (i = 0; i < this.inputs.length; i++) {
if (this.inputs[i].witness.items.length > 0)
input = this.inputs[i];
if (input.witness.items.length > 0)
return true;
}
@ -452,9 +461,6 @@ TX.prototype.hasWitness = function hasWitness() {
*/
TX.prototype.signatureHash = function signatureHash(index, prev, type, version) {
if (typeof index !== 'number')
index = this.inputs.indexOf(index);
if (typeof type === 'string')
type = constants.hashType[type.toUpperCase()];
@ -506,8 +512,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
input = this.inputs[index];
// Outpoint.
bw.writeHash(input.prevout.hash);
bw.writeU32(input.prevout.index);
input.prevout.toWriter(bw);
// Replace script with previous
// output script if current index.
@ -519,8 +524,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) {
input = this.inputs[i];
// Outpoint.
bw.writeHash(input.prevout.hash);
bw.writeU32(input.prevout.index);
input.prevout.toWriter(bw);
// Replace script with previous
// output script if current index.
@ -606,7 +610,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) {
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
input.prevout.toRaw(bw);
input.prevout.toWriter(bw);
}
prevouts = crypto.hash256(bw.render());
@ -649,7 +653,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) {
for (i = 0; i < this.outputs.length; i++) {
output = this.outputs[i];
output.toRaw(bw);
output.toWriter(bw);
}
outputs = crypto.hash256(bw.render());
@ -715,12 +719,7 @@ TX.prototype.verify = function verify(flags) {
*/
TX.prototype.verifyInput = function verifyInput(index, flags) {
var input;
if (typeof index === 'object')
index = this.inputs.indexOf(index);
input = this.inputs[index];
var input = this.inputs[index];
assert(input, 'Input does not exist.');
@ -753,15 +752,15 @@ TX.prototype.verifyInput = function verifyInput(index, flags) {
* @returns {Boolean} Whether the inputs are valid.
*/
TX.prototype.verifyAsync = function verifyAsync(flags) {
TX.prototype.verifyAsync = co(function* verifyAsync(flags) {
if (this.inputs.length === 0)
return Promise.resolve(false);
return false;
if (this.isCoinbase())
return Promise.resolve(true);
return true;
return workerPool.verify(this, flags);
};
return yield workerPool.verify(this, flags);
});
/**
* Verify a transaction input asynchronously.
@ -771,18 +770,11 @@ TX.prototype.verifyAsync = function verifyAsync(flags) {
* @returns {Boolean} Whether the input is valid.
*/
TX.prototype.verifyInputAsync = function verifyInputAsync(index, flags) {
var input;
if (typeof index === 'object')
index = this.inputs.indexOf(index);
input = this.inputs[index];
TX.prototype.verifyInputAsync = co(function* verifyInputAsync(index, flags) {
var input = this.inputs[index];
assert(input, 'Input does not exist.');
return workerPool.verifyInput(this, index, flags);
};
return yield workerPool.verifyInput(this, index, flags);
});
/**
* Test whether the transaction is a coinbase
@ -1169,13 +1161,17 @@ TX.prototype.isFinal = function isFinal(height, ts) {
TX.prototype.getLegacySigops = function getLegacySigops() {
var total = 0;
var i;
var i, input, output;
for (i = 0; i < this.inputs.length; i++)
total += this.inputs[i].script.getSigops(false);
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
total += input.script.getSigops(false);
}
for (i = 0; i < this.outputs.length; i++)
total += this.outputs[i].script.getSigops(false);
for (i = 0; i < this.outputs.length; i++) {
output = this.outputs[i];
total += output.script.getSigops(false);
}
return total;
};
@ -1187,19 +1183,20 @@ TX.prototype.getLegacySigops = function getLegacySigops() {
TX.prototype.getScripthashSigops = function getScripthashSigops() {
var total = 0;
var i, input;
var i, input, coin;
if (this.isCoinbase())
return 0;
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
coin = input.coin;
if (!input.coin)
if (!coin)
continue;
if (input.coin.script.isScripthash())
total += input.coin.script.getScripthashSigops(input.script);
if (coin.script.isScripthash())
total += coin.script.getScripthashSigops(input.script);
}
return total;
@ -1439,34 +1436,26 @@ TX.prototype.isStandard = function isStandard(ret) {
TX.prototype.hasStandardInputs = function hasStandardInputs() {
var maxSigops = constants.script.MAX_SCRIPTHASH_SIGOPS;
var VERIFY_NONE = constants.flags.VERIFY_NONE;
var i, input, stack, redeem;
var i, input, coin, redeem;
if (this.isCoinbase())
return true;
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
coin = input.coin;
if (!input.coin)
if (!coin)
return false;
if (input.coin.script.isUnknown())
if (coin.script.isUnknown())
return false;
if (input.coin.script.isScripthash()) {
stack = new Stack();
if (coin.script.isScripthash()) {
redeem = input.script.getRedeem();
try {
input.script.execute(stack, VERIFY_NONE, this, i, 0);
} catch (e) {
if (!redeem)
return false;
}
if (stack.length === 0)
return false;
redeem = Script.fromRaw(stack.top(-1));
if (redeem.getSigops(true) > maxSigops)
return false;
@ -1737,13 +1726,14 @@ TX.prototype.maxSize = function maxSize() {
*/
TX.prototype.getModifiedSize = function getModifiedSize(size) {
var i, offset;
var i, input, offset;
if (size == null)
size = this.maxSize();
for (i = 0; i < this.inputs.length; i++) {
offset = 41 + Math.min(110, this.inputs[i].script.getSize());
input = this.inputs[i];
offset = 41 + Math.min(110, input.script.getSize());
if (size > offset)
size -= offset;
}
@ -1940,9 +1930,6 @@ TX.prototype.isWatched = function isWatched(filter) {
var found = false;
var i, input, output, prevout;
if (!filter)
return false;
// 1. Test the tx hash
if (filter.test(this.hash()))
found = true;
@ -2195,32 +2182,51 @@ TX.fromRaw = function fromRaw(data, enc) {
return new TX().fromRaw(data);
};
/**
* Instantiate a transaction from a buffer reader.
* @param {BufferReader} br
* @returns {TX}
*/
TX.fromReader = function fromReader(br) {
return new TX().fromReader(br);
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer|BufferReader} data
* @param {Buffer} data
*/
TX.prototype.fromRaw = function fromRaw(data) {
var br, i, count;
return this.fromReader(new BufferReader(data));
};
if (TX.isWitness(data))
return this.fromWitness(data);
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
TX.prototype.fromReader = function fromReader(br) {
var i, count;
if (TX.isWitness(br))
return this.fromWitnessReader(br);
br = BufferReader(data);
br.start();
this.version = br.readU32(); // Technically signed
this.version = br.readU32();
count = br.readVarint();
for (i = 0; i < count; i++)
this.inputs.push(Input.fromRaw(br));
this.inputs.push(Input.fromReader(br));
count = br.readVarint();
for (i = 0; i < count; i++)
this.outputs.push(Output.fromRaw(br));
this.outputs.push(Output.fromReader(br));
this.locktime = br.readU32();
@ -2237,13 +2243,12 @@ TX.prototype.fromRaw = function fromRaw(data) {
/**
* Inject properties from serialized
* data (witness serialization).
* buffer reader (witness serialization).
* @private
* @param {Buffer|BufferReader} data
* @param {BufferReader} br
*/
TX.prototype.fromWitness = function fromWitness(data) {
var br = BufferReader(data);
TX.prototype.fromWitnessReader = function fromWitnessReader(br) {
var flag = 0;
var witnessSize = 0;
var hasWitness = false;
@ -2251,7 +2256,7 @@ TX.prototype.fromWitness = function fromWitness(data) {
br.start();
this.version = br.readU32(); // Technically signed
this.version = br.readU32();
assert(br.readU8() === 0, 'Non-zero marker.');
@ -2264,12 +2269,12 @@ TX.prototype.fromWitness = function fromWitness(data) {
count = br.readVarint();
for (i = 0; i < count; i++)
this.inputs.push(Input.fromRaw(br));
this.inputs.push(Input.fromReader(br));
count = br.readVarint();
for (i = 0; i < count; i++)
this.outputs.push(Output.fromRaw(br));
this.outputs.push(Output.fromReader(br));
if (flag & 1) {
flag ^= 1;
@ -2278,7 +2283,7 @@ TX.prototype.fromWitness = function fromWitness(data) {
for (i = 0; i < this.inputs.length; i++) {
input = this.inputs[i];
input.witness.fromRaw(br);
input.witness.fromReader(br);
if (input.witness.items.length > 0)
hasWitness = true;
}
@ -2311,12 +2316,39 @@ TX.prototype.fromWitness = function fromWitness(data) {
/**
* Serialize transaction without witness.
* @private
* @param {BufferWriter?} writer - A buffer writer to continue writing from.
* @returns {Buffer} Returns a BufferWriter if `writer` was passed in.
* @returns {RawTX}
*/
TX.prototype.frameNormal = function frameNormal(writer) {
var bw = BufferWriter(writer);
TX.prototype.frameNormal = function frameNormal() {
var bw = new BufferWriter();
var raw = this.frameNormalWriter(bw);
raw.data = bw.render();
return raw;
};
/**
* Serialize transaction with witness. Calculates the witness
* size as it is framing (exposed on return value as `witness`).
* @private
* @returns {RawTX}
*/
TX.prototype.frameWitness = function frameWitness() {
var bw = new BufferWriter();
var raw = this.frameWitnessWriter(bw);
raw.data = bw.render();
return raw;
};
/**
* Serialize transaction without witness.
* @private
* @param {BufferWriter} writer
* @returns {RawTX}
*/
TX.prototype.frameNormalWriter = function frameNormalWriter(bw) {
var offset = bw.written;
var i;
if (this.inputs.length === 0 && this.outputs.length !== 0)
@ -2327,33 +2359,28 @@ TX.prototype.frameNormal = function frameNormal(writer) {
bw.writeVarint(this.inputs.length);
for (i = 0; i < this.inputs.length; i++)
this.inputs[i].toRaw(bw);
this.inputs[i].toWriter(bw);
bw.writeVarint(this.outputs.length);
for (i = 0; i < this.outputs.length; i++)
this.outputs[i].toRaw(bw);
this.outputs[i].toWriter(bw);
bw.writeU32(this.locktime);
if (!writer)
bw = bw.render();
this._lastWitnessSize = 0;
return bw;
return new RawTX(bw.written - offset, 0);
};
/**
* Serialize transaction with witness. Calculates the witness
* size as it is framing (exposed on return value as `_witnessSize`).
* size as it is framing (exposed on return value as `witness`).
* @private
* @param {BufferWriter?} writer - A buffer writer to continue writing from.
* @returns {Buffer} Returns a BufferWriter if `writer` was passed in.
* @param {BufferWriter} bw
* @returns {RawTX}
*/
TX.prototype.frameWitness = function frameWitness(writer) {
var bw = BufferWriter(writer);
TX.prototype.frameWitnessWriter = function frameWitnessWriter(bw) {
var offset = bw.written;
var witnessSize = 0;
var i, start;
@ -2367,17 +2394,17 @@ TX.prototype.frameWitness = function frameWitness(writer) {
bw.writeVarint(this.inputs.length);
for (i = 0; i < this.inputs.length; i++)
this.inputs[i].toRaw(bw);
this.inputs[i].toWriter(bw);
bw.writeVarint(this.outputs.length);
for (i = 0; i < this.outputs.length; i++)
this.outputs[i].toRaw(bw);
this.outputs[i].toWriter(bw);
start = bw.written;
for (i = 0; i < this.inputs.length; i++)
this.inputs[i].witness.toRaw(bw);
this.inputs[i].witness.toWriter(bw);
witnessSize += bw.written - start;
@ -2386,12 +2413,7 @@ TX.prototype.frameWitness = function frameWitness(writer) {
if (witnessSize === this.inputs.length)
throw new Error('Cannot serialize empty-witness tx.');
this._lastWitnessSize = witnessSize + 2;
if (!writer)
bw = bw.render();
return bw;
return new RawTX(bw.written - offset, witnessSize + 2);
};
/**
@ -2400,19 +2422,12 @@ TX.prototype.frameWitness = function frameWitness(writer) {
* @returns {Boolean}
*/
TX.isWitness = function isWitness(data) {
if (Buffer.isBuffer(data)) {
if (data.length < 6)
return false;
return data[4] === 0 && data[5] !== 0;
}
if (data.left() < 6)
TX.isWitness = function isWitness(br) {
if (br.left() < 6)
return false;
return data.data[data.offset + 4] === 0
&& data.data[data.offset + 5] !== 0;
return br.data[br.offset + 4] === 0
&& br.data[br.offset + 5] !== 0;
};
/**
@ -2426,13 +2441,13 @@ TX.isWitness = function isWitness(data) {
* @returns {Buffer}
*/
TX.prototype.toExtended = function toExtended(saveCoins, writer) {
var bw = BufferWriter(writer);
TX.prototype.toExtended = function toExtended(saveCoins) {
var bw = new BufferWriter();
var height = this.height;
var index = this.index;
var i, input, field, bit, oct;
this.toRaw(bw);
this.toWriter(bw);
bw.writeU32(this.ps);
@ -2469,14 +2484,11 @@ TX.prototype.toExtended = function toExtended(saveCoins, writer) {
continue;
}
input.coin.toRaw(bw);
input.coin.toWriter(bw);
}
}
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2487,10 +2499,10 @@ TX.prototype.toExtended = function toExtended(saveCoins, writer) {
*/
TX.prototype.fromExtended = function fromExtended(data, saveCoins) {
var br = BufferReader(data);
var br = new BufferReader(data);
var i, input, coin, field, bit, oct, spent;
this.fromRaw(br);
this.fromReader(br);
this.ps = br.readU32();
@ -2520,7 +2532,7 @@ TX.prototype.fromExtended = function fromExtended(data, saveCoins) {
if (spent)
continue;
coin = Coin.fromRaw(br);
coin = Coin.fromReader(br);
coin.hash = input.prevout.hash;
coin.index = input.prevout.index;
@ -2570,9 +2582,10 @@ TX.isTX = function isTX(obj) {
* Helpers
*/
function TXSizes() {
this.total = 0;
this.witness = 0;
function RawTX(total, witness) {
this.data = null;
this.total = total;
this.witness = witness;
}
/*

View File

@ -7,12 +7,13 @@
'use strict';
var assert = require('assert');
var BN = require('bn.js');
var constants = require('../protocol/constants');
var util = require('../utils/util');
var encoding = require('./encoding');
var BufferReader = require('../utils/reader');
var BufferWriter = require('../utils/writer');
var assert = require('assert');
var opcodes = constants.opcodes;
/**
@ -30,45 +31,160 @@ function Opcode(value, data) {
if (!(this instanceof Opcode))
return new Opcode(value, data);
this.value = value;
this.value = value || 0;
this.data = data || null;
}
/**
* Encode the opcode to a buffer writer.
* @param {BufferWriter} bw
*/
Opcode.prototype.toWriter = function toWriter(bw) {
if (this.value === -1)
throw new Error('Cannot reserialize a parse error.');
if (!this.data) {
bw.writeU8(this.value);
return bw;
}
if (this.value <= 0x4b) {
assert(this.value === this.data.length);
bw.writeU8(this.value);
bw.writeBytes(this.data);
return bw;
}
switch (this.value) {
case opcodes.OP_PUSHDATA1:
bw.writeU8(this.value);
bw.writeU8(this.data.length);
bw.writeBytes(this.data);
break;
case opcodes.OP_PUSHDATA2:
bw.writeU8(this.value);
bw.writeU16(this.data.length);
bw.writeBytes(this.data);
break;
case opcodes.OP_PUSHDATA4:
bw.writeU8(this.value);
bw.writeU32(this.data.length);
bw.writeBytes(this.data);
break;
default:
throw new Error('Unknown pushdata opcode.');
}
return bw;
};
/**
* Encode the opcode.
* @returns {Buffer}
*/
Opcode.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
return this.toWriter(new BufferWriter()).render();
};
if (this.value === -1)
throw new Error('Cannot reserialize a parse error.');
/**
* Inject properties from buffer reader.
* @param {BufferReader} br
* @private
*/
if (this.data) {
if (this.value <= 0x4b) {
bw.writeU8(this.data.length);
bw.writeBytes(this.data);
} else if (this.value === opcodes.OP_PUSHDATA1) {
bw.writeU8(opcodes.OP_PUSHDATA1);
bw.writeU8(this.data.length);
bw.writeBytes(this.data);
} else if (this.value === opcodes.OP_PUSHDATA2) {
bw.writeU8(opcodes.OP_PUSHDATA2);
bw.writeU16(this.data.length);
bw.writeBytes(this.data);
} else if (this.value === opcodes.OP_PUSHDATA4) {
bw.writeU8(opcodes.OP_PUSHDATA4);
bw.writeU32(this.data.length);
bw.writeBytes(this.data);
} else {
throw new Error('Unknown pushdata opcode.');
Opcode.prototype.fromReader = function fromReader(br) {
var op = br.readU8();
var size;
if (op >= 0x01 && op <= 0x4b) {
if (br.left() < op) {
this.value = -1;
return this;
}
} else {
bw.writeU8(this.value);
this.value = op;
this.data = br.readBytes(op);
return this;
}
return bw.render();
switch (op) {
case opcodes.OP_PUSHDATA1:
if (br.left() < 1) {
this.value = -1;
break;
}
size = br.readU8();
if (br.left() < size) {
this.value = -1;
break;
}
this.value = op;
this.data = br.readBytes(size);
break;
case opcodes.OP_PUSHDATA2:
if (br.left() < 2) {
this.value = -1;
break;
}
size = br.readU16();
if (br.left() < size) {
this.value = -1;
break;
}
this.value = op;
this.data = br.readBytes(size);
break;
case opcodes.OP_PUSHDATA4:
if (br.left() < 4) {
this.value = -1;
break;
}
size = br.readU32();
if (br.left() < size) {
this.value = -1;
break;
}
this.value = op;
this.data = br.readBytes(size);
break;
default:
this.value = op;
break;
}
return this;
};
/**
* Inject properties from serialized data.
* @private
* @param {Buffer} data
* @returns {Opcode}
*/
Opcode.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Instantiate opcode from buffer reader.
* @param {BufferReader} br
* @returns {Opcode}
*/
Opcode.fromReader = function fromReader(br) {
return new Opcode().fromReader(br);
};
/**
* Instantiate opcode from serialized data.
* @param {Buffer} data
* @returns {Opcode}
*/
Opcode.fromRaw = function fromRaw(data) {
return new Opcode().fromRaw(data);
};
/**

View File

@ -129,7 +129,7 @@ Script.prototype.toArray = function toArray() {
Script.prototype.fromArray = function fromArray(code) {
assert(Array.isArray(code));
this.code = Script.parseArray(code);
this.raw = Script.encode(this.code);
this.compile();
return this;
};
@ -186,7 +186,27 @@ Script.prototype.toASM = function toASM(decode) {
*/
Script.prototype.compile = function compile() {
this.raw = Script.encode(this.code);
var bw = new BufferWriter();
var i, op;
for (i = 0; i < this.code.length; i++) {
op = this.code[i];
op.toWriter(bw);
}
this.raw = bw.render();
return this;
};
/**
* Write the script to a buffer writer.
* @param {BufferWriter} bw
*/
Script.prototype.toWriter = function toWriter(bw) {
bw.writeVarBytes(this.raw);
return bw;
};
/**
@ -195,11 +215,7 @@ Script.prototype.compile = function compile() {
* @returns {Buffer|String} Serialized script.
*/
Script.prototype.toRaw = function toRaw(writer) {
if (writer) {
writer.writeVarBytes(this.raw);
return writer;
}
Script.prototype.toRaw = function toRaw() {
return this.raw;
};
@ -1401,7 +1417,7 @@ Script.prototype.removeData = function removeData(data) {
for (i = index.length - 1; i >= 0; i--)
this.code.splice(index[i], 1);
this.raw = Script.encode(this.code);
this.compile();
return index.length;
};
@ -1478,14 +1494,11 @@ Script.isMinimal = function isMinimal(data, opcode, flags) {
*/
Script.isCode = function isCode(raw) {
var i, op, code;
var script = Script.fromRaw(raw);
var i, op;
assert(Buffer.isBuffer(raw));
code = Script.decode(raw);
for (i = 0; i < code.length; i++) {
op = code[i];
for (i = 0; i < script.code.length; i++) {
op = script.code[i];
if (op.data)
continue;
@ -2430,7 +2443,8 @@ Script.prototype.getCoinbaseFlags = function getCoinbaseFlags() {
else
nonce = -1;
flags = Script.encode(this.code.slice(index));
flags = Script.fromArray(this.code.slice(index));
flags = flags.toRaw();
text = flags.toString('utf8');
text = text.replace(/[\u0000-\u0019\u007f-\u00ff]/g, '');
@ -3439,6 +3453,16 @@ Script.sign = function sign(msg, key, type) {
return bw.render();
};
/**
* Inject properties from buffer reader.
* @private
* @param {BufferReader} br
*/
Script.prototype.fromReader = function fromReader(br) {
return this.fromRaw(br.readVarBytes());
};
/**
* Inject properties from serialized data.
* @private
@ -3446,15 +3470,27 @@ Script.sign = function sign(msg, key, type) {
*/
Script.prototype.fromRaw = function fromRaw(data) {
if (data instanceof BufferReader)
data = data.readVarBytes();
var br = new BufferReader(data, true);
this.raw = data;
this.code = Script.decode(data);
while (br.left())
this.code.push(Opcode.fromReader(br));
return this;
};
/**
* Create a script from buffer reader.
* @param {BufferReader} br
* @param {String?} enc - Either `"hex"` or `null`.
* @returns {Script}
*/
Script.fromReader = function fromReader(br) {
return new Script().fromReader(br);
};
/**
* Create a script from a serialized buffer.
* @param {Buffer|String} data - Serialized script.
@ -3468,127 +3504,6 @@ Script.fromRaw = function fromRaw(data, enc) {
return new Script().fromRaw(data);
};
/**
* Decode a serialized script into script code.
* Note that the serialized script must _not_
* include the varint size before it. Parse
* errors will output an opcode with a value
* of -1.
*
* @param {Buffer} raw - Serialized script.
* @returns {Opcode[]} Script code.
*/
Script.decode = function decode(raw) {
var br = new BufferReader(raw, true);
var code = [];
var op, size, data;
assert(Buffer.isBuffer(raw));
while (br.left()) {
op = br.readU8();
if (op >= 0x01 && op <= 0x4b) {
if (br.left() < op) {
code.push(new Opcode(-1));
break;
}
data = br.readBytes(op);
code.push(new Opcode(op, data));
} else if (op === opcodes.OP_PUSHDATA1) {
if (br.left() < 1) {
code.push(new Opcode(-1));
break;
}
size = br.readU8();
if (br.left() < size) {
code.push(new Opcode(-1));
break;
}
data = br.readBytes(size);
code.push(new Opcode(op, data));
} else if (op === opcodes.OP_PUSHDATA2) {
if (br.left() < 2) {
code.push(new Opcode(-1));
break;
}
size = br.readU16();
if (br.left() < size) {
code.push(new Opcode(-1));
break;
}
data = br.readBytes(size);
code.push(new Opcode(op, data));
} else if (op === opcodes.OP_PUSHDATA4) {
if (br.left() < 4) {
code.push(new Opcode(-1));
break;
}
size = br.readU32();
if (br.left() < size) {
code.push(new Opcode(-1));
break;
}
data = br.readBytes(size);
code.push(new Opcode(op, data));
} else {
code.push(new Opcode(op));
}
}
return code;
};
/**
* Encode and serialize script code. This will _not_
* include the varint size at the start.
* @param {Array} code - Script code.
* @returns {Buffer} Serialized script.
*/
Script.encode = function encode(code, writer) {
var bw = new BufferWriter(writer);
var i, op;
assert(Array.isArray(code));
for (i = 0; i < code.length; i++) {
op = code[i];
if (op.value === -1)
throw new Error('Cannot reserialize a parse error.');
if (op.data) {
if (op.value <= 0x4b) {
bw.writeU8(op.data.length);
bw.writeBytes(op.data);
} else if (op.value === opcodes.OP_PUSHDATA1) {
bw.writeU8(opcodes.OP_PUSHDATA1);
bw.writeU8(op.data.length);
bw.writeBytes(op.data);
} else if (op.value === opcodes.OP_PUSHDATA2) {
bw.writeU8(opcodes.OP_PUSHDATA2);
bw.writeU16(op.data.length);
bw.writeBytes(op.data);
} else if (op.value === opcodes.OP_PUSHDATA4) {
bw.writeU8(opcodes.OP_PUSHDATA4);
bw.writeU32(op.data.length);
bw.writeBytes(op.data);
} else {
throw new Error('Unknown pushdata opcode.');
}
continue;
}
bw.writeU8(op.value);
}
if (!writer)
bw = bw.render();
return bw;
};
/**
* Convert an array of Buffers and
* Numbers into an array of Opcodes.

View File

@ -299,13 +299,11 @@ Witness.prototype.indexOf = function indexOf(data) {
};
/**
* Encode the witness to a Buffer.
* @param {String} enc - Encoding, either `'hex'` or `null`.
* @returns {Buffer|String} Serialized script.
* Write witness to a buffer writer.
* @param {BufferWriter} bw
*/
Witness.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
Witness.prototype.toWriter = function toWriter(bw) {
var i;
bw.writeVarint(this.items.length);
@ -313,12 +311,19 @@ Witness.prototype.toRaw = function toRaw(writer) {
for (i = 0; i < this.items.length; i++)
bw.writeVarBytes(this.items[i]);
if (!writer)
bw = bw.render();
return bw;
};
/**
* Encode the witness to a Buffer.
* @param {String} enc - Encoding, either `'hex'` or `null`.
* @returns {Buffer|String} Serialized script.
*/
Witness.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
/**
* Convert witness to a hex string.
* @returns {String}
@ -513,13 +518,12 @@ Witness.encodeItem = function encodeItem(data) {
};
/**
* Inject properties from serialized data.
* Inject properties from buffer reader.
* @private
* @param {Buffer} data
* @param {BufferReader} br
*/
Witness.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
Witness.prototype.fromReader = function fromReader(br) {
var chunkCount = br.readVarint();
var i;
@ -530,7 +534,26 @@ Witness.prototype.fromRaw = function fromRaw(data) {
};
/**
* Create a Witness from a serialized buffer.
* Inject properties from serialized data.
* @private
* @param {Buffer} data
*/
Witness.prototype.fromRaw = function fromRaw(data) {
return this.fromReader(new BufferReader(data));
};
/**
* Create a witness from a buffer reader.
* @param {BufferReader} br
*/
Witness.fromReader = function fromReader(br) {
return new Witness().fromReader(br);
};
/**
* Create a witness from a serialized buffer.
* @param {Buffer|String} data - Serialized witness.
* @param {String?} enc - Either `"hex"` or `null`.
* @returns {Witness}

View File

@ -29,113 +29,96 @@
'use strict';
var assert = require('assert');
var BufferReader = require('./reader');
var ASN1 = exports;
ASN1.parseTag = function parseTag(br) {
var tag = br.readU8();
var primitive = (tag & 0x20) === 0;
/*
* Primitives
*/
ASN1.readTag = function readTag(br) {
var type = br.readU8();
var primitive = (type & 0x20) === 0;
var oct;
if ((tag & 0x1f) === 0x1f) {
oct = tag;
tag = 0;
if ((type & 0x1f) === 0x1f) {
oct = type;
type = 0;
while ((oct & 0x80) === 0x80) {
oct = br.readU8();
tag <<= 7;
tag |= oct & 0x7f;
type <<= 7;
type |= oct & 0x7f;
}
} else {
tag &= 0x1f;
type &= 0x1f;
}
return {
type: type,
primitive: primitive,
tag: tag,
len: ASN1.parseLen(br, primitive)
size: ASN1.readSize(br, primitive)
};
};
ASN1.parseLen = function parseLen(br, primitive) {
var len = br.readU8();
var num, i, j;
ASN1.readSize = function readSize(br, primitive) {
var size = br.readU8();
var bytes, i, j;
// Indefinite form
if (!primitive && len === 0x80)
return null;
if (!primitive && size === 0x80)
throw new Error('Indefinite size.');
// Definite form
if ((len & 0x80) === 0) {
if ((size & 0x80) === 0) {
// Short form
return len;
return size;
}
// Long form
num = len & 0x7f;
assert(num < 4, 'length octect is too long');
bytes = size & 0x7f;
len = 0;
for (i = 0; i < num; i++) {
len <<= 8;
if (bytes > 3)
throw new Error('Length octet is too long.');
size = 0;
for (i = 0; i < bytes; i++) {
size <<= 8;
j = br.readU8();
len |= j;
size |= j;
}
return len;
return size;
};
ASN1.parseCert = function parseCert(data) {
var d = BufferReader(data);
var br;
d.start();
br = BufferReader(ASN1.parseSeq(d));
return {
tbs: ASN1.parseTBS(br),
sigAlg: ASN1.parseAlgIdent(br),
sig: ASN1.parseBitstr(br),
raw: d.endData(true)
};
ASN1.readSeq = function readSeq(br) {
var tag = ASN1.implicit(br, 0x10);
return br.readBytes(tag.size);
};
ASN1.parseTBS = function parseTBS(data) {
var d = BufferReader(data);
var br;
d.start();
br = BufferReader(ASN1.parseSeq(d));
return {
version: ASN1.parseExplicitInt(br, 0, true),
serial: ASN1.parseInt(br),
sig: ASN1.parseAlgIdent(br),
issuer: ASN1.parseName(br),
validity: ASN1.parseValidity(br),
subject: ASN1.parseName(br),
pubkey: ASN1.parsePubkey(br),
raw: d.endData(true)
};
ASN1.implicit = function implicit(br, type) {
var tag = ASN1.readTag(br);
if (tag.type !== type)
throw new Error('Unexpected tag: ' + tag.type + '.');
return tag;
};
ASN1.parseSeq = function parseSeq(data) {
var br = BufferReader(data);
var tag = ASN1.parseTag(br);
assert.equal(tag.tag, 0x10); // seq
return br.readBytes(tag.len, true);
ASN1.explicit = function explicit(br, type) {
var offset = br.offset;
var tag = ASN1.readTag(br);
if (tag.type !== type) {
br.offset = offset;
return false;
}
return true;
};
ASN1.parseInt = function parseInt(data, readNum) {
var br = BufferReader(data);
var tag = ASN1.parseTag(br);
var num;
ASN1.seq = function seq(br) {
return new BufferReader(ASN1.readSeq(br), true);
};
assert.equal(tag.tag, 0x02); // int
num = br.readBytes(tag.len, true);
ASN1.readInt = function readInt(br, readNum) {
var tag = ASN1.implicit(br, 0x02);
var num = br.readBytes(tag.size);
if (readNum)
return num.readUIntBE(0, num.length);
@ -143,30 +126,28 @@ ASN1.parseInt = function parseInt(data, readNum) {
return num;
};
ASN1.parseExplicitInt = function parseExplicitInt(data, i, readNum) {
var br = BufferReader(data);
var off = br.offset;
var tag = ASN1.parseTag(br);
if (tag.tag !== i) {
br.seek(-(br.offset - off));
ASN1.readExplicitInt = function readExplicitInt(br, type, readNum) {
if (!ASN1.explicit(br, type))
return -1;
}
return ASN1.parseInt(br, readNum);
return ASN1.readInt(br, readNum);
};
ASN1.parseBitstr = function parseBitstr(data) {
var br = BufferReader(data);
var tag = ASN1.parseTag(br);
assert.equal(tag.tag, 0x03); // bitstr
return ASN1.alignBitstr(br.readBytes(tag.len, true));
ASN1.readBitstr = function readBitstr(br) {
var tag = ASN1.implicit(br, 0x03);
var str = br.readBytes(tag.size);
return ASN1.alignBitstr(str);
};
ASN1.parseString = function parseString(data) {
var br = BufferReader(data);
var tag = ASN1.parseTag(br);
switch (tag.tag) {
ASN1.readString = function readString(br) {
var tag = ASN1.readTag(br);
var str;
switch (tag.type) {
case 0x03: // bitstr
return ASN1.alignBitstr(br.readBytes(tag.len, true));
str = br.readBytes(tag.size);
return ASN1.alignBitstr(str);
// Note:
// Fuck all these.
case 0x04: // octstr
case 0x12: // numstr
case 0x13: // prinstr
@ -180,9 +161,9 @@ ASN1.parseString = function parseString(data) {
case 0x1c: // unistr
case 0x1d: // charstr
case 0x1e: // bmpstr
return br.readString('utf8', tag.len);
return br.readString('utf8', tag.size);
default:
assert(false, 'Bad string.');
throw new Error('Unexpected tag: ' + tag.type + '.');
}
};
@ -207,52 +188,83 @@ ASN1.alignBitstr = function(data) {
return out;
};
ASN1.parsePubkey = function parsePubkey(data) {
var br = BufferReader(data);
br = BufferReader(ASN1.parseSeq(br));
/*
* Certificates
*/
ASN1.readCert = function readCert(br) {
var buf = br;
buf.start();
br = ASN1.seq(buf);
return {
alg: ASN1.parseAlgIdent(br),
pubkey: ASN1.parseBitstr(br)
tbs: ASN1.readTBS(br),
sigAlg: ASN1.readAlgIdent(br),
sig: ASN1.readBitstr(br),
raw: buf.endData(true)
};
};
ASN1.parseName = function parseName(data) {
var br = BufferReader(data);
var values = [];
var tag;
ASN1.readTBS = function readTBS(br) {
var buf = br;
br = BufferReader(ASN1.parseSeq(br));
buf.start();
br = ASN1.seq(buf);
return {
version: ASN1.readExplicitInt(br, 0x00, true),
serial: ASN1.readInt(br),
sig: ASN1.readAlgIdent(br),
issuer: ASN1.readName(br),
validity: ASN1.readValidity(br),
subject: ASN1.readName(br),
pubkey: ASN1.readPubkey(br),
raw: buf.endData(true)
};
};
ASN1.readPubkey = function readPubkey(br) {
br = ASN1.seq(br);
return {
alg: ASN1.readAlgIdent(br),
pubkey: ASN1.readBitstr(br)
};
};
ASN1.readName = function readName(br) {
var values = [];
br = ASN1.seq(br);
while (br.left()) {
tag = ASN1.parseTag(br);
assert.equal(tag.tag, 0x11); // set
tag = ASN1.parseTag(br);
assert.equal(tag.tag, 0x10); // seq
ASN1.implicit(br, 0x11); // set
ASN1.implicit(br, 0x10); // seq
values.push({
type: ASN1.parseOID(br),
value: ASN1.parseString(br)
type: ASN1.readOID(br),
value: ASN1.readString(br)
});
}
return values;
};
ASN1.parseValidity = function parseValidity(data) {
var br = BufferReader(data);
br = BufferReader(ASN1.parseSeq(br));
ASN1.readValidity = function readValidity(br) {
br = ASN1.seq(br);
return {
notBefore: ASN1.parseTime(br),
notAfter: ASN1.parseTime(br)
notBefore: ASN1.readTime(br),
notAfter: ASN1.readTime(br)
};
};
ASN1.parseTime = function parseTime(data) {
var br = BufferReader(data);
var tag = ASN1.parseTag(br);
var str = br.readString('ascii', tag.len);
ASN1.readTime = function readTime(br) {
var tag = ASN1.readTag(br);
var str = br.readString('ascii', tag.size);
var year, mon, day, hour, min, sec;
switch (tag.tag) {
switch (tag.type) {
case 0x17: // utctime
year = str.slice(0, 2) | 0;
mon = str.slice(2, 4) | 0;
@ -274,25 +286,24 @@ ASN1.parseTime = function parseTime(data) {
sec = str.slice(12, 14) | 0;
break;
default:
assert(false);
break;
throw new Error('Unexpected tag: ' + tag.type + '.');
}
return Date.UTC(year, mon - 1, day, hour, min, sec, 0) / 1000;
};
ASN1.parseOID = function parseOID(data) {
var br = BufferReader(data);
var tag = ASN1.parseTag(br);
ASN1.readOID = function readOID(br) {
var tag = ASN1.implicit(br, 0x06);
var data = br.readBytes(tag.size);
return ASN1.formatOID(data);
};
ASN1.formatOID = function formatOID(data) {
var br = new BufferReader(data);
var ids = [];
var ident = 0;
var subident = 0;
var objid, result, first, second;
assert.equal(tag.tag, 0x06); // objid
objid = br.readBytes(tag.len, true);
br = BufferReader(objid);
var result, first, second;
while (br.left()) {
subident = br.readU8();
@ -314,17 +325,17 @@ ASN1.parseOID = function parseOID(data) {
return result.join('.');
};
ASN1.parseAlgIdent = function parseAlgIdent(data) {
var br = BufferReader(data);
ASN1.readAlgIdent = function readAlgIdent(br) {
var params = null;
var alg;
var alg, tag;
br = BufferReader(ASN1.parseSeq(br));
br = ASN1.seq(br);
alg = ASN1.parseOID(br);
alg = ASN1.readOID(br);
if (br.left() > 0) {
params = br.readBytes(ASN1.parseTag(br).len, true);
tag = ASN1.readTag(br);
params = br.readBytes(tag.size);
if (params.length === 0)
params = null;
}
@ -335,27 +346,49 @@ ASN1.parseAlgIdent = function parseAlgIdent(data) {
};
};
ASN1.parseRSAPublic = function parseRSAPublic(data) {
var br = BufferReader(data);
br = BufferReader(ASN1.parseSeq(br));
/*
* RSA
*/
ASN1.readRSAPublic = function readRSAPublic(br) {
br = ASN1.seq(br);
return {
modulus: ASN1.parseInt(br),
publicExponent: ASN1.parseInt(br)
modulus: ASN1.readInt(br),
publicExponent: ASN1.readInt(br)
};
};
ASN1.parseRSAPrivate = function parseRSAPrivate(data) {
var br = BufferReader(data);
br = BufferReader(ASN1.parseSeq(br));
ASN1.readRSAPrivate = function readRSAPrivate(br) {
br = ASN1.seq(br);
return {
version: ASN1.parseInt(br, true),
modulus: ASN1.parseInt(br),
publicExponent: ASN1.parseInt(br),
privateExponent: ASN1.parseInt(br),
prime1: ASN1.parseInt(br),
prime2: ASN1.parseInt(br),
exponent1: ASN1.parseInt(br),
exponent2: ASN1.parseInt(br),
coefficient: ASN1.parseInt(br)
version: ASN1.readInt(br, true),
modulus: ASN1.readInt(br),
publicExponent: ASN1.readInt(br),
privateExponent: ASN1.readInt(br),
prime1: ASN1.readInt(br),
prime2: ASN1.readInt(br),
exponent1: ASN1.readInt(br),
exponent2: ASN1.readInt(br),
coefficient: ASN1.readInt(br)
};
};
/*
* Public
*/
ASN1.parseRSAPublic = function parseRSAPublic(data) {
return ASN1.readRSAPublic(new BufferReader(data, true));
};
ASN1.parseRSAPrivate = function parseRSAPrivate(data) {
return ASN1.readRSAPrivate(new BufferReader(data, true));
};
ASN1.parseCert = function parseCert(data) {
return ASN1.readCert(new BufferReader(data, true));
};
ASN1.parseTBS = function parseTBS(data) {
return ASN1.readTBS(new BufferReader(data, true));
};

View File

@ -178,18 +178,15 @@ Bloom.fromRate = function fromRate(items, rate, update) {
* @returns {Buffer}
*/
Bloom.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
Bloom.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeVarBytes(this.filter);
bw.writeU32(this.n);
bw.writeU32(this.tweak);
bw.writeU8(this.update);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -199,7 +196,7 @@ Bloom.prototype.toRaw = function toRaw(writer) {
*/
Bloom.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
var br = new BufferReader(data);
this.filter = br.readVarBytes();
this.n = br.readU32();

View File

@ -11,6 +11,10 @@ var assert = require('assert');
var BufferReader = require('../utils/reader');
var BufferWriter = require('../utils/writer');
/*
* Constants
*/
var wireType = {
VARINT: 0,
FIXED64: 1,
@ -20,11 +24,15 @@ var wireType = {
FIXED32: 5
};
/**
* ProtoReader
* @constructor
*/
function ProtoReader(data, zeroCopy) {
if (data instanceof ProtoReader)
return data;
if (!(this instanceof ProtoReader))
return new ProtoReader(data, zeroCopy);
BufferReader.call(this, data, zeroCopy);
}
@ -92,72 +100,105 @@ ProtoReader.prototype.nextTag = function nextTag() {
ProtoReader.prototype.readField = function readField(tag, opt) {
var offset = this.offset;
var header = this.readVarint();
var value, data, group, field;
var field = new Field(header);
var inner;
if (tag != null && (header >>> 3) !== tag) {
if (tag != null && field.tag !== tag) {
assert(opt, 'Non-optional field not present.');
this.offset = offset;
return;
return null;
}
switch (header & 7) {
switch (field.type) {
case wireType.VARINT:
value = this.readVarint();
field.value = this.readVarint();
break;
case wireType.FIXED64:
value = this.readU64();
field.value = this.readU64();
break;
case wireType.DELIMITED:
data = this.readVarBytes();
field.data = this.readVarBytes();
break;
case wireType.START_GROUP:
group = [];
field.group = [];
for (;;) {
field = this.readField();
if (field.type === wireType.END_GROUP)
inner = this.readField();
if (inner.type === wireType.END_GROUP)
break;
group.push(field);
field.group.push(inner);
}
break;
case wireType.END_GROUP:
assert(false, 'Unexpected end group.');
break;
case wireType.FIXED32:
value = this.readU32();
field.value = this.readU32();
break;
default:
assert(false, 'Bad wire type.');
break;
}
return {
size: this.offset - offset,
header: header,
tag: header >>> 3,
type: header & 7,
value: value,
data: data,
group: group
};
field.size = this.offset - offset;
return field;
};
function ProtoWriter(options) {
if (options instanceof ProtoWriter)
return options;
/**
* ProtoWriter
* @constructor
*/
function ProtoWriter() {
if (!(this instanceof ProtoWriter))
return new ProtoWriter(options);
return new ProtoWriter();
BufferWriter.call(this, options);
BufferWriter.call(this);
}
util.inherits(ProtoWriter, BufferWriter);
ProtoWriter.prototype.writeVarint = function writeVarint(num) {
var size = exports.sizeVarint(num);
var buf = new Buffer(size);
exports.writeVarint(buf, num, 0);
this.writeBytes(buf);
var value;
// Avoid an extra allocation until
// we make bufferwriter more hackable.
// More insanity here...
switch (size) {
case 6:
value = exports.slipVarint(num);
this.writeU32BE(value / 0x10000 | 0);
this.writeU16BE(value & 0xffff);
break;
case 5:
value = exports.slipVarint(num);
this.writeU32BE(value / 0x100 | 0);
this.writeU8(value & 0xff);
break;
case 4:
value = exports.slipVarint(num);
this.writeU32BE(value);
break;
case 3:
value = exports.slipVarint(num);
this.writeU16BE(value >> 8);
this.writeU8(value & 0xff);
break;
case 2:
value = exports.slipVarint(num);
this.writeU16BE(value);
break;
case 1:
value = exports.slipVarint(num);
this.writeU8(value);
break;
default:
value = new Buffer(size);
exports.writeVarint(value, num, 0);
this.writeBytes(value);
break;
}
};
ProtoWriter.prototype.writeFieldVarint = function writeFieldVarint(tag, value) {
@ -189,6 +230,10 @@ ProtoWriter.prototype.writeFieldString = function writeFieldString(tag, data, en
this.writeFieldBytes(tag, data);
};
/*
* Encoding
*/
exports.readVarint = function readVarint(data, off) {
var num = 0;
var ch = 0x80;
@ -199,7 +244,9 @@ exports.readVarint = function readVarint(data, off) {
num = 0;
break;
}
ch = data[off++];
// Optimization for javascript insanity.
switch (size) {
case 0:
@ -215,12 +262,13 @@ exports.readVarint = function readVarint(data, off) {
num += (ch & 0x7f) * Math.pow(2, 7 * size);
break;
}
size++;
assert(size < 7, 'Number exceeds 2^53-1.');
}
assert(util.isSafeInteger(num), 'Number exceeds 2^53-1.');
return { size: size, value: num };
return new Varint(size, num);
};
exports.writeVarint = function writeVarint(data, num, off) {
@ -242,6 +290,28 @@ exports.writeVarint = function writeVarint(data, num, off) {
return off;
};
exports.slipVarint = function slipVarint(num) {
var data = 0;
var size = 0;
var ch;
assert(util.isSafeInteger(num), 'Number exceeds 2^53-1.');
do {
assert(size < 7);
ch = num & 0x7f;
num -= num % 0x80;
num /= 0x80;
if (num !== 0)
ch |= 0x80;
data *= 256;
data += ch;
size++;
} while (num > 0);
return data;
};
exports.sizeVarint = function sizeVarint(num) {
var size = 0;
@ -256,5 +326,27 @@ exports.sizeVarint = function sizeVarint(num) {
return size;
};
/*
* Helpers
*/
function Field(header) {
this.tag = header >>> 3;
this.type = header & 7;
this.size = 0;
this.value = 0;
this.data = null;
this.group = null;
}
function Varint(size, value) {
this.size = size;
this.value = value;
}
/*
* Expose
*/
exports.ProtoReader = ProtoReader;
exports.ProtoWriter = ProtoWriter;

View File

@ -7,9 +7,9 @@
'use strict';
var assert = require('assert');
var encoding = require('./encoding');
var crypto = require('../crypto/crypto');
var assert = require('assert');
/**
* An object that allows reading of buffers in a sane manner.
@ -22,15 +22,14 @@ var assert = require('assert');
*/
function BufferReader(data, zeroCopy) {
if (data instanceof BufferReader)
return data;
if (!(this instanceof BufferReader))
return new BufferReader(data, zeroCopy);
assert(Buffer.isBuffer(data), 'Must pass a Buffer.');
this.data = data;
this.offset = 0;
this.zeroCopy = zeroCopy;
this.zeroCopy = zeroCopy || false;
this.stack = [];
}

View File

@ -56,12 +56,9 @@ var FILL = 24;
* @param {(BufferWriter|Object)?} options
*/
function BufferWriter(options) {
if (options instanceof BufferWriter)
return options;
function BufferWriter() {
if (!(this instanceof BufferWriter))
return new BufferWriter(options);
return new BufferWriter();
this.ops = [];
this.written = 0;

View File

@ -910,8 +910,8 @@ Account.prototype.toJSON = function toJSON(minimal) {
* @returns {Buffer}
*/
Account.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
Account.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i, key;
bw.writeVarString(this.name, 'ascii');
@ -933,10 +933,7 @@ Account.prototype.toRaw = function toRaw(writer) {
bw.writeBytes(key.toRaw());
}
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -445,8 +445,8 @@ MasterKey.prototype._encrypt = co(function* encrypt(passphrase, aes) {
* @returns {Buffer}
*/
MasterKey.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
MasterKey.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
if (this.encrypted) {
bw.writeU8(1);
@ -458,19 +458,13 @@ MasterKey.prototype.toRaw = function toRaw(writer) {
bw.writeU32(this.r);
bw.writeU32(this.p);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
}
bw.writeU8(0);
bw.writeVarBytes(this.key.toExtended());
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -175,8 +175,8 @@ Path.fromRaw = function fromRaw(data) {
* @returns {Buffer}
*/
Path.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
Path.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeU32(this.account);
bw.writeU8(this.keyType);
@ -206,10 +206,7 @@ Path.prototype.toRaw = function toRaw(writer) {
bw.write8(this.version);
bw.writeU8(this.type);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -77,18 +77,15 @@ ChainState.fromRaw = function fromRaw(data) {
* @returns {Buffer}
*/
ChainState.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
ChainState.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeU32(this.startHeight);
bw.writeHash(this.startHash);
bw.writeU32(this.height);
bw.writeU8(this.marked ? 1 : 0);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -202,17 +199,12 @@ BlockMeta.fromRaw = function fromRaw(data) {
* @returns {Buffer}
*/
BlockMeta.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
BlockMeta.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeHash(this.hash);
bw.writeU32(this.height);
bw.writeU32(this.ts);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -258,7 +250,7 @@ BlockMapRecord.prototype.fromRaw = function fromRaw(data) {
for (i = 0; i < count; i++) {
hash = br.readHash('hex');
tx = TXMapRecord.fromRaw(hash, br);
tx = TXMapRecord.fromReader(hash, br);
this.txs.push(tx);
this.index[tx.hash] = tx;
}
@ -283,8 +275,8 @@ BlockMapRecord.fromRaw = function fromRaw(height, data) {
* @returns {Buffer}
*/
BlockMapRecord.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
BlockMapRecord.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i, tx;
bw.writeU32(this.txs.length);
@ -292,13 +284,10 @@ BlockMapRecord.prototype.toRaw = function toRaw(writer) {
for (i = 0; i < this.txs.length; i++) {
tx = this.txs[i];
bw.writeHash(tx.hash);
tx.toRaw(bw);
tx.toWriter(bw);
}
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -369,13 +358,25 @@ TXMapRecord.prototype.remove = function remove(wid) {
return util.binaryRemove(this.wids, wid, cmp);
};
TXMapRecord.prototype.toRaw = function toRaw(writer) {
return serializeWallets(this.wids, writer);
TXMapRecord.prototype.toWriter = function toWriter(bw) {
return serializeWallets(bw, this.wids);
};
TXMapRecord.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
TXMapRecord.prototype.fromReader = function fromReader(br) {
this.wids = parseWallets(br);
return this;
};
TXMapRecord.prototype.fromRaw = function fromRaw(data) {
this.wids = parseWallets(data);
return this;
return this.fromReader(new BufferReader(data));
};
TXMapRecord.fromReader = function fromReader(hash, br) {
return new TXMapRecord(hash).fromReader(br);
};
TXMapRecord.fromRaw = function fromRaw(hash, data) {
@ -401,13 +402,25 @@ OutpointMapRecord.prototype.remove = function remove(wid) {
return util.binaryRemove(this.wids, wid, cmp);
};
OutpointMapRecord.prototype.toRaw = function toRaw(writer) {
return serializeWallets(this.wids, writer);
OutpointMapRecord.prototype.toWriter = function toWriter(bw) {
return serializeWallets(bw, this.wids);
};
OutpointMapRecord.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
OutpointMapRecord.prototype.fromReader = function fromReader(br) {
this.wids = parseWallets(br);
return this;
};
OutpointMapRecord.prototype.fromRaw = function fromRaw(data) {
this.wids = parseWallets(data);
return this;
return this.fromReader(new BufferReader(data));
};
OutpointMapRecord.fromReader = function fromReader(hash, index, br) {
return new OutpointMapRecord(hash, index).fromReader(br);
};
OutpointMapRecord.fromRaw = function fromRaw(hash, index, data) {
@ -432,13 +445,25 @@ PathMapRecord.prototype.remove = function remove(wid) {
return util.binaryRemove(this.wids, wid, cmp);
};
PathMapRecord.prototype.toRaw = function toRaw(writer) {
return serializeWallets(this.wids, writer);
PathMapRecord.prototype.toWriter = function toWriter(bw) {
return serializeWallets(bw, this.wids);
};
PathMapRecord.prototype.toRaw = function toRaw() {
return this.toWriter(new BufferWriter()).render();
};
PathMapRecord.prototype.fromReader = function fromReader(br) {
this.wids = parseWallets(br);
return this;
};
PathMapRecord.prototype.fromRaw = function fromRaw(data) {
this.wids = parseWallets(data);
return this;
return this.fromReader(new BufferReader(data));
};
PathMapRecord.fromReader = function fromReader(hash, br) {
return new PathMapRecord(hash).fromReader(br);
};
PathMapRecord.fromRaw = function fromRaw(hash, data) {
@ -457,8 +482,7 @@ function cmpid(a, b) {
return a.id - b.id;
}
function parseWallets(data) {
var br = new BufferReader(data);
function parseWallets(br) {
var count = br.readU32();
var wids = [];
var i;
@ -469,8 +493,7 @@ function parseWallets(data) {
return wids;
}
function serializeWallets(wids, writer) {
var bw = new BufferWriter(writer);
function serializeWallets(bw, wids) {
var i, wid;
bw.writeU32(wids.length);
@ -480,9 +503,6 @@ function serializeWallets(wids, writer) {
bw.writeU32(wid);
}
if (!writer)
bw = bw.render();
return bw;
}

View File

@ -2895,18 +2895,15 @@ TXDBState.prototype.toBalance = function toBalance() {
* @returns {Buffer}
*/
TXDBState.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
TXDBState.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeU64(this.tx);
bw.writeU64(this.coin);
bw.writeU64(this.unconfirmed);
bw.writeU64(this.confirmed);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -2985,8 +2982,8 @@ function Credit(coin, spent) {
*/
Credit.prototype.fromRaw = function fromRaw(data) {
var br = BufferReader(data);
this.coin.fromRaw(br);
var br = new BufferReader(data);
this.coin.fromReader(br);
this.spent = br.readU8() === 1;
return this;
};
@ -3006,16 +3003,11 @@ Credit.fromRaw = function fromRaw(data) {
* @returns {Buffer}
*/
Credit.prototype.toRaw = function toRaw(writer) {
var bw = BufferWriter(writer);
this.coin.toRaw(bw);
Credit.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
this.coin.toWriter(bw);
bw.writeU8(this.spent ? 1 : 0);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**
@ -3377,8 +3369,8 @@ BlockRecord.fromRaw = function fromRaw(data) {
* @returns {Buffer}
*/
BlockRecord.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
BlockRecord.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
var i;
bw.writeHash(this.hash);
@ -3390,10 +3382,7 @@ BlockRecord.prototype.toRaw = function toRaw(writer) {
for (i = 0; i < this.hashes.length; i++)
bw.writeHash(this.hashes[i]);
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -2440,8 +2440,8 @@ Wallet.prototype.toJSON = function toJSON(unsafe) {
* @returns {Buffer}
*/
Wallet.prototype.toRaw = function toRaw(writer) {
var bw = new BufferWriter(writer);
Wallet.prototype.toRaw = function toRaw() {
var bw = new BufferWriter();
bw.writeU32(this.network.magic);
bw.writeU32(this.wid);
@ -2453,10 +2453,7 @@ Wallet.prototype.toRaw = function toRaw(writer) {
bw.writeU32(this.tokenDepth);
bw.writeVarBytes(this.master.toRaw());
if (!writer)
bw = bw.render();
return bw;
return bw.render();
};
/**

View File

@ -33,7 +33,7 @@ Framer.prototype.packet = function _packet(packet) {
bw.writeU8(packet.cmd);
bw.seek(4);
packet.toRaw(bw);
packet.toWriter(bw);
bw.writeU8(0x0a);

View File

@ -53,7 +53,7 @@ Packet.id = 0;
Packet.prototype.cmd = -1;
Packet.prototype.toRaw = function toRaw() {
Packet.prototype.toWriter = function toWriter() {
throw new Error('Abstract method.');
};
@ -71,7 +71,7 @@ util.inherits(EventPacket, Packet);
EventPacket.prototype.cmd = packetTypes.EVENT;
EventPacket.prototype.toRaw = function toRaw(bw) {
EventPacket.prototype.toWriter = function toWriter(bw) {
bw.writeVarString(JSON.stringify(this.items), 'utf8');
};
@ -96,7 +96,7 @@ util.inherits(LogPacket, Packet);
LogPacket.prototype.cmd = packetTypes.LOG;
LogPacket.prototype.toRaw = function toRaw(bw) {
LogPacket.prototype.toWriter = function toWriter(bw) {
bw.writeVarString(this.text, 'utf8');
};
@ -121,7 +121,7 @@ util.inherits(ErrorPacket, Packet);
ErrorPacket.prototype.cmd = packetTypes.ERROR;
ErrorPacket.prototype.toRaw = function toRaw(bw) {
ErrorPacket.prototype.toWriter = function toWriter(bw) {
bw.writeVarString(this.error.message + '', 'utf8');
bw.writeVarString(this.error.stack + '', 'utf8');
bw.writeVarString((this.error.type || ''), 'utf8');
@ -150,7 +150,7 @@ util.inherits(ErrorResultPacket, Packet);
ErrorResultPacket.prototype.cmd = packetTypes.ERRORRESULT;
ErrorResultPacket.prototype.toRaw = function toRaw(bw) {
ErrorResultPacket.prototype.toWriter = function toWriter(bw) {
bw.writeVarString(this.error.message + '', 'utf8');
bw.writeVarString(this.error.stack + '', 'utf8');
bw.writeVarString((this.error.type || ''), 'utf8');
@ -180,16 +180,22 @@ util.inherits(VerifyPacket, Packet);
VerifyPacket.prototype.cmd = packetTypes.VERIFY;
VerifyPacket.prototype.toRaw = function(bw) {
VerifyPacket.prototype.toWriter = function(bw) {
frameTX(this.tx, bw);
bw.writeU32(this.flags);
bw.write32(this.flags != null ? this.flags : -1);
};
VerifyPacket.fromRaw = function fromRaw(TX, data) {
var br = new BufferReader(data, true);
var packet = new VerifyPacket();
packet.tx = parseTX(TX, br);
packet.flags = br.readU32();
packet.flags = br.read32();
if (packet.flags === -1)
packet.flags = null;
return packet;
};
@ -207,7 +213,7 @@ util.inherits(VerifyResultPacket, Packet);
VerifyResultPacket.prototype.cmd = packetTypes.VERIFYRESULT;
VerifyResultPacket.prototype.toRaw = function toRaw(bw) {
VerifyResultPacket.prototype.toWriter = function toWriter(bw) {
bw.writeU8(this.value ? 1 : 0);
};
@ -234,16 +240,16 @@ util.inherits(SignPacket, Packet);
SignPacket.prototype.cmd = packetTypes.SIGN;
SignPacket.prototype.toRaw = function toRaw(bw) {
SignPacket.prototype.toWriter = function toWriter(bw) {
var i, ring;
frameTX(this.tx, bw);
bw.writeU32(this.rings.length);
bw.writeVarint(this.rings.length);
for (i = 0; i < this.rings.length; i++) {
ring = this.rings[i];
bw.writeBytes(ring.toRaw());
ring.toWriter(bw);
}
bw.write8(this.type != null ? this.type : -1);
@ -256,10 +262,10 @@ SignPacket.fromRaw = function fromRaw(MTX, KeyRing, data) {
packet.tx = parseTX(MTX, br);
count = br.readU32();
count = br.readVarint();
for (i = 0; i < count; i++) {
ring = KeyRing.fromRaw(br);
ring = KeyRing.fromReader(br);
packet.rings.push(ring);
}
@ -300,7 +306,7 @@ SignResultPacket.fromTX = function fromTX(tx, total) {
return packet;
};
SignResultPacket.prototype.toRaw = function toRaw(bw) {
SignResultPacket.prototype.toWriter = function toWriter(bw) {
var i;
assert(this.script.length === this.witness.length);
@ -309,8 +315,8 @@ SignResultPacket.prototype.toRaw = function toRaw(bw) {
bw.writeVarint(this.script.length);
for (i = 0; i < this.script.length; i++) {
this.script[i].toRaw(bw);
this.witness[i].toRaw(bw);
this.script[i].toWriter(bw);
this.witness[i].toWriter(bw);
}
};
@ -337,8 +343,8 @@ SignResultPacket.fromRaw = function fromRaw(data) {
count = br.readVarint();
for (i = 0; i < count; i++) {
packet.script.push(Script.fromRaw(br));
packet.witness.push(Witness.fromRaw(br));
packet.script.push(Script.fromReader(br));
packet.witness.push(Witness.fromReader(br));
}
return packet;
@ -360,9 +366,9 @@ util.inherits(VerifyInputPacket, Packet);
VerifyInputPacket.prototype.cmd = packetTypes.VERIFYINPUT;
VerifyInputPacket.prototype.toRaw = function toRaw(bw) {
VerifyInputPacket.prototype.toWriter = function toWriter(bw) {
frameTX(this.tx, bw);
bw.writeU32(this.index);
bw.writeVarint(this.index);
bw.write32(this.flags != null ? this.flags : -1);
};
@ -371,7 +377,7 @@ VerifyInputPacket.fromRaw = function fromRaw(TX, data) {
var packet = new VerifyInputPacket();
packet.tx = parseTX(TX, br);
packet.index = br.readU32();
packet.index = br.readVarint();
packet.flags = br.read32();
if (packet.flags === -1)
@ -394,7 +400,7 @@ util.inherits(VerifyInputResultPacket, Packet);
VerifyInputResultPacket.prototype.cmd = packetTypes.VERIFYINPUTRESULT;
VerifyInputResultPacket.prototype.toRaw = function toRaw(bw) {
VerifyInputResultPacket.prototype.toWriter = function toWriter(bw) {
bw.writeU8(this.value ? 1 : 0);
};
@ -410,11 +416,11 @@ VerifyInputResultPacket.fromRaw = function fromRaw(data) {
* @constructor
*/
function SignInputPacket(tx, index, rings, type) {
function SignInputPacket(tx, index, ring, type) {
Packet.call(this);
this.tx = tx || null;
this.index = index;
this.rings = rings || [];
this.ring = ring || null;
this.type = type != null ? type : null;
}
@ -422,18 +428,19 @@ util.inherits(SignInputPacket, Packet);
SignInputPacket.prototype.cmd = packetTypes.SIGNINPUT;
SignInputPacket.prototype.toRaw = function toRaw(bw) {
var i, ring;
SignInputPacket.prototype.toWriter = function toWriter(bw) {
var input = this.tx.inputs[this.index];
frameTX(this.tx, bw);
bw.writeU32(this.index);
assert(input);
assert(input.coin);
bw.writeU32(this.rings.length);
this.tx.toWriter(bw);
bw.writeVarint(this.index);
for (i = 0; i < this.rings.length; i++) {
ring = this.rings[i];
bw.writeBytes(ring.toRaw());
}
bw.writeVarint(input.coin.value);
input.coin.script.toWriter(bw);
this.ring.toWriter(bw);
bw.write8(this.type != null ? this.type : -1);
};
@ -441,27 +448,33 @@ SignInputPacket.prototype.toRaw = function toRaw(bw) {
SignInputPacket.fromRaw = function fromRaw(MTX, KeyRing, data) {
var br = new BufferReader(data, true);
var packet = new SignInputPacket();
var i, count, ring;
var coin = new Coin();
var input;
packet.tx = parseTX(MTX, br);
packet.index = br.readU32();
packet.index = br.readVarint();
count = br.readU32();
coin.value = br.readVarint();
coin.script.fromReader(br);
for (i = 0; i < count; i++) {
ring = KeyRing.fromRaw(br);
packet.rings.push(ring);
}
packet.ring = KeyRing.fromReader(br);
packet.type = br.read8();
if (packet.type === -1)
packet.type = null;
input = packet.tx.inputs[packet.index];
assert(input);
coin.hash = input.prevout.hash;
coin.index = input.prevout.index;
input.coin = coin;
return packet;
};
/**
* SignInputResultPacket
* @constructor
@ -490,10 +503,10 @@ SignInputResultPacket.fromTX = function fromTX(tx, i, value) {
return packet;
};
SignInputResultPacket.prototype.toRaw = function toRaw(bw) {
SignInputResultPacket.prototype.toWriter = function toWriter(bw) {
bw.writeU8(this.value ? 1 : 0);
this.script.toRaw(bw);
this.witness.toRaw(bw);
this.script.toWriter(bw);
this.witness.toWriter(bw);
};
SignInputResultPacket.prototype.inject = function inject(tx, i) {
@ -507,8 +520,8 @@ SignInputResultPacket.fromRaw = function fromRaw(data) {
var br = new BufferReader(data, true);
var packet = new SignInputResultPacket();
packet.value = br.readU8() === 1;
packet.script = Script.fromRaw(br);
packet.witness = Witness.fromRaw(br);
packet.script = Script.fromReader(br);
packet.witness = Witness.fromReader(br);
return packet;
};
@ -529,7 +542,7 @@ util.inherits(ECVerifyPacket, Packet);
ECVerifyPacket.prototype.cmd = packetTypes.ECVERIFY;
ECVerifyPacket.prototype.toRaw = function(bw) {
ECVerifyPacket.prototype.toWriter = function(bw) {
bw.writeVarBytes(this.msg);
bw.writeVarBytes(this.sig);
bw.writeVarBytes(this.key);
@ -558,7 +571,7 @@ util.inherits(ECVerifyResultPacket, Packet);
ECVerifyResultPacket.prototype.cmd = packetTypes.ECVERIFYRESULT;
ECVerifyResultPacket.prototype.toRaw = function toRaw(bw) {
ECVerifyResultPacket.prototype.toWriter = function toWriter(bw) {
bw.writeU8(this.value ? 1 : 0);
};
@ -584,7 +597,7 @@ util.inherits(ECSignPacket, Packet);
ECSignPacket.prototype.cmd = packetTypes.ECSIGN;
ECSignPacket.prototype.toRaw = function(bw) {
ECSignPacket.prototype.toWriter = function(bw) {
bw.writeVarBytes(this.msg);
bw.writeVarBytes(this.key);
};
@ -611,7 +624,7 @@ util.inherits(ECSignResultPacket, Packet);
ECSignResultPacket.prototype.cmd = packetTypes.ECSIGNRESULT;
ECSignResultPacket.prototype.toRaw = function toRaw(bw) {
ECSignResultPacket.prototype.toWriter = function toWriter(bw) {
bw.writeVarBytes(this.sig);
};
@ -639,7 +652,7 @@ util.inherits(MinePacket, Packet);
MinePacket.prototype.cmd = packetTypes.MINE;
MinePacket.prototype.toRaw = function(bw) {
MinePacket.prototype.toWriter = function(bw) {
bw.writeBytes(this.data);
bw.writeBytes(this.target);
bw.writeU32(this.min);
@ -670,7 +683,7 @@ util.inherits(MineResultPacket, Packet);
MineResultPacket.prototype.cmd = packetTypes.MINERESULT;
MineResultPacket.prototype.toRaw = function toRaw(bw) {
MineResultPacket.prototype.toWriter = function toWriter(bw) {
bw.writeU32(this.nonce);
};
@ -702,7 +715,7 @@ util.inherits(ScryptPacket, Packet);
ScryptPacket.prototype.cmd = packetTypes.SCRYPT;
ScryptPacket.prototype.toRaw = function(bw) {
ScryptPacket.prototype.toWriter = function(bw) {
bw.writeVarBytes(this.passwd);
bw.writeVarBytes(this.salt);
bw.writeU32(this.N);
@ -737,7 +750,7 @@ util.inherits(ScryptResultPacket, Packet);
ScryptResultPacket.prototype.cmd = packetTypes.SCRYPTRESULT;
ScryptResultPacket.prototype.toRaw = function toRaw(bw) {
ScryptResultPacket.prototype.toWriter = function toWriter(bw) {
bw.writeVarBytes(this.key);
};
@ -755,7 +768,7 @@ ScryptResultPacket.fromRaw = function fromRaw(data) {
function frameTX(tx, bw) {
var i, input;
tx.toRaw(bw);
tx.toWriter(bw);
for (i = 0; i < tx.inputs.length; i++) {
input = tx.inputs[i];
@ -767,12 +780,12 @@ function frameTX(tx, bw) {
bw.writeU8(1);
bw.writeVarint(input.coin.value);
input.coin.script.toRaw(bw);
input.coin.script.toWriter(bw);
}
}
function parseTX(TX, br) {
var tx = TX.fromRaw(br);
var tx = TX.fromReader(br);
var i, input, prevout, coin;
for (i = 0; i < tx.inputs.length; i++) {
@ -784,7 +797,7 @@ function parseTX(TX, br) {
coin = new Coin();
coin.value = br.readVarint();
coin.script.fromRaw(br);
coin.script.fromReader(br);
coin.hash = prevout.hash;
coin.index = prevout.index;

View File

@ -317,17 +317,9 @@ WorkerPool.prototype.verifyInput = co(function* verifyInput(tx, index, flags) {
*/
WorkerPool.prototype.signInput = co(function* signInput(tx, index, ring, type) {
var rings = ring;
var packet, result;
if (!Array.isArray(rings))
rings = [rings];
packet = new packets.SignInputPacket(tx, index, rings, type);
result = yield this.execute(packet, -1);
var packet = new packets.SignInputPacket(tx, index, ring, type);
var result = yield this.execute(packet, -1);
result.inject(tx);
return result.value;
});

View File

@ -188,7 +188,7 @@ var reserializeUndo = co(function* reserializeUndo() {
while (br.left()) {
undo.push(null);
injectCoin(undo.top(), Coin.fromRaw(br));
injectCoin(undo.top(), Coin.fromReader(br));
}
batch.write(item.key, undo.toRaw());

View File

@ -139,8 +139,8 @@ function parseWallets(data) {
return wids;
}
function serializeWallets(wids, writer) {
var p = new BufferWriter(writer);
function serializeWallets(wids) {
var p = new BufferWriter();
var i, wid;
p.writeU32(wids.length);
@ -150,10 +150,7 @@ function serializeWallets(wids, writer) {
p.writeU32(wid);
}
if (!writer)
p = p.render();
return p;
return p.render();
}
function accountToRaw(account) {

View File

@ -207,10 +207,9 @@ describe('Protocol', function() {
});
it('should parse, reserialize, and verify alert packets', function() {
var p = new bcoin.reader(alertData);
p.start();
while (p.left()) {
var alert = packets.AlertPacket.fromRaw(p);
var br = new bcoin.reader(alertData);
while (br.left()) {
var alert = packets.AlertPacket.fromReader(br);
assert(alert.verify(network.alertKey));
alert._payload = null;
alert._hash = null;
@ -218,6 +217,5 @@ describe('Protocol', function() {
alert = packets.AlertPacket.fromRaw(data);
assert(alert.verify(network.alertKey));
}
p.end();
});
});

View File

@ -19,22 +19,22 @@ describe('Script', function() {
+ '101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f'
+ 'ac';
var decoded = bcoin.script.decode(new Buffer(src, 'hex'));
assert.equal(decoded.length, 3);
assert.equal(decoded[0].data.toString('hex'),
var decoded = bcoin.script(new Buffer(src, 'hex'));
assert.equal(decoded.code.length, 3);
assert.equal(decoded.code[0].data.toString('hex'),
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f');
assert.equal(decoded[1].data.toString('hex'),
assert.equal(decoded.code[1].data.toString('hex'),
'101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f');
assert.equal(decoded[2].value, opcodes.OP_CHECKSIG);
assert.equal(decoded.code[2].value, opcodes.OP_CHECKSIG);
var dst = bcoin.script.encode(decoded);
var dst = decoded.toRaw();
assert.equal(dst.toString('hex'), src);
});
it('should encode/decode numbers', function() {
var script = [0, 0x51, 0x52, 0x60];
var encoded = bcoin.script.fromArray(script).raw;
var decoded = bcoin.script.decode(encoded).map(function(op) { return op.value; });
var decoded = bcoin.script(encoded).toArray();
assert.deepEqual(decoded, script);
});