Skip to content

Commit eb0fec8

Browse files
authored
DVT-1231 Add ability to recover public key from bor block (#196)
* feat: implement ecrecover command to fetch public key * working version of ecrecover * clean up unused arguments * add logs to show what block was recovered * make gen-doc * typos and remove unused logic * add usage file * feat: implement standard input and file inputs * fix lint * unmarshal magic * lint * revert fork stuff
1 parent 5e20a71 commit eb0fec8

File tree

10 files changed

+303
-10
lines changed

10 files changed

+303
-10
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ Note: Do not modify this section! It is auto-generated by `cobra` using `make ge
4646

4747
- [polycli dumpblocks](doc/polycli_dumpblocks.md) - Export a range of blocks from a JSON-RPC endpoint.
4848

49+
- [polycli ecrecover](doc/polycli_ecrecover.md) - Recovers and returns the public key of the signature
50+
4951
- [polycli enr](doc/polycli_enr.md) - Convert between ENR and Enode format
5052

5153
- [polycli fork](doc/polycli_fork.md) - Take a forked block and walk up the chain to do analysis.

cmd/ecrecover/ecrecover.go

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package ecrecover
2+
3+
import (
4+
_ "embed"
5+
"encoding/json"
6+
"io"
7+
"math/big"
8+
"os"
9+
10+
ethcommon "github.com/ethereum/go-ethereum/common"
11+
"github.com/ethereum/go-ethereum/core/types"
12+
"github.com/ethereum/go-ethereum/ethclient"
13+
ethrpc "github.com/ethereum/go-ethereum/rpc"
14+
"github.com/maticnetwork/polygon-cli/util"
15+
"github.com/rs/zerolog/log"
16+
"github.com/spf13/cobra"
17+
)
18+
19+
var (
20+
//go:embed usage.md
21+
usage string
22+
23+
rpcUrl string
24+
blockNumber uint64
25+
filePath string
26+
)
27+
28+
var EcRecoverCmd = &cobra.Command{
29+
Use: "ecrecover",
30+
Short: "Recovers and returns the public key of the signature",
31+
Long: usage,
32+
Args: cobra.NoArgs,
33+
PreRunE: func(cmd *cobra.Command, args []string) error {
34+
return checkFlags()
35+
},
36+
Run: func(cmd *cobra.Command, args []string) {
37+
ctx := cmd.Context()
38+
39+
var block *types.Block
40+
var err error
41+
42+
if rpcUrl == "" {
43+
var blockJSON []byte
44+
if filePath != "" {
45+
blockJSON, err = os.ReadFile(filePath)
46+
if err != nil {
47+
log.Error().Err(err).Msg("Unable to read file")
48+
return
49+
}
50+
} else {
51+
blockJSON, err = io.ReadAll(os.Stdin)
52+
if err != nil {
53+
log.Error().Err(err).Msg("Unable to read stdin")
54+
return
55+
}
56+
}
57+
58+
var header types.Header
59+
if err = json.Unmarshal(blockJSON, &header); err != nil {
60+
log.Error().Err(err).Msg("Unable to unmarshal JSON")
61+
return
62+
}
63+
64+
block = types.NewBlockWithHeader(&header)
65+
blockNumber = header.Number.Uint64()
66+
} else {
67+
var rpc *ethrpc.Client
68+
rpc, err = ethrpc.DialContext(ctx, rpcUrl)
69+
if err != nil {
70+
log.Error().Err(err).Msg("Unable to dial rpc")
71+
return
72+
}
73+
74+
ec := ethclient.NewClient(rpc)
75+
76+
if blockNumber == 0 {
77+
blockNumber, err = ec.BlockNumber(ctx)
78+
if err != nil {
79+
log.Error().Err(err).Msg("Unable to retrieve latest block number")
80+
return
81+
}
82+
}
83+
84+
block, err = ec.BlockByNumber(ctx, big.NewInt(int64(blockNumber)))
85+
if err != nil {
86+
log.Error().Err(err).Msg("Unable to retrieve block")
87+
return
88+
}
89+
}
90+
91+
signerBytes, err := util.Ecrecover(block)
92+
if err != nil {
93+
log.Error().Err(err).Msg("Unable to recover signature")
94+
return
95+
}
96+
cmd.Printf("Recovering signer from block #%d\n", blockNumber)
97+
cmd.Println(ethcommon.BytesToAddress(signerBytes))
98+
},
99+
}
100+
101+
func init() {
102+
EcRecoverCmd.PersistentFlags().StringVarP(&rpcUrl, "rpc-url", "r", "", "The RPC endpoint url")
103+
EcRecoverCmd.PersistentFlags().Uint64VarP(&blockNumber, "block-number", "b", 0, "Block number to check the extra data for (default: latest)")
104+
EcRecoverCmd.PersistentFlags().StringVarP(&filePath, "file", "f", "", "Path to a file containing block information in JSON format")
105+
}
106+
107+
func checkFlags() (err error) {
108+
if rpcUrl != "" && util.ValidateUrl(rpcUrl) != nil {
109+
return
110+
}
111+
112+
return nil
113+
}

cmd/ecrecover/usage.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Recover public key from block
2+
3+
```bash
4+
polycli ecrecover -r https://polygon-mumbai-bor.publicnode.com -b 45200775
5+
> Recovering signer from block #45200775
6+
> 0x5082F249cDb2f2c1eE035E4f423c46EA2daB3ab1
7+
8+
polycli ecrecover -r https://polygon-rpc.com
9+
> Recovering signer from block #52888893
10+
> 0xeEDBa2484aAF940f37cd3CD21a5D7C4A7DAfbfC0
11+
12+
polycli ecrecover -f block-52888893.json
13+
> Recovering signer from block #52888893
14+
> 0xeEDBa2484aAF940f37cd3CD21a5D7C4A7DAfbfC0
15+
16+
cat block-52888893.json | go run main.go ecrecover
17+
> Recovering signer from block #52888893
18+
> 0xeEDBa2484aAF940f37cd3CD21a5D7C4A7DAfbfC0
19+
```
20+
21+
JSON Data passed in follows object definition [here](https://www.quicknode.com/docs/ethereum/eth_getBlockByNumber)

cmd/root.go

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/maticnetwork/polygon-cli/cmd/abi"
1616
"github.com/maticnetwork/polygon-cli/cmd/dbbench"
1717
"github.com/maticnetwork/polygon-cli/cmd/dumpblocks"
18+
"github.com/maticnetwork/polygon-cli/cmd/ecrecover"
1819
"github.com/maticnetwork/polygon-cli/cmd/enr"
1920
"github.com/maticnetwork/polygon-cli/cmd/fund"
2021
"github.com/maticnetwork/polygon-cli/cmd/hash"
@@ -107,6 +108,7 @@ func NewPolycliCommand() *cobra.Command {
107108
cmd.AddCommand(
108109
abi.ABICmd,
109110
dumpblocks.DumpblocksCmd,
111+
ecrecover.EcRecoverCmd,
110112
fork.ForkCmd,
111113
fund.FundCmd,
112114
hash.HashCmd,

doc/polycli.md

+2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ Polycli is a collection of tools that are meant to be useful while building, tes
4141

4242
- [polycli dumpblocks](polycli_dumpblocks.md) - Export a range of blocks from a JSON-RPC endpoint.
4343

44+
- [polycli ecrecover](polycli_ecrecover.md) - Recovers and returns the public key of the signature
45+
4446
- [polycli enr](polycli_enr.md) - Convert between ENR and Enode format
4547

4648
- [polycli fork](polycli_fork.md) - Take a forked block and walk up the chain to do analysis.

doc/polycli_ecrecover.md

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# `polycli ecrecover`
2+
3+
> Auto-generated documentation.
4+
5+
## Table of Contents
6+
7+
- [Description](#description)
8+
- [Usage](#usage)
9+
- [Flags](#flags)
10+
- [See Also](#see-also)
11+
12+
## Description
13+
14+
Recovers and returns the public key of the signature
15+
16+
```bash
17+
polycli ecrecover [flags]
18+
```
19+
20+
## Usage
21+
22+
Recover public key from block
23+
24+
```bash
25+
polycli ecrecover -r https://polygon-mumbai-bor.publicnode.com -b 45200775
26+
> Recovering signer from block #45200775
27+
> 0x5082F249cDb2f2c1eE035E4f423c46EA2daB3ab1
28+
29+
polycli ecrecover -r https://polygon-rpc.com
30+
> Recovering signer from block #52888893
31+
> 0xeEDBa2484aAF940f37cd3CD21a5D7C4A7DAfbfC0
32+
33+
polycli ecrecover -f block-52888893.json
34+
> Recovering signer from block #52888893
35+
> 0xeEDBa2484aAF940f37cd3CD21a5D7C4A7DAfbfC0
36+
37+
cat block-52888893.json | go run main.go ecrecover
38+
> Recovering signer from block #52888893
39+
> 0xeEDBa2484aAF940f37cd3CD21a5D7C4A7DAfbfC0
40+
```
41+
42+
JSON Data passed in follows object definition [here](https://www.quicknode.com/docs/ethereum/eth_getBlockByNumber)
43+
44+
## Flags
45+
46+
```bash
47+
-b, --block-number uint Block number to check the extra data for (default: latest)
48+
-f, --file string Path to a file containing block information in JSON format
49+
-h, --help help for ecrecover
50+
-r, --rpc-url string The RPC endpoint url
51+
```
52+
53+
The command also inherits flags from parent commands.
54+
55+
```bash
56+
--config string config file (default is $HOME/.polygon-cli.yaml)
57+
--pretty-logs Should logs be in pretty format or JSON (default true)
58+
-v, --verbosity int 0 - Silent
59+
100 Panic
60+
200 Fatal
61+
300 Error
62+
400 Warning
63+
500 Info
64+
600 Debug
65+
700 Trace (default 500)
66+
```
67+
68+
## See also
69+
70+
- [polycli](polycli.md) - A Swiss Army knife of blockchain tools.

go.mod

+17-10
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ go 1.21
44

55
require (
66
cloud.google.com/go/datastore v1.15.0
7-
github.com/btcsuite/btcutil v1.0.2
7+
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
88
github.com/cenkalti/backoff/v4 v4.2.1
99
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
1010
github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593
11-
github.com/ethereum/go-ethereum v1.13.8
11+
github.com/ethereum/go-ethereum v1.13.11
1212
github.com/gizak/termui/v3 v3.1.1-0.20231111080052-b3569a6cd52d
1313
github.com/google/gofuzz v1.2.0
1414
github.com/hashicorp/golang-lru v1.0.2
@@ -24,7 +24,7 @@ require (
2424
github.com/spf13/pflag v1.0.5
2525
github.com/spf13/viper v1.17.0
2626
github.com/stretchr/testify v1.8.4
27-
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
27+
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
2828
github.com/tyler-smith/go-bip32 v1.0.0
2929
github.com/tyler-smith/go-bip39 v1.1.0
3030
github.com/xeipuuv/gojsonschema v1.2.0
@@ -38,7 +38,13 @@ require (
3838

3939
require github.com/alecthomas/participle/v2 v2.1.1
4040

41-
require github.com/go-errors/errors v1.5.1 // indirect
41+
require (
42+
github.com/go-errors/errors v1.5.1 // indirect
43+
github.com/sethvargo/go-retry v0.2.4 // indirect
44+
github.com/umbracle/ethgo v0.1.4-0.20231006072852-6b068360fc97 // indirect
45+
github.com/umbracle/fastrlp v0.1.1-0.20230504065717-58a1b8a9929d // indirect
46+
github.com/valyala/fastjson v1.6.3 // indirect
47+
)
4248

4349
require (
4450
cloud.google.com/go v0.110.8 // indirect
@@ -67,7 +73,7 @@ require (
6773
github.com/ethereum/c-kzg-4844 v0.4.0 // indirect
6874
github.com/fsnotify/fsnotify v1.6.0 // indirect
6975
github.com/getsentry/sentry-go v0.18.0 // indirect
70-
github.com/go-ole/go-ole v1.2.6 // indirect
76+
github.com/go-ole/go-ole v1.3.0 // indirect
7177
github.com/gofrs/flock v0.8.1 // indirect
7278
github.com/gogo/protobuf v1.3.2 // indirect
7379
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@@ -78,21 +84,21 @@ require (
7884
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
7985
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
8086
github.com/gorilla/websocket v1.5.0 // indirect
81-
github.com/hashicorp/hcl v1.0.0 // indirect
87+
github.com/hashicorp/hcl v1.0.1-vault // indirect
8288
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
8389
github.com/holiman/uint256 v1.2.4 // indirect
8490
github.com/huin/goupnp v1.3.0 // indirect
8591
github.com/inconshreveable/mousetrap v1.1.0 // indirect
8692
github.com/ipfs/go-cid v0.4.1 // indirect
8793
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
88-
github.com/klauspost/compress v1.17.0 // indirect
94+
github.com/klauspost/compress v1.17.1 // indirect
8995
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
9096
github.com/kr/pretty v0.3.1 // indirect
9197
github.com/kr/text v0.2.0 // indirect
9298
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
9399
github.com/magiconair/properties v1.8.7 // indirect
94100
github.com/mattn/go-colorable v0.1.13 // indirect
95-
github.com/mattn/go-isatty v0.0.19 // indirect
101+
github.com/mattn/go-isatty v0.0.20 // indirect
96102
github.com/mattn/go-runewidth v0.0.15 // indirect
97103
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
98104
github.com/minio/sha256-simd v1.0.1 // indirect
@@ -113,8 +119,8 @@ require (
113119
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
114120
github.com/pkg/errors v0.9.1 // indirect
115121
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
116-
github.com/prometheus/client_golang v1.15.1 // indirect
117-
github.com/prometheus/procfs v0.9.0 // indirect
122+
github.com/prometheus/client_golang v1.17.0 // indirect
123+
github.com/prometheus/procfs v0.11.1 // indirect
118124
github.com/rivo/uniseg v0.4.4 // indirect
119125
github.com/rogpeppe/go-internal v1.10.0 // indirect
120126
github.com/sagikazarmark/locafero v0.3.0 // indirect
@@ -158,6 +164,7 @@ require (
158164

159165
require (
160166
cloud.google.com/go/iam v1.1.3 // indirect
167+
github.com/0xPolygon/polygon-edge v1.3.2
161168
github.com/Microsoft/go-winio v0.6.1 // indirect
162169
github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect
163170
github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect

0 commit comments

Comments
 (0)