diff --git a/cmd/opera/launcher/defaults.go b/cmd/opera/launcher/defaults.go index 82dc14ffe..2e1c027ac 100644 --- a/cmd/opera/launcher/defaults.go +++ b/cmd/opera/launcher/defaults.go @@ -34,10 +34,10 @@ func overrideFlags() { // NodeDefaultConfig contains reasonable default settings. var NodeDefaultConfig = node.Config{ - DataDir: DefaultDataDir(), - HTTPPort: DefaultHTTPPort, - HTTPModules: []string{}, - HTTPVirtualHosts: []string{"localhost"}, + DataDir: DefaultDataDir(), + HTTPPort: DefaultHTTPPort, + HTTPModules: []string{}, + HTTPVirtualHosts: []string{"localhost"}, HTTPTimeouts: rpc.HTTPTimeouts{ ReadTimeout: 120 * time.Second, IdleTimeout: 120 * time.Second, diff --git a/evmcore/dummy_block.go b/evmcore/dummy_block.go index d5e1b0373..ea7953d70 100644 --- a/evmcore/dummy_block.go +++ b/evmcore/dummy_block.go @@ -50,6 +50,22 @@ type ( } ) +// NewEvmBlock constructor. +func NewEvmBlock(h *EvmHeader, txs types.Transactions) *EvmBlock { + b := &EvmBlock{ + EvmHeader: *h, + Transactions: txs, + } + + if len(txs) == 0 { + b.EvmHeader.TxHash = types.EmptyRootHash + } else { + b.EvmHeader.TxHash = types.DeriveSha(txs, new(trie.Trie)) + } + + return b +} + // ToEvmHeader converts inter.Block to EvmHeader. func ToEvmHeader(block *inter.Block, index idx.Block, prevHash hash.Event) *EvmHeader { return &EvmHeader{ diff --git a/evmcore/tx_pool.go b/evmcore/tx_pool.go index fdd716f29..db1770abd 100644 --- a/evmcore/tx_pool.go +++ b/evmcore/tx_pool.go @@ -565,13 +565,6 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if !local && tx.GasPriceIntCmp(pool.gasPrice) < 0 { return ErrUnderpriced } - // Ensure Opera-specific hard bounds - if pool.chain.MinGasPrice().Cmp(tx.GasPrice()) > 0 { - return ErrUnderpriced - } - if pool.chain.TxExists(tx.Hash()) { - return ErrUnderpriced - } // Ensure the transaction adheres to nonce ordering if pool.currentState.GetNonce(from) > tx.Nonce() { return ErrNonceTooLow @@ -589,6 +582,13 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error { if tx.Gas() < intrGas { return ErrIntrinsicGas } + // Ensure Opera-specific hard bounds + if pool.chain.MinGasPrice().Cmp(tx.GasPrice()) > 0 { + return ErrUnderpriced + } + if pool.chain.TxExists(tx.Hash()) { + return ErrUnderpriced + } return nil } diff --git a/go.mod b/go.mod index 5e1f4c76a..8038cd0d2 100644 --- a/go.mod +++ b/go.mod @@ -25,7 +25,7 @@ require ( github.com/google/uuid v1.1.1 // indirect github.com/gorilla/websocket v1.4.1 // indirect github.com/hashicorp/golang-lru v0.5.4 - github.com/holiman/uint256 v1.1.1 // indirect + github.com/holiman/uint256 v1.1.1 github.com/influxdata/influxdb v1.7.9 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/karalabe/usb v0.0.0-20191104083709-911d15fe12a9 // indirect @@ -54,6 +54,6 @@ require ( gopkg.in/urfave/cli.v1 v1.20.0 ) -replace github.com/ethereum/go-ethereum => github.com/Fantom-foundation/go-ethereum v1.9.22-ftm-0.5 +replace github.com/ethereum/go-ethereum => github.com/uprendis/go-ethereum v1.9.7-0.20210501212005-da4db6546f89 replace github.com/dvyukov/go-fuzz => github.com/guzenok/go-fuzz v0.0.0-20210103140116-f9104dfb626f diff --git a/go.sum b/go.sum index 04b90a3a6..646dec83e 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,6 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= -github.com/Fantom-foundation/go-ethereum v1.9.22-ftm-0.5 h1:hyMHsRBFoBIjwur3LgyYa/Lm7WzJqnM7HtK7/vnSkeA= -github.com/Fantom-foundation/go-ethereum v1.9.22-ftm-0.5/go.mod h1:27ZY0H7YdbxCL0E/d23qHo9WCkjqnmFKHQl9UaUSw8s= github.com/Fantom-foundation/lachesis-base v0.0.0-20210420092627-c16f01e35562 h1:SFcBjyI5dos9JeIRBHnzU88SlVTlEjRbAUrlZ40uWfk= github.com/Fantom-foundation/lachesis-base v0.0.0-20210420092627-c16f01e35562/go.mod h1:E6+2LOvgADwSOv0U5YXhRJz4PlX8qJxvq8M93AOC1tM= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -321,6 +319,8 @@ github.com/uber/jaeger-client-go v2.20.1+incompatible h1:HgqpYBng0n7tLJIlyT4kPCI github.com/uber/jaeger-client-go v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/uprendis/go-ethereum v1.9.7-0.20210501212005-da4db6546f89 h1:XW6JOLMYwa2z8x3C8PO9uQkoRT8GLroBbLZLivJX9uM= +github.com/uprendis/go-ethereum v1.9.7-0.20210501212005-da4db6546f89/go.mod h1:27ZY0H7YdbxCL0E/d23qHo9WCkjqnmFKHQl9UaUSw8s= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= diff --git a/gossip/blockproc/evmmodule/evm.go b/gossip/blockproc/evmmodule/evm.go index b09631a90..29595a04d 100644 --- a/gossip/blockproc/evmmodule/evm.go +++ b/gossip/blockproc/evmmodule/evm.go @@ -57,20 +57,18 @@ type OperaEVMProcessor struct { } func (p *OperaEVMProcessor) evmBlockWith(txs types.Transactions) *evmcore.EvmBlock { - return &evmcore.EvmBlock{ - EvmHeader: evmcore.EvmHeader{ - Number: p.blockIdx, - Hash: common.Hash(p.block.Atropos), - ParentHash: p.prevBlockHash, - Root: common.Hash{}, - TxHash: common.Hash{}, - Time: p.block.Time, - Coinbase: common.Address{}, - GasLimit: math.MaxUint64, - GasUsed: p.gasUsed, - }, - Transactions: txs, + h := &evmcore.EvmHeader{ + Number: p.blockIdx, + Hash: common.Hash(p.block.Atropos), + ParentHash: p.prevBlockHash, + Root: common.Hash{}, + Time: p.block.Time, + Coinbase: common.Address{}, + GasLimit: math.MaxUint64, + GasUsed: p.gasUsed, } + + return evmcore.NewEvmBlock(h, txs) } func (p *OperaEVMProcessor) Execute(txs types.Transactions, internal bool, cfg vm.Config) types.Receipts { diff --git a/gossip/c_block_callbacks.go b/gossip/c_block_callbacks.go index 0959d1da1..310a0b557 100644 --- a/gossip/c_block_callbacks.go +++ b/gossip/c_block_callbacks.go @@ -202,6 +202,22 @@ func consensusCallbackBeginBlockFn( block, blockEvents := spillBlockEvents(store, block, es.Rules) txs := make(types.Transactions, 0, blockEvents.Len()*10) for _, e := range blockEvents { + var renamedIdxs []uint32 + var renamedHashes []common.Hash + for i, tx := range e.Txs() { + if store.EvmStore().GetTxPosition(tx.Hash()) != nil { + h := tx.Hash() + for i := 0; i < 32; i++ { + h[i] = ^h[i] + } + tx.SetHash(h) + renamedIdxs = append(renamedIdxs, uint32(i)) + renamedHashes = append(renamedHashes, h) + } + } + if len(renamedIdxs) != 0 { + store.SetRenamedTxs(e.ID(), renamedIdxs, renamedHashes) + } txs = append(txs, e.Txs()...) } diff --git a/gossip/evm_state_reader.go b/gossip/evm_state_reader.go index ec346ab35..cd692a02a 100644 --- a/gossip/evm_state_reader.go +++ b/gossip/evm_state_reader.go @@ -9,7 +9,6 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/trie" "github.com/Fantom-foundation/go-opera/evmcore" "github.com/Fantom-foundation/go-opera/inter" @@ -116,22 +115,17 @@ func (r *EvmStateReader) getBlock(h hash.Event, n idx.Block, readTxs bool) *evmc } evmHeader := evmcore.ToEvmHeader(block, n, prev) + var evmBlock *evmcore.EvmBlock if readTxs { - if len(transactions) == 0 { - evmHeader.TxHash = types.EmptyRootHash - } else { - evmHeader.TxHash = types.DeriveSha(transactions, new(trie.Trie)) + evmBlock = evmcore.NewEvmBlock(evmHeader, transactions) + r.store.EvmStore().SetCachedEvmBlock(n, evmBlock) + } else { + // not completed block here + evmBlock = &evmcore.EvmBlock{ + EvmHeader: *evmHeader, } } - evmBlock := &evmcore.EvmBlock{ - EvmHeader: *evmHeader, - Transactions: transactions, - } - - if readTxs { - r.store.EvmStore().SetCachedEvmBlock(n, evmBlock) - } return evmBlock } diff --git a/gossip/evmstore/store_block_cache.go b/gossip/evmstore/store_block_cache.go index 943988e78..fd95551bb 100644 --- a/gossip/evmstore/store_block_cache.go +++ b/gossip/evmstore/store_block_cache.go @@ -2,6 +2,7 @@ package evmstore import ( "github.com/Fantom-foundation/lachesis-base/inter/idx" + "github.com/ethereum/go-ethereum/common" "github.com/Fantom-foundation/go-opera/evmcore" ) @@ -11,9 +12,14 @@ func (s *Store) GetCachedEvmBlock(n idx.Block) *evmcore.EvmBlock { if !ok { return nil } + return c.(*evmcore.EvmBlock) } func (s *Store) SetCachedEvmBlock(n idx.Block, b *evmcore.EvmBlock) { + var empty = common.Hash{} + if b.EvmHeader.TxHash == empty { + panic("You have to cache only completed blocks (with txs)") + } s.cache.EvmBlocks.Add(n, b, uint(b.EstimateSize())) } diff --git a/gossip/service.go b/gossip/service.go index c69b75921..24ecae8e1 100644 --- a/gossip/service.go +++ b/gossip/service.go @@ -228,6 +228,8 @@ func newService(config Config, store *Store, signer valkeystore.SignerI, blockPr svc.emitter = svc.makeEmitter(signer) + svc.store.GetEventPayload(hash.ZeroEvent) + svc.verWatcher = verwatcher.New(config.VersionWatcher, verwatcher.NewStore(store.table.NetworkVersion)) return svc, nil diff --git a/gossip/store.go b/gossip/store.go index 19b495954..b7f914b42 100644 --- a/gossip/store.go +++ b/gossip/store.go @@ -52,6 +52,7 @@ type Store struct { // API-only BlockHashes kvdb.Store `table:"B"` SfcAPI kvdb.Store `table:"S"` + RenamedTxs kvdb.Store `table:"9"` } prevFlushTime time.Time diff --git a/gossip/store_event.go b/gossip/store_event.go index 11168f84d..0fbc1ea85 100644 --- a/gossip/store_event.go +++ b/gossip/store_event.go @@ -7,8 +7,10 @@ package gossip import ( "bytes" + "github.com/Fantom-foundation/lachesis-base/common/bigendian" "github.com/Fantom-foundation/lachesis-base/hash" "github.com/Fantom-foundation/lachesis-base/inter/idx" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/rlp" @@ -51,6 +53,22 @@ func (s *Store) GetEventPayload(id hash.Event) *inter.EventPayload { key := id.Bytes() w, _ := s.rlp.Get(s.table.Events, key, &inter.EventPayload{}).(*inter.EventPayload) + if w != nil { + if !w.NoTxs() { + renamed, err := s.table.RenamedTxs.Get(id.Bytes()) + if err != nil { + s.Log.Crit("Failed to get key", "err", err) + } + if len(renamed) != 0 { + for i := 0; i < len(renamed); i += 36 { + index := bigendian.BytesToUint32(renamed[i : i+4]) + h := common.BytesToHash(renamed[i+4 : i+4+32]) + w.Txs()[index].SetHash(h) + } + } + } + } + // Put event to LRU cache. if w != nil { s.cache.Events.Add(id, w, uint(w.Size())) @@ -61,6 +79,18 @@ func (s *Store) GetEventPayload(id hash.Event) *inter.EventPayload { return w } +func (s *Store) SetRenamedTxs(id hash.Event, idxs []uint32, hashes []common.Hash) { + b := bytes.NewBuffer(make([]byte, 0, len(idxs)*36)) + for i := 0; i < len(idxs); i++ { + b.Write(bigendian.Uint32ToBytes(idxs[i])) + b.Write(hashes[i].Bytes()) + } + err := s.table.RenamedTxs.Put(id.Bytes(), b.Bytes()) + if err != nil { + s.Log.Crit("Failed to put key", "err", err) + } +} + // GetEvent returns stored event. func (s *Store) GetEvent(id hash.Event) *inter.Event { // Get event from LRU cache first. diff --git a/gossip/store_migration.go b/gossip/store_migration.go index 5f5498c06..503516e60 100644 --- a/gossip/store_migration.go +++ b/gossip/store_migration.go @@ -21,11 +21,8 @@ func (s *Store) migrateData() error { versions.SetID(s.migrations().ID()) return nil } - err := s.migrations().Exec(versions) - if err == nil { - err = s.Commit() - } + err := s.migrations().Exec(versions, s.Commit) return err } diff --git a/opera/genesis/evmwriter/evm_writer.go b/opera/genesis/evmwriter/evm_writer.go index 14a901eb6..ed5c1735c 100644 --- a/opera/genesis/evmwriter/evm_writer.go +++ b/opera/genesis/evmwriter/evm_writer.go @@ -166,7 +166,7 @@ func (_ PreCompiledContract) Run(stateDB vm.StateDB, ctx vm.Context, caller comm value := common.BytesToHash(input[:32]) stateDB.SetState(acc, key, value) - } else if bytes.Equal(input[:4], incNonceMethodID) { + } else if bytes.Equal(input[:4], incNonceMethodID) { input = input[4:] // incNonce if suppliedGas < params.CallValueTransferGas { @@ -194,7 +194,7 @@ func (_ PreCompiledContract) Run(stateDB vm.StateDB, ctx vm.Context, caller comm return nil, 0, vm.ErrExecutionReverted } - stateDB.SetNonce(acc, stateDB.GetNonce(acc) + value.Uint64()) + stateDB.SetNonce(acc, stateDB.GetNonce(acc)+value.Uint64()) } else { return nil, 0, vm.ErrExecutionReverted } diff --git a/topicsdb/search_lazy.go b/topicsdb/search_lazy.go index 49bb70b53..3a81e3af4 100644 --- a/topicsdb/search_lazy.go +++ b/topicsdb/search_lazy.go @@ -6,19 +6,19 @@ import ( "github.com/ethereum/go-ethereum/common" ) -type logHandler func(rec *logrec, complete bool) (gonext bool, err error) +type logHandler func(rec *logrec) (gonext bool, err error) -func (tt *Index) searchLazy(ctx context.Context, pattern [][]common.Hash, blockStart []byte, onMatched logHandler) (err error) { +func (tt *Index) searchLazy(ctx context.Context, pattern [][]common.Hash, blockStart []byte, blockEnd uint64, onMatched logHandler) (err error) { if ctx == nil { ctx = context.Background() } - _, err = tt.walkFirst(ctx, blockStart, pattern, 0, onMatched) + _, err = tt.walkFirst(ctx, blockStart, blockEnd, pattern, 0, onMatched) return } // walkFirst for topics recursive. func (tt *Index) walkFirst( - ctx context.Context, blockStart []byte, pattern [][]common.Hash, pos uint8, onMatched logHandler, + ctx context.Context, blockStart []byte, blockEnd uint64, pattern [][]common.Hash, pos uint8, onMatched logHandler, ) ( gonext bool, err error, ) { @@ -59,13 +59,11 @@ func (tt *Index) walkFirst( id := extractLogrecID(it.Key()) rec := newLogrec(id, topicCount) - gonext, err = onMatched(rec, false) - if err != nil || !gonext { - it.Release() - return + if blockEnd > 0 && rec.ID.BlockNumber() > blockEnd { + break } - gonext, err = tt.walkNexts(ctx, rec, nil, pattern, pos+1, onMatched) + gonext, err = tt.walkNexts(ctx, rec, pattern, pos+1, onMatched) if err != nil || !gonext { it.Release() return @@ -84,7 +82,7 @@ func (tt *Index) walkFirst( // walkNexts for topics recursive. func (tt *Index) walkNexts( - ctx context.Context, rec *logrec, blockStart []byte, pattern [][]common.Hash, pos uint8, onMatched logHandler, + ctx context.Context, rec *logrec, pattern [][]common.Hash, pos uint8, onMatched logHandler, ) ( gonext bool, err error, ) { @@ -93,7 +91,7 @@ func (tt *Index) walkNexts( for { // Max recursion depth is equal to len(topics) and limited by MaxCount. if pos >= patternLen { - gonext, err = onMatched(rec, true) + gonext, err = onMatched(rec) return } if len(pattern[pos]) < 1 { @@ -114,7 +112,7 @@ func (tt *Index) walkNexts( for _, variant := range pattern[pos] { copy(prefix[0:], variant.Bytes()) - it := tt.table.Topic.NewIterator(prefix[:prefLen], blockStart) + it := tt.table.Topic.NewIterator(prefix[:prefLen], nil) for it.Next() { err = ctx.Err() if err != nil { @@ -122,7 +120,7 @@ func (tt *Index) walkNexts( return } - gonext, err = tt.walkNexts(ctx, rec, nil, pattern, pos+1, onMatched) + gonext, err = tt.walkNexts(ctx, rec, pattern, pos+1, onMatched) if err != nil || !gonext { it.Release() return diff --git a/topicsdb/topicsdb.go b/topicsdb/topicsdb.go index 752497ae3..06b43dace 100644 --- a/topicsdb/topicsdb.go +++ b/topicsdb/topicsdb.go @@ -3,6 +3,7 @@ package topicsdb import ( "context" "fmt" + "math" "github.com/Fantom-foundation/lachesis-base/inter/idx" "github.com/Fantom-foundation/lachesis-base/kvdb" @@ -12,9 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) -const MaxTopicsCount = 1024 - -//const MaxTopicsCount = math.MaxUint8 +const MaxTopicsCount = math.MaxUint8 var ( ErrEmptyTopics = fmt.Errorf("Empty topics") @@ -64,12 +63,7 @@ func (tt *Index) ForEach(ctx context.Context, pattern [][]common.Hash, onLog fun return err } - onMatched := func(rec *logrec, complete bool) (gonext bool, err error) { - if !complete { - gonext = true - return - } - + onMatched := func(rec *logrec) (gonext bool, err error) { rec.fetch(tt.table.Logrec) if rec.err != nil { err = rec.err @@ -79,7 +73,7 @@ func (tt *Index) ForEach(ctx context.Context, pattern [][]common.Hash, onLog fun return } - return tt.searchLazy(ctx, pattern, nil, onMatched) + return tt.searchLazy(ctx, pattern, nil, 0, onMatched) } // ForEachInBlocks matches log records of block range by pattern. 1st pattern element is an address. @@ -93,16 +87,7 @@ func (tt *Index) ForEachInBlocks(ctx context.Context, from, to idx.Block, patter return err } - onMatched := func(rec *logrec, complete bool) (gonext bool, err error) { - if rec.ID.BlockNumber() > uint64(to) { - return - } - - if !complete { - gonext = true - return - } - + onMatched := func(rec *logrec) (gonext bool, err error) { rec.fetch(tt.table.Logrec) if rec.err != nil { err = rec.err @@ -112,7 +97,7 @@ func (tt *Index) ForEachInBlocks(ctx context.Context, from, to idx.Block, patter return } - return tt.searchLazy(ctx, pattern, uintToBytes(uint64(from)), onMatched) + return tt.searchLazy(ctx, pattern, uintToBytes(uint64(from)), uint64(to), onMatched) } func limitPattern(pattern [][]common.Hash) (limited [][]common.Hash, err error) { @@ -124,11 +109,8 @@ func limitPattern(pattern [][]common.Hash) (limited [][]common.Hash, err error) copy(limited, pattern) ok := false - for i, variants := range limited { + for _, variants := range limited { ok = ok || len(variants) > 0 - if len(variants) > MaxTopicsCount { - limited[i] = variants[:MaxTopicsCount] - } } if !ok { err = ErrEmptyTopics diff --git a/topicsdb/topicsdb_test.go b/topicsdb/topicsdb_test.go index fe252e684..9a43ba94f 100644 --- a/topicsdb/topicsdb_test.go +++ b/topicsdb/topicsdb_test.go @@ -49,16 +49,7 @@ func (tt *Index) FindInBlocksAsync(ctx context.Context, from, to idx.Block, patt } }() - onMatched := func(rec *logrec, complete bool) (gonext bool, err error) { - if rec.ID.BlockNumber() > uint64(to) { - return - } - - if !complete { - gonext = true - return - } - + onMatched := func(rec *logrec) (gonext bool, err error) { wg.Add(1) go func() { rec.fetch(tt.table.Logrec) @@ -69,7 +60,7 @@ func (tt *Index) FindInBlocksAsync(ctx context.Context, from, to idx.Block, patt return } - err = tt.searchLazy(ctx, pattern, uintToBytes(uint64(from)), onMatched) + err = tt.searchLazy(ctx, pattern, uintToBytes(uint64(from)), uint64(to), onMatched) wg.Wait() return @@ -173,6 +164,29 @@ func TestIndexSearchMultyVariants(t *testing.T) { check(require, got) }) + t.Run("With addresses and blocks", func(t *testing.T) { + require := require.New(t) + + got1, err := method(nil, 2, 998, [][]common.Hash{ + {addr1.Hash(), addr2.Hash(), addr3.Hash(), addr4.Hash()}, + {hash1, hash2, hash3, hash4}, + {}, + {hash1, hash2, hash3, hash4}, + }) + require.NoError(err) + require.Equal(2, len(got1)) + check(require, got1) + + got2, err := method(nil, 2, 998, [][]common.Hash{ + {addr4.Hash(), addr3.Hash(), addr2.Hash(), addr1.Hash()}, + {hash1, hash2, hash3, hash4}, + {}, + {hash1, hash2, hash3, hash4}, + }) + require.NoError(err) + require.ElementsMatch(got1, got2) + }) + }) } } diff --git a/utils/migration/migration.go b/utils/migration/migration.go index a0ab1d5f0..69ac443cf 100644 --- a/utils/migration/migration.go +++ b/utils/migration/migration.go @@ -49,7 +49,7 @@ func (m *Migration) ID() string { } // Exec method run migrations chain in order -func (m *Migration) Exec(curr IDStore) error { +func (m *Migration) Exec(curr IDStore, flush func() error) error { currID := curr.GetID() myID := m.ID() @@ -64,7 +64,7 @@ func (m *Migration) Exec(curr IDStore) error { return nil } - err := m.prev.Exec(curr) + err := m.prev.Exec(curr, flush) if err != nil { return err } @@ -77,7 +77,8 @@ func (m *Migration) Exec(curr IDStore) error { log.Warn("'" + m.name + "' migration has been applied") curr.SetID(myID) - return nil + + return flush() } func (m *Migration) veryFirst() bool { diff --git a/utils/migration/migration_test.go b/utils/migration/migration_test.go index 5ee601842..b4fa1b8f9 100644 --- a/utils/migration/migration_test.go +++ b/utils/migration/migration_test.go @@ -45,7 +45,7 @@ func TestMigrations(t *testing.T) { }, ) - err := afterBad.Exec(curVer) + err := afterBad.Exec(curVer, flush) require.Error(err, "Success after a migration error") lastID := curVer.GetID() @@ -73,7 +73,7 @@ func TestMigrations(t *testing.T) { }, ) - err = fixed.Exec(curVer) + err = fixed.Exec(curVer, flush) require.NoError(err, "Error when run migration manager") require.Equal(1, testData["migration1"], "Bad value after run migration1") @@ -93,8 +93,12 @@ func TestMigrations(t *testing.T) { }, ) - err := nonnative.Exec(curVer) + err := nonnative.Exec(curVer, flush) require.NotEqual(999, testData["migration1"], "nonnative migration is applied") require.Error(err) }) } + +func flush() error { + return nil +} diff --git a/version/version.go b/version/version.go index 71b09c1d8..88cdf4490 100644 --- a/version/version.go +++ b/version/version.go @@ -11,7 +11,7 @@ func init() { params.VersionMajor = 1 // Major version component of the current release params.VersionMinor = 0 // Minor version component of the current release params.VersionPatch = 1 // Patch version component of the current release - params.VersionMeta = "rc.2" // Version metadata to append to the version string + params.VersionMeta = "rc.3" // Version metadata to append to the version string } func BigToString(b *big.Int) string {