@@ -22,8 +22,8 @@ import (
2222)
2323
2424var (
25- cacheSize = 5000
26- cache []* cacheEntry
25+ defaultNumKeys uint32 = 5000
26+ cache []* cacheEntry
2727
2828 errAddrNotFound = errors .New ("addr not found" )
2929
@@ -40,6 +40,7 @@ type rescueClosedCommand struct {
4040 Addr string
4141 CommitPoint string
4242 LndLog string
43+ NumKeys uint32
4344
4445 rootKey * rootKey
4546 inputs * inputFlags
@@ -103,7 +104,12 @@ chantools rescueclosed --fromsummary results/summary-xxxxxx.json \
103104 cc .cmd .Flags ().StringVar (
104105 & cc .LndLog , "lnd_log" , "" , "the lnd log file to read to get " +
105106 "the commit_point values when rescuing multiple " +
106- "channels at the same time" )
107+ "channels at the same time" ,
108+ )
109+ cc .cmd .Flags ().Uint32Var (
110+ & cc .NumKeys , "num_keys" , defaultNumKeys , "the number of keys " +
111+ "to derive for the brute force attack" ,
112+ )
107113 cc .rootKey = newRootKey (cc .cmd , "decrypting the backup" )
108114 cc .inputs = newInputFlags (cc .cmd )
109115
@@ -136,7 +142,9 @@ func (c *rescueClosedCommand) Execute(_ *cobra.Command, _ []string) error {
136142 return fmt .Errorf ("error reading commit points from " +
137143 "db: %w" , err )
138144 }
139- return rescueClosedChannels (extendedKey , entries , commitPoints )
145+ return rescueClosedChannels (
146+ c .NumKeys , extendedKey , entries , commitPoints ,
147+ )
140148
141149 case c .Addr != "" :
142150 // First parse address to get targetPubKeyHash from it later.
@@ -156,7 +164,9 @@ func (c *rescueClosedCommand) Execute(_ *cobra.Command, _ []string) error {
156164 return fmt .Errorf ("error parsing commit point: %w" , err )
157165 }
158166
159- return rescueClosedChannel (extendedKey , targetAddr , commitPoint )
167+ return rescueClosedChannel (
168+ c .NumKeys , extendedKey , targetAddr , commitPoint ,
169+ )
160170
161171 case c .LndLog != "" :
162172 // Parse channel entries from any of the possible input files.
@@ -170,7 +180,9 @@ func (c *rescueClosedCommand) Execute(_ *cobra.Command, _ []string) error {
170180 return fmt .Errorf ("error parsing commit points from " +
171181 "log file: %w" , err )
172182 }
173- return rescueClosedChannels (extendedKey , entries , commitPoints )
183+ return rescueClosedChannels (
184+ c .NumKeys , extendedKey , entries , commitPoints ,
185+ )
174186
175187 default :
176188 return errors .New ("you either need to specify --channeldb and " +
@@ -241,11 +253,11 @@ func commitPointsFromLogFile(lndLog string) ([]*btcec.PublicKey, error) {
241253 return result , nil
242254}
243255
244- func rescueClosedChannels (extendedKey * hdkeychain.ExtendedKey ,
256+ func rescueClosedChannels (numKeys uint32 , extendedKey * hdkeychain.ExtendedKey ,
245257 entries []* dataformat.SummaryEntry ,
246258 possibleCommitPoints []* btcec.PublicKey ) error {
247259
248- err := fillCache (extendedKey )
260+ err := fillCache (numKeys , extendedKey )
249261 if err != nil {
250262 return err
251263 }
@@ -279,7 +291,7 @@ outer:
279291 addr = entry .ClosingTX .ToRemoteAddr
280292 }
281293
282- wif , err := addrInCache (addr , commitPoint )
294+ wif , err := addrInCache (numKeys , addr , commitPoint )
283295 switch {
284296 case err == nil :
285297 entry .ClosingTX .SweepPrivkey = wif
@@ -316,7 +328,7 @@ outer:
316328 return os .WriteFile (fileName , summaryBytes , 0644 )
317329}
318330
319- func rescueClosedChannel (extendedKey * hdkeychain.ExtendedKey ,
331+ func rescueClosedChannel (numKeys uint32 , extendedKey * hdkeychain.ExtendedKey ,
320332 addr btcutil.Address , commitPoint * btcec.PublicKey ) error {
321333
322334 // Make the check on the decoded address according to the active
@@ -336,12 +348,12 @@ func rescueClosedChannel(extendedKey *hdkeychain.ExtendedKey,
336348 return errors .New ("address: must be a bech32 P2WPKH address" )
337349 }
338350
339- err := fillCache (extendedKey )
351+ err := fillCache (numKeys , extendedKey )
340352 if err != nil {
341353 return err
342354 }
343355
344- wif , err := addrInCache (addr .String (), commitPoint )
356+ wif , err := addrInCache (numKeys , addr .String (), commitPoint )
345357 switch {
346358 case err == nil :
347359 log .Infof ("Found private key %s for address %v!" , wif , addr )
@@ -356,7 +368,7 @@ func rescueClosedChannel(extendedKey *hdkeychain.ExtendedKey,
356368 }
357369
358370 // Try again as a static_remote_key address.
359- wif , err = addrInCache (addr .String (), nil )
371+ wif , err = addrInCache (numKeys , addr .String (), nil )
360372 switch {
361373 case err == nil :
362374 log .Infof ("Found private key %s for address %v!" , wif , addr )
@@ -372,7 +384,9 @@ func rescueClosedChannel(extendedKey *hdkeychain.ExtendedKey,
372384 }
373385}
374386
375- func addrInCache (addr string , perCommitPoint * btcec.PublicKey ) (string , error ) {
387+ func addrInCache (numKeys uint32 , addr string ,
388+ perCommitPoint * btcec.PublicKey ) (string , error ) {
389+
376390 targetPubKeyHash , scriptHash , err := lnd .DecodeAddressHash (
377391 addr , chainParams ,
378392 )
@@ -386,7 +400,7 @@ func addrInCache(addr string, perCommitPoint *btcec.PublicKey) (string, error) {
386400 // If the commit point is nil, we try with plain private keys to match
387401 // static_remote_key outputs.
388402 if perCommitPoint == nil {
389- for i := range cacheSize {
403+ for i := range numKeys {
390404 cacheEntry := cache [i ]
391405 hashedPubKey := btcutil .Hash160 (
392406 cacheEntry .pubKey .SerializeCompressed (),
@@ -415,7 +429,7 @@ func addrInCache(addr string, perCommitPoint *btcec.PublicKey) (string, error) {
415429 // Loop through all cached payment base point keys, tweak each of it
416430 // with the per_commit_point and see if the hashed public key
417431 // corresponds to the target pubKeyHash of the given address.
418- for i := range cacheSize {
432+ for i := range numKeys {
419433 cacheEntry := cache [i ]
420434 basePoint := cacheEntry .pubKey
421435 tweakedPubKey := input .TweakPubKey (basePoint , perCommitPoint )
@@ -446,17 +460,16 @@ func addrInCache(addr string, perCommitPoint *btcec.PublicKey) (string, error) {
446460 return "" , errAddrNotFound
447461}
448462
449- func fillCache (extendedKey * hdkeychain.ExtendedKey ) error {
450- cache = make ([]* cacheEntry , cacheSize )
463+ func fillCache (numKeys uint32 , extendedKey * hdkeychain.ExtendedKey ) error {
464+ cache = make ([]* cacheEntry , numKeys )
451465
452- for i := range cacheSize {
466+ for i := range numKeys {
453467 key , err := lnd .DeriveChildren (extendedKey , []uint32 {
454468 lnd .HardenedKeyStart + uint32 (keychain .BIP0043Purpose ),
455469 lnd .HardenedKeyStart + chainParams .HDCoinType ,
456- lnd .HardenedKeyStart +
457- uint32 (keychain .KeyFamilyPaymentBase ),
458- 0 ,
459- uint32 (i ),
470+ lnd .HardenedKeyStart + uint32 (
471+ keychain .KeyFamilyPaymentBase ,
472+ ), 0 , i ,
460473 })
461474 if err != nil {
462475 return err
@@ -476,7 +489,7 @@ func fillCache(extendedKey *hdkeychain.ExtendedKey) error {
476489
477490 if i > 0 && i % 10000 == 0 {
478491 fmt .Printf ("Filled cache with %d of %d keys.\n " ,
479- i , cacheSize )
492+ i , numKeys )
480493 }
481494 }
482495 return nil
0 commit comments