forked from cerc-io/plugeth
Merge tag 'v1.10.10' into develop
This commit is contained in:
+63
-1
@@ -35,6 +35,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
@@ -342,7 +343,7 @@ func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs,
|
||||
} else {
|
||||
blockRlp = fmt.Sprintf("0x%x", rlpBytes)
|
||||
}
|
||||
if blockJSON, err = ethapi.RPCMarshalBlock(block, true, true); err != nil {
|
||||
if blockJSON, err = ethapi.RPCMarshalBlock(block, true, true, api.eth.APIBackend.ChainConfig()); err != nil {
|
||||
blockJSON = map[string]interface{}{"error": err.Error()}
|
||||
}
|
||||
results = append(results, &BadBlockArgs{
|
||||
@@ -545,3 +546,64 @@ func (api *PrivateDebugAPI) getModifiedAccounts(startBlock, endBlock *types.Bloc
|
||||
}
|
||||
return dirty, nil
|
||||
}
|
||||
|
||||
// GetAccessibleState returns the first number where the node has accessible
|
||||
// state on disk. Note this being the post-state of that block and the pre-state
|
||||
// of the next block.
|
||||
// The (from, to) parameters are the sequence of blocks to search, which can go
|
||||
// either forwards or backwards
|
||||
func (api *PrivateDebugAPI) GetAccessibleState(from, to rpc.BlockNumber) (uint64, error) {
|
||||
db := api.eth.ChainDb()
|
||||
var pivot uint64
|
||||
if p := rawdb.ReadLastPivotNumber(db); p != nil {
|
||||
pivot = *p
|
||||
log.Info("Found fast-sync pivot marker", "number", pivot)
|
||||
}
|
||||
var resolveNum = func(num rpc.BlockNumber) (uint64, error) {
|
||||
// We don't have state for pending (-2), so treat it as latest
|
||||
if num.Int64() < 0 {
|
||||
block := api.eth.blockchain.CurrentBlock()
|
||||
if block == nil {
|
||||
return 0, fmt.Errorf("current block missing")
|
||||
}
|
||||
return block.NumberU64(), nil
|
||||
}
|
||||
return uint64(num.Int64()), nil
|
||||
}
|
||||
var (
|
||||
start uint64
|
||||
end uint64
|
||||
delta = int64(1)
|
||||
lastLog time.Time
|
||||
err error
|
||||
)
|
||||
if start, err = resolveNum(from); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if end, err = resolveNum(to); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if start == end {
|
||||
return 0, fmt.Errorf("from and to needs to be different")
|
||||
}
|
||||
if start > end {
|
||||
delta = -1
|
||||
}
|
||||
for i := int64(start); i != int64(end); i += delta {
|
||||
if time.Since(lastLog) > 8*time.Second {
|
||||
log.Info("Finding roots", "from", start, "to", end, "at", i)
|
||||
lastLog = time.Now()
|
||||
}
|
||||
if i < int64(pivot) {
|
||||
continue
|
||||
}
|
||||
h := api.eth.BlockChain().GetHeaderByNumber(uint64(i))
|
||||
if h == nil {
|
||||
return 0, fmt.Errorf("missing header %d", i)
|
||||
}
|
||||
if ok, _ := api.eth.ChainDb().Has(h.Root[:]); ok {
|
||||
return uint64(i), nil
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("No state found")
|
||||
}
|
||||
|
||||
+10
-5
@@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
@@ -194,7 +195,10 @@ func (b *EthAPIBackend) GetLogs(ctx context.Context, hash common.Hash) ([][]*typ
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) GetTd(ctx context.Context, hash common.Hash) *big.Int {
|
||||
return b.eth.blockchain.GetTdByHash(hash)
|
||||
if header := b.eth.blockchain.GetHeaderByHash(hash); header != nil {
|
||||
return b.eth.blockchain.GetTd(hash, header.Number.Uint64())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config) (*vm.EVM, func() error, error) {
|
||||
@@ -236,10 +240,7 @@ func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
|
||||
pending, err := b.eth.txPool.Pending(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pending := b.eth.txPool.Pending(false)
|
||||
var txs types.Transactions
|
||||
for _, batch := range pending {
|
||||
txs = append(txs, batch...)
|
||||
@@ -316,6 +317,10 @@ func (b *EthAPIBackend) RPCGasCap() uint64 {
|
||||
return b.eth.config.RPCGasCap
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) RPCEVMTimeout() time.Duration {
|
||||
return b.eth.config.RPCEVMTimeout
|
||||
}
|
||||
|
||||
func (b *EthAPIBackend) RPCTxFeeCap() float64 {
|
||||
return b.eth.config.RPCTxFeeCap
|
||||
}
|
||||
|
||||
+1
-1
@@ -555,7 +555,7 @@ func (s *Ethereum) Stop() error {
|
||||
s.bloomIndexer.Close()
|
||||
close(s.closeBloomHandler)
|
||||
s.txPool.Stop()
|
||||
s.miner.Stop()
|
||||
s.miner.Close()
|
||||
s.blockchain.Stop()
|
||||
s.engine.Close()
|
||||
rawdb.PopUncleanShutdownMarker(s.chainDb)
|
||||
|
||||
+3
-8
@@ -39,10 +39,8 @@ import (
|
||||
// Register adds catalyst APIs to the node.
|
||||
func Register(stack *node.Node, backend *eth.Ethereum) error {
|
||||
chainconfig := backend.BlockChain().Config()
|
||||
if chainconfig.CatalystBlock == nil {
|
||||
return errors.New("catalystBlock is not set in genesis config")
|
||||
} else if chainconfig.CatalystBlock.Sign() != 0 {
|
||||
return errors.New("catalystBlock of genesis config must be zero")
|
||||
if chainconfig.TerminalTotalDifficulty == nil {
|
||||
return errors.New("catalyst started without valid total difficulty")
|
||||
}
|
||||
|
||||
log.Warn("Catalyst mode enabled")
|
||||
@@ -128,10 +126,7 @@ func (api *consensusAPI) AssembleBlock(params assembleBlockParams) (*executableD
|
||||
time.Sleep(wait)
|
||||
}
|
||||
|
||||
pending, err := pool.Pending(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pending := pool.Pending(true)
|
||||
|
||||
coinbase, err := api.eth.Etherbase()
|
||||
if err != nil {
|
||||
|
||||
+20
-14
@@ -62,26 +62,28 @@ func generateTestChain() (*core.Genesis, []*types.Block) {
|
||||
return genesis, blocks
|
||||
}
|
||||
|
||||
// TODO (MariusVanDerWijden) reenable once engine api is updated to the latest spec
|
||||
/*
|
||||
func generateTestChainWithFork(n int, fork int) (*core.Genesis, []*types.Block, []*types.Block) {
|
||||
if fork >= n {
|
||||
fork = n - 1
|
||||
}
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
config := ¶ms.ChainConfig{
|
||||
ChainID: big.NewInt(1337),
|
||||
HomesteadBlock: big.NewInt(0),
|
||||
EIP150Block: big.NewInt(0),
|
||||
EIP155Block: big.NewInt(0),
|
||||
EIP158Block: big.NewInt(0),
|
||||
ByzantiumBlock: big.NewInt(0),
|
||||
ConstantinopleBlock: big.NewInt(0),
|
||||
PetersburgBlock: big.NewInt(0),
|
||||
IstanbulBlock: big.NewInt(0),
|
||||
MuirGlacierBlock: big.NewInt(0),
|
||||
BerlinBlock: big.NewInt(0),
|
||||
LondonBlock: big.NewInt(0),
|
||||
CatalystBlock: big.NewInt(0),
|
||||
Ethash: new(params.EthashConfig),
|
||||
ChainID: big.NewInt(1337),
|
||||
HomesteadBlock: big.NewInt(0),
|
||||
EIP150Block: big.NewInt(0),
|
||||
EIP155Block: big.NewInt(0),
|
||||
EIP158Block: big.NewInt(0),
|
||||
ByzantiumBlock: big.NewInt(0),
|
||||
ConstantinopleBlock: big.NewInt(0),
|
||||
PetersburgBlock: big.NewInt(0),
|
||||
IstanbulBlock: big.NewInt(0),
|
||||
MuirGlacierBlock: big.NewInt(0),
|
||||
BerlinBlock: big.NewInt(0),
|
||||
LondonBlock: big.NewInt(0),
|
||||
TerminalTotalDifficulty: big.NewInt(0),
|
||||
Ethash: new(params.EthashConfig),
|
||||
}
|
||||
genesis := &core.Genesis{
|
||||
Config: config,
|
||||
@@ -105,6 +107,7 @@ func generateTestChainWithFork(n int, fork int) (*core.Genesis, []*types.Block,
|
||||
forkedBlocks, _ := core.GenerateChain(config, blocks[fork], engine, db, n-fork, generateFork)
|
||||
return genesis, blocks, forkedBlocks
|
||||
}
|
||||
*/
|
||||
|
||||
func TestEth2AssembleBlock(t *testing.T) {
|
||||
genesis, blocks := generateTestChain()
|
||||
@@ -156,6 +159,8 @@ func TestEth2AssembleBlockWithAnotherBlocksTxs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO (MariusVanDerWijden) reenable once engine api is updated to the latest spec
|
||||
/*
|
||||
func TestEth2NewBlock(t *testing.T) {
|
||||
genesis, blocks, forkedBlocks := generateTestChainWithFork(10, 4)
|
||||
n, ethservice := startEthService(t, genesis, blocks[1:5])
|
||||
@@ -216,6 +221,7 @@ func TestEth2NewBlock(t *testing.T) {
|
||||
t.Fatalf("Wrong head after inserting fork %x != %x", exp, ethservice.BlockChain().CurrentBlock().Hash())
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// startEthService creates a full node instance for testing.
|
||||
func startEthService(t *testing.T, genesis *core.Genesis, blocks []*types.Block) (*node.Node, *eth.Ethereum) {
|
||||
|
||||
@@ -87,10 +87,11 @@ var Defaults = Config{
|
||||
GasPrice: big.NewInt(params.GWei),
|
||||
Recommit: 3 * time.Second,
|
||||
},
|
||||
TxPool: core.DefaultTxPoolConfig,
|
||||
RPCGasCap: 50000000,
|
||||
GPO: FullNodeGPO,
|
||||
RPCTxFeeCap: 1, // 1 ether
|
||||
TxPool: core.DefaultTxPoolConfig,
|
||||
RPCGasCap: 50000000,
|
||||
RPCEVMTimeout: 5 * time.Second,
|
||||
GPO: FullNodeGPO,
|
||||
RPCTxFeeCap: 1, // 1 ether
|
||||
}
|
||||
|
||||
func init() {
|
||||
@@ -188,6 +189,9 @@ type Config struct {
|
||||
// RPCGasCap is the global gas cap for eth-call variants.
|
||||
RPCGasCap uint64
|
||||
|
||||
// RPCEVMTimeout is the global timeout for eth-call.
|
||||
RPCEVMTimeout time.Duration
|
||||
|
||||
// RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for
|
||||
// send-transction variants. The unit is ether.
|
||||
RPCTxFeeCap float64
|
||||
|
||||
@@ -55,6 +55,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||
EnablePreimageRecording bool
|
||||
DocRoot string `toml:"-"`
|
||||
RPCGasCap uint64
|
||||
RPCEVMTimeout time.Duration
|
||||
RPCTxFeeCap float64
|
||||
Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
|
||||
CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
|
||||
@@ -98,6 +99,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
|
||||
enc.EnablePreimageRecording = c.EnablePreimageRecording
|
||||
enc.DocRoot = c.DocRoot
|
||||
enc.RPCGasCap = c.RPCGasCap
|
||||
enc.RPCEVMTimeout = c.RPCEVMTimeout
|
||||
enc.RPCTxFeeCap = c.RPCTxFeeCap
|
||||
enc.Checkpoint = c.Checkpoint
|
||||
enc.CheckpointOracle = c.CheckpointOracle
|
||||
@@ -145,6 +147,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||
EnablePreimageRecording *bool
|
||||
DocRoot *string `toml:"-"`
|
||||
RPCGasCap *uint64
|
||||
RPCEVMTimeout *time.Duration
|
||||
RPCTxFeeCap *float64
|
||||
Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
|
||||
CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
|
||||
@@ -265,6 +268,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
|
||||
if dec.RPCGasCap != nil {
|
||||
c.RPCGasCap = *dec.RPCGasCap
|
||||
}
|
||||
if dec.RPCEVMTimeout != nil {
|
||||
c.RPCEVMTimeout = *dec.RPCEVMTimeout
|
||||
}
|
||||
if dec.RPCTxFeeCap != nil {
|
||||
c.RPCTxFeeCap = *dec.RPCTxFeeCap
|
||||
}
|
||||
|
||||
@@ -506,58 +506,80 @@ func TestPendingLogsSubscription(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
pendingBlockNumber = big.NewInt(rpc.PendingBlockNumber.Int64())
|
||||
|
||||
testCases = []struct {
|
||||
crit ethereum.FilterQuery
|
||||
expected []*types.Log
|
||||
c chan []*types.Log
|
||||
sub *Subscription
|
||||
err chan error
|
||||
}{
|
||||
// match all
|
||||
{
|
||||
ethereum.FilterQuery{}, flattenLogs(allLogs),
|
||||
nil, nil,
|
||||
ethereum.FilterQuery{FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
|
||||
flattenLogs(allLogs),
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match none due to no matching addresses
|
||||
{
|
||||
ethereum.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}},
|
||||
ethereum.FilterQuery{Addresses: []common.Address{{}, notUsedAddress}, Topics: [][]common.Hash{nil}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
|
||||
nil,
|
||||
nil, nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match logs based on addresses, ignore topics
|
||||
{
|
||||
ethereum.FilterQuery{Addresses: []common.Address{firstAddr}},
|
||||
ethereum.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
|
||||
append(flattenLogs(allLogs[:2]), allLogs[5][3]),
|
||||
nil, nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match none due to no matching topics (match with address)
|
||||
{
|
||||
ethereum.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}},
|
||||
ethereum.FilterQuery{Addresses: []common.Address{secondAddr}, Topics: [][]common.Hash{{notUsedTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
|
||||
nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match logs based on addresses and topics
|
||||
{
|
||||
ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}},
|
||||
ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
|
||||
append(flattenLogs(allLogs[3:5]), allLogs[5][0]),
|
||||
nil, nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match logs based on multiple addresses and "or" topics
|
||||
{
|
||||
ethereum.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}},
|
||||
ethereum.FilterQuery{Addresses: []common.Address{secondAddr, thirdAddress}, Topics: [][]common.Hash{{firstTopic, secondTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
|
||||
append(flattenLogs(allLogs[2:5]), allLogs[5][0]),
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
// block numbers are ignored for filters created with New***Filter, these return all logs that match the given criteria when the state changes
|
||||
{
|
||||
ethereum.FilterQuery{Addresses: []common.Address{firstAddr}, FromBlock: big.NewInt(2), ToBlock: big.NewInt(3)},
|
||||
append(flattenLogs(allLogs[:2]), allLogs[5][3]),
|
||||
nil, nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
// multiple pending logs, should match only 2 topics from the logs in block 5
|
||||
{
|
||||
ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}},
|
||||
ethereum.FilterQuery{Addresses: []common.Address{thirdAddress}, Topics: [][]common.Hash{{firstTopic, fourthTopic}}, FromBlock: pendingBlockNumber, ToBlock: pendingBlockNumber},
|
||||
[]*types.Log{allLogs[5][0], allLogs[5][2]},
|
||||
nil, nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match none due to only matching new mined logs
|
||||
{
|
||||
ethereum.FilterQuery{},
|
||||
nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match none due to only matching mined logs within a specific block range
|
||||
{
|
||||
ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(2)},
|
||||
nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match all due to matching mined and pending logs
|
||||
{
|
||||
ethereum.FilterQuery{FromBlock: big.NewInt(rpc.LatestBlockNumber.Int64()), ToBlock: big.NewInt(rpc.PendingBlockNumber.Int64())},
|
||||
flattenLogs(allLogs),
|
||||
nil, nil, nil,
|
||||
},
|
||||
// match none due to matching logs from a specific block number to new mined blocks
|
||||
{
|
||||
ethereum.FilterQuery{FromBlock: big.NewInt(1), ToBlock: big.NewInt(rpc.LatestBlockNumber.Int64())},
|
||||
nil,
|
||||
nil, nil, nil,
|
||||
},
|
||||
}
|
||||
)
|
||||
@@ -567,43 +589,69 @@ func TestPendingLogsSubscription(t *testing.T) {
|
||||
// (some) events are posted.
|
||||
for i := range testCases {
|
||||
testCases[i].c = make(chan []*types.Log)
|
||||
testCases[i].sub, _ = api.events.SubscribeLogs(testCases[i].crit, testCases[i].c)
|
||||
testCases[i].err = make(chan error)
|
||||
|
||||
var err error
|
||||
testCases[i].sub, err = api.events.SubscribeLogs(testCases[i].crit, testCases[i].c)
|
||||
if err != nil {
|
||||
t.Fatalf("SubscribeLogs %d failed: %v\n", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
for n, test := range testCases {
|
||||
i := n
|
||||
tt := test
|
||||
go func() {
|
||||
defer tt.sub.Unsubscribe()
|
||||
|
||||
var fetched []*types.Log
|
||||
|
||||
timeout := time.After(1 * time.Second)
|
||||
fetchLoop:
|
||||
for {
|
||||
logs := <-tt.c
|
||||
fetched = append(fetched, logs...)
|
||||
if len(fetched) >= len(tt.expected) {
|
||||
select {
|
||||
case logs := <-tt.c:
|
||||
// Do not break early if we've fetched greater, or equal,
|
||||
// to the number of logs expected. This ensures we do not
|
||||
// deadlock the filter system because it will do a blocking
|
||||
// send on this channel if another log arrives.
|
||||
fetched = append(fetched, logs...)
|
||||
case <-timeout:
|
||||
break fetchLoop
|
||||
}
|
||||
}
|
||||
|
||||
if len(fetched) != len(tt.expected) {
|
||||
panic(fmt.Sprintf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched)))
|
||||
tt.err <- fmt.Errorf("invalid number of logs for case %d, want %d log(s), got %d", i, len(tt.expected), len(fetched))
|
||||
return
|
||||
}
|
||||
|
||||
for l := range fetched {
|
||||
if fetched[l].Removed {
|
||||
panic(fmt.Sprintf("expected log not to be removed for log %d in case %d", l, i))
|
||||
tt.err <- fmt.Errorf("expected log not to be removed for log %d in case %d", l, i)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(fetched[l], tt.expected[l]) {
|
||||
panic(fmt.Sprintf("invalid log on index %d for case %d", l, i))
|
||||
tt.err <- fmt.Errorf("invalid log on index %d for case %d\n", l, i)
|
||||
return
|
||||
}
|
||||
}
|
||||
tt.err <- nil
|
||||
}()
|
||||
}
|
||||
|
||||
// raise events
|
||||
time.Sleep(1 * time.Second)
|
||||
for _, ev := range allLogs {
|
||||
backend.pendingLogsFeed.Send(ev)
|
||||
}
|
||||
|
||||
for i := range testCases {
|
||||
err := <-testCases[i].err
|
||||
if err != nil {
|
||||
t.Fatalf("test %d failed: %v", i, err)
|
||||
}
|
||||
<-testCases[i].sub.Err()
|
||||
}
|
||||
}
|
||||
|
||||
// TestPendingTxFilterDeadlock tests if the event loop hangs when pending
|
||||
|
||||
@@ -99,18 +99,14 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
|
||||
var (
|
||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||
addr = crypto.PubkeyToAddress(key.PublicKey)
|
||||
config = *params.TestChainConfig // needs copy because it is modified below
|
||||
gspec = &core.Genesis{
|
||||
Config: params.TestChainConfig,
|
||||
Config: &config,
|
||||
Alloc: core.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}},
|
||||
}
|
||||
signer = types.LatestSigner(gspec.Config)
|
||||
)
|
||||
if londonBlock != nil {
|
||||
gspec.Config.LondonBlock = londonBlock
|
||||
signer = types.LatestSigner(gspec.Config)
|
||||
} else {
|
||||
gspec.Config.LondonBlock = nil
|
||||
}
|
||||
config.LondonBlock = londonBlock
|
||||
engine := ethash.NewFaker()
|
||||
db := rawdb.NewMemoryDatabase()
|
||||
genesis, _ := gspec.Commit(db)
|
||||
@@ -119,9 +115,9 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
|
||||
blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, testHead+1, func(i int, b *core.BlockGen) {
|
||||
b.SetCoinbase(common.Address{1})
|
||||
|
||||
var tx *types.Transaction
|
||||
var txdata types.TxData
|
||||
if londonBlock != nil && b.Number().Cmp(londonBlock) >= 0 {
|
||||
txdata := &types.DynamicFeeTx{
|
||||
txdata = &types.DynamicFeeTx{
|
||||
ChainID: gspec.Config.ChainID,
|
||||
Nonce: b.TxNonce(addr),
|
||||
To: &common.Address{},
|
||||
@@ -130,9 +126,8 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
|
||||
GasTipCap: big.NewInt(int64(i+1) * params.GWei),
|
||||
Data: []byte{},
|
||||
}
|
||||
tx = types.NewTx(txdata)
|
||||
} else {
|
||||
txdata := &types.LegacyTx{
|
||||
txdata = &types.LegacyTx{
|
||||
Nonce: b.TxNonce(addr),
|
||||
To: &common.Address{},
|
||||
Gas: 21000,
|
||||
@@ -140,18 +135,13 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
|
||||
Value: big.NewInt(100),
|
||||
Data: []byte{},
|
||||
}
|
||||
tx = types.NewTx(txdata)
|
||||
}
|
||||
tx, err := types.SignTx(tx, signer, key)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create tx: %v", err)
|
||||
}
|
||||
b.AddTx(tx)
|
||||
b.AddTx(types.MustSignNewTx(key, signer, txdata))
|
||||
})
|
||||
// Construct testing chain
|
||||
diskdb := rawdb.NewMemoryDatabase()
|
||||
gspec.Commit(diskdb)
|
||||
chain, err := core.NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil)
|
||||
chain, err := core.NewBlockChain(diskdb, &core.CacheConfig{TrieCleanNoPrefetch: true}, &config, engine, vm.Config{}, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create local chain, %v", err)
|
||||
}
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ type txPool interface {
|
||||
|
||||
// Pending should return pending transactions.
|
||||
// The slice should be modifiable by the caller.
|
||||
Pending(enforceTips bool) (map[common.Address]types.Transactions, error)
|
||||
Pending(enforceTips bool) map[common.Address]types.Transactions
|
||||
|
||||
// SubscribeNewTxsEvent should return an event subscription of
|
||||
// NewTxsEvent and send events to the given channel.
|
||||
|
||||
@@ -486,7 +486,6 @@ func TestCheckpointChallenge(t *testing.T) {
|
||||
}
|
||||
|
||||
func testCheckpointChallenge(t *testing.T, syncmode downloader.SyncMode, checkpoint bool, timeout bool, empty bool, match bool, drop bool) {
|
||||
t.Parallel()
|
||||
|
||||
// Reduce the checkpoint handshake challenge timeout
|
||||
defer func(old time.Duration) { syncChallengeTimeout = old }(syncChallengeTimeout)
|
||||
|
||||
+2
-2
@@ -91,7 +91,7 @@ func (p *testTxPool) AddRemotes(txs []*types.Transaction) []error {
|
||||
}
|
||||
|
||||
// Pending returns all the transactions known to the pool
|
||||
func (p *testTxPool) Pending(enforceTips bool) (map[common.Address]types.Transactions, error) {
|
||||
func (p *testTxPool) Pending(enforceTips bool) map[common.Address]types.Transactions {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
|
||||
@@ -103,7 +103,7 @@ func (p *testTxPool) Pending(enforceTips bool) (map[common.Address]types.Transac
|
||||
for _, batch := range batches {
|
||||
sort.Sort(types.TxByNonce(batch))
|
||||
}
|
||||
return batches, nil
|
||||
return batches
|
||||
}
|
||||
|
||||
// SubscribeNewTxsEvent should return an event subscription of NewTxsEvent and
|
||||
|
||||
@@ -75,18 +75,18 @@ func (p *Peer) broadcastTransactions() {
|
||||
if done == nil && len(queue) > 0 {
|
||||
// Pile transaction until we reach our allowed network limit
|
||||
var (
|
||||
hashes []common.Hash
|
||||
txs []*types.Transaction
|
||||
size common.StorageSize
|
||||
hashesCount uint64
|
||||
txs []*types.Transaction
|
||||
size common.StorageSize
|
||||
)
|
||||
for i := 0; i < len(queue) && size < maxTxPacketSize; i++ {
|
||||
if tx := p.txpool.Get(queue[i]); tx != nil {
|
||||
txs = append(txs, tx)
|
||||
size += tx.Size()
|
||||
}
|
||||
hashes = append(hashes, queue[i])
|
||||
hashesCount++
|
||||
}
|
||||
queue = queue[:copy(queue, queue[len(hashes):])]
|
||||
queue = queue[:copy(queue, queue[hashesCount:])]
|
||||
|
||||
// If there's anything available to transfer, fire up an async writer
|
||||
if len(txs) > 0 {
|
||||
|
||||
@@ -126,6 +126,12 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
|
||||
for i := range unknown {
|
||||
unknown[i] = byte(i)
|
||||
}
|
||||
getHashes := func(from, limit uint64) (hashes []common.Hash) {
|
||||
for i := uint64(0); i < limit; i++ {
|
||||
hashes = append(hashes, backend.chain.GetCanonicalHash(from-1-i))
|
||||
}
|
||||
return hashes
|
||||
}
|
||||
// Create a batch of tests for various scenarios
|
||||
limit := uint64(maxHeadersServe)
|
||||
tests := []struct {
|
||||
@@ -183,7 +189,7 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
|
||||
// Ensure protocol limits are honored
|
||||
{
|
||||
&GetBlockHeadersPacket{Origin: HashOrNumber{Number: backend.chain.CurrentBlock().NumberU64() - 1}, Amount: limit + 10, Reverse: true},
|
||||
backend.chain.GetBlockHashesFromHash(backend.chain.CurrentBlock().Hash(), limit),
|
||||
getHashes(backend.chain.CurrentBlock().NumberU64(), limit),
|
||||
},
|
||||
// Check that requesting more than available is handled gracefully
|
||||
{
|
||||
@@ -379,7 +385,7 @@ func testGetNodeData(t *testing.T, protocol uint) {
|
||||
acc2Addr := crypto.PubkeyToAddress(acc2Key.PublicKey)
|
||||
|
||||
signer := types.HomesteadSigner{}
|
||||
// Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_markets_test)
|
||||
// Create a chain generator with some simple transactions (blatantly stolen from @fjl/chain_makers_test)
|
||||
generator := func(i int, block *core.BlockGen) {
|
||||
switch i {
|
||||
case 0:
|
||||
@@ -414,9 +420,8 @@ func testGetNodeData(t *testing.T, protocol uint) {
|
||||
peer, _ := newTestPeer("peer", protocol, backend)
|
||||
defer peer.close()
|
||||
|
||||
// Fetch for now the entire chain db
|
||||
// Collect all state tree hashes.
|
||||
var hashes []common.Hash
|
||||
|
||||
it := backend.db.NewIterator(nil, nil)
|
||||
for it.Next() {
|
||||
if key := it.Key(); len(key) == common.HashLength {
|
||||
@@ -425,6 +430,7 @@ func testGetNodeData(t *testing.T, protocol uint) {
|
||||
}
|
||||
it.Release()
|
||||
|
||||
// Request all hashes.
|
||||
p2p.Send(peer.app, GetNodeDataMsg, GetNodeDataPacket66{
|
||||
RequestId: 123,
|
||||
GetNodeDataPacket: hashes,
|
||||
@@ -436,38 +442,40 @@ func testGetNodeData(t *testing.T, protocol uint) {
|
||||
if msg.Code != NodeDataMsg {
|
||||
t.Fatalf("response packet code mismatch: have %x, want %x", msg.Code, NodeDataMsg)
|
||||
}
|
||||
var (
|
||||
data [][]byte
|
||||
res NodeDataPacket66
|
||||
)
|
||||
var res NodeDataPacket66
|
||||
if err := msg.Decode(&res); err != nil {
|
||||
t.Fatalf("failed to decode response node data: %v", err)
|
||||
}
|
||||
data = res.NodeDataPacket
|
||||
// Verify that all hashes correspond to the requested data, and reconstruct a state tree
|
||||
|
||||
// Verify that all hashes correspond to the requested data.
|
||||
data := res.NodeDataPacket
|
||||
for i, want := range hashes {
|
||||
if hash := crypto.Keccak256Hash(data[i]); hash != want {
|
||||
t.Errorf("data hash mismatch: have %x, want %x", hash, want)
|
||||
}
|
||||
}
|
||||
statedb := rawdb.NewMemoryDatabase()
|
||||
|
||||
// Reconstruct state tree from the received data.
|
||||
reconstructDB := rawdb.NewMemoryDatabase()
|
||||
for i := 0; i < len(data); i++ {
|
||||
statedb.Put(hashes[i].Bytes(), data[i])
|
||||
rawdb.WriteTrieNode(reconstructDB, hashes[i], data[i])
|
||||
}
|
||||
|
||||
// Sanity check whether all state matches.
|
||||
accounts := []common.Address{testAddr, acc1Addr, acc2Addr}
|
||||
for i := uint64(0); i <= backend.chain.CurrentBlock().NumberU64(); i++ {
|
||||
trie, _ := state.New(backend.chain.GetBlockByNumber(i).Root(), state.NewDatabase(statedb), nil)
|
||||
|
||||
root := backend.chain.GetBlockByNumber(i).Root()
|
||||
reconstructed, _ := state.New(root, state.NewDatabase(reconstructDB), nil)
|
||||
for j, acc := range accounts {
|
||||
state, _ := backend.chain.State()
|
||||
state, _ := backend.chain.StateAt(root)
|
||||
bw := state.GetBalance(acc)
|
||||
bh := trie.GetBalance(acc)
|
||||
bh := reconstructed.GetBalance(acc)
|
||||
|
||||
if (bw != nil && bh == nil) || (bw == nil && bh != nil) {
|
||||
t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw)
|
||||
if (bw == nil) != (bh == nil) {
|
||||
t.Errorf("block %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw)
|
||||
}
|
||||
if bw != nil && bh != nil && bw.Cmp(bw) != 0 {
|
||||
t.Errorf("test %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw)
|
||||
if bw != nil && bh != nil && bw.Cmp(bh) != 0 {
|
||||
t.Errorf("block %d, account %d: balance mismatch: have %v, want %v", i, j, bh, bw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -43,7 +43,7 @@ func (h *handler) syncTransactions(p *eth.Peer) {
|
||||
//
|
||||
// TODO(karalabe): Figure out if we could get away with random order somehow
|
||||
var txs types.Transactions
|
||||
pending, _ := h.txpool.Pending(false)
|
||||
pending := h.txpool.Pending(false)
|
||||
for _, batch := range pending {
|
||||
txs = append(txs, batch...)
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
|
||||
// If we're in fast sync mode, return that directly
|
||||
if atomic.LoadUint32(&cs.handler.fastSync) == 1 {
|
||||
block := cs.handler.chain.CurrentFastBlock()
|
||||
td := cs.handler.chain.GetTdByHash(block.Hash())
|
||||
td := cs.handler.chain.GetTd(block.Hash(), block.NumberU64())
|
||||
return downloader.FastSync, td
|
||||
}
|
||||
// We are probably in full sync, but we might have rewound to before the
|
||||
@@ -190,7 +190,7 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
|
||||
if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil {
|
||||
if head := cs.handler.chain.CurrentBlock(); head.NumberU64() < *pivot {
|
||||
block := cs.handler.chain.CurrentFastBlock()
|
||||
td := cs.handler.chain.GetTdByHash(block.Hash())
|
||||
td := cs.handler.chain.GetTd(block.Hash(), block.NumberU64())
|
||||
return downloader.FastSync, td
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -18,77 +18,68 @@
|
||||
// callFrameTracer uses the new call frame tracing methods to report useful information
|
||||
// about internal messages of a transaction.
|
||||
{
|
||||
callstack: [{}],
|
||||
fault: function(log, db) {
|
||||
var len = this.callstack.length
|
||||
if (len > 1) {
|
||||
var call = this.callstack.pop()
|
||||
if (this.callstack[len-1].calls === undefined) {
|
||||
this.callstack[len-1].calls = []
|
||||
}
|
||||
this.callstack[len-1].calls.push(call)
|
||||
}
|
||||
},
|
||||
result: function(ctx, db) {
|
||||
// Prepare outer message info
|
||||
var result = {
|
||||
type: ctx.type,
|
||||
from: toHex(ctx.from),
|
||||
to: toHex(ctx.to),
|
||||
value: '0x' + ctx.value.toString(16),
|
||||
gas: '0x' + bigInt(ctx.gas).toString(16),
|
||||
gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16),
|
||||
input: toHex(ctx.input),
|
||||
output: toHex(ctx.output),
|
||||
}
|
||||
if (this.callstack[0].calls !== undefined) {
|
||||
result.calls = this.callstack[0].calls
|
||||
}
|
||||
if (this.callstack[0].error !== undefined) {
|
||||
result.error = this.callstack[0].error
|
||||
} else if (ctx.error !== undefined) {
|
||||
result.error = ctx.error
|
||||
}
|
||||
if (result.error !== undefined && (result.error !== "execution reverted" || result.output ==="0x")) {
|
||||
delete result.output
|
||||
}
|
||||
callstack: [{}],
|
||||
fault: function(log, db) {},
|
||||
result: function(ctx, db) {
|
||||
// Prepare outer message info
|
||||
var result = {
|
||||
type: ctx.type,
|
||||
from: toHex(ctx.from),
|
||||
to: toHex(ctx.to),
|
||||
value: '0x' + ctx.value.toString(16),
|
||||
gas: '0x' + bigInt(ctx.gas).toString(16),
|
||||
gasUsed: '0x' + bigInt(ctx.gasUsed).toString(16),
|
||||
input: toHex(ctx.input),
|
||||
output: toHex(ctx.output),
|
||||
}
|
||||
if (this.callstack[0].calls !== undefined) {
|
||||
result.calls = this.callstack[0].calls
|
||||
}
|
||||
if (this.callstack[0].error !== undefined) {
|
||||
result.error = this.callstack[0].error
|
||||
} else if (ctx.error !== undefined) {
|
||||
result.error = ctx.error
|
||||
}
|
||||
if (result.error !== undefined && (result.error !== "execution reverted" || result.output ==="0x")) {
|
||||
delete result.output
|
||||
}
|
||||
|
||||
return this.finalize(result)
|
||||
},
|
||||
enter: function(frame) {
|
||||
var call = {
|
||||
type: frame.getType(),
|
||||
from: toHex(frame.getFrom()),
|
||||
to: toHex(frame.getTo()),
|
||||
input: toHex(frame.getInput()),
|
||||
gas: '0x' + bigInt(frame.getGas()).toString('16'),
|
||||
}
|
||||
if (frame.getValue() !== undefined){
|
||||
call.value='0x' + bigInt(frame.getValue()).toString(16)
|
||||
}
|
||||
this.callstack.push(call)
|
||||
},
|
||||
exit: function(frameResult) {
|
||||
var len = this.callstack.length
|
||||
if (len > 1) {
|
||||
var call = this.callstack.pop()
|
||||
call.gasUsed = '0x' + bigInt(frameResult.getGasUsed()).toString('16')
|
||||
var error = frameResult.getError()
|
||||
if (error === undefined) {
|
||||
call.output = toHex(frameResult.getOutput())
|
||||
} else {
|
||||
call.error = error
|
||||
if (call.type === 'CREATE' || call.type === 'CREATE2') {
|
||||
delete call.to
|
||||
}
|
||||
}
|
||||
len -= 1
|
||||
if (this.callstack[len-1].calls === undefined) {
|
||||
this.callstack[len-1].calls = []
|
||||
}
|
||||
this.callstack[len-1].calls.push(call)
|
||||
}
|
||||
},
|
||||
return this.finalize(result)
|
||||
},
|
||||
enter: function(frame) {
|
||||
var call = {
|
||||
type: frame.getType(),
|
||||
from: toHex(frame.getFrom()),
|
||||
to: toHex(frame.getTo()),
|
||||
input: toHex(frame.getInput()),
|
||||
gas: '0x' + bigInt(frame.getGas()).toString('16'),
|
||||
}
|
||||
if (frame.getValue() !== undefined){
|
||||
call.value='0x' + bigInt(frame.getValue()).toString(16)
|
||||
}
|
||||
this.callstack.push(call)
|
||||
},
|
||||
exit: function(frameResult) {
|
||||
var len = this.callstack.length
|
||||
if (len > 1) {
|
||||
var call = this.callstack.pop()
|
||||
call.gasUsed = '0x' + bigInt(frameResult.getGasUsed()).toString('16')
|
||||
var error = frameResult.getError()
|
||||
if (error === undefined) {
|
||||
call.output = toHex(frameResult.getOutput())
|
||||
} else {
|
||||
call.error = error
|
||||
if (call.type === 'CREATE' || call.type === 'CREATE2') {
|
||||
delete call.to
|
||||
}
|
||||
}
|
||||
len -= 1
|
||||
if (this.callstack[len-1].calls === undefined) {
|
||||
this.callstack[len-1].calls = []
|
||||
}
|
||||
this.callstack[len-1].calls.push(call)
|
||||
}
|
||||
},
|
||||
// finalize recreates a call object using the final desired field oder for json
|
||||
// serialization. This is a nicety feature to pass meaningfully ordered results
|
||||
// to users who don't interpret it, just display it.
|
||||
|
||||
@@ -795,9 +795,6 @@ func (jst *Tracer) CaptureExit(output []byte, gasUsed uint64, err error) {
|
||||
if !jst.traceCallFrames {
|
||||
return
|
||||
}
|
||||
if jst.err != nil {
|
||||
return
|
||||
}
|
||||
// If tracing was interrupted, set the error and stop
|
||||
if atomic.LoadUint32(&jst.interrupt) > 0 {
|
||||
jst.err = jst.reason
|
||||
|
||||
@@ -207,7 +207,7 @@ func TestNoStepExec(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIsPrecompile(t *testing.T) {
|
||||
chaincfg := ¶ms.ChainConfig{ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, EIP150Block: big.NewInt(0), EIP150Hash: common.Hash{}, EIP155Block: big.NewInt(0), EIP158Block: big.NewInt(0), ByzantiumBlock: big.NewInt(100), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(200), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(300), LondonBlock: big.NewInt(0), CatalystBlock: nil, Ethash: new(params.EthashConfig), Clique: nil}
|
||||
chaincfg := ¶ms.ChainConfig{ChainID: big.NewInt(1), HomesteadBlock: big.NewInt(0), DAOForkBlock: nil, DAOForkSupport: false, EIP150Block: big.NewInt(0), EIP150Hash: common.Hash{}, EIP155Block: big.NewInt(0), EIP158Block: big.NewInt(0), ByzantiumBlock: big.NewInt(100), ConstantinopleBlock: big.NewInt(0), PetersburgBlock: big.NewInt(0), IstanbulBlock: big.NewInt(200), MuirGlacierBlock: big.NewInt(0), BerlinBlock: big.NewInt(300), LondonBlock: big.NewInt(0), TerminalTotalDifficulty: nil, Ethash: new(params.EthashConfig), Clique: nil}
|
||||
chaincfg.ByzantiumBlock = big.NewInt(100)
|
||||
chaincfg.IstanbulBlock = big.NewInt(200)
|
||||
chaincfg.BerlinBlock = big.NewInt(300)
|
||||
|
||||
Reference in New Issue
Block a user