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;
}
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.
*/

View file

@ -104,10 +104,23 @@ class Psbt {
return this.__CACHE.__TX.locktime;
}
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() {
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) {
this.data.combine(...those.map(o => o.data));
@ -591,11 +604,6 @@ class PsbtTransaction {
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) {
switch (scriptType) {
case 'pubkey':

View file

@ -48,6 +48,12 @@ export function reverseBuffer(buffer: Buffer): 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.
*/

View file

@ -14,7 +14,7 @@ import {
} from 'bip174/src/lib/interfaces';
import { checkForInput } from 'bip174/src/lib/utils';
import { toOutputScript } from './address';
import { reverseBuffer } from './bufferutils';
import { cloneBuffer, reverseBuffer } from './bufferutils';
import { hash160 } from './crypto';
import {
fromPublicKey as ecPairFromPublicKey,
@ -24,7 +24,7 @@ import {
import { bitcoin as btcNetwork, Network } from './networks';
import * as payments from './payments';
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.
@ -137,12 +137,25 @@ export class Psbt {
return this.__CACHE.__TX.locktime;
}
get txInputs(): TransactionInput[] {
return deepClone(this.__CACHE.__TX.ins);
get txInputs(): Input[] {
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[] {
return deepClone(this.__CACHE.__TX.outs);
get txOutputs(): Output[] {
return this.__CACHE.__TX.outs.map(output => {
return {
script: cloneBuffer(output.script),
value: output.value,
};
});
}
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(
input: PsbtInput,
script: Buffer,

View file

@ -1,6 +1,7 @@
export declare function readUInt64LE(buffer: Buffer, offset: number): number;
export declare function writeUInt64LE(buffer: Buffer, value: number, offset: number): number;
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.
*/

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 { Signer, SignerAsync } from './ecpair';
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.
* There are 6 roles that this class fulfills. (Explained in BIP174)
@ -46,8 +46,8 @@ export declare class Psbt {
readonly inputCount: number;
readonly txVersion: number;
readonly txLocktime: number;
readonly txInputs: TransactionInput[];
readonly txOutputs: TransactionInput[];
readonly txInputs: Input[];
readonly txOutputs: Output[];
combine(...those: Psbt[]): this;
clone(): Psbt;
setMaximumFeeRate(satoshiPerByte: number): void;