diff --git a/src/block.js b/src/block.js index 22449fd..8ec6c29 100644 --- a/src/block.js +++ b/src/block.js @@ -127,12 +127,17 @@ class Block { hasWitness() { return anyTxHasWitness(this.transactions); } - byteLength(headersOnly) { + weight() { + const base = this.byteLength(false, false); + const total = this.byteLength(false, true); + return base * 3 + total; + } + byteLength(headersOnly, allowWitness = true) { if (headersOnly || !this.transactions) return 80; return ( 80 + varuint.encodingLength(this.transactions.length) + - this.transactions.reduce((a, x) => a + x.byteLength(), 0) + this.transactions.reduce((a, x) => a + x.byteLength(allowWitness), 0) ); } getHash() { diff --git a/src/transaction.js b/src/transaction.js index c4e6506..e2d6a6b 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -179,15 +179,31 @@ class Transaction { }); } weight() { - const base = this.__byteLength(false); - const total = this.__byteLength(true); + const base = this.byteLength(false); + const total = this.byteLength(true); return base * 3 + total; } virtualSize() { return Math.ceil(this.weight() / 4); } - byteLength() { - return this.__byteLength(true); + byteLength(_ALLOW_WITNESS = true) { + const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses(); + return ( + (hasWitnesses ? 10 : 8) + + varuint.encodingLength(this.ins.length) + + varuint.encodingLength(this.outs.length) + + this.ins.reduce((sum, input) => { + return sum + 40 + varSliceSize(input.script); + }, 0) + + this.outs.reduce((sum, output) => { + return sum + 8 + varSliceSize(output.script); + }, 0) + + (hasWitnesses + ? this.ins.reduce((sum, input) => { + return sum + vectorSize(input.witness); + }, 0) + : 0) + ); } clone() { const newTx = new Transaction(); @@ -269,7 +285,7 @@ class Transaction { txTmp.ins[inIndex].script = ourScript; } // serialize and hash - const buffer = Buffer.allocUnsafe(txTmp.__byteLength(false) + 4); + const buffer = Buffer.allocUnsafe(txTmp.byteLength(false) + 4); buffer.writeInt32LE(hashType, buffer.length - 4); txTmp.__toBuffer(buffer, 0, false); return bcrypto.hash256(buffer); @@ -386,27 +402,8 @@ class Transaction { typeforce(types.tuple(types.Number, [types.Buffer]), arguments); this.ins[index].witness = witness; } - __byteLength(_ALLOW_WITNESS) { - const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses(); - return ( - (hasWitnesses ? 10 : 8) + - varuint.encodingLength(this.ins.length) + - varuint.encodingLength(this.outs.length) + - this.ins.reduce((sum, input) => { - return sum + 40 + varSliceSize(input.script); - }, 0) + - this.outs.reduce((sum, output) => { - return sum + 8 + varSliceSize(output.script); - }, 0) + - (hasWitnesses - ? this.ins.reduce((sum, input) => { - return sum + vectorSize(input.witness); - }, 0) - : 0) - ); - } - __toBuffer(buffer, initialOffset, _ALLOW_WITNESS) { - if (!buffer) buffer = Buffer.allocUnsafe(this.__byteLength(_ALLOW_WITNESS)); + __toBuffer(buffer, initialOffset, _ALLOW_WITNESS = false) { + if (!buffer) buffer = Buffer.allocUnsafe(this.byteLength(_ALLOW_WITNESS)); let offset = initialOffset || 0; function writeSlice(slice) { offset += slice.copy(buffer, offset); diff --git a/test/block.spec.ts b/test/block.spec.ts index 0f74392..e93420c 100644 --- a/test/block.spec.ts +++ b/test/block.spec.ts @@ -48,6 +48,11 @@ describe('Block', () => { assert.strictEqual(block.bits, f.bits); assert.strictEqual(block.nonce, f.nonce); assert.strictEqual(!block.transactions, f.hex.length === 160); + if (f.size && f.strippedSize && f.weight) { + assert.strictEqual(block.byteLength(false, true), f.size); + assert.strictEqual(block.byteLength(false, false), f.strippedSize); + assert.strictEqual(block.weight(), f.weight); + } }); }); diff --git a/test/fixtures/block.json b/test/fixtures/block.json index c60685e..8ea521c 100644 --- a/test/fixtures/block.json +++ b/test/fixtures/block.json @@ -133,7 +133,10 @@ "prevHash": "8980ebb11236bacc66c447d5ad961bc546c0f9cc385a08000000000000000000", "timestamp": 1537429727, "valid": true, - "version": 536870912 + "version": 536870912, + "size": 2355, + "strippedSize": 2209, + "weight": 8982 } ], "invalid": [ diff --git a/ts_src/block.ts b/ts_src/block.ts index cf4ed51..9a4d675 100644 --- a/ts_src/block.ts +++ b/ts_src/block.ts @@ -148,13 +148,19 @@ export class Block { return anyTxHasWitness(this.transactions!); } - byteLength(headersOnly?: boolean): number { + weight(): number { + const base = this.byteLength(false, false); + const total = this.byteLength(false, true); + return base * 3 + total; + } + + byteLength(headersOnly?: boolean, allowWitness: boolean = true): number { if (headersOnly || !this.transactions) return 80; return ( 80 + varuint.encodingLength(this.transactions.length) + - this.transactions.reduce((a, x) => a + x.byteLength(), 0) + this.transactions.reduce((a, x) => a + x.byteLength(allowWitness), 0) ); } diff --git a/ts_src/transaction.ts b/ts_src/transaction.ts index 0419ba2..88e9242 100644 --- a/ts_src/transaction.ts +++ b/ts_src/transaction.ts @@ -237,8 +237,8 @@ export class Transaction { } weight(): number { - const base = this.__byteLength(false); - const total = this.__byteLength(true); + const base = this.byteLength(false); + const total = this.byteLength(true); return base * 3 + total; } @@ -246,8 +246,25 @@ export class Transaction { return Math.ceil(this.weight() / 4); } - byteLength(): number { - return this.__byteLength(true); + byteLength(_ALLOW_WITNESS: boolean = true): number { + const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses(); + + return ( + (hasWitnesses ? 10 : 8) + + varuint.encodingLength(this.ins.length) + + varuint.encodingLength(this.outs.length) + + this.ins.reduce((sum, input) => { + return sum + 40 + varSliceSize(input.script); + }, 0) + + this.outs.reduce((sum, output) => { + return sum + 8 + varSliceSize(output.script); + }, 0) + + (hasWitnesses + ? this.ins.reduce((sum, input) => { + return sum + vectorSize(input.witness); + }, 0) + : 0) + ); } clone(): Transaction { @@ -352,7 +369,7 @@ export class Transaction { } // serialize and hash - const buffer: Buffer = Buffer.allocUnsafe(txTmp.__byteLength(false) + 4); + const buffer: Buffer = Buffer.allocUnsafe(txTmp.byteLength(false) + 4); buffer.writeInt32LE(hashType, buffer.length - 4); txTmp.__toBuffer(buffer, 0, false); @@ -506,34 +523,13 @@ export class Transaction { this.ins[index].witness = witness; } - private __byteLength(_ALLOW_WITNESS: boolean): number { - const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses(); - - return ( - (hasWitnesses ? 10 : 8) + - varuint.encodingLength(this.ins.length) + - varuint.encodingLength(this.outs.length) + - this.ins.reduce((sum, input) => { - return sum + 40 + varSliceSize(input.script); - }, 0) + - this.outs.reduce((sum, output) => { - return sum + 8 + varSliceSize(output.script); - }, 0) + - (hasWitnesses - ? this.ins.reduce((sum, input) => { - return sum + vectorSize(input.witness); - }, 0) - : 0) - ); - } - private __toBuffer( buffer?: Buffer, initialOffset?: number, - _ALLOW_WITNESS?: boolean, + _ALLOW_WITNESS: boolean = false, ): Buffer { if (!buffer) - buffer = Buffer.allocUnsafe(this.__byteLength(_ALLOW_WITNESS!)) as Buffer; + buffer = Buffer.allocUnsafe(this.byteLength(_ALLOW_WITNESS)) as Buffer; let offset = initialOffset || 0; diff --git a/types/block.d.ts b/types/block.d.ts index d77bb1b..7d8309c 100644 --- a/types/block.d.ts +++ b/types/block.d.ts @@ -15,7 +15,8 @@ export declare class Block { getWitnessCommit(): Buffer | null; hasWitnessCommit(): boolean; hasWitness(): boolean; - byteLength(headersOnly?: boolean): number; + weight(): number; + byteLength(headersOnly?: boolean, allowWitness?: boolean): number; getHash(): Buffer; getId(): string; getUTCDate(): Date; diff --git a/types/transaction.d.ts b/types/transaction.d.ts index f0db04e..6846ea5 100644 --- a/types/transaction.d.ts +++ b/types/transaction.d.ts @@ -30,7 +30,7 @@ export declare class Transaction { hasWitnesses(): boolean; weight(): number; virtualSize(): number; - byteLength(): number; + byteLength(_ALLOW_WITNESS?: boolean): number; clone(): Transaction; /** * Hash transaction for signing a specific input. @@ -48,6 +48,5 @@ export declare class Transaction { toHex(): string; setInputScript(index: number, scriptSig: Buffer): void; setWitness(index: number, witness: Buffer[]): void; - private __byteLength; private __toBuffer; }