From c162dc09db14a02622c916bde64bb1f2a0f02f80 Mon Sep 17 00:00:00 2001 From: Morgan Date: Wed, 10 Jul 2024 10:25:20 -0500 Subject: [PATCH] fix(sdk/vm): re-load iavl store from backup if empty (#2568) This is a hack; during initialization, the iavlStore is backed up to the baseStore, and it is then recovered in Initialize if the iavlStore is found to be empty (but there's supposed to be packages inside). This is a hotfix for test4 non-validator nodes. It still requires to start up the non-validator node once, with the new changes applied, with a fresh db --- gno.land/pkg/sdk/vm/keeper.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/gno.land/pkg/sdk/vm/keeper.go b/gno.land/pkg/sdk/vm/keeper.go index 9899afa2eac..3caad44892b 100644 --- a/gno.land/pkg/sdk/vm/keeper.go +++ b/gno.land/pkg/sdk/vm/keeper.go @@ -118,6 +118,13 @@ func uncachedPackageLoad( loadStdlib(stdlibsDir, gnoStore) + // XXX Quick and dirty to make this function work on non-validator nodes + iter := iavlStore.Iterator(nil, nil) + for ; iter.Valid(); iter.Next() { + baseStore.Set(append(iavlBackupPrefix, iter.Key()...), iter.Value()) + } + iter.Close() + logger.Debug("Standard libraries initialized", "elapsed", time.Since(start)) } else { @@ -126,6 +133,18 @@ func uncachedPackageLoad( // and memory management across many objects/types/nodes/packages. start := time.Now() + // XXX Quick and dirty to make this function work on non-validator nodes + if isStoreEmpty(iavlStore) { + iter := baseStore.Iterator(iavlBackupPrefix, nil) + for ; iter.Valid(); iter.Next() { + if !bytes.HasPrefix(iter.Key(), iavlBackupPrefix) { + break + } + iavlStore.Set(iter.Key()[len(iavlBackupPrefix):], iter.Value()) + } + iter.Close() + } + m2 := gno.NewMachineWithOptions( gno.MachineOptions{ PkgPath: "", @@ -143,6 +162,17 @@ func uncachedPackageLoad( return gnoStore } +var iavlBackupPrefix = []byte("init_iavl_backup:") + +func isStoreEmpty(st store.Store) bool { + iter := st.Iterator(nil, nil) + defer iter.Close() + for ; iter.Valid(); iter.Next() { + return false + } + return true +} + func cachedStdlibLoad(stdlibsDir string, baseStore, iavlStore store.Store) gno.Store { cachedStdlibOnce.Do(func() { cachedStdlibBase = memdb.NewMemDB()