@@ -5,13 +5,13 @@ import * as utxolib from '@bitgo/utxo-lib';
55import { DescriptorMap , toDescriptorMap } from '../core/descriptor' ;
66
77import { parseDescriptor } from './builder' ;
8- import { NamedDescriptor } from './NamedDescriptor' ;
8+ import { hasValidSignature , NamedDescriptor } from './NamedDescriptor' ;
99
1010export type KeyTriple = Triple < utxolib . BIP32Interface > ;
1111
1212export interface DescriptorValidationPolicy {
1313 name : string ;
14- validate ( d : Descriptor , walletKeys : KeyTriple ) : boolean ;
14+ validate ( d : Descriptor , walletKeys : KeyTriple , signatures : string [ ] ) : boolean ;
1515}
1616
1717export const policyAllowAll : DescriptorValidationPolicy = {
@@ -36,17 +36,17 @@ export function getValidatorDescriptorTemplate(name: string): DescriptorValidati
3636export function getValidatorEvery ( validators : DescriptorValidationPolicy [ ] ) : DescriptorValidationPolicy {
3737 return {
3838 name : 'every(' + validators . map ( ( v ) => v . name ) . join ( ',' ) + ')' ,
39- validate ( d : Descriptor , walletKeys : KeyTriple ) : boolean {
40- return validators . every ( ( v ) => v . validate ( d , walletKeys ) ) ;
39+ validate ( d : Descriptor , walletKeys : KeyTriple , signatures : string [ ] ) : boolean {
40+ return validators . every ( ( v ) => v . validate ( d , walletKeys , signatures ) ) ;
4141 } ,
4242 } ;
4343}
4444
4545export function getValidatorSome ( validators : DescriptorValidationPolicy [ ] ) : DescriptorValidationPolicy {
4646 return {
4747 name : 'some(' + validators . map ( ( v ) => v . name ) . join ( ',' ) + ')' ,
48- validate ( d : Descriptor , walletKeys : KeyTriple ) : boolean {
49- return validators . some ( ( v ) => v . validate ( d , walletKeys ) ) ;
48+ validate ( d : Descriptor , walletKeys : KeyTriple , signatures : string [ ] ) : boolean {
49+ return validators . some ( ( v ) => v . validate ( d , walletKeys , signatures ) ) ;
5050 } ,
5151 } ;
5252}
@@ -55,6 +55,16 @@ export function getValidatorOneOfTemplates(names: string[]): DescriptorValidatio
5555 return getValidatorSome ( names . map ( getValidatorDescriptorTemplate ) ) ;
5656}
5757
58+ export function getValidatorSignedByUserKey ( ) : DescriptorValidationPolicy {
59+ return {
60+ name : 'signedByUser' ,
61+ validate ( d : Descriptor , walletKeys : KeyTriple , signatures : string [ ] ) : boolean {
62+ // the first key is the user key, by convention
63+ return hasValidSignature ( d , walletKeys [ 0 ] , signatures ) ;
64+ } ,
65+ } ;
66+ }
67+
5868export class DescriptorPolicyValidationError extends Error {
5969 constructor ( descriptor : Descriptor , policy : DescriptorValidationPolicy ) {
6070 super ( `Descriptor ${ descriptor . toString ( ) } does not match policy ${ policy . name } ` ) ;
@@ -64,9 +74,10 @@ export class DescriptorPolicyValidationError extends Error {
6474export function assertDescriptorPolicy (
6575 descriptor : Descriptor ,
6676 policy : DescriptorValidationPolicy ,
67- walletKeys : KeyTriple
77+ walletKeys : KeyTriple ,
78+ signatures : string [ ]
6879) : void {
69- if ( ! policy . validate ( descriptor , walletKeys ) ) {
80+ if ( ! policy . validate ( descriptor , walletKeys , signatures ) ) {
7081 throw new DescriptorPolicyValidationError ( descriptor , policy ) ;
7182 }
7283}
@@ -76,18 +87,25 @@ export function toDescriptorMapValidate(
7687 walletKeys : KeyTriple ,
7788 policy : DescriptorValidationPolicy
7889) : DescriptorMap {
79- const map = toDescriptorMap ( descriptors ) ;
80- for ( const descriptor of map . values ( ) ) {
81- assertDescriptorPolicy ( descriptor , policy , walletKeys ) ;
82- }
83- return map ;
90+ return toDescriptorMap (
91+ descriptors . map ( ( namedDescriptor ) => {
92+ const d = Descriptor . fromString ( namedDescriptor . value , 'derivable' ) ;
93+ assertDescriptorPolicy ( d , policy , walletKeys , namedDescriptor . signatures ?? [ ] ) ;
94+ return { name : namedDescriptor . name , value : d } ;
95+ } )
96+ ) ;
8497}
8598
8699export function getPolicyForEnv ( env : EnvironmentName ) : DescriptorValidationPolicy {
87100 switch ( env ) {
88101 case 'adminProd' :
89102 case 'prod' :
90- return getValidatorOneOfTemplates ( [ 'Wsh2Of3' , 'Wsh2Of3CltvDrop' , 'ShWsh2Of3CltvDrop' ] ) ;
103+ return getValidatorSome ( [
104+ // allow all 2-of-3-ish descriptors where the keys match the wallet keys
105+ getValidatorOneOfTemplates ( [ 'Wsh2Of3' , 'Wsh2Of3CltvDrop' , 'ShWsh2Of3CltvDrop' ] ) ,
106+ // allow all descriptors signed by the user key
107+ getValidatorSignedByUserKey ( ) ,
108+ ] ) ;
91109 default :
92110 return policyAllowAll ;
93111 }
0 commit comments