Merge tag 'v1.10.13' into HEAD
This commit is contained in:
commit
72b7820579
137 files changed
+3214
-1774
No files matched your search
@@ -462,6 +462,9 @@ func (b *SimulatedBackend) PendingNonceAt(ctx context.Context, account common.Ad
|
||||
// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
|
||||
// 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) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
if 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))
|
||||
ttl := rootTTL
|
||||
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}
|
||||
_, err = c.CreateDNSRecord(context.Background(), c.zoneID, record)
|
||||
|
||||
@@ -115,8 +115,9 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
rootTTL = 30 * 60 // 30 min
|
||||
treeNodeTTL = 4 * 7 * 24 * 60 * 60 // 4 weeks
|
||||
rootTTL = 30 * 60 // 30 min
|
||||
treeNodeTTL = 4 * 7 * 24 * 60 * 60 // 4 weeks
|
||||
treeNodeTTLCloudflare = 24 * 60 * 60 // 1 day
|
||||
)
|
||||
|
||||
// dnsSync performs dnsSyncCommand.
|
||||
|
||||
@@ -131,7 +131,7 @@ func (c *Conn) handshake() error {
|
||||
}
|
||||
c.negotiateEthProtocol(msg.Caps)
|
||||
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
|
||||
default:
|
||||
|
||||
@@ -52,35 +52,35 @@ func NewSuite(dest *enode.Node, chainfile string, genesisfile string) (*Suite, e
|
||||
func (s *Suite) AllEthTests() []utesting.Test {
|
||||
return []utesting.Test{
|
||||
// status
|
||||
{Name: "TestStatus", Fn: s.TestStatus},
|
||||
{Name: "TestStatus65", Fn: s.TestStatus65},
|
||||
{Name: "TestStatus66", Fn: s.TestStatus66},
|
||||
// get block headers
|
||||
{Name: "TestGetBlockHeaders", Fn: s.TestGetBlockHeaders},
|
||||
{Name: "TestGetBlockHeaders65", Fn: s.TestGetBlockHeaders65},
|
||||
{Name: "TestGetBlockHeaders66", Fn: s.TestGetBlockHeaders66},
|
||||
{Name: "TestSimultaneousRequests66", Fn: s.TestSimultaneousRequests66},
|
||||
{Name: "TestSameRequestID66", Fn: s.TestSameRequestID66},
|
||||
{Name: "TestZeroRequestID66", Fn: s.TestZeroRequestID66},
|
||||
// get block bodies
|
||||
{Name: "TestGetBlockBodies", Fn: s.TestGetBlockBodies},
|
||||
{Name: "TestGetBlockBodies65", Fn: s.TestGetBlockBodies65},
|
||||
{Name: "TestGetBlockBodies66", Fn: s.TestGetBlockBodies66},
|
||||
// broadcast
|
||||
{Name: "TestBroadcast", Fn: s.TestBroadcast},
|
||||
{Name: "TestBroadcast65", Fn: s.TestBroadcast65},
|
||||
{Name: "TestBroadcast66", Fn: s.TestBroadcast66},
|
||||
{Name: "TestLargeAnnounce", Fn: s.TestLargeAnnounce},
|
||||
{Name: "TestLargeAnnounce65", Fn: s.TestLargeAnnounce65},
|
||||
{Name: "TestLargeAnnounce66", Fn: s.TestLargeAnnounce66},
|
||||
{Name: "TestOldAnnounce", Fn: s.TestOldAnnounce},
|
||||
{Name: "TestOldAnnounce65", Fn: s.TestOldAnnounce65},
|
||||
{Name: "TestOldAnnounce66", Fn: s.TestOldAnnounce66},
|
||||
{Name: "TestBlockHashAnnounce", Fn: s.TestBlockHashAnnounce},
|
||||
{Name: "TestBlockHashAnnounce65", Fn: s.TestBlockHashAnnounce65},
|
||||
{Name: "TestBlockHashAnnounce66", Fn: s.TestBlockHashAnnounce66},
|
||||
// malicious handshakes + status
|
||||
{Name: "TestMaliciousHandshake", Fn: s.TestMaliciousHandshake},
|
||||
{Name: "TestMaliciousStatus", Fn: s.TestMaliciousStatus},
|
||||
{Name: "TestMaliciousHandshake65", Fn: s.TestMaliciousHandshake65},
|
||||
{Name: "TestMaliciousStatus65", Fn: s.TestMaliciousStatus65},
|
||||
{Name: "TestMaliciousHandshake66", Fn: s.TestMaliciousHandshake66},
|
||||
{Name: "TestMaliciousStatus66", Fn: s.TestMaliciousStatus66},
|
||||
// test transactions
|
||||
{Name: "TestTransaction", Fn: s.TestTransaction},
|
||||
{Name: "TestTransaction65", Fn: s.TestTransaction65},
|
||||
{Name: "TestTransaction66", Fn: s.TestTransaction66},
|
||||
{Name: "TestMaliciousTx", Fn: s.TestMaliciousTx},
|
||||
{Name: "TestMaliciousTx65", Fn: s.TestMaliciousTx65},
|
||||
{Name: "TestMaliciousTx66", Fn: s.TestMaliciousTx66},
|
||||
{Name: "TestLargeTxRequest66", Fn: s.TestLargeTxRequest66},
|
||||
{Name: "TestNewPooledTxs66", Fn: s.TestNewPooledTxs66},
|
||||
@@ -89,17 +89,17 @@ func (s *Suite) AllEthTests() []utesting.Test {
|
||||
|
||||
func (s *Suite) EthTests() []utesting.Test {
|
||||
return []utesting.Test{
|
||||
{Name: "TestStatus", Fn: s.TestStatus},
|
||||
{Name: "TestGetBlockHeaders", Fn: s.TestGetBlockHeaders},
|
||||
{Name: "TestGetBlockBodies", Fn: s.TestGetBlockBodies},
|
||||
{Name: "TestBroadcast", Fn: s.TestBroadcast},
|
||||
{Name: "TestLargeAnnounce", Fn: s.TestLargeAnnounce},
|
||||
{Name: "TestOldAnnounce", Fn: s.TestOldAnnounce},
|
||||
{Name: "TestBlockHashAnnounce", Fn: s.TestBlockHashAnnounce},
|
||||
{Name: "TestMaliciousHandshake", Fn: s.TestMaliciousHandshake},
|
||||
{Name: "TestMaliciousStatus", Fn: s.TestMaliciousStatus},
|
||||
{Name: "TestTransaction", Fn: s.TestTransaction},
|
||||
{Name: "TestMaliciousTx", Fn: s.TestMaliciousTx},
|
||||
{Name: "TestStatus65", Fn: s.TestStatus65},
|
||||
{Name: "TestGetBlockHeaders65", Fn: s.TestGetBlockHeaders65},
|
||||
{Name: "TestGetBlockBodies65", Fn: s.TestGetBlockBodies65},
|
||||
{Name: "TestBroadcast65", Fn: s.TestBroadcast65},
|
||||
{Name: "TestLargeAnnounce65", Fn: s.TestLargeAnnounce65},
|
||||
{Name: "TestOldAnnounce65", Fn: s.TestOldAnnounce65},
|
||||
{Name: "TestBlockHashAnnounce65", Fn: s.TestBlockHashAnnounce65},
|
||||
{Name: "TestMaliciousHandshake65", Fn: s.TestMaliciousHandshake65},
|
||||
{Name: "TestMaliciousStatus65", Fn: s.TestMaliciousStatus65},
|
||||
{Name: "TestTransaction65", Fn: s.TestTransaction65},
|
||||
{Name: "TestMaliciousTx65", Fn: s.TestMaliciousTx65},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,9 +130,9 @@ var (
|
||||
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.
|
||||
func (s *Suite) TestStatus(t *utesting.T) {
|
||||
func (s *Suite) TestStatus65(t *utesting.T) {
|
||||
conn, err := s.dial()
|
||||
if err != nil {
|
||||
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.
|
||||
func (s *Suite) TestGetBlockHeaders(t *utesting.T) {
|
||||
func (s *Suite) TestGetBlockHeaders65(t *utesting.T) {
|
||||
conn, err := s.dial()
|
||||
if err != nil {
|
||||
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.
|
||||
func (s *Suite) TestGetBlockBodies(t *utesting.T) {
|
||||
func (s *Suite) TestGetBlockBodies65(t *utesting.T) {
|
||||
conn, err := s.dial()
|
||||
if err != nil {
|
||||
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).
|
||||
func (s *Suite) TestBroadcast(t *utesting.T) {
|
||||
func (s *Suite) TestBroadcast65(t *utesting.T) {
|
||||
if err := s.sendNextBlock(eth65); err != nil {
|
||||
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.
|
||||
func (s *Suite) TestLargeAnnounce(t *utesting.T) {
|
||||
// TestLargeAnnounce65 tests the announcement mechanism with a large block.
|
||||
func (s *Suite) TestLargeAnnounce65(t *utesting.T) {
|
||||
nextBlock := len(s.chain.blocks)
|
||||
blocks := []*NewBlock{
|
||||
{
|
||||
@@ -569,8 +569,8 @@ func (s *Suite) TestLargeAnnounce66(t *utesting.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestOldAnnounce tests the announcement mechanism with an old block.
|
||||
func (s *Suite) TestOldAnnounce(t *utesting.T) {
|
||||
// TestOldAnnounce65 tests the announcement mechanism with an old block.
|
||||
func (s *Suite) TestOldAnnounce65(t *utesting.T) {
|
||||
if err := s.oldAnnounce(eth65); err != nil {
|
||||
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.
|
||||
func (s *Suite) TestBlockHashAnnounce(t *utesting.T) {
|
||||
func (s *Suite) TestBlockHashAnnounce65(t *utesting.T) {
|
||||
if err := s.hashAnnounce(eth65); err != nil {
|
||||
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.
|
||||
func (s *Suite) TestMaliciousHandshake(t *utesting.T) {
|
||||
// TestMaliciousHandshake65 tries to send malicious data during the handshake.
|
||||
func (s *Suite) TestMaliciousHandshake65(t *utesting.T) {
|
||||
if err := s.maliciousHandshakes(t, eth65); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -614,8 +614,8 @@ func (s *Suite) TestMaliciousHandshake66(t *utesting.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestMaliciousStatus sends a status package with a large total difficulty.
|
||||
func (s *Suite) TestMaliciousStatus(t *utesting.T) {
|
||||
// TestMaliciousStatus65 sends a status package with a large total difficulty.
|
||||
func (s *Suite) TestMaliciousStatus65(t *utesting.T) {
|
||||
conn, err := s.dial()
|
||||
if err != nil {
|
||||
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.
|
||||
func (s *Suite) TestTransaction(t *utesting.T) {
|
||||
func (s *Suite) TestTransaction65(t *utesting.T) {
|
||||
if err := s.sendSuccessfulTxs(t, eth65); err != nil {
|
||||
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.
|
||||
func (s *Suite) TestMaliciousTx(t *utesting.T) {
|
||||
func (s *Suite) TestMaliciousTx65(t *utesting.T) {
|
||||
if err := s.sendMaliciousTxs(t, eth65); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
StateRoot common.Hash `json:"stateRoot"`
|
||||
TxRoot common.Hash `json:"txRoot"`
|
||||
ReceiptRoot common.Hash `json:"receiptRoot"`
|
||||
ReceiptRoot common.Hash `json:"receiptsRoot"`
|
||||
LogsHash common.Hash `json:"logsHash"`
|
||||
Bloom types.Bloom `json:"logsBloom" gencodec:"required"`
|
||||
Receipts types.Receipts `json:"receipts"`
|
||||
Rejected []*rejectedTx `json:"rejected,omitempty"`
|
||||
Difficulty *math.HexOrDecimal256 `json:"currentDifficulty" gencodec:"required"`
|
||||
GasUsed math.HexOrDecimal64 `json:"gasUsed"`
|
||||
}
|
||||
|
||||
type ommer struct {
|
||||
@@ -255,6 +256,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||
Receipts: receipts,
|
||||
Rejected: rejectedTxs,
|
||||
Difficulty: (*math.HexOrDecimal256)(vmContext.Difficulty),
|
||||
GasUsed: (math.HexOrDecimal64)(gasUsed),
|
||||
}
|
||||
return statedb, execRs, nil
|
||||
}
|
||||
|
||||
@@ -32,7 +32,11 @@ var (
|
||||
}
|
||||
TraceDisableMemoryFlag = cli.BoolTFlag{
|
||||
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{
|
||||
Name: "trace.nostack",
|
||||
@@ -40,7 +44,11 @@ var (
|
||||
}
|
||||
TraceDisableReturnDataFlag = cli.BoolTFlag{
|
||||
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{
|
||||
Name: "output.basedir",
|
||||
@@ -68,6 +76,14 @@ var (
|
||||
"\t<file> - into the file <file> ",
|
||||
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{
|
||||
Name: "input.alloc",
|
||||
Usage: "`stdin` or file name of where to find the prestate alloc to use.",
|
||||
@@ -81,10 +97,41 @@ var (
|
||||
InputTxsFlag = cli.StringFlag{
|
||||
Name: "input.txs",
|
||||
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.",
|
||||
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{
|
||||
Name: "state.reward",
|
||||
Usage: "Mining reward. Set to -1 to disable",
|
||||
|
||||
@@ -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"`
|
||||
Address *common.Address `json:"address,omitempty"`
|
||||
Hash *common.Hash `json:"hash,omitempty"`
|
||||
IntrinsicGas uint64 `json:"intrinsicGas,omitempty"`
|
||||
IntrinsicGas hexutil.Uint64 `json:"intrinsicGas,omitempty"`
|
||||
}
|
||||
var out xx
|
||||
if r.Error != nil {
|
||||
@@ -60,7 +60,7 @@ func (r *result) MarshalJSON() ([]byte, error) {
|
||||
if r.Hash != (common.Hash{}) {
|
||||
out.Hash = &r.Hash
|
||||
}
|
||||
out.IntrinsicGas = r.IntrinsicGas
|
||||
out.IntrinsicGas = hexutil.Uint64(r.IntrinsicGas)
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ func Transaction(ctx *cli.Context) error {
|
||||
)
|
||||
// Construct the chainconfig
|
||||
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 {
|
||||
chainConfig = cConf
|
||||
}
|
||||
@@ -154,6 +154,8 @@ func Transaction(ctx *cli.Context) error {
|
||||
}
|
||||
// Validate <256bit fields
|
||||
switch {
|
||||
case tx.Nonce()+1 < tx.Nonce():
|
||||
r.Error = errors.New("nonce exceeds 2^64-1")
|
||||
case tx.Value().BitLen() > 256:
|
||||
r.Error = errors.New("value exceeds 256 bits")
|
||||
case tx.GasPrice().BitLen() > 256:
|
||||
|
||||
@@ -43,11 +43,12 @@ import (
|
||||
|
||||
const (
|
||||
ErrorEVM = 2
|
||||
ErrorVMConfig = 3
|
||||
ErrorConfig = 3
|
||||
ErrorMissingBlockhash = 4
|
||||
|
||||
ErrorJson = 10
|
||||
ErrorIO = 11
|
||||
ErrorRlp = 12
|
||||
|
||||
stdinSelector = "stdin"
|
||||
)
|
||||
@@ -88,28 +89,33 @@ func Transition(ctx *cli.Context) error {
|
||||
log.Root().SetHandler(glogger)
|
||||
|
||||
var (
|
||||
err error
|
||||
tracer vm.EVMLogger
|
||||
baseDir = ""
|
||||
err error
|
||||
tracer vm.EVMLogger
|
||||
)
|
||||
var getTracer func(txIndex int, txHash common.Hash) (vm.EVMLogger, error)
|
||||
|
||||
// If user specified a basedir, make sure it exists
|
||||
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 NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
|
||||
}
|
||||
baseDir = base
|
||||
}
|
||||
baseDir, err := createBasedir(ctx)
|
||||
if err != nil {
|
||||
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
|
||||
}
|
||||
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
|
||||
logConfig := &vm.LogConfig{
|
||||
DisableStack: ctx.Bool(TraceDisableStackFlag.Name),
|
||||
EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name),
|
||||
EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name),
|
||||
EnableMemory: !ctx.Bool(TraceDisableMemoryFlag.Name) || ctx.Bool(TraceEnableMemoryFlag.Name),
|
||||
EnableReturnData: !ctx.Bool(TraceDisableReturnDataFlag.Name) || ctx.Bool(TraceEnableReturnDataFlag.Name),
|
||||
Debug: true,
|
||||
}
|
||||
var prevFile *os.File
|
||||
@@ -155,29 +161,17 @@ func Transition(ctx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
if allocStr != stdinSelector {
|
||||
inFile, err := os.Open(allocStr)
|
||||
if err != nil {
|
||||
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))
|
||||
if err := readFile(allocStr, "alloc", &inputData.Alloc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
prestate.Pre = inputData.Alloc
|
||||
|
||||
// Set the block environment
|
||||
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
|
||||
if err := decoder.Decode(&env); err != nil {
|
||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshaling env-file: %v", err))
|
||||
if err := readFile(envStr, "env", &env); err != nil {
|
||||
return err
|
||||
}
|
||||
inputData.Env = &env
|
||||
}
|
||||
@@ -190,7 +184,7 @@ func Transition(ctx *cli.Context) error {
|
||||
// Construct the chainconfig
|
||||
var chainConfig *params.ChainConfig
|
||||
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 {
|
||||
chainConfig = cConf
|
||||
vmConfig.ExtraEips = extraEips
|
||||
@@ -254,18 +248,18 @@ func Transition(ctx *cli.Context) error {
|
||||
// Sanity check, to not `panic` in state_transition
|
||||
if chainConfig.IsLondon(big.NewInt(int64(prestate.Env.Number))) {
|
||||
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 difficulty was not provided by caller, we need to calculate it.
|
||||
switch {
|
||||
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:
|
||||
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:
|
||||
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))
|
||||
}
|
||||
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
|
||||
// a `secretKey`-field, for input
|
||||
type txWithKey struct {
|
||||
key *ecdsa.PrivateKey
|
||||
tx *types.Transaction
|
||||
key *ecdsa.PrivateKey
|
||||
tx *types.Transaction
|
||||
protected bool
|
||||
}
|
||||
|
||||
func (t *txWithKey) UnmarshalJSON(input []byte) error {
|
||||
// Read the secretKey, if present
|
||||
type sKey struct {
|
||||
Key *common.Hash `json:"secretKey"`
|
||||
// Read the metadata, if present
|
||||
type txMetadata struct {
|
||||
Key *common.Hash `json:"secretKey"`
|
||||
Protected *bool `json:"protected"`
|
||||
}
|
||||
var key sKey
|
||||
if err := json.Unmarshal(input, &key); err != nil {
|
||||
var data txMetadata
|
||||
if err := json.Unmarshal(input, &data); err != nil {
|
||||
return err
|
||||
}
|
||||
if key.Key != nil {
|
||||
k := key.Key.Hex()[2:]
|
||||
if data.Key != nil {
|
||||
k := data.Key.Hex()[2:]
|
||||
if ecdsaKey, err := crypto.HexToECDSA(k); err != nil {
|
||||
return err
|
||||
} else {
|
||||
t.key = ecdsaKey
|
||||
}
|
||||
}
|
||||
if data.Protected != nil {
|
||||
t.protected = *data.Protected
|
||||
} else {
|
||||
t.protected = true
|
||||
}
|
||||
// Now, read the transaction itself
|
||||
var tx types.Transaction
|
||||
if err := json.Unmarshal(input, &tx); err != nil {
|
||||
@@ -335,7 +336,15 @@ func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Tran
|
||||
v, r, s := tx.RawSignatureValues()
|
||||
if key != nil && v.BitLen()+r.BitLen()+s.BitLen() == 0 {
|
||||
// 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 {
|
||||
return nil, NewError(ErrorJson, fmt.Errorf("tx %d: failed to sign tx: %v", i, err))
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
t8ntool.TraceFlag,
|
||||
t8ntool.TraceDisableMemoryFlag,
|
||||
t8ntool.TraceEnableMemoryFlag,
|
||||
t8ntool.TraceDisableStackFlag,
|
||||
t8ntool.TraceDisableReturnDataFlag,
|
||||
t8ntool.TraceEnableReturnDataFlag,
|
||||
t8ntool.OutputBasedir,
|
||||
t8ntool.OutputAllocFlag,
|
||||
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() {
|
||||
app.Flags = []cli.Flag{
|
||||
BenchFlag,
|
||||
@@ -200,6 +221,7 @@ func init() {
|
||||
stateTestCommand,
|
||||
stateTransitionCommand,
|
||||
transactionCommand,
|
||||
blockBuilderCommand,
|
||||
}
|
||||
cli.CommandHelpTemplate = flags.OriginCommandHelpTemplate
|
||||
}
|
||||
|
||||
+130
-2
@@ -131,7 +131,7 @@ func TestT8n(t *testing.T) {
|
||||
output: t8nOutput{alloc: true, result: true},
|
||||
expExitCode: 4,
|
||||
},
|
||||
{ // Ommer test
|
||||
{ // Uncle test
|
||||
base: "./testdata/5",
|
||||
input: t8nInput{
|
||||
"alloc.json", "txs.json", "env.json", "Byzantium", "0x80",
|
||||
@@ -171,7 +171,7 @@ func TestT8n(t *testing.T) {
|
||||
output: t8nOutput{result: true},
|
||||
expOut: "exp2.json",
|
||||
},
|
||||
{ // Difficulty calculation - with uncles + Berlin
|
||||
{ // Difficulty calculation - with ommers + Berlin
|
||||
base: "./testdata/14",
|
||||
input: t8nInput{
|
||||
"alloc.json", "txs.json", "env.uncles.json", "Berlin", "",
|
||||
@@ -195,6 +195,14 @@ func TestT8n(t *testing.T) {
|
||||
output: t8nOutput{result: true},
|
||||
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"}
|
||||
@@ -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.
|
||||
func cmpJson(a, b []byte) (bool, error) {
|
||||
var j, j2 interface{}
|
||||
|
||||
Vendored
+4
-3
@@ -15,7 +15,7 @@
|
||||
"result": {
|
||||
"stateRoot": "0x84208a19bc2b46ada7445180c1db162be5b39b9abc8c0a54b05d32943eae4e13",
|
||||
"txRoot": "0xc4761fd7b87ff2364c7c60b6c5c8d02e522e815328aaea3f20e3b7b7ef52c42d",
|
||||
"receiptRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
|
||||
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receipts": [
|
||||
@@ -38,6 +38,7 @@
|
||||
"error": "nonce too low: address 0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192, tx: 0 state: 1"
|
||||
}
|
||||
],
|
||||
"currentDifficulty": "0x20000"
|
||||
"currentDifficulty": "0x20000",
|
||||
"gasUsed": "0x5208"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+3
-2
@@ -2,7 +2,7 @@
|
||||
"result": {
|
||||
"stateRoot": "0xe4b924a6adb5959fccf769d5b7bb2f6359e26d1e76a2443c5a91a36d826aef61",
|
||||
"txRoot": "0x013509c8563d41c0ae4bf38f2d6d19fc6512a1d0d6be045079c8c9f68bf45f9d",
|
||||
"receiptRoot": "0xa532a08aa9f62431d6fe5d924951b8efb86ed3c54d06fee77788c3767dd13420",
|
||||
"receiptsRoot": "0xa532a08aa9f62431d6fe5d924951b8efb86ed3c54d06fee77788c3767dd13420",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receipts": [
|
||||
@@ -33,6 +33,7 @@
|
||||
"transactionIndex": "0x1"
|
||||
}
|
||||
],
|
||||
"currentDifficulty": "0x20000"
|
||||
"currentDifficulty": "0x20000",
|
||||
"gasUsed": "0x109a0"
|
||||
}
|
||||
}
|
||||
Vendored
+4
-3
@@ -2,10 +2,11 @@
|
||||
"result": {
|
||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"currentDifficulty": "0x2000020000000",
|
||||
"receipts": []
|
||||
"receipts": [],
|
||||
"gasUsed": "0x0"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+4
-3
@@ -2,10 +2,11 @@
|
||||
"result": {
|
||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receipts": [],
|
||||
"currentDifficulty": "0x1ff8020000000"
|
||||
"currentDifficulty": "0x1ff8020000000",
|
||||
"gasUsed": "0x0"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+4
-3
@@ -2,10 +2,11 @@
|
||||
"result": {
|
||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receipts": [],
|
||||
"currentDifficulty": "0x1ff9000000000"
|
||||
"currentDifficulty": "0x1ff9000000000",
|
||||
"gasUsed": "0x0"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+2
-2
@@ -2,11 +2,11 @@
|
||||
{
|
||||
"address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
|
||||
"hash": "0xa98a24882ea90916c6a86da650fbc6b14238e46f0af04a131ce92be897507476",
|
||||
"intrinsicGas": 21000
|
||||
"intrinsicGas": "0x5208"
|
||||
},
|
||||
{
|
||||
"address": "0xd02d72e067e77158444ef2020ff2d325f929b363",
|
||||
"hash": "0x36bad80acce7040c45fd32764b5c2b2d2e6f778669fb41791f73f546d56e739a",
|
||||
"intrinsicGas": 21000
|
||||
"intrinsicGas": "0x5208"
|
||||
}
|
||||
]
|
||||
Vendored
+2
-2
@@ -2,12 +2,12 @@
|
||||
{
|
||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"hash": "0x7cc3d1a8540a44736750f03bb4d85c0113be4b3472a71bf82241a3b261b479e6",
|
||||
"intrinsicGas": 21000
|
||||
"intrinsicGas": "0x5208"
|
||||
},
|
||||
{
|
||||
"error": "intrinsic gas too low: have 82, want 21000",
|
||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"hash": "0x3b2d2609e4361562edb9169314f4c05afc6dbf5d706bf9dda5abe242ab76a22b",
|
||||
"intrinsicGas": 21000
|
||||
"intrinsicGas": "0x5208"
|
||||
}
|
||||
]
|
||||
Vendored
+2
-2
@@ -3,13 +3,13 @@
|
||||
"error": "value exceeds 256 bits",
|
||||
"address": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"hash": "0xfbd91685dcbf8172f0e8c53e2ddbb4d26707840da6b51a74371f62a33868fd82",
|
||||
"intrinsicGas": 21000
|
||||
"intrinsicGas": "0x5208"
|
||||
},
|
||||
{
|
||||
"error": "gasPrice exceeds 256 bits",
|
||||
"address": "0x1b57ccef1fe5fb73f1e64530fb4ebd9cf1655964",
|
||||
"hash": "0x45dc05035cada83748e4c1fe617220106b331eca054f44c2304d5654a9fb29d5",
|
||||
"intrinsicGas": 21000
|
||||
"intrinsicGas": "0x5208"
|
||||
},
|
||||
{
|
||||
"error": "invalid transaction v, r, s values",
|
||||
|
||||
+4
-3
@@ -2,10 +2,11 @@
|
||||
"result": {
|
||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"currentDifficulty": "0x2000000200000",
|
||||
"receipts": []
|
||||
"receipts": [],
|
||||
"gasUsed": "0x0"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+4
-3
@@ -2,10 +2,11 @@
|
||||
"result": {
|
||||
"stateRoot": "0x6f058887ca01549716789c380ede95aecc510e6d1fdc4dbf67d053c7c07f4bdc",
|
||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"currentDifficulty": "0x2000080000000",
|
||||
"receipts": []
|
||||
"receipts": [],
|
||||
"gasUsed": "0x0"
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"rlp": "0xf902d9f90211a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e997a23b159e2e2a5ce72333262972374b15425ca0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e99476574682f76312e302e312f6c696e75782f676f312e342e32a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf8897435673d874f7c8f8c2f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600c0",
|
||||
"hash": "0xaba9a3b6a4e96e9ecffcadaa5a2ae0589359455617535cd86589fe1dd26fe899"
|
||||
}
|
||||
Vendored
+14
@@ -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"
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
Vendored
+11
@@ -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"
|
||||
}
|
||||
```
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
"0xf8c2f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600f85f8002825208948a8eafb1cf62bfbeb1741769dae1a9dd4799619201801ba09500e8ba27d3c33ca7764e107410f44cbd8c19794bde214d694683a7aa998cdba07235ae07e4bd6e0206d102b1f8979d6adab280466b6a82d2208ee08951f1f600"
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
|
||||
"voted": "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||
"authorize": false,
|
||||
"vanity": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"rlp": "0xf9025ff9025aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277eb861aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac540a67aaee364005841da84f488f6b6d0116dfb5103d091402c81a163d5f66666595e37f56f196d8c5c98da714dbfae68d6b7e1790cc734a20ec6ce52213ad800a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88ffffffffffffffffc0c0",
|
||||
"hash": "0x71c59102cc805dbe8741e1210ebe229a321eff144ac7276006fefe39e8357dc7"
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"rlp": "0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0",
|
||||
"hash": "0x801411e9f6609a659825690d13e4f75a3cfe9143952fa2d9573f3b0a5eb9ebbb"
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e",
|
||||
"stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"difficulty": "0x1000",
|
||||
"number": "0xc3be",
|
||||
"gasLimit": "0x50785",
|
||||
"gasUsed": "0x0",
|
||||
"timestamp": "0x55c5277e",
|
||||
"mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf"
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
Vendored
+23
@@ -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"
|
||||
}
|
||||
```
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
"c0"
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"rlp": "0xf9025ff9025aa0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277eb861aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac540a67aaee364005841da84f488f6b6d0116dfb5103d091402c81a163d5f66666595e37f56f196d8c5c98da714dbfae68d6b7e1790cc734a20ec6ce52213ad800a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf88ffffffffffffffffc0c0",
|
||||
"hash": "0x71c59102cc805dbe8741e1210ebe229a321eff144ac7276006fefe39e8357dc7"
|
||||
}
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"rlp": "0xf905f5f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea06eb9f0c3cd68c9e97134e6725d12b1f1d8f0644458da6870a37ff84c908fb1e7940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0f903f6f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000f901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000",
|
||||
"hash": "0xd9a81c8fcd57a7f2a0d2c375eff6ad192c30c3729a271303f0a9a7e1b357e755"
|
||||
}
|
||||
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"parentHash": "0xd6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34e",
|
||||
"stateRoot": "0x325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2e",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"difficulty": "0x1000",
|
||||
"number": "0xc3be",
|
||||
"gasLimit": "0x50785",
|
||||
"gasUsed": "0x0",
|
||||
"timestamp": "0x55c5277e",
|
||||
"mixHash": "0x5865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf"
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
["0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0","0xf901fdf901f8a0d6d785d33cbecf30f30d07e00e226af58f72efdf385d46bc3e6326c23b11e34ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0325aea6db48e9d737cddf59034843e99f05bec269453be83c9b9a981a232cc2ea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000082100082c3be83050785808455c5277e80a05865e417635a26db6d1d39ac70d1abf373e5398b3c6fd506acd038fa1334eedf880000000000000000c0c0"]
|
||||
Vendored
+11
@@ -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"
|
||||
}
|
||||
```
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
"c0"
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"0x095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
|
||||
"balance" : "0x0de0b6b3a7640000",
|
||||
"code" : "0x6001",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x0de0b6b3a7640000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"currentCoinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
|
||||
"currentDifficulty" : "0x020000",
|
||||
"currentGasLimit" : "0x3b9aca00",
|
||||
"currentNumber" : "0x05",
|
||||
"currentTimestamp" : "0x03e8"
|
||||
}
|
||||
Vendored
+25
@@ -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"
|
||||
}
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
These files examplify how to sign a transaction using the pre-EIP155 scheme.
|
||||
Vendored
+15
@@ -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
|
||||
}
|
||||
]
|
||||
Vendored
+3
-2
@@ -15,7 +15,7 @@
|
||||
"result": {
|
||||
"stateRoot": "0xb7341da3f9f762a6884eaa186c32942734c146b609efee11c4b0214c44857ea1",
|
||||
"txRoot": "0x75e61774a2ff58cbe32653420256c7f44bc715715a423b0b746d5c622979af6b",
|
||||
"receiptRoot": "0xd0d26df80374a327c025d405ebadc752b1bbd089d864801ae78ab704bcad8086",
|
||||
"receiptsRoot": "0xd0d26df80374a327c025d405ebadc752b1bbd089d864801ae78ab704bcad8086",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receipts": [
|
||||
@@ -32,6 +32,7 @@
|
||||
"transactionIndex": "0x0"
|
||||
}
|
||||
],
|
||||
"currentDifficulty": "0x20000"
|
||||
"currentDifficulty": "0x20000",
|
||||
"gasUsed": "0x521f"
|
||||
}
|
||||
}
|
||||
Vendored
+3
-2
@@ -13,10 +13,11 @@
|
||||
"result": {
|
||||
"stateRoot": "0xa7312add33811645c6aa65d928a1a4f49d65d448801912c069a0aa8fe9c1f393",
|
||||
"txRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"logsHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
|
||||
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receipts": [],
|
||||
"currentDifficulty": "0x20000"
|
||||
"currentDifficulty": "0x20000",
|
||||
"gasUsed": "0x0"
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,7 @@ Remove blockchain and state databases`,
|
||||
ArgsUsage: "<prefix> <start>",
|
||||
Flags: []cli.Flag{
|
||||
utils.DataDirFlag,
|
||||
utils.AncientFlag,
|
||||
utils.SyncModeFlag,
|
||||
utils.MainnetFlag,
|
||||
utils.RopstenFlag,
|
||||
|
||||
+3
-1
@@ -43,7 +43,8 @@ import (
|
||||
"github.com/ethereum/go-ethereum/plugins"
|
||||
"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"
|
||||
|
||||
"gopkg.in/urfave/cli.v1"
|
||||
@@ -142,6 +143,7 @@ var (
|
||||
utils.MainnetFlag,
|
||||
utils.DeveloperFlag,
|
||||
utils.DeveloperPeriodFlag,
|
||||
utils.DeveloperGasLimitFlag,
|
||||
utils.RopstenFlag,
|
||||
utils.SepoliaFlag,
|
||||
utils.RinkebyFlag,
|
||||
|
||||
@@ -75,6 +75,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
|
||||
Flags: []cli.Flag{
|
||||
utils.DeveloperFlag,
|
||||
utils.DeveloperPeriodFlag,
|
||||
utils.DeveloperGasLimitFlag,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
+6
-1
@@ -167,6 +167,11 @@ var (
|
||||
Name: "dev.period",
|
||||
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{
|
||||
Name: "identity",
|
||||
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)
|
||||
|
||||
// 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) {
|
||||
// Check if we have an already initialized chain and fall back to
|
||||
// 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)
|
||||
}
|
||||
ethConf := ðconfig.Config{
|
||||
Genesis: core.DeveloperGenesisBlock(15, common.Address{}),
|
||||
Genesis: core.DeveloperGenesisBlock(15, 11_500_000, common.Address{}),
|
||||
Miner: miner.Config{
|
||||
Etherbase: common.HexToAddress(testAddress),
|
||||
},
|
||||
|
||||
+8
-8
@@ -296,7 +296,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
||||
if diskRoot != (common.Hash{}) {
|
||||
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 {
|
||||
return nil, err
|
||||
}
|
||||
@@ -306,7 +306,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
||||
}
|
||||
} else {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -482,11 +482,11 @@ func (bc *BlockChain) loadLastState() error {
|
||||
// was fast synced or full synced and in which state, the method will try to
|
||||
// delete minimal data from disk whilst retaining chain consistency.
|
||||
func (bc *BlockChain) SetHead(head uint64) error {
|
||||
_, err := bc.SetHeadBeyondRoot(head, common.Hash{})
|
||||
_, err := bc.setHeadBeyondRoot(head, common.Hash{}, false)
|
||||
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
|
||||
// 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
|
||||
@@ -494,7 +494,7 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
||||
// retaining chain consistency.
|
||||
//
|
||||
// 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() {
|
||||
return 0, errChainStopped
|
||||
}
|
||||
@@ -509,7 +509,7 @@ func (bc *BlockChain) SetHeadBeyondRoot(head uint64, root common.Hash) (uint64,
|
||||
frozen, _ := bc.db.Ancients()
|
||||
|
||||
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
|
||||
// chain reparation mechanism without deleting any data!
|
||||
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
|
||||
// touching the header chain altogether, unless the freezer is broken
|
||||
if block := bc.CurrentBlock(); block.NumberU64() == head {
|
||||
if target, force := updateFn(bc.db, block.Header()); force {
|
||||
if repair {
|
||||
if target, force := updateFn(bc.db, bc.CurrentBlock().Header()); force {
|
||||
bc.hc.SetHead(target, updateFn, delFn)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -51,6 +51,10 @@ var (
|
||||
// next one expected based on the local chain.
|
||||
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
|
||||
// by a transaction is higher than what's left in the block.
|
||||
ErrGasLimitReached = errors.New("gas limit reached")
|
||||
|
||||
+2
-2
@@ -416,7 +416,7 @@ func DefaultSepoliaGenesisBlock() *Genesis {
|
||||
}
|
||||
|
||||
// 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
|
||||
config := *params.AllCliqueProtocolChanges
|
||||
config.Clique = ¶ms.CliqueConfig{
|
||||
@@ -428,7 +428,7 @@ func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
|
||||
return &Genesis{
|
||||
Config: &config,
|
||||
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
|
||||
GasLimit: 11500000,
|
||||
GasLimit: gasLimit,
|
||||
BaseFee: big.NewInt(params.InitialBaseFee),
|
||||
Difficulty: big.NewInt(1),
|
||||
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
|
||||
// are populated with metadata. In case the receipts or the block body
|
||||
// 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
|
||||
data := ReadReceiptsRLP(db, hash, number)
|
||||
if len(data) == 0 {
|
||||
@@ -677,7 +677,12 @@ func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log {
|
||||
}
|
||||
receipts := []*receiptLogs{}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -697,6 +702,21 @@ func ReadLogs(db ethdb.Reader, hash common.Hash, number uint64) [][]*types.Log {
|
||||
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
|
||||
// back from the stored header and body. If either the header or body could not
|
||||
// be retrieved nil is returned.
|
||||
|
||||
@@ -744,7 +744,7 @@ func TestReadLogs(t *testing.T) {
|
||||
// Insert the receipt slice into the database and check presence
|
||||
WriteReceipts(db, hash, 0, receipts)
|
||||
|
||||
logs := ReadLogs(db, hash, 0)
|
||||
logs := ReadLogs(db, hash, 0, params.TestChainConfig)
|
||||
if len(logs) == 0 {
|
||||
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
|
||||
hash common.Hash
|
||||
)
|
||||
for i := uint64(0); i < frozen; i++ {
|
||||
// Since the freezer has all data in sequential order on a file,
|
||||
// it would be 'neat' to read more data in one go, and let the
|
||||
// freezerdb return N items (e.g up to 1000 items per go)
|
||||
// That would require an API change in Ancients though
|
||||
if h, err := db.Ancient(freezerHashTable, i); err != nil {
|
||||
for i := uint64(0); i < frozen; {
|
||||
// We read 100K hashes at a time, for a total of 3.2M
|
||||
count := uint64(100_000)
|
||||
if i+count > frozen {
|
||||
count = frozen - i
|
||||
}
|
||||
data, err := db.AncientRange(freezerHashTable, i, count, 32*count)
|
||||
if err != nil {
|
||||
log.Crit("Failed to init database from freezer", "err", err)
|
||||
} else {
|
||||
}
|
||||
for j, h := range data {
|
||||
number := i + uint64(j)
|
||||
hash = common.BytesToHash(h)
|
||||
}
|
||||
WriteHeaderNumber(batch, hash, i)
|
||||
// If enough data was accumulated in memory or we're at the last block, dump to disk
|
||||
if batch.ValueSize() > ethdb.IdealBatchSize {
|
||||
if err := batch.Write(); err != nil {
|
||||
log.Crit("Failed to write data to db", "err", err)
|
||||
WriteHeaderNumber(batch, hash, number)
|
||||
// If enough data was accumulated in memory or we're at the last block, dump to disk
|
||||
if batch.ValueSize() > ethdb.IdealBatchSize {
|
||||
if err := batch.Write(); err != nil {
|
||||
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 time.Since(logged) > 8*time.Second {
|
||||
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.
|
||||
func (batch *freezerTableBatch) Append(item uint64, data interface{}) error {
|
||||
if item != batch.curItem {
|
||||
return errOutOrderInsertion
|
||||
return fmt.Errorf("%w: have %d want %d", errOutOrderInsertion, item, batch.curItem)
|
||||
}
|
||||
|
||||
// Encode the item.
|
||||
@@ -138,7 +138,7 @@ func (batch *freezerTableBatch) Append(item uint64, data interface{}) error {
|
||||
// existing data.
|
||||
func (batch *freezerTableBatch) AppendRaw(item uint64, blob []byte) error {
|
||||
if item != batch.curItem {
|
||||
return errOutOrderInsertion
|
||||
return fmt.Errorf("%w: have %d want %d", errOutOrderInsertion, item, batch.curItem)
|
||||
}
|
||||
|
||||
encItem := blob
|
||||
|
||||
@@ -246,7 +246,7 @@ func TestFreezerConcurrentModifyTruncate(t *testing.T) {
|
||||
if truncateErr != nil {
|
||||
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)
|
||||
}
|
||||
checkAncientCount(t, f, "test", 10)
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"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/ethash"
|
||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||
@@ -54,11 +56,12 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||
LondonBlock: big.NewInt(0),
|
||||
Ethash: new(params.EthashConfig),
|
||||
}
|
||||
signer = types.LatestSigner(config)
|
||||
testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
signer = types.LatestSigner(config)
|
||||
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 {
|
||||
tx, _ := types.SignTx(types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data), signer, testKey)
|
||||
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, key)
|
||||
return tx
|
||||
}
|
||||
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,
|
||||
To: &to,
|
||||
Value: big.NewInt(0),
|
||||
}), signer, testKey)
|
||||
}), signer, key1)
|
||||
return tx
|
||||
}
|
||||
{ // Tests against a 'recent' chain definition
|
||||
@@ -82,6 +85,10 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||
Nonce: 0,
|
||||
},
|
||||
common.HexToAddress("0xfd0810DD14796680f72adf1a371963d0745BCc64"): GenesisAccount{
|
||||
Balance: big.NewInt(1000000000000000000), // 1 ether
|
||||
Nonce: math.MaxUint64,
|
||||
},
|
||||
},
|
||||
}
|
||||
genesis = gspec.MustCommit(db)
|
||||
@@ -97,32 +104,38 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||
}{
|
||||
{ // ErrNonceTooLow
|
||||
txs: []*types.Transaction{
|
||||
makeTx(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),
|
||||
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",
|
||||
},
|
||||
{ // ErrNonceTooHigh
|
||||
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",
|
||||
},
|
||||
{ // 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
|
||||
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",
|
||||
},
|
||||
{ // ErrInsufficientFundsForTransfer
|
||||
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",
|
||||
},
|
||||
{ // ErrInsufficientFunds
|
||||
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",
|
||||
},
|
||||
@@ -132,13 +145,13 @@ func TestStateProcessorErrors(t *testing.T) {
|
||||
// multiplication len(data) +gas_per_byte overflows uint64. Not testable at the moment
|
||||
{ // ErrIntrinsicGas
|
||||
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",
|
||||
},
|
||||
{ // ErrGasLimitReached
|
||||
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",
|
||||
},
|
||||
|
||||
@@ -222,6 +222,9 @@ func (st *StateTransition) preCheck() error {
|
||||
} else if stNonce > msgNonce {
|
||||
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow,
|
||||
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
|
||||
if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyCodeHash && codeHash != (common.Hash{}) {
|
||||
|
||||
+3
-2
@@ -621,8 +621,9 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
|
||||
if err != nil {
|
||||
return ErrInvalidSender
|
||||
}
|
||||
// Drop non-local transactions under our own minimal accepted gas price or tip
|
||||
if !local && tx.GasTipCapIntCmp(pool.gasPrice) < 0 {
|
||||
// Drop non-local transactions under our own minimal accepted gas price or tip.
|
||||
pendingBaseFee := pool.priced.urgent.baseFee
|
||||
if !local && tx.EffectiveGasTipIntCmp(pool.gasPrice, pendingBaseFee) < 0 {
|
||||
return ErrUnderpriced
|
||||
}
|
||||
// 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.
|
||||
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
|
||||
if (op == SLOAD || op == SSTORE) && stack.len() >= 1 {
|
||||
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) {}
|
||||
|
||||
@@ -35,6 +35,7 @@ var (
|
||||
ErrReturnDataOutOfBounds = errors.New("return data out of bounds")
|
||||
ErrGasUintOverflow = errors.New("gas uint64 overflow")
|
||||
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
|
||||
|
||||
@@ -424,6 +424,9 @@ func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64,
|
||||
return nil, common.Address{}, gas, ErrInsufficientBalance
|
||||
}
|
||||
nonce := evm.StateDB.GetNonce(caller.Address())
|
||||
if nonce+1 < nonce {
|
||||
return nil, common.Address{}, gas, ErrNonceUintOverflow
|
||||
}
|
||||
evm.StateDB.SetNonce(caller.Address(), nonce+1)
|
||||
// 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
|
||||
|
||||
@@ -169,9 +169,9 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
||||
defer func() {
|
||||
if err != nil {
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
+14
-10
@@ -105,10 +105,10 @@ func (s *StructLog) ErrorString() string {
|
||||
// if you need to retain them beyond the current call.
|
||||
type EVMLogger interface {
|
||||
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)
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -119,6 +119,7 @@ type EVMLogger interface {
|
||||
// contract their storage.
|
||||
type StructLogger struct {
|
||||
cfg LogConfig
|
||||
env *EVM
|
||||
|
||||
storage map[common.Address]Storage
|
||||
logs []StructLog
|
||||
@@ -147,12 +148,13 @@ func (l *StructLogger) Reset() {
|
||||
|
||||
// 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) {
|
||||
l.env = env
|
||||
}
|
||||
|
||||
// CaptureState logs a new structured log message and pushes it out to the environment
|
||||
//
|
||||
// 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
|
||||
stack := scope.Stack
|
||||
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 {
|
||||
var (
|
||||
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
|
||||
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)
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
|
||||
// CaptureFault implements the EVMLogger interface to trace an execution fault
|
||||
// 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.
|
||||
@@ -291,12 +293,13 @@ func WriteLogs(writer io.Writer, logs []*types.Log) {
|
||||
type mdLogger struct {
|
||||
out io.Writer
|
||||
cfg *LogConfig
|
||||
env *EVM
|
||||
}
|
||||
|
||||
// NewMarkdownLogger creates a logger which outputs information in a format adapted
|
||||
// for human readability, and is also a valid markdown table
|
||||
func NewMarkdownLogger(cfg *LogConfig, writer io.Writer) *mdLogger {
|
||||
l := &mdLogger{writer, cfg}
|
||||
l := &mdLogger{out: writer, cfg: cfg}
|
||||
if l.cfg == nil {
|
||||
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) {
|
||||
t.env = env
|
||||
if !create {
|
||||
fmt.Fprintf(t.out, "From: `%v`\nTo: `%v`\nData: `0x%x`\nGas: `%d`\nValue `%v` wei\n",
|
||||
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.
|
||||
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
|
||||
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, ","))
|
||||
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, "")
|
||||
if err != nil {
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,12 +29,13 @@ import (
|
||||
type JSONLogger struct {
|
||||
encoder *json.Encoder
|
||||
cfg *LogConfig
|
||||
env *EVM
|
||||
}
|
||||
|
||||
// NewJSONLogger creates a new EVM tracer that prints execution steps as JSON objects
|
||||
// into the provided stream.
|
||||
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 {
|
||||
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) {
|
||||
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.
|
||||
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
|
||||
stack := scope.Stack
|
||||
|
||||
@@ -58,7 +60,7 @@ func (l *JSONLogger) CaptureState(env *EVM, pc uint64, op OpCode, gas, cost uint
|
||||
GasCost: cost,
|
||||
MemorySize: memory.Len(),
|
||||
Depth: depth,
|
||||
RefundCounter: env.StateDB.GetRefund(),
|
||||
RefundCounter: l.env.StateDB.GetRefund(),
|
||||
Err: err,
|
||||
}
|
||||
if l.cfg.EnableMemory {
|
||||
|
||||
@@ -62,7 +62,8 @@ func TestStoreCapture(t *testing.T) {
|
||||
scope.Stack.push(uint256.NewInt(1))
|
||||
scope.Stack.push(new(uint256.Int))
|
||||
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 {
|
||||
t.Fatalf("expected exactly 1 changed value on address %x, got %d", contract.Address(),
|
||||
len(logger.storage[contract.Address()]))
|
||||
|
||||
+66
-57
@@ -39,68 +39,68 @@ func (op OpCode) IsStaticJump() bool {
|
||||
|
||||
// 0x0 range - arithmetic ops.
|
||||
const (
|
||||
STOP OpCode = iota
|
||||
ADD
|
||||
MUL
|
||||
SUB
|
||||
DIV
|
||||
SDIV
|
||||
MOD
|
||||
SMOD
|
||||
ADDMOD
|
||||
MULMOD
|
||||
EXP
|
||||
SIGNEXTEND
|
||||
STOP OpCode = 0x0
|
||||
ADD OpCode = 0x1
|
||||
MUL OpCode = 0x2
|
||||
SUB OpCode = 0x3
|
||||
DIV OpCode = 0x4
|
||||
SDIV OpCode = 0x5
|
||||
MOD OpCode = 0x6
|
||||
SMOD OpCode = 0x7
|
||||
ADDMOD OpCode = 0x8
|
||||
MULMOD OpCode = 0x9
|
||||
EXP OpCode = 0xa
|
||||
SIGNEXTEND OpCode = 0xb
|
||||
)
|
||||
|
||||
// 0x10 range - comparison ops.
|
||||
const (
|
||||
LT OpCode = iota + 0x10
|
||||
GT
|
||||
SLT
|
||||
SGT
|
||||
EQ
|
||||
ISZERO
|
||||
AND
|
||||
OR
|
||||
XOR
|
||||
NOT
|
||||
BYTE
|
||||
SHL
|
||||
SHR
|
||||
SAR
|
||||
LT OpCode = 0x10
|
||||
GT OpCode = 0x11
|
||||
SLT OpCode = 0x12
|
||||
SGT OpCode = 0x13
|
||||
EQ OpCode = 0x14
|
||||
ISZERO OpCode = 0x15
|
||||
AND OpCode = 0x16
|
||||
OR OpCode = 0x17
|
||||
XOR OpCode = 0x18
|
||||
NOT OpCode = 0x19
|
||||
BYTE OpCode = 0x1a
|
||||
SHL OpCode = 0x1b
|
||||
SHR OpCode = 0x1c
|
||||
SAR OpCode = 0x1d
|
||||
|
||||
SHA3 OpCode = 0x20
|
||||
)
|
||||
|
||||
// 0x30 range - closure state.
|
||||
const (
|
||||
ADDRESS OpCode = 0x30 + iota
|
||||
BALANCE
|
||||
ORIGIN
|
||||
CALLER
|
||||
CALLVALUE
|
||||
CALLDATALOAD
|
||||
CALLDATASIZE
|
||||
CALLDATACOPY
|
||||
CODESIZE
|
||||
CODECOPY
|
||||
GASPRICE
|
||||
EXTCODESIZE
|
||||
EXTCODECOPY
|
||||
RETURNDATASIZE
|
||||
RETURNDATACOPY
|
||||
EXTCODEHASH
|
||||
ADDRESS OpCode = 0x30
|
||||
BALANCE OpCode = 0x31
|
||||
ORIGIN OpCode = 0x32
|
||||
CALLER OpCode = 0x33
|
||||
CALLVALUE OpCode = 0x34
|
||||
CALLDATALOAD OpCode = 0x35
|
||||
CALLDATASIZE OpCode = 0x36
|
||||
CALLDATACOPY OpCode = 0x37
|
||||
CODESIZE OpCode = 0x38
|
||||
CODECOPY OpCode = 0x39
|
||||
GASPRICE OpCode = 0x3a
|
||||
EXTCODESIZE OpCode = 0x3b
|
||||
EXTCODECOPY OpCode = 0x3c
|
||||
RETURNDATASIZE OpCode = 0x3d
|
||||
RETURNDATACOPY OpCode = 0x3e
|
||||
EXTCODEHASH OpCode = 0x3f
|
||||
)
|
||||
|
||||
// 0x40 range - block operations.
|
||||
const (
|
||||
BLOCKHASH OpCode = 0x40 + iota
|
||||
COINBASE
|
||||
TIMESTAMP
|
||||
NUMBER
|
||||
DIFFICULTY
|
||||
GASLIMIT
|
||||
BLOCKHASH OpCode = 0x40
|
||||
COINBASE OpCode = 0x41
|
||||
TIMESTAMP OpCode = 0x42
|
||||
NUMBER OpCode = 0x43
|
||||
DIFFICULTY OpCode = 0x44
|
||||
GASLIMIT OpCode = 0x45
|
||||
CHAINID OpCode = 0x46
|
||||
SELFBALANCE OpCode = 0x47
|
||||
BASEFEE OpCode = 0x48
|
||||
@@ -122,7 +122,7 @@ const (
|
||||
JUMPDEST OpCode = 0x5b
|
||||
)
|
||||
|
||||
// 0x60 range.
|
||||
// 0x60 range - pushes.
|
||||
const (
|
||||
PUSH1 OpCode = 0x60 + iota
|
||||
PUSH2
|
||||
@@ -156,7 +156,11 @@ const (
|
||||
PUSH30
|
||||
PUSH31
|
||||
PUSH32
|
||||
DUP1
|
||||
)
|
||||
|
||||
// 0x80 range - dups.
|
||||
const (
|
||||
DUP1 = 0x80 + iota
|
||||
DUP2
|
||||
DUP3
|
||||
DUP4
|
||||
@@ -172,7 +176,11 @@ const (
|
||||
DUP14
|
||||
DUP15
|
||||
DUP16
|
||||
SWAP1
|
||||
)
|
||||
|
||||
// 0x90 range - swaps.
|
||||
const (
|
||||
SWAP1 = 0x90 + iota
|
||||
SWAP2
|
||||
SWAP3
|
||||
SWAP4
|
||||
@@ -208,12 +216,13 @@ const (
|
||||
|
||||
// 0xf0 range - closures.
|
||||
const (
|
||||
CREATE OpCode = 0xf0 + iota
|
||||
CALL
|
||||
CALLCODE
|
||||
RETURN
|
||||
DELEGATECALL
|
||||
CREATE2
|
||||
CREATE OpCode = 0xf0
|
||||
CALL OpCode = 0xf1
|
||||
CALLCODE OpCode = 0xf2
|
||||
RETURN OpCode = 0xf3
|
||||
DELEGATECALL OpCode = 0xf4
|
||||
CREATE2 OpCode = 0xf5
|
||||
|
||||
STATICCALL OpCode = 0xfa
|
||||
REVERT OpCode = 0xfd
|
||||
SELFDESTRUCT OpCode = 0xff
|
||||
|
||||
@@ -35,6 +35,9 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/eth/tracers"
|
||||
"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) {
|
||||
@@ -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) 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) 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++
|
||||
// Enable this for more output
|
||||
//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
|
||||
// EIP-2929 about gas repricings
|
||||
func TestEip2929Cases(t *testing.T) {
|
||||
|
||||
t.Skip("Test only useful for generating documentation")
|
||||
id := 1
|
||||
prettyPrint := func(comment string, code []byte) {
|
||||
|
||||
|
||||
+1
-1
@@ -170,7 +170,7 @@ func (api *PrivateAdminAPI) ExportChain(file string, first *uint64, last *uint64
|
||||
last = &head
|
||||
}
|
||||
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
|
||||
return false, errors.New("location would overwrite an existing file")
|
||||
}
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*typ
|
||||
if number == nil {
|
||||
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 {
|
||||
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.
|
||||
if origin+1 < frozen {
|
||||
if err := d.lightchain.SetHead(origin + 1); err != nil {
|
||||
if err := d.lightchain.SetHead(origin); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,8 +87,7 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
||||
if percent < 0 {
|
||||
percent = 0
|
||||
log.Warn("Sanitizing invalid gasprice oracle sample percentile", "provided", params.Percentile, "updated", percent)
|
||||
}
|
||||
if percent > 100 {
|
||||
} else if percent > 100 {
|
||||
percent = 100
|
||||
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 {
|
||||
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)
|
||||
headEvent := make(chan core.ChainHeadEvent, 1)
|
||||
@@ -125,8 +134,8 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
||||
ignorePrice: ignorePrice,
|
||||
checkBlocks: blocks,
|
||||
percentile: percent,
|
||||
maxHeaderHistory: params.MaxHeaderHistory,
|
||||
maxBlockHistory: params.MaxBlockHistory,
|
||||
maxHeaderHistory: maxHeaderHistory,
|
||||
maxBlockHistory: maxBlockHistory,
|
||||
historyCache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
+139
-198
@@ -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) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -503,90 +362,177 @@ func TestTraceBlock(t *testing.T) {
|
||||
var testSuite = []struct {
|
||||
blockNumber rpc.BlockNumber
|
||||
config *TraceConfig
|
||||
expect interface{}
|
||||
want string
|
||||
expectErr error
|
||||
}{
|
||||
// Trace genesis block, expect error
|
||||
{
|
||||
blockNumber: rpc.BlockNumber(0),
|
||||
config: nil,
|
||||
expect: nil,
|
||||
expectErr: errors.New("genesis is not traceable"),
|
||||
},
|
||||
// Trace head block
|
||||
{
|
||||
blockNumber: rpc.BlockNumber(genBlocks),
|
||||
config: nil,
|
||||
expectErr: nil,
|
||||
expect: []*txTraceResult{
|
||||
{
|
||||
Result: ðapi.ExecutionResult{
|
||||
Gas: params.TxGas,
|
||||
Failed: false,
|
||||
ReturnValue: "",
|
||||
StructLogs: []ethapi.StructLogRes{},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
|
||||
},
|
||||
// Trace non-existent block
|
||||
{
|
||||
blockNumber: rpc.BlockNumber(genBlocks + 1),
|
||||
config: nil,
|
||||
expectErr: fmt.Errorf("block #%d not found", genBlocks+1),
|
||||
expect: nil,
|
||||
},
|
||||
// Trace latest block
|
||||
{
|
||||
blockNumber: rpc.LatestBlockNumber,
|
||||
config: nil,
|
||||
expectErr: nil,
|
||||
expect: []*txTraceResult{
|
||||
{
|
||||
Result: ðapi.ExecutionResult{
|
||||
Gas: params.TxGas,
|
||||
Failed: false,
|
||||
ReturnValue: "",
|
||||
StructLogs: []ethapi.StructLogRes{},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
|
||||
},
|
||||
// Trace pending block
|
||||
{
|
||||
blockNumber: rpc.PendingBlockNumber,
|
||||
config: nil,
|
||||
expectErr: nil,
|
||||
expect: []*txTraceResult{
|
||||
{
|
||||
Result: ðapi.ExecutionResult{
|
||||
Gas: params.TxGas,
|
||||
Failed: false,
|
||||
ReturnValue: "",
|
||||
StructLogs: []ethapi.StructLogRes{},
|
||||
want: `[{"result":{"gas":21000,"failed":false,"returnValue":"","structLogs":[]}}]`,
|
||||
},
|
||||
}
|
||||
for i, tc := range testSuite {
|
||||
result, err := api.TraceBlockByNumber(context.Background(), tc.blockNumber, tc.config)
|
||||
if tc.expectErr != nil {
|
||||
if err == nil {
|
||||
t.Errorf("test %d, want error %v", i, tc.expectErr)
|
||||
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 {
|
||||
result, err := api.TraceBlockByNumber(context.Background(), testspec.blockNumber, testspec.config)
|
||||
if testspec.expectErr != nil {
|
||||
for i, tc := range testSuite {
|
||||
result, err := api.TraceCall(context.Background(), tc.call, rpc.BlockNumberOrHash{BlockNumber: &tc.blockNumber}, tc.config)
|
||||
if tc.expectErr != 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
|
||||
}
|
||||
if !reflect.DeepEqual(err, testspec.expectErr) {
|
||||
t.Errorf("Error mismatch, want %v, get %v", testspec.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)
|
||||
if !errors.Is(err, tc.expectErr) {
|
||||
t.Errorf("test %d: error mismatch, want %v, have %v", i, tc.expectErr, err)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
func newRPCUint64(number uint64) *hexutil.Uint64 {
|
||||
rpcUint64 := hexutil.Uint64(number)
|
||||
return &rpcUint64
|
||||
}
|
||||
|
||||
func newRPCBytes(bytes []byte) *hexutil.Bytes {
|
||||
rpcBytes := hexutil.Bytes(bytes)
|
||||
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;
|
||||
},
|
||||
}
|
||||
+154
-6
@@ -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 (
|
||||
"encoding/json"
|
||||
@@ -17,14 +33,67 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"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/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"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"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
Number math.HexOrDecimal64 `json:"number"`
|
||||
Difficulty *math.HexOrDecimal256 `json:"difficulty"`
|
||||
@@ -70,7 +139,7 @@ func TestCallTracerNative(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 {
|
||||
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)
|
||||
)
|
||||
// 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)
|
||||
} else if err := json.Unmarshal(blob, test); err != nil {
|
||||
t.Fatalf("failed to parse testcase: %v", err)
|
||||
@@ -175,7 +244,7 @@ func camel(str string) string {
|
||||
return strings.Join(pieces, "")
|
||||
}
|
||||
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 {
|
||||
b.Fatalf("failed to retrieve tracer test suite: %v", err)
|
||||
}
|
||||
@@ -185,7 +254,7 @@ func BenchmarkTracers(b *testing.B) {
|
||||
}
|
||||
file := file // capture range variable
|
||||
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 {
|
||||
b.Fatalf("failed to read testcase: %v", err)
|
||||
}
|
||||
@@ -244,3 +313,82 @@ func benchTracer(tracerName string, test *callTracerTest, b *testing.B) {
|
||||
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")
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loaded 100 of 137 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user