Merge tag 'v1.10.13' into HEAD
This commit is contained in:
commit
72b7820579
@ -462,6 +462,9 @@ func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Ad
|
|||||||
// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
|
// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
|
||||||
// chain doesn't have miners, we just return a gas price of 1 for any call.
|
// chain doesn't have miners, we just return a gas price of 1 for any call.
|
||||||
func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
|
func (b *SimulatedBackend) SuggestGasPrice(ctx context.Context) (*big.Int, error) {
|
||||||
|
b.mu.Lock()
|
||||||
|
defer b.mu.Unlock()
|
||||||
|
|
||||||
if b.pendingBlock.Header().BaseFee != nil {
|
if b.pendingBlock.Header().BaseFee != nil {
|
||||||
return b.pendingBlock.Header().BaseFee, nil
|
return b.pendingBlock.Header().BaseFee, nil
|
||||||
}
|
}
|
||||||
|
@ -133,7 +133,8 @@ func (c *cloudflareClient) uploadRecords(name string, records map[string]string)
|
|||||||
log.Info(fmt.Sprintf("Creating %s = %q", path, val))
|
log.Info(fmt.Sprintf("Creating %s = %q", path, val))
|
||||||
ttl := rootTTL
|
ttl := rootTTL
|
||||||
if path != name {
|
if path != name {
|
||||||
ttl = treeNodeTTL // Max TTL permitted by Cloudflare
|
ttl = treeNodeTTLCloudflare // Max TTL permitted by Cloudflare
|
||||||
|
|
||||||
}
|
}
|
||||||
record := cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl}
|
record := cloudflare.DNSRecord{Type: "TXT", Name: path, Content: val, TTL: ttl}
|
||||||
_, err = c.CreateDNSRecord(context.Background(), c.zoneID, record)
|
_, err = c.CreateDNSRecord(context.Background(), c.zoneID, record)
|
||||||
|
@ -115,8 +115,9 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rootTTL = 30 * 60 // 30 min
|
rootTTL = 30 * 60 // 30 min
|
||||||
treeNodeTTL = 4 * 7 * 24 * 60 * 60 // 4 weeks
|
treeNodeTTL = 4 * 7 * 24 * 60 * 60 // 4 weeks
|
||||||
|
treeNodeTTLCloudflare = 24 * 60 * 60 // 1 day
|
||||||
)
|
)
|
||||||
|
|
||||||
// dnsSync performs dnsSyncCommand.
|
// dnsSync performs dnsSyncCommand.
|
||||||
|
@ -131,7 +131,7 @@ func (c *Conn) handshake() error {
|
|||||||
}
|
}
|
||||||
c.negotiateEthProtocol(msg.Caps)
|
c.negotiateEthProtocol(msg.Caps)
|
||||||
if c.negotiatedProtoVersion == 0 {
|
if c.negotiatedProtoVersion == 0 {
|
||||||
return fmt.Errorf("unexpected eth protocol version")
|
return fmt.Errorf("could not negotiate protocol (remote caps: %v, local eth version: %v)", msg.Caps, c.ourHighestProtoVersion)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
default:
|
default:
|
||||||
|
@ -52,35 +52,35 @@ func NewSuite(dest *enode.Node, chainfile string, genesisfile string) (*Suite, e
|
|||||||
func (s *Suite) AllEthTests() []utesting.Test {
|
func (s *Suite) AllEthTests() []utesting.Test {
|
||||||
return []utesting.Test{
|
return []utesting.Test{
|
||||||
// status
|
// status
|
||||||
{Name: "TestStatus", Fn: s.TestStatus},
|
{Name: "TestStatus65", Fn: s.TestStatus65},
|
||||||
{Name: "TestStatus66", Fn: s.TestStatus66},
|
{Name: "TestStatus66", Fn: s.TestStatus66},
|
||||||
// get block headers
|
// get block headers
|
||||||
{Name: "TestGetBlockHeaders", Fn: s.TestGetBlockHeaders},
|
{Name: "TestGetBlockHeaders65", Fn: s.TestGetBlockHeaders65},
|
||||||
{Name: "TestGetBlockHeaders66", Fn: s.TestGetBlockHeaders66},
|
{Name: "TestGetBlockHeaders66", Fn: s.TestGetBlockHeaders66},
|
||||||
{Name: "TestSimultaneousRequests66", Fn: s.TestSimultaneousRequests66},
|
{Name: "TestSimultaneousRequests66", Fn: s.TestSimultaneousRequests66},
|
||||||
{Name: "TestSameRequestID66", Fn: s.TestSameRequestID66},
|
{Name: "TestSameRequestID66", Fn: s.TestSameRequestID66},
|
||||||
{Name: "TestZeroRequestID66", Fn: s.TestZeroRequestID66},
|
{Name: "TestZeroRequestID66", Fn: s.TestZeroRequestID66},
|
||||||
// get block bodies
|
// get block bodies
|
||||||
{Name: "TestGetBlockBodies", Fn: s.TestGetBlockBodies},
|
{Name: "TestGetBlockBodies65", Fn: s.TestGetBlockBodies65},
|
||||||
{Name: "TestGetBlockBodies66", Fn: s.TestGetBlockBodies66},
|
{Name: "TestGetBlockBodies66", Fn: s.TestGetBlockBodies66},
|
||||||
// broadcast
|
// broadcast
|
||||||
{Name: "TestBroadcast", Fn: s.TestBroadcast},
|
{Name: "TestBroadcast65", Fn: s.TestBroadcast65},
|
||||||
{Name: "TestBroadcast66", Fn: s.TestBroadcast66},
|
{Name: "TestBroadcast66", Fn: s.TestBroadcast66},
|
||||||
{Name: "TestLargeAnnounce", Fn: s.TestLargeAnnounce},
|
{Name: "TestLargeAnnounce65", Fn: s.TestLargeAnnounce65},
|
||||||
{Name: "TestLargeAnnounce66", Fn: s.TestLargeAnnounce66},
|
{Name: "TestLargeAnnounce66", Fn: s.TestLargeAnnounce66},
|
||||||
{Name: "TestOldAnnounce", Fn: s.TestOldAnnounce},
|
{Name: "TestOldAnnounce65", Fn: s.TestOldAnnounce65},
|
||||||
{Name: "TestOldAnnounce66", Fn: s.TestOldAnnounce66},
|
{Name: "TestOldAnnounce66", Fn: s.TestOldAnnounce66},
|
||||||
{Name: "TestBlockHashAnnounce", Fn: s.TestBlockHashAnnounce},
|
{Name: "TestBlockHashAnnounce65", Fn: s.TestBlockHashAnnounce65},
|
||||||
{Name: "TestBlockHashAnnounce66", Fn: s.TestBlockHashAnnounce66},
|
{Name: "TestBlockHashAnnounce66", Fn: s.TestBlockHashAnnounce66},
|
||||||
// malicious handshakes + status
|
// malicious handshakes + status
|
||||||
{Name: "TestMaliciousHandshake", Fn: s.TestMaliciousHandshake},
|
{Name: "TestMaliciousHandshake65", Fn: s.TestMaliciousHandshake65},
|
||||||
{Name: "TestMaliciousStatus", Fn: s.TestMaliciousStatus},
|
{Name: "TestMaliciousStatus65", Fn: s.TestMaliciousStatus65},
|
||||||
{Name: "TestMaliciousHandshake66", Fn: s.TestMaliciousHandshake66},
|
{Name: "TestMaliciousHandshake66", Fn: s.TestMaliciousHandshake66},
|
||||||
{Name: "TestMaliciousStatus66", Fn: s.TestMaliciousStatus66},
|
{Name: "TestMaliciousStatus66", Fn: s.TestMaliciousStatus66},
|
||||||
// test transactions
|
// test transactions
|
||||||
{Name: "TestTransaction", Fn: s.TestTransaction},
|
{Name: "TestTransaction65", Fn: s.TestTransaction65},
|
||||||
{Name: "TestTransaction66", Fn: s.TestTransaction66},
|
{Name: "TestTransaction66", Fn: s.TestTransaction66},
|
||||||
{Name: "TestMaliciousTx", Fn: s.TestMaliciousTx},
|
{Name: "TestMaliciousTx65", Fn: s.TestMaliciousTx65},
|
||||||
{Name: "TestMaliciousTx66", Fn: s.TestMaliciousTx66},
|
{Name: "TestMaliciousTx66", Fn: s.TestMaliciousTx66},
|
||||||
{Name: "TestLargeTxRequest66", Fn: s.TestLargeTxRequest66},
|
{Name: "TestLargeTxRequest66", Fn: s.TestLargeTxRequest66},
|
||||||
{Name: "TestNewPooledTxs66", Fn: s.TestNewPooledTxs66},
|
{Name: "TestNewPooledTxs66", Fn: s.TestNewPooledTxs66},
|
||||||
@ -89,17 +89,17 @@ func (s *Suite) AllEthTests() []utesting.Test {
|
|||||||
|
|
||||||
func (s *Suite) EthTests() []utesting.Test {
|
func (s *Suite) EthTests() []utesting.Test {
|
||||||
return []utesting.Test{
|
return []utesting.Test{
|
||||||
{Name: "TestStatus", Fn: s.TestStatus},
|
{Name: "TestStatus65", Fn: s.TestStatus65},
|
||||||
{Name: "TestGetBlockHeaders", Fn: s.TestGetBlockHeaders},
|
{Name: "TestGetBlockHeaders65", Fn: s.TestGetBlockHeaders65},
|
||||||
{Name: "TestGetBlockBodies", Fn: s.TestGetBlockBodies},
|
{Name: "TestGetBlockBodies65", Fn: s.TestGetBlockBodies65},
|
||||||
{Name: "TestBroadcast", Fn: s.TestBroadcast},
|
{Name: "TestBroadcast65", Fn: s.TestBroadcast65},
|
||||||
{Name: "TestLargeAnnounce", Fn: s.TestLargeAnnounce},
|
{Name: "TestLargeAnnounce65", Fn: s.TestLargeAnnounce65},
|
||||||
{Name: "TestOldAnnounce", Fn: s.TestOldAnnounce},
|
{Name: "TestOldAnnounce65", Fn: s.TestOldAnnounce65},
|
||||||
{Name: "TestBlockHashAnnounce", Fn: s.TestBlockHashAnnounce},
|
{Name: "TestBlockHashAnnounce65", Fn: s.TestBlockHashAnnounce65},
|
||||||
{Name: "TestMaliciousHandshake", Fn: s.TestMaliciousHandshake},
|
{Name: "TestMaliciousHandshake65", Fn: s.TestMaliciousHandshake65},
|
||||||
{Name: "TestMaliciousStatus", Fn: s.TestMaliciousStatus},
|
{Name: "TestMaliciousStatus65", Fn: s.TestMaliciousStatus65},
|
||||||
{Name: "TestTransaction", Fn: s.TestTransaction},
|
{Name: "TestTransaction65", Fn: s.TestTransaction65},
|
||||||
{Name: "TestMaliciousTx", Fn: s.TestMaliciousTx},
|
{Name: "TestMaliciousTx65", Fn: s.TestMaliciousTx65},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,9 +130,9 @@ var (
|
|||||||
eth65 = false // indicates whether suite should negotiate eth65 connection or below.
|
eth65 = false // indicates whether suite should negotiate eth65 connection or below.
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestStatus attempts to connect to the given node and exchange
|
// TestStatus65 attempts to connect to the given node and exchange
|
||||||
// a status message with it.
|
// a status message with it.
|
||||||
func (s *Suite) TestStatus(t *utesting.T) {
|
func (s *Suite) TestStatus65(t *utesting.T) {
|
||||||
conn, err := s.dial()
|
conn, err := s.dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("dial failed: %v", err)
|
t.Fatalf("dial failed: %v", err)
|
||||||
@ -156,9 +156,9 @@ func (s *Suite) TestStatus66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGetBlockHeaders tests whether the given node can respond to
|
// TestGetBlockHeaders65 tests whether the given node can respond to
|
||||||
// a `GetBlockHeaders` request accurately.
|
// a `GetBlockHeaders` request accurately.
|
||||||
func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
|
func (s *Suite) TestGetBlockHeaders65(t *utesting.T) {
|
||||||
conn, err := s.dial()
|
conn, err := s.dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("dial failed: %v", err)
|
t.Fatalf("dial failed: %v", err)
|
||||||
@ -392,9 +392,9 @@ func (s *Suite) TestZeroRequestID66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGetBlockBodies tests whether the given node can respond to
|
// TestGetBlockBodies65 tests whether the given node can respond to
|
||||||
// a `GetBlockBodies` request and that the response is accurate.
|
// a `GetBlockBodies` request and that the response is accurate.
|
||||||
func (s *Suite) TestGetBlockBodies(t *utesting.T) {
|
func (s *Suite) TestGetBlockBodies65(t *utesting.T) {
|
||||||
conn, err := s.dial()
|
conn, err := s.dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("dial failed: %v", err)
|
t.Fatalf("dial failed: %v", err)
|
||||||
@ -460,9 +460,9 @@ func (s *Suite) TestGetBlockBodies66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestBroadcast tests whether a block announcement is correctly
|
// TestBroadcast65 tests whether a block announcement is correctly
|
||||||
// propagated to the given node's peer(s).
|
// propagated to the given node's peer(s).
|
||||||
func (s *Suite) TestBroadcast(t *utesting.T) {
|
func (s *Suite) TestBroadcast65(t *utesting.T) {
|
||||||
if err := s.sendNextBlock(eth65); err != nil {
|
if err := s.sendNextBlock(eth65); err != nil {
|
||||||
t.Fatalf("block broadcast failed: %v", err)
|
t.Fatalf("block broadcast failed: %v", err)
|
||||||
}
|
}
|
||||||
@ -476,8 +476,8 @@ func (s *Suite) TestBroadcast66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestLargeAnnounce tests the announcement mechanism with a large block.
|
// TestLargeAnnounce65 tests the announcement mechanism with a large block.
|
||||||
func (s *Suite) TestLargeAnnounce(t *utesting.T) {
|
func (s *Suite) TestLargeAnnounce65(t *utesting.T) {
|
||||||
nextBlock := len(s.chain.blocks)
|
nextBlock := len(s.chain.blocks)
|
||||||
blocks := []*NewBlock{
|
blocks := []*NewBlock{
|
||||||
{
|
{
|
||||||
@ -569,8 +569,8 @@ func (s *Suite) TestLargeAnnounce66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestOldAnnounce tests the announcement mechanism with an old block.
|
// TestOldAnnounce65 tests the announcement mechanism with an old block.
|
||||||
func (s *Suite) TestOldAnnounce(t *utesting.T) {
|
func (s *Suite) TestOldAnnounce65(t *utesting.T) {
|
||||||
if err := s.oldAnnounce(eth65); err != nil {
|
if err := s.oldAnnounce(eth65); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -584,9 +584,9 @@ func (s *Suite) TestOldAnnounce66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestBlockHashAnnounce sends a new block hash announcement and expects
|
// TestBlockHashAnnounce65 sends a new block hash announcement and expects
|
||||||
// the node to perform a `GetBlockHeaders` request.
|
// the node to perform a `GetBlockHeaders` request.
|
||||||
func (s *Suite) TestBlockHashAnnounce(t *utesting.T) {
|
func (s *Suite) TestBlockHashAnnounce65(t *utesting.T) {
|
||||||
if err := s.hashAnnounce(eth65); err != nil {
|
if err := s.hashAnnounce(eth65); err != nil {
|
||||||
t.Fatalf("block hash announcement failed: %v", err)
|
t.Fatalf("block hash announcement failed: %v", err)
|
||||||
}
|
}
|
||||||
@ -600,8 +600,8 @@ func (s *Suite) TestBlockHashAnnounce66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestMaliciousHandshake tries to send malicious data during the handshake.
|
// TestMaliciousHandshake65 tries to send malicious data during the handshake.
|
||||||
func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
|
func (s *Suite) TestMaliciousHandshake65(t *utesting.T) {
|
||||||
if err := s.maliciousHandshakes(t, eth65); err != nil {
|
if err := s.maliciousHandshakes(t, eth65); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -614,8 +614,8 @@ func (s *Suite) TestMaliciousHandshake66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestMaliciousStatus sends a status package with a large total difficulty.
|
// TestMaliciousStatus65 sends a status package with a large total difficulty.
|
||||||
func (s *Suite) TestMaliciousStatus(t *utesting.T) {
|
func (s *Suite) TestMaliciousStatus65(t *utesting.T) {
|
||||||
conn, err := s.dial()
|
conn, err := s.dial()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("dial failed: %v", err)
|
t.Fatalf("dial failed: %v", err)
|
||||||
@ -641,9 +641,9 @@ func (s *Suite) TestMaliciousStatus66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestTransaction sends a valid transaction to the node and
|
// TestTransaction65 sends a valid transaction to the node and
|
||||||
// checks if the transaction gets propagated.
|
// checks if the transaction gets propagated.
|
||||||
func (s *Suite) TestTransaction(t *utesting.T) {
|
func (s *Suite) TestTransaction65(t *utesting.T) {
|
||||||
if err := s.sendSuccessfulTxs(t, eth65); err != nil {
|
if err := s.sendSuccessfulTxs(t, eth65); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -657,9 +657,9 @@ func (s *Suite) TestTransaction66(t *utesting.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestMaliciousTx sends several invalid transactions and tests whether
|
// TestMaliciousTx65 sends several invalid transactions and tests whether
|
||||||
// the node will propagate them.
|
// the node will propagate them.
|
||||||
func (s *Suite) TestMaliciousTx(t *utesting.T) {
|
func (s *Suite) TestMaliciousTx65(t *utesting.T) {
|
||||||
if err := s.sendMaliciousTxs(t, eth65); err != nil {
|
if err := s.sendMaliciousTxs(t, eth65); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
380
cmd/evm/internal/t8ntool/block.go
Normal file
380
cmd/evm/internal/t8ntool/block.go
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
// 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 (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/clique"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
|
"gopkg.in/urfave/cli.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate gencodec -type header -field-override headerMarshaling -out gen_header.go
|
||||||
|
type header struct {
|
||||||
|
ParentHash common.Hash `json:"parentHash"`
|
||||||
|
OmmerHash *common.Hash `json:"sha3Uncles"`
|
||||||
|
Coinbase *common.Address `json:"miner"`
|
||||||
|
Root common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
|
TxHash *common.Hash `json:"transactionsRoot"`
|
||||||
|
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||||
|
Bloom types.Bloom `json:"logsBloom"`
|
||||||
|
Difficulty *big.Int `json:"difficulty"`
|
||||||
|
Number *big.Int `json:"number" gencodec:"required"`
|
||||||
|
GasLimit uint64 `json:"gasLimit" gencodec:"required"`
|
||||||
|
GasUsed uint64 `json:"gasUsed"`
|
||||||
|
Time uint64 `json:"timestamp" gencodec:"required"`
|
||||||
|
Extra []byte `json:"extraData"`
|
||||||
|
MixDigest common.Hash `json:"mixHash"`
|
||||||
|
Nonce *types.BlockNonce `json:"nonce"`
|
||||||
|
BaseFee *big.Int `json:"baseFeePerGas" rlp:"optional"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type headerMarshaling struct {
|
||||||
|
Difficulty *math.HexOrDecimal256
|
||||||
|
Number *math.HexOrDecimal256
|
||||||
|
GasLimit math.HexOrDecimal64
|
||||||
|
GasUsed math.HexOrDecimal64
|
||||||
|
Time math.HexOrDecimal64
|
||||||
|
Extra hexutil.Bytes
|
||||||
|
BaseFee *math.HexOrDecimal256
|
||||||
|
}
|
||||||
|
|
||||||
|
type bbInput struct {
|
||||||
|
Header *header `json:"header,omitempty"`
|
||||||
|
OmmersRlp []string `json:"ommers,omitempty"`
|
||||||
|
TxRlp string `json:"txs,omitempty"`
|
||||||
|
Clique *cliqueInput `json:"clique,omitempty"`
|
||||||
|
|
||||||
|
Ethash bool `json:"-"`
|
||||||
|
EthashDir string `json:"-"`
|
||||||
|
PowMode ethash.Mode `json:"-"`
|
||||||
|
Txs []*types.Transaction `json:"-"`
|
||||||
|
Ommers []*types.Header `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type cliqueInput struct {
|
||||||
|
Key *ecdsa.PrivateKey
|
||||||
|
Voted *common.Address
|
||||||
|
Authorize *bool
|
||||||
|
Vanity common.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements json.Unmarshaler interface.
|
||||||
|
func (c *cliqueInput) UnmarshalJSON(input []byte) error {
|
||||||
|
var x struct {
|
||||||
|
Key *common.Hash `json:"secretKey"`
|
||||||
|
Voted *common.Address `json:"voted"`
|
||||||
|
Authorize *bool `json:"authorize"`
|
||||||
|
Vanity common.Hash `json:"vanity"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(input, &x); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if x.Key == nil {
|
||||||
|
return errors.New("missing required field 'secretKey' for cliqueInput")
|
||||||
|
}
|
||||||
|
if ecdsaKey, err := crypto.ToECDSA(x.Key[:]); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
c.Key = ecdsaKey
|
||||||
|
}
|
||||||
|
c.Voted = x.Voted
|
||||||
|
c.Authorize = x.Authorize
|
||||||
|
c.Vanity = x.Vanity
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToBlock converts i into a *types.Block
|
||||||
|
func (i *bbInput) ToBlock() *types.Block {
|
||||||
|
header := &types.Header{
|
||||||
|
ParentHash: i.Header.ParentHash,
|
||||||
|
UncleHash: types.EmptyUncleHash,
|
||||||
|
Coinbase: common.Address{},
|
||||||
|
Root: i.Header.Root,
|
||||||
|
TxHash: types.EmptyRootHash,
|
||||||
|
ReceiptHash: types.EmptyRootHash,
|
||||||
|
Bloom: i.Header.Bloom,
|
||||||
|
Difficulty: common.Big0,
|
||||||
|
Number: i.Header.Number,
|
||||||
|
GasLimit: i.Header.GasLimit,
|
||||||
|
GasUsed: i.Header.GasUsed,
|
||||||
|
Time: i.Header.Time,
|
||||||
|
Extra: i.Header.Extra,
|
||||||
|
MixDigest: i.Header.MixDigest,
|
||||||
|
BaseFee: i.Header.BaseFee,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill optional values.
|
||||||
|
if i.Header.OmmerHash != nil {
|
||||||
|
header.UncleHash = *i.Header.OmmerHash
|
||||||
|
} else if len(i.Ommers) != 0 {
|
||||||
|
// Calculate the ommer hash if none is provided and there are ommers to hash
|
||||||
|
header.UncleHash = types.CalcUncleHash(i.Ommers)
|
||||||
|
}
|
||||||
|
if i.Header.Coinbase != nil {
|
||||||
|
header.Coinbase = *i.Header.Coinbase
|
||||||
|
}
|
||||||
|
if i.Header.TxHash != nil {
|
||||||
|
header.TxHash = *i.Header.TxHash
|
||||||
|
}
|
||||||
|
if i.Header.ReceiptHash != nil {
|
||||||
|
header.ReceiptHash = *i.Header.ReceiptHash
|
||||||
|
}
|
||||||
|
if i.Header.Nonce != nil {
|
||||||
|
header.Nonce = *i.Header.Nonce
|
||||||
|
}
|
||||||
|
if header.Difficulty != nil {
|
||||||
|
header.Difficulty = i.Header.Difficulty
|
||||||
|
}
|
||||||
|
return types.NewBlockWithHeader(header).WithBody(i.Txs, i.Ommers)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SealBlock seals the given block using the configured engine.
|
||||||
|
func (i *bbInput) SealBlock(block *types.Block) (*types.Block, error) {
|
||||||
|
switch {
|
||||||
|
case i.Ethash:
|
||||||
|
return i.sealEthash(block)
|
||||||
|
case i.Clique != nil:
|
||||||
|
return i.sealClique(block)
|
||||||
|
default:
|
||||||
|
return block, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sealEthash seals the given block using ethash.
|
||||||
|
func (i *bbInput) sealEthash(block *types.Block) (*types.Block, error) {
|
||||||
|
if i.Header.Nonce != nil {
|
||||||
|
return nil, NewError(ErrorConfig, fmt.Errorf("sealing with ethash will overwrite provided nonce"))
|
||||||
|
}
|
||||||
|
ethashConfig := ethash.Config{
|
||||||
|
PowMode: i.PowMode,
|
||||||
|
DatasetDir: i.EthashDir,
|
||||||
|
CacheDir: i.EthashDir,
|
||||||
|
DatasetsInMem: 1,
|
||||||
|
DatasetsOnDisk: 2,
|
||||||
|
CachesInMem: 2,
|
||||||
|
CachesOnDisk: 3,
|
||||||
|
}
|
||||||
|
engine := ethash.New(ethashConfig, nil, true)
|
||||||
|
defer engine.Close()
|
||||||
|
// Use a buffered chan for results.
|
||||||
|
// If the testmode is used, the sealer will return quickly, and complain
|
||||||
|
// "Sealing result is not read by miner" if it cannot write the result.
|
||||||
|
results := make(chan *types.Block, 1)
|
||||||
|
if err := engine.Seal(nil, block, results, nil); err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to seal block: %v", err))
|
||||||
|
}
|
||||||
|
found := <-results
|
||||||
|
return block.WithSeal(found.Header()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// sealClique seals the given block using clique.
|
||||||
|
func (i *bbInput) sealClique(block *types.Block) (*types.Block, error) {
|
||||||
|
// If any clique value overwrites an explicit header value, fail
|
||||||
|
// to avoid silently building a block with unexpected values.
|
||||||
|
if i.Header.Extra != nil {
|
||||||
|
return nil, NewError(ErrorConfig, fmt.Errorf("sealing with clique will overwrite provided extra data"))
|
||||||
|
}
|
||||||
|
header := block.Header()
|
||||||
|
if i.Clique.Voted != nil {
|
||||||
|
if i.Header.Coinbase != nil {
|
||||||
|
return nil, NewError(ErrorConfig, fmt.Errorf("sealing with clique and voting will overwrite provided coinbase"))
|
||||||
|
}
|
||||||
|
header.Coinbase = *i.Clique.Voted
|
||||||
|
}
|
||||||
|
if i.Clique.Authorize != nil {
|
||||||
|
if i.Header.Nonce != nil {
|
||||||
|
return nil, NewError(ErrorConfig, fmt.Errorf("sealing with clique and voting will overwrite provided nonce"))
|
||||||
|
}
|
||||||
|
if *i.Clique.Authorize {
|
||||||
|
header.Nonce = [8]byte{}
|
||||||
|
} else {
|
||||||
|
header.Nonce = [8]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Extra is fixed 32 byte vanity and 65 byte signature
|
||||||
|
header.Extra = make([]byte, 32+65)
|
||||||
|
copy(header.Extra[0:32], i.Clique.Vanity.Bytes()[:])
|
||||||
|
|
||||||
|
// Sign the seal hash and fill in the rest of the extra data
|
||||||
|
h := clique.SealHash(header)
|
||||||
|
sighash, err := crypto.Sign(h[:], i.Clique.Key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
copy(header.Extra[32:], sighash)
|
||||||
|
block = block.WithSeal(header)
|
||||||
|
return block, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildBlock constructs a block from the given inputs.
|
||||||
|
func BuildBlock(ctx *cli.Context) error {
|
||||||
|
// Configure the go-ethereum logger
|
||||||
|
glogger := log.NewGlogHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(false)))
|
||||||
|
glogger.Verbosity(log.Lvl(ctx.Int(VerbosityFlag.Name)))
|
||||||
|
log.Root().SetHandler(glogger)
|
||||||
|
|
||||||
|
baseDir, err := createBasedir(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
|
||||||
|
}
|
||||||
|
inputData, err := readInput(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
block := inputData.ToBlock()
|
||||||
|
block, err = inputData.SealBlock(block)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return dispatchBlock(ctx, baseDir, block)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readInput(ctx *cli.Context) (*bbInput, error) {
|
||||||
|
var (
|
||||||
|
headerStr = ctx.String(InputHeaderFlag.Name)
|
||||||
|
ommersStr = ctx.String(InputOmmersFlag.Name)
|
||||||
|
txsStr = ctx.String(InputTxsRlpFlag.Name)
|
||||||
|
cliqueStr = ctx.String(SealCliqueFlag.Name)
|
||||||
|
ethashOn = ctx.Bool(SealEthashFlag.Name)
|
||||||
|
ethashDir = ctx.String(SealEthashDirFlag.Name)
|
||||||
|
ethashMode = ctx.String(SealEthashModeFlag.Name)
|
||||||
|
inputData = &bbInput{}
|
||||||
|
)
|
||||||
|
if ethashOn && cliqueStr != "" {
|
||||||
|
return nil, NewError(ErrorConfig, fmt.Errorf("both ethash and clique sealing specified, only one may be chosen"))
|
||||||
|
}
|
||||||
|
if ethashOn {
|
||||||
|
inputData.Ethash = ethashOn
|
||||||
|
inputData.EthashDir = ethashDir
|
||||||
|
switch ethashMode {
|
||||||
|
case "normal":
|
||||||
|
inputData.PowMode = ethash.ModeNormal
|
||||||
|
case "test":
|
||||||
|
inputData.PowMode = ethash.ModeTest
|
||||||
|
case "fake":
|
||||||
|
inputData.PowMode = ethash.ModeFake
|
||||||
|
default:
|
||||||
|
return nil, NewError(ErrorConfig, fmt.Errorf("unknown pow mode: %s, supported modes: test, fake, normal", ethashMode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if headerStr == stdinSelector || ommersStr == stdinSelector || txsStr == stdinSelector || cliqueStr == stdinSelector {
|
||||||
|
decoder := json.NewDecoder(os.Stdin)
|
||||||
|
if err := decoder.Decode(inputData); err != nil {
|
||||||
|
return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshaling stdin: %v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cliqueStr != stdinSelector && cliqueStr != "" {
|
||||||
|
var clique cliqueInput
|
||||||
|
if err := readFile(cliqueStr, "clique", &clique); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inputData.Clique = &clique
|
||||||
|
}
|
||||||
|
if headerStr != stdinSelector {
|
||||||
|
var env header
|
||||||
|
if err := readFile(headerStr, "header", &env); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inputData.Header = &env
|
||||||
|
}
|
||||||
|
if ommersStr != stdinSelector && ommersStr != "" {
|
||||||
|
var ommers []string
|
||||||
|
if err := readFile(ommersStr, "ommers", &ommers); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inputData.OmmersRlp = ommers
|
||||||
|
}
|
||||||
|
if txsStr != stdinSelector {
|
||||||
|
var txs string
|
||||||
|
if err := readFile(txsStr, "txs", &txs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inputData.TxRlp = txs
|
||||||
|
}
|
||||||
|
// Deserialize rlp txs and ommers
|
||||||
|
var (
|
||||||
|
ommers = []*types.Header{}
|
||||||
|
txs = []*types.Transaction{}
|
||||||
|
)
|
||||||
|
if inputData.TxRlp != "" {
|
||||||
|
if err := rlp.DecodeBytes(common.FromHex(inputData.TxRlp), &txs); err != nil {
|
||||||
|
return nil, NewError(ErrorRlp, fmt.Errorf("unable to decode transaction from rlp data: %v", err))
|
||||||
|
}
|
||||||
|
inputData.Txs = txs
|
||||||
|
}
|
||||||
|
for _, str := range inputData.OmmersRlp {
|
||||||
|
type extblock struct {
|
||||||
|
Header *types.Header
|
||||||
|
Txs []*types.Transaction
|
||||||
|
Ommers []*types.Header
|
||||||
|
}
|
||||||
|
var ommer *extblock
|
||||||
|
if err := rlp.DecodeBytes(common.FromHex(str), &ommer); err != nil {
|
||||||
|
return nil, NewError(ErrorRlp, fmt.Errorf("unable to decode ommer from rlp data: %v", err))
|
||||||
|
}
|
||||||
|
ommers = append(ommers, ommer.Header)
|
||||||
|
}
|
||||||
|
inputData.Ommers = ommers
|
||||||
|
|
||||||
|
return inputData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispatchOutput writes the output data to either stderr or stdout, or to the specified
|
||||||
|
// files
|
||||||
|
func dispatchBlock(ctx *cli.Context, baseDir string, block *types.Block) error {
|
||||||
|
raw, _ := rlp.EncodeToBytes(block)
|
||||||
|
|
||||||
|
type blockInfo struct {
|
||||||
|
Rlp hexutil.Bytes `json:"rlp"`
|
||||||
|
Hash common.Hash `json:"hash"`
|
||||||
|
}
|
||||||
|
var enc blockInfo
|
||||||
|
enc.Rlp = raw
|
||||||
|
enc.Hash = block.Hash()
|
||||||
|
|
||||||
|
b, err := json.MarshalIndent(enc, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return NewError(ErrorJson, fmt.Errorf("failed marshalling output: %v", err))
|
||||||
|
}
|
||||||
|
switch dest := ctx.String(OutputBlockFlag.Name); dest {
|
||||||
|
case "stdout":
|
||||||
|
os.Stdout.Write(b)
|
||||||
|
os.Stdout.WriteString("\n")
|
||||||
|
case "stderr":
|
||||||
|
os.Stderr.Write(b)
|
||||||
|
os.Stderr.WriteString("\n")
|
||||||
|
default:
|
||||||
|
if err := saveFile(baseDir, dest, enc); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -49,12 +49,13 @@ type Prestate struct {
|
|||||||
type ExecutionResult struct {
|
type ExecutionResult struct {
|
||||||
StateRoot common.Hash `json:"stateRoot"`
|
StateRoot common.Hash `json:"stateRoot"`
|
||||||
TxRoot common.Hash `json:"txRoot"`
|
TxRoot common.Hash `json:"txRoot"`
|
||||||
ReceiptRoot common.Hash `json:"receiptRoot"`
|
ReceiptRoot common.Hash `json:"receiptsRoot"`
|
||||||
LogsHash common.Hash `json:"logsHash"`
|
LogsHash common.Hash `json:"logsHash"`
|
||||||
Bloom types.Bloom `json:"logsBloom" gencodec:"required"`
|
Bloom types.Bloom `json:"logsBloom" gencodec:"required"`
|
||||||
Receipts types.Receipts `json:"receipts"`
|
Receipts types.Receipts `json:"receipts"`
|
||||||
Rejected []*rejectedTx `json:"rejected,omitempty"`
|
Rejected []*rejectedTx `json:"rejected,omitempty"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
||||||
|
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ommer struct {
|
type ommer struct {
|
||||||
@ -255,6 +256,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
|||||||
Receipts: receipts,
|
Receipts: receipts,
|
||||||
Rejected: rejectedTxs,
|
Rejected: rejectedTxs,
|
||||||
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
|
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
|
||||||
|
GasUsed: (math.HexOrDecimal64)(gasUsed),
|
||||||
}
|
}
|
||||||
return statedb, execRs, nil
|
return statedb, execRs, nil
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,11 @@ var (
|
|||||||
}
|
}
|
||||||
TraceDisableMemoryFlag = cli.BoolTFlag{
|
TraceDisableMemoryFlag = cli.BoolTFlag{
|
||||||
Name: "trace.nomemory",
|
Name: "trace.nomemory",
|
||||||
Usage: "Disable full memory dump in traces",
|
Usage: "Disable full memory dump in traces (deprecated)",
|
||||||
|
}
|
||||||
|
TraceEnableMemoryFlag = cli.BoolFlag{
|
||||||
|
Name: "trace.memory",
|
||||||
|
Usage: "Enable full memory dump in traces",
|
||||||
}
|
}
|
||||||
TraceDisableStackFlag = cli.BoolFlag{
|
TraceDisableStackFlag = cli.BoolFlag{
|
||||||
Name: "trace.nostack",
|
Name: "trace.nostack",
|
||||||
@ -40,7 +44,11 @@ var (
|
|||||||
}
|
}
|
||||||
TraceDisableReturnDataFlag = cli.BoolTFlag{
|
TraceDisableReturnDataFlag = cli.BoolTFlag{
|
||||||
Name: "trace.noreturndata",
|
Name: "trace.noreturndata",
|
||||||
Usage: "Disable return data output in traces",
|
Usage: "Disable return data output in traces (deprecated)",
|
||||||
|
}
|
||||||
|
TraceEnableReturnDataFlag = cli.BoolFlag{
|
||||||
|
Name: "trace.returndata",
|
||||||
|
Usage: "Enable return data output in traces",
|
||||||
}
|
}
|
||||||
OutputBasedir = cli.StringFlag{
|
OutputBasedir = cli.StringFlag{
|
||||||
Name: "output.basedir",
|
Name: "output.basedir",
|
||||||
@ -68,6 +76,14 @@ var (
|
|||||||
"\t<file> - into the file <file> ",
|
"\t<file> - into the file <file> ",
|
||||||
Value: "result.json",
|
Value: "result.json",
|
||||||
}
|
}
|
||||||
|
OutputBlockFlag = cli.StringFlag{
|
||||||
|
Name: "output.block",
|
||||||
|
Usage: "Determines where to put the `block` after building.\n" +
|
||||||
|
"\t`stdout` - into the stdout output\n" +
|
||||||
|
"\t`stderr` - into the stderr output\n" +
|
||||||
|
"\t<file> - into the file <file> ",
|
||||||
|
Value: "block.json",
|
||||||
|
}
|
||||||
InputAllocFlag = cli.StringFlag{
|
InputAllocFlag = cli.StringFlag{
|
||||||
Name: "input.alloc",
|
Name: "input.alloc",
|
||||||
Usage: "`stdin` or file name of where to find the prestate alloc to use.",
|
Usage: "`stdin` or file name of where to find the prestate alloc to use.",
|
||||||
@ -81,10 +97,41 @@ var (
|
|||||||
InputTxsFlag = cli.StringFlag{
|
InputTxsFlag = cli.StringFlag{
|
||||||
Name: "input.txs",
|
Name: "input.txs",
|
||||||
Usage: "`stdin` or file name of where to find the transactions to apply. " +
|
Usage: "`stdin` or file name of where to find the transactions to apply. " +
|
||||||
"If the file prefix is '.rlp', then the data is interpreted as an RLP list of signed transactions." +
|
"If the file extension is '.rlp', then the data is interpreted as an RLP list of signed transactions." +
|
||||||
"The '.rlp' format is identical to the output.body format.",
|
"The '.rlp' format is identical to the output.body format.",
|
||||||
Value: "txs.json",
|
Value: "txs.json",
|
||||||
}
|
}
|
||||||
|
InputHeaderFlag = cli.StringFlag{
|
||||||
|
Name: "input.header",
|
||||||
|
Usage: "`stdin` or file name of where to find the block header to use.",
|
||||||
|
Value: "header.json",
|
||||||
|
}
|
||||||
|
InputOmmersFlag = cli.StringFlag{
|
||||||
|
Name: "input.ommers",
|
||||||
|
Usage: "`stdin` or file name of where to find the list of ommer header RLPs to use.",
|
||||||
|
}
|
||||||
|
InputTxsRlpFlag = cli.StringFlag{
|
||||||
|
Name: "input.txs",
|
||||||
|
Usage: "`stdin` or file name of where to find the transactions list in RLP form.",
|
||||||
|
Value: "txs.rlp",
|
||||||
|
}
|
||||||
|
SealCliqueFlag = cli.StringFlag{
|
||||||
|
Name: "seal.clique",
|
||||||
|
Usage: "Seal block with Clique. `stdin` or file name of where to find the Clique sealing data.",
|
||||||
|
}
|
||||||
|
SealEthashFlag = cli.BoolFlag{
|
||||||
|
Name: "seal.ethash",
|
||||||
|
Usage: "Seal block with ethash.",
|
||||||
|
}
|
||||||
|
SealEthashDirFlag = cli.StringFlag{
|
||||||
|
Name: "seal.ethash.dir",
|
||||||
|
Usage: "Path to ethash DAG. If none exists, a new DAG will be generated.",
|
||||||
|
}
|
||||||
|
SealEthashModeFlag = cli.StringFlag{
|
||||||
|
Name: "seal.ethash.mode",
|
||||||
|
Usage: "Defines the type and amount of PoW verification an ethash engine makes.",
|
||||||
|
Value: "normal",
|
||||||
|
}
|
||||||
RewardFlag = cli.Int64Flag{
|
RewardFlag = cli.Int64Flag{
|
||||||
Name: "state.reward",
|
Name: "state.reward",
|
||||||
Usage: "Mining reward. Set to -1 to disable",
|
Usage: "Mining reward. Set to -1 to disable",
|
||||||
|
135
cmd/evm/internal/t8ntool/gen_header.go
Normal file
135
cmd/evm/internal/t8ntool/gen_header.go
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
||||||
|
|
||||||
|
package t8ntool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = (*headerMarshaling)(nil)
|
||||||
|
|
||||||
|
// MarshalJSON marshals as JSON.
|
||||||
|
func (h header) MarshalJSON() ([]byte, error) {
|
||||||
|
type header struct {
|
||||||
|
ParentHash common.Hash `json:"parentHash"`
|
||||||
|
OmmerHash *common.Hash `json:"sha3Uncles"`
|
||||||
|
Coinbase *common.Address `json:"miner"`
|
||||||
|
Root common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
|
TxHash *common.Hash `json:"transactionsRoot"`
|
||||||
|
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||||
|
Bloom types.Bloom `json:"logsBloom"`
|
||||||
|
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
||||||
|
Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
|
||||||
|
GasLimit math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
||||||
|
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
|
Time math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
|
||||||
|
Extra hexutil.Bytes `json:"extraData"`
|
||||||
|
MixDigest common.Hash `json:"mixHash"`
|
||||||
|
Nonce *types.BlockNonce `json:"nonce"`
|
||||||
|
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
|
||||||
|
}
|
||||||
|
var enc header
|
||||||
|
enc.ParentHash = h.ParentHash
|
||||||
|
enc.OmmerHash = h.OmmerHash
|
||||||
|
enc.Coinbase = h.Coinbase
|
||||||
|
enc.Root = h.Root
|
||||||
|
enc.TxHash = h.TxHash
|
||||||
|
enc.ReceiptHash = h.ReceiptHash
|
||||||
|
enc.Bloom = h.Bloom
|
||||||
|
enc.Difficulty = (*math.HexOrDecimal256)(h.Difficulty)
|
||||||
|
enc.Number = (*math.HexOrDecimal256)(h.Number)
|
||||||
|
enc.GasLimit = math.HexOrDecimal64(h.GasLimit)
|
||||||
|
enc.GasUsed = math.HexOrDecimal64(h.GasUsed)
|
||||||
|
enc.Time = math.HexOrDecimal64(h.Time)
|
||||||
|
enc.Extra = h.Extra
|
||||||
|
enc.MixDigest = h.MixDigest
|
||||||
|
enc.Nonce = h.Nonce
|
||||||
|
enc.BaseFee = (*math.HexOrDecimal256)(h.BaseFee)
|
||||||
|
return json.Marshal(&enc)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals from JSON.
|
||||||
|
func (h *header) UnmarshalJSON(input []byte) error {
|
||||||
|
type header struct {
|
||||||
|
ParentHash *common.Hash `json:"parentHash"`
|
||||||
|
OmmerHash *common.Hash `json:"sha3Uncles"`
|
||||||
|
Coinbase *common.Address `json:"miner"`
|
||||||
|
Root *common.Hash `json:"stateRoot" gencodec:"required"`
|
||||||
|
TxHash *common.Hash `json:"transactionsRoot"`
|
||||||
|
ReceiptHash *common.Hash `json:"receiptsRoot"`
|
||||||
|
Bloom *types.Bloom `json:"logsBloom"`
|
||||||
|
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
||||||
|
Number *math.HexOrDecimal256 `json:"number" gencodec:"required"`
|
||||||
|
GasLimit *math.HexOrDecimal64 `json:"gasLimit" gencodec:"required"`
|
||||||
|
GasUsed *math.HexOrDecimal64 `json:"gasUsed"`
|
||||||
|
Time *math.HexOrDecimal64 `json:"timestamp" gencodec:"required"`
|
||||||
|
Extra *hexutil.Bytes `json:"extraData"`
|
||||||
|
MixDigest *common.Hash `json:"mixHash"`
|
||||||
|
Nonce *types.BlockNonce `json:"nonce"`
|
||||||
|
BaseFee *math.HexOrDecimal256 `json:"baseFeePerGas" rlp:"optional"`
|
||||||
|
}
|
||||||
|
var dec header
|
||||||
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dec.ParentHash != nil {
|
||||||
|
h.ParentHash = *dec.ParentHash
|
||||||
|
}
|
||||||
|
if dec.OmmerHash != nil {
|
||||||
|
h.OmmerHash = dec.OmmerHash
|
||||||
|
}
|
||||||
|
if dec.Coinbase != nil {
|
||||||
|
h.Coinbase = dec.Coinbase
|
||||||
|
}
|
||||||
|
if dec.Root == nil {
|
||||||
|
return errors.New("missing required field 'stateRoot' for header")
|
||||||
|
}
|
||||||
|
h.Root = *dec.Root
|
||||||
|
if dec.TxHash != nil {
|
||||||
|
h.TxHash = dec.TxHash
|
||||||
|
}
|
||||||
|
if dec.ReceiptHash != nil {
|
||||||
|
h.ReceiptHash = dec.ReceiptHash
|
||||||
|
}
|
||||||
|
if dec.Bloom != nil {
|
||||||
|
h.Bloom = *dec.Bloom
|
||||||
|
}
|
||||||
|
if dec.Difficulty != nil {
|
||||||
|
h.Difficulty = (*big.Int)(dec.Difficulty)
|
||||||
|
}
|
||||||
|
if dec.Number == nil {
|
||||||
|
return errors.New("missing required field 'number' for header")
|
||||||
|
}
|
||||||
|
h.Number = (*big.Int)(dec.Number)
|
||||||
|
if dec.GasLimit == nil {
|
||||||
|
return errors.New("missing required field 'gasLimit' for header")
|
||||||
|
}
|
||||||
|
h.GasLimit = uint64(*dec.GasLimit)
|
||||||
|
if dec.GasUsed != nil {
|
||||||
|
h.GasUsed = uint64(*dec.GasUsed)
|
||||||
|
}
|
||||||
|
if dec.Time == nil {
|
||||||
|
return errors.New("missing required field 'timestamp' for header")
|
||||||
|
}
|
||||||
|
h.Time = uint64(*dec.Time)
|
||||||
|
if dec.Extra != nil {
|
||||||
|
h.Extra = *dec.Extra
|
||||||
|
}
|
||||||
|
if dec.MixDigest != nil {
|
||||||
|
h.MixDigest = *dec.MixDigest
|
||||||
|
}
|
||||||
|
if dec.Nonce != nil {
|
||||||
|
h.Nonce = dec.Nonce
|
||||||
|
}
|
||||||
|
if dec.BaseFee != nil {
|
||||||
|
h.BaseFee = (*big.Int)(dec.BaseFee)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -48,7 +48,7 @@ func (r *result) MarshalJSON() ([]byte, error) {
|
|||||||
Error string `json:"error,omitempty"`
|
Error string `json:"error,omitempty"`
|
||||||
Address *common.Address `json:"address,omitempty"`
|
Address *common.Address `json:"address,omitempty"`
|
||||||
Hash *common.Hash `json:"hash,omitempty"`
|
Hash *common.Hash `json:"hash,omitempty"`
|
||||||
IntrinsicGas uint64 `json:"intrinsicGas,omitempty"`
|
IntrinsicGas hexutil.Uint64 `json:"intrinsicGas,omitempty"`
|
||||||
}
|
}
|
||||||
var out xx
|
var out xx
|
||||||
if r.Error != nil {
|
if r.Error != nil {
|
||||||
@ -60,7 +60,7 @@ func (r *result) MarshalJSON() ([]byte, error) {
|
|||||||
if r.Hash != (common.Hash{}) {
|
if r.Hash != (common.Hash{}) {
|
||||||
out.Hash = &r.Hash
|
out.Hash = &r.Hash
|
||||||
}
|
}
|
||||||
out.IntrinsicGas = r.IntrinsicGas
|
out.IntrinsicGas = hexutil.Uint64(r.IntrinsicGas)
|
||||||
return json.Marshal(out)
|
return json.Marshal(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ func Transaction(ctx *cli.Context) error {
|
|||||||
)
|
)
|
||||||
// Construct the chainconfig
|
// Construct the chainconfig
|
||||||
if cConf, _, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil {
|
if cConf, _, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil {
|
||||||
return NewError(ErrorVMConfig, fmt.Errorf("failed constructing chain configuration: %v", err))
|
return NewError(ErrorConfig, fmt.Errorf("failed constructing chain configuration: %v", err))
|
||||||
} else {
|
} else {
|
||||||
chainConfig = cConf
|
chainConfig = cConf
|
||||||
}
|
}
|
||||||
@ -154,6 +154,8 @@ func Transaction(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
// Validate <256bit fields
|
// Validate <256bit fields
|
||||||
switch {
|
switch {
|
||||||
|
case tx.Nonce()+1 < tx.Nonce():
|
||||||
|
r.Error = errors.New("nonce exceeds 2^64-1")
|
||||||
case tx.Value().BitLen() > 256:
|
case tx.Value().BitLen() > 256:
|
||||||
r.Error = errors.New("value exceeds 256 bits")
|
r.Error = errors.New("value exceeds 256 bits")
|
||||||
case tx.GasPrice().BitLen() > 256:
|
case tx.GasPrice().BitLen() > 256:
|
||||||
|
@ -43,11 +43,12 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ErrorEVM = 2
|
ErrorEVM = 2
|
||||||
ErrorVMConfig = 3
|
ErrorConfig = 3
|
||||||
ErrorMissingBlockhash = 4
|
ErrorMissingBlockhash = 4
|
||||||
|
|
||||||
ErrorJson = 10
|
ErrorJson = 10
|
||||||
ErrorIO = 11
|
ErrorIO = 11
|
||||||
|
ErrorRlp = 12
|
||||||
|
|
||||||
stdinSelector = "stdin"
|
stdinSelector = "stdin"
|
||||||
)
|
)
|
||||||
@ -88,28 +89,33 @@ func Transition(ctx *cli.Context) error {
|
|||||||
log.Root().SetHandler(glogger)
|
log.Root().SetHandler(glogger)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
tracer vm.EVMLogger
|
tracer vm.EVMLogger
|
||||||
baseDir = ""
|
|
||||||
)
|
)
|
||||||
var getTracer func(txIndex int, txHash common.Hash) (vm.EVMLogger, error)
|
var getTracer func(txIndex int, txHash common.Hash) (vm.EVMLogger, error)
|
||||||
|
|
||||||
// If user specified a basedir, make sure it exists
|
baseDir, err := createBasedir(ctx)
|
||||||
if ctx.IsSet(OutputBasedir.Name) {
|
if err != nil {
|
||||||
if base := ctx.String(OutputBasedir.Name); len(base) > 0 {
|
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
|
||||||
err := os.MkdirAll(base, 0755) // //rw-r--r--
|
|
||||||
if err != nil {
|
|
||||||
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
|
|
||||||
}
|
|
||||||
baseDir = base
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ctx.Bool(TraceFlag.Name) {
|
if ctx.Bool(TraceFlag.Name) {
|
||||||
|
if ctx.IsSet(TraceDisableMemoryFlag.Name) && ctx.IsSet(TraceEnableMemoryFlag.Name) {
|
||||||
|
return NewError(ErrorConfig, fmt.Errorf("can't use both flags --%s and --%s", TraceDisableMemoryFlag.Name, TraceEnableMemoryFlag.Name))
|
||||||
|
}
|
||||||
|
if ctx.IsSet(TraceDisableReturnDataFlag.Name) && ctx.IsSet(TraceEnableReturnDataFlag.Name) {
|
||||||
|
return NewError(ErrorConfig, fmt.Errorf("can't use both flags --%s and --%s", TraceDisableReturnDataFlag.Name, TraceEnableReturnDataFlag.Name))
|
||||||
|
}
|
||||||
|
if ctx.IsSet(TraceDisableMemoryFlag.Name) {
|
||||||
|
log.Warn(fmt.Sprintf("--%s has been deprecated in favour of --%s", TraceDisableMemoryFlag.Name, TraceEnableMemoryFlag.Name))
|
||||||
|
}
|
||||||
|
if ctx.IsSet(TraceDisableReturnDataFlag.Name) {
|
||||||
|
log.Warn(fmt.Sprintf("--%s has been deprecated in favour of --%s", TraceDisableReturnDataFlag.Name, TraceEnableReturnDataFlag.Name))
|
||||||
|
}
|
||||||
// Configure the EVM logger
|
// Configure the EVM logger
|
||||||
logConfig := &vm.LogConfig{
|
logConfig := &vm.LogConfig{
|
||||||
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
|
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
|
||||||
EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name),
|
EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name) || ctx.Bool(TraceEnableMemoryFlag.Name),
|
||||||
EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name),
|
EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name) || ctx.Bool(TraceEnableReturnDataFlag.Name),
|
||||||
Debug: true,
|
Debug: true,
|
||||||
}
|
}
|
||||||
var prevFile *os.File
|
var prevFile *os.File
|
||||||
@ -155,29 +161,17 @@ func Transition(ctx *cli.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if allocStr != stdinSelector {
|
if allocStr != stdinSelector {
|
||||||
inFile, err := os.Open(allocStr)
|
if err := readFile(allocStr, "alloc", &inputData.Alloc); err != nil {
|
||||||
if err != nil {
|
return err
|
||||||
return NewError(ErrorIO, fmt.Errorf("failed reading alloc file: %v", err))
|
|
||||||
}
|
|
||||||
defer inFile.Close()
|
|
||||||
decoder := json.NewDecoder(inFile)
|
|
||||||
if err := decoder.Decode(&inputData.Alloc); err != nil {
|
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling alloc-file: %v", err))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prestate.Pre = inputData.Alloc
|
prestate.Pre = inputData.Alloc
|
||||||
|
|
||||||
// Set the block environment
|
// Set the block environment
|
||||||
if envStr != stdinSelector {
|
if envStr != stdinSelector {
|
||||||
inFile, err := os.Open(envStr)
|
|
||||||
if err != nil {
|
|
||||||
return NewError(ErrorIO, fmt.Errorf("failed reading env file: %v", err))
|
|
||||||
}
|
|
||||||
defer inFile.Close()
|
|
||||||
decoder := json.NewDecoder(inFile)
|
|
||||||
var env stEnv
|
var env stEnv
|
||||||
if err := decoder.Decode(&env); err != nil {
|
if err := readFile(envStr, "env", &env); err != nil {
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling env-file: %v", err))
|
return err
|
||||||
}
|
}
|
||||||
inputData.Env = &env
|
inputData.Env = &env
|
||||||
}
|
}
|
||||||
@ -190,7 +184,7 @@ func Transition(ctx *cli.Context) error {
|
|||||||
// Construct the chainconfig
|
// Construct the chainconfig
|
||||||
var chainConfig *params.ChainConfig
|
var chainConfig *params.ChainConfig
|
||||||
if cConf, extraEips, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil {
|
if cConf, extraEips, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil {
|
||||||
return NewError(ErrorVMConfig, fmt.Errorf("failed constructing chain configuration: %v", err))
|
return NewError(ErrorConfig, fmt.Errorf("failed constructing chain configuration: %v", err))
|
||||||
} else {
|
} else {
|
||||||
chainConfig = cConf
|
chainConfig = cConf
|
||||||
vmConfig.ExtraEips = extraEips
|
vmConfig.ExtraEips = extraEips
|
||||||
@ -254,18 +248,18 @@ func Transition(ctx *cli.Context) error {
|
|||||||
// Sanity check, to not `panic` in state_transition
|
// Sanity check, to not `panic` in state_transition
|
||||||
if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) {
|
if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) {
|
||||||
if prestate.Env.BaseFee == nil {
|
if prestate.Env.BaseFee == nil {
|
||||||
return NewError(ErrorVMConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
|
return NewError(ErrorConfig, errors.New("EIP-1559 config but missing 'currentBaseFee' in env section"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if env := prestate.Env; env.Difficulty == nil {
|
if env := prestate.Env; env.Difficulty == nil {
|
||||||
// If difficulty was not provided by caller, we need to calculate it.
|
// If difficulty was not provided by caller, we need to calculate it.
|
||||||
switch {
|
switch {
|
||||||
case env.ParentDifficulty == nil:
|
case env.ParentDifficulty == nil:
|
||||||
return NewError(ErrorVMConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty"))
|
return NewError(ErrorConfig, errors.New("currentDifficulty was not provided, and cannot be calculated due to missing parentDifficulty"))
|
||||||
case env.Number == 0:
|
case env.Number == 0:
|
||||||
return NewError(ErrorVMConfig, errors.New("currentDifficulty needs to be provided for block number 0"))
|
return NewError(ErrorConfig, errors.New("currentDifficulty needs to be provided for block number 0"))
|
||||||
case env.Timestamp <= env.ParentTimestamp:
|
case env.Timestamp <= env.ParentTimestamp:
|
||||||
return NewError(ErrorVMConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)",
|
return NewError(ErrorConfig, fmt.Errorf("currentDifficulty cannot be calculated -- currentTime (%d) needs to be after parent time (%d)",
|
||||||
env.Timestamp, env.ParentTimestamp))
|
env.Timestamp, env.ParentTimestamp))
|
||||||
}
|
}
|
||||||
prestate.Env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp,
|
prestate.Env.Difficulty = calcDifficulty(chainConfig, env.Number, env.Timestamp,
|
||||||
@ -286,27 +280,34 @@ func Transition(ctx *cli.Context) error {
|
|||||||
// txWithKey is a helper-struct, to allow us to use the types.Transaction along with
|
// txWithKey is a helper-struct, to allow us to use the types.Transaction along with
|
||||||
// a `secretKey`-field, for input
|
// a `secretKey`-field, for input
|
||||||
type txWithKey struct {
|
type txWithKey struct {
|
||||||
key *ecdsa.PrivateKey
|
key *ecdsa.PrivateKey
|
||||||
tx *types.Transaction
|
tx *types.Transaction
|
||||||
|
protected bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *txWithKey) UnmarshalJSON(input []byte) error {
|
func (t *txWithKey) UnmarshalJSON(input []byte) error {
|
||||||
// Read the secretKey, if present
|
// Read the metadata, if present
|
||||||
type sKey struct {
|
type txMetadata struct {
|
||||||
Key *common.Hash `json:"secretKey"`
|
Key *common.Hash `json:"secretKey"`
|
||||||
|
Protected *bool `json:"protected"`
|
||||||
}
|
}
|
||||||
var key sKey
|
var data txMetadata
|
||||||
if err := json.Unmarshal(input, &key); err != nil {
|
if err := json.Unmarshal(input, &data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if key.Key != nil {
|
if data.Key != nil {
|
||||||
k := key.Key.Hex()[2:]
|
k := data.Key.Hex()[2:]
|
||||||
if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
|
if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
t.key = ecdsaKey
|
t.key = ecdsaKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if data.Protected != nil {
|
||||||
|
t.protected = *data.Protected
|
||||||
|
} else {
|
||||||
|
t.protected = true
|
||||||
|
}
|
||||||
// Now, read the transaction itself
|
// Now, read the transaction itself
|
||||||
var tx types.Transaction
|
var tx types.Transaction
|
||||||
if err := json.Unmarshal(input, &tx); err != nil {
|
if err := json.Unmarshal(input, &tx); err != nil {
|
||||||
@ -335,7 +336,15 @@ func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Tran
|
|||||||
v, r, s := tx.RawSignatureValues()
|
v, r, s := tx.RawSignatureValues()
|
||||||
if key != nil && v.BitLen()+r.BitLen()+s.BitLen() == 0 {
|
if key != nil && v.BitLen()+r.BitLen()+s.BitLen() == 0 {
|
||||||
// This transaction needs to be signed
|
// This transaction needs to be signed
|
||||||
signed, err := types.SignTx(tx, signer, key)
|
var (
|
||||||
|
signed *types.Transaction
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if txWithKey.protected {
|
||||||
|
signed, err = types.SignTx(tx, signer, key)
|
||||||
|
} else {
|
||||||
|
signed, err = types.SignTx(tx, types.FrontierSigner{}, key)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
||||||
}
|
}
|
||||||
|
54
cmd/evm/internal/t8ntool/utils.go
Normal file
54
cmd/evm/internal/t8ntool/utils.go
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// 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"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gopkg.in/urfave/cli.v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// readFile reads the json-data in the provided path and marshals into dest.
|
||||||
|
func readFile(path, desc string, dest interface{}) error {
|
||||||
|
inFile, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return NewError(ErrorIO, fmt.Errorf("failed reading %s file: %v", desc, err))
|
||||||
|
}
|
||||||
|
defer inFile.Close()
|
||||||
|
decoder := json.NewDecoder(inFile)
|
||||||
|
if err := decoder.Decode(dest); err != nil {
|
||||||
|
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling %s file: %v", desc, err))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createBasedir makes sure the basedir exists, if user specified one.
|
||||||
|
func createBasedir(ctx *cli.Context) (string, error) {
|
||||||
|
baseDir := ""
|
||||||
|
if ctx.IsSet(OutputBasedir.Name) {
|
||||||
|
if base := ctx.String(OutputBasedir.Name); len(base) > 0 {
|
||||||
|
err := os.MkdirAll(base, 0755) // //rw-r--r--
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
baseDir = base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return baseDir, nil
|
||||||
|
}
|
@ -139,8 +139,10 @@ var stateTransitionCommand = cli.Command{
|
|||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
t8ntool.TraceFlag,
|
t8ntool.TraceFlag,
|
||||||
t8ntool.TraceDisableMemoryFlag,
|
t8ntool.TraceDisableMemoryFlag,
|
||||||
|
t8ntool.TraceEnableMemoryFlag,
|
||||||
t8ntool.TraceDisableStackFlag,
|
t8ntool.TraceDisableStackFlag,
|
||||||
t8ntool.TraceDisableReturnDataFlag,
|
t8ntool.TraceDisableReturnDataFlag,
|
||||||
|
t8ntool.TraceEnableReturnDataFlag,
|
||||||
t8ntool.OutputBasedir,
|
t8ntool.OutputBasedir,
|
||||||
t8ntool.OutputAllocFlag,
|
t8ntool.OutputAllocFlag,
|
||||||
t8ntool.OutputResultFlag,
|
t8ntool.OutputResultFlag,
|
||||||
@ -167,6 +169,25 @@ var transactionCommand = cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var blockBuilderCommand = cli.Command{
|
||||||
|
Name: "block-builder",
|
||||||
|
Aliases: []string{"b11r"},
|
||||||
|
Usage: "builds a block",
|
||||||
|
Action: t8ntool.BuildBlock,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
t8ntool.OutputBasedir,
|
||||||
|
t8ntool.OutputBlockFlag,
|
||||||
|
t8ntool.InputHeaderFlag,
|
||||||
|
t8ntool.InputOmmersFlag,
|
||||||
|
t8ntool.InputTxsRlpFlag,
|
||||||
|
t8ntool.SealCliqueFlag,
|
||||||
|
t8ntool.SealEthashFlag,
|
||||||
|
t8ntool.SealEthashDirFlag,
|
||||||
|
t8ntool.SealEthashModeFlag,
|
||||||
|
t8ntool.VerbosityFlag,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
BenchFlag,
|
BenchFlag,
|
||||||
@ -200,6 +221,7 @@ func init() {
|
|||||||
stateTestCommand,
|
stateTestCommand,
|
||||||
stateTransitionCommand,
|
stateTransitionCommand,
|
||||||
transactionCommand,
|
transactionCommand,
|
||||||
|
blockBuilderCommand,
|
||||||
}
|
}
|
||||||
cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
|
cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ func TestT8n(t *testing.T) {
|
|||||||
output: t8nOutput{alloc: true, result: true},
|
output: t8nOutput{alloc: true, result: true},
|
||||||
expExitCode: 4,
|
expExitCode: 4,
|
||||||
},
|
},
|
||||||
{ // Ommer test
|
{ // Uncle test
|
||||||
base: "./testdata/5",
|
base: "./testdata/5",
|
||||||
input: t8nInput{
|
input: t8nInput{
|
||||||
"alloc.json", "txs.json", "env.json", "Byzantium", "0x80",
|
"alloc.json", "txs.json", "env.json", "Byzantium", "0x80",
|
||||||
@ -171,7 +171,7 @@ func TestT8n(t *testing.T) {
|
|||||||
output: t8nOutput{result: true},
|
output: t8nOutput{result: true},
|
||||||
expOut: "exp2.json",
|
expOut: "exp2.json",
|
||||||
},
|
},
|
||||||
{ // Difficulty calculation - with uncles + Berlin
|
{ // Difficulty calculation - with ommers + Berlin
|
||||||
base: "./testdata/14",
|
base: "./testdata/14",
|
||||||
input: t8nInput{
|
input: t8nInput{
|
||||||
"alloc.json", "txs.json", "env.uncles.json", "Berlin", "",
|
"alloc.json", "txs.json", "env.uncles.json", "Berlin", "",
|
||||||
@ -195,6 +195,14 @@ func TestT8n(t *testing.T) {
|
|||||||
output: t8nOutput{result: true},
|
output: t8nOutput{result: true},
|
||||||
expOut: "exp_arrowglacier.json",
|
expOut: "exp_arrowglacier.json",
|
||||||
},
|
},
|
||||||
|
{ // Sign unprotected (pre-EIP155) transaction
|
||||||
|
base: "./testdata/23",
|
||||||
|
input: t8nInput{
|
||||||
|
"alloc.json", "txs.json", "env.json", "Berlin", "",
|
||||||
|
},
|
||||||
|
output: t8nOutput{result: true},
|
||||||
|
expOut: "exp.json",
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
|
|
||||||
args := []string{"t8n"}
|
args := []string{"t8n"}
|
||||||
@ -336,6 +344,126 @@ func TestT9n(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type b11rInput struct {
|
||||||
|
inEnv string
|
||||||
|
inOmmersRlp string
|
||||||
|
inTxsRlp string
|
||||||
|
inClique string
|
||||||
|
ethash bool
|
||||||
|
ethashMode string
|
||||||
|
ethashDir string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (args *b11rInput) get(base string) []string {
|
||||||
|
var out []string
|
||||||
|
if opt := args.inEnv; opt != "" {
|
||||||
|
out = append(out, "--input.header")
|
||||||
|
out = append(out, fmt.Sprintf("%v/%v", base, opt))
|
||||||
|
}
|
||||||
|
if opt := args.inOmmersRlp; opt != "" {
|
||||||
|
out = append(out, "--input.ommers")
|
||||||
|
out = append(out, fmt.Sprintf("%v/%v", base, opt))
|
||||||
|
}
|
||||||
|
if opt := args.inTxsRlp; opt != "" {
|
||||||
|
out = append(out, "--input.txs")
|
||||||
|
out = append(out, fmt.Sprintf("%v/%v", base, opt))
|
||||||
|
}
|
||||||
|
if opt := args.inClique; opt != "" {
|
||||||
|
out = append(out, "--seal.clique")
|
||||||
|
out = append(out, fmt.Sprintf("%v/%v", base, opt))
|
||||||
|
}
|
||||||
|
if args.ethash {
|
||||||
|
out = append(out, "--seal.ethash")
|
||||||
|
}
|
||||||
|
if opt := args.ethashMode; opt != "" {
|
||||||
|
out = append(out, "--seal.ethash.mode")
|
||||||
|
out = append(out, fmt.Sprintf("%v/%v", base, opt))
|
||||||
|
}
|
||||||
|
if opt := args.ethashDir; opt != "" {
|
||||||
|
out = append(out, "--seal.ethash.dir")
|
||||||
|
out = append(out, fmt.Sprintf("%v/%v", base, opt))
|
||||||
|
}
|
||||||
|
out = append(out, "--output.block")
|
||||||
|
out = append(out, "stdout")
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestB11r(t *testing.T) {
|
||||||
|
tt := new(testT8n)
|
||||||
|
tt.TestCmd = cmdtest.NewTestCmd(t, tt)
|
||||||
|
for i, tc := range []struct {
|
||||||
|
base string
|
||||||
|
input b11rInput
|
||||||
|
expExitCode int
|
||||||
|
expOut string
|
||||||
|
}{
|
||||||
|
{ // unsealed block
|
||||||
|
base: "./testdata/20",
|
||||||
|
input: b11rInput{
|
||||||
|
inEnv: "header.json",
|
||||||
|
inOmmersRlp: "ommers.json",
|
||||||
|
inTxsRlp: "txs.rlp",
|
||||||
|
},
|
||||||
|
expOut: "exp.json",
|
||||||
|
},
|
||||||
|
{ // ethash test seal
|
||||||
|
base: "./testdata/21",
|
||||||
|
input: b11rInput{
|
||||||
|
inEnv: "header.json",
|
||||||
|
inOmmersRlp: "ommers.json",
|
||||||
|
inTxsRlp: "txs.rlp",
|
||||||
|
},
|
||||||
|
expOut: "exp.json",
|
||||||
|
},
|
||||||
|
{ // clique test seal
|
||||||
|
base: "./testdata/21",
|
||||||
|
input: b11rInput{
|
||||||
|
inEnv: "header.json",
|
||||||
|
inOmmersRlp: "ommers.json",
|
||||||
|
inTxsRlp: "txs.rlp",
|
||||||
|
inClique: "clique.json",
|
||||||
|
},
|
||||||
|
expOut: "exp-clique.json",
|
||||||
|
},
|
||||||
|
{ // block with ommers
|
||||||
|
base: "./testdata/22",
|
||||||
|
input: b11rInput{
|
||||||
|
inEnv: "header.json",
|
||||||
|
inOmmersRlp: "ommers.json",
|
||||||
|
inTxsRlp: "txs.rlp",
|
||||||
|
},
|
||||||
|
expOut: "exp.json",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
|
||||||
|
args := []string{"b11r"}
|
||||||
|
args = append(args, tc.input.get(tc.base)...)
|
||||||
|
|
||||||
|
tt.Run("evm-test", args...)
|
||||||
|
tt.Logf("args:\n go run . %v\n", strings.Join(args, " "))
|
||||||
|
// Compare the expected output, if provided
|
||||||
|
if tc.expOut != "" {
|
||||||
|
want, err := os.ReadFile(fmt.Sprintf("%v/%v", tc.base, tc.expOut))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("test %d: could not read expected output: %v", i, err)
|
||||||
|
}
|
||||||
|
have := tt.Output()
|
||||||
|
ok, err := cmpJson(have, want)
|
||||||
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
t.Logf(string(have))
|
||||||
|
t.Fatalf("test %d, json parsing failed: %v", i, err)
|
||||||
|
case !ok:
|
||||||
|
t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tt.WaitExit()
|
||||||
|
if have, want := tt.ExitStatus(), tc.expExitCode; have != want {
|
||||||
|
t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// cmpJson compares the JSON in two byte slices.
|
// cmpJson compares the JSON in two byte slices.
|
||||||
func cmpJson(a, b []byte) (bool, error) {
|
func cmpJson(a, b []byte) (bool, error) {
|
||||||
var j, j2 interface{}
|
var j, j2 interface{}
|
||||||
|
7
cmd/evm/testdata/1/exp.json
vendored
7
cmd/evm/testdata/1/exp.json
vendored
@ -15,7 +15,7 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13",
|
"stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13",
|
||||||
"txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d",
|
"txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d",
|
||||||
"receiptRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
|
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receipts": [
|
"receipts": [
|
||||||
@ -38,6 +38,7 @@
|
|||||||
"error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
"error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"currentDifficulty": "0x20000"
|
"currentDifficulty": "0x20000",
|
||||||
|
"gasUsed": "0x5208"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
cmd/evm/testdata/13/exp2.json
vendored
5
cmd/evm/testdata/13/exp2.json
vendored
@ -2,7 +2,7 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61",
|
"stateRoot": "0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61",
|
||||||
"txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d",
|
"txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d",
|
||||||
"receiptRoot": "0xa532a08aa9f62431d6fe5d924951b8efb86ed3c54d06fee77788c3767dd13420",
|
"receiptsRoot": "0xa532a08aa9f62431d6fe5d924951b8efb86ed3c54d06fee77788c3767dd13420",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receipts": [
|
"receipts": [
|
||||||
@ -33,6 +33,7 @@
|
|||||||
"transactionIndex": "0x1"
|
"transactionIndex": "0x1"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"currentDifficulty": "0x20000"
|
"currentDifficulty": "0x20000",
|
||||||
|
"gasUsed": "0x109a0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
cmd/evm/testdata/14/exp.json
vendored
7
cmd/evm/testdata/14/exp.json
vendored
@ -2,10 +2,11 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"currentDifficulty": "0x2000020000000",
|
"currentDifficulty": "0x2000020000000",
|
||||||
"receipts": []
|
"receipts": [],
|
||||||
|
"gasUsed": "0x0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
cmd/evm/testdata/14/exp2.json
vendored
7
cmd/evm/testdata/14/exp2.json
vendored
@ -2,10 +2,11 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receipts": [],
|
"receipts": [],
|
||||||
"currentDifficulty": "0x1ff8020000000"
|
"currentDifficulty": "0x1ff8020000000",
|
||||||
|
"gasUsed": "0x0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
cmd/evm/testdata/14/exp_berlin.json
vendored
7
cmd/evm/testdata/14/exp_berlin.json
vendored
@ -2,10 +2,11 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receipts": [],
|
"receipts": [],
|
||||||
"currentDifficulty": "0x1ff9000000000"
|
"currentDifficulty": "0x1ff9000000000",
|
||||||
|
"gasUsed": "0x0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
cmd/evm/testdata/15/exp2.json
vendored
4
cmd/evm/testdata/15/exp2.json
vendored
@ -2,11 +2,11 @@
|
|||||||
{
|
{
|
||||||
"address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
|
"address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
|
||||||
"hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
"hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||||
"intrinsicGas": 21000
|
"intrinsicGas": "0x5208"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
|
"address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
|
||||||
"hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
"hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||||
"intrinsicGas": 21000
|
"intrinsicGas": "0x5208"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
4
cmd/evm/testdata/16/exp.json
vendored
4
cmd/evm/testdata/16/exp.json
vendored
@ -2,12 +2,12 @@
|
|||||||
{
|
{
|
||||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||||
"hash": "0x7cc3d1a8540a44736750f03bb4d85c0113be4b3472a71bf82241a3b261b479e6",
|
"hash": "0x7cc3d1a8540a44736750f03bb4d85c0113be4b3472a71bf82241a3b261b479e6",
|
||||||
"intrinsicGas": 21000
|
"intrinsicGas": "0x5208"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"error": "intrinsic gas too low: have 82, want 21000",
|
"error": "intrinsic gas too low: have 82, want 21000",
|
||||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||||
"hash": "0x3b2d2609e4361562edb9169314f4c05afc6dbf5d706bf9dda5abe242ab76a22b",
|
"hash": "0x3b2d2609e4361562edb9169314f4c05afc6dbf5d706bf9dda5abe242ab76a22b",
|
||||||
"intrinsicGas": 21000
|
"intrinsicGas": "0x5208"
|
||||||
}
|
}
|
||||||
]
|
]
|
4
cmd/evm/testdata/17/exp.json
vendored
4
cmd/evm/testdata/17/exp.json
vendored
@ -3,13 +3,13 @@
|
|||||||
"error": "value exceeds 256 bits",
|
"error": "value exceeds 256 bits",
|
||||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||||
"hash": "0xfbd91685dcbf8172f0e8c53e2ddbb4d26707840da6b51a74371f62a33868fd82",
|
"hash": "0xfbd91685dcbf8172f0e8c53e2ddbb4d26707840da6b51a74371f62a33868fd82",
|
||||||
"intrinsicGas": 21000
|
"intrinsicGas": "0x5208"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"error": "gasPrice exceeds 256 bits",
|
"error": "gasPrice exceeds 256 bits",
|
||||||
"address": "0x1b57ccef1fe5fb73f1e64530fb4ebd9cf1655964",
|
"address": "0x1b57ccef1fe5fb73f1e64530fb4ebd9cf1655964",
|
||||||
"hash": "0x45dc05035cada83748e4c1fe617220106b331eca054f44c2304d5654a9fb29d5",
|
"hash": "0x45dc05035cada83748e4c1fe617220106b331eca054f44c2304d5654a9fb29d5",
|
||||||
"intrinsicGas": 21000
|
"intrinsicGas": "0x5208"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"error": "invalid transaction v, r, s values",
|
"error": "invalid transaction v, r, s values",
|
||||||
|
7
cmd/evm/testdata/19/exp_arrowglacier.json
vendored
7
cmd/evm/testdata/19/exp_arrowglacier.json
vendored
@ -2,10 +2,11 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"currentDifficulty": "0x2000000200000",
|
"currentDifficulty": "0x2000000200000",
|
||||||
"receipts": []
|
"receipts": [],
|
||||||
|
"gasUsed": "0x0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
cmd/evm/testdata/19/exp_london.json
vendored
7
cmd/evm/testdata/19/exp_london.json
vendored
@ -2,10 +2,11 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"currentDifficulty": "0x2000080000000",
|
"currentDifficulty": "0x2000080000000",
|
||||||
"receipts": []
|
"receipts": [],
|
||||||
|
"gasUsed": "0x0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
cmd/evm/testdata/20/exp.json
vendored
Normal file
4
cmd/evm/testdata/20/exp.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"rlp": "0xf902d9f90211a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e997a23b159e2e2a5ce72333262972374b15425ca0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e99476574682f76312e302e312f6c696e75782f676f312e342e32a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf8897435673d874f7c8f8c2f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600c0",
|
||||||
|
"hash": "0xaba9a3b6a4e96e9ecffcadaa5a2ae0589359455617535cd86589fe1dd26fe899"
|
||||||
|
}
|
14
cmd/evm/testdata/20/header.json
vendored
Normal file
14
cmd/evm/testdata/20/header.json
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e",
|
||||||
|
"miner": "0xe997a23b159e2e2a5ce72333262972374b15425c",
|
||||||
|
"stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"difficulty": "0x1000",
|
||||||
|
"number": "0xc3be",
|
||||||
|
"gasLimit": "0x50785",
|
||||||
|
"gasUsed": "0x0",
|
||||||
|
"timestamp": "0x55c5277e",
|
||||||
|
"extraData": "0x476574682f76312e302e312f6c696e75782f676f312e342e32",
|
||||||
|
"mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf",
|
||||||
|
"nonce": "0x97435673d874f7c8"
|
||||||
|
}
|
1
cmd/evm/testdata/20/ommers.json
vendored
Normal file
1
cmd/evm/testdata/20/ommers.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
11
cmd/evm/testdata/20/readme.md
vendored
Normal file
11
cmd/evm/testdata/20/readme.md
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Block building
|
||||||
|
|
||||||
|
This test shows how `b11r` can be used to assemble an unsealed block.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ go run . b11r --input.header=testdata/20/header.json --input.txs=testdata/20/txs.rlp --input.ommers=testdata/20/ommers.json --output.block=stdout
|
||||||
|
{
|
||||||
|
"rlp": "0xf90216f90211a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e997a23b159e2e2a5ce72333262972374b15425ca0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e99476574682f76312e302e312f6c696e75782f676f312e342e32a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf8897435673d874f7c8c0c0",
|
||||||
|
"hash": "0xaba9a3b6a4e96e9ecffcadaa5a2ae0589359455617535cd86589fe1dd26fe899"
|
||||||
|
}
|
||||||
|
```
|
1
cmd/evm/testdata/20/txs.rlp
vendored
Normal file
1
cmd/evm/testdata/20/txs.rlp
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"0xf8c2f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600"
|
6
cmd/evm/testdata/21/clique.json
vendored
Normal file
6
cmd/evm/testdata/21/clique.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||||
|
"voted": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
"authorize": false,
|
||||||
|
"vanity": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||||
|
}
|
4
cmd/evm/testdata/21/exp-clique.json
vendored
Normal file
4
cmd/evm/testdata/21/exp-clique.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"rlp": "0xf9025ff9025aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277eb861aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac540a67aaee364005841da84f488f6b6d0116dfb5103d091402c81a163d5f66666595e37f56f196d8c5c98da714dbfae68d6b7e1790cc734a20ec6ce52213ad800a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88ffffffffffffffffc0c0",
|
||||||
|
"hash": "0x71c59102cc805dbe8741e1210ebe229a321eff144ac7276006fefe39e8357dc7"
|
||||||
|
}
|
4
cmd/evm/testdata/21/exp.json
vendored
Normal file
4
cmd/evm/testdata/21/exp.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"rlp": "0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0",
|
||||||
|
"hash": "0x801411e9f6609a659825690d13e4f75a3cfe9143952fa2d9573f3b0a5eb9ebbb"
|
||||||
|
}
|
11
cmd/evm/testdata/21/header.json
vendored
Normal file
11
cmd/evm/testdata/21/header.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e",
|
||||||
|
"stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"difficulty": "0x1000",
|
||||||
|
"number": "0xc3be",
|
||||||
|
"gasLimit": "0x50785",
|
||||||
|
"gasUsed": "0x0",
|
||||||
|
"timestamp": "0x55c5277e",
|
||||||
|
"mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf"
|
||||||
|
}
|
1
cmd/evm/testdata/21/ommers.json
vendored
Normal file
1
cmd/evm/testdata/21/ommers.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[]
|
23
cmd/evm/testdata/21/readme.md
vendored
Normal file
23
cmd/evm/testdata/21/readme.md
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Sealed block building
|
||||||
|
|
||||||
|
This test shows how `b11r` can be used to assemble a sealed block.
|
||||||
|
|
||||||
|
## Ethash
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ go run . b11r --input.header=testdata/21/header.json --input.txs=testdata/21/txs.rlp --input.ommers=testdata/21/ommers.json --seal.ethash --seal.ethash.mode=test --output.block=stdout
|
||||||
|
{
|
||||||
|
"rlp": "0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0",
|
||||||
|
"hash": "0x801411e9f6609a659825690d13e4f75a3cfe9143952fa2d9573f3b0a5eb9ebbb"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Clique
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ go run . b11r --input.header=testdata/21/header.json --input.txs=testdata/21/txs.rlp --input.ommers=testdata/21/ommers.json --seal.clique=testdata/21/clique.json --output.block=stdout
|
||||||
|
{
|
||||||
|
"rlp": "0xf9025ff9025aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277eb861aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac540a67aaee364005841da84f488f6b6d0116dfb5103d091402c81a163d5f66666595e37f56f196d8c5c98da714dbfae68d6b7e1790cc734a20ec6ce52213ad800a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88ffffffffffffffffc0c0",
|
||||||
|
"hash": "0x71c59102cc805dbe8741e1210ebe229a321eff144ac7276006fefe39e8357dc7"
|
||||||
|
}
|
||||||
|
```
|
1
cmd/evm/testdata/21/txs.rlp
vendored
Normal file
1
cmd/evm/testdata/21/txs.rlp
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"c0"
|
4
cmd/evm/testdata/22/exp-clique.json
vendored
Normal file
4
cmd/evm/testdata/22/exp-clique.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"rlp": "0xf9025ff9025aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277eb861aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac540a67aaee364005841da84f488f6b6d0116dfb5103d091402c81a163d5f66666595e37f56f196d8c5c98da714dbfae68d6b7e1790cc734a20ec6ce52213ad800a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88ffffffffffffffffc0c0",
|
||||||
|
"hash": "0x71c59102cc805dbe8741e1210ebe229a321eff144ac7276006fefe39e8357dc7"
|
||||||
|
}
|
4
cmd/evm/testdata/22/exp.json
vendored
Normal file
4
cmd/evm/testdata/22/exp.json
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"rlp": "0xf905f5f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea06eb9f0c3cd68c9e97134e6725d12b1f1d8f0644458da6870a37ff84c908fb1e7940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0f903f6f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000",
|
||||||
|
"hash": "0xd9a81c8fcd57a7f2a0d2c375eff6ad192c30c3729a271303f0a9a7e1b357e755"
|
||||||
|
}
|
11
cmd/evm/testdata/22/header.json
vendored
Normal file
11
cmd/evm/testdata/22/header.json
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e",
|
||||||
|
"stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"difficulty": "0x1000",
|
||||||
|
"number": "0xc3be",
|
||||||
|
"gasLimit": "0x50785",
|
||||||
|
"gasUsed": "0x0",
|
||||||
|
"timestamp": "0x55c5277e",
|
||||||
|
"mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf"
|
||||||
|
}
|
1
cmd/evm/testdata/22/ommers.json
vendored
Normal file
1
cmd/evm/testdata/22/ommers.json
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
["0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0","0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0"]
|
11
cmd/evm/testdata/22/readme.md
vendored
Normal file
11
cmd/evm/testdata/22/readme.md
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Building blocks with ommers
|
||||||
|
|
||||||
|
This test shows how `b11r` can chain together ommer assembles into a canonical block.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ echo "{ \"ommers\": [`go run . b11r --input.header=testdata/22/header.json --input.txs=testdata/22/txs.rlp --output.block=stdout | jq '.[\"rlp\"]'`,`go run . b11r --input.header=testdata/22/header.json --input.txs=testdata/22/txs.rlp --output.block=stdout | jq '.[\"rlp\"]'`]}" | go run . b11r --input.header=testdata/22/header.json --input.txs=testdata/22/txs.rlp --input.ommers=stdin --output.block=stdout
|
||||||
|
{
|
||||||
|
"rlp": "0xf905f5f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea06eb9f0c3cd68c9e97134e6725d12b1f1d8f0644458da6870a37ff84c908fb1e7940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0f903f6f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000",
|
||||||
|
"hash": "0xd9a81c8fcd57a7f2a0d2c375eff6ad192c30c3729a271303f0a9a7e1b357e755"
|
||||||
|
}
|
||||||
|
```
|
1
cmd/evm/testdata/22/txs.rlp
vendored
Normal file
1
cmd/evm/testdata/22/txs.rlp
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
"c0"
|
16
cmd/evm/testdata/23/alloc.json
vendored
Normal file
16
cmd/evm/testdata/23/alloc.json
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
|
||||||
|
"balance" : "0x0de0b6b3a7640000",
|
||||||
|
"code" : "0x6001",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||||
|
"balance" : "0x0de0b6b3a7640000",
|
||||||
|
"code" : "0x",
|
||||||
|
"nonce" : "0x00",
|
||||||
|
"storage" : {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
7
cmd/evm/testdata/23/env.json
vendored
Normal file
7
cmd/evm/testdata/23/env.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||||
|
"currentDifficulty" : "0x020000",
|
||||||
|
"currentGasLimit" : "0x3b9aca00",
|
||||||
|
"currentNumber" : "0x05",
|
||||||
|
"currentTimestamp" : "0x03e8"
|
||||||
|
}
|
25
cmd/evm/testdata/23/exp.json
vendored
Normal file
25
cmd/evm/testdata/23/exp.json
vendored
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"result": {
|
||||||
|
"stateRoot": "0x65334305e4accfa18352deb24f007b837b5036425b0712cf0e65a43bfa95154d",
|
||||||
|
"txRoot": "0x75e61774a2ff58cbe32653420256c7f44bc715715a423b0b746d5c622979af6b",
|
||||||
|
"receiptsRoot": "0xf951f9396af203499cc7d379715a9110323de73967c5700e2f424725446a3c76",
|
||||||
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"receipts": [
|
||||||
|
{
|
||||||
|
"root": "0x",
|
||||||
|
"status": "0x1",
|
||||||
|
"cumulativeGasUsed": "0x520b",
|
||||||
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"logs": null,
|
||||||
|
"transactionHash": "0x72fadbef39cd251a437eea619cfeda752271a5faaaa2147df012e112159ffb81",
|
||||||
|
"contractAddress": "0x0000000000000000000000000000000000000000",
|
||||||
|
"gasUsed": "0x520b",
|
||||||
|
"blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"transactionIndex": "0x0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"currentDifficulty": "0x20000",
|
||||||
|
"gasUsed": "0x520b"
|
||||||
|
}
|
||||||
|
}
|
1
cmd/evm/testdata/23/readme.md
vendored
Normal file
1
cmd/evm/testdata/23/readme.md
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
These files examplify how to sign a transaction using the pre-EIP155 scheme.
|
15
cmd/evm/testdata/23/txs.json
vendored
Normal file
15
cmd/evm/testdata/23/txs.json
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"input" : "0x",
|
||||||
|
"gas" : "0x5f5e100",
|
||||||
|
"gasPrice" : "0x1",
|
||||||
|
"nonce" : "0x0",
|
||||||
|
"to" : "0x095e7baea6a6c7c4c2dfeb977efac326af552d87",
|
||||||
|
"value" : "0x186a0",
|
||||||
|
"v" : "0x0",
|
||||||
|
"r" : "0x0",
|
||||||
|
"s" : "0x0",
|
||||||
|
"secretKey" : "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||||
|
"protected": false
|
||||||
|
}
|
||||||
|
]
|
5
cmd/evm/testdata/3/exp.json
vendored
5
cmd/evm/testdata/3/exp.json
vendored
@ -15,7 +15,7 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0xb7341da3f9f762a6884eaa186c32942734c146b609efee11c4b0214c44857ea1",
|
"stateRoot": "0xb7341da3f9f762a6884eaa186c32942734c146b609efee11c4b0214c44857ea1",
|
||||||
"txRoot": "0x75e61774a2ff58cbe32653420256c7f44bc715715a423b0b746d5c622979af6b",
|
"txRoot": "0x75e61774a2ff58cbe32653420256c7f44bc715715a423b0b746d5c622979af6b",
|
||||||
"receiptRoot": "0xd0d26df80374a327c025d405ebadc752b1bbd089d864801ae78ab704bcad8086",
|
"receiptsRoot": "0xd0d26df80374a327c025d405ebadc752b1bbd089d864801ae78ab704bcad8086",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receipts": [
|
"receipts": [
|
||||||
@ -32,6 +32,7 @@
|
|||||||
"transactionIndex": "0x0"
|
"transactionIndex": "0x0"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"currentDifficulty": "0x20000"
|
"currentDifficulty": "0x20000",
|
||||||
|
"gasUsed": "0x521f"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
cmd/evm/testdata/5/exp.json
vendored
5
cmd/evm/testdata/5/exp.json
vendored
@ -13,10 +13,11 @@
|
|||||||
"result": {
|
"result": {
|
||||||
"stateRoot": "0xa7312add33811645c6aa65d928a1a4f49d65d448801912c069a0aa8fe9c1f393",
|
"stateRoot": "0xa7312add33811645c6aa65d928a1a4f49d65d448801912c069a0aa8fe9c1f393",
|
||||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"receipts": [],
|
"receipts": [],
|
||||||
"currentDifficulty": "0x20000"
|
"currentDifficulty": "0x20000",
|
||||||
|
"gasUsed": "0x0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,7 @@ Remove blockchain and state databases`,
|
|||||||
ArgsUsage: "<prefix> <start>",
|
ArgsUsage: "<prefix> <start>",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.DataDirFlag,
|
utils.DataDirFlag,
|
||||||
|
utils.AncientFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
utils.MainnetFlag,
|
utils.MainnetFlag,
|
||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
|
@ -43,7 +43,8 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/plugins"
|
"github.com/ethereum/go-ethereum/plugins"
|
||||||
"github.com/ethereum/go-ethereum/plugins/wrappers"
|
"github.com/ethereum/go-ethereum/plugins/wrappers"
|
||||||
|
|
||||||
// Force-load the native, to trigger registration
|
// Force-load the tracer engines to trigger registration
|
||||||
|
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
||||||
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||||
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
"gopkg.in/urfave/cli.v1"
|
||||||
@ -142,6 +143,7 @@ var (
|
|||||||
utils.MainnetFlag,
|
utils.MainnetFlag,
|
||||||
utils.DeveloperFlag,
|
utils.DeveloperFlag,
|
||||||
utils.DeveloperPeriodFlag,
|
utils.DeveloperPeriodFlag,
|
||||||
|
utils.DeveloperGasLimitFlag,
|
||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.SepoliaFlag,
|
utils.SepoliaFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
|
@ -75,6 +75,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
|
|||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
utils.DeveloperFlag,
|
utils.DeveloperFlag,
|
||||||
utils.DeveloperPeriodFlag,
|
utils.DeveloperPeriodFlag,
|
||||||
|
utils.DeveloperGasLimitFlag,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -167,6 +167,11 @@ var (
|
|||||||
Name: "dev.period",
|
Name: "dev.period",
|
||||||
Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
|
Usage: "Block period to use in developer mode (0 = mine only if transaction pending)",
|
||||||
}
|
}
|
||||||
|
DeveloperGasLimitFlag = cli.Uint64Flag{
|
||||||
|
Name: "dev.gaslimit",
|
||||||
|
Usage: "Initial block gas limit",
|
||||||
|
Value: 11500000,
|
||||||
|
}
|
||||||
IdentityFlag = cli.StringFlag{
|
IdentityFlag = cli.StringFlag{
|
||||||
Name: "identity",
|
Name: "identity",
|
||||||
Usage: "Custom node name",
|
Usage: "Custom node name",
|
||||||
@ -1661,7 +1666,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||||||
log.Info("Using developer account", "address", developer.Address)
|
log.Info("Using developer account", "address", developer.Address)
|
||||||
|
|
||||||
// Create a new developer genesis block or reuse existing one
|
// Create a new developer genesis block or reuse existing one
|
||||||
cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address)
|
cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), ctx.GlobalUint64(DeveloperGasLimitFlag.Name), developer.Address)
|
||||||
if ctx.GlobalIsSet(DataDirFlag.Name) {
|
if ctx.GlobalIsSet(DataDirFlag.Name) {
|
||||||
// Check if we have an already initialized chain and fall back to
|
// Check if we have an already initialized chain and fall back to
|
||||||
// that if so. Otherwise we need to generate a new genesis spec.
|
// that if so. Otherwise we need to generate a new genesis spec.
|
||||||
|
@ -99,7 +99,7 @@ func newTester(t *testing.T, confOverride func(*ethconfig.Config)) *tester {
|
|||||||
t.Fatalf("failed to create node: %v", err)
|
t.Fatalf("failed to create node: %v", err)
|
||||||
}
|
}
|
||||||
ethConf := ðconfig.Config{
|
ethConf := ðconfig.Config{
|
||||||
Genesis: core.DeveloperGenesisBlock(15, common.Address{}),
|
Genesis: core.DeveloperGenesisBlock(15, 11_500_000, common.Address{}),
|
||||||
Miner: miner.Config{
|
Miner: miner.Config{
|
||||||
Etherbase: common.HexToAddress(testAddress),
|
Etherbase: common.HexToAddress(testAddress),
|
||||||
},
|
},
|
||||||
|
@ -296,7 +296,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
|||||||
if diskRoot != (common.Hash{}) {
|
if diskRoot != (common.Hash{}) {
|
||||||
log.Warn("Head state missing, repairing", "number", head.Number(), "hash", head.Hash(), "snaproot", diskRoot)
|
log.Warn("Head state missing, repairing", "number", head.Number(), "hash", head.Hash(), "snaproot", diskRoot)
|
||||||
|
|
||||||
snapDisk, err := bc.SetHeadBeyondRoot(head.NumberU64(), diskRoot)
|
snapDisk, err := bc.setHeadBeyondRoot(head.NumberU64(), diskRoot, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -306,7 +306,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Warn("Head state missing, repairing", "number", head.Number(), "hash", head.Hash())
|
log.Warn("Head state missing, repairing", "number", head.Number(), "hash", head.Hash())
|
||||||
if err := bc.SetHead(head.NumberU64()); err != nil {
|
if _, err := bc.setHeadBeyondRoot(head.NumberU64(), common.Hash{}, true); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -482,11 +482,11 @@ func (bc *BlockChain) loadLastState() error {
|
|||||||
// was fast synced or full synced and in which state, the method will try to
|
// was fast synced or full synced and in which state, the method will try to
|
||||||
// delete minimal data from disk whilst retaining chain consistency.
|
// delete minimal data from disk whilst retaining chain consistency.
|
||||||
func (bc *BlockChain) SetHead(head uint64) error {
|
func (bc *BlockChain) SetHead(head uint64) error {
|
||||||
_, err := bc.SetHeadBeyondRoot(head, common.Hash{})
|
_, err := bc.setHeadBeyondRoot(head, common.Hash{}, false)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHeadBeyondRoot rewinds the local chain to a new head with the extra condition
|
// setHeadBeyondRoot rewinds the local chain to a new head with the extra condition
|
||||||
// that the rewind must pass the specified state root. This method is meant to be
|
// that the rewind must pass the specified state root. This method is meant to be
|
||||||
// used when rewinding with snapshots enabled to ensure that we go back further than
|
// used when rewinding with snapshots enabled to ensure that we go back further than
|
||||||
// persistent disk layer. Depending on whether the node was fast synced or full, and
|
// persistent disk layer. Depending on whether the node was fast synced or full, and
|
||||||
@ -494,7 +494,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
|||||||
// retaining chain consistency.
|
// retaining chain consistency.
|
||||||
//
|
//
|
||||||
// The method returns the block number where the requested root cap was found.
|
// The method returns the block number where the requested root cap was found.
|
||||||
func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64, error) {
|
func (bc *BlockChain) setHeadBeyondRoot(head uint64, root common.Hash, repair bool) (uint64, error) {
|
||||||
if !bc.chainmu.TryLock() {
|
if !bc.chainmu.TryLock() {
|
||||||
return 0, errChainStopped
|
return 0, errChainStopped
|
||||||
}
|
}
|
||||||
@ -509,7 +509,7 @@ func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64,
|
|||||||
frozen, _ := bc.db.Ancients()
|
frozen, _ := bc.db.Ancients()
|
||||||
|
|
||||||
updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (uint64, bool) {
|
updateFn := func(db ethdb.KeyValueWriter, header *types.Header) (uint64, bool) {
|
||||||
// Rewind the block chain, ensuring we don't end up with a stateless head
|
// Rewind the blockchain, ensuring we don't end up with a stateless head
|
||||||
// block. Note, depth equality is permitted to allow using SetHead as a
|
// block. Note, depth equality is permitted to allow using SetHead as a
|
||||||
// chain reparation mechanism without deleting any data!
|
// chain reparation mechanism without deleting any data!
|
||||||
if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.NumberU64() {
|
if currentBlock := bc.CurrentBlock(); currentBlock != nil && header.Number.Uint64() <= currentBlock.NumberU64() {
|
||||||
@ -610,8 +610,8 @@ func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64,
|
|||||||
}
|
}
|
||||||
// If SetHead was only called as a chain reparation method, try to skip
|
// If SetHead was only called as a chain reparation method, try to skip
|
||||||
// touching the header chain altogether, unless the freezer is broken
|
// touching the header chain altogether, unless the freezer is broken
|
||||||
if block := bc.CurrentBlock(); block.NumberU64() == head {
|
if repair {
|
||||||
if target, force := updateFn(bc.db, block.Header()); force {
|
if target, force := updateFn(bc.db, bc.CurrentBlock().Header()); force {
|
||||||
bc.hc.SetHead(target, updateFn, delFn)
|
bc.hc.SetHead(target, updateFn, delFn)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,6 +51,10 @@ var (
|
|||||||
// next one expected based on the local chain.
|
// next one expected based on the local chain.
|
||||||
ErrNonceTooHigh = errors.New("nonce too high")
|
ErrNonceTooHigh = errors.New("nonce too high")
|
||||||
|
|
||||||
|
// ErrNonceMax is returned if the nonce of a transaction sender account has
|
||||||
|
// maximum allowed value and would become invalid if incremented.
|
||||||
|
ErrNonceMax = errors.New("nonce has max value")
|
||||||
|
|
||||||
// ErrGasLimitReached is returned by the gas pool if the amount of gas required
|
// ErrGasLimitReached is returned by the gas pool if the amount of gas required
|
||||||
// by a transaction is higher than what's left in the block.
|
// by a transaction is higher than what's left in the block.
|
||||||
ErrGasLimitReached = errors.New("gas limit reached")
|
ErrGasLimitReached = errors.New("gas limit reached")
|
||||||
|
@ -416,7 +416,7 @@ func DefaultSepoliaGenesisBlock() *Genesis {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
||||||
func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
|
func DeveloperGenesisBlock(period uint64, gasLimit uint64, faucet common.Address) *Genesis {
|
||||||
// Override the default period to the user requested one
|
// Override the default period to the user requested one
|
||||||
config := *params.AllCliqueProtocolChanges
|
config := *params.AllCliqueProtocolChanges
|
||||||
config.Clique = ¶ms.CliqueConfig{
|
config.Clique = ¶ms.CliqueConfig{
|
||||||
@ -428,7 +428,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
|
|||||||
return &Genesis{
|
return &Genesis{
|
||||||
Config: &config,
|
Config: &config,
|
||||||
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
|
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
|
||||||
GasLimit: 11500000,
|
GasLimit: gasLimit,
|
||||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||||
Difficulty: big.NewInt(1),
|
Difficulty: big.NewInt(1),
|
||||||
Alloc: map[common.Address]GenesisAccount{
|
Alloc: map[common.Address]GenesisAccount{
|
||||||
|
@ -669,7 +669,7 @@ func deriveLogFields(receipts []*receiptLogs, hash common.Hash, number uint64, t
|
|||||||
// ReadLogs retrieves the logs for all transactions in a block. The log fields
|
// ReadLogs retrieves the logs for all transactions in a block. The log fields
|
||||||
// are populated with metadata. In case the receipts or the block body
|
// are populated with metadata. In case the receipts or the block body
|
||||||
// are not found, a nil is returned.
|
// are not found, a nil is returned.
|
||||||
func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log {
|
func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) [][]*types.Log {
|
||||||
// Retrieve the flattened receipt slice
|
// Retrieve the flattened receipt slice
|
||||||
data := ReadReceiptsRLP(db, hash, number)
|
data := ReadReceiptsRLP(db, hash, number)
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
@ -677,7 +677,12 @@ func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log {
|
|||||||
}
|
}
|
||||||
receipts := []*receiptLogs{}
|
receipts := []*receiptLogs{}
|
||||||
if err := rlp.DecodeBytes(data, &receipts); err != nil {
|
if err := rlp.DecodeBytes(data, &receipts); err != nil {
|
||||||
log.Error("Invalid receipt array RLP", "hash", hash, "err", err)
|
// Receipts might be in the legacy format, try decoding that.
|
||||||
|
// TODO: to be removed after users migrated
|
||||||
|
if logs := readLegacyLogs(db, hash, number, config); logs != nil {
|
||||||
|
return logs
|
||||||
|
}
|
||||||
|
log.Error("Invalid receipt array RLP", "hash", "err", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -697,6 +702,21 @@ func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log {
|
|||||||
return logs
|
return logs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readLegacyLogs is a temporary workaround for when trying to read logs
|
||||||
|
// from a block which has its receipt stored in the legacy format. It'll
|
||||||
|
// be removed after users have migrated their freezer databases.
|
||||||
|
func readLegacyLogs(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) [][]*types.Log {
|
||||||
|
receipts := ReadReceipts(db, hash, number, config)
|
||||||
|
if receipts == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
logs := make([][]*types.Log, len(receipts))
|
||||||
|
for i, receipt := range receipts {
|
||||||
|
logs[i] = receipt.Logs
|
||||||
|
}
|
||||||
|
return logs
|
||||||
|
}
|
||||||
|
|
||||||
// ReadBlock retrieves an entire block corresponding to the hash, assembling it
|
// ReadBlock retrieves an entire block corresponding to the hash, assembling it
|
||||||
// back from the stored header and body. If either the header or body could not
|
// back from the stored header and body. If either the header or body could not
|
||||||
// be retrieved nil is returned.
|
// be retrieved nil is returned.
|
||||||
|
@ -744,7 +744,7 @@ func TestReadLogs(t *testing.T) {
|
|||||||
// Insert the receipt slice into the database and check presence
|
// Insert the receipt slice into the database and check presence
|
||||||
WriteReceipts(db, hash, 0, receipts)
|
WriteReceipts(db, hash, 0, receipts)
|
||||||
|
|
||||||
logs := ReadLogs(db, hash, 0)
|
logs := ReadLogs(db, hash, 0, params.TestChainConfig)
|
||||||
if len(logs) == 0 {
|
if len(logs) == 0 {
|
||||||
t.Fatalf("no logs returned")
|
t.Fatalf("no logs returned")
|
||||||
}
|
}
|
||||||
|
@ -44,24 +44,29 @@ func InitDatabaseFromFreezer(db ethdb.Database) {
|
|||||||
logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log
|
logged = start.Add(-7 * time.Second) // Unindex during import is fast, don't double log
|
||||||
hash common.Hash
|
hash common.Hash
|
||||||
)
|
)
|
||||||
for i := uint64(0); i < frozen; i++ {
|
for i := uint64(0); i < frozen; {
|
||||||
// Since the freezer has all data in sequential order on a file,
|
// We read 100K hashes at a time, for a total of 3.2M
|
||||||
// it would be 'neat' to read more data in one go, and let the
|
count := uint64(100_000)
|
||||||
// freezerdb return N items (e.g up to 1000 items per go)
|
if i+count > frozen {
|
||||||
// That would require an API change in Ancients though
|
count = frozen - i
|
||||||
if h, err := db.Ancient(freezerHashTable, i); err != nil {
|
}
|
||||||
|
data, err := db.AncientRange(freezerHashTable, i, count, 32*count)
|
||||||
|
if err != nil {
|
||||||
log.Crit("Failed to init database from freezer", "err", err)
|
log.Crit("Failed to init database from freezer", "err", err)
|
||||||
} else {
|
}
|
||||||
|
for j, h := range data {
|
||||||
|
number := i + uint64(j)
|
||||||
hash = common.BytesToHash(h)
|
hash = common.BytesToHash(h)
|
||||||
}
|
WriteHeaderNumber(batch, hash, number)
|
||||||
WriteHeaderNumber(batch, hash, i)
|
// If enough data was accumulated in memory or we're at the last block, dump to disk
|
||||||
// If enough data was accumulated in memory or we're at the last block, dump to disk
|
if batch.ValueSize() > ethdb.IdealBatchSize {
|
||||||
if batch.ValueSize() > ethdb.IdealBatchSize {
|
if err := batch.Write(); err != nil {
|
||||||
if err := batch.Write(); err != nil {
|
log.Crit("Failed to write data to db", "err", err)
|
||||||
log.Crit("Failed to write data to db", "err", err)
|
}
|
||||||
|
batch.Reset()
|
||||||
}
|
}
|
||||||
batch.Reset()
|
|
||||||
}
|
}
|
||||||
|
i += uint64(len(data))
|
||||||
// If we've spent too much time already, notify the user of what we're doing
|
// If we've spent too much time already, notify the user of what we're doing
|
||||||
if time.Since(logged) > 8*time.Second {
|
if time.Since(logged) > 8*time.Second {
|
||||||
log.Info("Initializing database from freezer", "total", frozen, "number", i, "hash", hash, "elapsed", common.PrettyDuration(time.Since(start)))
|
log.Info("Initializing database from freezer", "total", frozen, "number", i, "hash", hash, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
|
@ -118,7 +118,7 @@ func (batch *freezerTableBatch) reset() {
|
|||||||
// existing data.
|
// existing data.
|
||||||
func (batch *freezerTableBatch) Append(item uint64, data interface{}) error {
|
func (batch *freezerTableBatch) Append(item uint64, data interface{}) error {
|
||||||
if item != batch.curItem {
|
if item != batch.curItem {
|
||||||
return errOutOrderInsertion
|
return fmt.Errorf("%w: have %d want %d", errOutOrderInsertion, item, batch.curItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encode the item.
|
// Encode the item.
|
||||||
@ -138,7 +138,7 @@ func (batch *freezerTableBatch) Append(item uint64, data interface{}) error {
|
|||||||
// existing data.
|
// existing data.
|
||||||
func (batch *freezerTableBatch) AppendRaw(item uint64, blob []byte) error {
|
func (batch *freezerTableBatch) AppendRaw(item uint64, blob []byte) error {
|
||||||
if item != batch.curItem {
|
if item != batch.curItem {
|
||||||
return errOutOrderInsertion
|
return fmt.Errorf("%w: have %d want %d", errOutOrderInsertion, item, batch.curItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
encItem := blob
|
encItem := blob
|
||||||
|
@ -246,7 +246,7 @@ func TestFreezerConcurrentModifyTruncate(t *testing.T) {
|
|||||||
if truncateErr != nil {
|
if truncateErr != nil {
|
||||||
t.Fatal("concurrent truncate failed:", err)
|
t.Fatal("concurrent truncate failed:", err)
|
||||||
}
|
}
|
||||||
if !(modifyErr == nil || modifyErr == errOutOrderInsertion) {
|
if !(errors.Is(modifyErr, nil) || errors.Is(modifyErr, errOutOrderInsertion)) {
|
||||||
t.Fatal("wrong error from concurrent modify:", modifyErr)
|
t.Fatal("wrong error from concurrent modify:", modifyErr)
|
||||||
}
|
}
|
||||||
checkAncientCount(t, f, "test", 10)
|
checkAncientCount(t, f, "test", 10)
|
||||||
|
@ -17,10 +17,12 @@
|
|||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
@ -54,11 +56,12 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||||||
LondonBlock: big.NewInt(0),
|
LondonBlock: big.NewInt(0),
|
||||||
Ethash: new(params.EthashConfig),
|
Ethash: new(params.EthashConfig),
|
||||||
}
|
}
|
||||||
signer = types.LatestSigner(config)
|
signer = types.LatestSigner(config)
|
||||||
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
key2, _ = crypto.HexToECDSA("0202020202020202020202020202020202020202020202020202002020202020")
|
||||||
)
|
)
|
||||||
var makeTx = func(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction {
|
var makeTx = func(key *ecdsa.PrivateKey, nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *types.Transaction {
|
||||||
tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, testKey)
|
tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, key)
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
var mkDynamicTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap *big.Int) *types.Transaction {
|
var mkDynamicTx = func(nonce uint64, to common.Address, gasLimit uint64, gasTipCap, gasFeeCap *big.Int) *types.Transaction {
|
||||||
@ -69,7 +72,7 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||||||
Gas: gasLimit,
|
Gas: gasLimit,
|
||||||
To: &to,
|
To: &to,
|
||||||
Value: big.NewInt(0),
|
Value: big.NewInt(0),
|
||||||
}), signer, testKey)
|
}), signer, key1)
|
||||||
return tx
|
return tx
|
||||||
}
|
}
|
||||||
{ // Tests against a 'recent' chain definition
|
{ // Tests against a 'recent' chain definition
|
||||||
@ -82,6 +85,10 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||||||
Balance: big.NewInt(1000000000000000000), // 1 ether
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
Nonce: 0,
|
Nonce: 0,
|
||||||
},
|
},
|
||||||
|
common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): GenesisAccount{
|
||||||
|
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||||
|
Nonce: math.MaxUint64,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
genesis = gspec.MustCommit(db)
|
genesis = gspec.MustCommit(db)
|
||||||
@ -97,32 +104,38 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{ // ErrNonceTooLow
|
{ // ErrNonceTooLow
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil),
|
||||||
makeTx(0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 1 [0x0026256b3939ed97e2c4a6f3fce8ecf83bdcfa6d507c47838c308a1fb0436f62]: nonce too low: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 0 state: 1",
|
want: "could not apply tx 1 [0x0026256b3939ed97e2c4a6f3fce8ecf83bdcfa6d507c47838c308a1fb0436f62]: nonce too low: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 0 state: 1",
|
||||||
},
|
},
|
||||||
{ // ErrNonceTooHigh
|
{ // ErrNonceTooHigh
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(100, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil),
|
makeTx(key1, 100, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0xdebad714ca7f363bd0d8121c4518ad48fa469ca81b0a081be3d10c17460f751b]: nonce too high: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 100 state: 0",
|
want: "could not apply tx 0 [0xdebad714ca7f363bd0d8121c4518ad48fa469ca81b0a081be3d10c17460f751b]: nonce too high: address 0x71562b71999873DB5b286dF957af199Ec94617F7, tx: 100 state: 0",
|
||||||
},
|
},
|
||||||
|
{ // ErrNonceMax
|
||||||
|
txs: []*types.Transaction{
|
||||||
|
makeTx(key2, math.MaxUint64, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(875000000), nil),
|
||||||
|
},
|
||||||
|
want: "could not apply tx 0 [0x84ea18d60eb2bb3b040e3add0eb72f757727122cc257dd858c67cb6591a85986]: nonce has max value: address 0xfd0810DD14796680f72adf1a371963d0745BCc64, nonce: 18446744073709551615",
|
||||||
|
},
|
||||||
{ // ErrGasLimitReached
|
{ // ErrGasLimitReached
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(0, common.Address{}, big.NewInt(0), 21000000, big.NewInt(875000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), 21000000, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached",
|
want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached",
|
||||||
},
|
},
|
||||||
{ // ErrInsufficientFundsForTransfer
|
{ // ErrInsufficientFundsForTransfer
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(0, common.Address{}, big.NewInt(1000000000000000000), params.TxGas, big.NewInt(875000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(1000000000000000000), params.TxGas, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0x98c796b470f7fcab40aaef5c965a602b0238e1034cce6fb73823042dd0638d74]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1000018375000000000",
|
want: "could not apply tx 0 [0x98c796b470f7fcab40aaef5c965a602b0238e1034cce6fb73823042dd0638d74]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 1000018375000000000",
|
||||||
},
|
},
|
||||||
{ // ErrInsufficientFunds
|
{ // ErrInsufficientFunds
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(900000000000000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas, big.NewInt(900000000000000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0x4a69690c4b0cd85e64d0d9ea06302455b01e10a83db964d60281739752003440]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 18900000000000000000000",
|
want: "could not apply tx 0 [0x4a69690c4b0cd85e64d0d9ea06302455b01e10a83db964d60281739752003440]: insufficient funds for gas * price + value: address 0x71562b71999873DB5b286dF957af199Ec94617F7 have 1000000000000000000 want 18900000000000000000000",
|
||||||
},
|
},
|
||||||
@ -132,13 +145,13 @@ func TestStateProcessorErrors(t *testing.T) {
|
|||||||
// multiplication len(data) +gas_per_byte overflows uint64. Not testable at the moment
|
// multiplication len(data) +gas_per_byte overflows uint64. Not testable at the moment
|
||||||
{ // ErrIntrinsicGas
|
{ // ErrIntrinsicGas
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(0, common.Address{}, big.NewInt(0), params.TxGas-1000, big.NewInt(875000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas-1000, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0xcf3b049a0b516cb4f9274b3e2a264359e2ba53b2fb64b7bda2c634d5c9d01fca]: intrinsic gas too low: have 20000, want 21000",
|
want: "could not apply tx 0 [0xcf3b049a0b516cb4f9274b3e2a264359e2ba53b2fb64b7bda2c634d5c9d01fca]: intrinsic gas too low: have 20000, want 21000",
|
||||||
},
|
},
|
||||||
{ // ErrGasLimitReached
|
{ // ErrGasLimitReached
|
||||||
txs: []*types.Transaction{
|
txs: []*types.Transaction{
|
||||||
makeTx(0, common.Address{}, big.NewInt(0), params.TxGas*1000, big.NewInt(875000000), nil),
|
makeTx(key1, 0, common.Address{}, big.NewInt(0), params.TxGas*1000, big.NewInt(875000000), nil),
|
||||||
},
|
},
|
||||||
want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached",
|
want: "could not apply tx 0 [0xbd49d8dadfd47fb846986695f7d4da3f7b2c48c8da82dbc211a26eb124883de9]: gas limit reached",
|
||||||
},
|
},
|
||||||
|
@ -222,6 +222,9 @@ func (st *StateTransition) preCheck() error {
|
|||||||
} else if stNonce > msgNonce {
|
} else if stNonce > msgNonce {
|
||||||
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow,
|
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow,
|
||||||
st.msg.From().Hex(), msgNonce, stNonce)
|
st.msg.From().Hex(), msgNonce, stNonce)
|
||||||
|
} else if stNonce+1 < stNonce {
|
||||||
|
return fmt.Errorf("%w: address %v, nonce: %d", ErrNonceMax,
|
||||||
|
st.msg.From().Hex(), stNonce)
|
||||||
}
|
}
|
||||||
// Make sure the sender is an EOA
|
// Make sure the sender is an EOA
|
||||||
if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyCodeHash && codeHash != (common.Hash{}) {
|
if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyCodeHash && codeHash != (common.Hash{}) {
|
||||||
|
@ -621,8 +621,9 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrInvalidSender
|
return ErrInvalidSender
|
||||||
}
|
}
|
||||||
// Drop non-local transactions under our own minimal accepted gas price or tip
|
// Drop non-local transactions under our own minimal accepted gas price or tip.
|
||||||
if !local && tx.GasTipCapIntCmp(pool.gasPrice) < 0 {
|
pendingBaseFee := pool.priced.urgent.baseFee
|
||||||
|
if !local && tx.EffectiveGasTipIntCmp(pool.gasPrice, pendingBaseFee) < 0 {
|
||||||
return ErrUnderpriced
|
return ErrUnderpriced
|
||||||
}
|
}
|
||||||
// Ensure the transaction adheres to nonce ordering
|
// Ensure the transaction adheres to nonce ordering
|
||||||
|
@ -141,7 +141,7 @@ func (a *AccessListTracer) CaptureStart(env *EVM, from common.Address, to common
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist.
|
// CaptureState captures all opcodes that touch storage or addresses and adds them to the accesslist.
|
||||||
func (a *AccessListTracer) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
func (a *AccessListTracer) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
||||||
stack := scope.Stack
|
stack := scope.Stack
|
||||||
if (op == SLOAD || op == SSTORE) && stack.len() >= 1 {
|
if (op == SLOAD || op == SSTORE) && stack.len() >= 1 {
|
||||||
slot := common.Hash(stack.data[stack.len()-1].Bytes32())
|
slot := common.Hash(stack.data[stack.len()-1].Bytes32())
|
||||||
@ -161,7 +161,7 @@ func (a *AccessListTracer) CaptureState(env *EVM, pc uint64, op OpCode, gas, cos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*AccessListTracer) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
|
func (*AccessListTracer) CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*AccessListTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
|
func (*AccessListTracer) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
|
||||||
|
@ -35,6 +35,7 @@ var (
|
|||||||
ErrReturnDataOutOfBounds = errors.New("return data out of bounds")
|
ErrReturnDataOutOfBounds = errors.New("return data out of bounds")
|
||||||
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
||||||
ErrInvalidCode = errors.New("invalid code: must not begin with 0xef")
|
ErrInvalidCode = errors.New("invalid code: must not begin with 0xef")
|
||||||
|
ErrNonceUintOverflow = errors.New("nonce uint64 overflow")
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrStackUnderflow wraps an evm error when the items on the stack less
|
// ErrStackUnderflow wraps an evm error when the items on the stack less
|
||||||
|
@ -424,6 +424,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
|||||||
return nil, common.Address{}, gas, ErrInsufficientBalance
|
return nil, common.Address{}, gas, ErrInsufficientBalance
|
||||||
}
|
}
|
||||||
nonce := evm.StateDB.GetNonce(caller.Address())
|
nonce := evm.StateDB.GetNonce(caller.Address())
|
||||||
|
if nonce+1 < nonce {
|
||||||
|
return nil, common.Address{}, gas, ErrNonceUintOverflow
|
||||||
|
}
|
||||||
evm.StateDB.SetNonce(caller.Address(), nonce+1)
|
evm.StateDB.SetNonce(caller.Address(), nonce+1)
|
||||||
// We add this to the access list _before_ taking a snapshot. Even if the creation fails,
|
// We add this to the access list _before_ taking a snapshot. Even if the creation fails,
|
||||||
// the access-list change should not be rolled back
|
// the access-list change should not be rolled back
|
||||||
|
@ -169,9 +169,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !logged {
|
if !logged {
|
||||||
in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
in.cfg.Tracer.CaptureState(pcCopy, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
||||||
} else {
|
} else {
|
||||||
in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, callContext, in.evm.depth, err)
|
in.cfg.Tracer.CaptureFault(pcCopy, op, gasCopy, cost, callContext, in.evm.depth, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@ -253,7 +253,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if in.cfg.Debug {
|
if in.cfg.Debug {
|
||||||
in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
in.cfg.Tracer.CaptureState(pc, op, gasCopy, cost, callContext, in.returnData, in.evm.depth, err)
|
||||||
logged = true
|
logged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,10 +105,10 @@ func (s *StructLog) ErrorString() string {
|
|||||||
// if you need to retain them beyond the current call.
|
// if you need to retain them beyond the current call.
|
||||||
type EVMLogger interface {
|
type EVMLogger interface {
|
||||||
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
|
CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int)
|
||||||
CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error)
|
CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error)
|
||||||
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
|
CaptureEnter(typ OpCode, from common.Address, to common.Address, input []byte, gas uint64, value *big.Int)
|
||||||
CaptureExit(output []byte, gasUsed uint64, err error)
|
CaptureExit(output []byte, gasUsed uint64, err error)
|
||||||
CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error)
|
CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error)
|
||||||
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error)
|
CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +119,7 @@ type EVMLogger interface {
|
|||||||
// contract their storage.
|
// contract their storage.
|
||||||
type StructLogger struct {
|
type StructLogger struct {
|
||||||
cfg LogConfig
|
cfg LogConfig
|
||||||
|
env *EVM
|
||||||
|
|
||||||
storage map[common.Address]Storage
|
storage map[common.Address]Storage
|
||||||
logs []StructLog
|
logs []StructLog
|
||||||
@ -147,12 +148,13 @@ func (l *StructLogger) Reset() {
|
|||||||
|
|
||||||
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
// CaptureStart implements the EVMLogger interface to initialize the tracing operation.
|
||||||
func (l *StructLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (l *StructLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
|
l.env = env
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState logs a new structured log message and pushes it out to the environment
|
// CaptureState logs a new structured log message and pushes it out to the environment
|
||||||
//
|
//
|
||||||
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
|
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
|
||||||
func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
||||||
memory := scope.Memory
|
memory := scope.Memory
|
||||||
stack := scope.Stack
|
stack := scope.Stack
|
||||||
contract := scope.Contract
|
contract := scope.Contract
|
||||||
@ -186,7 +188,7 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
|
|||||||
if op == SLOAD && stack.len() >= 1 {
|
if op == SLOAD && stack.len() >= 1 {
|
||||||
var (
|
var (
|
||||||
address = common.Hash(stack.data[stack.len()-1].Bytes32())
|
address = common.Hash(stack.data[stack.len()-1].Bytes32())
|
||||||
value = env.StateDB.GetState(contract.Address(), address)
|
value = l.env.StateDB.GetState(contract.Address(), address)
|
||||||
)
|
)
|
||||||
l.storage[contract.Address()][address] = value
|
l.storage[contract.Address()][address] = value
|
||||||
storage = l.storage[contract.Address()].Copy()
|
storage = l.storage[contract.Address()].Copy()
|
||||||
@ -206,13 +208,13 @@ func (l *StructLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost ui
|
|||||||
copy(rdata, rData)
|
copy(rdata, rData)
|
||||||
}
|
}
|
||||||
// create a new snapshot of the EVM.
|
// create a new snapshot of the EVM.
|
||||||
log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, env.StateDB.GetRefund(), err}
|
log := StructLog{pc, op, gas, cost, mem, memory.Len(), stck, rdata, storage, depth, l.env.StateDB.GetRefund(), err}
|
||||||
l.logs = append(l.logs, log)
|
l.logs = append(l.logs, log)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureFault implements the EVMLogger interface to trace an execution fault
|
// CaptureFault implements the EVMLogger interface to trace an execution fault
|
||||||
// while running an opcode.
|
// while running an opcode.
|
||||||
func (l *StructLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
|
func (l *StructLogger) CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CaptureEnd is called after the call finishes to finalize the tracing.
|
// CaptureEnd is called after the call finishes to finalize the tracing.
|
||||||
@ -291,12 +293,13 @@ func WriteLogs(writer io.Writer, logs []*types.Log) {
|
|||||||
type mdLogger struct {
|
type mdLogger struct {
|
||||||
out io.Writer
|
out io.Writer
|
||||||
cfg *LogConfig
|
cfg *LogConfig
|
||||||
|
env *EVM
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMarkdownLogger creates a logger which outputs information in a format adapted
|
// NewMarkdownLogger creates a logger which outputs information in a format adapted
|
||||||
// for human readability, and is also a valid markdown table
|
// for human readability, and is also a valid markdown table
|
||||||
func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger {
|
func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger {
|
||||||
l := &mdLogger{writer, cfg}
|
l := &mdLogger{out: writer, cfg: cfg}
|
||||||
if l.cfg == nil {
|
if l.cfg == nil {
|
||||||
l.cfg = &LogConfig{}
|
l.cfg = &LogConfig{}
|
||||||
}
|
}
|
||||||
@ -304,6 +307,7 @@ func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *mdLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (t *mdLogger) CaptureStart(env *EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
|
t.env = env
|
||||||
if !create {
|
if !create {
|
||||||
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `0x%x`\nGas: `%d`\nValue `%v` wei\n",
|
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `0x%x`\nGas: `%d`\nValue `%v` wei\n",
|
||||||
from.String(), to.String(),
|
from.String(), to.String(),
|
||||||
@ -321,7 +325,7 @@ func (t *mdLogger) CaptureStart(env *EVM, from common.Address, to common.Address
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
|
// CaptureState also tracks SLOAD/SSTORE ops to track storage change.
|
||||||
func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
func (t *mdLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
||||||
stack := scope.Stack
|
stack := scope.Stack
|
||||||
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
|
fmt.Fprintf(t.out, "| %4d | %10v | %3d |", pc, op, cost)
|
||||||
|
|
||||||
@ -334,14 +338,14 @@ func (t *mdLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64
|
|||||||
b := fmt.Sprintf("[%v]", strings.Join(a, ","))
|
b := fmt.Sprintf("[%v]", strings.Join(a, ","))
|
||||||
fmt.Fprintf(t.out, "%10v |", b)
|
fmt.Fprintf(t.out, "%10v |", b)
|
||||||
}
|
}
|
||||||
fmt.Fprintf(t.out, "%10v |", env.StateDB.GetRefund())
|
fmt.Fprintf(t.out, "%10v |", t.env.StateDB.GetRefund())
|
||||||
fmt.Fprintln(t.out, "")
|
fmt.Fprintln(t.out, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(t.out, "Error: %v\n", err)
|
fmt.Fprintf(t.out, "Error: %v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *mdLogger) CaptureFault(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
|
func (t *mdLogger) CaptureFault(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, depth int, err error) {
|
||||||
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
|
fmt.Fprintf(t.out, "\nError: at pc=%d, op=%v: %v\n", pc, op, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,12 +29,13 @@ import (
|
|||||||
type JSONLogger struct {
|
type JSONLogger struct {
|
||||||
encoder *json.Encoder
|
encoder *json.Encoder
|
||||||
cfg *LogConfig
|
cfg *LogConfig
|
||||||
|
env *EVM
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
|
// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
|
||||||
// into the provided stream.
|
// into the provided stream.
|
||||||
func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger {
|
func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger {
|
||||||
l := &JSONLogger{json.NewEncoder(writer), cfg}
|
l := &JSONLogger{encoder: json.NewEncoder(writer), cfg: cfg}
|
||||||
if l.cfg == nil {
|
if l.cfg == nil {
|
||||||
l.cfg = &LogConfig{}
|
l.cfg = &LogConfig{}
|
||||||
}
|
}
|
||||||
@ -42,12 +43,13 @@ func NewJSONLogger(cfg *LogConfig, writer io.Writer) *JSONLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureStart(env *EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (l *JSONLogger) CaptureStart(env *EVM, from, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
|
l.env = env
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *JSONLogger) CaptureFault(*EVM, uint64, OpCode, uint64, uint64, *ScopeContext, int, error) {}
|
func (l *JSONLogger) CaptureFault(uint64, OpCode, uint64, uint64, *ScopeContext, int, error) {}
|
||||||
|
|
||||||
// CaptureState outputs state information on the logger.
|
// CaptureState outputs state information on the logger.
|
||||||
func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
func (l *JSONLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scope *ScopeContext, rData []byte, depth int, err error) {
|
||||||
memory := scope.Memory
|
memory := scope.Memory
|
||||||
stack := scope.Stack
|
stack := scope.Stack
|
||||||
|
|
||||||
@ -58,7 +60,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
|
|||||||
GasCost: cost,
|
GasCost: cost,
|
||||||
MemorySize: memory.Len(),
|
MemorySize: memory.Len(),
|
||||||
Depth: depth,
|
Depth: depth,
|
||||||
RefundCounter: env.StateDB.GetRefund(),
|
RefundCounter: l.env.StateDB.GetRefund(),
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
if l.cfg.EnableMemory {
|
if l.cfg.EnableMemory {
|
||||||
|
@ -62,7 +62,8 @@ func TestStoreCapture(t *testing.T) {
|
|||||||
scope.Stack.push(uint256.NewInt(1))
|
scope.Stack.push(uint256.NewInt(1))
|
||||||
scope.Stack.push(new(uint256.Int))
|
scope.Stack.push(new(uint256.Int))
|
||||||
var index common.Hash
|
var index common.Hash
|
||||||
logger.CaptureState(env, 0, SSTORE, 0, 0, scope, nil, 0, nil)
|
logger.CaptureStart(env, common.Address{}, contract.Address(), false, nil, 0, nil)
|
||||||
|
logger.CaptureState(0, SSTORE, 0, 0, scope, nil, 0, nil)
|
||||||
if len(logger.storage[contract.Address()]) == 0 {
|
if len(logger.storage[contract.Address()]) == 0 {
|
||||||
t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(),
|
t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(),
|
||||||
len(logger.storage[contract.Address()]))
|
len(logger.storage[contract.Address()]))
|
||||||
|
@ -39,68 +39,68 @@ func (op OpCode) IsStaticJump() bool {
|
|||||||
|
|
||||||
// 0x0 range - arithmetic ops.
|
// 0x0 range - arithmetic ops.
|
||||||
const (
|
const (
|
||||||
STOP OpCode = iota
|
STOP OpCode = 0x0
|
||||||
ADD
|
ADD OpCode = 0x1
|
||||||
MUL
|
MUL OpCode = 0x2
|
||||||
SUB
|
SUB OpCode = 0x3
|
||||||
DIV
|
DIV OpCode = 0x4
|
||||||
SDIV
|
SDIV OpCode = 0x5
|
||||||
MOD
|
MOD OpCode = 0x6
|
||||||
SMOD
|
SMOD OpCode = 0x7
|
||||||
ADDMOD
|
ADDMOD OpCode = 0x8
|
||||||
MULMOD
|
MULMOD OpCode = 0x9
|
||||||
EXP
|
EXP OpCode = 0xa
|
||||||
SIGNEXTEND
|
SIGNEXTEND OpCode = 0xb
|
||||||
)
|
)
|
||||||
|
|
||||||
// 0x10 range - comparison ops.
|
// 0x10 range - comparison ops.
|
||||||
const (
|
const (
|
||||||
LT OpCode = iota + 0x10
|
LT OpCode = 0x10
|
||||||
GT
|
GT OpCode = 0x11
|
||||||
SLT
|
SLT OpCode = 0x12
|
||||||
SGT
|
SGT OpCode = 0x13
|
||||||
EQ
|
EQ OpCode = 0x14
|
||||||
ISZERO
|
ISZERO OpCode = 0x15
|
||||||
AND
|
AND OpCode = 0x16
|
||||||
OR
|
OR OpCode = 0x17
|
||||||
XOR
|
XOR OpCode = 0x18
|
||||||
NOT
|
NOT OpCode = 0x19
|
||||||
BYTE
|
BYTE OpCode = 0x1a
|
||||||
SHL
|
SHL OpCode = 0x1b
|
||||||
SHR
|
SHR OpCode = 0x1c
|
||||||
SAR
|
SAR OpCode = 0x1d
|
||||||
|
|
||||||
SHA3 OpCode = 0x20
|
SHA3 OpCode = 0x20
|
||||||
)
|
)
|
||||||
|
|
||||||
// 0x30 range - closure state.
|
// 0x30 range - closure state.
|
||||||
const (
|
const (
|
||||||
ADDRESS OpCode = 0x30 + iota
|
ADDRESS OpCode = 0x30
|
||||||
BALANCE
|
BALANCE OpCode = 0x31
|
||||||
ORIGIN
|
ORIGIN OpCode = 0x32
|
||||||
CALLER
|
CALLER OpCode = 0x33
|
||||||
CALLVALUE
|
CALLVALUE OpCode = 0x34
|
||||||
CALLDATALOAD
|
CALLDATALOAD OpCode = 0x35
|
||||||
CALLDATASIZE
|
CALLDATASIZE OpCode = 0x36
|
||||||
CALLDATACOPY
|
CALLDATACOPY OpCode = 0x37
|
||||||
CODESIZE
|
CODESIZE OpCode = 0x38
|
||||||
CODECOPY
|
CODECOPY OpCode = 0x39
|
||||||
GASPRICE
|
GASPRICE OpCode = 0x3a
|
||||||
EXTCODESIZE
|
EXTCODESIZE OpCode = 0x3b
|
||||||
EXTCODECOPY
|
EXTCODECOPY OpCode = 0x3c
|
||||||
RETURNDATASIZE
|
RETURNDATASIZE OpCode = 0x3d
|
||||||
RETURNDATACOPY
|
RETURNDATACOPY OpCode = 0x3e
|
||||||
EXTCODEHASH
|
EXTCODEHASH OpCode = 0x3f
|
||||||
)
|
)
|
||||||
|
|
||||||
// 0x40 range - block operations.
|
// 0x40 range - block operations.
|
||||||
const (
|
const (
|
||||||
BLOCKHASH OpCode = 0x40 + iota
|
BLOCKHASH OpCode = 0x40
|
||||||
COINBASE
|
COINBASE OpCode = 0x41
|
||||||
TIMESTAMP
|
TIMESTAMP OpCode = 0x42
|
||||||
NUMBER
|
NUMBER OpCode = 0x43
|
||||||
DIFFICULTY
|
DIFFICULTY OpCode = 0x44
|
||||||
GASLIMIT
|
GASLIMIT OpCode = 0x45
|
||||||
CHAINID OpCode = 0x46
|
CHAINID OpCode = 0x46
|
||||||
SELFBALANCE OpCode = 0x47
|
SELFBALANCE OpCode = 0x47
|
||||||
BASEFEE OpCode = 0x48
|
BASEFEE OpCode = 0x48
|
||||||
@ -122,7 +122,7 @@ const (
|
|||||||
JUMPDEST OpCode = 0x5b
|
JUMPDEST OpCode = 0x5b
|
||||||
)
|
)
|
||||||
|
|
||||||
// 0x60 range.
|
// 0x60 range - pushes.
|
||||||
const (
|
const (
|
||||||
PUSH1 OpCode = 0x60 + iota
|
PUSH1 OpCode = 0x60 + iota
|
||||||
PUSH2
|
PUSH2
|
||||||
@ -156,7 +156,11 @@ const (
|
|||||||
PUSH30
|
PUSH30
|
||||||
PUSH31
|
PUSH31
|
||||||
PUSH32
|
PUSH32
|
||||||
DUP1
|
)
|
||||||
|
|
||||||
|
// 0x80 range - dups.
|
||||||
|
const (
|
||||||
|
DUP1 = 0x80 + iota
|
||||||
DUP2
|
DUP2
|
||||||
DUP3
|
DUP3
|
||||||
DUP4
|
DUP4
|
||||||
@ -172,7 +176,11 @@ const (
|
|||||||
DUP14
|
DUP14
|
||||||
DUP15
|
DUP15
|
||||||
DUP16
|
DUP16
|
||||||
SWAP1
|
)
|
||||||
|
|
||||||
|
// 0x90 range - swaps.
|
||||||
|
const (
|
||||||
|
SWAP1 = 0x90 + iota
|
||||||
SWAP2
|
SWAP2
|
||||||
SWAP3
|
SWAP3
|
||||||
SWAP4
|
SWAP4
|
||||||
@ -208,12 +216,13 @@ const (
|
|||||||
|
|
||||||
// 0xf0 range - closures.
|
// 0xf0 range - closures.
|
||||||
const (
|
const (
|
||||||
CREATE OpCode = 0xf0 + iota
|
CREATE OpCode = 0xf0
|
||||||
CALL
|
CALL OpCode = 0xf1
|
||||||
CALLCODE
|
CALLCODE OpCode = 0xf2
|
||||||
RETURN
|
RETURN OpCode = 0xf3
|
||||||
DELEGATECALL
|
DELEGATECALL OpCode = 0xf4
|
||||||
CREATE2
|
CREATE2 OpCode = 0xf5
|
||||||
|
|
||||||
STATICCALL OpCode = 0xfa
|
STATICCALL OpCode = 0xfa
|
||||||
REVERT OpCode = 0xfd
|
REVERT OpCode = 0xfd
|
||||||
SELFDESTRUCT OpCode = 0xff
|
SELFDESTRUCT OpCode = 0xff
|
||||||
|
@ -35,6 +35,9 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
|
||||||
|
// force-load js tracers to trigger registration
|
||||||
|
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDefaults(t *testing.T) {
|
func TestDefaults(t *testing.T) {
|
||||||
@ -330,12 +333,12 @@ type stepCounter struct {
|
|||||||
func (s *stepCounter) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
func (s *stepCounter) CaptureStart(env *vm.EVM, from common.Address, to common.Address, create bool, input []byte, gas uint64, value *big.Int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepCounter) CaptureFault(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
func (s *stepCounter) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stepCounter) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
|
func (s *stepCounter) CaptureEnd(output []byte, gasUsed uint64, t time.Duration, err error) {}
|
||||||
|
|
||||||
func (s *stepCounter) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
|
func (s *stepCounter) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
|
||||||
s.steps++
|
s.steps++
|
||||||
// Enable this for more output
|
// Enable this for more output
|
||||||
//s.inner.CaptureState(env, pc, op, gas, cost, memory, stack, rStack, contract, depth, err)
|
//s.inner.CaptureState(env, pc, op, gas, cost, memory, stack, rStack, contract, depth, err)
|
||||||
@ -511,7 +514,7 @@ func BenchmarkSimpleLoop(b *testing.B) {
|
|||||||
// TestEip2929Cases contains various testcases that are used for
|
// TestEip2929Cases contains various testcases that are used for
|
||||||
// EIP-2929 about gas repricings
|
// EIP-2929 about gas repricings
|
||||||
func TestEip2929Cases(t *testing.T) {
|
func TestEip2929Cases(t *testing.T) {
|
||||||
|
t.Skip("Test only useful for generating documentation")
|
||||||
id := 1
|
id := 1
|
||||||
prettyPrint := func(comment string, code []byte) {
|
prettyPrint := func(comment string, code []byte) {
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ func (api *PrivateAdminAPI) ExportChain(file string, first *uint64, last *uint64
|
|||||||
last = &head
|
last = &head
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(file); err == nil {
|
if _, err := os.Stat(file); err == nil {
|
||||||
// File already exists. Allowing overwrite could be a DoS vecotor,
|
// File already exists. Allowing overwrite could be a DoS vector,
|
||||||
// since the 'file' may point to arbitrary paths on the drive
|
// since the 'file' may point to arbitrary paths on the drive
|
||||||
return false, errors.New("location would overwrite an existing file")
|
return false, errors.New("location would overwrite an existing file")
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*typ
|
|||||||
if number == nil {
|
if number == nil {
|
||||||
return nil, errors.New("failed to get block number from hash")
|
return nil, errors.New("failed to get block number from hash")
|
||||||
}
|
}
|
||||||
logs := rawdb.ReadLogs(db, hash, *number)
|
logs := rawdb.ReadLogs(db, hash, *number, b.eth.blockchain.Config())
|
||||||
if logs == nil {
|
if logs == nil {
|
||||||
return nil, errors.New("failed to get logs for block")
|
return nil, errors.New("failed to get logs for block")
|
||||||
}
|
}
|
||||||
|
@ -535,7 +535,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
|
|||||||
}
|
}
|
||||||
// Rewind the ancient store and blockchain if reorg happens.
|
// Rewind the ancient store and blockchain if reorg happens.
|
||||||
if origin+1 < frozen {
|
if origin+1 < frozen {
|
||||||
if err := d.lightchain.SetHead(origin + 1); err != nil {
|
if err := d.lightchain.SetHead(origin); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,7 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
|||||||
if percent < 0 {
|
if percent < 0 {
|
||||||
percent = 0
|
percent = 0
|
||||||
log.Warn("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent)
|
log.Warn("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent)
|
||||||
}
|
} else if percent > 100 {
|
||||||
if percent > 100 {
|
|
||||||
percent = 100
|
percent = 100
|
||||||
log.Warn("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent)
|
log.Warn("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent)
|
||||||
}
|
}
|
||||||
@ -104,6 +103,16 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
|||||||
} else if ignorePrice.Int64() > 0 {
|
} else if ignorePrice.Int64() > 0 {
|
||||||
log.Info("Gasprice oracle is ignoring threshold set", "threshold", ignorePrice)
|
log.Info("Gasprice oracle is ignoring threshold set", "threshold", ignorePrice)
|
||||||
}
|
}
|
||||||
|
maxHeaderHistory := params.MaxHeaderHistory
|
||||||
|
if maxHeaderHistory < 1 {
|
||||||
|
maxHeaderHistory = 1
|
||||||
|
log.Warn("Sanitizing invalid gasprice oracle max header history", "provided", params.MaxHeaderHistory, "updated", maxHeaderHistory)
|
||||||
|
}
|
||||||
|
maxBlockHistory := params.MaxBlockHistory
|
||||||
|
if maxBlockHistory < 1 {
|
||||||
|
maxBlockHistory = 1
|
||||||
|
log.Warn("Sanitizing invalid gasprice oracle max block history", "provided", params.MaxBlockHistory, "updated", maxBlockHistory)
|
||||||
|
}
|
||||||
|
|
||||||
cache, _ := lru.New(2048)
|
cache, _ := lru.New(2048)
|
||||||
headEvent := make(chan core.ChainHeadEvent, 1)
|
headEvent := make(chan core.ChainHeadEvent, 1)
|
||||||
@ -125,8 +134,8 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
|||||||
ignorePrice: ignorePrice,
|
ignorePrice: ignorePrice,
|
||||||
checkBlocks: blocks,
|
checkBlocks: blocks,
|
||||||
percentile: percent,
|
percentile: percent,
|
||||||
maxHeaderHistory: params.MaxHeaderHistory,
|
maxHeaderHistory: maxHeaderHistory,
|
||||||
maxBlockHistory: params.MaxBlockHistory,
|
maxBlockHistory: maxBlockHistory,
|
||||||
historyCache: cache,
|
historyCache: cache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,147 +306,6 @@ func TestTraceCall(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOverriddenTraceCall(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// Initialize test accounts
|
|
||||||
accounts := newAccounts(3)
|
|
||||||
genesis := &core.Genesis{Alloc: core.GenesisAlloc{
|
|
||||||
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
|
||||||
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
|
||||||
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
|
|
||||||
}}
|
|
||||||
genBlocks := 10
|
|
||||||
signer := types.HomesteadSigner{}
|
|
||||||
api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
|
|
||||||
// Transfer from account[0] to account[1]
|
|
||||||
// value: 1000 wei
|
|
||||||
// fee: 0 wei
|
|
||||||
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
|
|
||||||
b.AddTx(tx)
|
|
||||||
}))
|
|
||||||
randomAccounts, tracer := newAccounts(3), "callTracerJs"
|
|
||||||
|
|
||||||
var testSuite = []struct {
|
|
||||||
blockNumber rpc.BlockNumber
|
|
||||||
call ethapi.TransactionArgs
|
|
||||||
config *TraceCallConfig
|
|
||||||
expectErr error
|
|
||||||
expect *callTrace
|
|
||||||
}{
|
|
||||||
// Succcessful call with state overriding
|
|
||||||
{
|
|
||||||
blockNumber: rpc.PendingBlockNumber,
|
|
||||||
call: ethapi.TransactionArgs{
|
|
||||||
From: &randomAccounts[0].addr,
|
|
||||||
To: &randomAccounts[1].addr,
|
|
||||||
Value: (*hexutil.Big)(big.NewInt(1000)),
|
|
||||||
},
|
|
||||||
config: &TraceCallConfig{
|
|
||||||
Tracer: &tracer,
|
|
||||||
StateOverrides: ðapi.StateOverride{
|
|
||||||
randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectErr: nil,
|
|
||||||
expect: &callTrace{
|
|
||||||
Type: "CALL",
|
|
||||||
From: randomAccounts[0].addr,
|
|
||||||
To: randomAccounts[1].addr,
|
|
||||||
Gas: newRPCUint64(24979000),
|
|
||||||
GasUsed: newRPCUint64(0),
|
|
||||||
Value: (*hexutil.Big)(big.NewInt(1000)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Invalid call without state overriding
|
|
||||||
{
|
|
||||||
blockNumber: rpc.PendingBlockNumber,
|
|
||||||
call: ethapi.TransactionArgs{
|
|
||||||
From: &randomAccounts[0].addr,
|
|
||||||
To: &randomAccounts[1].addr,
|
|
||||||
Value: (*hexutil.Big)(big.NewInt(1000)),
|
|
||||||
},
|
|
||||||
config: &TraceCallConfig{
|
|
||||||
Tracer: &tracer,
|
|
||||||
},
|
|
||||||
expectErr: core.ErrInsufficientFunds,
|
|
||||||
expect: nil,
|
|
||||||
},
|
|
||||||
// Successful simple contract call
|
|
||||||
//
|
|
||||||
// // SPDX-License-Identifier: GPL-3.0
|
|
||||||
//
|
|
||||||
// pragma solidity >=0.7.0 <0.8.0;
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * @title Storage
|
|
||||||
// * @dev Store & retrieve value in a variable
|
|
||||||
// */
|
|
||||||
// contract Storage {
|
|
||||||
// uint256 public number;
|
|
||||||
// constructor() {
|
|
||||||
// number = block.number;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
{
|
|
||||||
blockNumber: rpc.PendingBlockNumber,
|
|
||||||
call: ethapi.TransactionArgs{
|
|
||||||
From: &randomAccounts[0].addr,
|
|
||||||
To: &randomAccounts[2].addr,
|
|
||||||
Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number()
|
|
||||||
},
|
|
||||||
config: &TraceCallConfig{
|
|
||||||
Tracer: &tracer,
|
|
||||||
StateOverrides: ðapi.StateOverride{
|
|
||||||
randomAccounts[2].addr: ethapi.OverrideAccount{
|
|
||||||
Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")),
|
|
||||||
StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectErr: nil,
|
|
||||||
expect: &callTrace{
|
|
||||||
Type: "CALL",
|
|
||||||
From: randomAccounts[0].addr,
|
|
||||||
To: randomAccounts[2].addr,
|
|
||||||
Input: hexutil.Bytes(common.Hex2Bytes("8381f58a")),
|
|
||||||
Output: hexutil.Bytes(common.BigToHash(big.NewInt(123)).Bytes()),
|
|
||||||
Gas: newRPCUint64(24978936),
|
|
||||||
GasUsed: newRPCUint64(2283),
|
|
||||||
Value: (*hexutil.Big)(big.NewInt(0)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for i, testspec := range testSuite {
|
|
||||||
result, err := api.TraceCall(context.Background(), testspec.call, rpc.BlockNumberOrHash{BlockNumber: &testspec.blockNumber}, testspec.config)
|
|
||||||
if testspec.expectErr != nil {
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("test %d: want error %v, have nothing", i, testspec.expectErr)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !errors.Is(err, testspec.expectErr) {
|
|
||||||
t.Errorf("test %d: error mismatch, want %v, have %v", i, testspec.expectErr, err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("test %d: want no error, have %v", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ret := new(callTrace)
|
|
||||||
if err := json.Unmarshal(result.(json.RawMessage), ret); err != nil {
|
|
||||||
t.Fatalf("test %d: failed to unmarshal trace result: %v", i, err)
|
|
||||||
}
|
|
||||||
if !jsonEqual(ret, testspec.expect) {
|
|
||||||
// uncomment this for easier debugging
|
|
||||||
//have, _ := json.MarshalIndent(ret, "", " ")
|
|
||||||
//want, _ := json.MarshalIndent(testspec.expect, "", " ")
|
|
||||||
//t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", string(have), string(want))
|
|
||||||
t.Fatalf("trace mismatch: \nhave %+v\nwant %+v", ret, testspec.expect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTraceTransaction(t *testing.T) {
|
func TestTraceTransaction(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
@ -503,90 +362,177 @@ func TestTraceBlock(t *testing.T) {
|
|||||||
var testSuite = []struct {
|
var testSuite = []struct {
|
||||||
blockNumber rpc.BlockNumber
|
blockNumber rpc.BlockNumber
|
||||||
config *TraceConfig
|
config *TraceConfig
|
||||||
expect interface{}
|
want string
|
||||||
expectErr error
|
expectErr error
|
||||||
}{
|
}{
|
||||||
// Trace genesis block, expect error
|
// Trace genesis block, expect error
|
||||||
{
|
{
|
||||||
blockNumber: rpc.BlockNumber(0),
|
blockNumber: rpc.BlockNumber(0),
|
||||||
config: nil,
|
|
||||||
expect: nil,
|
|
||||||
expectErr: errors.New("genesis is not traceable"),
|
expectErr: errors.New("genesis is not traceable"),
|
||||||
},
|
},
|
||||||
// Trace head block
|
// Trace head block
|
||||||
{
|
{
|
||||||
blockNumber: rpc.BlockNumber(genBlocks),
|
blockNumber: rpc.BlockNumber(genBlocks),
|
||||||
config: nil,
|
want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
|
||||||
expectErr: nil,
|
|
||||||
expect: []*txTraceResult{
|
|
||||||
{
|
|
||||||
Result: ðapi.ExecutionResult{
|
|
||||||
Gas: params.TxGas,
|
|
||||||
Failed: false,
|
|
||||||
ReturnValue: "",
|
|
||||||
StructLogs: []ethapi.StructLogRes{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
// Trace non-existent block
|
// Trace non-existent block
|
||||||
{
|
{
|
||||||
blockNumber: rpc.BlockNumber(genBlocks + 1),
|
blockNumber: rpc.BlockNumber(genBlocks + 1),
|
||||||
config: nil,
|
|
||||||
expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
|
expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
|
||||||
expect: nil,
|
|
||||||
},
|
},
|
||||||
// Trace latest block
|
// Trace latest block
|
||||||
{
|
{
|
||||||
blockNumber: rpc.LatestBlockNumber,
|
blockNumber: rpc.LatestBlockNumber,
|
||||||
config: nil,
|
want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
|
||||||
expectErr: nil,
|
|
||||||
expect: []*txTraceResult{
|
|
||||||
{
|
|
||||||
Result: ðapi.ExecutionResult{
|
|
||||||
Gas: params.TxGas,
|
|
||||||
Failed: false,
|
|
||||||
ReturnValue: "",
|
|
||||||
StructLogs: []ethapi.StructLogRes{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
// Trace pending block
|
// Trace pending block
|
||||||
{
|
{
|
||||||
blockNumber: rpc.PendingBlockNumber,
|
blockNumber: rpc.PendingBlockNumber,
|
||||||
config: nil,
|
want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
|
||||||
expectErr: nil,
|
},
|
||||||
expect: []*txTraceResult{
|
}
|
||||||
{
|
for i, tc := range testSuite {
|
||||||
Result: ðapi.ExecutionResult{
|
result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config)
|
||||||
Gas: params.TxGas,
|
if tc.expectErr != nil {
|
||||||
Failed: false,
|
if err == nil {
|
||||||
ReturnValue: "",
|
t.Errorf("test %d, want error %v", i, tc.expectErr)
|
||||||
StructLogs: []ethapi.StructLogRes{},
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(err, tc.expectErr) {
|
||||||
|
t.Errorf("test %d: error mismatch, want %v, get %v", i, tc.expectErr, err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %d, want no error, have %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
have, _ := json.Marshal(result)
|
||||||
|
want := tc.want
|
||||||
|
if string(have) != want {
|
||||||
|
t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(have), want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTracingWithOverrides(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// Initialize test accounts
|
||||||
|
accounts := newAccounts(3)
|
||||||
|
genesis := &core.Genesis{Alloc: core.GenesisAlloc{
|
||||||
|
accounts[0].addr: {Balance: big.NewInt(params.Ether)},
|
||||||
|
accounts[1].addr: {Balance: big.NewInt(params.Ether)},
|
||||||
|
accounts[2].addr: {Balance: big.NewInt(params.Ether)},
|
||||||
|
}}
|
||||||
|
genBlocks := 10
|
||||||
|
signer := types.HomesteadSigner{}
|
||||||
|
api := NewAPI(newTestBackend(t, genBlocks, genesis, func(i int, b *core.BlockGen) {
|
||||||
|
// Transfer from account[0] to account[1]
|
||||||
|
// value: 1000 wei
|
||||||
|
// fee: 0 wei
|
||||||
|
tx, _ := types.SignTx(types.NewTransaction(uint64(i), accounts[1].addr, big.NewInt(1000), params.TxGas, b.BaseFee(), nil), signer, accounts[0].key)
|
||||||
|
b.AddTx(tx)
|
||||||
|
}))
|
||||||
|
randomAccounts := newAccounts(3)
|
||||||
|
type res struct {
|
||||||
|
Gas int
|
||||||
|
Failed bool
|
||||||
|
returnValue string
|
||||||
|
}
|
||||||
|
var testSuite = []struct {
|
||||||
|
blockNumber rpc.BlockNumber
|
||||||
|
call ethapi.TransactionArgs
|
||||||
|
config *TraceCallConfig
|
||||||
|
expectErr error
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
// Call which can only succeed if state is state overridden
|
||||||
|
{
|
||||||
|
blockNumber: rpc.PendingBlockNumber,
|
||||||
|
call: ethapi.TransactionArgs{
|
||||||
|
From: &randomAccounts[0].addr,
|
||||||
|
To: &randomAccounts[1].addr,
|
||||||
|
Value: (*hexutil.Big)(big.NewInt(1000)),
|
||||||
|
},
|
||||||
|
config: &TraceCallConfig{
|
||||||
|
StateOverrides: ðapi.StateOverride{
|
||||||
|
randomAccounts[0].addr: ethapi.OverrideAccount{Balance: newRPCBalance(new(big.Int).Mul(big.NewInt(1), big.NewInt(params.Ether)))},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: `{"gas":21000,"failed":false,"returnValue":""}`,
|
||||||
|
},
|
||||||
|
// Invalid call without state overriding
|
||||||
|
{
|
||||||
|
blockNumber: rpc.PendingBlockNumber,
|
||||||
|
call: ethapi.TransactionArgs{
|
||||||
|
From: &randomAccounts[0].addr,
|
||||||
|
To: &randomAccounts[1].addr,
|
||||||
|
Value: (*hexutil.Big)(big.NewInt(1000)),
|
||||||
|
},
|
||||||
|
config: &TraceCallConfig{},
|
||||||
|
expectErr: core.ErrInsufficientFunds,
|
||||||
|
},
|
||||||
|
// Successful simple contract call
|
||||||
|
//
|
||||||
|
// // SPDX-License-Identifier: GPL-3.0
|
||||||
|
//
|
||||||
|
// pragma solidity >=0.7.0 <0.8.0;
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * @title Storage
|
||||||
|
// * @dev Store & retrieve value in a variable
|
||||||
|
// */
|
||||||
|
// contract Storage {
|
||||||
|
// uint256 public number;
|
||||||
|
// constructor() {
|
||||||
|
// number = block.number;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
{
|
||||||
|
blockNumber: rpc.PendingBlockNumber,
|
||||||
|
call: ethapi.TransactionArgs{
|
||||||
|
From: &randomAccounts[0].addr,
|
||||||
|
To: &randomAccounts[2].addr,
|
||||||
|
Data: newRPCBytes(common.Hex2Bytes("8381f58a")), // call number()
|
||||||
|
},
|
||||||
|
config: &TraceCallConfig{
|
||||||
|
//Tracer: &tracer,
|
||||||
|
StateOverrides: ðapi.StateOverride{
|
||||||
|
randomAccounts[2].addr: ethapi.OverrideAccount{
|
||||||
|
Code: newRPCBytes(common.Hex2Bytes("6080604052348015600f57600080fd5b506004361060285760003560e01c80638381f58a14602d575b600080fd5b60336049565b6040518082815260200191505060405180910390f35b6000548156fea2646970667358221220eab35ffa6ab2adfe380772a48b8ba78e82a1b820a18fcb6f59aa4efb20a5f60064736f6c63430007040033")),
|
||||||
|
StateDiff: newStates([]common.Hash{{}}, []common.Hash{common.BigToHash(big.NewInt(123))}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
want: `{"gas":23347,"failed":false,"returnValue":"000000000000000000000000000000000000000000000000000000000000007b"}`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, testspec := range testSuite {
|
for i, tc := range testSuite {
|
||||||
result, err := api.TraceBlockByNumber(context.Background(), testspec.blockNumber, testspec.config)
|
result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)
|
||||||
if testspec.expectErr != nil {
|
if tc.expectErr != nil {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expect error %v, get nothing", testspec.expectErr)
|
t.Errorf("test %d: want error %v, have nothing", i, tc.expectErr)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(err, testspec.expectErr) {
|
if !errors.Is(err, tc.expectErr) {
|
||||||
t.Errorf("Error mismatch, want %v, get %v", testspec.expectErr, err)
|
t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Expect no error, get %v", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(result, testspec.expect) {
|
|
||||||
t.Errorf("Result mismatch, want %v, get %v", testspec.expect, result)
|
|
||||||
}
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("test %d: want no error, have %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Turn result into res-struct
|
||||||
|
var (
|
||||||
|
have res
|
||||||
|
want res
|
||||||
|
)
|
||||||
|
resBytes, _ := json.Marshal(result)
|
||||||
|
json.Unmarshal(resBytes, &have)
|
||||||
|
json.Unmarshal([]byte(tc.want), &want)
|
||||||
|
if !reflect.DeepEqual(have, want) {
|
||||||
|
t.Errorf("test %d, result mismatch, have\n%v\n, want\n%v\n", i, string(resBytes), want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -617,11 +563,6 @@ func newRPCBalance(balance *big.Int) **hexutil.Big {
|
|||||||
return &rpcBalance
|
return &rpcBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRPCUint64(number uint64) *hexutil.Uint64 {
|
|
||||||
rpcUint64 := hexutil.Uint64(number)
|
|
||||||
return &rpcUint64
|
|
||||||
}
|
|
||||||
|
|
||||||
func newRPCBytes(bytes []byte) *hexutil.Bytes {
|
func newRPCBytes(bytes []byte) *hexutil.Bytes {
|
||||||
rpcBytes := hexutil.Bytes(bytes)
|
rpcBytes := hexutil.Bytes(bytes)
|
||||||
return &rpcBytes
|
return &rpcBytes
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
// Copyright 2017 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/>.
|
|
||||||
|
|
||||||
// 4byteTracer searches for 4byte-identifiers, and collects them for post-processing.
|
|
||||||
// It collects the methods identifiers along with the size of the supplied data, so
|
|
||||||
// a reversed signature can be matched against the size of the data.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// > debug.traceTransaction( "0x214e597e35da083692f5386141e69f47e973b2c56e7a8073b1ea08fd7571e9de", {tracer: "4byteTracer"})
|
|
||||||
// {
|
|
||||||
// 0x27dc297e-128: 1,
|
|
||||||
// 0x38cc4831-0: 2,
|
|
||||||
// 0x524f3889-96: 1,
|
|
||||||
// 0xadf59f99-288: 1,
|
|
||||||
// 0xc281d19e-0: 1
|
|
||||||
// }
|
|
||||||
{
|
|
||||||
// ids aggregates the 4byte ids found.
|
|
||||||
ids : {},
|
|
||||||
|
|
||||||
// store save the given indentifier and datasize.
|
|
||||||
store: function(id, size){
|
|
||||||
var key = "" + toHex(id) + "-" + size;
|
|
||||||
this.ids[key] = this.ids[key] + 1 || 1;
|
|
||||||
},
|
|
||||||
|
|
||||||
enter: function(frame) {
|
|
||||||
// Skip any pre-compile invocations, those are just fancy opcodes
|
|
||||||
if (isPrecompiled(frame.getTo())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var input = frame.getInput()
|
|
||||||
if (input.length >= 4) {
|
|
||||||
this.store(slice(input, 0, 4), input.length - 4);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
exit: function(frameResult) {},
|
|
||||||
|
|
||||||
// fault is invoked when the actual execution of an opcode fails.
|
|
||||||
fault: function(log, db) {},
|
|
||||||
|
|
||||||
// result is invoked when all the opcodes have been iterated over and returns
|
|
||||||
// the final result of the tracing.
|
|
||||||
result: function(ctx) {
|
|
||||||
// Save the outer calldata also
|
|
||||||
if (ctx.input.length >= 4) {
|
|
||||||
this.store(slice(ctx.input, 0, 4), ctx.input.length-4)
|
|
||||||
}
|
|
||||||
return this.ids;
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,4 +1,20 @@
|
|||||||
package testing
|
// Copyright 2021 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 tracetest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -17,14 +33,67 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"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"
|
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||||
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/tests"
|
"github.com/ethereum/go-ethereum/tests"
|
||||||
|
|
||||||
// Force-load the native, to trigger registration
|
// Force-load native and js pacakges, to trigger registration
|
||||||
|
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
||||||
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// To generate a new callTracer test, copy paste the makeTest method below into
|
||||||
|
// a Geth console and call it with a transaction hash you which to export.
|
||||||
|
|
||||||
|
/*
|
||||||
|
// makeTest generates a callTracer test by running a prestate reassembled and a
|
||||||
|
// call trace run, assembling all the gathered information into a test case.
|
||||||
|
var makeTest = function(tx, rewind) {
|
||||||
|
// Generate the genesis block from the block, transaction and prestate data
|
||||||
|
var block = eth.getBlock(eth.getTransaction(tx).blockHash);
|
||||||
|
var genesis = eth.getBlock(block.parentHash);
|
||||||
|
|
||||||
|
delete genesis.gasUsed;
|
||||||
|
delete genesis.logsBloom;
|
||||||
|
delete genesis.parentHash;
|
||||||
|
delete genesis.receiptsRoot;
|
||||||
|
delete genesis.sha3Uncles;
|
||||||
|
delete genesis.size;
|
||||||
|
delete genesis.transactions;
|
||||||
|
delete genesis.transactionsRoot;
|
||||||
|
delete genesis.uncles;
|
||||||
|
|
||||||
|
genesis.gasLimit = genesis.gasLimit.toString();
|
||||||
|
genesis.number = genesis.number.toString();
|
||||||
|
genesis.timestamp = genesis.timestamp.toString();
|
||||||
|
|
||||||
|
genesis.alloc = debug.traceTransaction(tx, {tracer: "prestateTracer", rewind: rewind});
|
||||||
|
for (var key in genesis.alloc) {
|
||||||
|
genesis.alloc[key].nonce = genesis.alloc[key].nonce.toString();
|
||||||
|
}
|
||||||
|
genesis.config = admin.nodeInfo.protocols.eth.config;
|
||||||
|
|
||||||
|
// Generate the call trace and produce the test input
|
||||||
|
var result = debug.traceTransaction(tx, {tracer: "callTracer", rewind: rewind});
|
||||||
|
delete result.time;
|
||||||
|
|
||||||
|
console.log(JSON.stringify({
|
||||||
|
genesis: genesis,
|
||||||
|
context: {
|
||||||
|
number: block.number.toString(),
|
||||||
|
difficulty: block.difficulty,
|
||||||
|
timestamp: block.timestamp.toString(),
|
||||||
|
gasLimit: block.gasLimit.toString(),
|
||||||
|
miner: block.miner,
|
||||||
|
},
|
||||||
|
input: eth.getRawTransaction(tx),
|
||||||
|
result: result,
|
||||||
|
}, null, 2));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
type callContext struct {
|
type callContext struct {
|
||||||
Number math.HexOrDecimal64 `json:"number"`
|
Number math.HexOrDecimal64 `json:"number"`
|
||||||
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
||||||
@ -70,7 +139,7 @@ func TestCallTracerNative(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
||||||
files, err := ioutil.ReadDir(filepath.Join("..", "testdata", dirPath))
|
files, err := ioutil.ReadDir(filepath.Join("testdata", dirPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve tracer test suite: %v", err)
|
t.Fatalf("failed to retrieve tracer test suite: %v", err)
|
||||||
}
|
}
|
||||||
@ -87,7 +156,7 @@ func testCallTracer(tracerName string, dirPath string, t *testing.T) {
|
|||||||
tx = new(types.Transaction)
|
tx = new(types.Transaction)
|
||||||
)
|
)
|
||||||
// Call tracer test found, read if from disk
|
// Call tracer test found, read if from disk
|
||||||
if blob, err := ioutil.ReadFile(filepath.Join("..", "testdata", dirPath, file.Name())); err != nil {
|
if blob, err := ioutil.ReadFile(filepath.Join("testdata", dirPath, file.Name())); err != nil {
|
||||||
t.Fatalf("failed to read testcase: %v", err)
|
t.Fatalf("failed to read testcase: %v", err)
|
||||||
} else if err := json.Unmarshal(blob, test); err != nil {
|
} else if err := json.Unmarshal(blob, test); err != nil {
|
||||||
t.Fatalf("failed to parse testcase: %v", err)
|
t.Fatalf("failed to parse testcase: %v", err)
|
||||||
@ -175,7 +244,7 @@ func camel(str string) string {
|
|||||||
return strings.Join(pieces, "")
|
return strings.Join(pieces, "")
|
||||||
}
|
}
|
||||||
func BenchmarkTracers(b *testing.B) {
|
func BenchmarkTracers(b *testing.B) {
|
||||||
files, err := ioutil.ReadDir(filepath.Join("..", "testdata", "call_tracer"))
|
files, err := ioutil.ReadDir(filepath.Join("testdata", "call_tracer"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("failed to retrieve tracer test suite: %v", err)
|
b.Fatalf("failed to retrieve tracer test suite: %v", err)
|
||||||
}
|
}
|
||||||
@ -185,7 +254,7 @@ func BenchmarkTracers(b *testing.B) {
|
|||||||
}
|
}
|
||||||
file := file // capture range variable
|
file := file // capture range variable
|
||||||
b.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(b *testing.B) {
|
b.Run(camel(strings.TrimSuffix(file.Name(), ".json")), func(b *testing.B) {
|
||||||
blob, err := ioutil.ReadFile(filepath.Join("..", "testdata", "call_tracer", file.Name()))
|
blob, err := ioutil.ReadFile(filepath.Join("testdata", "call_tracer", file.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatalf("failed to read testcase: %v", err)
|
b.Fatalf("failed to read testcase: %v", err)
|
||||||
}
|
}
|
||||||
@ -244,3 +313,82 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
|||||||
statedb.RevertToSnapshot(snap)
|
statedb.RevertToSnapshot(snap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestZeroValueToNotExitCall tests the calltracer(s) on the following:
|
||||||
|
// Tx to A, A calls B with zero value. B does not already exist.
|
||||||
|
// Expected: that enter/exit is invoked and the inner call is shown in the result
|
||||||
|
func TestZeroValueToNotExitCall(t *testing.T) {
|
||||||
|
var to = common.HexToAddress("0x00000000000000000000000000000000deadbeef")
|
||||||
|
privkey, err := crypto.HexToECDSA("0000000000000000deadbeef00000000000000000000000000000000deadbeef")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err %v", err)
|
||||||
|
}
|
||||||
|
signer := types.NewEIP155Signer(big.NewInt(1))
|
||||||
|
tx, err := types.SignNewTx(privkey, signer, &types.LegacyTx{
|
||||||
|
GasPrice: big.NewInt(0),
|
||||||
|
Gas: 50000,
|
||||||
|
To: &to,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err %v", err)
|
||||||
|
}
|
||||||
|
origin, _ := signer.Sender(tx)
|
||||||
|
txContext := vm.TxContext{
|
||||||
|
Origin: origin,
|
||||||
|
GasPrice: big.NewInt(1),
|
||||||
|
}
|
||||||
|
context := vm.BlockContext{
|
||||||
|
CanTransfer: core.CanTransfer,
|
||||||
|
Transfer: core.Transfer,
|
||||||
|
Coinbase: common.Address{},
|
||||||
|
BlockNumber: new(big.Int).SetUint64(8000000),
|
||||||
|
Time: new(big.Int).SetUint64(5),
|
||||||
|
Difficulty: big.NewInt(0x30000),
|
||||||
|
GasLimit: uint64(6000000),
|
||||||
|
}
|
||||||
|
var code = []byte{
|
||||||
|
byte(vm.PUSH1), 0x0, byte(vm.DUP1), byte(vm.DUP1), byte(vm.DUP1), // in and outs zero
|
||||||
|
byte(vm.DUP1), byte(vm.PUSH1), 0xff, byte(vm.GAS), // value=0,address=0xff, gas=GAS
|
||||||
|
byte(vm.CALL),
|
||||||
|
}
|
||||||
|
var alloc = core.GenesisAlloc{
|
||||||
|
to: core.GenesisAccount{
|
||||||
|
Nonce: 1,
|
||||||
|
Code: code,
|
||||||
|
},
|
||||||
|
origin: core.GenesisAccount{
|
||||||
|
Nonce: 0,
|
||||||
|
Balance: big.NewInt(500000000000000),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, statedb := tests.MakePreState(rawdb.NewMemoryDatabase(), alloc, false)
|
||||||
|
// Create the tracer, the EVM environment and run it
|
||||||
|
tracer, err := tracers.New("callTracer", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create call tracer: %v", err)
|
||||||
|
}
|
||||||
|
evm := vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||||
|
msg, err := tx.AsMessage(signer, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to prepare transaction for tracing: %v", err)
|
||||||
|
}
|
||||||
|
st := core.NewStateTransition(evm, msg, new(core.GasPool).AddGas(tx.Gas()))
|
||||||
|
if _, err = st.TransitionDb(); err != nil {
|
||||||
|
t.Fatalf("failed to execute transaction: %v", err)
|
||||||
|
}
|
||||||
|
// Retrieve the trace result and compare against the etalon
|
||||||
|
res, err := tracer.GetResult()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to retrieve trace result: %v", err)
|
||||||
|
}
|
||||||
|
have := new(callTrace)
|
||||||
|
if err := json.Unmarshal(res, have); err != nil {
|
||||||
|
t.Fatalf("failed to unmarshal trace result: %v", err)
|
||||||
|
}
|
||||||
|
wantStr := `{"type":"CALL","from":"0x682a80a6f560eec50d54e63cbeda1c324c5f8d1b","to":"0x00000000000000000000000000000000deadbeef","value":"0x0","gas":"0x7148","gasUsed":"0x2d0","input":"0x","output":"0x","calls":[{"type":"CALL","from":"0x00000000000000000000000000000000deadbeef","to":"0x00000000000000000000000000000000000000ff","value":"0x0","gas":"0x6cbf","gasUsed":"0x0","input":"0x","output":"0x"}]}`
|
||||||
|
want := new(callTrace)
|
||||||
|
json.Unmarshal([]byte(wantStr), want)
|
||||||
|
if !jsonEqual(have, want) {
|
||||||
|
t.Error("have != want")
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user