Skip to content

Commit 71366cd

Browse files
Merge pull request #7650 from BitGo/BTC-2806.move-sign-code
feat(abstract-utxo): refactor replay protection and signing for better testing
2 parents 2af5ce8 + 65f39e1 commit 71366cd

File tree

9 files changed

+24
-11
lines changed

9 files changed

+24
-11
lines changed

modules/abstract-utxo/src/abstractUtxoCoin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ import {
5555
v1Sweep,
5656
V1SweepParams,
5757
} from './recovery';
58-
import { isReplayProtectionUnspent } from './replayProtection';
58+
import { isReplayProtectionUnspent } from './transaction/fixedScript/replayProtection';
5959
import { supportedCrossChainRecoveries } from './config';
6060
import {
6161
assertValidTransactionRecipient,

modules/abstract-utxo/src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ export * from './abstractUtxoCoin';
22
export * from './address';
33
export * from './config';
44
export * from './recovery';
5-
export * from './replayProtection';
6-
export * from './sign';
5+
export * from './transaction/fixedScript/replayProtection';
6+
export * from './transaction/fixedScript/sign';
77

88
export { UtxoWallet } from './wallet';
99
export * as descriptor from './descriptor';

modules/abstract-utxo/src/recovery/backupKeyRecovery.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
import { getMainnet, networks } from '@bitgo/utxo-lib';
1717

1818
import { AbstractUtxoCoin } from '../abstractUtxoCoin';
19-
import { signAndVerifyPsbt } from '../sign';
19+
import { signAndVerifyPsbt } from '../transaction/fixedScript/sign';
2020
import { generateAddressWithChainAndIndex } from '../address';
2121

2222
import { forCoin, RecoveryProvider } from './RecoveryProvider';

modules/abstract-utxo/src/recovery/crossChainRecovery.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { BitGoBase, IWallet, Keychain, Triple, Wallet } from '@bitgo/sdk-core';
55
import { decrypt } from '@bitgo/sdk-api';
66

77
import { AbstractUtxoCoin, TransactionInfo } from '../abstractUtxoCoin';
8-
import { signAndVerifyWalletTransaction } from '../sign';
8+
import { signAndVerifyWalletTransaction } from '../transaction/fixedScript/sign';
99

1010
const { unspentSum, scriptTypeForChain, outputScripts } = utxolib.bitgo;
1111
type RootWalletKeys = utxolib.bitgo.RootWalletKeys;

modules/abstract-utxo/src/transaction/explainTransaction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { isTriple, IWallet, Triple } from '@bitgo/sdk-core';
55
import { getDescriptorMapFromWallet, isDescriptorWallet } from '../descriptor';
66
import { toBip32Triple } from '../keychains';
77
import { getPolicyForEnv } from '../descriptor/validatePolicy';
8-
import { getReplayProtectionOutputScripts } from '../replayProtection';
98

9+
import { getReplayProtectionOutputScripts } from './fixedScript/replayProtection';
1010
import type {
1111
TransactionExplanationUtxolibLegacy,
1212
TransactionExplanationUtxolibPsbt,

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ export { parseTransaction } from './parseTransaction';
44
export { CustomChangeOptions } from './parseOutput';
55
export { verifyTransaction } from './verifyTransaction';
66
export { signTransaction } from './signTransaction';
7+
export * from './sign';
8+
export * from './replayProtection';

modules/abstract-utxo/src/sign.ts renamed to modules/abstract-utxo/src/transaction/fixedScript/sign.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as utxolib from '@bitgo/utxo-lib';
22
import debugLib from 'debug';
33

4-
import { isReplayProtectionUnspent } from './replayProtection';
4+
import { getReplayProtectionAddresses } from './replayProtection';
55

66
const debug = debugLib('bitgo:v2:utxo');
77

@@ -139,14 +139,24 @@ export function signAndVerifyPsbt(
139139
* @param unspents - transaction unspents
140140
* @param walletSigner - signing parameters
141141
* @param isLastSignature - Returns full-signed transaction when true. Builds half-signed when false.
142+
* @param replayProtectionAddresses - List of replay protection addresses to skip signing
142143
*/
143144
export function signAndVerifyWalletTransaction<TNumber extends number | bigint>(
144145
transaction: utxolib.bitgo.UtxoTransaction<TNumber> | utxolib.bitgo.UtxoTransactionBuilder<TNumber>,
145146
unspents: Unspent<TNumber>[],
146147
walletSigner: utxolib.bitgo.WalletUnspentSigner<RootWalletKeys>,
147-
{ isLastSignature }: { isLastSignature: boolean }
148+
{
149+
isLastSignature,
150+
replayProtectionAddresses,
151+
}: {
152+
isLastSignature: boolean;
153+
replayProtectionAddresses?: string[];
154+
}
148155
): utxolib.bitgo.UtxoTransaction<TNumber> {
149156
const network = transaction.network as utxolib.Network;
157+
if (replayProtectionAddresses === undefined) {
158+
replayProtectionAddresses = getReplayProtectionAddresses(network);
159+
}
150160
const prevOutputs = unspents.map((u) => toOutput(u, network));
151161

152162
let txBuilder: utxolib.bitgo.UtxoTransactionBuilder<TNumber>;
@@ -163,7 +173,7 @@ export function signAndVerifyWalletTransaction<TNumber extends number | bigint>(
163173

164174
const signErrors: InputSigningError<TNumber>[] = unspents
165175
.map((unspent: Unspent<TNumber>, inputIndex: number) => {
166-
if (isReplayProtectionUnspent<TNumber>(unspent, network)) {
176+
if (replayProtectionAddresses.includes(unspent.address)) {
167177
debug('Skipping signature for input %d of %d (RP input?)', inputIndex + 1, unspents.length);
168178
return;
169179
}
@@ -184,7 +194,7 @@ export function signAndVerifyWalletTransaction<TNumber extends number | bigint>(
184194
const verifyErrors: InputSigningError<TNumber>[] = signedTransaction.ins
185195
.map((input, inputIndex) => {
186196
const unspent = unspents[inputIndex] as Unspent<TNumber>;
187-
if (isReplayProtectionUnspent<TNumber>(unspent, network)) {
197+
if (replayProtectionAddresses.includes(unspent.address)) {
188198
debug(
189199
'Skipping input signature %d of %d (unspent from replay protection address which is platform signed only)',
190200
inputIndex + 1,

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import { bitgo } from '@bitgo/utxo-lib';
66
import * as utxolib from '@bitgo/utxo-lib';
77
import { isTriple, Triple } from '@bitgo/sdk-core';
88

9-
import { signAndVerifyPsbt, signAndVerifyWalletTransaction } from '../../sign';
109
import { AbstractUtxoCoin, DecodedTransaction, RootWalletKeys } from '../../abstractUtxoCoin';
1110

11+
import { signAndVerifyPsbt, signAndVerifyWalletTransaction } from './sign';
12+
1213
/**
1314
* Key Value: Unsigned tx id => PSBT
1415
* It is used to cache PSBTs with taproot key path (MuSig2) inputs during external express signer is activated.

0 commit comments

Comments
 (0)