forked from cerc-io/plugeth
Merge remote-tracking branch 'origin/master' into feature/blockTracer
Merging to prevent circle-ci test failure before pull request is made.
This commit is contained in:
@@ -36,17 +36,19 @@ import (
|
||||
)
|
||||
|
||||
type result struct {
|
||||
Error error
|
||||
Address common.Address
|
||||
Hash common.Hash
|
||||
Error error
|
||||
Address common.Address
|
||||
Hash common.Hash
|
||||
IntrinsicGas uint64
|
||||
}
|
||||
|
||||
// MarshalJSON marshals as JSON with a hash.
|
||||
func (r *result) MarshalJSON() ([]byte, error) {
|
||||
type xx struct {
|
||||
Error string `json:"error,omitempty"`
|
||||
Address *common.Address `json:"address,omitempty"`
|
||||
Hash *common.Hash `json:"hash,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
Address *common.Address `json:"address,omitempty"`
|
||||
Hash *common.Hash `json:"hash,omitempty"`
|
||||
IntrinsicGas uint64 `json:"intrinsicGas,omitempty"`
|
||||
}
|
||||
var out xx
|
||||
if r.Error != nil {
|
||||
@@ -58,6 +60,7 @@ func (r *result) MarshalJSON() ([]byte, error) {
|
||||
if r.Hash != (common.Hash{}) {
|
||||
out.Hash = &r.Hash
|
||||
}
|
||||
out.IntrinsicGas = r.IntrinsicGas
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
@@ -132,12 +135,36 @@ func Transaction(ctx *cli.Context) error {
|
||||
} else {
|
||||
r.Address = sender
|
||||
}
|
||||
|
||||
// Check intrinsic gas
|
||||
if gas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil,
|
||||
chainConfig.IsHomestead(new(big.Int)), chainConfig.IsIstanbul(new(big.Int))); err != nil {
|
||||
r.Error = err
|
||||
} else if tx.Gas() < gas {
|
||||
r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), gas)
|
||||
results = append(results, r)
|
||||
continue
|
||||
} else {
|
||||
r.IntrinsicGas = gas
|
||||
if tx.Gas() < gas {
|
||||
r.Error = fmt.Errorf("%w: have %d, want %d", core.ErrIntrinsicGas, tx.Gas(), gas)
|
||||
results = append(results, r)
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Validate <256bit fields
|
||||
switch {
|
||||
case tx.Value().BitLen() > 256:
|
||||
r.Error = errors.New("value exceeds 256 bits")
|
||||
case tx.GasPrice().BitLen() > 256:
|
||||
r.Error = errors.New("gasPrice exceeds 256 bits")
|
||||
case tx.GasTipCap().BitLen() > 256:
|
||||
r.Error = errors.New("maxPriorityFeePerGas exceeds 256 bits")
|
||||
case tx.GasFeeCap().BitLen() > 256:
|
||||
r.Error = errors.New("maxFeePerGas exceeds 256 bits")
|
||||
case tx.GasFeeCap().Cmp(tx.GasTipCap()) < 0:
|
||||
r.Error = errors.New("maxFeePerGas < maxPriorityFeePerGas")
|
||||
case new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas())).BitLen() > 256:
|
||||
r.Error = errors.New("gas * gasPrice exceeds 256 bits")
|
||||
case new(big.Int).Mul(tx.GasFeeCap(), new(big.Int).SetUint64(tx.Gas())).BitLen() > 256:
|
||||
r.Error = errors.New("gas * maxFeePerGas exceeds 256 bits")
|
||||
}
|
||||
results = append(results, r)
|
||||
}
|
||||
|
||||
@@ -257,6 +257,14 @@ func TestT9n(t *testing.T) {
|
||||
},
|
||||
expOut: "exp.json",
|
||||
},
|
||||
{ // Transactions with value exceeding 256 bits
|
||||
base: "./testdata/17",
|
||||
input: t9nInput{
|
||||
inTxs: "signed_txs.rlp",
|
||||
stFork: "London",
|
||||
},
|
||||
expOut: "exp.json",
|
||||
},
|
||||
} {
|
||||
|
||||
args := []string{"t9n"}
|
||||
|
||||
Vendored
+4
-2
@@ -1,10 +1,12 @@
|
||||
[
|
||||
{
|
||||
"address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
|
||||
"hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476"
|
||||
"hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||
"intrinsicGas": 21000
|
||||
},
|
||||
{
|
||||
"address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
|
||||
"hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a"
|
||||
"hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||
"intrinsicGas": 21000
|
||||
}
|
||||
]
|
||||
|
||||
Vendored
+4
-2
@@ -1,11 +1,13 @@
|
||||
[
|
||||
{
|
||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"hash": "0x7cc3d1a8540a44736750f03bb4d85c0113be4b3472a71bf82241a3b261b479e6"
|
||||
"hash": "0x7cc3d1a8540a44736750f03bb4d85c0113be4b3472a71bf82241a3b261b479e6",
|
||||
"intrinsicGas": 21000
|
||||
},
|
||||
{
|
||||
"error": "intrinsic gas too low: have 82, want 21000",
|
||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"hash": "0x3b2d2609e4361562edb9169314f4c05afc6dbf5d706bf9dda5abe242ab76a22b"
|
||||
"hash": "0x3b2d2609e4361562edb9169314f4c05afc6dbf5d706bf9dda5abe242ab76a22b",
|
||||
"intrinsicGas": 21000
|
||||
}
|
||||
]
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
[
|
||||
{
|
||||
"error": "value exceeds 256 bits",
|
||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"hash": "0xfbd91685dcbf8172f0e8c53e2ddbb4d26707840da6b51a74371f62a33868fd82",
|
||||
"intrinsicGas": 21000
|
||||
},
|
||||
{
|
||||
"error": "gasPrice exceeds 256 bits",
|
||||
"address": "0x1b57ccef1fe5fb73f1e64530fb4ebd9cf1655964",
|
||||
"hash": "0x45dc05035cada83748e4c1fe617220106b331eca054f44c2304d5654a9fb29d5",
|
||||
"intrinsicGas": 21000
|
||||
},
|
||||
{
|
||||
"error": "invalid transaction v, r, s values",
|
||||
"hash": "0xf06691c2a803ab7f3c81d06a0c0a896f80f311105c599fc59a9fdbc669356d35"
|
||||
},
|
||||
{
|
||||
"error": "invalid transaction v, r, s values",
|
||||
"hash": "0x84703b697ad5b0db25e4f1f98fb6b1adce85b9edb2232eeba9cedd8c6601694b"
|
||||
}
|
||||
]
|
||||
Vendored
+46
@@ -0,0 +1,46 @@
|
||||
[
|
||||
[
|
||||
"",
|
||||
"d",
|
||||
5208,
|
||||
d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0,
|
||||
010000000000000000000000000000000000000000000000000000000000000001,
|
||||
"",
|
||||
1b,
|
||||
c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549d,
|
||||
6180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28,
|
||||
],
|
||||
[
|
||||
"",
|
||||
010000000000000000000000000000000000000000000000000000000000000001,
|
||||
5208,
|
||||
d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0,
|
||||
11,
|
||||
"",
|
||||
1b,
|
||||
c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549d,
|
||||
6180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28,
|
||||
],
|
||||
[
|
||||
"",
|
||||
11,
|
||||
5208,
|
||||
d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0,
|
||||
11,
|
||||
"",
|
||||
1b,
|
||||
c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549daa,
|
||||
6180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28,
|
||||
],
|
||||
[
|
||||
"",
|
||||
11,
|
||||
5208,
|
||||
d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0,
|
||||
11,
|
||||
"",
|
||||
1b,
|
||||
c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549d,
|
||||
6180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28bb,
|
||||
],
|
||||
]
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
"0xf901c8f880806482520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a1010000000000000000000000000000000000000000000000000000000000000001801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28f88080a101000000000000000000000000000000000000000000000000000000000000000182520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d011801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28f860801182520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d011801ba1c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549daaa06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28f860801182520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d011801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da16180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28bb"
|
||||
+16
-5
@@ -17,6 +17,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -335,14 +336,15 @@ func dbGet(ctx *cli.Context) error {
|
||||
db := utils.MakeChainDatabase(ctx, stack, true)
|
||||
defer db.Close()
|
||||
|
||||
key, err := hexutil.Decode(ctx.Args().Get(0))
|
||||
key, err := parseHexOrString(ctx.Args().Get(0))
|
||||
if err != nil {
|
||||
log.Info("Could not decode the key", "error", err)
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := db.Get(key)
|
||||
if err != nil {
|
||||
log.Info("Get operation failed", "error", err)
|
||||
log.Info("Get operation failed", "key", fmt.Sprintf("0x%#x", key), "error", err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("key %#x: %#x\n", key, data)
|
||||
@@ -360,7 +362,7 @@ func dbDelete(ctx *cli.Context) error {
|
||||
db := utils.MakeChainDatabase(ctx, stack, false)
|
||||
defer db.Close()
|
||||
|
||||
key, err := hexutil.Decode(ctx.Args().Get(0))
|
||||
key, err := parseHexOrString(ctx.Args().Get(0))
|
||||
if err != nil {
|
||||
log.Info("Could not decode the key", "error", err)
|
||||
return err
|
||||
@@ -370,7 +372,7 @@ func dbDelete(ctx *cli.Context) error {
|
||||
fmt.Printf("Previous value: %#x\n", data)
|
||||
}
|
||||
if err = db.Delete(key); err != nil {
|
||||
log.Info("Delete operation returned an error", "error", err)
|
||||
log.Info("Delete operation returned an error", "key", fmt.Sprintf("0x%#x", key), "error", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -393,7 +395,7 @@ func dbPut(ctx *cli.Context) error {
|
||||
data []byte
|
||||
err error
|
||||
)
|
||||
key, err = hexutil.Decode(ctx.Args().Get(0))
|
||||
key, err = parseHexOrString(ctx.Args().Get(0))
|
||||
if err != nil {
|
||||
log.Info("Could not decode the key", "error", err)
|
||||
return err
|
||||
@@ -499,3 +501,12 @@ func freezerInspect(ctx *cli.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseHexOrString tries to hexdecode b, but if the prefix is missing, it instead just returns the raw bytes
|
||||
func parseHexOrString(str string) ([]byte, error) {
|
||||
b, err := hexutil.Decode(str)
|
||||
if errors.Is(err, hexutil.ErrMissingPrefix) {
|
||||
return []byte(str), nil
|
||||
}
|
||||
return b, err
|
||||
}
|
||||
|
||||
+33
-88
@@ -17,7 +17,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -32,8 +31,10 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/console/prompt"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/peterh/liner"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
@@ -76,17 +77,27 @@ type wizard struct {
|
||||
servers map[string]*sshClient // SSH connections to servers to administer
|
||||
services map[string][]string // Ethereum services known to be running on servers
|
||||
|
||||
in *bufio.Reader // Wrapper around stdin to allow reading user input
|
||||
lock sync.Mutex // Lock to protect configs during concurrent service discovery
|
||||
lock sync.Mutex // Lock to protect configs during concurrent service discovery
|
||||
}
|
||||
|
||||
// prompts the user for input with the given prompt string. Returns when a value is entered.
|
||||
// Causes the wizard to exit if ctrl-d is pressed
|
||||
func promptInput(p string) string {
|
||||
for {
|
||||
text, err := prompt.Stdin.PromptInput(p)
|
||||
if err != nil {
|
||||
if err != liner.ErrPromptAborted {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
} else {
|
||||
return text
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// read reads a single line from stdin, trimming if from spaces.
|
||||
func (w *wizard) read() string {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
return strings.TrimSpace(text)
|
||||
}
|
||||
|
||||
@@ -94,11 +105,7 @@ func (w *wizard) read() string {
|
||||
// non-emptyness.
|
||||
func (w *wizard) readString() string {
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
if text = strings.TrimSpace(text); text != "" {
|
||||
return text
|
||||
}
|
||||
@@ -108,11 +115,7 @@ func (w *wizard) readString() string {
|
||||
// readDefaultString reads a single line from stdin, trimming if from spaces. If
|
||||
// an empty line is entered, the default value is returned.
|
||||
func (w *wizard) readDefaultString(def string) string {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
if text = strings.TrimSpace(text); text != "" {
|
||||
return text
|
||||
}
|
||||
@@ -124,11 +127,7 @@ func (w *wizard) readDefaultString(def string) string {
|
||||
// value is returned.
|
||||
func (w *wizard) readDefaultYesNo(def bool) bool {
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
if text = strings.ToLower(strings.TrimSpace(text)); text == "" {
|
||||
return def
|
||||
}
|
||||
@@ -146,11 +145,7 @@ func (w *wizard) readDefaultYesNo(def bool) bool {
|
||||
// interpret it as a URL (http, https or file).
|
||||
func (w *wizard) readURL() *url.URL {
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
uri, err := url.Parse(strings.TrimSpace(text))
|
||||
if err != nil {
|
||||
log.Error("Invalid input, expected URL", "err", err)
|
||||
@@ -164,11 +159,7 @@ func (w *wizard) readURL() *url.URL {
|
||||
// to parse into an integer.
|
||||
func (w *wizard) readInt() int {
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
if text = strings.TrimSpace(text); text == "" {
|
||||
continue
|
||||
}
|
||||
@@ -186,11 +177,7 @@ func (w *wizard) readInt() int {
|
||||
// returned.
|
||||
func (w *wizard) readDefaultInt(def int) int {
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
if text = strings.TrimSpace(text); text == "" {
|
||||
return def
|
||||
}
|
||||
@@ -208,11 +195,7 @@ func (w *wizard) readDefaultInt(def int) int {
|
||||
// default value is returned.
|
||||
func (w *wizard) readDefaultBigInt(def *big.Int) *big.Int {
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
if text = strings.TrimSpace(text); text == "" {
|
||||
return def
|
||||
}
|
||||
@@ -225,38 +208,11 @@ func (w *wizard) readDefaultBigInt(def *big.Int) *big.Int {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// readFloat reads a single line from stdin, trimming if from spaces, enforcing it
|
||||
// to parse into a float.
|
||||
func (w *wizard) readFloat() float64 {
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
if text = strings.TrimSpace(text); text == "" {
|
||||
continue
|
||||
}
|
||||
val, err := strconv.ParseFloat(strings.TrimSpace(text), 64)
|
||||
if err != nil {
|
||||
log.Error("Invalid input, expected float", "err", err)
|
||||
continue
|
||||
}
|
||||
return val
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// readDefaultFloat reads a single line from stdin, trimming if from spaces, enforcing
|
||||
// it to parse into a float. If an empty line is entered, the default value is returned.
|
||||
func (w *wizard) readDefaultFloat(def float64) float64 {
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
if text = strings.TrimSpace(text); text == "" {
|
||||
return def
|
||||
}
|
||||
@@ -285,12 +241,7 @@ func (w *wizard) readPassword() string {
|
||||
// it to an Ethereum address.
|
||||
func (w *wizard) readAddress() *common.Address {
|
||||
for {
|
||||
// Read the address from the user
|
||||
fmt.Printf("> 0x")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> 0x")
|
||||
if text = strings.TrimSpace(text); text == "" {
|
||||
return nil
|
||||
}
|
||||
@@ -311,11 +262,7 @@ func (w *wizard) readAddress() *common.Address {
|
||||
func (w *wizard) readDefaultAddress(def common.Address) common.Address {
|
||||
for {
|
||||
// Read the address from the user
|
||||
fmt.Printf("> 0x")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> 0x")
|
||||
if text = strings.TrimSpace(text); text == "" {
|
||||
return def
|
||||
}
|
||||
@@ -334,8 +281,9 @@ func (w *wizard) readJSON() string {
|
||||
var blob json.RawMessage
|
||||
|
||||
for {
|
||||
fmt.Printf("> ")
|
||||
if err := json.NewDecoder(w.in).Decode(&blob); err != nil {
|
||||
text := promptInput("> ")
|
||||
reader := strings.NewReader(text)
|
||||
if err := json.NewDecoder(reader).Decode(&blob); err != nil {
|
||||
log.Error("Invalid JSON, please try again", "err", err)
|
||||
continue
|
||||
}
|
||||
@@ -351,10 +299,7 @@ func (w *wizard) readIPAddress() string {
|
||||
for {
|
||||
// Read the IP address from the user
|
||||
fmt.Printf("> ")
|
||||
text, err := w.in.ReadString('\n')
|
||||
if err != nil {
|
||||
log.Crit("Failed to read user input", "err", err)
|
||||
}
|
||||
text := promptInput("> ")
|
||||
if text = strings.TrimSpace(text); text == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -38,7 +37,6 @@ func makeWizard(network string) *wizard {
|
||||
},
|
||||
servers: make(map[string]*sshClient),
|
||||
services: make(map[string][]string),
|
||||
in: bufio.NewReader(os.Stdin),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+86
-23
@@ -18,7 +18,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"container/list"
|
||||
"encoding/hex"
|
||||
"flag"
|
||||
"fmt"
|
||||
@@ -26,18 +28,20 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
var (
|
||||
hexMode = flag.String("hex", "", "dump given hex data")
|
||||
noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably")
|
||||
single = flag.Bool("single", false, "print only the first element, discard the rest")
|
||||
hexMode = flag.String("hex", "", "dump given hex data")
|
||||
reverseMode = flag.Bool("reverse", false, "convert ASCII to rlp")
|
||||
noASCII = flag.Bool("noascii", false, "don't print ASCII strings readably")
|
||||
single = flag.Bool("single", false, "print only the first element, discard the rest")
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex <data>] [filename]")
|
||||
fmt.Fprintln(os.Stderr, "Usage:", os.Args[0], "[-noascii] [-hex <data>][-reverse] [filename]")
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintln(os.Stderr, `
|
||||
Dumps RLP data from the given file in readable form.
|
||||
@@ -73,23 +77,40 @@ func main() {
|
||||
flag.Usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
s := rlp.NewStream(r, 0)
|
||||
for {
|
||||
if err := dump(s, 0); err != nil {
|
||||
if err != io.EOF {
|
||||
die(err)
|
||||
}
|
||||
break
|
||||
out := os.Stdout
|
||||
if *reverseMode {
|
||||
data, err := textToRlp(r)
|
||||
if err != nil {
|
||||
die(err)
|
||||
}
|
||||
fmt.Println()
|
||||
if *single {
|
||||
break
|
||||
fmt.Printf("0x%x\n", data)
|
||||
return
|
||||
} else {
|
||||
err := rlpToText(r, out)
|
||||
if err != nil {
|
||||
die(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func dump(s *rlp.Stream, depth int) error {
|
||||
func rlpToText(r io.Reader, out io.Writer) error {
|
||||
s := rlp.NewStream(r, 0)
|
||||
for {
|
||||
if err := dump(s, 0, out); err != nil {
|
||||
if err != io.EOF {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
fmt.Fprintln(out)
|
||||
if *single {
|
||||
break
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func dump(s *rlp.Stream, depth int, out io.Writer) error {
|
||||
kind, size, err := s.Kind()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -101,28 +122,28 @@ func dump(s *rlp.Stream, depth int) error {
|
||||
return err
|
||||
}
|
||||
if len(str) == 0 || !*noASCII && isASCII(str) {
|
||||
fmt.Printf("%s%q", ws(depth), str)
|
||||
fmt.Fprintf(out, "%s%q", ws(depth), str)
|
||||
} else {
|
||||
fmt.Printf("%s%x", ws(depth), str)
|
||||
fmt.Fprintf(out, "%s%x", ws(depth), str)
|
||||
}
|
||||
case rlp.List:
|
||||
s.List()
|
||||
defer s.ListEnd()
|
||||
if size == 0 {
|
||||
fmt.Print(ws(depth) + "[]")
|
||||
fmt.Fprintf(out, ws(depth)+"[]")
|
||||
} else {
|
||||
fmt.Println(ws(depth) + "[")
|
||||
fmt.Fprintln(out, ws(depth)+"[")
|
||||
for i := 0; ; i++ {
|
||||
if i > 0 {
|
||||
fmt.Print(",\n")
|
||||
fmt.Fprint(out, ",\n")
|
||||
}
|
||||
if err := dump(s, depth+1); err == rlp.EOL {
|
||||
if err := dump(s, depth+1, out); err == rlp.EOL {
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Print(ws(depth) + "]")
|
||||
fmt.Fprint(out, ws(depth)+"]")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -145,3 +166,45 @@ func die(args ...interface{}) {
|
||||
fmt.Fprintln(os.Stderr, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// textToRlp converts text into RLP (best effort).
|
||||
func textToRlp(r io.Reader) ([]byte, error) {
|
||||
// We're expecting the input to be well-formed, meaning that
|
||||
// - each element is on a separate line
|
||||
// - each line is either an (element OR a list start/end) + comma
|
||||
// - an element is either hex-encoded bytes OR a quoted string
|
||||
var (
|
||||
scanner = bufio.NewScanner(r)
|
||||
obj []interface{}
|
||||
stack = list.New()
|
||||
)
|
||||
for scanner.Scan() {
|
||||
t := strings.TrimSpace(scanner.Text())
|
||||
if len(t) == 0 {
|
||||
continue
|
||||
}
|
||||
switch t {
|
||||
case "[": // list start
|
||||
stack.PushFront(obj)
|
||||
obj = make([]interface{}, 0)
|
||||
case "]", "],": // list end
|
||||
parent := stack.Remove(stack.Front()).([]interface{})
|
||||
obj = append(parent, obj)
|
||||
case "[],": // empty list
|
||||
obj = append(obj, make([]interface{}, 0))
|
||||
default: // element
|
||||
data := []byte(t)[:len(t)-1] // cut off comma
|
||||
if data[0] == '"' { // ascii string
|
||||
data = []byte(t)[1 : len(data)-1]
|
||||
} else { // hex data
|
||||
data = common.FromHex(string(data))
|
||||
}
|
||||
obj = append(obj, data)
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data, err := rlp.EncodeToBytes(obj[0])
|
||||
return data, err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
func TestRoundtrip(t *testing.T) {
|
||||
for i, want := range []string{
|
||||
"0xf880806482520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a1010000000000000000000000000000000000000000000000000000000000000001801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28",
|
||||
"0xd5c0d3cb84746573742a2a808213378667617a6f6e6b",
|
||||
"0xc780c0c1c0825208",
|
||||
} {
|
||||
var out strings.Builder
|
||||
err := rlpToText(bytes.NewReader(common.FromHex(want)), &out)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
text := out.String()
|
||||
rlpBytes, err := textToRlp(strings.NewReader(text))
|
||||
if err != nil {
|
||||
t.Errorf("test %d: error %v", i, err)
|
||||
continue
|
||||
}
|
||||
have := fmt.Sprintf("0x%x", rlpBytes)
|
||||
if have != want {
|
||||
t.Errorf("test %d: have\n%v\nwant:\n%v\n", i, have, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTextToRlp(t *testing.T) {
|
||||
type tc struct {
|
||||
text string
|
||||
want string
|
||||
}
|
||||
cases := []tc{
|
||||
{
|
||||
text: `[
|
||||
"",
|
||||
[],
|
||||
[
|
||||
[],
|
||||
],
|
||||
5208,
|
||||
]`,
|
||||
want: "0xc780c0c1c0825208",
|
||||
},
|
||||
}
|
||||
for i, tc := range cases {
|
||||
have, err := textToRlp(strings.NewReader(tc.text))
|
||||
if err != nil {
|
||||
t.Errorf("test %d: error %v", i, err)
|
||||
continue
|
||||
}
|
||||
if hexutil.Encode(have) != tc.want {
|
||||
t.Errorf("test %d:\nhave %v\nwant %v", i, hexutil.Encode(have), tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -686,7 +686,7 @@ var (
|
||||
}
|
||||
GpoMaxGasPriceFlag = cli.Int64Flag{
|
||||
Name: "gpo.maxprice",
|
||||
Usage: "Maximum gas price will be recommended by gpo",
|
||||
Usage: "Maximum transaction priority fee (or gasprice before London fork) to be recommended by gpo",
|
||||
Value: ethconfig.Defaults.GPO.MaxPrice.Int64(),
|
||||
}
|
||||
GpoIgnoreGasPriceFlag = cli.Int64Flag{
|
||||
|
||||
Reference in New Issue
Block a user