mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
clef: bundle 4byte db into clef, fix #19048
This commit is contained in:
parent
74acde4b08
commit
c36b7a3056
8 changed files with 428 additions and 21 deletions
File diff suppressed because one or more lines are too long
273
cmd/clef/bindata.go
Normal file
273
cmd/clef/bindata.go
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -104,11 +104,6 @@ var (
|
||||||
Name: "signersecret",
|
Name: "signersecret",
|
||||||
Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash",
|
Usage: "A file containing the (encrypted) master seed to encrypt Clef data, e.g. keystore credentials and ruleset hash",
|
||||||
}
|
}
|
||||||
dBFlag = cli.StringFlag{
|
|
||||||
Name: "4bytedb",
|
|
||||||
Usage: "File containing 4byte-identifiers",
|
|
||||||
Value: "./4byte.json",
|
|
||||||
}
|
|
||||||
customDBFlag = cli.StringFlag{
|
customDBFlag = cli.StringFlag{
|
||||||
Name: "4bytedb-custom",
|
Name: "4bytedb-custom",
|
||||||
Usage: "File used for writing new 4byte-identifiers submitted via API",
|
Usage: "File used for writing new 4byte-identifiers submitted via API",
|
||||||
|
|
@ -206,7 +201,6 @@ func init() {
|
||||||
utils.RPCEnabledFlag,
|
utils.RPCEnabledFlag,
|
||||||
rpcPortFlag,
|
rpcPortFlag,
|
||||||
signerSecretFlag,
|
signerSecretFlag,
|
||||||
dBFlag,
|
|
||||||
customDBFlag,
|
customDBFlag,
|
||||||
auditLogFlag,
|
auditLogFlag,
|
||||||
ruleFlag,
|
ruleFlag,
|
||||||
|
|
@ -365,13 +359,17 @@ func signer(c *cli.Context) error {
|
||||||
log.Info("Using CLI as UI-channel")
|
log.Info("Using CLI as UI-channel")
|
||||||
ui = core.NewCommandlineUI()
|
ui = core.NewCommandlineUI()
|
||||||
}
|
}
|
||||||
fourByteDb := c.GlobalString(dBFlag.Name)
|
// 4bytedb data
|
||||||
fourByteLocal := c.GlobalString(customDBFlag.Name)
|
fourByteLocal := c.GlobalString(customDBFlag.Name)
|
||||||
db, err := core.NewAbiDBFromFiles(fourByteDb, fourByteLocal)
|
data, err := Asset("resources/4byte.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf(err.Error())
|
utils.Fatalf(err.Error())
|
||||||
}
|
}
|
||||||
log.Info("Loaded 4byte db", "signatures", db.Size(), "file", fourByteDb, "local", fourByteLocal)
|
db, err := core.NewAbiDBFromFiles(data, fourByteLocal)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf(err.Error())
|
||||||
|
}
|
||||||
|
log.Info("Loaded 4byte db", "signatures", db.Size(), "local", fourByteLocal)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
api core.ExternalAPI
|
api core.ExternalAPI
|
||||||
|
|
|
||||||
1
cmd/clef/resources/4byte.json
Normal file
1
cmd/clef/resources/4byte.json
Normal file
File diff suppressed because one or more lines are too long
138
cmd/internal/abidbbuilder/abidbbuilder.go
Normal file
138
cmd/internal/abidbbuilder/abidbbuilder.go
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
// Copyright 2019 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
inDir = flag.String("i", "", "input directory to read")
|
||||||
|
outFile = flag.String("o", "", "file to write to (overwrites if exists)")
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flag.Usage = func() {
|
||||||
|
fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "-i directory -o outputfile")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
fmt.Fprintln(os.Stderr, `
|
||||||
|
This is a little helper-utility to collect the data from
|
||||||
|
https://github.com/ethereum-lists/4bytes and massage it into a
|
||||||
|
clef-digestable format.
|
||||||
|
|
||||||
|
It parses the signatures from the given directory, and writes
|
||||||
|
them to the given outputfile as a json struct.
|
||||||
|
|
||||||
|
Afterwards, you can do
|
||||||
|
|
||||||
|
[cmd/clef]$ go-bindata resources
|
||||||
|
|
||||||
|
To generatee the bindata.go asset file.
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
in := *inDir
|
||||||
|
out := *outFile
|
||||||
|
if in == "" {
|
||||||
|
fmt.Fprintf(os.Stderr, "input directory not given\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if out == "" {
|
||||||
|
fmt.Fprintf(os.Stderr, "output file not given\n")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
data, err := readFiles(in)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "error reading data: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
err = dumpData(data, out)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "error writing data: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func dumpData(db map[string]string, outfile string) error {
|
||||||
|
data, err := json.Marshal(db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("data size %d kB\n", len(data)/1000)
|
||||||
|
return ioutil.WriteFile(outfile, data, 0644)
|
||||||
|
|
||||||
|
}
|
||||||
|
func readFiles(dir string) (map[string]string, error) {
|
||||||
|
f, err := os.Open(dir)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
files, err := f.Readdir(-1)
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
db := make(map[string]string)
|
||||||
|
for _, file := range files {
|
||||||
|
// Only bother with signature files
|
||||||
|
sig, err := hex.DecodeString(file.Name())
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(sig) != 4 {
|
||||||
|
fmt.Printf("Invalid sig, wrong length: %x", sig)
|
||||||
|
}
|
||||||
|
dat, err := ioutil.ReadFile(fmt.Sprintf("%s/%s", dir, file.Name()))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("err reading file: %v\n", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
selectors := strings.Split(string(dat), ";")
|
||||||
|
if len(selectors) > 1 {
|
||||||
|
fmt.Printf("sig `%s`\n", sig)
|
||||||
|
for _, selector := range selectors {
|
||||||
|
fmt.Printf(" - %v\n", selector)
|
||||||
|
}
|
||||||
|
fmt.Println(" -- ignoring this signature\n")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
selector := strings.TrimSpace(selectors[0])
|
||||||
|
// We do a basic sanity check here, not fully verifying the correctness of
|
||||||
|
// arguments, e.g the parameter types. We assume that the 4byte db comes
|
||||||
|
// from a somewhat trusted source
|
||||||
|
want := crypto.Keccak256([]byte(selector))[:4]
|
||||||
|
if !bytes.Equal(sig, want) {
|
||||||
|
fmt.Printf("Erroneous selector: %s, have %x want %x", selector, sig, want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
db[fmt.Sprintf("%x", sig)] = selector
|
||||||
|
}
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
@ -18,6 +18,7 @@ package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
@ -183,17 +184,13 @@ func NewAbiDBFromFile(path string) (*AbiDb, error) {
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAbiDBFromFiles loads both the standard signature database and a custom database. The latter will be used
|
// NewAbiDBFromFiles loads both the standard signature database (resource file)and a custom database.
|
||||||
// to write new values into if they are submitted via the API
|
// The latter will be used to write new values into if they are submitted via the API
|
||||||
func NewAbiDBFromFiles(standard, custom string) (*AbiDb, error) {
|
func NewAbiDBFromFiles(raw []byte, custom string) (*AbiDb, error) {
|
||||||
|
|
||||||
db := &AbiDb{make(map[string]string), make(map[string]string), custom}
|
db := &AbiDb{make(map[string]string), make(map[string]string), custom}
|
||||||
db.customdbPath = custom
|
db.customdbPath = custom
|
||||||
|
|
||||||
raw, err := ioutil.ReadFile(standard)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(raw, &db.db); err != nil {
|
if err := json.Unmarshal(raw, &db.db); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +204,6 @@ func NewAbiDBFromFiles(standard, custom string) (*AbiDb, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,7 +213,7 @@ func (db *AbiDb) LookupMethodSelector(id []byte) (string, error) {
|
||||||
if len(id) < 4 {
|
if len(id) < 4 {
|
||||||
return "", fmt.Errorf("Expected 4-byte id, got %d", len(id))
|
return "", fmt.Errorf("Expected 4-byte id, got %d", len(id))
|
||||||
}
|
}
|
||||||
sig := common.ToHex(id[:4])
|
sig := hex.EncodeToString(id[:4])
|
||||||
if key, exists := db.db[sig]; exists {
|
if key, exists := db.db[sig]; exists {
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
|
@ -226,6 +222,7 @@ func (db *AbiDb) LookupMethodSelector(id []byte) (string, error) {
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("Signature %v not found", sig)
|
return "", fmt.Errorf("Signature %v not found", sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *AbiDb) Size() int {
|
func (db *AbiDb) Size() int {
|
||||||
return len(db.db)
|
return len(db.db)
|
||||||
}
|
}
|
||||||
|
|
@ -255,6 +252,6 @@ func (db *AbiDb) AddSignature(selector string, data []byte) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
sig := common.ToHex(data[:4])
|
sig := hex.EncodeToString(data[:4])
|
||||||
return db.saveCustomAbi(selector, sig)
|
return db.saveCustomAbi(selector, sig)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ func TestCustomABI(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
filename := fmt.Sprintf("%s/4byte_custom.json", d)
|
filename := fmt.Sprintf("%s/4byte_custom.json", d)
|
||||||
abidb, err := NewAbiDBFromFiles("../../cmd/clef/4byte.json", filename)
|
abidb, err := NewAbiDBFromFiles([]byte(""), filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ type Validator struct {
|
||||||
func NewValidator(db *AbiDb) *Validator {
|
func NewValidator(db *AbiDb) *Validator {
|
||||||
return &Validator{db}
|
return &Validator{db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSelector(selector string, data []byte) (*decodedCallData, error) {
|
func testSelector(selector string, data []byte) (*decodedCallData, error) {
|
||||||
if selector == "" {
|
if selector == "" {
|
||||||
return nil, fmt.Errorf("selector not found")
|
return nil, fmt.Errorf("selector not found")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue