diff --git a/cmd/chantools/rescueclosed.go b/cmd/chantools/rescueclosed.go index 7d03389..5ec19dd 100644 --- a/cmd/chantools/rescueclosed.go +++ b/cmd/chantools/rescueclosed.go @@ -22,7 +22,7 @@ import ( ) var ( - cacheSize = 2000 + cacheSize = 5000 cache []*cacheEntry errAddrNotFound = errors.New("addr not found") @@ -248,6 +248,14 @@ func rescueClosedChannels(extendedKey *hdkeychain.ExtendedKey, return err } + // Add a nil commit point to the list of possible commit points to also + // try brute forcing a static_remote_key address. + possibleCommitPoints = append(possibleCommitPoints, nil) + + // We'll also keep track of all rescued keys for an additional log + // output. + resultMap := make(map[string]string) + // Try naive/lucky guess by trying out all combinations. outer: for _, entry := range entries { @@ -273,6 +281,8 @@ outer: switch { case err == nil: entry.ClosingTX.SweepPrivkey = wif + resultMap[addr] = wif + continue outer case err == errAddrNotFound: @@ -283,6 +293,15 @@ outer: } } + importStr := "" + for addr, wif := range resultMap { + importStr += fmt.Sprintf(`importprivkey "%s" "%s" false%s`, wif, + addr, "\n") + } + log.Infof("Found %d private keys! Import them into bitcoind through "+ + "the console by pasting: \n%srescanblockchain 481824\n", + len(resultMap), importStr) + summaryBytes, err := json.MarshalIndent(&dataformat.SummaryEntryFile{ Channels: entries, }, "", " ") @@ -327,6 +346,21 @@ func rescueClosedChannel(extendedKey *hdkeychain.ExtendedKey, return nil + case err == errAddrNotFound: + // Try again as a static_remote_key. + + default: + return err + } + + // Try again as a static_remote_key address. + wif, err = addrInCache(addr.String(), nil) + switch { + case err == nil: + log.Infof("Found private key %s for address %v!", wif, addr) + + return nil + case err == errAddrNotFound: return fmt.Errorf("did not find private key for address %v", addr) @@ -347,6 +381,33 @@ func addrInCache(addr string, perCommitPoint *btcec.PublicKey) (string, error) { return "", fmt.Errorf("address must be a P2WPKH address") } + // If the commit point is nil, we try with plain private keys to match + // static_remote_key outputs. + if perCommitPoint == nil { + for i := 0; i < cacheSize; i++ { + cacheEntry := cache[i] + hashedPubKey := btcutil.Hash160( + cacheEntry.pubKey.SerializeCompressed(), + ) + equal := subtle.ConstantTimeCompare( + targetPubKeyHash, hashedPubKey, + ) + if equal == 1 { + wif, err := btcutil.NewWIF( + cacheEntry.privKey, chainParams, true, + ) + if err != nil { + return "", err + } + log.Infof("The private key for addr %s "+ + "(static_remote_key) found after "+ + "%d tries: %s", addr, i, wif.String(), + ) + return wif.String(), nil + } + } + } + // Loop through all cached payment base point keys, tweak each of it // with the per_commit_point and see if the hashed public key // corresponds to the target pubKeyHash of the given address. diff --git a/cmd/chantools/root.go b/cmd/chantools/root.go index c98ac14..7853d7a 100644 --- a/cmd/chantools/root.go +++ b/cmd/chantools/root.go @@ -26,7 +26,7 @@ import ( const ( defaultAPIURL = "https://blockstream.info/api" - version = "0.8.2" + version = "0.8.3" na = "n/a" Commit = ""