diff --git a/cmd/simulator/go.mod b/cmd/simulator/go.mod index bc86766091..a8290227c0 100644 --- a/cmd/simulator/go.mod +++ b/cmd/simulator/go.mod @@ -38,7 +38,7 @@ require ( github.com/tklauser/numcpus v0.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect - golang.org/x/sys v0.0.0-20220727055044-e65921a090b8 // indirect + golang.org/x/sys v0.0.0-20220908164124-27713097b956 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/cmd/simulator/go.sum b/cmd/simulator/go.sum index b41d261434..365f2f028f 100644 --- a/cmd/simulator/go.sum +++ b/cmd/simulator/go.sum @@ -101,8 +101,8 @@ golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220727055044-e65921a090b8 h1:dyU22nBWzrmTQxtNrr4dzVOvaw35nUYE279vF9UmsI8= -golang.org/x/sys v0.0.0-20220727055044-e65921a090b8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/core/blockchain.go b/core/blockchain.go index 7a46f42819..42b454e2fc 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -347,10 +347,8 @@ func NewBlockChain( // If periodic cache journal is required, spin it up. if bc.cacheConfig.TrieCleanRejournal > 0 && len(bc.cacheConfig.TrieCleanJournal) > 0 { - if bc.cacheConfig.TrieCleanRejournal < time.Minute { - log.Warn("Sanitizing invalid trie cache journal time", "provided", bc.cacheConfig.TrieCleanRejournal, "updated", time.Minute) - bc.cacheConfig.TrieCleanRejournal = time.Minute - } + log.Info("Starting to save trie clean cache periodically", "journalDir", bc.cacheConfig.TrieCleanJournal, "freq", bc.cacheConfig.TrieCleanRejournal) + triedb := bc.stateCache.TrieDB() bc.rejournalWg.Add(1) go func() { diff --git a/core/blockchain_test.go b/core/blockchain_test.go index e7f23c8496..9feadcecea 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -6,7 +6,9 @@ package core import ( "fmt" "math/big" + "os" "testing" + "time" "github.com/ava-labs/subnet-evm/consensus/dummy" "github.com/ava-labs/subnet-evm/core/rawdb" @@ -18,6 +20,9 @@ import ( "github.com/ava-labs/subnet-evm/params" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/fsnotify/fsnotify" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var ( @@ -70,6 +75,104 @@ func TestArchiveBlockChain(t *testing.T) { } } +// awaitWatcherEventsSubside waits for at least one event on [watcher] and then waits +// for at least [subsideTimeout] before returning +func awaitWatcherEventsSubside(watcher *fsnotify.Watcher, subsideTimeout time.Duration) { + done := make(chan struct{}) + + go func() { + defer func() { + close(done) + }() + + select { + case <-watcher.Events: + case <-watcher.Errors: + return + } + + for { + select { + case <-watcher.Events: + case <-watcher.Errors: + return + case <-time.After(subsideTimeout): + return + } + } + }() + <-done +} + +func TestTrieCleanJournal(t *testing.T) { + require := require.New(t) + assert := assert.New(t) + + trieCleanJournal := t.TempDir() + trieCleanJournalWatcher, err := fsnotify.NewWatcher() + require.NoError(err) + defer func() { + assert.NoError(trieCleanJournalWatcher.Close()) + }() + require.NoError(trieCleanJournalWatcher.Add(trieCleanJournal)) + + create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { + config := *archiveConfig + config.TrieCleanJournal = trieCleanJournal + config.TrieCleanRejournal = 100 * time.Millisecond + return createBlockChain(db, &config, chainConfig, lastAcceptedHash) + } + + var ( + key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") + key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a") + addr1 = crypto.PubkeyToAddress(key1.PublicKey) + addr2 = crypto.PubkeyToAddress(key2.PublicKey) + // We use two separate databases since GenerateChain commits the state roots to its underlying + // database. + genDB = rawdb.NewMemoryDatabase() + chainDB = rawdb.NewMemoryDatabase() + ) + + // Ensure that key1 has some funds in the genesis block. + genesisBalance := big.NewInt(1000000) + gspec := &Genesis{ + Config: ¶ms.ChainConfig{HomesteadBlock: new(big.Int)}, + Alloc: GenesisAlloc{addr1: {Balance: genesisBalance}}, + } + genesis := gspec.MustCommit(genDB) + _ = gspec.MustCommit(chainDB) + + blockchain, err := create(chainDB, gspec.Config, common.Hash{}) + require.NoError(err) + defer blockchain.Stop() + + // This call generates a chain of 3 blocks. + signer := types.HomesteadSigner{} + // Generate chain of blocks using [genDB] instead of [chainDB] to avoid writing + // to the BlockChain's database while generating blocks. + chain, _, err := GenerateChain(gspec.Config, genesis, blockchain.engine, genDB, 3, 10, func(i int, gen *BlockGen) { + tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1) + gen.AddTx(tx) + }) + require.NoError(err) + + // Insert and accept the generated chain + _, err = blockchain.InsertChain(chain) + require.NoError(err) + + for _, block := range chain { + require.NoError(blockchain.Accept(block)) + } + blockchain.DrainAcceptorQueue() + + awaitWatcherEventsSubside(trieCleanJournalWatcher, time.Second) + // Assert that a new file is created in the trie clean journal + dirEntries, err := os.ReadDir(trieCleanJournal) + require.NoError(err) + require.NotEmpty(dirEntries) +} + func TestArchiveBlockChainSnapsDisabled(t *testing.T) { create := func(db ethdb.Database, chainConfig *params.ChainConfig, lastAcceptedHash common.Hash) (*BlockChain, error) { return createBlockChain( diff --git a/go.mod b/go.mod index 71f41cd084..7514bc6f9a 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/ethereum/go-ethereum v1.10.25 github.com/fatih/color v1.13.0 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 + github.com/fsnotify/fsnotify v1.6.0 github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 github.com/google/uuid v1.2.0 github.com/gorilla/rpc v1.2.0 @@ -40,7 +41,7 @@ require ( github.com/urfave/cli/v2 v2.10.2 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f + golang.org/x/sys v0.0.0-20220908164124-27713097b956 golang.org/x/text v0.3.7 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac gopkg.in/urfave/cli.v1 v1.20.0 @@ -71,7 +72,6 @@ require ( github.com/decred/dcrd/lru v1.1.1 // indirect github.com/deepmap/oapi-codegen v1.8.2 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/golang-jwt/jwt v3.2.1+incompatible // indirect diff --git a/go.sum b/go.sum index 5946a23418..64c278f3d5 100644 --- a/go.sum +++ b/go.sum @@ -166,8 +166,9 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/ github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= @@ -799,8 +800,8 @@ golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956 h1:XeJjHH1KiLpKGb6lvMiksZ9l0fVUh+AmGcm0nOMEBOY= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go index cd10323a32..67a373ff8e 100644 --- a/plugin/evm/vm.go +++ b/plugin/evm/vm.go @@ -305,6 +305,8 @@ func (vm *VM) Initialize( vm.ethConfig.Preimages = vm.config.Preimages vm.ethConfig.Pruning = vm.config.Pruning vm.ethConfig.TrieCleanCache = vm.config.TrieCleanCache + vm.ethConfig.TrieCleanJournal = vm.config.TrieCleanJournal + vm.ethConfig.TrieCleanRejournal = vm.config.TrieCleanRejournal.Duration vm.ethConfig.TrieDirtyCache = vm.config.TrieDirtyCache vm.ethConfig.TrieDirtyCommitTarget = vm.config.TrieDirtyCommitTarget vm.ethConfig.SnapshotCache = vm.config.SnapshotCache