Skip to content

Commit 3a06ffe

Browse files
committed
rescueclosed: support static_remote_key outputs
1 parent e8e7c64 commit 3a06ffe

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

cmd/chantools/rescueclosed.go

+62-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import (
2222
)
2323

2424
var (
25-
cacheSize = 2000
25+
cacheSize = 5000
2626
cache []*cacheEntry
2727

2828
errAddrNotFound = errors.New("addr not found")
@@ -248,6 +248,14 @@ func rescueClosedChannels(extendedKey *hdkeychain.ExtendedKey,
248248
return err
249249
}
250250

251+
// Add a nil commit point to the list of possible commit points to also
252+
// try brute forcing a static_remote_key address.
253+
possibleCommitPoints = append(possibleCommitPoints, nil)
254+
255+
// We'll also keep track of all rescued keys for an additional log
256+
// output.
257+
resultMap := make(map[string]string)
258+
251259
// Try naive/lucky guess by trying out all combinations.
252260
outer:
253261
for _, entry := range entries {
@@ -273,6 +281,8 @@ outer:
273281
switch {
274282
case err == nil:
275283
entry.ClosingTX.SweepPrivkey = wif
284+
resultMap[addr] = wif
285+
276286
continue outer
277287

278288
case err == errAddrNotFound:
@@ -283,6 +293,15 @@ outer:
283293
}
284294
}
285295

296+
importStr := ""
297+
for addr, wif := range resultMap {
298+
importStr += fmt.Sprintf(`importprivkey "%s" "%s" false%s`, wif,
299+
addr, "\n")
300+
}
301+
log.Infof("Found %d private keys! Import them into bitcoind through "+
302+
"the console by pasting: \n%srescanblockchain 481824\n",
303+
len(resultMap), importStr)
304+
286305
summaryBytes, err := json.MarshalIndent(&dataformat.SummaryEntryFile{
287306
Channels: entries,
288307
}, "", " ")
@@ -327,6 +346,21 @@ func rescueClosedChannel(extendedKey *hdkeychain.ExtendedKey,
327346

328347
return nil
329348

349+
case err == errAddrNotFound:
350+
// Try again as a static_remote_key.
351+
352+
default:
353+
return err
354+
}
355+
356+
// Try again as a static_remote_key address.
357+
wif, err = addrInCache(addr.String(), nil)
358+
switch {
359+
case err == nil:
360+
log.Infof("Found private key %s for address %v!", wif, addr)
361+
362+
return nil
363+
330364
case err == errAddrNotFound:
331365
return fmt.Errorf("did not find private key for address %v",
332366
addr)
@@ -347,6 +381,33 @@ func addrInCache(addr string, perCommitPoint *btcec.PublicKey) (string, error) {
347381
return "", fmt.Errorf("address must be a P2WPKH address")
348382
}
349383

384+
// If the commit point is nil, we try with plain private keys to match
385+
// static_remote_key outputs.
386+
if perCommitPoint == nil {
387+
for i := 0; i < cacheSize; i++ {
388+
cacheEntry := cache[i]
389+
hashedPubKey := btcutil.Hash160(
390+
cacheEntry.pubKey.SerializeCompressed(),
391+
)
392+
equal := subtle.ConstantTimeCompare(
393+
targetPubKeyHash, hashedPubKey,
394+
)
395+
if equal == 1 {
396+
wif, err := btcutil.NewWIF(
397+
cacheEntry.privKey, chainParams, true,
398+
)
399+
if err != nil {
400+
return "", err
401+
}
402+
log.Infof("The private key for addr %s "+
403+
"(static_remote_key) found after "+
404+
"%d tries: %s", addr, i, wif.String(),
405+
)
406+
return wif.String(), nil
407+
}
408+
}
409+
}
410+
350411
// Loop through all cached payment base point keys, tweak each of it
351412
// with the per_commit_point and see if the hashed public key
352413
// corresponds to the target pubKeyHash of the given address.

cmd/chantools/root.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626

2727
const (
2828
defaultAPIURL = "https://blockstream.info/api"
29-
version = "0.8.2"
29+
version = "0.8.3"
3030
na = "n/a"
3131

3232
Commit = ""

0 commit comments

Comments
 (0)