buffer writer.

This commit is contained in:
Christopher Jeffrey 2016-03-15 00:56:00 -07:00
parent 3953f392f6
commit 6e6b1bd054

View File

@ -7,6 +7,7 @@
var bcoin = require('../../bcoin'); var bcoin = require('../../bcoin');
var network = require('./network'); var network = require('./network');
var constants = require('./constants'); var constants = require('./constants');
var bn = require('bn.js');
var utils = bcoin.utils; var utils = bcoin.utils;
var assert = utils.assert; var assert = utils.assert;
@ -487,6 +488,57 @@ Framer.tx = function _tx(tx) {
return p; return p;
}; };
Framer.btx = function btx(tx, writer) {
var p = new BufferWriter(writer);
p.write32(tx.version);
p.writeUIntv(tx.inputs.length);
for (i = 0; i < tx.inputs.length; i++)
Framer.binput(tx.inputs[i], p);
p.writeUIntv(tx.outputs.length);
for (i = 0; i < tx.outputs.length; i++)
Framer.boutput(tx.outputs[i], p);
p.writeU32(tx.locktime);
if (!writer)
p = p.render();
p._witnessSize = 0;
return p;
};
Framer.binput = function _input(input, writer) {
var p = new BufferWriter(writer);
p.writeHash(input.prevout.hash);
p.writeU32(input.prevout.index);
p.writeVarBytes(input.script.encode());
p.writeU32(input.sequence);
if (!writer)
p = p.render();
return p;
};
Framer.boutput = function _output(output, writer) {
var p = new BufferWriter(writer);
assert(output.value.byteLength() <= 8);
p.write64(output.value);
p.writeVarBytes(output.script.encode());
if (!writer)
p = p.render();
return p;
};
Framer.witnessTX = function _witnessTX(tx) { Framer.witnessTX = function _witnessTX(tx) {
var inputs = []; var inputs = [];
var outputs = []; var outputs = [];
@ -818,204 +870,165 @@ Framer.mempool = function mempool() {
return new Buffer([]); return new Buffer([]);
}; };
function BufferWriter(size, offset) { function BufferWriter(options) {
this.buffers = []; if (options instanceof BufferWriter)
if (Buffer.isBuffer(size)) { return options;
this.offset = offset || 0;
this.size = 100; if (!(this instanceof BufferWriter))
this.buffers.push(size); return new BufferWriter(options);
} else {
this.offset = 0; this.data = [];
this.size = size || 100; this.written = 0;
} this.offset = 0;
this.data = new Buffer(this.size);
} }
BufferWriter.prototype.render = function render() { BufferWriter.prototype.render = function render() {
this.buffers.push(this.data.slice(this.offset)); var data = new Buffer(this.written);
var ret = Buffer.concat(this.buffers); var off = 0;
this.buffers.length = 0; var i;
delete this.size;
delete this.offset;
delete this.buffers;
delete this.data;
return ret;
};
BufferWriter.prototype._realloc = function _realloc(size) { for (i = 0; i < this.data.length; i++) {
if (this.data.length >= size) item = this.data[i];
return; switch (item[0]) {
case 'u8': off += utils.writeU8(data, item[1], off); break;
case 'u16': off += utils.writeU16(data, item[1], off); break;
case 'u16be': off += utils.writeU16BE(data, item[1], off); break;
case 'u32': off += utils.writeU32(data, item[1], off); break;
case 'u32be': off += utils.writeU32BE(data, item[1], off); break;
case 'u64': off += utils.writeU64(data, item[1], off); break;
case 'u64be': off += utils.writeU64BE(data, item[1], off); break;
case '8': off += utils.write8(data, item[1], off); break;
case '16': off += utils.write16(data, item[1], off); break;
case '16be': off += utils.write16BE(data, item[1], off); break;
case '32': off += utils.write32(data, item[1], off); break;
case '32be': off += utils.write32BE(data, item[1], off); break;
case '64': off += utils.write64(data, item[1], off); break;
case '64be': off += utils.write64BE(data, item[1], off); break;
case 'varint': off += utils.writeIntv(data, item[1], off); break;
case 'bytes': off += utils.copy(item[1], data, off); break;
}
}
var len = this.data.length; return data;
var newSize = len + (len / 2 | 0);
if (size > newSize)
newSize = size + (size / 2 | 0);
this.buffers.push(this.data.slice(this.offset));
this.data = new Buffer(newSize);
}; };
BufferWriter.prototype.writeU8 = function writeU8(value) { BufferWriter.prototype.writeU8 = function writeU8(value) {
this._realloc(this.offset + 1); this.written += 1;
var ret = utils.writeU8(this.data, value, this.offset); this.data.push(['u8', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.writeU16 = function writeU16(value) { BufferWriter.prototype.writeU16 = function writeU16(value) {
this._realloc(this.offset + 2); this.written += 2;
var ret = utils.writeU16(this.data, value, this.offset); this.data.push(['u16', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.writeU16BE = function writeU16BE(value) { BufferWriter.prototype.writeU16BE = function writeU16BE(value) {
this._realloc(this.offset + 2); this.written += 2;
var ret = utils.writeU16BE(this.data, value, this.offset); this.data.push(['u16be', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.writeU32 = function writeU32(value) { BufferWriter.prototype.writeU32 = function writeU32(value) {
this._realloc(this.offset + 4); this.written += 4;
var ret = utils.writeU32(this.data, value, this.offset); this.data.push(['u32', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.writeU32BE = function writeU32BE(value) { BufferWriter.prototype.writeU32BE = function writeU32BE(value) {
this._realloc(this.offset + 4); this.written += 4;
var ret = utils.writeU32BE(this.data, value, this.offset); this.data.push(['u32be', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.writeU64 = function writeU64(value) { BufferWriter.prototype.writeU64 = function writeU64(value) {
this._realloc(this.offset + 8); this.written += 8;
var ret = utils.writeU64(this.data, value, this.offset); this.data.push(['u64', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.writeU64BE = function writeU64BE(value) { BufferWriter.prototype.writeU64BE = function writeU64BE(value) {
this._realloc(this.offset + 8); this.written += 8;
var ret = utils.writeU64BE(this.data, value, this.offset); this.data.push(['u64be', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.write8 = function write8(value) { BufferWriter.prototype.write8 = function write8(value) {
this._realloc(this.offset + 1); this.written += 1;
var ret = utils.write8(this.data, value, this.offset); this.data.push(['8', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.write16 = function write16(value) { BufferWriter.prototype.write16 = function write16(value) {
this._realloc(this.offset + 2); this.written += 2;
var ret = utils.write16(this.data, value, this.offset); this.data.push(['16', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.write16BE = function write16BE(value) { BufferWriter.prototype.write16BE = function write16BE(value) {
this._realloc(this.offset + 2); this.written += 2;
var ret = utils.write16BE(this.data, value, this.offset); this.data.push(['16be', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.write32 = function write32(value) { BufferWriter.prototype.write32 = function write32(value) {
this._realloc(this.offset + 4); this.written += 4;
var ret = utils.write32(this.data, value, this.offset); this.data.push(['32', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.write32BE = function write32BE(value) { BufferWriter.prototype.write32BE = function write32BE(value) {
this._realloc(this.offset + 4); this.written += 4;
var ret = utils.write32BE(this.data, value, this.offset); this.data.push(['32be', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.write64 = function write64(value) { BufferWriter.prototype.write64 = function write64(value) {
this._realloc(this.offset + 8); this.written += 8;
var ret = utils.write64(this.data, value, this.offset); this.data.push(['64', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.write64BE = function write64BE(value) { BufferWriter.prototype.write64BE = function write64BE(value) {
this._realloc(this.offset + 8); this.written += 8;
var ret = utils.write64BE(this.data, value, this.offset); this.data.push(['64be', value]);
this.offset += ret;
return ret;
}; };
BufferWriter.prototype.writeBytes = function writeBytes(value) { BufferWriter.prototype.writeBytes = function writeBytes(value) {
assert(Buffer.isBuffer(value)); this.written += value.length;
if (this.left() > value.length) this.data.push(['bytes', value]);
return utils.copy(value, this.data, 0);
this.buffers.push(this.data.slice(this.offset));
this.buffers.push(value);
this.data = new Buffer(100);
this.offset += value.length;
return value.length;
};
BufferWriter.prototype.left = function left() {
return this.data.length - this.offset;
}; };
BufferWriter.prototype.getSize = function getSize() { BufferWriter.prototype.getSize = function getSize() {
return this.offset; return this.written;
}; };
BufferWriter.prototype.writeString = function writeString(value, enc) { BufferWriter.prototype.writeString = function writeString(value, enc) {
if (typeof value === 'string') if (typeof value === 'string')
value = new Buffer(value, enc); value = new Buffer(value, enc);
return this.writeBytes(value); this.writeBytes(value);
}; };
BufferWriter.prototype.writeHash = function writeHash(value) { BufferWriter.prototype.writeHash = function writeHash(value) {
if (typeof value === 'string') if (typeof value === 'string')
value = new Buffer(value, 'hex'); value = new Buffer(value, 'hex');
assert(value.length === 32 || value.length === 20); this.writeBytes(value);
return this.writeBytes(value);
}; };
BufferWriter.prototype.writeVarString = function writeVarString(value, enc) { BufferWriter.prototype.writeVarString = function writeVarString(value, enc) {
var len = typeof value === 'string' if (typeof value === 'string')
? Buffer.byteLength(value, enc) value = new Buffer(value, enc);
: value.length; this.writeVarBytes(value);
var ret = this.writeUIntv(len);
return this.writeString(value, enc) + ret;
}; };
BufferWriter.prototype.writeVarBytes = function writeVarBytes(value) { BufferWriter.prototype.writeVarBytes = function writeVarBytes(value) {
var ret = this.writeUIntv(value.length); this.written += utils.sizeIntv(value.length);
return this.writeBytes(value) + ret; this.written += value.length;
this.data.push(['varint', value.length]);
this.data.push(['bytes', value]);
}; };
BufferWriter.prototype.writeNullString = function writeNullString(value, enc) { BufferWriter.prototype.writeNullString = function writeNullString(value, enc) {
var ret = this.writeString(value, enc); this.writeString(value, enc);
this.writeU8(0); this.writeU8(0);
return ret + 1;
}; };
BufferWriter.prototype.writeIntv = function writeIntv(value) { BufferWriter.prototype.writeIntv = function writeIntv(value) {
this._realloc(this.offset + utils.sizeIntv(value)); this.written += utils.sizeIntv(value);
return utils.writeIntv(this.data, value, this.offset); this.data.push(['varint', value]);
}; };
BufferWriter.prototype.writeUIntv = function writeUIntv(value) { BufferWriter.prototype.writeUIntv = function writeUIntv(value) {
if (value instanceof bn) this.written += utils.sizeIntv(value);
assert(value.cmpn(0) >= 0); this.data.push(['varint', value]);
else
assert(value >= 0);
return this.writeIntv(value);
}; };
/** /**