@@ -108,6 +108,7 @@ fn parse_wallet_policy_pk(pk: &str) -> Result<(usize, u32, u32), ()> {
108
108
fn get_change_and_address_index < R : core:: convert:: AsRef < str > , T : core:: iter:: Iterator < Item = R > > (
109
109
pubkeys : T ,
110
110
keys : & [ pb:: KeyOriginInfo ] ,
111
+ is_our_key : & [ bool ] ,
111
112
keypath : & [ u32 ] ,
112
113
) -> Result < ( bool , u32 ) , Error > {
113
114
for pk in pubkeys {
@@ -118,7 +119,8 @@ fn get_change_and_address_index<R: core::convert::AsRef<str>, T: core::iter::Ite
118
119
Some ( pb:: KeyOriginInfo {
119
120
keypath : keypath_account,
120
121
..
121
- } ) if keypath. starts_with ( keypath_account)
122
+ } ) if is_our_key[ key_index]
123
+ && keypath. starts_with ( keypath_account)
122
124
&& keypath. len ( ) == keypath_account. len ( ) + 2 =>
123
125
{
124
126
let keypath_change = keypath[ keypath. len ( ) - 2 ] ;
@@ -424,6 +426,7 @@ impl<'a> ParsedPolicy<'a> {
424
426
let ( is_change, address_index) = get_change_and_address_index (
425
427
miniscript_expr. iter_pk ( ) ,
426
428
& self . policy . keys ,
429
+ & self . is_our_key ,
427
430
keypath,
428
431
) ?;
429
432
self . derive ( is_change, address_index)
@@ -438,6 +441,7 @@ impl<'a> ParsedPolicy<'a> {
438
441
let ( is_change, _) = get_change_and_address_index (
439
442
miniscript_expr. iter_pk ( ) ,
440
443
& self . policy . keys ,
444
+ & self . is_our_key ,
441
445
keypath,
442
446
) ?;
443
447
Ok ( is_change)
@@ -836,6 +840,7 @@ mod tests {
836
840
get_change_and_address_index(
837
841
[ "@0/<10;11>/*" , "@1/<20;21>/*" ] . iter( ) ,
838
842
& [ our_key. clone( ) , some_key. clone( ) ] ,
843
+ & [ true , false ] ,
839
844
& [
840
845
48 + HARDENED ,
841
846
1 + HARDENED ,
@@ -852,6 +857,7 @@ mod tests {
852
857
get_change_and_address_index(
853
858
[ "@0/<10;11>/*" , "@1/<20;21>/*" ] . iter( ) ,
854
859
& [ our_key. clone( ) , some_key. clone( ) ] ,
860
+ & [ true , false ] ,
855
861
& [
856
862
48 + HARDENED ,
857
863
1 + HARDENED ,
@@ -868,6 +874,7 @@ mod tests {
868
874
assert ! ( get_change_and_address_index(
869
875
[ "@0/<10;11>/*" , "@1/<20;21>/*" ] . iter( ) ,
870
876
& [ our_key. clone( ) , some_key. clone( ) ] ,
877
+ & [ true , false ] ,
871
878
& [
872
879
48 + HARDENED ,
873
880
1 + HARDENED ,
@@ -883,6 +890,7 @@ mod tests {
883
890
assert ! ( get_change_and_address_index(
884
891
[ "@0/<10;11>/*" , "@1/<20;21>/*" ] . iter( ) ,
885
892
& [ our_key. clone( ) , some_key. clone( ) ] ,
893
+ & [ true , false ] ,
886
894
& [
887
895
48 + HARDENED ,
888
896
1 + HARDENED ,
@@ -898,6 +906,7 @@ mod tests {
898
906
assert ! ( get_change_and_address_index(
899
907
[ "@0/<10;11>/*" , "@1/<20;21>/*" ] . iter( ) ,
900
908
& [ our_key. clone( ) , some_key. clone( ) ] ,
909
+ & [ true , false ] ,
901
910
& [
902
911
48 + HARDENED ,
903
912
1 + HARDENED ,
@@ -914,9 +923,26 @@ mod tests {
914
923
assert ! ( get_change_and_address_index(
915
924
[ "@0/<10;11>/*" , "@1/<20;21>/*" ] . iter( ) ,
916
925
& [ our_key. clone( ) , some_key. clone( ) ] ,
926
+ & [ true , false ] ,
917
927
& [ 48 + HARDENED , 1 + HARDENED , 0 + HARDENED , 3 + HARDENED , 10 , ] ,
918
928
)
919
929
. is_err( ) ) ;
930
+
931
+ // Keypath is valid but uses a key in the policy that is not ours.
932
+ assert ! ( get_change_and_address_index(
933
+ [ "@0/<10;11>/*" , "@1/<20;21>/*" ] . iter( ) ,
934
+ & [
935
+ our_key. clone( ) ,
936
+ pb:: KeyOriginInfo {
937
+ root_fingerprint: b"aaaa" . to_vec( ) ,
938
+ keypath: vec![ 99 + HARDENED ] ,
939
+ xpub: Some ( parse_xpub( SOME_XPUB_1 ) . unwrap( ) ) ,
940
+ }
941
+ ] ,
942
+ & [ true , false ] ,
943
+ & [ 99 + HARDENED , 20 , 0 ] ,
944
+ )
945
+ . is_err( ) ) ;
920
946
}
921
947
922
948
#[ test]
0 commit comments