Skip to content

Commit 3c3bdc4

Browse files
minhd-vuleovctclaude
authored
feat: query witnesses over wit/1 protocol (#634)
* feat: query witnesses * fix: update request id * fix: disable tx fetching * fix: print enode * fix: return when EOF error * fix: lint * feat: use witness pagination * feat: request witness pages * fix: requesting multiple witness pages * fix: logging * fix: logging * fix: undo comments * feat: ping private key flags * fix: flag set * feat: add DialOpts * fix: remove duplicate listen flag * fix: remove unnecessary int cast * fix: listen flag desc * docs: make gen-doc * fix: remove unused log * fix: remove log import * feat: add key file flags to p2p query * fix: mark query key flags mutex * fix: p2p query conflicting `a` shorthand * docs: make gen-doc * fix: clean up logs * feat: handle enabling caps --------- Co-authored-by: Léo Vincent <[email protected]> Co-authored-by: Claude <[email protected]>
1 parent e530bd0 commit 3c3bdc4

File tree

9 files changed

+326
-27
lines changed

9 files changed

+326
-27
lines changed

cmd/p2p/crawl/crawl_util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func (c *crawler) updateNode(n *enode.Node) int {
181181
c.mu.Unlock()
182182
}()
183183

184-
conn, dialErr := p2p.Dial(n)
184+
conn, dialErr := p2p.Dial(n, p2p.NewDialOpts())
185185
if err = dialErr; err != nil {
186186
log.Error().Err(err).Msg("Dial failed")
187187
return nodeDialErr

cmd/p2p/ping/ping.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package ping
22

33
import (
4+
"crypto/ecdsa"
5+
"net"
46
"sync"
57
"time"
68

@@ -17,6 +19,13 @@ type (
1719
OutputFile string
1820
NodesFile string
1921
Listen bool
22+
Port int
23+
Addr net.IP
24+
KeyFile string
25+
PrivateKey string
26+
EnableWit bool
27+
28+
privateKey *ecdsa.PrivateKey
2029
}
2130
)
2231

@@ -34,6 +43,14 @@ Status messages and output JSON. If providing a enode/enr rather than a nodes
3443
file, then the connection will remain open by default (--listen=true), and you
3544
can see other messages the peer sends (e.g. blocks, transactions, etc.).`,
3645
Args: cobra.MinimumNArgs(1),
46+
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
47+
inputPingParams.privateKey, err = p2p.ParsePrivateKey(inputPingParams.KeyFile, inputPingParams.PrivateKey)
48+
if err != nil {
49+
return err
50+
}
51+
52+
return nil
53+
},
3754
RunE: func(cmd *cobra.Command, args []string) error {
3855
nodes := []*enode.Node{}
3956
if input, err := p2p.ReadNodeSet(args[0]); err == nil {
@@ -81,7 +98,14 @@ can see other messages the peer sends (e.g. blocks, transactions, etc.).`,
8198
status *p2p.Status
8299
)
83100

84-
conn, err := p2p.Dial(node)
101+
opts := p2p.DialOpts{
102+
EnableWit: inputPingParams.EnableWit,
103+
Port: inputPingParams.Port,
104+
Addr: inputPingParams.Addr,
105+
PrivateKey: inputPingParams.privateKey,
106+
}
107+
108+
conn, err := p2p.Dial(node, opts)
85109
if err != nil {
86110
log.Error().Err(err).Msg("Dial failed")
87111
} else {
@@ -133,4 +157,10 @@ func init() {
133157
f.BoolVarP(&inputPingParams.Listen, "listen", "l", true,
134158
`keep connection open and listen to peer. This only works if first
135159
argument is an enode/enr, not a nodes file`)
160+
f.BoolVarP(&inputPingParams.EnableWit, "wit", "w", false, "enable wit/1 capability")
161+
f.IntVarP(&inputPingParams.Port, "port", "P", 30303, "port for discovery protocol")
162+
f.IPVarP(&inputPingParams.Addr, "addr", "a", net.ParseIP("127.0.0.1"), "address to bind discovery listener")
163+
f.StringVarP(&inputPingParams.KeyFile, "key-file", "k", "", "private key file (cannot be set with --key)")
164+
f.StringVar(&inputPingParams.PrivateKey, "key", "", "hex-encoded private key (cannot be set with --key-file)")
165+
PingCmd.MarkFlagsMutuallyExclusive("key-file", "key")
136166
}

cmd/p2p/query/query.go

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package query
22

33
import (
4+
"crypto/ecdsa"
45
"fmt"
6+
"net"
57

68
"github.com/ethereum/go-ethereum/eth/protocols/eth"
79
"github.com/rs/zerolog/log"
@@ -14,6 +16,12 @@ type (
1416
queryParams struct {
1517
StartBlock uint64
1618
Amount uint64
19+
Port int
20+
Addr net.IP
21+
KeyFile string
22+
PrivateKey string
23+
24+
privateKey *ecdsa.PrivateKey
1725
}
1826
)
1927

@@ -30,10 +38,16 @@ This command will initially establish a handshake and exchange status message
3038
from the peer. Then, it will query the node for block(s) given the start block
3139
and the amount of blocks to query and print the results.`,
3240
Args: cobra.MinimumNArgs(1),
33-
PreRunE: func(cmd *cobra.Command, args []string) error {
41+
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
3442
if inputQueryParams.Amount < 1 {
3543
return fmt.Errorf("amount must be greater than 0")
3644
}
45+
46+
inputQueryParams.privateKey, err = p2p.ParsePrivateKey(inputQueryParams.KeyFile, inputQueryParams.PrivateKey)
47+
if err != nil {
48+
return err
49+
}
50+
3751
return nil
3852
},
3953
Run: func(cmd *cobra.Command, args []string) {
@@ -50,7 +64,13 @@ and the amount of blocks to query and print the results.`,
5064
amount uint64 = inputQueryParams.Amount
5165
)
5266

53-
conn, err := p2p.Dial(node)
67+
opts := p2p.DialOpts{
68+
Port: inputQueryParams.Port,
69+
Addr: inputQueryParams.Addr,
70+
PrivateKey: inputQueryParams.privateKey,
71+
}
72+
73+
conn, err := p2p.Dial(node, opts)
5474
if err != nil {
5575
log.Error().Err(err).Msg("Dial failed")
5676
return
@@ -104,8 +124,14 @@ func print(headers eth.BlockHeadersRequest) {
104124
}
105125

106126
func init() {
107-
QueryCmd.Flags().Uint64VarP(&inputQueryParams.StartBlock, "start-block", "s", 0, "block number to start querying from")
108-
QueryCmd.Flags().Uint64VarP(&inputQueryParams.Amount, "amount", "a", 1, "amount of blocks to query")
127+
f := QueryCmd.Flags()
128+
f.Uint64VarP(&inputQueryParams.StartBlock, "start-block", "s", 0, "block number to start querying from")
129+
f.Uint64VarP(&inputQueryParams.Amount, "amount", "a", 1, "amount of blocks to query")
130+
f.IntVarP(&inputQueryParams.Port, "port", "P", 30303, "port for discovery protocol")
131+
f.IPVar(&inputQueryParams.Addr, "addr", net.ParseIP("127.0.0.1"), "address to bind discovery listener")
132+
f.StringVarP(&inputQueryParams.KeyFile, "key-file", "k", "", "private key file (cannot be set with --key)")
133+
f.StringVar(&inputQueryParams.PrivateKey, "key", "", "hex-encoded private key (cannot be set with --key-file)")
134+
QueryCmd.MarkFlagsMutuallyExclusive("key-file", "key")
109135
if err := QueryCmd.MarkFlagRequired("start-block"); err != nil {
110136
log.Error().Err(err).Msg("Failed to mark start-block as required flag")
111137
}

doc/polycli_p2p_ping.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,16 @@ can see other messages the peer sends (e.g. blocks, transactions, etc.).
2828
## Flags
2929

3030
```bash
31-
-h, --help help for ping
32-
-l, --listen keep connection open and listen to peer. This only works if first
33-
argument is an enode/enr, not a nodes file (default true)
34-
-o, --output string write ping results to output file (default stdout)
35-
-p, --parallel int how many parallel pings to attempt (default 16)
31+
-a, --addr ip address to bind discovery listener (default 127.0.0.1)
32+
-h, --help help for ping
33+
--key string hex-encoded private key (cannot be set with --key-file)
34+
-k, --key-file string private key file (cannot be set with --key)
35+
-l, --listen keep connection open and listen to peer. This only works if first
36+
argument is an enode/enr, not a nodes file (default true)
37+
-o, --output string write ping results to output file (default stdout)
38+
-p, --parallel int how many parallel pings to attempt (default 16)
39+
-P, --port int port for discovery protocol (default 30303)
40+
-w, --wit enable wit/1 capability
3641
```
3742
3843
The command also inherits flags from parent commands.

doc/polycli_p2p_query.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ and the amount of blocks to query and print the results.
2727
## Flags
2828

2929
```bash
30+
--addr ip address to bind discovery listener (default 127.0.0.1)
3031
-a, --amount uint amount of blocks to query (default 1)
3132
-h, --help help for query
33+
--key string hex-encoded private key (cannot be set with --key-file)
34+
-k, --key-file string private key file (cannot be set with --key)
35+
-P, --port int port for discovery protocol (default 30303)
3236
-s, --start-block uint block number to start querying from
3337
```
3438

p2p/log.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ type MessageCount struct {
2121
Pings int64 `json:"pings,omitempty"`
2222
Errors int64 `json:"errors,omitempty"`
2323
Disconnects int64 `json:"disconnects,omitempty"`
24+
NewWitness int64 `json:"new_witness,omitempty"`
25+
NewWitnessHashes int64 `json:"new_witness_hashes,omitempty"`
26+
GetWitnessRequest int64 `json:"get_witness_request,omitempty"`
27+
Witness int64 `json:"witness,omitempty"`
2428
}
2529

2630
// Load takes a snapshot of all the counts in a thread-safe manner. Make sure
@@ -39,6 +43,10 @@ func (count *MessageCount) Load() MessageCount {
3943
Pings: atomic.LoadInt64(&count.Pings),
4044
Errors: atomic.LoadInt64(&count.Errors),
4145
Disconnects: atomic.LoadInt64(&count.Disconnects),
46+
NewWitness: atomic.LoadInt64(&count.NewWitness),
47+
NewWitnessHashes: atomic.LoadInt64(&count.NewWitnessHashes),
48+
GetWitnessRequest: atomic.LoadInt64(&count.GetWitnessRequest),
49+
Witness: atomic.LoadInt64(&count.Witness),
4250
}
4351
}
4452

@@ -56,6 +64,10 @@ func (count *MessageCount) Clear() {
5664
atomic.StoreInt64(&count.Pings, 0)
5765
atomic.StoreInt64(&count.Errors, 0)
5866
atomic.StoreInt64(&count.Disconnects, 0)
67+
atomic.StoreInt64(&count.NewWitness, 0)
68+
atomic.StoreInt64(&count.NewWitnessHashes, 0)
69+
atomic.StoreInt64(&count.GetWitnessRequest, 0)
70+
atomic.StoreInt64(&count.Witness, 0)
5971
}
6072

6173
// IsEmpty checks whether the sum of all the counts is empty. Make sure to call

p2p/p2p.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ package p2p
22

33
import (
44
"bytes"
5+
"crypto/ecdsa"
56
"encoding/base64"
67
"encoding/hex"
78
"fmt"
89
"net"
910
"strings"
1011

12+
"github.com/ethereum/go-ethereum/crypto"
1113
"github.com/ethereum/go-ethereum/p2p/enode"
1214
"github.com/ethereum/go-ethereum/p2p/enr"
1315
"github.com/ethereum/go-ethereum/rlp"
16+
"github.com/rs/zerolog/log"
1417
)
1518

1619
func Listen(ln *enode.LocalNode) (*net.UDPConn, error) {
@@ -101,3 +104,43 @@ func ParseBootnodes(bootnodes string) ([]*enode.Node, error) {
101104

102105
return nodes, nil
103106
}
107+
108+
// ParsePrivateKey loads a private key from a file path or hex string.
109+
// If file is provided, it attempts to load from the file path first.
110+
// If the file doesn't exist, it generates a new key and saves it to the file.
111+
// If key is provided instead, it parses the hex-encoded private key string.
112+
// If neither file nor key is provided, it generates and returns a new private key.
113+
func ParsePrivateKey(file string, key string) (*ecdsa.PrivateKey, error) {
114+
if len(file) > 0 {
115+
privateKey, err := crypto.LoadECDSA(file)
116+
if err == nil {
117+
return privateKey, nil
118+
}
119+
120+
log.Warn().Err(err).Msg("Key file was not found, generating a new key file")
121+
122+
privateKey, err = crypto.GenerateKey()
123+
if err != nil {
124+
log.Error().Err(err).Msg("Failed to generate new private key")
125+
return nil, err
126+
}
127+
128+
if err := crypto.SaveECDSA(file, privateKey); err != nil {
129+
log.Error().Err(err).Msg("Failed to save private key to file")
130+
return nil, err
131+
}
132+
133+
return privateKey, nil
134+
}
135+
136+
if len(key) > 0 {
137+
privateKey, err := crypto.HexToECDSA(key)
138+
if err != nil {
139+
log.Error().Err(err).Msg("Failed to parse private key")
140+
return nil, err
141+
}
142+
return privateKey, nil
143+
}
144+
145+
return crypto.GenerateKey()
146+
}

0 commit comments

Comments
 (0)