553bafc127
This change fixes a problem with our non-core binaries: evm, clef, bootnode. First of all, they failed to convert from legacy loglevels 1 to 5, to the new slog loglevels -4 to 4. Secondly, the logging was actually setup in the init phase, and then overridden in the main. This is not needed for evm, since it used the same flag name as the main geth verbosity. Better to let the flags/internal handle the logging init.
178 lines
5.6 KiB
Go
178 lines
5.6 KiB
Go
// Copyright 2021 The go-ethereum Authors
|
|
// This file is part of go-ethereum.
|
|
//
|
|
// go-ethereum is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// go-ethereum 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 General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package t8ntool
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/ethereum/go-ethereum/core"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/params"
|
|
"github.com/ethereum/go-ethereum/rlp"
|
|
"github.com/ethereum/go-ethereum/tests"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
type result struct {
|
|
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"`
|
|
IntrinsicGas hexutil.Uint64 `json:"intrinsicGas,omitempty"`
|
|
}
|
|
var out xx
|
|
if r.Error != nil {
|
|
out.Error = r.Error.Error()
|
|
}
|
|
if r.Address != (common.Address{}) {
|
|
out.Address = &r.Address
|
|
}
|
|
if r.Hash != (common.Hash{}) {
|
|
out.Hash = &r.Hash
|
|
}
|
|
out.IntrinsicGas = hexutil.Uint64(r.IntrinsicGas)
|
|
return json.Marshal(out)
|
|
}
|
|
|
|
func Transaction(ctx *cli.Context) error {
|
|
var (
|
|
err error
|
|
)
|
|
// We need to load the transactions. May be either in stdin input or in files.
|
|
// Check if anything needs to be read from stdin
|
|
var (
|
|
txStr = ctx.String(InputTxsFlag.Name)
|
|
inputData = &input{}
|
|
chainConfig *params.ChainConfig
|
|
)
|
|
// Construct the chainconfig
|
|
if cConf, _, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil {
|
|
return NewError(ErrorConfig, fmt.Errorf("failed constructing chain configuration: %v", err))
|
|
} else {
|
|
chainConfig = cConf
|
|
}
|
|
// Set the chain id
|
|
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
|
|
var body hexutil.Bytes
|
|
if txStr == stdinSelector {
|
|
decoder := json.NewDecoder(os.Stdin)
|
|
if err := decoder.Decode(inputData); err != nil {
|
|
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err))
|
|
}
|
|
// Decode the body of already signed transactions
|
|
body = common.FromHex(inputData.TxRlp)
|
|
} else {
|
|
// Read input from file
|
|
inFile, err := os.Open(txStr)
|
|
if err != nil {
|
|
return NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
|
|
}
|
|
defer inFile.Close()
|
|
decoder := json.NewDecoder(inFile)
|
|
if strings.HasSuffix(txStr, ".rlp") {
|
|
if err := decoder.Decode(&body); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
return NewError(ErrorIO, errors.New("only rlp supported"))
|
|
}
|
|
}
|
|
signer := types.MakeSigner(chainConfig, new(big.Int), 0)
|
|
// We now have the transactions in 'body', which is supposed to be an
|
|
// rlp list of transactions
|
|
it, err := rlp.NewListIterator([]byte(body))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
var results []result
|
|
for it.Next() {
|
|
if err := it.Err(); err != nil {
|
|
return NewError(ErrorIO, err)
|
|
}
|
|
var tx types.Transaction
|
|
err := rlp.DecodeBytes(it.Value(), &tx)
|
|
if err != nil {
|
|
results = append(results, result{Error: err})
|
|
continue
|
|
}
|
|
r := result{Hash: tx.Hash()}
|
|
if sender, err := types.Sender(signer, &tx); err != nil {
|
|
r.Error = err
|
|
results = append(results, r)
|
|
continue
|
|
} 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)), chainConfig.IsShanghai(new(big.Int), 0)); err != nil {
|
|
r.Error = err
|
|
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.Nonce()+1 < tx.Nonce():
|
|
r.Error = errors.New("nonce exceeds 2^64-1")
|
|
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")
|
|
}
|
|
// Check whether the init code size has been exceeded.
|
|
if chainConfig.IsShanghai(new(big.Int), 0) && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize {
|
|
r.Error = errors.New("max initcode size exceeded")
|
|
}
|
|
results = append(results, r)
|
|
}
|
|
out, err := json.MarshalIndent(results, "", " ")
|
|
fmt.Println(string(out))
|
|
return err
|
|
}
|