Skip to content

Commit 8c8644c

Browse files
OttoAllmendingerllm-git
andcommitted
feat(utxo-lib): improve validation for path chain and index
Require chain to be a valid ChainCode and ensure index is a non-negative integer. Improve error messages and test cases. TICKET: BTC-1966 Co-authored-by: llm-git <[email protected]>
1 parent fd77718 commit 8c8644c

File tree

2 files changed

+15
-16
lines changed

2 files changed

+15
-16
lines changed

modules/utxo-lib/src/bitgo/parseInput.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { TxInput, script as bscript } from 'bitcoinjs-lib';
44

55
import { isTriple } from './types';
66
import { isScriptType2Of3 } from './outputScripts';
7+
import { ChainCode, isChainCode } from './wallet/chains';
78

89
export function isPlaceholderSignature(v: number | Buffer): boolean {
910
if (Buffer.isBuffer(v)) {
@@ -699,18 +700,18 @@ export function parsePubScript(
699700
return result;
700701
}
701702

702-
export function getChainAndIndexFromPath(path: string): { chain: number; index: number } {
703+
export function getChainAndIndexFromPath(path: string): { chain: ChainCode; index: number } {
703704
const parts = path.split('/');
704705
if (parts.length <= 2) {
705706
throw new Error(`invalid path "${path}"`);
706707
}
707708
const chain = Number(parts[parts.length - 2]);
708709
const index = Number(parts[parts.length - 1]);
709-
if (isNaN(chain) || isNaN(index)) {
710-
throw new Error(`Could not parse chain and index into numbers from path ${path}`);
710+
if (!isChainCode(chain)) {
711+
throw new Error(`invalid chain "${chain}"`);
711712
}
712-
if (chain < 0 || index < 0) {
713-
throw new Error(`chain and index must be non-negative`);
713+
if (!Number.isInteger(index) || index < 0) {
714+
throw new Error(`invalid index "${index}"`);
714715
}
715716

716717
return { chain, index };

modules/utxo-lib/test/bitgo/wallet/chains.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,18 @@ describe('getChainAndIndexFromPath', function () {
6767
});
6868

6969
it('should throw if the path is not a number', function () {
70-
assert.throws(() => getChainAndIndexFromPath('m/0/ssss'), /Could not parse chain and index into numbers from path/);
71-
assert.throws(
72-
() => getChainAndIndexFromPath('//d/dd/d/d/dd/dd'),
73-
/Could not parse chain and index into numbers from path/
74-
);
75-
});
76-
77-
it('should throw if chain or index is negative', function () {
78-
assert.throws(() => getChainAndIndexFromPath('m/-1/0'), /chain and index must be non-negative/);
79-
assert.throws(() => getChainAndIndexFromPath('m/0/-1'), /chain and index must be non-negative/);
70+
const invalidChain = [-1, 2, 'lol'];
71+
const invalidIndex = [-1, 'lol'];
72+
for (const chain of invalidChain) {
73+
assert.throws(() => getChainAndIndexFromPath(`m/${chain}/0`), /invalid chain/);
74+
}
75+
for (const index of invalidIndex) {
76+
assert.throws(() => getChainAndIndexFromPath(`m/0/${index}`), /invalid index/);
77+
}
8078
});
8179

8280
it('should set the chain and index correctly', function () {
8381
assert.deepStrictEqual(getChainAndIndexFromPath('m/1/2'), { chain: 1, index: 2 });
84-
assert.deepStrictEqual(getChainAndIndexFromPath('m/4/3/2'), { chain: 3, index: 2 });
82+
assert.deepStrictEqual(getChainAndIndexFromPath('m/1/2/3/4/5/10/20'), { chain: 10, index: 20 });
8583
});
8684
});

0 commit comments

Comments
 (0)