mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 15:16:43 +00:00
merge develop
This commit is contained in:
commit
b7a282792c
40 changed files with 957 additions and 200 deletions
23
.github/CODEOWNERS
vendored
23
.github/CODEOWNERS
vendored
|
|
@ -1,23 +0,0 @@
|
||||||
# Lines starting with '#' are comments.
|
|
||||||
# Each line is a file pattern followed by one or more owners.
|
|
||||||
|
|
||||||
accounts/usbwallet @karalabe
|
|
||||||
accounts/scwallet @gballet
|
|
||||||
accounts/abi @gballet @MariusVanDerWijden
|
|
||||||
cmd/clef @holiman
|
|
||||||
cmd/puppeth @karalabe
|
|
||||||
consensus @karalabe
|
|
||||||
core/ @karalabe @holiman @rjl493456442
|
|
||||||
eth/ @karalabe @holiman @rjl493456442
|
|
||||||
eth/catalyst/ @gballet
|
|
||||||
graphql/ @gballet
|
|
||||||
les/ @zsfelfoldi @rjl493456442
|
|
||||||
light/ @zsfelfoldi @rjl493456442
|
|
||||||
mobile/ @karalabe @ligi
|
|
||||||
node/ @fjl @renaynay
|
|
||||||
p2p/ @fjl @zsfelfoldi
|
|
||||||
rpc/ @fjl @holiman
|
|
||||||
p2p/simulations @fjl
|
|
||||||
p2p/protocols @fjl
|
|
||||||
p2p/testing @fjl
|
|
||||||
signer/ @holiman
|
|
||||||
3
.github/matic-cli-config.yml
vendored
3
.github/matic-cli-config.yml
vendored
|
|
@ -3,6 +3,9 @@ defaultFee: 2000
|
||||||
borChainId: "15001"
|
borChainId: "15001"
|
||||||
heimdallChainId: heimdall-15001
|
heimdallChainId: heimdall-15001
|
||||||
contractsBranch: arpit/v0.3.2-backport
|
contractsBranch: arpit/v0.3.2-backport
|
||||||
|
sprintSize: 64
|
||||||
|
blockNumber: '0'
|
||||||
|
blockTime: '2'
|
||||||
numOfValidators: 3
|
numOfValidators: 3
|
||||||
numOfNonValidators: 0
|
numOfNonValidators: 0
|
||||||
ethURL: http://ganache:9545
|
ethURL: http://ganache:9545
|
||||||
|
|
|
||||||
44
.github/pull_request_template.md
vendored
Normal file
44
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
# Description
|
||||||
|
|
||||||
|
Please provide a detailed description of what was done in this PR
|
||||||
|
|
||||||
|
# Changes
|
||||||
|
|
||||||
|
- [ ] Bugfix (non-breaking change that solves an issue)
|
||||||
|
- [ ] Hotfix (change that solves an urgent issue, and requires immediate attention)
|
||||||
|
- [ ] New feature (non-breaking change that adds functionality)
|
||||||
|
- [ ] Breaking change (change that is not backwards-compatible and/or changes current functionality)
|
||||||
|
|
||||||
|
# Breaking changes
|
||||||
|
|
||||||
|
Please complete this section if any breaking changes have been made, otherwise delete it
|
||||||
|
|
||||||
|
# Checklist
|
||||||
|
|
||||||
|
- [ ] I have added at least 2 reviewer or the whole pos-v1 team
|
||||||
|
- [ ] I have added sufficient documentation in code
|
||||||
|
- [ ] I will be resolving comments - if any - by pushing each fix in a separate commit and linking the commit hash in the comment reply
|
||||||
|
|
||||||
|
# Cross repository changes
|
||||||
|
|
||||||
|
- [ ] This PR requires changes to heimdall
|
||||||
|
- In case link the PR here:
|
||||||
|
- [ ] This PR requires changes to matic-cli
|
||||||
|
- In case link the PR here:
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
- [ ] I have added unit tests
|
||||||
|
- [ ] I have added tests to CI
|
||||||
|
- [ ] I have tested this code manually on local environment
|
||||||
|
- [ ] I have tested this code manually on remote devnet using express-cli
|
||||||
|
- [ ] I have tested this code manually on mumbai
|
||||||
|
- [ ] I have created new e2e tests into express-cli
|
||||||
|
|
||||||
|
### Manual tests
|
||||||
|
|
||||||
|
Please complete this section with the steps you performed if you ran manual tests for this functionality, otherwise delete it
|
||||||
|
|
||||||
|
# Additional comments
|
||||||
|
|
||||||
|
Please post additional comments in this section if you have them, otherwise delete it
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -53,3 +53,5 @@ profile.cov
|
||||||
./bor-debug-*
|
./bor-debug-*
|
||||||
|
|
||||||
dist
|
dist
|
||||||
|
|
||||||
|
*.csv
|
||||||
|
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -65,7 +65,7 @@ test-race:
|
||||||
$(GOTEST) --timeout 15m -race -shuffle=on $(TESTALL)
|
$(GOTEST) --timeout 15m -race -shuffle=on $(TESTALL)
|
||||||
|
|
||||||
test-integration:
|
test-integration:
|
||||||
$(GOTEST) --timeout 30m -tags integration $(TESTE2E)
|
$(GOTEST) --timeout 60m -tags integration $(TESTE2E)
|
||||||
|
|
||||||
escape:
|
escape:
|
||||||
cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out
|
cd $(path) && go test -gcflags "-m -m" -run none -bench=BenchmarkJumpdest* -benchmem -memprofile mem.out
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ datadir = "/var/lib/bor/data"
|
||||||
syncmode = "full"
|
syncmode = "full"
|
||||||
# gcmode = "full"
|
# gcmode = "full"
|
||||||
# snapshot = true
|
# snapshot = true
|
||||||
|
# "bor.logs" = false
|
||||||
# ethstats = ""
|
# ethstats = ""
|
||||||
|
|
||||||
# ["eth.requiredblocks"]
|
# ["eth.requiredblocks"]
|
||||||
|
|
@ -77,8 +78,7 @@ syncmode = "full"
|
||||||
# prefix = ""
|
# prefix = ""
|
||||||
# host = "localhost"
|
# host = "localhost"
|
||||||
# api = ["web3", "net"]
|
# api = ["web3", "net"]
|
||||||
# vhosts = ["*"]
|
# origins = ["*"]
|
||||||
# corsdomain = ["*"]
|
|
||||||
# [jsonrpc.graphql]
|
# [jsonrpc.graphql]
|
||||||
# enabled = false
|
# enabled = false
|
||||||
# port = 0
|
# port = 0
|
||||||
|
|
@ -121,6 +121,7 @@ syncmode = "full"
|
||||||
# noprefetch = false
|
# noprefetch = false
|
||||||
# preimages = false
|
# preimages = false
|
||||||
# txlookuplimit = 2350000
|
# txlookuplimit = 2350000
|
||||||
|
# triesinmemory = 128
|
||||||
|
|
||||||
[accounts]
|
[accounts]
|
||||||
# allow-insecure-unlock = true
|
# allow-insecure-unlock = true
|
||||||
|
|
@ -134,4 +135,4 @@ syncmode = "full"
|
||||||
|
|
||||||
# [developer]
|
# [developer]
|
||||||
# dev = false
|
# dev = false
|
||||||
# period = 0
|
# period = 0
|
||||||
|
|
|
||||||
|
|
@ -327,7 +327,7 @@ func setDefaultMumbaiGethConfig(ctx *cli.Context, config *gethConfig) {
|
||||||
config.Eth.TxPool.AccountQueue = 64
|
config.Eth.TxPool.AccountQueue = 64
|
||||||
config.Eth.TxPool.GlobalQueue = 131072
|
config.Eth.TxPool.GlobalQueue = 131072
|
||||||
config.Eth.TxPool.Lifetime = 90 * time.Minute
|
config.Eth.TxPool.Lifetime = 90 * time.Minute
|
||||||
config.Node.P2P.MaxPeers = 200
|
config.Node.P2P.MaxPeers = 50
|
||||||
config.Metrics.Enabled = true
|
config.Metrics.Enabled = true
|
||||||
// --pprof is enabled in 'internal/debug/flags.go'
|
// --pprof is enabled in 'internal/debug/flags.go'
|
||||||
}
|
}
|
||||||
|
|
@ -350,7 +350,7 @@ func setDefaultBorMainnetGethConfig(ctx *cli.Context, config *gethConfig) {
|
||||||
config.Eth.TxPool.AccountQueue = 64
|
config.Eth.TxPool.AccountQueue = 64
|
||||||
config.Eth.TxPool.GlobalQueue = 131072
|
config.Eth.TxPool.GlobalQueue = 131072
|
||||||
config.Eth.TxPool.Lifetime = 90 * time.Minute
|
config.Eth.TxPool.Lifetime = 90 * time.Minute
|
||||||
config.Node.P2P.MaxPeers = 200
|
config.Node.P2P.MaxPeers = 50
|
||||||
config.Metrics.Enabled = true
|
config.Metrics.Enabled = true
|
||||||
// --pprof is enabled in 'internal/debug/flags.go'
|
// --pprof is enabled in 'internal/debug/flags.go'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/JekaMas/crand"
|
"github.com/maticnetwork/crand"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"pgregory.net/rapid"
|
"pgregory.net/rapid"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,22 +31,22 @@ func (c ChainContext) GetHeader(hash common.Hash, number uint64) *types.Header {
|
||||||
}
|
}
|
||||||
|
|
||||||
// callmsg implements core.Message to allow passing it as a transaction simulator.
|
// callmsg implements core.Message to allow passing it as a transaction simulator.
|
||||||
type callmsg struct {
|
type Callmsg struct {
|
||||||
ethereum.CallMsg
|
ethereum.CallMsg
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m callmsg) From() common.Address { return m.CallMsg.From }
|
func (m Callmsg) From() common.Address { return m.CallMsg.From }
|
||||||
func (m callmsg) Nonce() uint64 { return 0 }
|
func (m Callmsg) Nonce() uint64 { return 0 }
|
||||||
func (m callmsg) CheckNonce() bool { return false }
|
func (m Callmsg) CheckNonce() bool { return false }
|
||||||
func (m callmsg) To() *common.Address { return m.CallMsg.To }
|
func (m Callmsg) To() *common.Address { return m.CallMsg.To }
|
||||||
func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
func (m Callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
||||||
func (m callmsg) Gas() uint64 { return m.CallMsg.Gas }
|
func (m Callmsg) Gas() uint64 { return m.CallMsg.Gas }
|
||||||
func (m callmsg) Value() *big.Int { return m.CallMsg.Value }
|
func (m Callmsg) Value() *big.Int { return m.CallMsg.Value }
|
||||||
func (m callmsg) Data() []byte { return m.CallMsg.Data }
|
func (m Callmsg) Data() []byte { return m.CallMsg.Data }
|
||||||
|
|
||||||
// get system message
|
// get system message
|
||||||
func GetSystemMessage(toAddress common.Address, data []byte) callmsg {
|
func GetSystemMessage(toAddress common.Address, data []byte) Callmsg {
|
||||||
return callmsg{
|
return Callmsg{
|
||||||
ethereum.CallMsg{
|
ethereum.CallMsg{
|
||||||
From: systemAddress,
|
From: systemAddress,
|
||||||
Gas: math.MaxUint64 / 2,
|
Gas: math.MaxUint64 / 2,
|
||||||
|
|
@ -61,7 +61,7 @@ func GetSystemMessage(toAddress common.Address, data []byte) callmsg {
|
||||||
// apply message
|
// apply message
|
||||||
func ApplyMessage(
|
func ApplyMessage(
|
||||||
_ context.Context,
|
_ context.Context,
|
||||||
msg callmsg,
|
msg Callmsg,
|
||||||
state *state.StateDB,
|
state *state.StateDB,
|
||||||
header *types.Header,
|
header *types.Header,
|
||||||
chainConfig *params.ChainConfig,
|
chainConfig *params.ChainConfig,
|
||||||
|
|
@ -93,3 +93,28 @@ func ApplyMessage(
|
||||||
|
|
||||||
return gasUsed, nil
|
return gasUsed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ApplyBorMessage(vmenv vm.EVM, msg Callmsg) (*core.ExecutionResult, error) {
|
||||||
|
initialGas := msg.Gas()
|
||||||
|
|
||||||
|
// Apply the transaction to the current state (included in the env)
|
||||||
|
ret, gasLeft, err := vmenv.Call(
|
||||||
|
vm.AccountRef(msg.From()),
|
||||||
|
*msg.To(),
|
||||||
|
msg.Data(),
|
||||||
|
msg.Gas(),
|
||||||
|
msg.Value(),
|
||||||
|
)
|
||||||
|
// Update the state with pending changes
|
||||||
|
if err != nil {
|
||||||
|
vmenv.StateDB.Finalise(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
gasUsed := initialGas - gasLeft
|
||||||
|
|
||||||
|
return &core.ExecutionResult{
|
||||||
|
UsedGas: gasUsed,
|
||||||
|
Err: err,
|
||||||
|
ReturnData: ret,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -180,9 +180,6 @@ func TestRemoteMultiNotify(t *testing.T) {
|
||||||
// Tests that pushing work packages fast to the miner doesn't cause any data race
|
// Tests that pushing work packages fast to the miner doesn't cause any data race
|
||||||
// issues in the notifications. Full pending block body / --miner.notify.full)
|
// issues in the notifications. Full pending block body / --miner.notify.full)
|
||||||
func TestRemoteMultiNotifyFull(t *testing.T) {
|
func TestRemoteMultiNotifyFull(t *testing.T) {
|
||||||
// TODO: Understand the test case and Identify the reason for failing tests.
|
|
||||||
// Also, make it more deterministic.
|
|
||||||
t.Skip("skipping - non-deterministic test, no dependency on this test for now and not directly relevant to bor")
|
|
||||||
|
|
||||||
// Start a simple web server to capture notifications.
|
// Start a simple web server to capture notifications.
|
||||||
sink := make(chan map[string]interface{}, 64)
|
sink := make(chan map[string]interface{}, 64)
|
||||||
|
|
@ -197,6 +194,9 @@ func TestRemoteMultiNotifyFull(t *testing.T) {
|
||||||
}
|
}
|
||||||
sink <- work
|
sink <- work
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
// Allowing the server to start listening.
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
// Create the custom ethash engine.
|
// Create the custom ethash engine.
|
||||||
|
|
|
||||||
|
|
@ -162,7 +162,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
|
||||||
|
|
||||||
// genUncles generates blocks with two uncle headers.
|
// genUncles generates blocks with two uncle headers.
|
||||||
func genUncles(i int, gen *BlockGen) {
|
func genUncles(i int, gen *BlockGen) {
|
||||||
if i >= 6 {
|
if i >= 7 {
|
||||||
b2 := gen.PrevBlock(i - 6).Header()
|
b2 := gen.PrevBlock(i - 6).Header()
|
||||||
b2.Extra = []byte("foo")
|
b2.Extra = []byte("foo")
|
||||||
gen.AddUncle(b2)
|
gen.AddUncle(b2)
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ const (
|
||||||
txLookupCacheLimit = 1024
|
txLookupCacheLimit = 1024
|
||||||
maxFutureBlocks = 256
|
maxFutureBlocks = 256
|
||||||
maxTimeFutureBlocks = 30
|
maxTimeFutureBlocks = 30
|
||||||
TriesInMemory = 128
|
|
||||||
|
|
||||||
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
|
// BlockChainVersion ensures that an incompatible database forces a resync from scratch.
|
||||||
//
|
//
|
||||||
|
|
@ -132,6 +131,7 @@ type CacheConfig struct {
|
||||||
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
TrieTimeLimit time.Duration // Time limit after which to flush the current in-memory trie to disk
|
||||||
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
|
||||||
Preimages bool // Whether to store preimage of trie key to the disk
|
Preimages bool // Whether to store preimage of trie key to the disk
|
||||||
|
TriesInMemory uint64 // Number of recent tries to keep in memory
|
||||||
|
|
||||||
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
|
||||||
}
|
}
|
||||||
|
|
@ -144,6 +144,7 @@ var DefaultCacheConfig = &CacheConfig{
|
||||||
TrieTimeLimit: 5 * time.Minute,
|
TrieTimeLimit: 5 * time.Minute,
|
||||||
SnapshotLimit: 256,
|
SnapshotLimit: 256,
|
||||||
SnapshotWait: true,
|
SnapshotWait: true,
|
||||||
|
TriesInMemory: 128,
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockChain represents the canonical chain given a database with a genesis
|
// BlockChain represents the canonical chain given a database with a genesis
|
||||||
|
|
@ -229,6 +230,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
|
||||||
if cacheConfig == nil {
|
if cacheConfig == nil {
|
||||||
cacheConfig = DefaultCacheConfig
|
cacheConfig = DefaultCacheConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cacheConfig.TriesInMemory <= 0 {
|
||||||
|
cacheConfig.TriesInMemory = DefaultCacheConfig.TriesInMemory
|
||||||
|
}
|
||||||
bodyCache, _ := lru.New(bodyCacheLimit)
|
bodyCache, _ := lru.New(bodyCacheLimit)
|
||||||
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
bodyRLPCache, _ := lru.New(bodyCacheLimit)
|
||||||
receiptsCache, _ := lru.New(receiptsCacheLimit)
|
receiptsCache, _ := lru.New(receiptsCacheLimit)
|
||||||
|
|
@ -829,7 +834,7 @@ func (bc *BlockChain) Stop() {
|
||||||
if !bc.cacheConfig.TrieDirtyDisabled {
|
if !bc.cacheConfig.TrieDirtyDisabled {
|
||||||
triedb := bc.stateCache.TrieDB()
|
triedb := bc.stateCache.TrieDB()
|
||||||
|
|
||||||
for _, offset := range []uint64{0, 1, TriesInMemory - 1} {
|
for _, offset := range []uint64{0, 1, bc.cacheConfig.TriesInMemory - 1} {
|
||||||
if number := bc.CurrentBlock().NumberU64(); number > offset {
|
if number := bc.CurrentBlock().NumberU64(); number > offset {
|
||||||
recent := bc.GetBlockByNumber(number - offset)
|
recent := bc.GetBlockByNumber(number - offset)
|
||||||
|
|
||||||
|
|
@ -1297,7 +1302,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive
|
triedb.Reference(root, common.Hash{}) // metadata reference to keep trie alive
|
||||||
bc.triegc.Push(root, -int64(block.NumberU64()))
|
bc.triegc.Push(root, -int64(block.NumberU64()))
|
||||||
|
|
||||||
if current := block.NumberU64(); current > TriesInMemory {
|
if current := block.NumberU64(); current > bc.cacheConfig.TriesInMemory {
|
||||||
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
// If we exceeded our memory allowance, flush matured singleton nodes to disk
|
||||||
var (
|
var (
|
||||||
nodes, imgs = triedb.Size()
|
nodes, imgs = triedb.Size()
|
||||||
|
|
@ -1307,7 +1312,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
triedb.Cap(limit - ethdb.IdealBatchSize)
|
triedb.Cap(limit - ethdb.IdealBatchSize)
|
||||||
}
|
}
|
||||||
// Find the next state trie we need to commit
|
// Find the next state trie we need to commit
|
||||||
chosen := current - TriesInMemory
|
chosen := current - bc.cacheConfig.TriesInMemory
|
||||||
|
|
||||||
// If we exceeded out time allowance, flush an entire trie to disk
|
// If we exceeded out time allowance, flush an entire trie to disk
|
||||||
if bc.gcproc > bc.cacheConfig.TrieTimeLimit {
|
if bc.gcproc > bc.cacheConfig.TrieTimeLimit {
|
||||||
|
|
@ -1319,8 +1324,8 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
|
||||||
} else {
|
} else {
|
||||||
// If we're exceeding limits but haven't reached a large enough memory gap,
|
// If we're exceeding limits but haven't reached a large enough memory gap,
|
||||||
// warn the user that the system is becoming unstable.
|
// warn the user that the system is becoming unstable.
|
||||||
if chosen < lastWrite+TriesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
|
if chosen < lastWrite+bc.cacheConfig.TriesInMemory && bc.gcproc >= 2*bc.cacheConfig.TrieTimeLimit {
|
||||||
log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TrieTimeLimit, "optimum", float64(chosen-lastWrite)/TriesInMemory)
|
log.Info("State in memory for too long, committing", "time", bc.gcproc, "allowance", bc.cacheConfig.TriesInMemory, "optimum", float64(chosen-lastWrite)/float64((bc.cacheConfig.TriesInMemory)))
|
||||||
}
|
}
|
||||||
// Flush an entire trie and restart the counters
|
// Flush an entire trie and restart the counters
|
||||||
triedb.Commit(header.Root, true, nil)
|
triedb.Commit(header.Root, true, nil)
|
||||||
|
|
|
||||||
|
|
@ -1652,7 +1652,7 @@ func TestTrieForkGC(t *testing.T) {
|
||||||
|
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
||||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
|
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
|
||||||
|
|
||||||
// Generate a bunch of fork blocks, each side forking from the canonical chain
|
// Generate a bunch of fork blocks, each side forking from the canonical chain
|
||||||
forks := make([]*types.Block, len(blocks))
|
forks := make([]*types.Block, len(blocks))
|
||||||
|
|
@ -1681,7 +1681,7 @@ func TestTrieForkGC(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Dereference all the recent tries and ensure no past trie is left in
|
// Dereference all the recent tries and ensure no past trie is left in
|
||||||
for i := 0; i < TriesInMemory; i++ {
|
for i := 0; i < int(chain.cacheConfig.TriesInMemory); i++ {
|
||||||
chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
|
chain.stateCache.TrieDB().Dereference(blocks[len(blocks)-1-i].Root())
|
||||||
chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
|
chain.stateCache.TrieDB().Dereference(forks[len(blocks)-1-i].Root())
|
||||||
}
|
}
|
||||||
|
|
@ -1700,8 +1700,8 @@ func TestLargeReorgTrieGC(t *testing.T) {
|
||||||
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
||||||
|
|
||||||
shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
|
shared, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 64, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{1}) })
|
||||||
original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
|
original, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) { b.SetCoinbase(common.Address{2}) })
|
||||||
competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*TriesInMemory+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
|
competitor, _ := GenerateChain(params.TestChainConfig, shared[len(shared)-1], engine, db, 2*int(DefaultCacheConfig.TriesInMemory)+1, func(i int, b *BlockGen) { b.SetCoinbase(common.Address{3}) })
|
||||||
|
|
||||||
// Import the shared chain and the original canonical one
|
// Import the shared chain and the original canonical one
|
||||||
diskdb := rawdb.NewMemoryDatabase()
|
diskdb := rawdb.NewMemoryDatabase()
|
||||||
|
|
@ -1736,7 +1736,8 @@ func TestLargeReorgTrieGC(t *testing.T) {
|
||||||
if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil {
|
if _, err := chain.InsertChain(competitor[len(competitor)-2:]); err != nil {
|
||||||
t.Fatalf("failed to finalize competitor chain: %v", err)
|
t.Fatalf("failed to finalize competitor chain: %v", err)
|
||||||
}
|
}
|
||||||
for i, block := range competitor[:len(competitor)-TriesInMemory] {
|
|
||||||
|
for i, block := range competitor[:len(competitor)-int(chain.cacheConfig.TriesInMemory)] {
|
||||||
if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
|
if node, _ := chain.stateCache.TrieDB().Node(block.Root()); node != nil {
|
||||||
t.Fatalf("competitor %d: competing chain state missing", i)
|
t.Fatalf("competitor %d: competing chain state missing", i)
|
||||||
}
|
}
|
||||||
|
|
@ -1882,8 +1883,8 @@ func TestInsertReceiptChainRollback(t *testing.T) {
|
||||||
// overtake the 'canon' chain until after it's passed canon by about 200 blocks.
|
// overtake the 'canon' chain until after it's passed canon by about 200 blocks.
|
||||||
//
|
//
|
||||||
// Details at:
|
// Details at:
|
||||||
// - https://github.com/ethereum/go-ethereum/issues/18977
|
// - https://github.com/ethereum/go-ethereum/issues/18977
|
||||||
// - https://github.com/ethereum/go-ethereum/pull/18988
|
// - https://github.com/ethereum/go-ethereum/pull/18988
|
||||||
func TestLowDiffLongChain(t *testing.T) {
|
func TestLowDiffLongChain(t *testing.T) {
|
||||||
// Generate a canonical chain to act as the main dataset
|
// Generate a canonical chain to act as the main dataset
|
||||||
engine := ethash.NewFaker()
|
engine := ethash.NewFaker()
|
||||||
|
|
@ -1892,7 +1893,7 @@ func TestLowDiffLongChain(t *testing.T) {
|
||||||
|
|
||||||
// We must use a pretty long chain to ensure that the fork doesn't overtake us
|
// We must use a pretty long chain to ensure that the fork doesn't overtake us
|
||||||
// until after at least 128 blocks post tip
|
// until after at least 128 blocks post tip
|
||||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*TriesInMemory, func(i int, b *BlockGen) {
|
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 6*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
||||||
b.SetCoinbase(common.Address{1})
|
b.SetCoinbase(common.Address{1})
|
||||||
b.OffsetTime(-9)
|
b.OffsetTime(-9)
|
||||||
})
|
})
|
||||||
|
|
@ -1910,7 +1911,7 @@ func TestLowDiffLongChain(t *testing.T) {
|
||||||
}
|
}
|
||||||
// Generate fork chain, starting from an early block
|
// Generate fork chain, starting from an early block
|
||||||
parent := blocks[10]
|
parent := blocks[10]
|
||||||
fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*TriesInMemory, func(i int, b *BlockGen) {
|
fork, _ := GenerateChain(params.TestChainConfig, parent, engine, db, 8*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
||||||
b.SetCoinbase(common.Address{2})
|
b.SetCoinbase(common.Address{2})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -1979,7 +1980,8 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
// Set the terminal total difficulty in the config
|
// Set the terminal total difficulty in the config
|
||||||
gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
|
gspec.Config.TerminalTotalDifficulty = big.NewInt(0)
|
||||||
}
|
}
|
||||||
blocks, _ := GenerateChain(&chainConfig, genesis, genEngine, db, 2*TriesInMemory, func(i int, gen *BlockGen) {
|
|
||||||
|
blocks, _ := GenerateChain(&chainConfig, genesis, genEngine, db, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, gen *BlockGen) {
|
||||||
tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key)
|
tx, err := types.SignTx(types.NewTransaction(nonce, common.HexToAddress("deadbeef"), big.NewInt(100), 21000, big.NewInt(int64(i+1)*params.GWei), nil), signer, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to create tx: %v", err)
|
t.Fatalf("failed to create tx: %v", err)
|
||||||
|
|
@ -1991,9 +1993,9 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPrunedIndex := len(blocks) - TriesInMemory - 1
|
lastPrunedIndex := len(blocks) - int(chain.cacheConfig.TriesInMemory) - 1
|
||||||
lastPrunedBlock := blocks[lastPrunedIndex]
|
lastPrunedBlock := blocks[lastPrunedIndex]
|
||||||
firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory]
|
firstNonPrunedBlock := blocks[len(blocks)-int(chain.cacheConfig.TriesInMemory)]
|
||||||
|
|
||||||
// Verify pruning of lastPrunedBlock
|
// Verify pruning of lastPrunedBlock
|
||||||
if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
|
if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
|
||||||
|
|
@ -2019,7 +2021,7 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
// Generate fork chain, make it longer than canon
|
// Generate fork chain, make it longer than canon
|
||||||
parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock
|
parentIndex := lastPrunedIndex + blocksBetweenCommonAncestorAndPruneblock
|
||||||
parent := blocks[parentIndex]
|
parent := blocks[parentIndex]
|
||||||
fork, _ := GenerateChain(&chainConfig, parent, genEngine, db, 2*TriesInMemory, func(i int, b *BlockGen) {
|
fork, _ := GenerateChain(&chainConfig, parent, genEngine, db, 2*int(DefaultCacheConfig.TriesInMemory), func(i int, b *BlockGen) {
|
||||||
b.SetCoinbase(common.Address{2})
|
b.SetCoinbase(common.Address{2})
|
||||||
})
|
})
|
||||||
// Prepend the parent(s)
|
// Prepend the parent(s)
|
||||||
|
|
@ -2046,7 +2048,8 @@ func testSideImport(t *testing.T, numCanonBlocksInSidechain, blocksBetweenCommon
|
||||||
// That is: the sidechain for import contains some blocks already present in canon chain.
|
// That is: the sidechain for import contains some blocks already present in canon chain.
|
||||||
// So the blocks are
|
// So the blocks are
|
||||||
// [ Cn, Cn+1, Cc, Sn+3 ... Sm]
|
// [ Cn, Cn+1, Cc, Sn+3 ... Sm]
|
||||||
// ^ ^ ^ pruned
|
//
|
||||||
|
// ^ ^ ^ pruned
|
||||||
func TestPrunedImportSide(t *testing.T) {
|
func TestPrunedImportSide(t *testing.T) {
|
||||||
//glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
|
//glogger := log.NewGlogHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
|
||||||
//glogger.Verbosity(3)
|
//glogger.Verbosity(3)
|
||||||
|
|
@ -2841,9 +2844,9 @@ func BenchmarkBlockChain_1x1000Executions(b *testing.B) {
|
||||||
// This internally leads to a sidechain import, since the blocks trigger an
|
// This internally leads to a sidechain import, since the blocks trigger an
|
||||||
// ErrPrunedAncestor error.
|
// ErrPrunedAncestor error.
|
||||||
// This may e.g. happen if
|
// This may e.g. happen if
|
||||||
// 1. Downloader rollbacks a batch of inserted blocks and exits
|
// 1. Downloader rollbacks a batch of inserted blocks and exits
|
||||||
// 2. Downloader starts to sync again
|
// 2. Downloader starts to sync again
|
||||||
// 3. The blocks fetched are all known and canonical blocks
|
// 3. The blocks fetched are all known and canonical blocks
|
||||||
func TestSideImportPrunedBlocks(t *testing.T) {
|
func TestSideImportPrunedBlocks(t *testing.T) {
|
||||||
// Generate a canonical chain to act as the main dataset
|
// Generate a canonical chain to act as the main dataset
|
||||||
engine := ethash.NewFaker()
|
engine := ethash.NewFaker()
|
||||||
|
|
@ -2851,7 +2854,7 @@ func TestSideImportPrunedBlocks(t *testing.T) {
|
||||||
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
genesis := (&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(db)
|
||||||
|
|
||||||
// Generate and import the canonical chain
|
// Generate and import the canonical chain
|
||||||
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*TriesInMemory, nil)
|
blocks, _ := GenerateChain(params.TestChainConfig, genesis, engine, db, 2*int(DefaultCacheConfig.TriesInMemory), nil)
|
||||||
diskdb := rawdb.NewMemoryDatabase()
|
diskdb := rawdb.NewMemoryDatabase()
|
||||||
|
|
||||||
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
|
(&Genesis{BaseFee: big.NewInt(params.InitialBaseFee)}).MustCommit(diskdb)
|
||||||
|
|
@ -2863,14 +2866,15 @@ func TestSideImportPrunedBlocks(t *testing.T) {
|
||||||
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lastPrunedIndex := len(blocks) - TriesInMemory - 1
|
lastPrunedIndex := len(blocks) - int(chain.cacheConfig.TriesInMemory) - 1
|
||||||
lastPrunedBlock := blocks[lastPrunedIndex]
|
lastPrunedBlock := blocks[lastPrunedIndex]
|
||||||
|
|
||||||
// Verify pruning of lastPrunedBlock
|
// Verify pruning of lastPrunedBlock
|
||||||
if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
|
if chain.HasBlockAndState(lastPrunedBlock.Hash(), lastPrunedBlock.NumberU64()) {
|
||||||
t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64())
|
t.Errorf("Block %d not pruned", lastPrunedBlock.NumberU64())
|
||||||
}
|
}
|
||||||
firstNonPrunedBlock := blocks[len(blocks)-TriesInMemory]
|
|
||||||
|
firstNonPrunedBlock := blocks[len(blocks)-int(chain.cacheConfig.TriesInMemory)]
|
||||||
// Verify firstNonPrunedBlock is not pruned
|
// Verify firstNonPrunedBlock is not pruned
|
||||||
if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
|
if !chain.HasBlockAndState(firstNonPrunedBlock.Hash(), firstNonPrunedBlock.NumberU64()) {
|
||||||
t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
|
t.Errorf("Block %d pruned", firstNonPrunedBlock.NumberU64())
|
||||||
|
|
@ -3356,20 +3360,19 @@ func TestDeleteRecreateSlotsAcrossManyBlocks(t *testing.T) {
|
||||||
|
|
||||||
// TestInitThenFailCreateContract tests a pretty notorious case that happened
|
// TestInitThenFailCreateContract tests a pretty notorious case that happened
|
||||||
// on mainnet over blocks 7338108, 7338110 and 7338115.
|
// on mainnet over blocks 7338108, 7338110 and 7338115.
|
||||||
// - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated
|
// - Block 7338108: address e771789f5cccac282f23bb7add5690e1f6ca467c is initiated
|
||||||
// with 0.001 ether (thus created but no code)
|
// with 0.001 ether (thus created but no code)
|
||||||
// - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on
|
// - Block 7338110: a CREATE2 is attempted. The CREATE2 would deploy code on
|
||||||
// the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the
|
// the same address e771789f5cccac282f23bb7add5690e1f6ca467c. However, the
|
||||||
// deployment fails due to OOG during initcode execution
|
// deployment fails due to OOG during initcode execution
|
||||||
// - Block 7338115: another tx checks the balance of
|
// - Block 7338115: another tx checks the balance of
|
||||||
// e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as
|
// e771789f5cccac282f23bb7add5690e1f6ca467c, and the snapshotter returned it as
|
||||||
// zero.
|
// zero.
|
||||||
//
|
//
|
||||||
// The problem being that the snapshotter maintains a destructset, and adds items
|
// The problem being that the snapshotter maintains a destructset, and adds items
|
||||||
// to the destructset in case something is created "onto" an existing item.
|
// to the destructset in case something is created "onto" an existing item.
|
||||||
// We need to either roll back the snapDestructs, or not place it into snapDestructs
|
// We need to either roll back the snapDestructs, or not place it into snapDestructs
|
||||||
// in the first place.
|
// in the first place.
|
||||||
//
|
|
||||||
func TestInitThenFailCreateContract(t *testing.T) {
|
func TestInitThenFailCreateContract(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
// Generate a canonical chain to act as the main dataset
|
// Generate a canonical chain to act as the main dataset
|
||||||
|
|
@ -3558,13 +3561,13 @@ func TestEIP2718Transition(t *testing.T) {
|
||||||
|
|
||||||
// TestEIP1559Transition tests the following:
|
// TestEIP1559Transition tests the following:
|
||||||
//
|
//
|
||||||
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
|
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
|
||||||
// 2. Gas accounting for access lists on EIP-1559 transactions is correct.
|
// 2. Gas accounting for access lists on EIP-1559 transactions is correct.
|
||||||
// 3. Only the transaction's tip will be received by the coinbase.
|
// 3. Only the transaction's tip will be received by the coinbase.
|
||||||
// 4. The transaction sender pays for both the tip and baseFee.
|
// 4. The transaction sender pays for both the tip and baseFee.
|
||||||
// 5. The coinbase receives only the partially realized tip when
|
// 5. The coinbase receives only the partially realized tip when
|
||||||
// gasFeeCap - gasTipCap < baseFee.
|
// gasFeeCap - gasTipCap < baseFee.
|
||||||
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
|
// 6. Legacy transaction behave as expected (e.g. gasPrice = gasFeeCap = gasTipCap).
|
||||||
func TestEIP1559Transition(t *testing.T) {
|
func TestEIP1559Transition(t *testing.T) {
|
||||||
var (
|
var (
|
||||||
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
|
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/JekaMas/crand"
|
"github.com/maticnetwork/crand"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum"
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
|
|
||||||
|
|
@ -2082,6 +2082,7 @@ func testSetHead(t *testing.T, tt *rewindTest, snapshots bool) {
|
||||||
|
|
||||||
// verifyNoGaps checks that there are no gaps after the initial set of blocks in
|
// verifyNoGaps checks that there are no gaps after the initial set of blocks in
|
||||||
// the database and errors if found.
|
// the database and errors if found.
|
||||||
|
//
|
||||||
//nolint:gocognit
|
//nolint:gocognit
|
||||||
func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks) {
|
func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
@ -2135,6 +2136,7 @@ func verifyNoGaps(t *testing.T, chain *core.BlockChain, canonical bool, inserted
|
||||||
|
|
||||||
// verifyCutoff checks that there are no chain data available in the chain after
|
// verifyCutoff checks that there are no chain data available in the chain after
|
||||||
// the specified limit, but that it is available before.
|
// the specified limit, but that it is available before.
|
||||||
|
//
|
||||||
//nolint:gocognit
|
//nolint:gocognit
|
||||||
func verifyCutoff(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks, head int) {
|
func verifyCutoff(t *testing.T, chain *core.BlockChain, canonical bool, inserted types.Blocks, head int) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,8 @@ type StateDB interface {
|
||||||
AddPreimage(common.Hash, []byte)
|
AddPreimage(common.Hash, []byte)
|
||||||
|
|
||||||
ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error
|
ForEachStorage(common.Address, func(common.Hash, common.Hash) bool) error
|
||||||
|
|
||||||
|
Finalise(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
// CallContext provides a basic interface for the EVM calling conventions. The EVM
|
||||||
|
|
|
||||||
|
|
@ -5,18 +5,16 @@
|
||||||
|
|
||||||
- [Configuration file](./config.md)
|
- [Configuration file](./config.md)
|
||||||
|
|
||||||
## Deprecation notes
|
## Additional notes
|
||||||
|
|
||||||
- The new entrypoint to run the Bor client is ```server```.
|
- The new entrypoint to run the Bor client is ```server```.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ bor server
|
$ bor server <flags>
|
||||||
```
|
```
|
||||||
|
|
||||||
- Toml files to configure nodes are being deprecated. Currently, we only allow for static and trusted nodes to be configured using toml files.
|
- Toml files used earlier just to configure static/trusted nodes are being deprecated. Instead, a toml file now can be used instead of flags and can contain all configuration for the node to run. The link to a sample config file is given above. To simply run bor with a configuration file, the following command can be used.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ bor server --config ./legacy.toml
|
$ bor server --config <path_to_config.toml>
|
||||||
```
|
```
|
||||||
|
|
||||||
- ```Admin```, ```Personal``` and account related endpoints in ```Eth``` are being removed from the JsonRPC interface. Some of this functionality will be moved to the new GRPC server for operational tasks.
|
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,6 @@ The ```bor removedb``` command will remove the blockchain and state databases at
|
||||||
|
|
||||||
## Options
|
## Options
|
||||||
|
|
||||||
- ```datadir```: Path of the data directory to store information
|
- ```address```: Address of the grpc endpoint
|
||||||
|
|
||||||
|
- ```datadir```: Path of the data directory to store information
|
||||||
|
|
@ -16,18 +16,22 @@ The ```bor server``` command runs the Bor client.
|
||||||
|
|
||||||
- ```config```: File for the config file
|
- ```config```: File for the config file
|
||||||
|
|
||||||
- ```syncmode```: Blockchain sync mode ("fast", "full", or "snap")
|
- ```syncmode```: Blockchain sync mode (only "full" sync supported)
|
||||||
|
|
||||||
- ```gcmode```: Blockchain garbage collection mode ("full", "archive")
|
- ```gcmode```: Blockchain garbage collection mode ("full", "archive")
|
||||||
|
|
||||||
- ```requiredblocks```: Comma separated block number-to-hash mappings to enforce (<number>=<hash>)
|
- ```eth.requiredblocks```: Comma separated block number-to-hash mappings to require for peering (<number>=<hash>)
|
||||||
|
|
||||||
- ```snapshot```: Disables/Enables the snapshot-database mode (default = true)
|
- ```snapshot```: Enables the snapshot-database mode (default = true)
|
||||||
|
|
||||||
|
- ```bor.logs```: Enables bor log retrieval (default = false)
|
||||||
|
|
||||||
- ```bor.heimdall```: URL of Heimdall service
|
- ```bor.heimdall```: URL of Heimdall service
|
||||||
|
|
||||||
- ```bor.withoutheimdall```: Run without Heimdall service (for testing purpose)
|
- ```bor.withoutheimdall```: Run without Heimdall service (for testing purpose)
|
||||||
|
|
||||||
|
- ```bor.heimdallgRPC```: Address of Heimdall gRPC service
|
||||||
|
|
||||||
- ```ethstats```: Reporting URL of a ethstats service (nodename:secret@host:port)
|
- ```ethstats```: Reporting URL of a ethstats service (nodename:secret@host:port)
|
||||||
|
|
||||||
- ```gpo.blocks```: Number of recent blocks to check for gas prices
|
- ```gpo.blocks```: Number of recent blocks to check for gas prices
|
||||||
|
|
@ -76,6 +80,8 @@ The ```bor server``` command runs the Bor client.
|
||||||
|
|
||||||
- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys
|
- ```cache.preimages```: Enable recording the SHA3/keccak preimages of trie keys
|
||||||
|
|
||||||
|
- ```cache.triesinmemory```: Number of block states (tries) to keep in memory (default = 128)
|
||||||
|
|
||||||
- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)
|
- ```txlookuplimit```: Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)
|
||||||
|
|
||||||
### JsonRPC Options
|
### JsonRPC Options
|
||||||
|
|
@ -92,9 +98,7 @@ The ```bor server``` command runs the Bor client.
|
||||||
|
|
||||||
- ```http.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
|
- ```http.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
|
||||||
|
|
||||||
- ```ws.corsdomain```: Comma separated list of domains from which to accept cross origin requests (browser enforced)
|
- ```ws.origins```: Origins from which to accept websockets requests
|
||||||
|
|
||||||
- ```ws.vhosts```: Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.
|
|
||||||
|
|
||||||
- ```graphql.corsdomain```: Comma separated list of domains from which to accept cross origin requests (browser enforced)
|
- ```graphql.corsdomain```: Comma separated list of domains from which to accept cross origin requests (browser enforced)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ ethstats = ""
|
||||||
["eth.requiredblocks"]
|
["eth.requiredblocks"]
|
||||||
|
|
||||||
[p2p]
|
[p2p]
|
||||||
maxpeers = 30
|
maxpeers = 50
|
||||||
maxpendpeers = 50
|
maxpendpeers = 50
|
||||||
bind = "0.0.0.0"
|
bind = "0.0.0.0"
|
||||||
port = 30303
|
port = 30303
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
|
||||||
TrieTimeLimit: config.TrieTimeout,
|
TrieTimeLimit: config.TrieTimeout,
|
||||||
SnapshotLimit: config.SnapshotCache,
|
SnapshotLimit: config.SnapshotCache,
|
||||||
Preimages: config.Preimages,
|
Preimages: config.Preimages,
|
||||||
|
TriesInMemory: config.TriesInMemory,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ type Config struct {
|
||||||
TrieTimeout time.Duration
|
TrieTimeout time.Duration
|
||||||
SnapshotCache int
|
SnapshotCache int
|
||||||
Preimages bool
|
Preimages bool
|
||||||
|
TriesInMemory uint64
|
||||||
|
|
||||||
// Mining options
|
// Mining options
|
||||||
Miner miner.Config
|
Miner miner.Config
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,11 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum"
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/bor/statefull"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
|
@ -63,6 +65,8 @@ const (
|
||||||
defaultTracechainMemLimit = common.StorageSize(500 * 1024 * 1024)
|
defaultTracechainMemLimit = common.StorageSize(500 * 1024 * 1024)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var defaultBorTraceEnabled = newBoolPtr(false)
|
||||||
|
|
||||||
// Backend interface provides the common API services (that are provided by
|
// Backend interface provides the common API services (that are provided by
|
||||||
// both full and light clients) with access to necessary functions.
|
// both full and light clients) with access to necessary functions.
|
||||||
type Backend interface {
|
type Backend interface {
|
||||||
|
|
@ -80,6 +84,9 @@ type Backend interface {
|
||||||
// so this method should be called with the parent.
|
// so this method should be called with the parent.
|
||||||
StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error)
|
StateAtBlock(ctx context.Context, block *types.Block, reexec uint64, base *state.StateDB, checkLive, preferDisk bool) (*state.StateDB, error)
|
||||||
StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error)
|
StateAtTransaction(ctx context.Context, block *types.Block, txIndex int, reexec uint64) (core.Message, vm.BlockContext, *state.StateDB, error)
|
||||||
|
|
||||||
|
// Bor related APIs
|
||||||
|
GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// API is the collection of tracing APIs exposed over the private debugging endpoint.
|
// API is the collection of tracing APIs exposed over the private debugging endpoint.
|
||||||
|
|
@ -164,12 +171,33 @@ func (api *API) blockByNumberAndHash(ctx context.Context, number rpc.BlockNumber
|
||||||
return api.blockByHash(ctx, hash)
|
return api.blockByHash(ctx, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns block transactions along with state-sync transaction if present
|
||||||
|
func (api *API) getAllBlockTransactions(ctx context.Context, block *types.Block) (types.Transactions, bool) {
|
||||||
|
txs := block.Transactions()
|
||||||
|
|
||||||
|
stateSyncPresent := false
|
||||||
|
|
||||||
|
borReceipt := rawdb.ReadBorReceipt(api.backend.ChainDb(), block.Hash(), block.NumberU64())
|
||||||
|
if borReceipt != nil {
|
||||||
|
txHash := types.GetDerivedBorTxHash(types.BorReceiptKey(block.Number().Uint64(), block.Hash()))
|
||||||
|
if txHash != (common.Hash{}) {
|
||||||
|
borTx, _, _, _, _ := api.backend.GetBorBlockTransactionWithBlockHash(ctx, txHash, block.Hash())
|
||||||
|
txs = append(txs, borTx)
|
||||||
|
stateSyncPresent = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return txs, stateSyncPresent
|
||||||
|
}
|
||||||
|
|
||||||
// TraceConfig holds extra parameters to trace functions.
|
// TraceConfig holds extra parameters to trace functions.
|
||||||
type TraceConfig struct {
|
type TraceConfig struct {
|
||||||
*logger.Config
|
*logger.Config
|
||||||
Tracer *string
|
Tracer *string
|
||||||
Timeout *string
|
Timeout *string
|
||||||
Reexec *uint64
|
Reexec *uint64
|
||||||
|
BorTraceEnabled *bool
|
||||||
|
BorTx *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// TraceCallConfig is the config for traceCall API. It holds one more
|
// TraceCallConfig is the config for traceCall API. It holds one more
|
||||||
|
|
@ -185,8 +213,9 @@ type TraceCallConfig struct {
|
||||||
// StdTraceConfig holds extra parameters to standard-json trace functions.
|
// StdTraceConfig holds extra parameters to standard-json trace functions.
|
||||||
type StdTraceConfig struct {
|
type StdTraceConfig struct {
|
||||||
logger.Config
|
logger.Config
|
||||||
Reexec *uint64
|
Reexec *uint64
|
||||||
TxHash common.Hash
|
TxHash common.Hash
|
||||||
|
BorTraceEnabled *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// txTraceResult is the result of a single transaction trace.
|
// txTraceResult is the result of a single transaction trace.
|
||||||
|
|
@ -240,6 +269,16 @@ func (api *API) TraceChain(ctx context.Context, start, end rpc.BlockNumber, conf
|
||||||
// executes all the transactions contained within. The return value will be one item
|
// executes all the transactions contained within. The return value will be one item
|
||||||
// per transaction, dependent on the requested tracer.
|
// per transaction, dependent on the requested tracer.
|
||||||
func (api *API) traceChain(ctx context.Context, start, end *types.Block, config *TraceConfig) (*rpc.Subscription, error) {
|
func (api *API) traceChain(ctx context.Context, start, end *types.Block, config *TraceConfig) (*rpc.Subscription, error) {
|
||||||
|
if config == nil {
|
||||||
|
config = &TraceConfig{
|
||||||
|
BorTraceEnabled: defaultBorTraceEnabled,
|
||||||
|
BorTx: newBoolPtr(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.BorTraceEnabled == nil {
|
||||||
|
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||||
|
}
|
||||||
// Tracing a chain is a **long** operation, only do with subscriptions
|
// Tracing a chain is a **long** operation, only do with subscriptions
|
||||||
notifier, supported := rpc.NotifierFromContext(ctx)
|
notifier, supported := rpc.NotifierFromContext(ctx)
|
||||||
if !supported {
|
if !supported {
|
||||||
|
|
@ -274,19 +313,39 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
|
||||||
signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number())
|
signer := types.MakeSigner(api.backend.ChainConfig(), task.block.Number())
|
||||||
blockCtx := core.NewEVMBlockContext(task.block.Header(), api.chainContext(localctx), nil)
|
blockCtx := core.NewEVMBlockContext(task.block.Header(), api.chainContext(localctx), nil)
|
||||||
// Trace all the transactions contained within
|
// Trace all the transactions contained within
|
||||||
for i, tx := range task.block.Transactions() {
|
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, task.block)
|
||||||
|
if !*config.BorTraceEnabled && stateSyncPresent {
|
||||||
|
txs = txs[:len(txs)-1]
|
||||||
|
stateSyncPresent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tx := range txs {
|
||||||
msg, _ := tx.AsMessage(signer, task.block.BaseFee())
|
msg, _ := tx.AsMessage(signer, task.block.BaseFee())
|
||||||
txctx := &Context{
|
txctx := &Context{
|
||||||
BlockHash: task.block.Hash(),
|
BlockHash: task.block.Hash(),
|
||||||
TxIndex: i,
|
TxIndex: i,
|
||||||
TxHash: tx.Hash(),
|
TxHash: tx.Hash(),
|
||||||
}
|
}
|
||||||
res, err := api.traceTx(localctx, msg, txctx, blockCtx, task.statedb, config)
|
|
||||||
|
var res interface{}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if stateSyncPresent && i == len(txs)-1 {
|
||||||
|
if *config.BorTraceEnabled {
|
||||||
|
config.BorTx = newBoolPtr(true)
|
||||||
|
res, err = api.traceTx(localctx, msg, txctx, blockCtx, task.statedb, config)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res, err = api.traceTx(localctx, msg, txctx, blockCtx, task.statedb, config)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
task.results[i] = &txTraceResult{Error: err.Error()}
|
task.results[i] = &txTraceResult{Error: err.Error()}
|
||||||
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||||
task.statedb.Finalise(api.backend.ChainConfig().IsEIP158(task.block.Number()))
|
task.statedb.Finalise(api.backend.ChainConfig().IsEIP158(task.block.Number()))
|
||||||
task.results[i] = &txTraceResult{Result: res}
|
task.results[i] = &txTraceResult{Result: res}
|
||||||
|
|
@ -430,6 +489,11 @@ func (api *API) traceChain(ctx context.Context, start, end *types.Block, config
|
||||||
return sub, nil
|
return sub, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newBoolPtr(bb bool) *bool {
|
||||||
|
b := bb
|
||||||
|
return &b
|
||||||
|
}
|
||||||
|
|
||||||
// TraceBlockByNumber returns the structured logs created during the execution of
|
// TraceBlockByNumber returns the structured logs created during the execution of
|
||||||
// EVM and returns them as a JSON object.
|
// EVM and returns them as a JSON object.
|
||||||
func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) {
|
func (api *API) TraceBlockByNumber(ctx context.Context, number rpc.BlockNumber, config *TraceConfig) ([]*txTraceResult, error) {
|
||||||
|
|
@ -492,9 +556,35 @@ func (api *API) StandardTraceBlockToFile(ctx context.Context, hash common.Hash,
|
||||||
return api.standardTraceBlockToFile(ctx, block, config)
|
return api.standardTraceBlockToFile(ctx, block, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prepareCallMessage(msg core.Message) statefull.Callmsg {
|
||||||
|
return statefull.Callmsg{
|
||||||
|
CallMsg: ethereum.CallMsg{
|
||||||
|
From: msg.From(),
|
||||||
|
To: msg.To(),
|
||||||
|
Gas: msg.Gas(),
|
||||||
|
GasPrice: msg.GasPrice(),
|
||||||
|
GasFeeCap: msg.GasFeeCap(),
|
||||||
|
GasTipCap: msg.GasTipCap(),
|
||||||
|
Value: msg.Value(),
|
||||||
|
Data: msg.Data(),
|
||||||
|
AccessList: msg.AccessList(),
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
|
// IntermediateRoots executes a block (bad- or canon- or side-), and returns a list
|
||||||
// of intermediate roots: the stateroot after each transaction.
|
// of intermediate roots: the stateroot after each transaction.
|
||||||
func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
|
func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config *TraceConfig) ([]common.Hash, error) {
|
||||||
|
if config == nil {
|
||||||
|
config = &TraceConfig{
|
||||||
|
BorTraceEnabled: defaultBorTraceEnabled,
|
||||||
|
BorTx: newBoolPtr(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.BorTraceEnabled == nil {
|
||||||
|
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||||
|
}
|
||||||
|
|
||||||
block, _ := api.blockByHash(ctx, hash)
|
block, _ := api.blockByHash(ctx, hash)
|
||||||
if block == nil {
|
if block == nil {
|
||||||
// Check in the bad blocks
|
// Check in the bad blocks
|
||||||
|
|
@ -525,23 +615,47 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
|
||||||
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
vmctx = core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||||
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
deleteEmptyObjects = chainConfig.IsEIP158(block.Number())
|
||||||
)
|
)
|
||||||
for i, tx := range block.Transactions() {
|
|
||||||
|
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, block)
|
||||||
|
for i, tx := range txs {
|
||||||
var (
|
var (
|
||||||
msg, _ = tx.AsMessage(signer, block.BaseFee())
|
msg, _ = tx.AsMessage(signer, block.BaseFee())
|
||||||
txContext = core.NewEVMTxContext(msg)
|
txContext = core.NewEVMTxContext(msg)
|
||||||
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
|
vmenv = vm.NewEVM(vmctx, txContext, statedb, chainConfig, vm.Config{})
|
||||||
)
|
)
|
||||||
statedb.Prepare(tx.Hash(), i)
|
statedb.Prepare(tx.Hash(), i)
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
//nolint: nestif
|
||||||
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
if stateSyncPresent && i == len(txs)-1 {
|
||||||
// We intentionally don't return the error here: if we do, then the RPC server will not
|
if *config.BorTraceEnabled {
|
||||||
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
callmsg := prepareCallMessage(msg)
|
||||||
// be included, but still want the intermediate roots that led to that point.
|
|
||||||
// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
|
if _, err := statefull.ApplyMessage(ctx, callmsg, statedb, block.Header(), api.backend.ChainConfig(), api.chainContext(ctx)); err != nil {
|
||||||
// executable.
|
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
||||||
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
|
// We intentionally don't return the error here: if we do, then the RPC server will not
|
||||||
return roots, nil
|
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
||||||
|
// be included, but still want the intermediate roots that led to that point.
|
||||||
|
// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
|
||||||
|
// executable.
|
||||||
|
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
|
||||||
|
return roots, nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
||||||
|
log.Warn("Tracing intermediate roots did not complete", "txindex", i, "txhash", tx.Hash(), "err", err)
|
||||||
|
// We intentionally don't return the error here: if we do, then the RPC server will not
|
||||||
|
// return the roots. Most likely, the caller already knows that a certain transaction fails to
|
||||||
|
// be included, but still want the intermediate roots that led to that point.
|
||||||
|
// It may happen the tx_N causes an erroneous state, which in turn causes tx_N+M to not be
|
||||||
|
// executable.
|
||||||
|
// N.B: This should never happen while tracing canon blocks, only when tracing bad blocks.
|
||||||
|
return roots, nil
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// calling IntermediateRoot will internally call Finalize on the state
|
// calling IntermediateRoot will internally call Finalize on the state
|
||||||
// so any modifications are written to the trie
|
// so any modifications are written to the trie
|
||||||
roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects))
|
roots = append(roots, statedb.IntermediateRoot(deleteEmptyObjects))
|
||||||
|
|
@ -564,6 +678,18 @@ func (api *API) StandardTraceBadBlockToFile(ctx context.Context, hash common.Has
|
||||||
// executes all the transactions contained within. The return value will be one item
|
// executes all the transactions contained within. The return value will be one item
|
||||||
// per transaction, dependent on the requestd tracer.
|
// per transaction, dependent on the requestd tracer.
|
||||||
func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) {
|
func (api *API) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) {
|
||||||
|
|
||||||
|
if config == nil {
|
||||||
|
config = &TraceConfig{
|
||||||
|
BorTraceEnabled: defaultBorTraceEnabled,
|
||||||
|
BorTx: newBoolPtr(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.BorTraceEnabled == nil {
|
||||||
|
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||||
|
}
|
||||||
|
|
||||||
if block.NumberU64() == 0 {
|
if block.NumberU64() == 0 {
|
||||||
return nil, errors.New("genesis is not traceable")
|
return nil, errors.New("genesis is not traceable")
|
||||||
}
|
}
|
||||||
|
|
@ -581,9 +707,9 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
}
|
}
|
||||||
// Execute all the transaction contained within the block concurrently
|
// Execute all the transaction contained within the block concurrently
|
||||||
var (
|
var (
|
||||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
||||||
txs = block.Transactions()
|
txs, stateSyncPresent = api.getAllBlockTransactions(ctx, block)
|
||||||
results = make([]*txTraceResult, len(txs))
|
results = make([]*txTraceResult, len(txs))
|
||||||
|
|
||||||
pend = new(sync.WaitGroup)
|
pend = new(sync.WaitGroup)
|
||||||
jobs = make(chan *txTraceTask, len(txs))
|
jobs = make(chan *txTraceTask, len(txs))
|
||||||
|
|
@ -606,7 +732,21 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
TxIndex: task.index,
|
TxIndex: task.index,
|
||||||
TxHash: txs[task.index].Hash(),
|
TxHash: txs[task.index].Hash(),
|
||||||
}
|
}
|
||||||
res, err := api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
|
||||||
|
var res interface{}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if stateSyncPresent && task.index == len(txs)-1 {
|
||||||
|
if *config.BorTraceEnabled {
|
||||||
|
config.BorTx = newBoolPtr(true)
|
||||||
|
res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res, err = api.traceTx(ctx, msg, txctx, blockCtx, task.statedb, config)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
results[task.index] = &txTraceResult{Error: err.Error()}
|
results[task.index] = &txTraceResult{Error: err.Error()}
|
||||||
continue
|
continue
|
||||||
|
|
@ -625,11 +765,26 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
// Generate the next state snapshot fast without tracing
|
// Generate the next state snapshot fast without tracing
|
||||||
msg, _ := tx.AsMessage(signer, block.BaseFee())
|
msg, _ := tx.AsMessage(signer, block.BaseFee())
|
||||||
statedb.Prepare(tx.Hash(), i)
|
statedb.Prepare(tx.Hash(), i)
|
||||||
|
|
||||||
vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{})
|
vmenv := vm.NewEVM(blockCtx, core.NewEVMTxContext(msg), statedb, api.backend.ChainConfig(), vm.Config{})
|
||||||
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
//nolint: nestif
|
||||||
failed = err
|
if stateSyncPresent && i == len(txs)-1 {
|
||||||
break
|
if *config.BorTraceEnabled {
|
||||||
|
callmsg := prepareCallMessage(msg)
|
||||||
|
if _, err := statefull.ApplyBorMessage(*vmenv, callmsg); err != nil {
|
||||||
|
failed = err
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
|
||||||
|
failed = err
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finalize the state so any modifications are written to the trie
|
// Finalize the state so any modifications are written to the trie
|
||||||
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
// Only delete empty objects if EIP158/161 (a.k.a Spurious Dragon) is in effect
|
||||||
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
statedb.Finalise(vmenv.ChainConfig().IsEIP158(block.Number()))
|
||||||
|
|
@ -641,16 +796,30 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
|
||||||
if failed != nil {
|
if failed != nil {
|
||||||
return nil, failed
|
return nil, failed
|
||||||
}
|
}
|
||||||
return results, nil
|
|
||||||
|
if !*config.BorTraceEnabled && stateSyncPresent {
|
||||||
|
return results[:len(results)-1], nil
|
||||||
|
} else {
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// standardTraceBlockToFile configures a new tracer which uses standard JSON output,
|
// standardTraceBlockToFile configures a new tracer which uses standard JSON output,
|
||||||
// and traces either a full block or an individual transaction. The return value will
|
// and traces either a full block or an individual transaction. The return value will
|
||||||
// be one filename per transaction traced.
|
// be one filename per transaction traced.
|
||||||
func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) {
|
func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block, config *StdTraceConfig) ([]string, error) {
|
||||||
|
if config == nil {
|
||||||
|
config = &StdTraceConfig{
|
||||||
|
BorTraceEnabled: defaultBorTraceEnabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.BorTraceEnabled == nil {
|
||||||
|
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||||
|
}
|
||||||
// If we're tracing a single transaction, make sure it's present
|
// If we're tracing a single transaction, make sure it's present
|
||||||
if config != nil && config.TxHash != (common.Hash{}) {
|
if config != nil && config.TxHash != (common.Hash{}) {
|
||||||
if !containsTx(block, config.TxHash) {
|
if !api.containsTx(ctx, block, config.TxHash) {
|
||||||
return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash)
|
return nil, fmt.Errorf("transaction %#x not found in block", config.TxHash)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -705,7 +874,14 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
canon = false
|
canon = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i, tx := range block.Transactions() {
|
|
||||||
|
txs, stateSyncPresent := api.getAllBlockTransactions(ctx, block)
|
||||||
|
if !*config.BorTraceEnabled && stateSyncPresent {
|
||||||
|
txs = txs[:len(txs)-1]
|
||||||
|
stateSyncPresent = false
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tx := range txs {
|
||||||
// Prepare the trasaction for un-traced execution
|
// Prepare the trasaction for un-traced execution
|
||||||
var (
|
var (
|
||||||
msg, _ = tx.AsMessage(signer, block.BaseFee())
|
msg, _ = tx.AsMessage(signer, block.BaseFee())
|
||||||
|
|
@ -739,10 +915,23 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
// Execute the transaction and flush any traces to disk
|
// Execute the transaction and flush any traces to disk
|
||||||
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
vmenv := vm.NewEVM(vmctx, txContext, statedb, chainConfig, vmConf)
|
||||||
statedb.Prepare(tx.Hash(), i)
|
statedb.Prepare(tx.Hash(), i)
|
||||||
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
|
//nolint: nestif
|
||||||
if writer != nil {
|
if stateSyncPresent && i == len(txs)-1 {
|
||||||
writer.Flush()
|
if *config.BorTraceEnabled {
|
||||||
|
callmsg := prepareCallMessage(msg)
|
||||||
|
_, err = statefull.ApplyBorMessage(*vmenv, callmsg)
|
||||||
|
|
||||||
|
if writer != nil {
|
||||||
|
writer.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, err = core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas()))
|
||||||
|
if writer != nil {
|
||||||
|
writer.Flush()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if dump != nil {
|
if dump != nil {
|
||||||
dump.Close()
|
dump.Close()
|
||||||
log.Info("Wrote standard trace", "file", dump.Name())
|
log.Info("Wrote standard trace", "file", dump.Name())
|
||||||
|
|
@ -764,8 +953,9 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
|
||||||
|
|
||||||
// containsTx reports whether the transaction with a certain hash
|
// containsTx reports whether the transaction with a certain hash
|
||||||
// is contained within the specified block.
|
// is contained within the specified block.
|
||||||
func containsTx(block *types.Block, hash common.Hash) bool {
|
func (api *API) containsTx(ctx context.Context, block *types.Block, hash common.Hash) bool {
|
||||||
for _, tx := range block.Transactions() {
|
txs, _ := api.getAllBlockTransactions(ctx, block)
|
||||||
|
for _, tx := range txs {
|
||||||
if tx.Hash() == hash {
|
if tx.Hash() == hash {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -776,6 +966,17 @@ func containsTx(block *types.Block, hash common.Hash) bool {
|
||||||
// TraceTransaction returns the structured logs created during the execution of EVM
|
// TraceTransaction returns the structured logs created during the execution of EVM
|
||||||
// and returns them as a JSON object.
|
// and returns them as a JSON object.
|
||||||
func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
|
func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) {
|
||||||
|
if config == nil {
|
||||||
|
config = &TraceConfig{
|
||||||
|
BorTraceEnabled: defaultBorTraceEnabled,
|
||||||
|
BorTx: newBoolPtr(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.BorTraceEnabled == nil {
|
||||||
|
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||||
|
}
|
||||||
|
|
||||||
tx, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
|
tx, blockHash, blockNumber, index, err := api.backend.GetTransaction(ctx, hash)
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
// For BorTransaction, there will be no trace available
|
// For BorTransaction, there will be no trace available
|
||||||
|
|
@ -811,6 +1012,7 @@ func (api *API) TraceTransaction(ctx context.Context, hash common.Hash, config *
|
||||||
TxIndex: int(index),
|
TxIndex: int(index),
|
||||||
TxHash: hash,
|
TxHash: hash,
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.traceTx(ctx, msg, txctx, vmctx, statedb, config)
|
return api.traceTx(ctx, msg, txctx, vmctx, statedb, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -865,6 +1067,7 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
Reexec: config.Reexec,
|
Reexec: config.Reexec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig)
|
return api.traceTx(ctx, msg, new(Context), vmctx, statedb, traceConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -872,6 +1075,18 @@ func (api *API) TraceCall(ctx context.Context, args ethapi.TransactionArgs, bloc
|
||||||
// executes the given message in the provided environment. The return value will
|
// executes the given message in the provided environment. The return value will
|
||||||
// be tracer dependent.
|
// be tracer dependent.
|
||||||
func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
|
func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Context, vmctx vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) {
|
||||||
|
|
||||||
|
if config == nil {
|
||||||
|
config = &TraceConfig{
|
||||||
|
BorTraceEnabled: defaultBorTraceEnabled,
|
||||||
|
BorTx: newBoolPtr(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.BorTraceEnabled == nil {
|
||||||
|
config.BorTraceEnabled = defaultBorTraceEnabled
|
||||||
|
}
|
||||||
|
|
||||||
// Assemble the structured logger or the JavaScript tracer
|
// Assemble the structured logger or the JavaScript tracer
|
||||||
var (
|
var (
|
||||||
tracer vm.EVMLogger
|
tracer vm.EVMLogger
|
||||||
|
|
@ -911,9 +1126,22 @@ func (api *API) traceTx(ctx context.Context, message core.Message, txctx *Contex
|
||||||
// Call Prepare to clear out the statedb access list
|
// Call Prepare to clear out the statedb access list
|
||||||
statedb.Prepare(txctx.TxHash, txctx.TxIndex)
|
statedb.Prepare(txctx.TxHash, txctx.TxIndex)
|
||||||
|
|
||||||
result, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
var result *core.ExecutionResult
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("tracing failed: %w", err)
|
if config.BorTx == nil {
|
||||||
|
config.BorTx = newBoolPtr(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *config.BorTx {
|
||||||
|
callmsg := prepareCallMessage(message)
|
||||||
|
if result, err = statefull.ApplyBorMessage(*vmenv, callmsg); err != nil {
|
||||||
|
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("tracing failed: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Depending on the tracer type, format and return the output.
|
// Depending on the tracer type, format and return the output.
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus/bor/statefull"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
|
@ -68,14 +69,14 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
||||||
|
|
||||||
// Execute all the transaction contained within the block concurrently
|
// Execute all the transaction contained within the block concurrently
|
||||||
var (
|
var (
|
||||||
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
signer = types.MakeSigner(api.backend.ChainConfig(), block.Number())
|
||||||
txs = block.Transactions()
|
txs, stateSyncPresent = api.getAllBlockTransactions(ctx, block)
|
||||||
deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number())
|
deleteEmptyObjects = api.backend.ChainConfig().IsEIP158(block.Number())
|
||||||
)
|
)
|
||||||
|
|
||||||
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
blockCtx := core.NewEVMBlockContext(block.Header(), api.chainContext(ctx), nil)
|
||||||
|
|
||||||
traceTxn := func(indx int, tx *types.Transaction) *TxTraceResult {
|
traceTxn := func(indx int, tx *types.Transaction, borTx bool) *TxTraceResult {
|
||||||
message, _ := tx.AsMessage(signer, block.BaseFee())
|
message, _ := tx.AsMessage(signer, block.BaseFee())
|
||||||
txContext := core.NewEVMTxContext(message)
|
txContext := core.NewEVMTxContext(message)
|
||||||
|
|
||||||
|
|
@ -88,7 +89,15 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
||||||
// Not sure if we need to do this
|
// Not sure if we need to do this
|
||||||
statedb.Prepare(tx.Hash(), indx)
|
statedb.Prepare(tx.Hash(), indx)
|
||||||
|
|
||||||
execRes, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
var execRes *core.ExecutionResult
|
||||||
|
|
||||||
|
if borTx {
|
||||||
|
callmsg := prepareCallMessage(message)
|
||||||
|
execRes, err = statefull.ApplyBorMessage(*vmenv, callmsg)
|
||||||
|
} else {
|
||||||
|
execRes, err = core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &TxTraceResult{
|
return &TxTraceResult{
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
|
|
@ -115,7 +124,11 @@ func (api *API) traceBorBlock(ctx context.Context, block *types.Block, config *T
|
||||||
}
|
}
|
||||||
|
|
||||||
for indx, tx := range txs {
|
for indx, tx := range txs {
|
||||||
res.Transactions = append(res.Transactions, traceTxn(indx, tx))
|
if stateSyncPresent && indx == len(txs)-1 {
|
||||||
|
res.Transactions = append(res.Transactions, traceTxn(indx, tx, true))
|
||||||
|
} else {
|
||||||
|
res.Transactions = append(res.Transactions, traceTxn(indx, tx, false))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,11 @@ func (b *testBackend) StateAtTransaction(ctx context.Context, block *types.Block
|
||||||
return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
return nil, vm.BlockContext{}, nil, fmt.Errorf("transaction index %d out of range for block %#x", txIndex, block.Hash())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *testBackend) GetBorBlockTransactionWithBlockHash(ctx context.Context, txHash common.Hash, blockHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
|
||||||
|
tx, blockHash, blockNumber, index := rawdb.ReadBorTransactionWithBlockHash(b.ChainDb(), txHash, blockHash)
|
||||||
|
return tx, blockHash, blockNumber, index, nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestTraceCall(t *testing.T) {
|
func TestTraceCall(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
||||||
2
go.mod
2
go.mod
|
|
@ -5,7 +5,6 @@ go 1.19
|
||||||
require (
|
require (
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0
|
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0
|
||||||
github.com/BurntSushi/toml v1.1.0
|
github.com/BurntSushi/toml v1.1.0
|
||||||
github.com/JekaMas/crand v1.0.1
|
|
||||||
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d
|
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d
|
||||||
github.com/VictoriaMetrics/fastcache v1.6.0
|
github.com/VictoriaMetrics/fastcache v1.6.0
|
||||||
github.com/aws/aws-sdk-go-v2 v1.2.0
|
github.com/aws/aws-sdk-go-v2 v1.2.0
|
||||||
|
|
@ -47,6 +46,7 @@ require (
|
||||||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
||||||
github.com/julienschmidt/httprouter v1.3.0
|
github.com/julienschmidt/httprouter v1.3.0
|
||||||
github.com/karalabe/usb v0.0.2
|
github.com/karalabe/usb v0.0.2
|
||||||
|
github.com/maticnetwork/crand v1.0.2
|
||||||
github.com/maticnetwork/polyproto v0.0.2
|
github.com/maticnetwork/polyproto v0.0.2
|
||||||
github.com/mattn/go-colorable v0.1.8
|
github.com/mattn/go-colorable v0.1.8
|
||||||
github.com/mattn/go-isatty v0.0.12
|
github.com/mattn/go-isatty v0.0.12
|
||||||
|
|
|
||||||
4
go.sum
4
go.sum
|
|
@ -29,8 +29,6 @@ github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I
|
||||||
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/JekaMas/crand v1.0.1 h1:FMPxkUQqH/hExl0aUXsr0UCGYZ4lJH9IJ5H/KbM6Y9A=
|
|
||||||
github.com/JekaMas/crand v1.0.1/go.mod h1:GGzGpMCht/tbaNQ5A4kSiKSqEoNAhhyTfSDQyIENBQU=
|
|
||||||
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d h1:RO27lgfZF8s9lZ3pWyzc0gCE0RZC+6/PXbRjAa0CNp8=
|
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d h1:RO27lgfZF8s9lZ3pWyzc0gCE0RZC+6/PXbRjAa0CNp8=
|
||||||
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d/go.mod h1:romz7UPgSYhfJkKOalzEEyV6sWtt/eAEm0nX2aOrod0=
|
github.com/JekaMas/go-grpc-net-conn v0.0.0-20220708155319-6aff21f2d13d/go.mod h1:romz7UPgSYhfJkKOalzEEyV6sWtt/eAEm0nX2aOrod0=
|
||||||
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
|
github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg=
|
||||||
|
|
@ -345,6 +343,8 @@ github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/maticnetwork/crand v1.0.2 h1:Af0tAivC8zrxXDpGWNWVT/0s1fOz8w0eRbahZgURS8I=
|
||||||
|
github.com/maticnetwork/crand v1.0.2/go.mod h1:/NRNL3bj2eYdqpWmoIP5puxndTpi0XRxpj5ZKxfHjyg=
|
||||||
github.com/maticnetwork/polyproto v0.0.2 h1:cPxuxbIDItdwGnucc3lZB58U8Zfe1mH73PWTGd15554=
|
github.com/maticnetwork/polyproto v0.0.2 h1:cPxuxbIDItdwGnucc3lZB58U8Zfe1mH73PWTGd15554=
|
||||||
github.com/maticnetwork/polyproto v0.0.2/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
|
github.com/maticnetwork/polyproto v0.0.2/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o=
|
||||||
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,12 @@ type Config struct {
|
||||||
// GcMode selects the garbage collection mode for the trie
|
// GcMode selects the garbage collection mode for the trie
|
||||||
GcMode string `hcl:"gcmode,optional" toml:"gcmode,optional"`
|
GcMode string `hcl:"gcmode,optional" toml:"gcmode,optional"`
|
||||||
|
|
||||||
// Snapshot disables/enables the snapshot database mode
|
// Snapshot enables the snapshot database mode
|
||||||
Snapshot bool `hcl:"snapshot,optional" toml:"snapshot,optional"`
|
Snapshot bool `hcl:"snapshot,optional" toml:"snapshot,optional"`
|
||||||
|
|
||||||
|
// BorLogs enables bor log retrieval
|
||||||
|
BorLogs bool `hcl:"bor.logs,optional" toml:"bor.logs,optional"`
|
||||||
|
|
||||||
// Ethstats is the address of the ethstats server to send telemetry
|
// Ethstats is the address of the ethstats server to send telemetry
|
||||||
Ethstats string `hcl:"ethstats,optional" toml:"ethstats,optional"`
|
Ethstats string `hcl:"ethstats,optional" toml:"ethstats,optional"`
|
||||||
|
|
||||||
|
|
@ -263,6 +266,9 @@ type APIConfig struct {
|
||||||
|
|
||||||
// Cors is the list of Cors endpoints
|
// Cors is the list of Cors endpoints
|
||||||
Cors []string `hcl:"corsdomain,optional" toml:"corsdomain,optional"`
|
Cors []string `hcl:"corsdomain,optional" toml:"corsdomain,optional"`
|
||||||
|
|
||||||
|
// Origins is the list of endpoints to accept requests from (only consumed for websockets)
|
||||||
|
Origins []string `hcl:"origins,optional" toml:"origins,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GpoConfig struct {
|
type GpoConfig struct {
|
||||||
|
|
@ -361,6 +367,9 @@ type CacheConfig struct {
|
||||||
|
|
||||||
// TxLookupLimit sets the maximum number of blocks from head whose tx indices are reserved.
|
// TxLookupLimit sets the maximum number of blocks from head whose tx indices are reserved.
|
||||||
TxLookupLimit uint64 `hcl:"txlookuplimit,optional" toml:"txlookuplimit,optional"`
|
TxLookupLimit uint64 `hcl:"txlookuplimit,optional" toml:"txlookuplimit,optional"`
|
||||||
|
|
||||||
|
// Number of block states to keep in memory (default = 128)
|
||||||
|
TriesInMemory uint64 `hcl:"triesinmemory,optional" toml:"triesinmemory,optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccountsConfig struct {
|
type AccountsConfig struct {
|
||||||
|
|
@ -396,7 +405,7 @@ func DefaultConfig() *Config {
|
||||||
LogLevel: "INFO",
|
LogLevel: "INFO",
|
||||||
DataDir: DefaultDataDir(),
|
DataDir: DefaultDataDir(),
|
||||||
P2P: &P2PConfig{
|
P2P: &P2PConfig{
|
||||||
MaxPeers: 30,
|
MaxPeers: 50,
|
||||||
MaxPendPeers: 50,
|
MaxPendPeers: 50,
|
||||||
Bind: "0.0.0.0",
|
Bind: "0.0.0.0",
|
||||||
Port: 30303,
|
Port: 30303,
|
||||||
|
|
@ -420,6 +429,7 @@ func DefaultConfig() *Config {
|
||||||
SyncMode: "full",
|
SyncMode: "full",
|
||||||
GcMode: "full",
|
GcMode: "full",
|
||||||
Snapshot: true,
|
Snapshot: true,
|
||||||
|
BorLogs: false,
|
||||||
TxPool: &TxPoolConfig{
|
TxPool: &TxPoolConfig{
|
||||||
Locals: []string{},
|
Locals: []string{},
|
||||||
NoLocals: false,
|
NoLocals: false,
|
||||||
|
|
@ -466,8 +476,7 @@ func DefaultConfig() *Config {
|
||||||
Prefix: "",
|
Prefix: "",
|
||||||
Host: "localhost",
|
Host: "localhost",
|
||||||
API: []string{"net", "web3"},
|
API: []string{"net", "web3"},
|
||||||
Cors: []string{"localhost"},
|
Origins: []string{"localhost"},
|
||||||
VHost: []string{"localhost"},
|
|
||||||
},
|
},
|
||||||
Graphql: &APIConfig{
|
Graphql: &APIConfig{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
|
|
@ -505,6 +514,7 @@ func DefaultConfig() *Config {
|
||||||
NoPrefetch: false,
|
NoPrefetch: false,
|
||||||
Preimages: false,
|
Preimages: false,
|
||||||
TxLookupLimit: 2350000,
|
TxLookupLimit: 2350000,
|
||||||
|
TriesInMemory: 128,
|
||||||
},
|
},
|
||||||
Accounts: &AccountsConfig{
|
Accounts: &AccountsConfig{
|
||||||
Unlock: []string{},
|
Unlock: []string{},
|
||||||
|
|
@ -649,6 +659,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (*
|
||||||
n.NetworkId = c.chain.NetworkId
|
n.NetworkId = c.chain.NetworkId
|
||||||
n.Genesis = c.chain.Genesis
|
n.Genesis = c.chain.Genesis
|
||||||
}
|
}
|
||||||
|
|
||||||
n.HeimdallURL = c.Heimdall.URL
|
n.HeimdallURL = c.Heimdall.URL
|
||||||
n.WithoutHeimdall = c.Heimdall.Without
|
n.WithoutHeimdall = c.Heimdall.Without
|
||||||
n.HeimdallgRPCAddress = c.Heimdall.GRPCAddress
|
n.HeimdallgRPCAddress = c.Heimdall.GRPCAddress
|
||||||
|
|
@ -881,6 +892,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
n.BorLogs = c.BorLogs
|
||||||
n.DatabaseHandles = dbHandles
|
n.DatabaseHandles = dbHandles
|
||||||
|
|
||||||
return &n, nil
|
return &n, nil
|
||||||
|
|
@ -920,7 +932,7 @@ func (c *Config) buildNode() (*node.Config, error) {
|
||||||
HTTPVirtualHosts: c.JsonRPC.Http.VHost,
|
HTTPVirtualHosts: c.JsonRPC.Http.VHost,
|
||||||
HTTPPathPrefix: c.JsonRPC.Http.Prefix,
|
HTTPPathPrefix: c.JsonRPC.Http.Prefix,
|
||||||
WSModules: c.JsonRPC.Ws.API,
|
WSModules: c.JsonRPC.Ws.API,
|
||||||
WSOrigins: c.JsonRPC.Ws.Cors,
|
WSOrigins: c.JsonRPC.Ws.Origins,
|
||||||
WSPathPrefix: c.JsonRPC.Ws.Prefix,
|
WSPathPrefix: c.JsonRPC.Ws.Prefix,
|
||||||
GraphQLCors: c.JsonRPC.Graphql.Cors,
|
GraphQLCors: c.JsonRPC.Graphql.Cors,
|
||||||
GraphQLVirtualHosts: c.JsonRPC.Graphql.VHost,
|
GraphQLVirtualHosts: c.JsonRPC.Graphql.VHost,
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ func (c *Command) Flags() *flagset.Flagset {
|
||||||
})
|
})
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
Name: "syncmode",
|
Name: "syncmode",
|
||||||
Usage: `Blockchain sync mode ("fast", "full", or "snap")`,
|
Usage: `Blockchain sync mode (only "full" sync supported)`,
|
||||||
Value: &c.cliConfig.SyncMode,
|
Value: &c.cliConfig.SyncMode,
|
||||||
Default: c.cliConfig.SyncMode,
|
Default: c.cliConfig.SyncMode,
|
||||||
})
|
})
|
||||||
|
|
@ -62,10 +62,16 @@ func (c *Command) Flags() *flagset.Flagset {
|
||||||
})
|
})
|
||||||
f.BoolFlag(&flagset.BoolFlag{
|
f.BoolFlag(&flagset.BoolFlag{
|
||||||
Name: "snapshot",
|
Name: "snapshot",
|
||||||
Usage: `Disables/Enables the snapshot-database mode (default = true)`,
|
Usage: `Enables the snapshot-database mode (default = true)`,
|
||||||
Value: &c.cliConfig.Snapshot,
|
Value: &c.cliConfig.Snapshot,
|
||||||
Default: c.cliConfig.Snapshot,
|
Default: c.cliConfig.Snapshot,
|
||||||
})
|
})
|
||||||
|
f.BoolFlag(&flagset.BoolFlag{
|
||||||
|
Name: "bor.logs",
|
||||||
|
Usage: `Enables bor log retrieval (default = false)`,
|
||||||
|
Value: &c.cliConfig.BorLogs,
|
||||||
|
Default: c.cliConfig.BorLogs,
|
||||||
|
})
|
||||||
|
|
||||||
// heimdall
|
// heimdall
|
||||||
f.StringFlag(&flagset.StringFlag{
|
f.StringFlag(&flagset.StringFlag{
|
||||||
|
|
@ -298,6 +304,13 @@ func (c *Command) Flags() *flagset.Flagset {
|
||||||
Default: c.cliConfig.Cache.Preimages,
|
Default: c.cliConfig.Cache.Preimages,
|
||||||
Group: "Cache",
|
Group: "Cache",
|
||||||
})
|
})
|
||||||
|
f.Uint64Flag(&flagset.Uint64Flag{
|
||||||
|
Name: "cache.triesinmemory",
|
||||||
|
Usage: "Number of block states (tries) to keep in memory (default = 128)",
|
||||||
|
Value: &c.cliConfig.Cache.TriesInMemory,
|
||||||
|
Default: c.cliConfig.Cache.TriesInMemory,
|
||||||
|
Group: "Cache",
|
||||||
|
})
|
||||||
f.Uint64Flag(&flagset.Uint64Flag{
|
f.Uint64Flag(&flagset.Uint64Flag{
|
||||||
Name: "txlookuplimit",
|
Name: "txlookuplimit",
|
||||||
Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)",
|
Usage: "Number of recent blocks to maintain transactions index for (default = about 56 days, 0 = entire chain)",
|
||||||
|
|
@ -350,17 +363,10 @@ func (c *Command) Flags() *flagset.Flagset {
|
||||||
Group: "JsonRPC",
|
Group: "JsonRPC",
|
||||||
})
|
})
|
||||||
f.SliceStringFlag(&flagset.SliceStringFlag{
|
f.SliceStringFlag(&flagset.SliceStringFlag{
|
||||||
Name: "ws.corsdomain",
|
Name: "ws.origins",
|
||||||
Usage: "Comma separated list of domains from which to accept cross origin requests (browser enforced)",
|
Usage: "Origins from which to accept websockets requests",
|
||||||
Value: &c.cliConfig.JsonRPC.Ws.Cors,
|
Value: &c.cliConfig.JsonRPC.Ws.Origins,
|
||||||
Default: c.cliConfig.JsonRPC.Ws.Cors,
|
Default: c.cliConfig.JsonRPC.Ws.Origins,
|
||||||
Group: "JsonRPC",
|
|
||||||
})
|
|
||||||
f.SliceStringFlag(&flagset.SliceStringFlag{
|
|
||||||
Name: "ws.vhosts",
|
|
||||||
Usage: "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.",
|
|
||||||
Value: &c.cliConfig.JsonRPC.Ws.VHost,
|
|
||||||
Default: c.cliConfig.JsonRPC.Ws.VHost,
|
|
||||||
Group: "JsonRPC",
|
Group: "JsonRPC",
|
||||||
})
|
})
|
||||||
f.SliceStringFlag(&flagset.SliceStringFlag{
|
f.SliceStringFlag(&flagset.SliceStringFlag{
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,10 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/metrics/influxdb"
|
"github.com/ethereum/go-ethereum/metrics/influxdb"
|
||||||
"github.com/ethereum/go-ethereum/metrics/prometheus"
|
"github.com/ethereum/go-ethereum/metrics/prometheus"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
|
||||||
|
// Force-load the tracer engines to trigger registration
|
||||||
|
_ "github.com/ethereum/go-ethereum/eth/tracers/js"
|
||||||
|
_ "github.com/ethereum/go-ethereum/eth/tracers/native"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
|
|
@ -253,6 +257,12 @@ func (s *Server) Stop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error {
|
func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error {
|
||||||
|
// Check the global metrics if they're matching with the provided config
|
||||||
|
if metrics.Enabled != config.Enabled || metrics.EnabledExpensive != config.Expensive {
|
||||||
|
log.Warn("Metric misconfiguration, some of them might not be visible")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the values anyways (for services which don't need immediate attention)
|
||||||
metrics.Enabled = config.Enabled
|
metrics.Enabled = config.Enabled
|
||||||
metrics.EnabledExpensive = config.Expensive
|
metrics.EnabledExpensive = config.Expensive
|
||||||
|
|
||||||
|
|
@ -263,6 +273,10 @@ func (s *Server) setupMetrics(config *TelemetryConfig, serviceName string) error
|
||||||
|
|
||||||
log.Info("Enabling metrics collection")
|
log.Info("Enabling metrics collection")
|
||||||
|
|
||||||
|
if metrics.EnabledExpensive {
|
||||||
|
log.Info("Enabling expensive metrics collection")
|
||||||
|
}
|
||||||
|
|
||||||
// influxdb
|
// influxdb
|
||||||
if v1Enabled, v2Enabled := config.InfluxDB.V1Enabled, config.InfluxDB.V2Enabled; v1Enabled || v2Enabled {
|
if v1Enabled, v2Enabled := config.InfluxDB.V1Enabled, config.InfluxDB.V2Enabled; v1Enabled || v2Enabled {
|
||||||
if v1Enabled && v2Enabled {
|
if v1Enabled && v2Enabled {
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ func TestGetStaleCodeLes4(t *testing.T) { testGetStaleCode(t, 4) }
|
||||||
|
|
||||||
func testGetStaleCode(t *testing.T, protocol int) {
|
func testGetStaleCode(t *testing.T, protocol int) {
|
||||||
netconfig := testnetConfig{
|
netconfig := testnetConfig{
|
||||||
blocks: core.TriesInMemory + 4,
|
blocks: int(core.DefaultCacheConfig.TriesInMemory) + 4,
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
nopruning: true,
|
nopruning: true,
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +430,7 @@ func TestGetStaleProofLes4(t *testing.T) { testGetStaleProof(t, 4) }
|
||||||
|
|
||||||
func testGetStaleProof(t *testing.T, protocol int) {
|
func testGetStaleProof(t *testing.T, protocol int) {
|
||||||
netconfig := testnetConfig{
|
netconfig := testnetConfig{
|
||||||
blocks: core.TriesInMemory + 4,
|
blocks: int(core.DefaultCacheConfig.TriesInMemory) + 4,
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
nopruning: true,
|
nopruning: true,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1058,7 +1058,7 @@ func (p *clientPeer) Handshake(td *big.Int, head common.Hash, headNum uint64, ge
|
||||||
|
|
||||||
// If local ethereum node is running in archive mode, advertise ourselves we have
|
// If local ethereum node is running in archive mode, advertise ourselves we have
|
||||||
// all version state data. Otherwise only recent state is available.
|
// all version state data. Otherwise only recent state is available.
|
||||||
stateRecent := uint64(core.TriesInMemory - blockSafetyMargin)
|
stateRecent := core.DefaultCacheConfig.TriesInMemory - blockSafetyMargin
|
||||||
if server.archiveMode {
|
if server.archiveMode {
|
||||||
stateRecent = 0
|
stateRecent = 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,7 @@ func handleGetCode(msg Decoder) (serveRequestFn, uint64, uint64, error) {
|
||||||
// Refuse to search stale state data in the database since looking for
|
// Refuse to search stale state data in the database since looking for
|
||||||
// a non-exist key is kind of expensive.
|
// a non-exist key is kind of expensive.
|
||||||
local := bc.CurrentHeader().Number.Uint64()
|
local := bc.CurrentHeader().Number.Uint64()
|
||||||
if !backend.ArchiveMode() && header.Number.Uint64()+core.TriesInMemory <= local {
|
if !backend.ArchiveMode() && header.Number.Uint64()+core.DefaultCacheConfig.TriesInMemory <= local {
|
||||||
p.Log().Debug("Reject stale code request", "number", header.Number.Uint64(), "head", local)
|
p.Log().Debug("Reject stale code request", "number", header.Number.Uint64(), "head", local)
|
||||||
p.bumpInvalid()
|
p.bumpInvalid()
|
||||||
continue
|
continue
|
||||||
|
|
@ -396,7 +396,7 @@ func handleGetProofs(msg Decoder) (serveRequestFn, uint64, uint64, error) {
|
||||||
// Refuse to search stale state data in the database since looking for
|
// Refuse to search stale state data in the database since looking for
|
||||||
// a non-exist key is kind of expensive.
|
// a non-exist key is kind of expensive.
|
||||||
local := bc.CurrentHeader().Number.Uint64()
|
local := bc.CurrentHeader().Number.Uint64()
|
||||||
if !backend.ArchiveMode() && header.Number.Uint64()+core.TriesInMemory <= local {
|
if !backend.ArchiveMode() && header.Number.Uint64()+core.DefaultCacheConfig.TriesInMemory <= local {
|
||||||
p.Log().Debug("Reject stale trie request", "number", header.Number.Uint64(), "head", local)
|
p.Log().Debug("Reject stale trie request", "number", header.Number.Uint64(), "head", local)
|
||||||
p.bumpInvalid()
|
p.bumpInvalid()
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -377,7 +377,7 @@ func (p *testPeer) handshakeWithClient(t *testing.T, td *big.Int, head common.Ha
|
||||||
sendList = sendList.add("serveHeaders", nil)
|
sendList = sendList.add("serveHeaders", nil)
|
||||||
sendList = sendList.add("serveChainSince", uint64(0))
|
sendList = sendList.add("serveChainSince", uint64(0))
|
||||||
sendList = sendList.add("serveStateSince", uint64(0))
|
sendList = sendList.add("serveStateSince", uint64(0))
|
||||||
sendList = sendList.add("serveRecentState", uint64(core.TriesInMemory-4))
|
sendList = sendList.add("serveRecentState", core.DefaultCacheConfig.TriesInMemory-4)
|
||||||
sendList = sendList.add("txRelay", nil)
|
sendList = sendList.add("txRelay", nil)
|
||||||
sendList = sendList.add("flowControl/BL", testBufLimit)
|
sendList = sendList.add("flowControl/BL", testBufLimit)
|
||||||
sendList = sendList.add("flowControl/MRR", testBufRecharge)
|
sendList = sendList.add("flowControl/MRR", testBufRecharge)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/BurntSushi/toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enabled is checked by the constructor functions for all of the
|
// Enabled is checked by the constructor functions for all of the
|
||||||
|
|
@ -32,26 +32,71 @@ var enablerFlags = []string{"metrics"}
|
||||||
// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections.
|
// expensiveEnablerFlags is the CLI flag names to use to enable metrics collections.
|
||||||
var expensiveEnablerFlags = []string{"metrics.expensive"}
|
var expensiveEnablerFlags = []string{"metrics.expensive"}
|
||||||
|
|
||||||
|
// configFlag is the CLI flag name to use to start node by providing a toml based config
|
||||||
|
var configFlag = "config"
|
||||||
|
|
||||||
// Init enables or disables the metrics system. Since we need this to run before
|
// Init enables or disables the metrics system. Since we need this to run before
|
||||||
// any other code gets to create meters and timers, we'll actually do an ugly hack
|
// any other code gets to create meters and timers, we'll actually do an ugly hack
|
||||||
// and peek into the command line args for the metrics flag.
|
// and peek into the command line args for the metrics flag.
|
||||||
func init() {
|
func init() {
|
||||||
for _, arg := range os.Args {
|
var configFile string
|
||||||
|
|
||||||
|
for i := 0; i < len(os.Args); i++ {
|
||||||
|
arg := os.Args[i]
|
||||||
|
|
||||||
flag := strings.TrimLeft(arg, "-")
|
flag := strings.TrimLeft(arg, "-")
|
||||||
|
|
||||||
|
// check for existence of `config` flag
|
||||||
|
if flag == configFlag && i < len(os.Args)-1 {
|
||||||
|
configFile = strings.TrimLeft(os.Args[i+1], "-") // find the value of flag
|
||||||
|
}
|
||||||
|
|
||||||
for _, enabler := range enablerFlags {
|
for _, enabler := range enablerFlags {
|
||||||
if !Enabled && flag == enabler {
|
if !Enabled && flag == enabler {
|
||||||
log.Info("Enabling metrics collection")
|
|
||||||
Enabled = true
|
Enabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, enabler := range expensiveEnablerFlags {
|
for _, enabler := range expensiveEnablerFlags {
|
||||||
if !EnabledExpensive && flag == enabler {
|
if !EnabledExpensive && flag == enabler {
|
||||||
log.Info("Enabling expensive metrics collection")
|
|
||||||
EnabledExpensive = true
|
EnabledExpensive = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the global metrics value, if they're provided in the config file
|
||||||
|
updateMetricsFromConfig(configFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateMetricsFromConfig(path string) {
|
||||||
|
// Don't act upon any errors here. They're already taken into
|
||||||
|
// consideration when the toml config file will be parsed in the cli.
|
||||||
|
data, err := os.ReadFile(path)
|
||||||
|
tomlData := string(data)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a minimal config to decode
|
||||||
|
type TelemetryConfig struct {
|
||||||
|
Enabled bool `hcl:"metrics,optional" toml:"metrics,optional"`
|
||||||
|
Expensive bool `hcl:"expensive,optional" toml:"expensive,optional"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CliConfig struct {
|
||||||
|
Telemetry *TelemetryConfig `hcl:"telemetry,block" toml:"telemetry,block"`
|
||||||
|
}
|
||||||
|
|
||||||
|
conf := &CliConfig{}
|
||||||
|
|
||||||
|
if _, err := toml.Decode(tomlData, &conf); err != nil || conf == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have the values now, update them
|
||||||
|
Enabled = conf.Telemetry.Enabled
|
||||||
|
EnabledExpensive = conf.Telemetry.Expensive
|
||||||
}
|
}
|
||||||
|
|
||||||
// CollectProcessMetrics periodically collects various metrics about the running
|
// CollectProcessMetrics periodically collects various metrics about the running
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ var flagMap = map[string][]string{
|
||||||
"override.arrowglacier": {"notABoolFlag", "No"},
|
"override.arrowglacier": {"notABoolFlag", "No"},
|
||||||
"override.terminaltotaldifficulty": {"notABoolFlag", "No"},
|
"override.terminaltotaldifficulty": {"notABoolFlag", "No"},
|
||||||
"verbosity": {"notABoolFlag", "YesFV"},
|
"verbosity": {"notABoolFlag", "YesFV"},
|
||||||
"ws.origins": {"notABoolFlag", "YesF"},
|
"ws.origins": {"notABoolFlag", "No"},
|
||||||
}
|
}
|
||||||
|
|
||||||
// map from cli flags to corresponding toml tags
|
// map from cli flags to corresponding toml tags
|
||||||
|
|
@ -109,8 +109,9 @@ var nameTagMap = map[string]string{
|
||||||
"gcmode": "gcmode",
|
"gcmode": "gcmode",
|
||||||
"eth.requiredblocks": "eth.requiredblocks",
|
"eth.requiredblocks": "eth.requiredblocks",
|
||||||
"0-snapshot": "snapshot",
|
"0-snapshot": "snapshot",
|
||||||
|
"\"bor.logs\"": "bor.logs",
|
||||||
"url": "bor.heimdall",
|
"url": "bor.heimdall",
|
||||||
"bor.without": "bor.withoutheimdall",
|
"\"bor.without\"": "bor.withoutheimdall",
|
||||||
"grpc-address": "bor.heimdallgRPC",
|
"grpc-address": "bor.heimdallgRPC",
|
||||||
"locals": "txpool.locals",
|
"locals": "txpool.locals",
|
||||||
"nolocals": "txpool.nolocals",
|
"nolocals": "txpool.nolocals",
|
||||||
|
|
@ -149,8 +150,7 @@ var nameTagMap = map[string]string{
|
||||||
"ipcpath": "ipcpath",
|
"ipcpath": "ipcpath",
|
||||||
"1-corsdomain": "http.corsdomain",
|
"1-corsdomain": "http.corsdomain",
|
||||||
"1-vhosts": "http.vhosts",
|
"1-vhosts": "http.vhosts",
|
||||||
"2-corsdomain": "ws.corsdomain",
|
"origins": "ws.origins",
|
||||||
"2-vhosts": "ws.vhosts",
|
|
||||||
"3-corsdomain": "graphql.corsdomain",
|
"3-corsdomain": "graphql.corsdomain",
|
||||||
"3-vhosts": "graphql.vhosts",
|
"3-vhosts": "graphql.vhosts",
|
||||||
"1-enabled": "http",
|
"1-enabled": "http",
|
||||||
|
|
@ -225,12 +225,12 @@ var replacedFlagsMapFlagAndValue = map[string]map[string]map[string]string{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var replacedFlagsMapFlag = map[string]string{
|
// Do not remove
|
||||||
"ws.origins": "ws.corsdomain",
|
var replacedFlagsMapFlag = map[string]string{}
|
||||||
}
|
|
||||||
|
|
||||||
var currentBoolFlags = []string{
|
var currentBoolFlags = []string{
|
||||||
"snapshot",
|
"snapshot",
|
||||||
|
"bor.logs",
|
||||||
"bor.withoutheimdall",
|
"bor.withoutheimdall",
|
||||||
"txpool.nolocals",
|
"txpool.nolocals",
|
||||||
"mine",
|
"mine",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,19 @@
|
||||||
#!/usr/bin/env sh
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
# Instructions:
|
# Instructions:
|
||||||
# Execute `./getconfig.sh`, and follow the instructions displayed on the terminal
|
# Execute `./getconfig.sh`, and follow the instructions displayed on the terminal
|
||||||
# The `*-config.toml` file will be created in the same directory as start.sh
|
# The `*-config.toml` file will be created in the same directory as start.sh
|
||||||
# It is recommended to check the flags generated in config.toml
|
# It is recommended to check the flags generated in config.toml
|
||||||
|
|
||||||
|
# Some checks to make commands OS independent
|
||||||
|
OS="$(uname -s)"
|
||||||
|
MKTEMPOPTION=
|
||||||
|
SEDOPTION= ## Not used as of now (TODO)
|
||||||
|
shopt -s nocasematch; if [[ "$OS" == "darwin"* ]]; then
|
||||||
|
SEDOPTION="''"
|
||||||
|
MKTEMPOPTION="-t"
|
||||||
|
fi
|
||||||
|
|
||||||
read -p "* Path to start.sh: " startPath
|
read -p "* Path to start.sh: " startPath
|
||||||
# check if start.sh is present
|
# check if start.sh is present
|
||||||
|
|
@ -15,7 +24,7 @@ then
|
||||||
fi
|
fi
|
||||||
read -p "* Your validator address (e.g. 0xca67a8D767e45056DC92384b488E9Af654d78DE2), or press Enter to skip if running a sentry node: " ADD
|
read -p "* Your validator address (e.g. 0xca67a8D767e45056DC92384b488E9Af654d78DE2), or press Enter to skip if running a sentry node: " ADD
|
||||||
|
|
||||||
echo "\nThank you, your inputs are:"
|
printf "\nThank you, your inputs are:\n"
|
||||||
echo "Path to start.sh: "$startPath
|
echo "Path to start.sh: "$startPath
|
||||||
echo "Address: "$ADD
|
echo "Address: "$ADD
|
||||||
|
|
||||||
|
|
@ -26,8 +35,9 @@ if [[ -f $confPath ]]
|
||||||
then
|
then
|
||||||
echo "WARN: config.toml exists, data will be overwritten."
|
echo "WARN: config.toml exists, data will be overwritten."
|
||||||
fi
|
fi
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
tmpDir="$(mktemp -d -t ./temp-dir-XXXXXXXXXXX || oops "Can't create temporary directory")"
|
tmpDir="$(mktemp -d $MKTEMPOPTION ./temp-dir-XXXXXXXXXXX || oops "Can't create temporary directory")"
|
||||||
cleanup() {
|
cleanup() {
|
||||||
rm -rf "$tmpDir"
|
rm -rf "$tmpDir"
|
||||||
}
|
}
|
||||||
|
|
@ -39,8 +49,11 @@ chmod +x $tmpDir/3305fe263dd4a999d58f96deb064e21bb70123d9.sh
|
||||||
$tmpDir/3305fe263dd4a999d58f96deb064e21bb70123d9.sh $ADD
|
$tmpDir/3305fe263dd4a999d58f96deb064e21bb70123d9.sh $ADD
|
||||||
rm $tmpDir/3305fe263dd4a999d58f96deb064e21bb70123d9.sh
|
rm $tmpDir/3305fe263dd4a999d58f96deb064e21bb70123d9.sh
|
||||||
|
|
||||||
|
shopt -s nocasematch; if [[ "$OS" == "darwin"* ]]; then
|
||||||
sed -i '' "s%*%'*'%g" ./temp
|
sed -i '' "s%*%'*'%g" ./temp
|
||||||
|
else
|
||||||
|
sed -i "s%*%'*'%g" ./temp
|
||||||
|
fi
|
||||||
|
|
||||||
# read the flags from `./temp`
|
# read the flags from `./temp`
|
||||||
dumpconfigflags=$(head -1 ./temp)
|
dumpconfigflags=$(head -1 ./temp)
|
||||||
|
|
@ -51,17 +64,27 @@ bash -c "$command"
|
||||||
|
|
||||||
rm ./temp
|
rm ./temp
|
||||||
|
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
if [[ -f ./tempStaticNodes.json ]]
|
if [[ -f ./tempStaticNodes.json ]]
|
||||||
then
|
then
|
||||||
echo "JSON StaticNodes found"
|
echo "JSON StaticNodes found"
|
||||||
staticnodesjson=$(head -1 ./tempStaticNodes.json)
|
staticnodesjson=$(head -1 ./tempStaticNodes.json)
|
||||||
sed -i '' "s%static-nodes = \[\]%static-nodes = \[\"${staticnodesjson}\"\]%" $confPath
|
shopt -s nocasematch; if [[ "$OS" == "darwin"* ]]; then
|
||||||
|
sed -i '' "s%static-nodes = \[\]%static-nodes = \[\"${staticnodesjson}\"\]%" $confPath
|
||||||
|
else
|
||||||
|
sed -i "s%static-nodes = \[\]%static-nodes = \[\"${staticnodesjson}\"\]%" $confPath
|
||||||
|
fi
|
||||||
rm ./tempStaticNodes.json
|
rm ./tempStaticNodes.json
|
||||||
elif [[ -f ./tempStaticNodes.toml ]]
|
elif [[ -f ./tempStaticNodes.toml ]]
|
||||||
then
|
then
|
||||||
echo "TOML StaticNodes found"
|
echo "TOML StaticNodes found"
|
||||||
staticnodestoml=$(head -1 ./tempStaticNodes.toml)
|
staticnodestoml=$(head -1 ./tempStaticNodes.toml)
|
||||||
sed -i '' "s%static-nodes = \[\]%static-nodes = \[\"${staticnodestoml}\"\]%" $confPath
|
shopt -s nocasematch; if [[ "$OS" == "darwin"* ]]; then
|
||||||
|
sed -i '' "s%static-nodes = \[\]%static-nodes = \[\"${staticnodestoml}\"\]%" $confPath
|
||||||
|
else
|
||||||
|
sed -i "s%static-nodes = \[\]%static-nodes = \[\"${staticnodestoml}\"\]%" $confPath
|
||||||
|
fi
|
||||||
rm ./tempStaticNodes.toml
|
rm ./tempStaticNodes.toml
|
||||||
else
|
else
|
||||||
echo "neither JSON nor TOML StaticNodes found"
|
echo "neither JSON nor TOML StaticNodes found"
|
||||||
|
|
@ -71,12 +94,18 @@ if [[ -f ./tempTrustedNodes.toml ]]
|
||||||
then
|
then
|
||||||
echo "TOML TrustedNodes found"
|
echo "TOML TrustedNodes found"
|
||||||
trustednodestoml=$(head -1 ./tempTrustedNodes.toml)
|
trustednodestoml=$(head -1 ./tempTrustedNodes.toml)
|
||||||
sed -i '' "s%trusted-nodes = \[\]%trusted-nodes = \[\"${trustednodestoml}\"\]%" $confPath
|
shopt -s nocasematch; if [[ "$OS" == "darwin"* ]]; then
|
||||||
|
sed -i '' "s%trusted-nodes = \[\]%trusted-nodes = \[\"${trustednodestoml}\"\]%" $confPath
|
||||||
|
else
|
||||||
|
sed -i "s%trusted-nodes = \[\]%trusted-nodes = \[\"${trustednodestoml}\"\]%" $confPath
|
||||||
|
fi
|
||||||
rm ./tempTrustedNodes.toml
|
rm ./tempTrustedNodes.toml
|
||||||
else
|
else
|
||||||
echo "neither JSON nor TOML TrustedNodes found"
|
echo "neither JSON nor TOML TrustedNodes found"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
printf "\n"
|
||||||
|
|
||||||
# comment flags in $configPath that were not passed through $startPath
|
# comment flags in $configPath that were not passed through $startPath
|
||||||
# SHA1 hash of `tempStart` -> `3305fe263dd4a999d58f96deb064e21bb70123d9`
|
# SHA1 hash of `tempStart` -> `3305fe263dd4a999d58f96deb064e21bb70123d9`
|
||||||
sed "s%bor --%go run getconfig.go ${confPath} --%" $startPath > $tmpDir/3305fe263dd4a999d58f96deb064e21bb70123d9.sh
|
sed "s%bor --%go run getconfig.go ${confPath} --%" $startPath > $tmpDir/3305fe263dd4a999d58f96deb064e21bb70123d9.sh
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,11 @@ package bor
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
_log "log"
|
_log "log"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -15,12 +18,18 @@ import (
|
||||||
|
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/fdlimit"
|
"github.com/ethereum/go-ethereum/common/fdlimit"
|
||||||
"github.com/ethereum/go-ethereum/core"
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/eth"
|
"github.com/ethereum/go-ethereum/eth"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||||
|
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/miner"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
)
|
)
|
||||||
|
|
@ -52,7 +61,7 @@ func TestValidatorsBlockProduction(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an Ethash network based off of the Ropsten config
|
// Create an Ethash network based off of the Ropsten config
|
||||||
genesis := InitGenesis(t, faucets, "./testdata/genesis_sprint_length_change.json", 32)
|
genesis := InitGenesisSprintLength(t, faucets, "./testdata/genesis_sprint_length_change.json", 32)
|
||||||
nodes := make([]*eth.Ethereum, 2)
|
nodes := make([]*eth.Ethereum, 2)
|
||||||
enodes := make([]*enode.Node, 2)
|
enodes := make([]*enode.Node, 2)
|
||||||
|
|
||||||
|
|
@ -265,7 +274,7 @@ func getTestSprintLengthReorgCases2Nodes() []map[string]interface{} {
|
||||||
"reorgLength": j,
|
"reorgLength": j,
|
||||||
"startBlock": k,
|
"startBlock": k,
|
||||||
"sprintSize": sprintSizes[i],
|
"sprintSize": sprintSizes[i],
|
||||||
"faultyNodes": faultyNodes[i], // node 1(index) is primary validator of the first sprint
|
"faultyNodes": faultyNodes[l], // node 1(index) is primary validator of the first sprint
|
||||||
}
|
}
|
||||||
reorgsLengthTests = append(reorgsLengthTests, reorgsLengthTest)
|
reorgsLengthTests = append(reorgsLengthTests, reorgsLengthTest)
|
||||||
}
|
}
|
||||||
|
|
@ -356,7 +365,7 @@ func SprintLengthReorgIndividual2Nodes(t *testing.T, index int, tt map[string]in
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSprintLengthReorg2Nodes(t *testing.T) {
|
func TestSprintLengthReorg2Nodes(t *testing.T) {
|
||||||
t.Skip()
|
// t.Skip()
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
reorgsLengthTests := getTestSprintLengthReorgCases2Nodes()
|
reorgsLengthTests := getTestSprintLengthReorgCases2Nodes()
|
||||||
|
|
@ -476,7 +485,7 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an Ethash network based off of the Ropsten config
|
// Create an Ethash network based off of the Ropsten config
|
||||||
genesis := InitGenesis(t, nil, "./testdata/genesis_7val.json", tt["sprintSize"])
|
genesis := InitGenesisSprintLength(t, nil, "./testdata/genesis_7val.json", tt["sprintSize"])
|
||||||
|
|
||||||
nodes := make([]*eth.Ethereum, len(keys_21val))
|
nodes := make([]*eth.Ethereum, len(keys_21val))
|
||||||
enodes := make([]*enode.Node, len(keys_21val))
|
enodes := make([]*enode.Node, len(keys_21val))
|
||||||
|
|
@ -599,9 +608,8 @@ func SetupValidatorsAndTest2Nodes(t *testing.T, tt map[string]interface{}) (uint
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an Ethash network based off of the Ropsten config
|
// Create an Ethash network based off of the Ropsten config
|
||||||
genesis := InitGenesis(t, nil, "./testdata/genesis_7val.json", tt["sprintSize"])
|
genesis := InitGenesisSprintLength(t, nil, "./testdata/genesis_7val.json", tt["sprintSize"].(uint64))
|
||||||
|
|
||||||
nodes := make([]*eth.Ethereum, len(keys_21val))
|
nodes := make([]*eth.Ethereum, len(keys_21val))
|
||||||
enodes := make([]*enode.Node, len(keys_21val))
|
enodes := make([]*enode.Node, len(keys_21val))
|
||||||
|
|
@ -711,3 +719,81 @@ func SetupValidatorsAndTest2Nodes(t *testing.T, tt map[string]interface{}) (uint
|
||||||
|
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func InitGenesisSprintLength(t *testing.T, faucets []*ecdsa.PrivateKey, fileLocation string, sprintSize uint64) *core.Genesis {
|
||||||
|
|
||||||
|
// sprint size = 8 in genesis
|
||||||
|
genesisData, err := ioutil.ReadFile(fileLocation)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
genesis := &core.Genesis{}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(genesisData, genesis); err != nil {
|
||||||
|
t.Fatalf("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
genesis.Config.ChainID = big.NewInt(15001)
|
||||||
|
genesis.Config.EIP150Hash = common.Hash{}
|
||||||
|
genesis.Config.Bor.Sprint["0"] = sprintSize
|
||||||
|
|
||||||
|
return genesis
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitMiner(genesis *core.Genesis, privKey *ecdsa.PrivateKey, withoutHeimdall bool) (*node.Node, *eth.Ethereum, error) {
|
||||||
|
// Define the basic configurations for the Ethereum node
|
||||||
|
datadir, _ := ioutil.TempDir("", "")
|
||||||
|
|
||||||
|
config := &node.Config{
|
||||||
|
Name: "geth",
|
||||||
|
Version: params.Version,
|
||||||
|
DataDir: datadir,
|
||||||
|
P2P: p2p.Config{
|
||||||
|
ListenAddr: "0.0.0.0:0",
|
||||||
|
NoDiscovery: true,
|
||||||
|
MaxPeers: 25,
|
||||||
|
},
|
||||||
|
UseLightweightKDF: true,
|
||||||
|
}
|
||||||
|
// Create the node and configure a full Ethereum node on it
|
||||||
|
stack, err := node.New(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ethBackend, err := eth.New(stack, ðconfig.Config{
|
||||||
|
Genesis: genesis,
|
||||||
|
NetworkId: genesis.Config.ChainID.Uint64(),
|
||||||
|
SyncMode: downloader.FullSync,
|
||||||
|
DatabaseCache: 256,
|
||||||
|
DatabaseHandles: 256,
|
||||||
|
TxPool: core.DefaultTxPoolConfig,
|
||||||
|
GPO: ethconfig.Defaults.GPO,
|
||||||
|
Ethash: ethconfig.Defaults.Ethash,
|
||||||
|
Miner: miner.Config{
|
||||||
|
Etherbase: crypto.PubkeyToAddress(privKey.PublicKey),
|
||||||
|
GasCeil: genesis.GasLimit * 11 / 10,
|
||||||
|
GasPrice: big.NewInt(1),
|
||||||
|
Recommit: time.Second,
|
||||||
|
},
|
||||||
|
WithoutHeimdall: withoutHeimdall,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// register backend to account manager with keystore for signing
|
||||||
|
keydir := stack.KeyStoreDir()
|
||||||
|
|
||||||
|
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
||||||
|
kStore := keystore.NewKeyStore(keydir, n, p)
|
||||||
|
|
||||||
|
kStore.ImportECDSA(privKey, "")
|
||||||
|
acc := kStore.Accounts()[0]
|
||||||
|
kStore.Unlock(acc, "")
|
||||||
|
// proceed to authorize the local account manager in any case
|
||||||
|
ethBackend.AccountManager().AddBackend(kStore)
|
||||||
|
|
||||||
|
err = stack.Start()
|
||||||
|
return stack, ethBackend, err
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -210,6 +210,141 @@ func TestValidatorWentOffline(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestForkWithBlockTime(t *testing.T) {
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
sprint uint64
|
||||||
|
blockTime map[string]uint64
|
||||||
|
change uint64
|
||||||
|
producerDelay uint64
|
||||||
|
forkExpected bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "No fork after 2 sprints with producer delay = max block time",
|
||||||
|
sprint: 128,
|
||||||
|
blockTime: map[string]uint64{
|
||||||
|
"0": 5,
|
||||||
|
"128": 2,
|
||||||
|
"256": 8,
|
||||||
|
},
|
||||||
|
change: 2,
|
||||||
|
producerDelay: 8,
|
||||||
|
forkExpected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "No Fork after 1 sprint producer delay = max block time",
|
||||||
|
sprint: 64,
|
||||||
|
blockTime: map[string]uint64{
|
||||||
|
"0": 5,
|
||||||
|
"64": 2,
|
||||||
|
},
|
||||||
|
change: 1,
|
||||||
|
producerDelay: 5,
|
||||||
|
forkExpected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fork after 4 sprints with producer delay < max block time",
|
||||||
|
sprint: 16,
|
||||||
|
blockTime: map[string]uint64{
|
||||||
|
"0": 2,
|
||||||
|
"64": 5,
|
||||||
|
},
|
||||||
|
change: 4,
|
||||||
|
producerDelay: 4,
|
||||||
|
forkExpected: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an Ethash network based off of the Ropsten config
|
||||||
|
genesis := initGenesis(t)
|
||||||
|
|
||||||
|
for _, test := range cases {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|
||||||
|
genesis.Config.Bor.Sprint = test.sprint
|
||||||
|
genesis.Config.Bor.Period = test.blockTime
|
||||||
|
genesis.Config.Bor.BackupMultiplier = test.blockTime
|
||||||
|
genesis.Config.Bor.ProducerDelay = test.producerDelay
|
||||||
|
|
||||||
|
stacks, nodes, _ := setupMiner(t, 2, genesis)
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
for _, stack := range stacks {
|
||||||
|
stack.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Iterate over all the nodes and start mining
|
||||||
|
for _, node := range nodes {
|
||||||
|
if err := node.StartMining(1); err != nil {
|
||||||
|
t.Fatal("Error occured while starting miner", "node", node, "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
blockHeaders := make([]*types.Header, 2)
|
||||||
|
ticker := time.NewTicker(time.Duration(test.blockTime["0"]) * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func(i int) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
for range ticker.C {
|
||||||
|
blockHeaders[i] = nodes[i].BlockChain().GetHeaderByNumber(test.sprint*test.change + 10)
|
||||||
|
if blockHeaders[i] != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
// Before the end of sprint
|
||||||
|
blockHeaderVal0 := nodes[0].BlockChain().GetHeaderByNumber(test.sprint - 1)
|
||||||
|
blockHeaderVal1 := nodes[1].BlockChain().GetHeaderByNumber(test.sprint - 1)
|
||||||
|
assert.Equal(t, blockHeaderVal0.Hash(), blockHeaderVal1.Hash())
|
||||||
|
assert.Equal(t, blockHeaderVal0.Time, blockHeaderVal1.Time)
|
||||||
|
|
||||||
|
author0, err := nodes[0].Engine().Author(blockHeaderVal0)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Error occured while fetching author", "err", err)
|
||||||
|
}
|
||||||
|
author1, err := nodes[1].Engine().Author(blockHeaderVal1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Error occured while fetching author", "err", err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, author0, author1)
|
||||||
|
|
||||||
|
// After the end of sprint
|
||||||
|
author2, err := nodes[0].Engine().Author(blockHeaders[0])
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Error occured while fetching author", "err", err)
|
||||||
|
}
|
||||||
|
author3, err := nodes[1].Engine().Author(blockHeaders[1])
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Error occured while fetching author", "err", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.forkExpected {
|
||||||
|
assert.NotEqual(t, blockHeaders[0].Hash(), blockHeaders[1].Hash())
|
||||||
|
assert.NotEqual(t, blockHeaders[0].Time, blockHeaders[1].Time)
|
||||||
|
assert.NotEqual(t, author2, author3)
|
||||||
|
} else {
|
||||||
|
assert.Equal(t, blockHeaders[0].Hash(), blockHeaders[1].Hash())
|
||||||
|
assert.Equal(t, blockHeaders[0].Time, blockHeaders[1].Time)
|
||||||
|
assert.Equal(t, author2, author3)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestInsertingSpanSizeBlocks(t *testing.T) {
|
func TestInsertingSpanSizeBlocks(t *testing.T) {
|
||||||
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
|
init := buildEthereumInstance(t, rawdb.NewMemoryDatabase())
|
||||||
chain := init.ethereum.BlockChain()
|
chain := init.ethereum.BlockChain()
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/miner"
|
"github.com/ethereum/go-ethereum/miner"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/p2p"
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/tests/bor/mocks"
|
"github.com/ethereum/go-ethereum/tests/bor/mocks"
|
||||||
)
|
)
|
||||||
|
|
@ -53,6 +54,8 @@ var (
|
||||||
// This account is one the validators for 1st span (0-indexed)
|
// This account is one the validators for 1st span (0-indexed)
|
||||||
key2, _ = crypto.HexToECDSA(privKey2)
|
key2, _ = crypto.HexToECDSA(privKey2)
|
||||||
addr2 = crypto.PubkeyToAddress(key2.PublicKey) // 0x9fB29AAc15b9A4B7F17c3385939b007540f4d791
|
addr2 = crypto.PubkeyToAddress(key2.PublicKey) // 0x9fB29AAc15b9A4B7F17c3385939b007540f4d791
|
||||||
|
|
||||||
|
keys = []*ecdsa.PrivateKey{key, key2}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -73,6 +76,117 @@ type initializeData struct {
|
||||||
ethereum *eth.Ethereum
|
ethereum *eth.Ethereum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupMiner(t *testing.T, n int, genesis *core.Genesis) ([]*node.Node, []*eth.Ethereum, []*enode.Node) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
// Create an Ethash network based off of the Ropsten config
|
||||||
|
var (
|
||||||
|
stacks []*node.Node
|
||||||
|
nodes []*eth.Ethereum
|
||||||
|
enodes []*enode.Node
|
||||||
|
)
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
// Start the node and wait until it's up
|
||||||
|
stack, ethBackend, err := initMiner(genesis, keys[i])
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("Error occured while initialising miner", "error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for stack.Server().NodeInfo().Ports.Listener == 0 {
|
||||||
|
time.Sleep(250 * time.Millisecond)
|
||||||
|
}
|
||||||
|
// Connect the node to all the previous ones
|
||||||
|
for _, n := range enodes {
|
||||||
|
stack.Server().AddPeer(n)
|
||||||
|
}
|
||||||
|
// Start tracking the node and its enode
|
||||||
|
stacks = append(stacks, stack)
|
||||||
|
nodes = append(nodes, ethBackend)
|
||||||
|
enodes = append(enodes, stack.Server().Self())
|
||||||
|
}
|
||||||
|
|
||||||
|
return stacks, nodes, enodes
|
||||||
|
}
|
||||||
|
|
||||||
|
func initMiner(genesis *core.Genesis, privKey *ecdsa.PrivateKey) (*node.Node, *eth.Ethereum, error) {
|
||||||
|
// Define the basic configurations for the Ethereum node
|
||||||
|
datadir, _ := ioutil.TempDir("", "")
|
||||||
|
|
||||||
|
config := &node.Config{
|
||||||
|
Name: "geth",
|
||||||
|
Version: params.Version,
|
||||||
|
DataDir: datadir,
|
||||||
|
P2P: p2p.Config{
|
||||||
|
ListenAddr: "0.0.0.0:0",
|
||||||
|
NoDiscovery: true,
|
||||||
|
MaxPeers: 25,
|
||||||
|
},
|
||||||
|
UseLightweightKDF: true,
|
||||||
|
}
|
||||||
|
// Create the node and configure a full Ethereum node on it
|
||||||
|
stack, err := node.New(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
ethBackend, err := eth.New(stack, ðconfig.Config{
|
||||||
|
Genesis: genesis,
|
||||||
|
NetworkId: genesis.Config.ChainID.Uint64(),
|
||||||
|
SyncMode: downloader.FullSync,
|
||||||
|
DatabaseCache: 256,
|
||||||
|
DatabaseHandles: 256,
|
||||||
|
TxPool: core.DefaultTxPoolConfig,
|
||||||
|
GPO: ethconfig.Defaults.GPO,
|
||||||
|
Ethash: ethconfig.Defaults.Ethash,
|
||||||
|
Miner: miner.Config{
|
||||||
|
Etherbase: crypto.PubkeyToAddress(privKey.PublicKey),
|
||||||
|
GasCeil: genesis.GasLimit * 11 / 10,
|
||||||
|
GasPrice: big.NewInt(1),
|
||||||
|
Recommit: time.Second,
|
||||||
|
},
|
||||||
|
WithoutHeimdall: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// register backend to account manager with keystore for signing
|
||||||
|
keydir := stack.KeyStoreDir()
|
||||||
|
|
||||||
|
n, p := keystore.StandardScryptN, keystore.StandardScryptP
|
||||||
|
kStore := keystore.NewKeyStore(keydir, n, p)
|
||||||
|
|
||||||
|
kStore.ImportECDSA(privKey, "")
|
||||||
|
acc := kStore.Accounts()[0]
|
||||||
|
kStore.Unlock(acc, "")
|
||||||
|
// proceed to authorize the local account manager in any case
|
||||||
|
ethBackend.AccountManager().AddBackend(kStore)
|
||||||
|
|
||||||
|
err = stack.Start()
|
||||||
|
return stack, ethBackend, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func initGenesis(t *testing.T) *core.Genesis {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
// sprint size = 8 in genesis
|
||||||
|
genesisData, err := ioutil.ReadFile("./testdata/genesis_2val.json")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
genesis := &core.Genesis{}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(genesisData, genesis); err != nil {
|
||||||
|
t.Fatalf("%s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
genesis.Config.ChainID = big.NewInt(15001)
|
||||||
|
genesis.Config.EIP150Hash = common.Hash{}
|
||||||
|
|
||||||
|
return genesis
|
||||||
|
}
|
||||||
|
|
||||||
func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData {
|
func buildEthereumInstance(t *testing.T, db ethdb.Database) *initializeData {
|
||||||
genesisData, err := ioutil.ReadFile("./testdata/genesis.json")
|
genesisData, err := ioutil.ReadFile("./testdata/genesis.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue