From 10ef1809bfdad48817dd159079ce864da7859be8 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Mon, 8 Apr 2019 18:03:43 -0700 Subject: [PATCH] primitives: add serialized offset and only for block reader/writer --- lib/primitives/block.js | 4 ++-- lib/primitives/tx.js | 37 ++++++++++++++++++++++++++++--------- test/block-test.js | 41 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 70 insertions(+), 12 deletions(-) diff --git a/lib/primitives/block.js b/lib/primitives/block.js index b10b3dc92e..25c2b6d1df 100644 --- a/lib/primitives/block.js +++ b/lib/primitives/block.js @@ -645,7 +645,7 @@ class Block extends AbstractBlock { let witness = 0; for (let i = 0; i < count; i++) { - const tx = TX.fromReader(br); + const tx = TX.fromReader(br, true); witness += tx._witness; this.txs.push(tx); } @@ -738,7 +738,7 @@ class Block extends AbstractBlock { bw.writeVarint(this.txs.length); for (const tx of this.txs) - tx.toWriter(bw); + tx.toWriter(bw, true); return bw; } diff --git a/lib/primitives/tx.js b/lib/primitives/tx.js index af0c7deddf..bfc94b11a9 100644 --- a/lib/primitives/tx.js +++ b/lib/primitives/tx.js @@ -58,6 +58,7 @@ class TX { this._raw = null; this._offset = -1; + this._block = false; this._size = -1; this._witness = -1; this._sigops = -1; @@ -159,6 +160,7 @@ class TX { this._raw = null; this._size = -1; this._offset = -1; + this._block = false; this._witness = -1; this._sigops = -1; @@ -247,15 +249,21 @@ class TX { /** * Write the transaction to a buffer writer. * @param {BufferWriter} bw + * @param {Boolean} block */ - toWriter(bw) { + toWriter(bw, block) { if (this.mutable) { if (this.hasWitness()) return this.writeWitness(bw); return this.writeNormal(bw); } + if (block) { + this._offset = bw.offset; + this._block = true; + } + bw.writeBytes(this.toRaw()); return bw; @@ -320,7 +328,7 @@ class TX { */ getPosition() { - assert(this._offset >= 0, 'Position not available.'); + assert(this._block && this._offset > 80, 'Position not available.'); return { offset: this._offset, @@ -2243,11 +2251,12 @@ class TX { /** * Instantiate a transaction from a buffer reader. * @param {BufferReader} br + * @param {Boolean} block * @returns {TX} */ - static fromReader(br) { - return new this().fromReader(br); + static fromReader(br, block) { + return new this().fromReader(br, block); } /** @@ -2264,11 +2273,12 @@ class TX { * Inject properties from buffer reader. * @private * @param {BufferReader} br + * @param {Boolean} block */ - fromReader(br) { + fromReader(br, block) { if (hasWitnessBytes(br)) - return this.fromWitnessReader(br); + return this.fromWitnessReader(br, block); const start = br.start(); @@ -2286,9 +2296,13 @@ class TX { this.locktime = br.readU32(); + if (block) { + this._offset = start; + this._block = true; + } + if (!this.mutable) { this._raw = br.endData(); - this._offset = start; this._size = this._raw.length; this._witness = 0; } else { @@ -2303,9 +2317,10 @@ class TX { * buffer reader (witness serialization). * @private * @param {BufferReader} br + * @param {Boolean} block */ - fromWitnessReader(br) { + fromWitnessReader(br, block) { const start = br.start(); this.version = br.readU32(); @@ -2354,10 +2369,14 @@ class TX { this.locktime = br.readU32(); + if (block) { + this._offset = start; + this._block = true; + } + if (!this.mutable && hasWitness) { this._raw = br.endData(); this._size = this._raw.length; - this._offset = start; this._witness = witness; } else { br.end(); diff --git a/test/block-test.js b/test/block-test.js index 17cfbffbc5..20f2047b29 100644 --- a/test/block-test.js +++ b/test/block-test.js @@ -405,7 +405,46 @@ describe('Block', function() { } }); - it('should deserialize with offset positions for txs (witness)', () => { + it('should serialize with offset positions for txs (witness)', () => { + const [block] = block482683.getBlock(); + + const expected = [ + {offset: 81, size: 217}, + {offset: 298, size: 815}, + {offset: 1113, size: 192}, + {offset: 1305, size: 259}, + {offset: 1564, size: 223}, + {offset: 1787, size: 1223}, + {offset: 3010, size: 486}, + {offset: 3496, size: 665}, + {offset: 4161, size: 3176}, + {offset: 7337, size: 225}, + {offset: 7562, size: 1223}, + {offset: 8785, size: 503} + ]; + + assert.equal(expected.length, block.txs.length); + assert.equal(block.getSize(), expected.reduce((a, b) => a + b.size, 81)); + + // Reset the offset for all transactions, and clear + // any cached values for the block. + block.refresh(true); + for (let i = 0; i < block.txs.length; i++) + assert.equal(block.txs[i]._offset, -1); + + // Serialize the block, as done before saving to disk. + const raw = block.toRaw(); + assert(raw); + + for (let i = 0; i < block.txs.length; i++) { + const {offset, size} = block.txs[i].getPosition(); + + assert.strictEqual(offset, expected[i].offset); + assert.strictEqual(size, expected[i].size); + } + }); + + it('should deserialize with offset positions for txs', () => { const [block] = block300025.getBlock(); assert.equal(block.txs.length, 461);