Skip to content

Commit 6d15285

Browse files
authored
Merge pull request #199 from lightninglabs/itest
Add more tests, make `derivekey` CLN compatible, allow disabling log
2 parents 30920a3 + 0491cf7 commit 6d15285

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+532
-182
lines changed

.github/workflows/main.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ jobs:
4848
uses: actions/setup-go@v2
4949
with:
5050
go-version: '${{ env.GO_VERSION }}'
51+
52+
- name: Install chantools
53+
run: make install
5154

5255
- name: run unit tests
5356
run: make unit

.golangci.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
run:
22
# timeout for analysis
33
timeout: 4m
4+
go: "1.23"
45

56
linters-settings:
67
govet:
78
# Don't report about shadowed variables
8-
check-shadowing: false
9+
shadow: false
910
gofmt:
1011
# simplify code: gofmt with `-s` option, true by default
1112
simplify: true
@@ -17,7 +18,6 @@ linters-settings:
1718
rules:
1819
json: snake
1920
staticcheck:
20-
go: "1.18"
2121
checks: ["-SA1019"]
2222
gomoddirectives:
2323
replace-allow-list:
@@ -34,7 +34,6 @@ linters:
3434
- varnamelen
3535
- wrapcheck
3636
- testpackage
37-
- gomnd
3837
- err113
3938
- exhaustruct
4039
- forbidigo

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ Legend:
484484
| [compactdb](doc/chantools_compactdb.md) | Run database compaction manually to reclaim space |
485485
| [createwallet](doc/chantools_createwallet.md) | :pencil: Create a new lnd compatible wallet.db file from an existing seed or by generating a new one |
486486
| [deletepayments](doc/chantools_deletepayments.md) | Remove ALL payments from a `channel.db` file to reduce size |
487-
| [derivekey](doc/chantools_derivekey.md) | :pencil: Derive a single private/public key from `lnd`'s seed, use to test seed |
487+
| [derivekey](doc/chantools_derivekey.md) | :pencil: (**CLN**) Derive a single private/public key from `lnd`'s seed, use to test seed |
488488
| [doublespendinputs](doc/chantools_doublespendinputs.md) | :pencil: Tries to double spend the given inputs by deriving the private for the address and sweeping the funds to the given address |
489489
| [dropchannelgraph](doc/chantools_dropchannelgraph.md) | ( :warning: ) Completely drop the channel graph from a `channel.db` to force re-sync (not recommended while channels are open!) |
490490
| [dropgraphzombies](doc/chantools_dropgraphzombies.md) | Drop all zombie channels from a `channel.db` to force a graph re-sync |

cmd/chantools/derivekey.go

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package main
22

33
import (
4+
"encoding/hex"
5+
"errors"
46
"fmt"
57

68
"github.com/btcsuite/btcd/btcutil"
79
"github.com/btcsuite/btcd/btcutil/hdkeychain"
10+
"github.com/lightninglabs/chantools/cln"
811
"github.com/lightninglabs/chantools/lnd"
912
"github.com/spf13/cobra"
1013
)
@@ -27,6 +30,8 @@ type deriveKeyCommand struct {
2730
Neuter bool
2831
Identity bool
2932

33+
HsmSecret string
34+
3035
rootKey *rootKey
3136
cmd *cobra.Command
3237
}
@@ -53,8 +58,14 @@ chantools derivekey --identity`,
5358
"only public key(s)",
5459
)
5560
cc.cmd.Flags().BoolVar(
56-
&cc.Identity, "identity", false, "derive the lnd "+
57-
"identity_pubkey",
61+
&cc.Identity, "identity", false, "derive the node's identity "+
62+
"public key",
63+
)
64+
cc.cmd.Flags().StringVar(
65+
&cc.HsmSecret, "hsm_secret", "", "the hex encoded HSM secret "+
66+
"to use for deriving the multisig keys for a CLN "+
67+
"node; obtain by running 'xxd -p -c32 "+
68+
"~/.lightning/bitcoin/hsm_secret'",
5869
)
5970

6071
cc.rootKey = newRootKey(cc.cmd, "decrypting the backup")
@@ -63,6 +74,40 @@ chantools derivekey --identity`,
6374
}
6475

6576
func (c *deriveKeyCommand) Execute(_ *cobra.Command, _ []string) error {
77+
if c.HsmSecret != "" {
78+
if c.Path != "" {
79+
return errors.New("cannot specify --path with " +
80+
"--hsm_secret, only identity key can be " +
81+
"derived")
82+
}
83+
84+
secretBytes, err := hex.DecodeString(c.HsmSecret)
85+
if err != nil {
86+
return fmt.Errorf("error decoding HSM secret: %w", err)
87+
}
88+
89+
var hsmSecret [32]byte
90+
copy(hsmSecret[:], secretBytes)
91+
92+
nodePubKey, _, err := cln.NodeKey(hsmSecret)
93+
if err != nil {
94+
return fmt.Errorf("error deriving node key from HSM: "+
95+
"%w", err)
96+
}
97+
98+
result := fmt.Sprintf(
99+
"Node identity public key: %x",
100+
nodePubKey.SerializeCompressed(),
101+
)
102+
fmt.Println(result)
103+
104+
// For the tests, also log as trace level which is disabled by
105+
// default.
106+
log.Tracef(result)
107+
108+
return nil
109+
}
110+
66111
extendedKey, err := c.rootKey.read()
67112
if err != nil {
68113
return fmt.Errorf("error reading root key: %w", err)

cmd/chantools/derivekey_test.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,9 @@ func TestDeriveKeyXprv(t *testing.T) {
9999
err := derive.Execute(nil, nil)
100100
require.NoError(t, err)
101101

102-
h.assertLogContains("cQcdieZy2d1TAdCsa5MjmHJs2gdHcD7x22nDbhJyVTUa3Ax" +
103-
"5KB3w")
102+
h.assertLogContains(
103+
"cQcdieZy2d1TAdCsa5MjmHJs2gdHcD7x22nDbhJyVTUa3Ax5KB3w",
104+
)
104105
}
105106

106107
func TestDeriveKeyXpub(t *testing.T) {
@@ -120,8 +121,10 @@ func TestDeriveKeyXpub(t *testing.T) {
120121
err := derive.Execute(nil, nil)
121122
require.NoError(t, err)
122123

123-
h.assertLogContains("03dc8655d58bd4fd4326863fe34bd5cdddbefaa3b042571" +
124-
"05eb1ab99aa05e01c2a")
124+
h.assertLogContains(
125+
"03dc8655d58bd4fd4326863fe34bd5cdddbefaa3b04257105eb1ab99aa05e" +
126+
"01c2a",
127+
)
125128
}
126129

127130
func TestDeriveKeyXpubNoNeuter(t *testing.T) {
@@ -140,6 +143,27 @@ func TestDeriveKeyXpubNoNeuter(t *testing.T) {
140143
err := derive.Execute(nil, nil)
141144
require.NoError(t, err)
142145

143-
h.assertLogContains("03dc8655d58bd4fd4326863fe34bd5cdddbefaa3b042571" +
144-
"05eb1ab99aa05e01c2a")
146+
h.assertLogContains(
147+
"03dc8655d58bd4fd4326863fe34bd5cdddbefaa3b04257105eb1ab99aa05e" +
148+
"01c2a",
149+
)
150+
}
151+
152+
func TestDeriveKeyHsmSecret(t *testing.T) {
153+
h := newHarness(t)
154+
155+
// Derive a specific key from the serialized root key.
156+
derive := &deriveKeyCommand{
157+
Identity: true,
158+
HsmSecret: "471a115fb8edd6281f883ac82509fb0f30707e590d895f683" +
159+
"2d781f1639c07ff",
160+
}
161+
162+
err := derive.Execute(nil, nil)
163+
require.NoError(t, err)
164+
165+
h.assertLogContains(
166+
"03508beb59d2ec4772cd7b143bbef0fdac204b240747e82bc5fe58bd0418" +
167+
"4f35a3",
168+
)
145169
}

cmd/chantools/root.go

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const (
3131
// version is the current version of the tool. It is set during build.
3232
// NOTE: When changing this, please also update the version in the
3333
// download link shown in the README.
34-
version = "0.14.0"
34+
version = "0.14.1"
3535
na = "n/a"
3636

3737
// lndVersion is the current version of lnd that we support. This is
@@ -47,15 +47,13 @@ const (
4747
)
4848

4949
var (
50-
Testnet bool
51-
Regtest bool
52-
Signet bool
50+
Testnet bool
51+
Regtest bool
52+
Signet bool
53+
NoLogFile bool
54+
55+
log btclog.Logger
5356

54-
logWriter = build.NewRotatingLogWriter()
55-
subLogMgr = build.NewSubLoggerManager(build.NewDefaultLogHandlers(
56-
build.DefaultLogConfig(), logWriter,
57-
)...)
58-
log = build.NewSubLogger("CHAN", genSubLogger(subLogMgr))
5957
chainParams = &chaincfg.MainNetParams
6058
)
6159

@@ -103,6 +101,11 @@ func main() {
103101
&Signet, "signet", "s", false, "Indicates if the public "+
104102
"signet parameters should be used",
105103
)
104+
rootCmd.PersistentFlags().BoolVar(
105+
&NoLogFile, "nologfile", false, "If set, no log file "+
106+
"will be created. This is useful for testing purposes "+
107+
"where we don't want to create a log file.",
108+
)
106109

107110
rootCmd.AddCommand(
108111
newChanBackupCommand(),
@@ -328,28 +331,34 @@ func readInput(input string) ([]byte, error) {
328331
}
329332

330333
func setupLogging() {
331-
setSubLogger("CHAN", log)
332-
addSubLogger("CHDB", channeldb.UseLogger)
333-
addSubLogger("BCKP", chanbackup.UseLogger)
334-
addSubLogger("PEER", peer.UseLogger)
335-
336-
err := logWriter.InitLogRotator(
337-
&build.FileLoggerConfig{
338-
Compressor: build.Gzip,
339-
MaxLogFiles: 3,
340-
MaxLogFileSize: 10,
341-
},
342-
"./results/chantools.log",
343-
)
344-
if err != nil {
345-
panic(err)
346-
}
347-
334+
logWriter := build.NewRotatingLogWriter()
348335
subLogMgr := build.NewSubLoggerManager(build.NewDefaultLogHandlers(
349336
build.DefaultLogConfig(), logWriter,
350337
)...)
351338

352-
err = build.ParseAndSetDebugLevels("debug", subLogMgr)
339+
log = build.NewSubLogger("CHAN", genSubLogger(subLogMgr))
340+
log.SetLevel(btclog.LevelDebug)
341+
342+
setSubLogger(subLogMgr, "CHAN", log)
343+
addSubLogger(subLogMgr, "CHDB", channeldb.UseLogger)
344+
addSubLogger(subLogMgr, "BCKP", chanbackup.UseLogger)
345+
addSubLogger(subLogMgr, "PEER", peer.UseLogger)
346+
347+
if !NoLogFile {
348+
err := logWriter.InitLogRotator(
349+
&build.FileLoggerConfig{
350+
Compressor: build.Gzip,
351+
MaxLogFiles: 3,
352+
MaxLogFileSize: 10,
353+
},
354+
"./results/chantools.log",
355+
)
356+
if err != nil {
357+
panic(err)
358+
}
359+
}
360+
361+
err := build.ParseAndSetDebugLevels("debug", subLogMgr)
353362
if err != nil {
354363
panic(err)
355364
}
@@ -364,17 +373,19 @@ func genSubLogger(mgr *build.SubLoggerManager) func(string) btclog.Logger {
364373

365374
// addSubLogger is a helper method to conveniently create and register the
366375
// logger of one or more sub systems.
367-
func addSubLogger(subsystem string, useLoggers ...func(btclog.Logger)) {
376+
func addSubLogger(subLogMgr *build.SubLoggerManager, subsystem string,
377+
useLoggers ...func(btclog.Logger)) {
378+
368379
// Create and register just a single logger to prevent them from
369380
// overwriting each other internally.
370381
logger := build.NewSubLogger(subsystem, genSubLogger(subLogMgr))
371-
setSubLogger(subsystem, logger, useLoggers...)
382+
setSubLogger(subLogMgr, subsystem, logger, useLoggers...)
372383
}
373384

374385
// setSubLogger is a helper method to conveniently register the logger of a sub
375386
// system.
376-
func setSubLogger(subsystem string, logger btclog.Logger,
377-
useLoggers ...func(btclog.Logger)) {
387+
func setSubLogger(subLogMgr *build.SubLoggerManager, subsystem string,
388+
logger btclog.Logger, useLoggers ...func(btclog.Logger)) {
378389

379390
subLogMgr.RegisterSubLogger(subsystem, logger)
380391
for _, useLogger := range useLoggers {

doc/chantools.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ https://github.com/lightninglabs/chantools/.
1212
### Options
1313

1414
```
15-
-h, --help help for chantools
16-
-r, --regtest Indicates if regtest parameters should be used
17-
-s, --signet Indicates if the public signet parameters should be used
18-
-t, --testnet Indicates if testnet parameters should be used
15+
-h, --help help for chantools
16+
--nologfile If set, no log file will be created. This is useful for testing purposes where we don't want to create a log file.
17+
-r, --regtest Indicates if regtest parameters should be used
18+
-s, --signet Indicates if the public signet parameters should be used
19+
-t, --testnet Indicates if testnet parameters should be used
1920
```
2021

2122
### SEE ALSO

doc/chantools_chanbackup.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ chantools chanbackup \
3333
### Options inherited from parent commands
3434

3535
```
36-
-r, --regtest Indicates if regtest parameters should be used
37-
-s, --signet Indicates if the public signet parameters should be used
38-
-t, --testnet Indicates if testnet parameters should be used
36+
--nologfile If set, no log file will be created. This is useful for testing purposes where we don't want to create a log file.
37+
-r, --regtest Indicates if regtest parameters should be used
38+
-s, --signet Indicates if the public signet parameters should be used
39+
-t, --testnet Indicates if testnet parameters should be used
3940
```
4041

4142
### SEE ALSO

doc/chantools_closepoolaccount.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ chantools closepoolaccount \
4848
### Options inherited from parent commands
4949

5050
```
51-
-r, --regtest Indicates if regtest parameters should be used
52-
-s, --signet Indicates if the public signet parameters should be used
53-
-t, --testnet Indicates if testnet parameters should be used
51+
--nologfile If set, no log file will be created. This is useful for testing purposes where we don't want to create a log file.
52+
-r, --regtest Indicates if regtest parameters should be used
53+
-s, --signet Indicates if the public signet parameters should be used
54+
-t, --testnet Indicates if testnet parameters should be used
5455
```
5556

5657
### SEE ALSO

doc/chantools_compactdb.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ chantools compactdb \
3131
### Options inherited from parent commands
3232

3333
```
34-
-r, --regtest Indicates if regtest parameters should be used
35-
-s, --signet Indicates if the public signet parameters should be used
36-
-t, --testnet Indicates if testnet parameters should be used
34+
--nologfile If set, no log file will be created. This is useful for testing purposes where we don't want to create a log file.
35+
-r, --regtest Indicates if regtest parameters should be used
36+
-s, --signet Indicates if the public signet parameters should be used
37+
-t, --testnet Indicates if testnet parameters should be used
3738
```
3839

3940
### SEE ALSO

0 commit comments

Comments
 (0)