Merge pull request #1515 from bitcoinjs/addWeightBlock

Add weight and ability to get strippedsize
This commit is contained in:
d-yokoi 2019-12-09 10:57:44 +09:00 committed by GitHub
commit 456ba5a6d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 74 additions and 62 deletions

View file

@ -127,12 +127,17 @@ class Block {
hasWitness() { hasWitness() {
return anyTxHasWitness(this.transactions); 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; if (headersOnly || !this.transactions) return 80;
return ( return (
80 + 80 +
varuint.encodingLength(this.transactions.length) + 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() { getHash() {

View file

@ -179,15 +179,31 @@ class Transaction {
}); });
} }
weight() { weight() {
const base = this.__byteLength(false); const base = this.byteLength(false);
const total = this.__byteLength(true); const total = this.byteLength(true);
return base * 3 + total; return base * 3 + total;
} }
virtualSize() { virtualSize() {
return Math.ceil(this.weight() / 4); return Math.ceil(this.weight() / 4);
} }
byteLength() { byteLength(_ALLOW_WITNESS = true) {
return this.__byteLength(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() { clone() {
const newTx = new Transaction(); const newTx = new Transaction();
@ -269,7 +285,7 @@ class Transaction {
txTmp.ins[inIndex].script = ourScript; txTmp.ins[inIndex].script = ourScript;
} }
// serialize and hash // 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); buffer.writeInt32LE(hashType, buffer.length - 4);
txTmp.__toBuffer(buffer, 0, false); txTmp.__toBuffer(buffer, 0, false);
return bcrypto.hash256(buffer); return bcrypto.hash256(buffer);
@ -386,27 +402,8 @@ class Transaction {
typeforce(types.tuple(types.Number, [types.Buffer]), arguments); typeforce(types.tuple(types.Number, [types.Buffer]), arguments);
this.ins[index].witness = witness; this.ins[index].witness = witness;
} }
__byteLength(_ALLOW_WITNESS) { __toBuffer(buffer, initialOffset, _ALLOW_WITNESS = false) {
const hasWitnesses = _ALLOW_WITNESS && this.hasWitnesses(); if (!buffer) buffer = Buffer.allocUnsafe(this.byteLength(_ALLOW_WITNESS));
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));
let offset = initialOffset || 0; let offset = initialOffset || 0;
function writeSlice(slice) { function writeSlice(slice) {
offset += slice.copy(buffer, offset); offset += slice.copy(buffer, offset);

View file

@ -48,6 +48,11 @@ describe('Block', () => {
assert.strictEqual(block.bits, f.bits); assert.strictEqual(block.bits, f.bits);
assert.strictEqual(block.nonce, f.nonce); assert.strictEqual(block.nonce, f.nonce);
assert.strictEqual(!block.transactions, f.hex.length === 160); 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);
}
}); });
}); });

View file

@ -133,7 +133,10 @@
"prevHash": "8980ebb11236bacc66c447d5ad961bc546c0f9cc385a08000000000000000000", "prevHash": "8980ebb11236bacc66c447d5ad961bc546c0f9cc385a08000000000000000000",
"timestamp": 1537429727, "timestamp": 1537429727,
"valid": true, "valid": true,
"version": 536870912 "version": 536870912,
"size": 2355,
"strippedSize": 2209,
"weight": 8982
} }
], ],
"invalid": [ "invalid": [

View file

@ -148,13 +148,19 @@ export class Block {
return anyTxHasWitness(this.transactions!); 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; if (headersOnly || !this.transactions) return 80;
return ( return (
80 + 80 +
varuint.encodingLength(this.transactions.length) + varuint.encodingLength(this.transactions.length) +
this.transactions.reduce((a, x) => a + x.byteLength(), 0) this.transactions.reduce((a, x) => a + x.byteLength(allowWitness), 0)
); );
} }

View file

@ -237,8 +237,8 @@ export class Transaction {
} }
weight(): number { weight(): number {
const base = this.__byteLength(false); const base = this.byteLength(false);
const total = this.__byteLength(true); const total = this.byteLength(true);
return base * 3 + total; return base * 3 + total;
} }
@ -246,8 +246,25 @@ export class Transaction {
return Math.ceil(this.weight() / 4); return Math.ceil(this.weight() / 4);
} }
byteLength(): number { byteLength(_ALLOW_WITNESS: boolean = true): number {
return this.__byteLength(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(): Transaction { clone(): Transaction {
@ -352,7 +369,7 @@ export class Transaction {
} }
// serialize and hash // 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); buffer.writeInt32LE(hashType, buffer.length - 4);
txTmp.__toBuffer(buffer, 0, false); txTmp.__toBuffer(buffer, 0, false);
@ -506,34 +523,13 @@ export class Transaction {
this.ins[index].witness = witness; 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( private __toBuffer(
buffer?: Buffer, buffer?: Buffer,
initialOffset?: number, initialOffset?: number,
_ALLOW_WITNESS?: boolean, _ALLOW_WITNESS: boolean = false,
): Buffer { ): Buffer {
if (!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; let offset = initialOffset || 0;

3
types/block.d.ts vendored
View file

@ -15,7 +15,8 @@ export declare class Block {
getWitnessCommit(): Buffer | null; getWitnessCommit(): Buffer | null;
hasWitnessCommit(): boolean; hasWitnessCommit(): boolean;
hasWitness(): boolean; hasWitness(): boolean;
byteLength(headersOnly?: boolean): number; weight(): number;
byteLength(headersOnly?: boolean, allowWitness?: boolean): number;
getHash(): Buffer; getHash(): Buffer;
getId(): string; getId(): string;
getUTCDate(): Date; getUTCDate(): Date;

View file

@ -30,7 +30,7 @@ export declare class Transaction {
hasWitnesses(): boolean; hasWitnesses(): boolean;
weight(): number; weight(): number;
virtualSize(): number; virtualSize(): number;
byteLength(): number; byteLength(_ALLOW_WITNESS?: boolean): number;
clone(): Transaction; clone(): Transaction;
/** /**
* Hash transaction for signing a specific input. * Hash transaction for signing a specific input.
@ -48,6 +48,5 @@ export declare class Transaction {
toHex(): string; toHex(): string;
setInputScript(index: number, scriptSig: Buffer): void; setInputScript(index: number, scriptSig: Buffer): void;
setWitness(index: number, witness: Buffer[]): void; setWitness(index: number, witness: Buffer[]): void;
private __byteLength;
private __toBuffer; private __toBuffer;
} }