66	"encoding/json" 
77	"errors" 
88	"fmt" 
9- 	"io/ioutil " 
9+ 	"os " 
1010	"regexp" 
1111	"time" 
1212
@@ -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 "  + 
@@ -204,7 +216,7 @@ func commitPointsFromDB(chanDb *channeldb.ChannelStateDB) ([]*btcec.PublicKey,
204216}
205217
206218func  commitPointsFromLogFile (lndLog  string ) ([]* btcec.PublicKey , error ) {
207- 	logFileBytes , err  :=  ioutil .ReadFile (lndLog )
219+ 	logFileBytes , err  :=  os .ReadFile (lndLog )
208220	if  err  !=  nil  {
209221		return  nil , fmt .Errorf ("error reading log file %s: %w" , lndLog ,
210222			err )
@@ -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 
@@ -313,10 +325,10 @@ outer:
313325	fileName  :=  fmt .Sprintf ("results/rescueclosed-%s.json" ,
314326		time .Now ().Format ("2006-01-02-15-04-05" ))
315327	log .Infof ("Writing result to %s" , fileName )
316- 	return  ioutil .WriteFile (fileName , summaryBytes , 0644 )
328+ 	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