From e4e51113768a48061fd1ae2982f40ee3fffb05ef Mon Sep 17 00:00:00 2001 From: junderw Date: Tue, 9 Jul 2019 11:51:28 +0900 Subject: [PATCH] Refactor: cache --- src/psbt.js | 149 ++++++++++++++++++++++-------------------- test/psbt.js | 12 ++-- ts_src/psbt.ts | 169 +++++++++++++++++++++++++----------------------- types/psbt.d.ts | 4 -- 4 files changed, 171 insertions(+), 163 deletions(-) diff --git a/src/psbt.js b/src/psbt.js index fdb457f..c549d30 100644 --- a/src/psbt.js +++ b/src/psbt.js @@ -22,10 +22,13 @@ class Psbt extends bip174_1.Psbt { __NON_WITNESS_UTXO_TX_CACHE: [], __NON_WITNESS_UTXO_BUF_CACHE: [], __TX_IN_CACHE: {}, + __TX: new transaction_1.Transaction(), }; // set defaults this.opts = Object.assign({}, DEFAULT_OPTS, opts); - this.__TX = transaction_1.Transaction.fromBuffer(this.globalMap.unsignedTx); + this.__CACHE.__TX = transaction_1.Transaction.fromBuffer( + this.globalMap.unsignedTx, + ); this.setVersion(2); // set cache const self = this; @@ -33,15 +36,15 @@ class Psbt extends bip174_1.Psbt { Object.defineProperty(this.globalMap, 'unsignedTx', { enumerable: true, get() { - if (self.__TX_BUF_CACHE !== undefined) { - return self.__TX_BUF_CACHE; + if (self.__CACHE.__TX_BUF_CACHE !== undefined) { + return self.__CACHE.__TX_BUF_CACHE; } else { - self.__TX_BUF_CACHE = self.__TX.toBuffer(); - return self.__TX_BUF_CACHE; + self.__CACHE.__TX_BUF_CACHE = self.__CACHE.__TX.toBuffer(); + return self.__CACHE.__TX_BUF_CACHE; } }, set(data) { - self.__TX_BUF_CACHE = data; + self.__CACHE.__TX_BUF_CACHE = data; }, }); // Make data hidden when enumerating @@ -52,8 +55,6 @@ class Psbt extends bip174_1.Psbt { }); dpew(this, '__TX', false, true); dpew(this, '__EXTRACTED_TX', false, true); - dpew(this, '__FEE_RATE', false, true); - dpew(this, '__TX_BUF_CACHE', false, true); dpew(this, '__CACHE', false, true); dpew(this, 'opts', false, true); } @@ -61,7 +62,7 @@ class Psbt extends bip174_1.Psbt { const tx = transaction_1.Transaction.fromBuffer(txBuf); checkTxEmpty(tx); const psbt = new this(); - psbt.__TX = tx; + psbt.__CACHE.__TX = tx; checkTxForDupeIns(tx, psbt.__CACHE); let inputCount = tx.ins.length; let outputCount = tx.outs.length; @@ -90,7 +91,7 @@ class Psbt extends bip174_1.Psbt { }; }; const psbt = super.fromBuffer(buffer, txCountGetter); - psbt.__TX = tx; + psbt.__CACHE.__TX = tx; checkTxForDupeIns(tx, psbt.__CACHE); return psbt; } @@ -104,63 +105,39 @@ class Psbt extends bip174_1.Psbt { setVersion(version) { check32Bit(version); checkInputsForPartialSig(this.inputs, 'setVersion'); - this.__TX.version = version; - this.__TX_BUF_CACHE = undefined; - this.__EXTRACTED_TX = undefined; + const c = this.__CACHE; + c.__TX.version = version; + c.__TX_BUF_CACHE = undefined; + c.__EXTRACTED_TX = undefined; return this; } setLocktime(locktime) { check32Bit(locktime); checkInputsForPartialSig(this.inputs, 'setLocktime'); - this.__TX.locktime = locktime; - this.__TX_BUF_CACHE = undefined; - this.__EXTRACTED_TX = undefined; + const c = this.__CACHE; + c.__TX.locktime = locktime; + c.__TX_BUF_CACHE = undefined; + c.__EXTRACTED_TX = undefined; return this; } setSequence(inputIndex, sequence) { check32Bit(sequence); checkInputsForPartialSig(this.inputs, 'setSequence'); - if (this.__TX.ins.length <= inputIndex) { + const c = this.__CACHE; + if (c.__TX.ins.length <= inputIndex) { throw new Error('Input index too high'); } - this.__TX.ins[inputIndex].sequence = sequence; - this.__TX_BUF_CACHE = undefined; - this.__EXTRACTED_TX = undefined; + c.__TX.ins[inputIndex].sequence = sequence; + c.__TX_BUF_CACHE = undefined; + c.__EXTRACTED_TX = undefined; return this; } addInput(inputData) { checkInputsForPartialSig(this.inputs, 'addInput'); - const self = this; - const inputAdder = (_inputData, txBuf) => { - if ( - !txBuf || - _inputData.hash === undefined || - _inputData.index === undefined || - (!Buffer.isBuffer(_inputData.hash) && - typeof _inputData.hash !== 'string') || - typeof _inputData.index !== 'number' - ) { - throw new Error('Error adding input.'); - } - const prevHash = Buffer.isBuffer(_inputData.hash) - ? _inputData.hash - : bufferutils_1.reverseBuffer(Buffer.from(_inputData.hash, 'hex')); - // Check if input already exists in cache. - const input = { hash: prevHash, index: _inputData.index }; - checkTxInputCache(self.__CACHE, input); - self.__TX.ins.push( - Object.assign({}, input, { - script: Buffer.alloc(0), - sequence: - _inputData.sequence || transaction_1.Transaction.DEFAULT_SEQUENCE, - witness: [], - }), - ); - return self.__TX.toBuffer(); - }; + const inputAdder = getInputAdder(this.__CACHE); super.addInput(inputData, inputAdder); - this.__FEE_RATE = undefined; - this.__EXTRACTED_TX = undefined; + this.__CACHE.__FEE_RATE = undefined; + this.__CACHE.__EXTRACTED_TX = undefined; return this; } addOutput(outputData) { @@ -182,15 +159,15 @@ class Psbt extends bip174_1.Psbt { ) { throw new Error('Error adding output.'); } - self.__TX.outs.push({ + self.__CACHE.__TX.outs.push({ script: _outputData.script, value: _outputData.value, }); - return self.__TX.toBuffer(); + return self.__CACHE.__TX.toBuffer(); }; super.addOutput(outputData, true, outputAdder); - this.__FEE_RATE = undefined; - this.__EXTRACTED_TX = undefined; + this.__CACHE.__FEE_RATE = undefined; + this.__CACHE.__EXTRACTED_TX = undefined; return this; } addNonWitnessUtxoToInput(inputIndex, nonWitnessUtxo) { @@ -202,8 +179,8 @@ class Psbt extends bip174_1.Psbt { extractTransaction(disableFeeCheck) { if (!this.inputs.every(isFinalized)) throw new Error('Not finalized'); if (!disableFeeCheck) { - const feeRate = this.__FEE_RATE || this.getFeeRate(); - const vsize = this.__EXTRACTED_TX.virtualSize(); + const feeRate = this.__CACHE.__FEE_RATE || this.getFeeRate(); + const vsize = this.__CACHE.__EXTRACTED_TX.virtualSize(); const satoshis = feeRate * vsize; if (feeRate >= this.opts.maximumFeeRate) { throw new Error( @@ -215,8 +192,8 @@ class Psbt extends bip174_1.Psbt { ); } } - if (this.__EXTRACTED_TX) return this.__EXTRACTED_TX; - const tx = this.__TX.clone(); + if (this.__CACHE.__EXTRACTED_TX) return this.__CACHE.__EXTRACTED_TX; + const tx = this.__CACHE.__TX.clone(); this.inputs.forEach((input, idx) => { if (input.finalScriptSig) tx.ins[idx].script = input.finalScriptSig; if (input.finalScriptWitness) { @@ -225,21 +202,21 @@ class Psbt extends bip174_1.Psbt { ); } }); - this.__EXTRACTED_TX = tx; + this.__CACHE.__EXTRACTED_TX = tx; return tx; } getFeeRate() { if (!this.inputs.every(isFinalized)) throw new Error('PSBT must be finalized to calculate fee rate'); - if (this.__FEE_RATE) return this.__FEE_RATE; + if (this.__CACHE.__FEE_RATE) return this.__CACHE.__FEE_RATE; let tx; let inputAmount = 0; let mustFinalize = true; - if (this.__EXTRACTED_TX) { - tx = this.__EXTRACTED_TX; + if (this.__CACHE.__EXTRACTED_TX) { + tx = this.__CACHE.__EXTRACTED_TX; mustFinalize = false; } else { - tx = this.__TX.clone(); + tx = this.__CACHE.__TX.clone(); } this.inputs.forEach((input, idx) => { if (mustFinalize && input.finalScriptSig) @@ -253,17 +230,17 @@ class Psbt extends bip174_1.Psbt { inputAmount += input.witnessUtxo.value; } else if (input.nonWitnessUtxo) { const nwTx = nonWitnessUtxoTxFromCache(this.__CACHE, input, idx); - const vout = this.__TX.ins[idx].index; + const vout = this.__CACHE.__TX.ins[idx].index; const out = nwTx.outs[vout]; inputAmount += out.value; } }); - this.__EXTRACTED_TX = tx; + this.__CACHE.__EXTRACTED_TX = tx; const outputAmount = tx.outs.reduce((total, o) => total + o.value, 0); const fee = inputAmount - outputAmount; const bytes = tx.virtualSize(); - this.__FEE_RATE = Math.floor(fee / bytes); - return this.__FEE_RATE; + this.__CACHE.__FEE_RATE = Math.floor(fee / bytes); + return this.__CACHE.__FEE_RATE; } finalizeAllInputs() { const inputResults = range(this.inputs.length).map(idx => @@ -280,7 +257,7 @@ class Psbt extends bip174_1.Psbt { const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput( inputIndex, input, - this.__TX, + this.__CACHE.__TX, this.__CACHE, ); if (!script) return false; @@ -322,7 +299,7 @@ class Psbt extends bip174_1.Psbt { ? getHashForSig( inputIndex, Object.assign({}, input, { sighashType: sig.hashType }), - this.__TX, + this.__CACHE.__TX, this.__CACHE, ) : { hash: hashCache, script: scriptCache }; @@ -391,7 +368,7 @@ class Psbt extends bip174_1.Psbt { this.inputs, inputIndex, keyPair.publicKey, - this.__TX, + this.__CACHE.__TX, this.__CACHE, ); const partialSig = { @@ -408,7 +385,7 @@ class Psbt extends bip174_1.Psbt { this.inputs, inputIndex, keyPair.publicKey, - this.__TX, + this.__CACHE.__TX, this.__CACHE, ); Promise.resolve(keyPair.sign(hash)).then(signature => { @@ -847,6 +824,36 @@ function nonWitnessUtxoTxFromCache(cache, input, inputIndex) { } return cache.__NON_WITNESS_UTXO_TX_CACHE[inputIndex]; } +function getInputAdder(cache) { + const selfCache = cache; + return (_inputData, txBuf) => { + if ( + !txBuf || + _inputData.hash === undefined || + _inputData.index === undefined || + (!Buffer.isBuffer(_inputData.hash) && + typeof _inputData.hash !== 'string') || + typeof _inputData.index !== 'number' + ) { + throw new Error('Error adding input.'); + } + const prevHash = Buffer.isBuffer(_inputData.hash) + ? _inputData.hash + : bufferutils_1.reverseBuffer(Buffer.from(_inputData.hash, 'hex')); + // Check if input already exists in cache. + const input = { hash: prevHash, index: _inputData.index }; + checkTxInputCache(selfCache, input); + selfCache.__TX.ins.push( + Object.assign({}, input, { + script: Buffer.alloc(0), + sequence: + _inputData.sequence || transaction_1.Transaction.DEFAULT_SEQUENCE, + witness: [], + }), + ); + return selfCache.__TX.toBuffer(); + }; +} function check32Bit(num) { if ( typeof num !== 'number' || diff --git a/test/psbt.js b/test/psbt.js index cd45c1e..657a67a 100644 --- a/test/psbt.js +++ b/test/psbt.js @@ -397,9 +397,9 @@ describe(`Psbt`, () => { }); assert.strictEqual(psbt.inputCount, 1) - assert.strictEqual(psbt.__TX.ins[0].sequence, 0xffffffff) + assert.strictEqual(psbt.__CACHE.__TX.ins[0].sequence, 0xffffffff) psbt.setSequence(0, 0) - assert.strictEqual(psbt.__TX.ins[0].sequence, 0) + assert.strictEqual(psbt.__CACHE.__TX.ins[0].sequence, 0) }) it('throws if input index is too high', () => { @@ -467,24 +467,24 @@ describe(`Psbt`, () => { it('fromTransaction returns Psbt type (not base class)', () => { const psbt = Psbt.fromTransaction(Buffer.from([2,0,0,0,0,0,0,0,0,0])); assert.strictEqual(psbt instanceof Psbt, true); - assert.ok(psbt.__TX); + assert.ok(psbt.__CACHE.__TX); }) it('fromBuffer returns Psbt type (not base class)', () => { const psbt = Psbt.fromBuffer(Buffer.from( '70736274ff01000a01000000000000000000000000', 'hex' //cHNidP8BAAoBAAAAAAAAAAAAAAAA )); assert.strictEqual(psbt instanceof Psbt, true); - assert.ok(psbt.__TX); + assert.ok(psbt.__CACHE.__TX); }) it('fromBase64 returns Psbt type (not base class)', () => { const psbt = Psbt.fromBase64('cHNidP8BAAoBAAAAAAAAAAAAAAAA'); assert.strictEqual(psbt instanceof Psbt, true); - assert.ok(psbt.__TX); + assert.ok(psbt.__CACHE.__TX); }) it('fromHex returns Psbt type (not base class)', () => { const psbt = Psbt.fromHex('70736274ff01000a01000000000000000000000000'); assert.strictEqual(psbt instanceof Psbt, true); - assert.ok(psbt.__TX); + assert.ok(psbt.__CACHE.__TX); }) }) }) diff --git a/ts_src/psbt.ts b/ts_src/psbt.ts index 272ac8e..0174b3b 100644 --- a/ts_src/psbt.ts +++ b/ts_src/psbt.ts @@ -34,7 +34,7 @@ export class Psbt extends PsbtBase { const tx = Transaction.fromBuffer(txBuf); checkTxEmpty(tx); const psbt = new this() as Psbt; - psbt.__TX = tx; + psbt.__CACHE.__TX = tx; checkTxForDupeIns(tx, psbt.__CACHE); let inputCount = tx.ins.length; let outputCount = tx.outs.length; @@ -71,25 +71,22 @@ export class Psbt extends PsbtBase { }; }; const psbt = super.fromBuffer(buffer, txCountGetter) as Psbt; - psbt.__TX = tx!; + psbt.__CACHE.__TX = tx!; checkTxForDupeIns(tx!, psbt.__CACHE); return psbt as InstanceType; } - private __CACHE = { - __NON_WITNESS_UTXO_TX_CACHE: [] as Transaction[], - __NON_WITNESS_UTXO_BUF_CACHE: [] as Buffer[], - __TX_IN_CACHE: {} as { [index: string]: number }, + private __CACHE: PsbtCache = { + __NON_WITNESS_UTXO_TX_CACHE: [], + __NON_WITNESS_UTXO_BUF_CACHE: [], + __TX_IN_CACHE: {}, + __TX: new Transaction(), }; - private __TX: Transaction; - private __TX_BUF_CACHE?: Buffer; - private __FEE_RATE?: number; - private __EXTRACTED_TX?: Transaction; private opts: PsbtOpts; constructor(opts: PsbtOptsOptional = {}) { super(); // set defaults this.opts = Object.assign({}, DEFAULT_OPTS, opts); - this.__TX = Transaction.fromBuffer(this.globalMap.unsignedTx!); + this.__CACHE.__TX = Transaction.fromBuffer(this.globalMap.unsignedTx!); this.setVersion(2); // set cache @@ -98,15 +95,15 @@ export class Psbt extends PsbtBase { Object.defineProperty(this.globalMap, 'unsignedTx', { enumerable: true, get(): Buffer { - if (self.__TX_BUF_CACHE !== undefined) { - return self.__TX_BUF_CACHE; + if (self.__CACHE.__TX_BUF_CACHE !== undefined) { + return self.__CACHE.__TX_BUF_CACHE; } else { - self.__TX_BUF_CACHE = self.__TX.toBuffer(); - return self.__TX_BUF_CACHE; + self.__CACHE.__TX_BUF_CACHE = self.__CACHE.__TX.toBuffer(); + return self.__CACHE.__TX_BUF_CACHE; } }, set(data: Buffer): void { - self.__TX_BUF_CACHE = data; + self.__CACHE.__TX_BUF_CACHE = data; }, }); @@ -123,8 +120,6 @@ export class Psbt extends PsbtBase { }); dpew(this, '__TX', false, true); dpew(this, '__EXTRACTED_TX', false, true); - dpew(this, '__FEE_RATE', false, true); - dpew(this, '__TX_BUF_CACHE', false, true); dpew(this, '__CACHE', false, true); dpew(this, 'opts', false, true); } @@ -141,69 +136,42 @@ export class Psbt extends PsbtBase { setVersion(version: number): this { check32Bit(version); checkInputsForPartialSig(this.inputs, 'setVersion'); - this.__TX.version = version; - this.__TX_BUF_CACHE = undefined; - this.__EXTRACTED_TX = undefined; + const c = this.__CACHE; + c.__TX.version = version; + c.__TX_BUF_CACHE = undefined; + c.__EXTRACTED_TX = undefined; return this; } setLocktime(locktime: number): this { check32Bit(locktime); checkInputsForPartialSig(this.inputs, 'setLocktime'); - this.__TX.locktime = locktime; - this.__TX_BUF_CACHE = undefined; - this.__EXTRACTED_TX = undefined; + const c = this.__CACHE; + c.__TX.locktime = locktime; + c.__TX_BUF_CACHE = undefined; + c.__EXTRACTED_TX = undefined; return this; } setSequence(inputIndex: number, sequence: number): this { check32Bit(sequence); checkInputsForPartialSig(this.inputs, 'setSequence'); - if (this.__TX.ins.length <= inputIndex) { + const c = this.__CACHE; + if (c.__TX.ins.length <= inputIndex) { throw new Error('Input index too high'); } - this.__TX.ins[inputIndex].sequence = sequence; - this.__TX_BUF_CACHE = undefined; - this.__EXTRACTED_TX = undefined; + c.__TX.ins[inputIndex].sequence = sequence; + c.__TX_BUF_CACHE = undefined; + c.__EXTRACTED_TX = undefined; return this; } addInput(inputData: TransactionInput): this { checkInputsForPartialSig(this.inputs, 'addInput'); - const self = this; - const inputAdder = ( - _inputData: TransactionInput, - txBuf: Buffer, - ): Buffer => { - if ( - !txBuf || - (_inputData as any).hash === undefined || - (_inputData as any).index === undefined || - (!Buffer.isBuffer((_inputData as any).hash) && - typeof (_inputData as any).hash !== 'string') || - typeof (_inputData as any).index !== 'number' - ) { - throw new Error('Error adding input.'); - } - const prevHash = Buffer.isBuffer(_inputData.hash) - ? _inputData.hash - : reverseBuffer(Buffer.from(_inputData.hash, 'hex')); - - // Check if input already exists in cache. - const input = { hash: prevHash, index: _inputData.index }; - checkTxInputCache(self.__CACHE, input); - - self.__TX.ins.push({ - ...input, - script: Buffer.alloc(0), - sequence: _inputData.sequence || Transaction.DEFAULT_SEQUENCE, - witness: [], - }); - return self.__TX.toBuffer(); - }; + const inputAdder = getInputAdder(this.__CACHE); super.addInput(inputData, inputAdder); - this.__FEE_RATE = undefined; - this.__EXTRACTED_TX = undefined; + this.__CACHE.__FEE_RATE = undefined; + this.__CACHE.__EXTRACTED_TX = undefined; return this; } @@ -229,15 +197,15 @@ export class Psbt extends PsbtBase { ) { throw new Error('Error adding output.'); } - self.__TX.outs.push({ + self.__CACHE.__TX.outs.push({ script: (_outputData as any).script!, value: _outputData.value, }); - return self.__TX.toBuffer(); + return self.__CACHE.__TX.toBuffer(); }; super.addOutput(outputData, true, outputAdder); - this.__FEE_RATE = undefined; - this.__EXTRACTED_TX = undefined; + this.__CACHE.__FEE_RATE = undefined; + this.__CACHE.__EXTRACTED_TX = undefined; return this; } @@ -254,8 +222,8 @@ export class Psbt extends PsbtBase { extractTransaction(disableFeeCheck?: boolean): Transaction { if (!this.inputs.every(isFinalized)) throw new Error('Not finalized'); if (!disableFeeCheck) { - const feeRate = this.__FEE_RATE || this.getFeeRate(); - const vsize = this.__EXTRACTED_TX!.virtualSize(); + const feeRate = this.__CACHE.__FEE_RATE || this.getFeeRate(); + const vsize = this.__CACHE.__EXTRACTED_TX!.virtualSize(); const satoshis = feeRate * vsize; if (feeRate >= this.opts.maximumFeeRate) { throw new Error( @@ -267,8 +235,8 @@ export class Psbt extends PsbtBase { ); } } - if (this.__EXTRACTED_TX) return this.__EXTRACTED_TX; - const tx = this.__TX.clone(); + if (this.__CACHE.__EXTRACTED_TX) return this.__CACHE.__EXTRACTED_TX; + const tx = this.__CACHE.__TX.clone(); this.inputs.forEach((input, idx) => { if (input.finalScriptSig) tx.ins[idx].script = input.finalScriptSig; if (input.finalScriptWitness) { @@ -277,22 +245,22 @@ export class Psbt extends PsbtBase { ); } }); - this.__EXTRACTED_TX = tx; + this.__CACHE.__EXTRACTED_TX = tx; return tx; } getFeeRate(): number { if (!this.inputs.every(isFinalized)) throw new Error('PSBT must be finalized to calculate fee rate'); - if (this.__FEE_RATE) return this.__FEE_RATE; + if (this.__CACHE.__FEE_RATE) return this.__CACHE.__FEE_RATE; let tx: Transaction; let inputAmount = 0; let mustFinalize = true; - if (this.__EXTRACTED_TX) { - tx = this.__EXTRACTED_TX; + if (this.__CACHE.__EXTRACTED_TX) { + tx = this.__CACHE.__EXTRACTED_TX; mustFinalize = false; } else { - tx = this.__TX.clone(); + tx = this.__CACHE.__TX.clone(); } this.inputs.forEach((input, idx) => { if (mustFinalize && input.finalScriptSig) @@ -306,20 +274,20 @@ export class Psbt extends PsbtBase { inputAmount += input.witnessUtxo.value; } else if (input.nonWitnessUtxo) { const nwTx = nonWitnessUtxoTxFromCache(this.__CACHE, input, idx); - const vout = this.__TX.ins[idx].index; + const vout = this.__CACHE.__TX.ins[idx].index; const out = nwTx.outs[vout] as Output; inputAmount += out.value; } }); - this.__EXTRACTED_TX = tx; + this.__CACHE.__EXTRACTED_TX = tx; const outputAmount = (tx.outs as Output[]).reduce( (total, o) => total + o.value, 0, ); const fee = inputAmount - outputAmount; const bytes = tx.virtualSize(); - this.__FEE_RATE = Math.floor(fee / bytes); - return this.__FEE_RATE; + this.__CACHE.__FEE_RATE = Math.floor(fee / bytes); + return this.__CACHE.__FEE_RATE; } finalizeAllInputs(): { @@ -341,7 +309,7 @@ export class Psbt extends PsbtBase { const { script, isP2SH, isP2WSH, isSegwit } = getScriptFromInput( inputIndex, input, - this.__TX, + this.__CACHE.__TX, this.__CACHE, ); if (!script) return false; @@ -388,7 +356,7 @@ export class Psbt extends PsbtBase { ? getHashForSig( inputIndex, Object.assign({}, input, { sighashType: sig.hashType }), - this.__TX, + this.__CACHE.__TX, this.__CACHE, ) : { hash: hashCache!, script: scriptCache! }; @@ -464,7 +432,7 @@ export class Psbt extends PsbtBase { this.inputs, inputIndex, keyPair.publicKey, - this.__TX, + this.__CACHE.__TX, this.__CACHE, ); @@ -485,7 +453,7 @@ export class Psbt extends PsbtBase { this.inputs, inputIndex, keyPair.publicKey, - this.__TX, + this.__CACHE.__TX, this.__CACHE, ); @@ -517,6 +485,10 @@ interface PsbtCache { __NON_WITNESS_UTXO_TX_CACHE: Transaction[]; __NON_WITNESS_UTXO_BUF_CACHE: Buffer[]; __TX_IN_CACHE: { [index: string]: number }; + __TX: Transaction; + __TX_BUF_CACHE?: Buffer; + __FEE_RATE?: number; + __EXTRACTED_TX?: Transaction; } interface PsbtOptsOptional { @@ -1065,6 +1037,39 @@ function nonWitnessUtxoTxFromCache( return cache.__NON_WITNESS_UTXO_TX_CACHE[inputIndex]; } +function getInputAdder( + cache: PsbtCache, +): (_inputData: TransactionInput, txBuf: Buffer) => Buffer { + const selfCache = cache; + return (_inputData: TransactionInput, txBuf: Buffer): Buffer => { + if ( + !txBuf || + (_inputData as any).hash === undefined || + (_inputData as any).index === undefined || + (!Buffer.isBuffer((_inputData as any).hash) && + typeof (_inputData as any).hash !== 'string') || + typeof (_inputData as any).index !== 'number' + ) { + throw new Error('Error adding input.'); + } + const prevHash = Buffer.isBuffer(_inputData.hash) + ? _inputData.hash + : reverseBuffer(Buffer.from(_inputData.hash, 'hex')); + + // Check if input already exists in cache. + const input = { hash: prevHash, index: _inputData.index }; + checkTxInputCache(selfCache, input); + + selfCache.__TX.ins.push({ + ...input, + script: Buffer.alloc(0), + sequence: _inputData.sequence || Transaction.DEFAULT_SEQUENCE, + witness: [], + }); + return selfCache.__TX.toBuffer(); + }; +} + function check32Bit(num: number): void { if ( typeof num !== 'number' || diff --git a/types/psbt.d.ts b/types/psbt.d.ts index b2893b8..775f3b0 100644 --- a/types/psbt.d.ts +++ b/types/psbt.d.ts @@ -8,10 +8,6 @@ export declare class Psbt extends PsbtBase { static fromTransaction(this: T, txBuf: Buffer): InstanceType; static fromBuffer(this: T, buffer: Buffer): InstanceType; private __CACHE; - private __TX; - private __TX_BUF_CACHE?; - private __FEE_RATE?; - private __EXTRACTED_TX?; private opts; constructor(opts?: PsbtOptsOptional); readonly inputCount: number;