1- import { Descriptor } from '@bitgo/wasm-miniscript' ;
21import { EnvironmentName , Triple } from '@bitgo/sdk-core' ;
32import * as utxolib from '@bitgo/utxo-lib' ;
43import { DescriptorMap , toDescriptorMap } from '@bitgo/utxo-core/descriptor' ;
54
65import { parseDescriptor } from './builder' ;
7- import { hasValidSignature , NamedDescriptor } from './NamedDescriptor' ;
6+ import { hasValidSignature , NamedDescriptor , NamedDescriptorNative , toNamedDescriptorNative } from './NamedDescriptor' ;
87
98export type KeyTriple = Triple < utxolib . BIP32Interface > ;
109
1110export interface DescriptorValidationPolicy {
1211 name : string ;
13- validate ( d : Descriptor , walletKeys : KeyTriple , signatures : string [ ] ) : boolean ;
12+
13+ validate ( arr : NamedDescriptorNative [ ] , walletKeys : KeyTriple ) : boolean ;
1414}
1515
1616export const policyAllowAll : DescriptorValidationPolicy = {
@@ -21,31 +21,33 @@ export const policyAllowAll: DescriptorValidationPolicy = {
2121export function getValidatorDescriptorTemplate ( name : string ) : DescriptorValidationPolicy {
2222 return {
2323 name : 'descriptorTemplate(' + name + ')' ,
24- validate ( d : Descriptor , walletKeys : KeyTriple ) : boolean {
25- const parsed = parseDescriptor ( d ) ;
26- return (
27- parsed . name === name &&
28- parsed . keys . length === walletKeys . length &&
29- parsed . keys . every ( ( k , i ) => k . toBase58 ( ) === walletKeys [ i ] . neutered ( ) . toBase58 ( ) )
30- ) ;
24+ validate ( arr : NamedDescriptorNative [ ] , walletKeys : KeyTriple ) : boolean {
25+ return arr . every ( ( d ) => {
26+ const parsed = parseDescriptor ( d . value ) ;
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+ } ) ;
3133 } ,
3234 } ;
3335}
3436
3537export function getValidatorEvery ( validators : DescriptorValidationPolicy [ ] ) : DescriptorValidationPolicy {
3638 return {
3739 name : 'every(' + validators . map ( ( v ) => v . name ) . join ( ',' ) + ')' ,
38- validate ( d : Descriptor , walletKeys : KeyTriple , signatures : string [ ] ) : boolean {
39- return validators . every ( ( v ) => v . validate ( d , walletKeys , signatures ) ) ;
40+ validate ( arr : NamedDescriptorNative [ ] , walletKeys : KeyTriple ) : boolean {
41+ return validators . every ( ( v ) => v . validate ( arr , walletKeys ) ) ;
4042 } ,
4143 } ;
4244}
4345
4446export function getValidatorSome ( validators : DescriptorValidationPolicy [ ] ) : DescriptorValidationPolicy {
4547 return {
4648 name : 'some(' + validators . map ( ( v ) => v . name ) . join ( ',' ) + ')' ,
47- validate ( d : Descriptor , walletKeys : KeyTriple , signatures : string [ ] ) : boolean {
48- return validators . some ( ( v ) => v . validate ( d , walletKeys , signatures ) ) ;
49+ validate ( arr : NamedDescriptorNative [ ] , walletKeys : KeyTriple ) : boolean {
50+ return validators . some ( ( v ) => v . validate ( arr , walletKeys ) ) ;
4951 } ,
5052 } ;
5153}
@@ -57,27 +59,26 @@ export function getValidatorOneOfTemplates(names: string[]): DescriptorValidatio
5759export function getValidatorSignedByUserKey ( ) : DescriptorValidationPolicy {
5860 return {
5961 name : 'signedByUser' ,
60- validate ( d : Descriptor , walletKeys : KeyTriple , signatures : string [ ] ) : boolean {
62+ validate ( arr : NamedDescriptorNative [ ] , walletKeys : KeyTriple ) : boolean {
6163 // the first key is the user key, by convention
62- return hasValidSignature ( d , walletKeys [ 0 ] , signatures ) ;
64+ return arr . every ( ( d ) => hasValidSignature ( d . value , walletKeys [ 0 ] , d . signatures ?? [ ] ) ) ;
6365 } ,
6466 } ;
6567}
6668
6769export class DescriptorPolicyValidationError extends Error {
68- constructor ( descriptor : Descriptor , policy : DescriptorValidationPolicy ) {
69- super ( `Descriptor ${ descriptor . toString ( ) } does not match policy ${ policy . name } ` ) ;
70+ constructor ( ds : NamedDescriptorNative [ ] , policy : DescriptorValidationPolicy ) {
71+ super ( `Descriptors ${ ds . map ( ( d ) => d . value . toString ( ) ) } does not match policy ${ policy . name } ` ) ;
7072 }
7173}
7274
7375export function assertDescriptorPolicy (
74- descriptor : Descriptor ,
76+ descriptors : NamedDescriptorNative [ ] ,
7577 policy : DescriptorValidationPolicy ,
76- walletKeys : KeyTriple ,
77- signatures : string [ ]
78+ walletKeys : KeyTriple
7879) : void {
79- if ( ! policy . validate ( descriptor , walletKeys , signatures ) ) {
80- throw new DescriptorPolicyValidationError ( descriptor , policy ) ;
80+ if ( ! policy . validate ( descriptors , walletKeys ) ) {
81+ throw new DescriptorPolicyValidationError ( descriptors , policy ) ;
8182 }
8283}
8384
@@ -86,22 +87,22 @@ export function toDescriptorMapValidate(
8687 walletKeys : KeyTriple ,
8788 policy : DescriptorValidationPolicy
8889) : DescriptorMap {
89- return toDescriptorMap (
90- descriptors . map ( ( namedDescriptor ) => {
91- const d = Descriptor . fromString ( namedDescriptor . value , 'derivable' ) ;
92- assertDescriptorPolicy ( d , policy , walletKeys , namedDescriptor . signatures ?? [ ] ) ;
93- return { name : namedDescriptor . name , value : d } ;
94- } )
90+ const namedDescriptorsNative : NamedDescriptorNative [ ] = descriptors . map ( ( v ) =>
91+ toNamedDescriptorNative ( v , 'derivable' )
9592 ) ;
93+ assertDescriptorPolicy ( namedDescriptorsNative , policy , walletKeys ) ;
94+ return toDescriptorMap ( namedDescriptorsNative ) ;
9695}
9796
9897export function getPolicyForEnv ( env : EnvironmentName ) : DescriptorValidationPolicy {
9998 switch ( env ) {
10099 case 'adminProd' :
101100 case 'prod' :
102101 return getValidatorSome ( [
103- // allow all 2-of-3-ish descriptors where the keys match the wallet keys
104- getValidatorOneOfTemplates ( [ 'Wsh2Of3' , 'Wsh2Of3CltvDrop' , 'ShWsh2Of3CltvDrop' ] ) ,
102+ // allow 2-of-3-ish descriptor groups where the keys match the wallet keys
103+ getValidatorDescriptorTemplate ( 'Wsh2Of3' ) ,
104+ // allow descriptor groups where all keys match the wallet keys plus OP_DROP (coredao staking)
105+ getValidatorDescriptorTemplate ( 'Wsh2Of3CltvDrop' ) ,
105106 // allow all descriptors signed by the user key
106107 getValidatorSignedByUserKey ( ) ,
107108 ] ) ;
0 commit comments