From 6e242378d5d71688be0cfacb5d8e7641d753b2cb Mon Sep 17 00:00:00 2001 From: Eric Taylor Date: Wed, 27 Nov 2024 14:19:50 -0700 Subject: [PATCH 1/3] fix: filter utxos in etna import tx builder --- src/vms/pvm/etna-builder/builder.ts | 90 ++++++++++++++--------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/vms/pvm/etna-builder/builder.ts b/src/vms/pvm/etna-builder/builder.ts index 8221c2cbf..b45994161 100644 --- a/src/vms/pvm/etna-builder/builder.ts +++ b/src/vms/pvm/etna-builder/builder.ts @@ -302,50 +302,50 @@ export const newImportTx: TxBuilderFn = ( ) => { const fromAddresses = addressesFromBytes(fromAddressesBytes); - const { importedInputs, importedAmounts } = utxos - .filter( - (utxo): utxo is Utxo => - isTransferOut(utxo.output) && - // Currently - only AVAX is allowed to be imported to the P-Chain - utxo.assetId.toString() === context.avaxAssetID, - ) - .reduce<{ - importedInputs: TransferableInput[]; - importedAmounts: Record; - }>( - (acc, utxo) => { - const { sigIndicies: inputSigIndices } = - matchOwners(utxo.getOutputOwners(), fromAddresses, minIssuanceTime) || - {}; - - if (inputSigIndices === undefined) { - // We couldn't spend this UTXO, so we skip to the next one. - return acc; - } - - const assetId = utxo.getAssetId(); - - return { - importedInputs: [ - ...acc.importedInputs, - new TransferableInput( - utxo.utxoId, - utxo.assetId, - new TransferInput( - utxo.output.amt, - new Input(inputSigIndices.map((value) => new Int(value))), - ), + const filteredUtxos = utxos.filter( + (utxo): utxo is Utxo => + isTransferOut(utxo.output) && + // Currently - only AVAX is allowed to be imported to the P-Chain + utxo.assetId.toString() === context.avaxAssetID, + ); + + const { importedInputs, importedAmounts } = filteredUtxos.reduce<{ + importedInputs: TransferableInput[]; + importedAmounts: Record; + }>( + (acc, utxo) => { + const { sigIndicies: inputSigIndices } = + matchOwners(utxo.getOutputOwners(), fromAddresses, minIssuanceTime) || + {}; + + if (inputSigIndices === undefined) { + // We couldn't spend this UTXO, so we skip to the next one. + return acc; + } + + const assetId = utxo.getAssetId(); + + return { + importedInputs: [ + ...acc.importedInputs, + new TransferableInput( + utxo.utxoId, + utxo.assetId, + new TransferInput( + utxo.output.amt, + new Input(inputSigIndices.map((value) => new Int(value))), ), - ], - importedAmounts: { - ...acc.importedAmounts, - [assetId]: - (acc.importedAmounts[assetId] ?? 0n) + utxo.output.amount(), - }, - }; - }, - { importedInputs: [], importedAmounts: {} }, - ); + ), + ], + importedAmounts: { + ...acc.importedAmounts, + [assetId]: + (acc.importedAmounts[assetId] ?? 0n) + utxo.output.amount(), + }, + }; + }, + { importedInputs: [], importedAmounts: {} }, + ); if (importedInputs.length === 0) { throw new Error('no UTXOs available to import'); @@ -355,7 +355,7 @@ export const newImportTx: TxBuilderFn = ( const addressMaps = AddressMaps.fromTransferableInputs( importedInputs, - utxos, + filteredUtxos, minIssuanceTime, fromAddressesBytes, ); @@ -391,7 +391,7 @@ export const newImportTx: TxBuilderFn = ( fromAddresses, initialComplexity: complexity, minIssuanceTime, - utxos, + utxos: filteredUtxos, }, [useUnlockedUTXOs], context, From ea9f31ea7dc68d21e2c65f4b058eb2496224a85a Mon Sep 17 00:00:00 2001 From: Eric Taylor Date: Wed, 27 Nov 2024 14:36:18 -0700 Subject: [PATCH 2/3] fix: correct unsigned tx utxos on etna import tx builder --- src/vms/pvm/etna-builder/builder.test.ts | 6 ++++++ src/vms/pvm/etna-builder/builder.ts | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/vms/pvm/etna-builder/builder.test.ts b/src/vms/pvm/etna-builder/builder.test.ts index 1a0b71246..6ba28dfb5 100644 --- a/src/vms/pvm/etna-builder/builder.test.ts +++ b/src/vms/pvm/etna-builder/builder.test.ts @@ -308,6 +308,12 @@ describe('./src/vms/pvm/etna-builder/builder.test.ts', () => { ); expectTxs(unsignedTx.getTx(), expectedTx); + + // Ensure that the unsigned tx utxos are the filtered utxos, + // and not the inputUtxos registered in the spend helper. + // This is only relevant for the ImportTx. + expect(unsignedTx.utxos).toHaveLength(2); + expect(unsignedTx.utxos).not.toContain(utxos[1]); }); test('newExportTx', () => { diff --git a/src/vms/pvm/etna-builder/builder.ts b/src/vms/pvm/etna-builder/builder.ts index b45994161..118d25513 100644 --- a/src/vms/pvm/etna-builder/builder.ts +++ b/src/vms/pvm/etna-builder/builder.ts @@ -397,7 +397,7 @@ export const newImportTx: TxBuilderFn = ( context, ); - const { changeOutputs, inputs, inputUTXOs } = spendResults; + const { changeOutputs, inputs } = spendResults; return new UnsignedTx( new ImportTx( @@ -411,7 +411,7 @@ export const newImportTx: TxBuilderFn = ( Id.fromString(sourceChainId), importedInputs.sort(TransferableInput.compare), ), - inputUTXOs, + filteredUtxos, addressMaps, ); }; From cf709de3a4ab2368b5afd9956df429fb9dd30d3d Mon Sep 17 00:00:00 2001 From: Eric Taylor Date: Wed, 27 Nov 2024 14:49:56 -0700 Subject: [PATCH 3/3] fix: use utxos that were imported --- src/vms/pvm/etna-builder/builder.test.ts | 3 ++- src/vms/pvm/etna-builder/builder.ts | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/vms/pvm/etna-builder/builder.test.ts b/src/vms/pvm/etna-builder/builder.test.ts index 6ba28dfb5..df0ee6d8c 100644 --- a/src/vms/pvm/etna-builder/builder.test.ts +++ b/src/vms/pvm/etna-builder/builder.test.ts @@ -312,7 +312,8 @@ describe('./src/vms/pvm/etna-builder/builder.test.ts', () => { // Ensure that the unsigned tx utxos are the filtered utxos, // and not the inputUtxos registered in the spend helper. // This is only relevant for the ImportTx. - expect(unsignedTx.utxos).toHaveLength(2); + expect(unsignedTx.utxos).toHaveLength(1); + expect(unsignedTx.utxos).not.toContain(utxos[0]); expect(unsignedTx.utxos).not.toContain(utxos[1]); }); diff --git a/src/vms/pvm/etna-builder/builder.ts b/src/vms/pvm/etna-builder/builder.ts index 118d25513..2e26d9170 100644 --- a/src/vms/pvm/etna-builder/builder.ts +++ b/src/vms/pvm/etna-builder/builder.ts @@ -309,9 +309,10 @@ export const newImportTx: TxBuilderFn = ( utxo.assetId.toString() === context.avaxAssetID, ); - const { importedInputs, importedAmounts } = filteredUtxos.reduce<{ + const { importedInputs, importedAmounts, inputUtxos } = filteredUtxos.reduce<{ importedInputs: TransferableInput[]; importedAmounts: Record; + inputUtxos: Utxo[]; }>( (acc, utxo) => { const { sigIndicies: inputSigIndices } = @@ -342,9 +343,10 @@ export const newImportTx: TxBuilderFn = ( [assetId]: (acc.importedAmounts[assetId] ?? 0n) + utxo.output.amount(), }, + inputUtxos: [...acc.inputUtxos, utxo], }; }, - { importedInputs: [], importedAmounts: {} }, + { importedInputs: [], importedAmounts: {}, inputUtxos: [] }, ); if (importedInputs.length === 0) { @@ -397,6 +399,9 @@ export const newImportTx: TxBuilderFn = ( context, ); + // Note: We don't use the `inputUTXOs` from `spendResults` + // for the `UnsignedTx` because we want to use the original + // UTXOs that were imported. const { changeOutputs, inputs } = spendResults; return new UnsignedTx( @@ -411,7 +416,7 @@ export const newImportTx: TxBuilderFn = ( Id.fromString(sourceChainId), importedInputs.sort(TransferableInput.compare), ), - filteredUtxos, + inputUtxos, addressMaps, ); };