cmd/evm/internal/t8ntool: move tx handling to separate file

This commit is contained in:
Martin Holst Swende 2023-10-21 22:17:09 +02:00
parent c1d5a012ea
commit efcb866643
No known key found for this signature in database
GPG key ID: 683B438C05A5DDF0
7 changed files with 192 additions and 122 deletions

View file

@ -17,14 +17,12 @@
package t8ntool package t8ntool
import ( import (
"crypto/ecdsa"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
"os" "os"
"path" "path"
"strings"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
@ -33,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/eth/tracers/logger"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -219,125 +216,6 @@ func Transition(ctx *cli.Context) error {
return dispatchOutput(ctx, baseDir, result, collector, body) return dispatchOutput(ctx, baseDir, result, collector, body)
} }
// txWithKey is a helper-struct, to allow us to use the types.Transaction along with
// a `secretKey`-field, for input
type txWithKey struct {
key *ecdsa.PrivateKey
tx *types.Transaction
protected bool
}
func (t *txWithKey) UnmarshalJSON(input []byte) error {
// Read the metadata, if present
type txMetadata struct {
Key *common.Hash `json:"secretKey"`
Protected *bool `json:"protected"`
}
var data txMetadata
if err := json.Unmarshal(input, &data); err != nil {
return err
}
if data.Key != nil {
k := data.Key.Hex()[2:]
if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
return err
} else {
t.key = ecdsaKey
}
}
if data.Protected != nil {
t.protected = *data.Protected
} else {
t.protected = true
}
// Now, read the transaction itself
var tx types.Transaction
if err := json.Unmarshal(input, &tx); err != nil {
return err
}
t.tx = &tx
return nil
}
// signUnsignedTransactions converts the input txs to canonical transactions.
//
// The transactions can have two forms, either
// 1. unsigned or
// 2. signed
//
// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set.
// If so, we sign it here and now, with the given `secretKey`
// If the condition above is not met, then it's considered a signed transaction.
//
// To manage this, we read the transactions twice, first trying to read the secretKeys,
// and secondly to read them with the standard tx json format
func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
var signedTxs []*types.Transaction
for i, tx := range txs {
var (
v, r, s = tx.tx.RawSignatureValues()
signed *types.Transaction
err error
)
if tx.key == nil || v.BitLen()+r.BitLen()+s.BitLen() != 0 {
// Already signed
signedTxs = append(signedTxs, tx.tx)
continue
}
// This transaction needs to be signed
if tx.protected {
signed, err = types.SignTx(tx.tx, signer, tx.key)
} else {
signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key)
}
if err != nil {
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
}
signedTxs = append(signedTxs, signed)
}
return signedTxs, nil
}
func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (types.Transactions, error) {
var txsWithKeys []*txWithKey
var signed types.Transactions
if txStr != stdinSelector {
data, err := os.ReadFile(txStr)
if err != nil {
return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
}
if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list
var body hexutil.Bytes
if err := json.Unmarshal(data, &body); err != nil {
return nil, err
}
// Already signed transactions
if err := rlp.DecodeBytes(body, &signed); err != nil {
return nil, err
}
return signed, nil
}
if err := json.Unmarshal(data, &txsWithKeys); err != nil {
return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
}
} else {
if len(inputData.TxRlp) > 0 {
// Decode the body of already signed transactions
body := common.FromHex(inputData.TxRlp)
// Already signed transactions
if err := rlp.DecodeBytes(body, &signed); err != nil {
return nil, err
}
return signed, nil
}
// JSON encoded transactions
txsWithKeys = inputData.Txs
}
// We may have to sign the transactions.
signer := types.LatestSignerForChainID(chainConfig.ChainID)
return signUnsignedTransactions(txsWithKeys, signer)
}
func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error { func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) { if !chainConfig.IsLondon(big.NewInt(int64(env.Number))) {
return nil return nil

View file

@ -0,0 +1,151 @@
// Copyright 2020 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 (
"crypto/ecdsa"
"encoding/json"
"fmt"
"os"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
)
// txWithKey is a helper-struct, to allow us to use the types.Transaction along with
// a `secretKey`-field, for input
type txWithKey struct {
key *ecdsa.PrivateKey
tx *types.Transaction
protected bool
}
func (t *txWithKey) UnmarshalJSON(input []byte) error {
// Read the metadata, if present
type txMetadata struct {
Key *common.Hash `json:"secretKey"`
Protected *bool `json:"protected"`
}
var data txMetadata
if err := json.Unmarshal(input, &data); err != nil {
return err
}
if data.Key != nil {
k := data.Key.Hex()[2:]
if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
return err
} else {
t.key = ecdsaKey
}
}
if data.Protected != nil {
t.protected = *data.Protected
} else {
t.protected = true
}
// Now, read the transaction itself
var tx types.Transaction
if err := json.Unmarshal(input, &tx); err != nil {
return err
}
t.tx = &tx
return nil
}
// signUnsignedTransactions converts the input txs to canonical transactions.
//
// The transactions can have two forms, either
// 1. unsigned or
// 2. signed
//
// For (1), r, s, v, need so be zero, and the `secretKey` needs to be set.
// If so, we sign it here and now, with the given `secretKey`
// If the condition above is not met, then it's considered a signed transaction.
//
// To manage this, we read the transactions twice, first trying to read the secretKeys,
// and secondly to read them with the standard tx json format
func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Transactions, error) {
var signedTxs []*types.Transaction
for i, tx := range txs {
var (
v, r, s = tx.tx.RawSignatureValues()
signed *types.Transaction
err error
)
if tx.key == nil || v.BitLen()+r.BitLen()+s.BitLen() != 0 {
// Already signed
signedTxs = append(signedTxs, tx.tx)
continue
}
// This transaction needs to be signed
if tx.protected {
signed, err = types.SignTx(tx.tx, signer, tx.key)
} else {
signed, err = types.SignTx(tx.tx, types.FrontierSigner{}, tx.key)
}
if err != nil {
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
}
signedTxs = append(signedTxs, signed)
}
return signedTxs, nil
}
func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (types.Transactions, error) {
var txsWithKeys []*txWithKey
var signed types.Transactions
if txStr != stdinSelector {
data, err := os.ReadFile(txStr)
if err != nil {
return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
}
if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list
var body hexutil.Bytes
if err := json.Unmarshal(data, &body); err != nil {
return nil, err
}
// Already signed transactions
if err := rlp.DecodeBytes(body, &signed); err != nil {
return nil, err
}
return signed, nil
}
if err := json.Unmarshal(data, &txsWithKeys); err != nil {
return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling txs-file: %v", err))
}
} else {
if len(inputData.TxRlp) > 0 {
// Decode the body of already signed transactions
body := common.FromHex(inputData.TxRlp)
// Already signed transactions
if err := rlp.DecodeBytes(body, &signed); err != nil {
return nil, err
}
return signed, nil
}
// JSON encoded transactions
txsWithKeys = inputData.Txs
}
// We may have to sign the transactions.
signer := types.LatestSignerForChainID(chainConfig.ChainID)
return signUnsignedTransactions(txsWithKeys, signer)
}

16
cmd/evm/testdata/30/alloc.json vendored Normal file
View file

@ -0,0 +1,16 @@
{
"0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x60004960005500",
"nonce" : "0x00",
"storage" : {
}
},
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
}

1
cmd/evm/testdata/30/command.sh vendored Normal file
View file

@ -0,0 +1 @@
/home/wins/.retesteth/default/start.sh --state.fork Cancun --state.reward 0 --state.chainid 1 --input.alloc /home/wins/Ethereum/rettmp/default_Cancun_block1_0xe4e2a3/alloc.json --input.txs /home/wins/Ethereum/rettmp/default_Cancun_block1_0xe4e2a3/txs.rlp --input.env /home/wins/Ethereum/rettmp/default_Cancun_block1_0xe4e2a3/env.json --output.basedir /home/wins/Ethereum/rettmp/default_Cancun_block1_0xe4e2a3 --output.result out.json --output.alloc outAlloc.json --output.errorlog /home/wins/Ethereum/rettmp/default_Cancun_block1_0xe4e2a3/error.json

22
cmd/evm/testdata/30/env.json vendored Normal file
View file

@ -0,0 +1,22 @@
{
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentNumber" : "0x01",
"currentTimestamp" : "0x03e8",
"currentGasLimit" : "0x1000000000",
"previousHash" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da",
"currentDataGasUsed" : "0x2000",
"parentTimestamp" : "0x00",
"parentDifficulty" : "0x00",
"parentUncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"currentRandom" : "0x0000000000000000000000000000000000000000000000000000000000020000",
"withdrawals" : [
],
"parentBaseFee" : "0x08",
"parentGasUsed" : "0x00",
"parentGasLimit" : "0x1000000000",
"parentExcessDataGas" : "0x1000",
"parentDataGasUsed" : "0x2000",
"blockHashes" : {
"0" : "0xe4e2a30b340bec696242b67584264f878600dce98354ae0b6328740fd4ff18da"
}
}

1
cmd/evm/testdata/30/error.json vendored Normal file
View file

@ -0,0 +1 @@
rlp: input string too short for common.Address, decoding into (types.Transactions)[0](types.BlobTx).To

1
cmd/evm/testdata/30/txs.rlp vendored Normal file
View file

@ -0,0 +1 @@
"0xf8dbb8d903f8d601800285012a05f200833d090080830186a000f85bf85994095e7baea6a6c7c4c2dfeb977efac326af552d87f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d880a0fc12b67159a3567f8bdbc49e0be369a2e20e09d57a51c41310543a4128409464a02de0cfe5495c4f58ff60645ceda0afd67a4c90a70bc89fe207269435b35e5b67"