@@ -4,45 +4,71 @@ import * as utxolib from '@bitgo/utxo-lib';
44
55import { DescriptorMap , toDescriptorMap } from '../core/descriptor' ;
66
7- import { DescriptorBuilder , parseDescriptor } from './builder' ;
7+ import { parseDescriptor } from './builder' ;
88import { NamedDescriptor } from './NamedDescriptor' ;
99
10- export type DescriptorValidationPolicy = { allowedTemplates : DescriptorBuilder [ 'name' ] [ ] } | 'allowAll' ;
11-
1210export type KeyTriple = Triple < utxolib . BIP32Interface > ;
1311
14- function isDescriptorWithTemplate (
15- d : Descriptor ,
16- name : DescriptorBuilder [ 'name' ] ,
17- walletKeys : Triple < utxolib . BIP32Interface >
18- ) : boolean {
19- const parsed = parseDescriptor ( d ) ;
20- if ( parsed . name !== name ) {
21- return false ;
22- }
23- if ( parsed . keys . length !== walletKeys . length ) {
24- return false ;
12+ export interface DescriptorValidationPolicy {
13+ name : string ;
14+ validate ( d : Descriptor , walletKeys : KeyTriple ) : boolean ;
15+ }
16+
17+ export const policyAllowAll : DescriptorValidationPolicy = {
18+ name : 'allowAll' ,
19+ validate : ( ) => true ,
20+ } ;
21+
22+ export function getValidatorDescriptorTemplate ( name : string ) : DescriptorValidationPolicy {
23+ return {
24+ name : 'descriptorTemplate(' + name + ')' ,
25+ validate ( d : Descriptor , walletKeys : KeyTriple ) : boolean {
26+ const parsed = parseDescriptor ( d ) ;
27+ return (
28+ parsed . name === name &&
29+ parsed . keys . length === walletKeys . length &&
30+ parsed . keys . every ( ( k , i ) => k . toBase58 ( ) === walletKeys [ i ] . neutered ( ) . toBase58 ( ) )
31+ ) ;
32+ } ,
33+ } ;
34+ }
35+
36+ export function getValidatorEvery ( validators : DescriptorValidationPolicy [ ] ) : DescriptorValidationPolicy {
37+ return {
38+ name : 'every(' + validators . map ( ( v ) => v . name ) . join ( ',' ) + ')' ,
39+ validate ( d : Descriptor , walletKeys : KeyTriple ) : boolean {
40+ return validators . every ( ( v ) => v . validate ( d , walletKeys ) ) ;
41+ } ,
42+ } ;
43+ }
44+
45+ export function getValidatorSome ( validators : DescriptorValidationPolicy [ ] ) : DescriptorValidationPolicy {
46+ return {
47+ name : 'some(' + validators . map ( ( v ) => v . name ) . join ( ',' ) + ')' ,
48+ validate ( d : Descriptor , walletKeys : KeyTriple ) : boolean {
49+ return validators . some ( ( v ) => v . validate ( d , walletKeys ) ) ;
50+ } ,
51+ } ;
52+ }
53+
54+ export function getValidatorOneOfTemplates ( names : string [ ] ) : DescriptorValidationPolicy {
55+ return getValidatorSome ( names . map ( getValidatorDescriptorTemplate ) ) ;
56+ }
57+
58+ export class DescriptorPolicyValidationError extends Error {
59+ constructor ( descriptor : Descriptor , policy : DescriptorValidationPolicy ) {
60+ super ( `Descriptor ${ descriptor . toString ( ) } does not match policy ${ policy . name } ` ) ;
2561 }
26- return parsed . keys . every ( ( k , i ) => k . toBase58 ( ) === walletKeys [ i ] . toBase58 ( ) ) ;
2762}
2863
2964export function assertDescriptorPolicy (
3065 descriptor : Descriptor ,
3166 policy : DescriptorValidationPolicy ,
32- walletKeys : Triple < utxolib . BIP32Interface >
67+ walletKeys : KeyTriple
3368) : void {
34- if ( policy === 'allowAll' ) {
35- return ;
36- }
37-
38- if ( 'allowedTemplates' in policy ) {
39- const allowed = policy . allowedTemplates ;
40- if ( ! allowed . some ( ( t ) => isDescriptorWithTemplate ( descriptor , t , walletKeys ) ) ) {
41- throw new Error ( `Descriptor ${ descriptor . toString ( ) } does not match any allowed template` ) ;
42- }
69+ if ( ! policy . validate ( descriptor , walletKeys ) ) {
70+ throw new DescriptorPolicyValidationError ( descriptor , policy ) ;
4371 }
44-
45- throw new Error ( `Unknown descriptor validation policy: ${ policy } ` ) ;
4672}
4773
4874export function toDescriptorMapValidate (
@@ -61,10 +87,8 @@ export function getPolicyForEnv(env: EnvironmentName): DescriptorValidationPolic
6187 switch ( env ) {
6288 case 'adminProd' :
6389 case 'prod' :
64- return {
65- allowedTemplates : [ 'Wsh2Of3' , 'Wsh2Of3CltvDrop' , 'ShWsh2Of3CltvDrop' ] ,
66- } ;
90+ return getValidatorOneOfTemplates ( [ 'Wsh2Of3' , 'Wsh2Of3CltvDrop' , 'ShWsh2Of3CltvDrop' ] ) ;
6791 default :
68- return 'allowAll' ;
92+ return policyAllowAll ;
6993 }
7094}
0 commit comments