From 4dc9ae77c820e41a0f6faeabf42e172fcdee1b12 Mon Sep 17 00:00:00 2001 From: Grizzly Bera Date: Mon, 20 Jan 2025 15:52:38 -0500 Subject: [PATCH] Wrap pebble DB to use SetSync always with deposit store. (#2381) Co-authored-by: Alberto Benegiamo Co-authored-by: Fridrik Asmundsson Co-authored-by: Cal Bera --- node-core/components/deposit_store.go | 5 +- storage/deposit/synced_db.go | 94 +++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 storage/deposit/synced_db.go diff --git a/node-core/components/deposit_store.go b/node-core/components/deposit_store.go index 282693d5dd..0144edeaad 100644 --- a/node-core/components/deposit_store.go +++ b/node-core/components/deposit_store.go @@ -59,12 +59,13 @@ func ProvideDepositStore[ if err != nil { return nil, err } + spdb := depositstore.NewSynced(pdb) // pass a closure to close the db as its not supported by the KVStoreService interface - closeFunc := func() error { return pdb.Close() } + closeFunc := func() error { return spdb.Close() } return depositstore.NewStore( - storage.NewKVStoreProvider(pdb), + storage.NewKVStoreProvider(spdb), closeFunc, in.Logger.With("service", "deposit-store"), ), nil diff --git a/storage/deposit/synced_db.go b/storage/deposit/synced_db.go new file mode 100644 index 0000000000..3e19869e36 --- /dev/null +++ b/storage/deposit/synced_db.go @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: BUSL-1.1 +// +// Copyright (C) 2025, Berachain Foundation. All rights reserved. +// Use of this software is governed by the Business Source License included +// in the LICENSE file of this repository and at www.mariadb.com/bsl11. +// +// ANY USE OF THE LICENSED WORK IN VIOLATION OF THIS LICENSE WILL AUTOMATICALLY +// TERMINATE YOUR RIGHTS UNDER THIS LICENSE FOR THE CURRENT AND ALL OTHER +// VERSIONS OF THE LICENSED WORK. +// +// THIS LICENSE DOES NOT GRANT YOU ANY RIGHT IN ANY TRADEMARK OR LOGO OF +// LICENSOR OR ITS AFFILIATES (PROVIDED THAT YOU MAY USE A TRADEMARK OR LOGO OF +// LICENSOR AS EXPRESSLY REQUIRED BY THIS LICENSE). +// +// TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON +// AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, +// EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND +// TITLE. + +package deposit + +import ( + "cosmossdk.io/core/store" + dbm "github.com/cosmos/cosmos-db" +) + +var _ store.KVStoreWithBatch = &syncedDB{} + +// We have verified experimentally that deposits are often *not* flushed +// as soon as they are enqueue when pebbleDB is chosed as backend. This may +// cause an issue with ungraceful restarts, which may lead to loss of deposits, +// resulting in the node being unable to verify any incoming deposit. +// SyncedDB solves the issues since it maps the Set call to a SetSync call +// which ensure that every single deposit is flushed when enqueued. +type syncedDB struct { + db dbm.DB +} + +func NewSynced(db dbm.DB) dbm.DB { + return syncedDB{db: db} +} + +func (s syncedDB) Get(key []byte) ([]byte, error) { + return s.db.Get(key) +} + +func (s syncedDB) Has(key []byte) (bool, error) { + return s.db.Has(key) +} + +func (s syncedDB) Set(key, value []byte) error { + return s.db.SetSync(key, value) +} + +func (s syncedDB) SetSync(key, value []byte) error { + return s.db.SetSync(key, value) +} + +func (s syncedDB) Delete(key []byte) error { + return s.db.Delete(key) +} + +func (s syncedDB) DeleteSync(key []byte) error { + return s.db.DeleteSync(key) +} + +func (s syncedDB) Iterator(start, end []byte) (store.Iterator, error) { + return s.db.Iterator(start, end) +} + +func (s syncedDB) ReverseIterator(start, end []byte) (store.Iterator, error) { + return s.db.ReverseIterator(start, end) +} + +func (s syncedDB) NewBatch() store.Batch { + return s.db.NewBatch() +} + +func (s syncedDB) NewBatchWithSize(i int) store.Batch { + return s.db.NewBatchWithSize(i) +} + +func (s syncedDB) Close() error { + return s.db.Close() +} + +func (s syncedDB) Print() error { + return s.db.Print() +} + +func (s syncedDB) Stats() map[string]string { + return s.db.Stats() +}