-
Notifications
You must be signed in to change notification settings - Fork 79
Expand file tree
/
Copy pathquery.go
More file actions
138 lines (117 loc) · 4.06 KB
/
query.go
File metadata and controls
138 lines (117 loc) · 4.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package query
import (
"crypto/ecdsa"
"fmt"
"net"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/0xPolygon/polygon-cli/p2p"
)
type (
queryParams struct {
StartBlock uint64
Amount uint64
Port int
Addr net.IP
KeyFile string
PrivateKey string
privateKey *ecdsa.PrivateKey
}
)
var (
inputQueryParams queryParams
)
var QueryCmd = &cobra.Command{
Use: "query [enode/enr]",
Short: "Query block header(s) from node and prints the output.",
Long: `Query header of single block or range of blocks given a single enode/enr.
This command will initially establish a handshake and exchange status message
from the peer. Then, it will query the node for block(s) given the start block
and the amount of blocks to query and print the results.`,
Args: cobra.MinimumNArgs(1),
PreRunE: func(cmd *cobra.Command, args []string) (err error) {
if inputQueryParams.Amount < 1 {
return fmt.Errorf("amount must be greater than 0")
}
inputQueryParams.privateKey, err = p2p.ParsePrivateKey(inputQueryParams.KeyFile, inputQueryParams.PrivateKey)
if err != nil {
return err
}
return nil
},
Run: func(cmd *cobra.Command, args []string) {
node, err := p2p.ParseNode(args[0])
if err != nil {
log.Error().Err(err).Msg("Unable to parse enode")
return
}
var (
hello *p2p.Hello
status *p2p.Status
start uint64 = inputQueryParams.StartBlock
amount uint64 = inputQueryParams.Amount
)
opts := p2p.DialOpts{
Port: inputQueryParams.Port,
Addr: inputQueryParams.Addr,
PrivateKey: inputQueryParams.privateKey,
}
conn, err := p2p.Dial(node, opts)
if err != nil {
log.Error().Err(err).Msg("Dial failed")
return
}
defer conn.Close()
if hello, status, err = conn.Peer(); err != nil {
log.Error().Err(err).Msg("Peer failed")
return
}
log.Info().Interface("hello", hello).Interface("status", status).Msg("Peering messages received")
log.Info().Uint64("start", start).Uint64("amount", amount).Msg("Requesting headers")
// Handshake completed, now proceed to query headers
if err = conn.QueryHeaders(start, amount); err != nil {
log.Error().Err(err).Msg("Failed to request header(s)")
return
}
headers, err := conn.ListenHeaders()
if err != nil {
log.Error().Err(err).Msg("Failed to listen for header(s)")
return
}
// Verify requested headers
if len(headers) != int(amount) {
log.Error().Uint64("want", amount).Int("have", len(headers)).Msg("Received less headers than requested")
return
}
var (
headerStart uint64 = headers[0].Number.Uint64()
headerEnd uint64 = headers[len(headers)-1].Number.Uint64()
end uint64 = start + amount - 1
)
if headerStart != start || headerEnd != end {
log.Error().Uint64("start", start).Uint64("end", end).Uint64("header start", headerStart).Uint64("header end", headerEnd).Msg("Received headers out of range")
return
}
print(headers)
},
}
// print simply prints necessary contents of headers assuming they're already verified
func print(headers eth.BlockHeadersRequest) {
for _, header := range headers {
log.Info().Uint64("number", header.Number.Uint64()).Str("hash", header.Hash().Hex()).Msg("Header")
}
}
func init() {
f := QueryCmd.Flags()
f.Uint64VarP(&inputQueryParams.StartBlock, "start-block", "s", 0, "block number to start querying from")
f.Uint64VarP(&inputQueryParams.Amount, "amount", "a", 1, "amount of blocks to query")
f.IntVarP(&inputQueryParams.Port, "port", "P", 30303, "port for discovery protocol")
f.IPVar(&inputQueryParams.Addr, "addr", net.ParseIP("127.0.0.1"), "address to bind discovery listener")
f.StringVarP(&inputQueryParams.KeyFile, "key-file", "k", "", "private key file (cannot be set with --key)")
f.StringVar(&inputQueryParams.PrivateKey, "key", "", "hex-encoded private key (cannot be set with --key-file)")
QueryCmd.MarkFlagsMutuallyExclusive("key-file", "key")
if err := QueryCmd.MarkFlagRequired("start-block"); err != nil {
log.Error().Err(err).Msg("Failed to mark start-block as required flag")
}
}