diff --git a/modules/abstract-utxo/src/abstractUtxoCoin.ts b/modules/abstract-utxo/src/abstractUtxoCoin.ts index dccb1d666c..7eed62252e 100644 --- a/modules/abstract-utxo/src/abstractUtxoCoin.ts +++ b/modules/abstract-utxo/src/abstractUtxoCoin.ts @@ -55,7 +55,7 @@ import { v1Sweep, V1SweepParams, } from './recovery'; -import { isReplayProtectionUnspent } from './replayProtection'; +import { isReplayProtectionUnspent } from './transaction/fixedScript/replayProtection'; import { supportedCrossChainRecoveries } from './config'; import { assertValidTransactionRecipient, diff --git a/modules/abstract-utxo/src/index.ts b/modules/abstract-utxo/src/index.ts index 21e5287285..d045dd51e0 100644 --- a/modules/abstract-utxo/src/index.ts +++ b/modules/abstract-utxo/src/index.ts @@ -2,8 +2,8 @@ export * from './abstractUtxoCoin'; export * from './address'; export * from './config'; export * from './recovery'; -export * from './replayProtection'; -export * from './sign'; +export * from './transaction/fixedScript/replayProtection'; +export * from './transaction/fixedScript/sign'; export { UtxoWallet } from './wallet'; export * as descriptor from './descriptor'; diff --git a/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts b/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts index daaa2d0add..7a99b65760 100644 --- a/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts +++ b/modules/abstract-utxo/src/recovery/backupKeyRecovery.ts @@ -16,7 +16,7 @@ import { import { getMainnet, networks } from '@bitgo/utxo-lib'; import { AbstractUtxoCoin } from '../abstractUtxoCoin'; -import { signAndVerifyPsbt } from '../sign'; +import { signAndVerifyPsbt } from '../transaction/fixedScript/sign'; import { generateAddressWithChainAndIndex } from '../address'; import { forCoin, RecoveryProvider } from './RecoveryProvider'; diff --git a/modules/abstract-utxo/src/recovery/crossChainRecovery.ts b/modules/abstract-utxo/src/recovery/crossChainRecovery.ts index a09eccebbc..957ca89a67 100644 --- a/modules/abstract-utxo/src/recovery/crossChainRecovery.ts +++ b/modules/abstract-utxo/src/recovery/crossChainRecovery.ts @@ -5,7 +5,7 @@ import { BitGoBase, IWallet, Keychain, Triple, Wallet } from '@bitgo/sdk-core'; import { decrypt } from '@bitgo/sdk-api'; import { AbstractUtxoCoin, TransactionInfo } from '../abstractUtxoCoin'; -import { signAndVerifyWalletTransaction } from '../sign'; +import { signAndVerifyWalletTransaction } from '../transaction/fixedScript/sign'; const { unspentSum, scriptTypeForChain, outputScripts } = utxolib.bitgo; type RootWalletKeys = utxolib.bitgo.RootWalletKeys; diff --git a/modules/abstract-utxo/src/transaction/explainTransaction.ts b/modules/abstract-utxo/src/transaction/explainTransaction.ts index 18e083b5f1..57c3b0b14b 100644 --- a/modules/abstract-utxo/src/transaction/explainTransaction.ts +++ b/modules/abstract-utxo/src/transaction/explainTransaction.ts @@ -5,8 +5,8 @@ import { isTriple, IWallet, Triple } from '@bitgo/sdk-core'; import { getDescriptorMapFromWallet, isDescriptorWallet } from '../descriptor'; import { toBip32Triple } from '../keychains'; import { getPolicyForEnv } from '../descriptor/validatePolicy'; -import { getReplayProtectionOutputScripts } from '../replayProtection'; +import { getReplayProtectionOutputScripts } from './fixedScript/replayProtection'; import type { TransactionExplanationUtxolibLegacy, TransactionExplanationUtxolibPsbt, diff --git a/modules/abstract-utxo/src/transaction/fixedScript/index.ts b/modules/abstract-utxo/src/transaction/fixedScript/index.ts index a1290e62a2..a4a5348e7f 100644 --- a/modules/abstract-utxo/src/transaction/fixedScript/index.ts +++ b/modules/abstract-utxo/src/transaction/fixedScript/index.ts @@ -4,3 +4,5 @@ export { parseTransaction } from './parseTransaction'; export { CustomChangeOptions } from './parseOutput'; export { verifyTransaction } from './verifyTransaction'; export { signTransaction } from './signTransaction'; +export * from './sign'; +export * from './replayProtection'; diff --git a/modules/abstract-utxo/src/replayProtection.ts b/modules/abstract-utxo/src/transaction/fixedScript/replayProtection.ts similarity index 100% rename from modules/abstract-utxo/src/replayProtection.ts rename to modules/abstract-utxo/src/transaction/fixedScript/replayProtection.ts diff --git a/modules/abstract-utxo/src/sign.ts b/modules/abstract-utxo/src/transaction/fixedScript/sign.ts similarity index 93% rename from modules/abstract-utxo/src/sign.ts rename to modules/abstract-utxo/src/transaction/fixedScript/sign.ts index e81a574821..ddba7bc73e 100644 --- a/modules/abstract-utxo/src/sign.ts +++ b/modules/abstract-utxo/src/transaction/fixedScript/sign.ts @@ -1,7 +1,7 @@ import * as utxolib from '@bitgo/utxo-lib'; import debugLib from 'debug'; -import { isReplayProtectionUnspent } from './replayProtection'; +import { getReplayProtectionAddresses } from './replayProtection'; const debug = debugLib('bitgo:v2:utxo'); @@ -139,14 +139,24 @@ export function signAndVerifyPsbt( * @param unspents - transaction unspents * @param walletSigner - signing parameters * @param isLastSignature - Returns full-signed transaction when true. Builds half-signed when false. + * @param replayProtectionAddresses - List of replay protection addresses to skip signing */ export function signAndVerifyWalletTransaction( transaction: utxolib.bitgo.UtxoTransaction | utxolib.bitgo.UtxoTransactionBuilder, unspents: Unspent[], walletSigner: utxolib.bitgo.WalletUnspentSigner, - { isLastSignature }: { isLastSignature: boolean } + { + isLastSignature, + replayProtectionAddresses, + }: { + isLastSignature: boolean; + replayProtectionAddresses?: string[]; + } ): utxolib.bitgo.UtxoTransaction { const network = transaction.network as utxolib.Network; + if (replayProtectionAddresses === undefined) { + replayProtectionAddresses = getReplayProtectionAddresses(network); + } const prevOutputs = unspents.map((u) => toOutput(u, network)); let txBuilder: utxolib.bitgo.UtxoTransactionBuilder; @@ -163,7 +173,7 @@ export function signAndVerifyWalletTransaction( const signErrors: InputSigningError[] = unspents .map((unspent: Unspent, inputIndex: number) => { - if (isReplayProtectionUnspent(unspent, network)) { + if (replayProtectionAddresses.includes(unspent.address)) { debug('Skipping signature for input %d of %d (RP input?)', inputIndex + 1, unspents.length); return; } @@ -184,7 +194,7 @@ export function signAndVerifyWalletTransaction( const verifyErrors: InputSigningError[] = signedTransaction.ins .map((input, inputIndex) => { const unspent = unspents[inputIndex] as Unspent; - if (isReplayProtectionUnspent(unspent, network)) { + if (replayProtectionAddresses.includes(unspent.address)) { debug( 'Skipping input signature %d of %d (unspent from replay protection address which is platform signed only)', inputIndex + 1, diff --git a/modules/abstract-utxo/src/transaction/fixedScript/signTransaction.ts b/modules/abstract-utxo/src/transaction/fixedScript/signTransaction.ts index 823fe68be8..27c6854a21 100644 --- a/modules/abstract-utxo/src/transaction/fixedScript/signTransaction.ts +++ b/modules/abstract-utxo/src/transaction/fixedScript/signTransaction.ts @@ -6,9 +6,10 @@ import { bitgo } from '@bitgo/utxo-lib'; import * as utxolib from '@bitgo/utxo-lib'; import { isTriple, Triple } from '@bitgo/sdk-core'; -import { signAndVerifyPsbt, signAndVerifyWalletTransaction } from '../../sign'; import { AbstractUtxoCoin, DecodedTransaction, RootWalletKeys } from '../../abstractUtxoCoin'; +import { signAndVerifyPsbt, signAndVerifyWalletTransaction } from './sign'; + /** * Key Value: Unsigned tx id => PSBT * It is used to cache PSBTs with taproot key path (MuSig2) inputs during external express signer is activated.