diff --git a/modules/bitgo/test/v2/unit/internal/tssUtils/eddsa.ts b/modules/bitgo/test/v2/unit/internal/tssUtils/eddsa.ts index 59d55cb7e5..0602b58e3b 100644 --- a/modules/bitgo/test/v2/unit/internal/tssUtils/eddsa.ts +++ b/modules/bitgo/test/v2/unit/internal/tssUtils/eddsa.ts @@ -21,6 +21,7 @@ import { Eddsa, EncryptedSignerShareType, ExchangeCommitmentResponse, + InvalidTransactionError, Keychain, KeyShare, RequestTracer, @@ -127,9 +128,14 @@ describe('TSS Utils:', async function () { }, }; + // Sol TSS unsigned tx bytes — same fixtures as eddsaMPCv2/signTxRequest.ts + const solTssSignableHex = + '02010206c2d5b5f4fb9a9bcd8a2f303e4d06f78d8ded300713f456da2abff0b3ea0185aa051a34bc8acd438763976f96876115050f73828553566d111d7ac8bffebf587c4f5f5987bfe26aa66013efd96d36360f2b4336c91f993259fb56051305614d42f2ea13f8ff9d7958dbf269c6e36bfdf5cb5c43de4b4e1d3efb7dab3d5d028604000000000000000000000000000000000000000000000000000000000000000006a7d517192c568ee08a845f73d29788cf035c3145b21ab344d8062ea94000003a621f6d1cc4b8fb2a739aa08e4034da0fc588ece3bd857630de30f7edde45dd0204030205010404000000040200030c02000000f0a29a3b00000000'; + const solTssSerializedTxHex = `02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003bc9df0b397bec2ed3b6444a8c33f38267cc08b5fb2a7d37e26b6c487e26d15b7c07830eb78e26a88db5de4aa6986a327f09aed8c01533e5b972748ddf60b80f${solTssSignableHex}`; + const txRequest = { txRequestId: 'randomId', - unsignedTxs: [{ signableHex: 'MPC on a Friday night', serializedTxHex: 'MPC on a Friday night' }], + unsignedTxs: [{ signableHex: solTssSignableHex, serializedTxHex: solTssSerializedTxHex }], signatureShares: [ { from: 'bitgo', @@ -656,13 +662,21 @@ describe('TSS Utils:', async function () { txRequestId: 'v2-signing-test', unsignedTxs: [ { - serializedTxHex: 'test-payload', - signableHex: 'deadbeef', + serializedTxHex: solTssSerializedTxHex, + signableHex: solTssSignableHex, derivationPath: 'm/0', }, ], date: new Date().toISOString(), - intent: { intentType: 'payment' }, + intent: { + intentType: 'payment', + recipients: [ + { + address: { address: 'HMEgbR4S2hLKfst2VZUVpHVUu4FioFPyW5iUuJvZdMvs' }, + amount: { value: '999990000', symbol: 'tsol' }, + }, + ], + }, latest: true, state: 'pendingUserSignature', walletType: 'hot', @@ -672,6 +686,10 @@ describe('TSS Utils:', async function () { userId: 'userId', }; + beforeEach(function () { + sandbox.stub(baseCoin, 'verifyTransaction').resolves(true); + }); + it('v2 R-share round-trip: encrypt via commitment, verify envelope, decrypt via createRShare', async function () { const passphrase = 'test-passphrase'; const prv = JSON.stringify(validUserSigningMaterial); @@ -716,14 +734,20 @@ describe('TSS Utils:', async function () { transactions: [], unsignedTxs: [ { - serializedTxHex: 'MPC on a Friday night', - signableHex: 'MPC on a Friday night', + serializedTxHex: solTssSerializedTxHex, + signableHex: solTssSignableHex, derivationPath: 'm/0', }, ], date: new Date().toISOString(), intent: { intentType: 'payment', + recipients: [ + { + address: { address: 'HMEgbR4S2hLKfst2VZUVpHVUu4FioFPyW5iUuJvZdMvs' }, + amount: { value: '999990000', symbol: 'tsol' }, + }, + ], }, latest: true, state: 'pendingUserSignature', @@ -735,6 +759,8 @@ describe('TSS Utils:', async function () { }; beforeEach(async function () { + sandbox.stub(baseCoin, 'verifyTransaction').resolves(true); + const userSignShare = validUserSignShare; const rShare = userSignShare.rShares[3]; const signatureShare: SignatureShareRecord = { @@ -805,14 +831,20 @@ describe('TSS Utils:', async function () { transactions: [], unsignedTxs: [ { - serializedTxHex: 'MPC on a Friday night', - signableHex: 'MPC on a Friday night', + serializedTxHex: solTssSerializedTxHex, + signableHex: solTssSignableHex, derivationPath: 'm/0', }, ], date: new Date().toISOString(), intent: { intentType: 'payment', + recipients: [ + { + address: { address: 'HMEgbR4S2hLKfst2VZUVpHVUu4FioFPyW5iUuJvZdMvs' }, + amount: { value: '999990000', symbol: 'tsol' }, + }, + ], }, latest: true, state: 'pendingUserSignature', @@ -824,6 +856,8 @@ describe('TSS Utils:', async function () { }; beforeEach(async function () { + sandbox.stub(baseCoin, 'verifyTransaction').resolves(true); + const userSignShare = validUserSignShare; const rShare = userSignShare.rShares[3]; const signatureShare: SignatureShareRecord = { @@ -886,6 +920,201 @@ describe('TSS Utils:', async function () { }); }); + describe('signTxRequest resolveEffectiveTxParams guard:', function () { + const txRequestId = 'randomid-guard'; + const baseTxRequest: TxRequest = { + txRequestId, + transactions: [], + unsignedTxs: [ + { + serializedTxHex: solTssSerializedTxHex, + signableHex: solTssSignableHex, + derivationPath: 'm/0', + }, + ], + date: new Date().toISOString(), + intent: { + intentType: 'payment', + recipients: [ + { + address: { address: 'HMEgbR4S2hLKfst2VZUVpHVUu4FioFPyW5iUuJvZdMvs' }, + amount: { value: '999990000', symbol: 'tsol' }, + }, + ], + }, + latest: true, + state: 'pendingUserSignature', + walletType: 'hot', + walletId: 'walletId', + policiesChecked: true, + version: 1, + userId: 'userId', + }; + + it('throws InvalidTransactionError when txParams is absent and intent has no recipients', async function () { + const maliciousTxRequest: TxRequest = { + ...baseTxRequest, + intent: { intentType: 'stakingAuthorize' }, + }; + await tssUtils + .signTxRequest({ + txRequest: maliciousTxRequest, + prv: JSON.stringify(validUserSigningMaterial), + reqId, + }) + .should.be.rejectedWith(InvalidTransactionError); + }); + + it('uses intent recipients when txParams is absent', async function () { + const verifyStub = sandbox.stub(baseCoin, 'verifyTransaction').resolves(true); + + const userSignShare = validUserSignShare; + const rShare = userSignShare.rShares[3]; + const signatureShare: SignatureShareRecord = { + from: SignatureShareType.USER, + to: SignatureShareType.BITGO, + share: rShare.r + rShare.R, + }; + await nockSendSignatureShare({ + walletId: wallet.id(), + txRequestId: baseTxRequest.txRequestId, + signatureShare, + }); + const signatureShare2: SignatureShareRecord = { + from: SignatureShareType.BITGO, + to: SignatureShareType.USER, + share: validBitgoToUserSignShare.rShares[1].r + validBitgoToUserSignShare.rShares[1].R, + }; + const response = { txRequests: [{ ...baseTxRequest, signatureShares: [signatureShare2] }] }; + await nockGetTxRequest({ walletId: wallet.id(), txRequestId: baseTxRequest.txRequestId, response }); + const bitgoToUserCommitmentShare: CommitmentShareRecord = { + from: SignatureShareType.BITGO, + to: SignatureShareType.USER, + type: CommitmentType.COMMITMENT, + share: validBitgoToUserSignShare.rShares[1].commitment, + }; + await nockExchangeCommitments({ + walletId: wallet.id(), + txRequestId: baseTxRequest.txRequestId, + response: { commitmentShare: bitgoToUserCommitmentShare }, + }); + + await tssUtils.signTxRequest({ + txRequest: baseTxRequest, + prv: JSON.stringify(validUserSigningMaterial), + reqId, + }); + + verifyStub.calledOnce.should.be.true(); + const verifyArgs = verifyStub.firstCall.args[0]; + verifyArgs.txParams.recipients?.[0].address.should.equal('HMEgbR4S2hLKfst2VZUVpHVUu4FioFPyW5iUuJvZdMvs'); + }); + + it('does not throw for allowlisted no-recipient intentType (deactivate)', async function () { + const verifyStub = sandbox.stub(baseCoin, 'verifyTransaction').resolves(true); + + const deactivateTxRequest: TxRequest = { + ...baseTxRequest, + intent: { intentType: 'deactivate' }, + }; + + const userSignShare = validUserSignShare; + const rShare = userSignShare.rShares[3]; + const signatureShare: SignatureShareRecord = { + from: SignatureShareType.USER, + to: SignatureShareType.BITGO, + share: rShare.r + rShare.R, + }; + await nockSendSignatureShare({ + walletId: wallet.id(), + txRequestId: deactivateTxRequest.txRequestId, + signatureShare, + }); + const signatureShare2: SignatureShareRecord = { + from: SignatureShareType.BITGO, + to: SignatureShareType.USER, + share: validBitgoToUserSignShare.rShares[1].r + validBitgoToUserSignShare.rShares[1].R, + }; + const response = { txRequests: [{ ...deactivateTxRequest, signatureShares: [signatureShare2] }] }; + await nockGetTxRequest({ + walletId: wallet.id(), + txRequestId: deactivateTxRequest.txRequestId, + response, + }); + const bitgoToUserCommitmentShare: CommitmentShareRecord = { + from: SignatureShareType.BITGO, + to: SignatureShareType.USER, + type: CommitmentType.COMMITMENT, + share: validBitgoToUserSignShare.rShares[1].commitment, + }; + await nockExchangeCommitments({ + walletId: wallet.id(), + txRequestId: deactivateTxRequest.txRequestId, + response: { commitmentShare: bitgoToUserCommitmentShare }, + }); + + await tssUtils.signTxRequest({ + txRequest: deactivateTxRequest, + prv: JSON.stringify(validUserSigningMaterial), + reqId, + }); + + verifyStub.calledOnce.should.be.true(); + }); + }); + + describe('signEddsaTssUsingExternalSigner resolveEffectiveTxParams guard:', function () { + const externalGuardTxRequest: TxRequest = { + txRequestId: 'randomid-external-guard', + transactions: [], + unsignedTxs: [ + { + serializedTxHex: solTssSerializedTxHex, + signableHex: solTssSignableHex, + derivationPath: 'm/0', + }, + ], + date: new Date().toISOString(), + intent: { + intentType: 'payment', + recipients: [ + { + address: { address: 'HMEgbR4S2hLKfst2VZUVpHVUu4FioFPyW5iUuJvZdMvs' }, + amount: { value: '999990000', symbol: 'tsol' }, + }, + ], + }, + latest: true, + state: 'pendingUserSignature', + walletType: 'hot', + walletId: 'walletId', + policiesChecked: true, + version: 1, + userId: 'userId', + }; + + it('throws InvalidTransactionError before external signer callbacks when intent has no recipients', async function () { + const commitmentGen = sandbox.stub().rejects(new Error('should not run')); + const maliciousTxRequest: TxRequest = { + ...externalGuardTxRequest, + intent: { intentType: 'stakingAuthorize' }, + }; + await tssUtils + .signEddsaTssUsingExternalSigner( + maliciousTxRequest, + commitmentGen, + async function () { + throw new Error('should not run'); + }, + async function () { + throw new Error('should not run'); + } + ) + .should.be.rejectedWith(InvalidTransactionError); + commitmentGen.notCalled.should.be.true(); + }); + }); + describe('signTxRequestForMessage:', function () { const txRequestId = 'randomid-abc'; const messageRaw = 'hello world'; diff --git a/modules/bitgo/test/v2/unit/signTransactionVerification.ts b/modules/bitgo/test/v2/unit/signTransactionVerification.ts index b7a8945a3b..c6943d98a1 100644 --- a/modules/bitgo/test/v2/unit/signTransactionVerification.ts +++ b/modules/bitgo/test/v2/unit/signTransactionVerification.ts @@ -6,7 +6,14 @@ import 'should'; import { BitGoAPI } from '@bitgo/sdk-api'; import { TestBitGo } from '@bitgo/sdk-test'; import { Tbtc } from '@bitgo/sdk-coin-btc'; -import { common, BaseCoin, BitGoBase, Wallet, WalletSignTransactionOptions } from '@bitgo/sdk-core'; +import { + common, + BaseCoin, + BitGoBase, + InvalidTransactionError, + Wallet, + WalletSignTransactionOptions, +} from '@bitgo/sdk-core'; describe('Wallet signTransaction with verifyTxParams', function () { let wallet: Wallet; @@ -151,4 +158,18 @@ describe('Wallet signTransaction with verifyTxParams', function () { assert.strictEqual(verifyParams.txPrebuild.txHex, 'mock-tx-hex'); assert.deepStrictEqual(verifyParams.txParams, verifyTxParams.txParams); }); + + it('should throw when verifyTxParams is provided without txHex or TSS txRequestId', async function () { + const signParams: WalletSignTransactionOptions = { + txPrebuild: {}, + verifyTxParams: { + txParams: { + recipients: [{ address: 'test-address', amount: '1000' }], + }, + }, + }; + + await wallet.signTransaction(signParams).should.be.rejectedWith(InvalidTransactionError); + sinon.assert.notCalled(verifyTransactionStub); + }); }); diff --git a/modules/sdk-core/src/bitgo/utils/tss/baseTSSUtils.ts b/modules/sdk-core/src/bitgo/utils/tss/baseTSSUtils.ts index 311527e192..634809a733 100644 --- a/modules/sdk-core/src/bitgo/utils/tss/baseTSSUtils.ts +++ b/modules/sdk-core/src/bitgo/utils/tss/baseTSSUtils.ts @@ -1,7 +1,7 @@ import { EncryptionVersion, IRequestTracer } from '../../../api'; import * as openpgp from 'openpgp'; import { Key, readKey, SerializedKeyPair } from 'openpgp'; -import { IBaseCoin, KeychainsTriplet } from '../../baseCoin'; +import { IBaseCoin, KeychainsTriplet, TransactionParams } from '../../baseCoin'; import { BitGoBase } from '../../bitgoBase'; import { Keychain, KeyIndices, WebauthnKeyEncryptionInfo } from '../../keychain'; import { getTxRequest } from '../../tss'; @@ -269,7 +269,9 @@ export default class BaseTssUtils extends MpcUtils implements ITssUtil txRequest: string | TxRequest, externalSignerCommitmentGenerator: CustomCommitmentGeneratingFunction, externalSignerRShareGenerator: CustomRShareGeneratingFunction, - externalSignerGShareGenerator: CustomGShareGeneratingFunction + externalSignerGShareGenerator: CustomGShareGeneratingFunction, + _reqId?: IRequestTracer, + _txParams?: TransactionParams ): Promise { throw new Error('Method not implemented.'); } diff --git a/modules/sdk-core/src/bitgo/utils/tss/baseTypes.ts b/modules/sdk-core/src/bitgo/utils/tss/baseTypes.ts index 011cebbaea..697bf95fb2 100644 --- a/modules/sdk-core/src/bitgo/utils/tss/baseTypes.ts +++ b/modules/sdk-core/src/bitgo/utils/tss/baseTypes.ts @@ -915,7 +915,9 @@ export interface ITssUtils { txRequest: string | TxRequest, externalSignerCommitmentGenerator: CustomCommitmentGeneratingFunction, externalSignerRShareGenerator: CustomRShareGeneratingFunction, - externalSignerGShareGenerator: CustomGShareGeneratingFunction + externalSignerGShareGenerator: CustomGShareGeneratingFunction, + reqId?: IRequestTracer, + txParams?: TransactionParams ): Promise; signEcdsaTssUsingExternalSigner( params: TSSParams | TSSParamsForMessage, diff --git a/modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsa.ts b/modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsa.ts index 400d67402c..94247da5ba 100644 --- a/modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsa.ts +++ b/modules/sdk-core/src/bitgo/utils/tss/eddsa/eddsa.ts @@ -40,7 +40,7 @@ import { InvalidTransactionError } from '../../../errors'; import { CreateEddsaBitGoKeychainParams, CreateEddsaKeychainParams, KeyShare, YShare } from './types'; import baseTSSUtils from '../baseTSSUtils'; import { BaseEddsaUtils } from './base'; -import { KeychainsTriplet } from '../../../baseCoin'; +import { KeychainsTriplet, TransactionParams } from '../../../baseCoin'; import { exchangeEddsaCommitments } from '../../../tss/common'; import { Ed25519Bip32HdTree } from '@bitgo/sdk-lib-mpc'; import { EncryptionVersion, IRequestTracer } from '../../../../api'; @@ -48,6 +48,7 @@ import { envRequiresBitgoPubGpgKeyConfig, getBitgoMpcGpgPubKey, isBitgoMpcPubKey import { EnvironmentName } from '../../../environments'; import { readKey } from 'openpgp'; import type { EddsaKeyGenCallbacks } from '../../../wallet/iWallets'; +import { resolveEffectiveTxParams } from '../recipientUtils'; /** * Utility functions for TSS work flows. @@ -657,7 +658,8 @@ export class EddsaUtils extends baseTSSUtils { externalSignerCommitmentGenerator: CustomCommitmentGeneratingFunction, externalSignerRShareGenerator: CustomRShareGeneratingFunction, externalSignerGShareGenerator: CustomGShareGeneratingFunction, - reqId?: IRequestTracer + reqId?: IRequestTracer, + txParams?: TransactionParams ): Promise { let txRequestResolved: TxRequest; let txRequestId: string; @@ -669,6 +671,8 @@ export class EddsaUtils extends baseTSSUtils { txRequestId = txRequest.txRequestId; } + await this.verifyEdDsaTxRequestBeforeSigning(txRequestResolved, txParams); + const { apiVersion } = txRequestResolved; const bitgoGpgKey = await this.pickBitgoPubGpgKeyForSigning(false, reqId, txRequestResolved.enterpriseId); @@ -766,6 +770,8 @@ export class EddsaUtils extends baseTSSUtils { ); unsignedTx = apiVersion === 'full' ? txRequestResolved.transactions![0].unsignedTx : txRequestResolved.unsignedTxs[0]; + const txParams = 'txParams' in params ? params.txParams : undefined; + await this.verifyEdDsaTxRequestBeforeSigning(txRequestResolved, txParams); } else if (requestType === RequestType.message) { assert(txRequestResolved.messages?.length, 'Unable to find messages in txRequest for message signing'); const message = txRequestResolved.messages[0]; @@ -872,6 +878,24 @@ export class EddsaUtils extends baseTSSUtils { return BaseEddsaUtils.getPublicKeyFromCommonKeychain(commonKeychain); } + private async verifyEdDsaTxRequestBeforeSigning( + txRequestResolved: TxRequest, + txParams?: TransactionParams + ): Promise { + assert(txRequestResolved.transactions || txRequestResolved.unsignedTxs, 'Unable to find transactions in txRequest'); + const unsignedTx = + txRequestResolved.apiVersion === 'full' + ? txRequestResolved.transactions![0].unsignedTx + : txRequestResolved.unsignedTxs[0]; + assert(unsignedTx.signableHex, 'Missing signableHex in unsignedTx'); + await this.baseCoin.verifyTransaction({ + txPrebuild: { txHex: unsignedTx.serializedTxHex ?? unsignedTx.signableHex }, + txParams: resolveEffectiveTxParams(txRequestResolved, txParams, this.baseCoin.getChain()), + wallet: this.wallet, + walletType: this.wallet.multisigType(), + }); + } + createUserToBitgoCommitmentShare(commitment: string): CommitmentShareRecord { return { from: SignatureShareType.USER, diff --git a/modules/sdk-core/src/bitgo/wallet/iWallet.ts b/modules/sdk-core/src/bitgo/wallet/iWallet.ts index 435599da12..27bc4941c4 100644 --- a/modules/sdk-core/src/bitgo/wallet/iWallet.ts +++ b/modules/sdk-core/src/bitgo/wallet/iWallet.ts @@ -406,6 +406,8 @@ export interface WalletSignTransactionOptions extends WalletSignBaseOptions { txParams: TransactionParams; verification?: VerificationOptions; }; + /** Populated by wallet.verifyTxParams TSS path so signing uses the same txRequest that was verified. */ + resolvedTxRequestForSigning?: TxRequest; [index: string]: unknown; } diff --git a/modules/sdk-core/src/bitgo/wallet/wallet.ts b/modules/sdk-core/src/bitgo/wallet/wallet.ts index 02f0ab5e31..93b7fedb40 100644 --- a/modules/sdk-core/src/bitgo/wallet/wallet.ts +++ b/modules/sdk-core/src/bitgo/wallet/wallet.ts @@ -27,6 +27,7 @@ import { getSharedSecret } from '../ecdh'; import { AddressGenerationError, IncorrectPasswordError, + InvalidTransactionError, MethodNotImplementedError, MissingEncryptedKeychainError, NeedUserSignupError, @@ -56,6 +57,7 @@ import { decodeWithCodec } from '../utils/codecs'; import { postWithCodec } from '../utils/postWithCodec'; import { EcdsaMPCv2Utils, EcdsaUtils } from '../utils/tss/ecdsa'; import EddsaUtils, { EddsaMPCv2Utils } from '../utils/tss/eddsa'; +import { resolveEffectiveTxParams } from '../utils/tss/recipientUtils'; import { RedpallasMPCv2Utils } from '../utils/tss/redpallas'; import { getTxRequestApiVersion, validateTxRequestApiVersion } from '../utils/txRequest'; import { buildParamKeys, BuildParams } from './BuildParams'; @@ -2386,18 +2388,41 @@ export class Wallet implements IWallet { params.txPrebuild = { txRequestId }; } - // Verify transaction if verifyTxParams is provided - if (params.verifyTxParams && txPrebuild?.txHex) { - const verifyParams = { - txPrebuild: { ...txPrebuild }, - txParams: params.verifyTxParams.txParams, - wallet: this as IWallet, - verification: params.verifyTxParams.verification, - reqId: params.reqId, - walletType: this.multisigType() as 'onchain' | 'tss', - }; + // Verify transaction if verifyTxParams is provided (fail closed — never skip silently). + if (params.verifyTxParams) { + const prebuild = params.txPrebuild; + if (prebuild?.txHex) { + const verifyParams = { + txPrebuild: { ...prebuild }, + txParams: params.verifyTxParams.txParams, + wallet: this, + verification: params.verifyTxParams.verification, + reqId: params.reqId, + walletType: this.multisigType(), + }; - await this.baseCoin.verifyTransaction(verifyParams); + await this.baseCoin.verifyTransaction(verifyParams); + } else if (this.multisigType() === 'tss' && prebuild?.txRequestId && typeof prebuild.txRequestId === 'string') { + const txRequest = await getTxRequest(this.bitgo, this.id(), prebuild.txRequestId, params.reqId); + assert(txRequest.transactions || txRequest.unsignedTxs, 'Unable to find transactions in txRequest'); + const unsignedTx = + txRequest.apiVersion === 'full' ? txRequest.transactions![0].unsignedTx : txRequest.unsignedTxs![0]; + assert(unsignedTx.signableHex, 'Missing signableHex in unsignedTx'); + await this.baseCoin.verifyTransaction({ + txPrebuild: { txHex: unsignedTx.serializedTxHex ?? unsignedTx.signableHex }, + txParams: resolveEffectiveTxParams(txRequest, params.verifyTxParams.txParams, this.baseCoin.getChain()), + wallet: this, + verification: params.verifyTxParams.verification, + reqId: params.reqId, + walletType: this.multisigType(), + }); + // Sign the same resolved txRequest (avoid TOCTOU re-fetch before signing). + params.resolvedTxRequestForSigning = txRequest; + } else { + throw new InvalidTransactionError( + 'verifyTxParams was provided but txPrebuild does not include txHex or a TSS txRequestId.' + ); + } } if ( @@ -4980,13 +5005,16 @@ export class Wallet implements IWallet { const reqId = params.reqId || undefined; await this.tssUtils.deleteSignatureShares(txRequestId, reqId); + const txParams = params.verifyTxParams?.txParams ?? params.txPrebuild?.buildParams; + try { return await this.tssUtils.signEddsaTssUsingExternalSigner( txRequestId, params.customCommitmentGeneratingFunction, params.customRShareGeneratingFunction, params.customGShareGeneratingFunction, - reqId + reqId, + txParams ); } catch (e) { debug('failed to sign transaction %O', e); @@ -5226,7 +5254,7 @@ export class Wallet implements IWallet { throw new Error('prv required to sign transactions with TSS'); } - const txRequest: string | TxRequest = params.txPrebuild.txRequestId; + const txRequest: string | TxRequest = params.resolvedTxRequestForSigning ?? params.txPrebuild.txRequestId; const txParams: TransactionParams | undefined = params.txPrebuild.buildParams; try {