88using System . Linq ;
99using static NBitcoin . Tests . Comparer ;
1010using Xunit . Abstractions ;
11- using System . Net . Http ;
12- using System . Threading . Tasks ;
1311
1412namespace NBitcoin . Tests
1513{
@@ -41,6 +39,27 @@ public static void ShouldThrowExceptionForInvalidData()
4139 }
4240 }
4341
42+ [ Fact ]
43+ [ Trait ( "UnitTest" , "UnitTest" ) ]
44+ public static void CanDeriveHDKey ( )
45+ {
46+ var k = new ExtKey ( ) ;
47+ var kwif = k . GetWif ( Network . Main ) ;
48+ var pk = k . Neuter ( ) ;
49+ var pkwif = pk . GetWif ( Network . Main ) ;
50+ static void AssertEqualKey ( IHDKey a , IHDKey b )
51+ {
52+ Assert . Equal ( a . GetPublicKey ( ) , b . GetPublicKey ( ) ) ;
53+ }
54+ AssertEqualKey ( ( ( IHDKey ) k ) . Derive ( new KeyPath ( "1" ) ) , ( ( IHDKey ) pk ) . Derive ( new KeyPath ( "1" ) ) ) ;
55+ AssertEqualKey ( ( ( IHDKey ) kwif ) . Derive ( new KeyPath ( "1" ) ) , ( ( IHDKey ) pkwif ) . Derive ( new KeyPath ( "1" ) ) ) ;
56+ AssertEqualKey ( ( ( IHDKey ) k ) . Derive ( new KeyPath ( "1" ) ) , ( ( IHDKey ) kwif ) . Derive ( new KeyPath ( "1" ) ) ) ;
57+ Assert . Null ( ( ( IHDKey ) pk ) . Derive ( new KeyPath ( "1'" ) ) ) ;
58+ Assert . Null ( ( ( IHDKey ) pkwif ) . Derive ( new KeyPath ( "1'" ) ) ) ;
59+ Assert . NotNull ( ( ( IHDKey ) k ) . Derive ( new KeyPath ( "1'" ) ) ) ;
60+ Assert . NotNull ( ( ( IHDKey ) kwif ) . Derive ( new KeyPath ( "1'" ) ) ) ;
61+ }
62+
4463 [ Theory ]
4564 [ InlineData ( PSBTVersion . PSBTv0 ) ]
4665 [ InlineData ( PSBTVersion . PSBTv2 ) ]
@@ -52,7 +71,7 @@ public static void ShouldCalculateBalanceOfHDKey(PSBTVersion version)
5271 var aliceMaster = new ExtKey ( ) ;
5372 var bobMaster = new ExtKey ( ) ;
5473
55- var alice = aliceMaster . Derive ( new KeyPath ( "1/2/3" ) ) ;
74+ var alice = aliceMaster . Derive ( new KeyPath ( "1' /2/3" ) ) ;
5675 var bob = bobMaster . Derive ( new KeyPath ( "4/5/6" ) ) ;
5776
5877 var funding = network . CreateTransaction ( ) ;
@@ -83,18 +102,21 @@ public static void ShouldCalculateBalanceOfHDKey(PSBTVersion version)
83102 builder . SendFees ( Money . Coins ( 0.001m ) ) ;
84103
85104 var psbt = builder . BuildPSBT ( false , version ) ;
86- psbt . AddKeyPath ( aliceMaster , new KeyPath ( "1/2/3" ) ) ;
105+ psbt . AddKeyPath ( aliceMaster , new KeyPath ( "1' /2/3" ) ) ;
87106 psbt . AddKeyPath ( bobMaster , new KeyPath ( "4/5/6" ) ) ;
88107
89108 var actualBalance = psbt . GetBalance ( ScriptPubKeyType . Legacy , aliceMaster ) ;
90109 var expectedChange = aliceCoin . Amount - ( Money . Coins ( 0.2m ) + Money . Coins ( 0.1m ) + Money . Coins ( 0.123m ) ) ;
91110 var expectedBalance = - aliceCoin . Amount + expectedChange ;
92111 Assert . Equal ( expectedBalance , actualBalance ) ;
112+ // We can't derive Alice's balance from the xpub only
113+ Assert . Equal ( Money . Zero , psbt . GetBalance ( ScriptPubKeyType . Legacy , aliceMaster . Neuter ( ) ) ) ;
93114
94115 actualBalance = psbt . GetBalance ( ScriptPubKeyType . Legacy , bobMaster ) ;
95116 expectedChange = bobCoin . Amount - ( Money . Coins ( 0.25m ) + Money . Coins ( 0.01m ) + Money . Coins ( 0.001m ) ) + Money . Coins ( 0.123m ) ;
96117 expectedBalance = - bobCoin . Amount + expectedChange ;
97118 Assert . Equal ( expectedBalance , actualBalance ) ;
119+ Assert . Equal ( expectedBalance , psbt . GetBalance ( ScriptPubKeyType . Legacy , bobMaster . Neuter ( ) ) ) ;
98120
99121 Assert . False ( psbt . TryGetFee ( out _ ) ) ;
100122 Assert . False ( psbt . IsReadyToSign ( ) ) ;
0 commit comments