Skip to content

Commit 5fdb2f0

Browse files
committed
feat: improve transaction verification error handling
Replace custom validation errors with SDK's TxIntentMismatchRecipientError to provide more detailed information about mismatched transaction outputs. This enhances error reporting by including specific details about missing or unexpected outputs, helping users understand what differs between their intent and the actual transaction. Co-authored-by: llm-git <llm-git@ttll.de> Ticket: BTC-2579 TICKET: WP-6189
1 parent 6e7a8b7 commit 5fdb2f0

File tree

2 files changed

+16
-8
lines changed

2 files changed

+16
-8
lines changed

modules/abstract-utxo/src/transaction/descriptor/verifyTransaction.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import * as utxolib from '@bitgo/utxo-lib';
2-
import { ITransactionRecipient, TxIntentMismatchError, VerifyTransactionOptions } from '@bitgo/sdk-core';
2+
import {
3+
IRequestTracer,
4+
ITransactionRecipient,
5+
MismatchedRecipient,
6+
TxIntentMismatchError,
7+
TxIntentMismatchRecipientError,
8+
VerifyTransactionOptions,
9+
} from '@bitgo/sdk-core';
310
import { DescriptorMap } from '@bitgo/utxo-core/descriptor';
411

512
import { AbstractUtxoCoin, BaseOutput, BaseParsedTransactionOutputs } from '../../abstractUtxoCoin';
@@ -68,6 +75,7 @@ export function assertValidTransaction(
6875
* @param descriptorMap
6976
* @returns {boolean} True if verification passes
7077
* @throws {TxIntentMismatchError} if transaction validation fails
78+
* @throws {TxIntentMismatchRecipientError} if transaction recipients don't match user intent
7179
*/
7280
export async function verifyTransaction(
7381
coin: AbstractUtxoCoin,

modules/abstract-utxo/src/transaction/fixedScript/verifyTransaction.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,11 @@ export async function verifyTransaction<TNumber extends bigint | number>(
5555
};
5656

5757
if (!_.isUndefined(verification.disableNetworking) && !_.isBoolean(verification.disableNetworking)) {
58-
throwTxMismatch('verification.disableNetworking must be a boolean');
58+
throw new TypeError('verification.disableNetworking must be a boolean');
5959
}
6060
const isPsbt = txPrebuild.txHex && utxolib.bitgo.isPsbt(txPrebuild.txHex);
6161
if (isPsbt && txPrebuild.txInfo?.unspents) {
62-
throwTxMismatch('should not have unspents in txInfo for psbt');
62+
throw new Error('should not have unspents in txInfo for psbt');
6363
}
6464
const disableNetworking = !!verification.disableNetworking;
6565
const parsedTransaction: ParsedTransaction<TNumber> = await coin.parseTransaction<TNumber>({
@@ -97,7 +97,7 @@ export async function verifyTransaction<TNumber extends bigint | number>(
9797
const isBackupKeySignatureValid = verify(keychains.backup, keySignatures.backupPub);
9898
const isBitgoKeySignatureValid = verify(keychains.bitgo, keySignatures.bitgoPub);
9999
if (!isBackupKeySignatureValid || !isBitgoKeySignatureValid) {
100-
throwTxMismatch('secondary public key signatures invalid');
100+
throw new Error('secondary public key signatures invalid');
101101
}
102102
debug('successfully verified backup and bitgo key signatures');
103103
} else if (!disableNetworking) {
@@ -108,11 +108,11 @@ export async function verifyTransaction<TNumber extends bigint | number>(
108108

109109
if (parsedTransaction.needsCustomChangeKeySignatureVerification) {
110110
if (!keychains.user || !userPublicKeyVerified) {
111-
throwTxMismatch('transaction requires verification of user public key, but it was unable to be verified');
111+
throw new Error('transaction requires verification of user public key, but it was unable to be verified');
112112
}
113113
const customChangeKeySignaturesVerified = verifyCustomChangeKeySignatures(parsedTransaction, keychains.user);
114114
if (!customChangeKeySignaturesVerified) {
115-
throwTxMismatch(
115+
throw new Error(
116116
'transaction requires verification of custom change key signatures, but they were unable to be verified'
117117
);
118118
}
@@ -168,7 +168,7 @@ export async function verifyTransaction<TNumber extends bigint | number>(
168168

169169
const allOutputs = parsedTransaction.outputs;
170170
if (!txPrebuild.txHex) {
171-
throw new TxIntentMismatchError(`txPrebuild.txHex not set`, reqId, [txParams], undefined);
171+
throw new Error(`txPrebuild.txHex not set`);
172172
}
173173
const inputs = isPsbt
174174
? getPsbtTxInputs(txPrebuild.txHex, coin.network).map((v) => ({
@@ -185,7 +185,7 @@ export async function verifyTransaction<TNumber extends bigint | number>(
185185
const fee = inputAmount - outputAmount;
186186

187187
if (fee < 0) {
188-
throwTxMismatch(
188+
throw new Error(
189189
`attempting to spend ${outputAmount} satoshis, which exceeds the input amount (${inputAmount} satoshis) by ${-fee}`
190190
);
191191
}

0 commit comments

Comments
 (0)