mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
cmd/evm/internal/t8ntool: move tx handling to separate file
This commit is contained in:
parent
c1d5a012ea
commit
efcb866643
7 changed files with 192 additions and 122 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
151
cmd/evm/internal/t8ntool/tx_iterator.go
Normal file
151
cmd/evm/internal/t8ntool/tx_iterator.go
Normal 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
16
cmd/evm/testdata/30/alloc.json
vendored
Normal 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
1
cmd/evm/testdata/30/command.sh
vendored
Normal 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
22
cmd/evm/testdata/30/env.json
vendored
Normal 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
1
cmd/evm/testdata/30/error.json
vendored
Normal 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
1
cmd/evm/testdata/30/txs.rlp
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
"0xf8dbb8d903f8d601800285012a05f200833d090080830186a000f85bf85994095e7baea6a6c7c4c2dfeb977efac326af552d87f842a00000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010ae1a001a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d880a0fc12b67159a3567f8bdbc49e0be369a2e20e09d57a51c41310543a4128409464a02de0cfe5495c4f58ff60645ceda0afd67a4c90a70bc89fe207269435b35e5b67"
|
||||||
Loading…
Reference in a new issue