Clone transaction data more efficiently

This commit is contained in:
Luke Childs 2020-04-26 15:22:38 +07:00
parent 5d81b94362
commit f7034350e9
6 changed files with 50 additions and 22 deletions

View file

@ -41,6 +41,12 @@ function reverseBuffer(buffer) {
return buffer; return buffer;
} }
exports.reverseBuffer = reverseBuffer; exports.reverseBuffer = reverseBuffer;
function cloneBuffer(buffer) {
const clone = Buffer.alloc(buffer.length);
buffer.copy(clone);
return buffer;
}
exports.cloneBuffer = cloneBuffer;
/** /**
* Helper class for serialization of bitcoin data types into a pre-allocated buffer. * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
*/ */

View file

@ -104,10 +104,23 @@ class Psbt {
return this.__CACHE.__TX.locktime; return this.__CACHE.__TX.locktime;
} }
get txInputs() { get txInputs() {
return deepClone(this.__CACHE.__TX.ins); return this.__CACHE.__TX.ins.map(input => {
return {
hash: bufferutils_1.cloneBuffer(input.hash),
index: input.index,
script: bufferutils_1.cloneBuffer(input.script),
sequence: input.sequence,
witness: input.witness.map(buffer => bufferutils_1.cloneBuffer(buffer)),
};
});
} }
get txOutputs() { get txOutputs() {
return deepClone(this.__CACHE.__TX.outs); return this.__CACHE.__TX.outs.map(output => {
return {
script: bufferutils_1.cloneBuffer(output.script),
value: output.value,
};
});
} }
combine(...those) { combine(...those) {
this.data.combine(...those.map(o => o.data)); this.data.combine(...those.map(o => o.data));
@ -591,11 +604,6 @@ class PsbtTransaction {
return this.tx.toBuffer(); return this.tx.toBuffer();
} }
} }
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj), (_, value) =>
value.type === 'Buffer' ? Buffer.from(value.data) : value,
);
}
function canFinalize(input, script, scriptType) { function canFinalize(input, script, scriptType) {
switch (scriptType) { switch (scriptType) {
case 'pubkey': case 'pubkey':

View file

@ -48,6 +48,12 @@ export function reverseBuffer(buffer: Buffer): Buffer {
return buffer; return buffer;
} }
export function cloneBuffer(buffer: Buffer): Buffer {
const clone = Buffer.alloc(buffer.length);
buffer.copy(clone);
return buffer;
}
/** /**
* Helper class for serialization of bitcoin data types into a pre-allocated buffer. * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
*/ */

View file

@ -14,7 +14,7 @@ import {
} from 'bip174/src/lib/interfaces'; } from 'bip174/src/lib/interfaces';
import { checkForInput } from 'bip174/src/lib/utils'; import { checkForInput } from 'bip174/src/lib/utils';
import { toOutputScript } from './address'; import { toOutputScript } from './address';
import { reverseBuffer } from './bufferutils'; import { cloneBuffer, reverseBuffer } from './bufferutils';
import { hash160 } from './crypto'; import { hash160 } from './crypto';
import { import {
fromPublicKey as ecPairFromPublicKey, fromPublicKey as ecPairFromPublicKey,
@ -24,7 +24,7 @@ import {
import { bitcoin as btcNetwork, Network } from './networks'; import { bitcoin as btcNetwork, Network } from './networks';
import * as payments from './payments'; import * as payments from './payments';
import * as bscript from './script'; import * as bscript from './script';
import { Output, Transaction } from './transaction'; import { Input, Output, Transaction } from './transaction';
/** /**
* These are the default arguments for a Psbt instance. * These are the default arguments for a Psbt instance.
@ -137,12 +137,25 @@ export class Psbt {
return this.__CACHE.__TX.locktime; return this.__CACHE.__TX.locktime;
} }
get txInputs(): TransactionInput[] { get txInputs(): Input[] {
return deepClone(this.__CACHE.__TX.ins); return this.__CACHE.__TX.ins.map(input => {
return {
hash: cloneBuffer(input.hash),
index: input.index,
script: cloneBuffer(input.script),
sequence: input.sequence,
witness: input.witness.map(buffer => cloneBuffer(buffer)),
};
});
} }
get txOutputs(): TransactionInput[] { get txOutputs(): Output[] {
return deepClone(this.__CACHE.__TX.outs); return this.__CACHE.__TX.outs.map(output => {
return {
script: cloneBuffer(output.script),
value: output.value,
};
});
} }
combine(...those: Psbt[]): this { combine(...those: Psbt[]): this {
@ -773,12 +786,6 @@ class PsbtTransaction implements ITransaction {
} }
} }
function deepClone(obj: any): any {
return JSON.parse(JSON.stringify(obj), (_, value) =>
value.type === 'Buffer' ? Buffer.from(value.data) : value,
);
}
function canFinalize( function canFinalize(
input: PsbtInput, input: PsbtInput,
script: Buffer, script: Buffer,

View file

@ -1,6 +1,7 @@
export declare function readUInt64LE(buffer: Buffer, offset: number): number; export declare function readUInt64LE(buffer: Buffer, offset: number): number;
export declare function writeUInt64LE(buffer: Buffer, value: number, offset: number): number; export declare function writeUInt64LE(buffer: Buffer, value: number, offset: number): number;
export declare function reverseBuffer(buffer: Buffer): Buffer; export declare function reverseBuffer(buffer: Buffer): Buffer;
export declare function cloneBuffer(buffer: Buffer): Buffer;
/** /**
* Helper class for serialization of bitcoin data types into a pre-allocated buffer. * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
*/ */

6
types/psbt.d.ts vendored
View file

@ -2,7 +2,7 @@ import { Psbt as PsbtBase } from 'bip174';
import { KeyValue, PsbtGlobalUpdate, PsbtInput, PsbtInputUpdate, PsbtOutput, PsbtOutputUpdate, TransactionInput } from 'bip174/src/lib/interfaces'; import { KeyValue, PsbtGlobalUpdate, PsbtInput, PsbtInputUpdate, PsbtOutput, PsbtOutputUpdate, TransactionInput } from 'bip174/src/lib/interfaces';
import { Signer, SignerAsync } from './ecpair'; import { Signer, SignerAsync } from './ecpair';
import { Network } from './networks'; import { Network } from './networks';
import { Transaction } from './transaction'; import { Input, Output, Transaction } from './transaction';
/** /**
* Psbt class can parse and generate a PSBT binary based off of the BIP174. * Psbt class can parse and generate a PSBT binary based off of the BIP174.
* There are 6 roles that this class fulfills. (Explained in BIP174) * There are 6 roles that this class fulfills. (Explained in BIP174)
@ -46,8 +46,8 @@ export declare class Psbt {
readonly inputCount: number; readonly inputCount: number;
readonly txVersion: number; readonly txVersion: number;
readonly txLocktime: number; readonly txLocktime: number;
readonly txInputs: TransactionInput[]; readonly txInputs: Input[];
readonly txOutputs: TransactionInput[]; readonly txOutputs: Output[];
combine(...those: Psbt[]): this; combine(...those: Psbt[]): this;
clone(): Psbt; clone(): Psbt;
setMaximumFeeRate(satoshiPerByte: number): void; setMaximumFeeRate(satoshiPerByte: number): void;