From 0c6bb7cb52f694a75d7f92c766d1480ea2309013 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Tue, 8 Jul 2025 16:54:27 -0400 Subject: [PATCH] upsert functionality for dao coin limit orders in badger --- lib/block_view_flush.go | 31 ++++++++++---------------- lib/block_view_types.go | 4 ++++ lib/db_utils.go | 48 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 20 deletions(-) diff --git a/lib/block_view_flush.go b/lib/block_view_flush.go index 6dc4701ce..24c6de316 100644 --- a/lib/block_view_flush.go +++ b/lib/block_view_flush.go @@ -1307,6 +1307,8 @@ func (bav *UtxoView) _flushDAOCoinLimitOrderEntriesToDbWithTxn(txn *badger.Txn, glog.V(2).Infof("_flushDAOCoinLimitOrderEntriesToDbWithTxn: flushing %d mappings", len(bav.DAOCoinLimitOrderMapKeyToDAOCoinLimitOrderEntry)) // Go through all the entries in the DAOCoinLimitOrderMapKeyToDAOCoinLimitOrderEntry map. + numDeleted := 0 + numPut := 0 for orderIter, orderEntry := range bav.DAOCoinLimitOrderMapKeyToDAOCoinLimitOrderEntry { // Make a copy of the iterator since we take references to it below. orderKey := orderIter @@ -1314,7 +1316,7 @@ func (bav *UtxoView) _flushDAOCoinLimitOrderEntriesToDbWithTxn(txn *badger.Txn, // Validate order map key matches order entry. orderMapKey := orderEntry.ToMapKey() - if !reflect.DeepEqual(orderKey, orderMapKey) { + if !orderKey.Eq(orderMapKey) { return fmt.Errorf("_flushDAOCoinLimitOrderEntriesToDbWithTxn: DAOCoinLimitOrderEntry has "+ "map key: %v which does not match match "+ "the DAOCoinLimitOrderMapKey map key %v", @@ -1323,31 +1325,20 @@ func (bav *UtxoView) _flushDAOCoinLimitOrderEntriesToDbWithTxn(txn *badger.Txn, // Delete the existing mappings in the db for this balance key. They will be re-added // if the corresponding entry in memory has isDeleted=false. - if err := DBDeleteDAOCoinLimitOrderWithTxn(txn, bav.Snapshot, orderEntry, bav.EventManager, orderEntry.isDeleted); err != nil { - return errors.Wrapf( - err, "_flushDAOCoinLimitOrderEntriesToDbWithTxn: problem deleting mappings") - } - } - - // Update logs with number of entries deleted and/ put. - numDeleted := 0 - numPut := 0 - - // Go through all the entries in the DAOCoinLimitOrderMapKeyToDAOCoinLimitOrderEntry map. - for _, orderEntry := range bav.DAOCoinLimitOrderMapKeyToDAOCoinLimitOrderEntry { - // Make a copy of the iterator since we take references to it below. if orderEntry.isDeleted { numDeleted++ - // If the OrderEntry has isDeleted=true then there's nothing to do because - // we already deleted the entry above. + if err := DBDeleteDAOCoinLimitOrderWithTxn(txn, bav.Snapshot, orderEntry, bav.EventManager, orderEntry.isDeleted); err != nil { + return errors.Wrapf( + err, "_flushDAOCoinLimitOrderEntriesToDbWithTxn: problem deleting mappings") + } } else { numPut++ - // If the OrderEntry has (isDeleted = false) then we put the corresponding - // mappings for it into the db. - if err := DBPutDAOCoinLimitOrderWithTxn(txn, bav.Snapshot, orderEntry, blockHeight, bav.EventManager); err != nil { - return err + if err := DBUpsertDAOCoinLimitOrderWithTxn(txn, bav.Snapshot, orderEntry, blockHeight, bav.EventManager); err != nil { + return errors.Wrapf( + err, "_flushDAOCoinLimitOrderEntriesToDbWithTxn: problem putting mappings for order %v", orderEntry) } } + } glog.V(2).Infof("_flushDAOCoinLimitOrderEntriesToDbWithTxn: deleted %d mappings, put %d mappings", numDeleted, numPut) diff --git a/lib/block_view_types.go b/lib/block_view_types.go index 6cdd43df8..f8fe018ed 100644 --- a/lib/block_view_types.go +++ b/lib/block_view_types.go @@ -6118,6 +6118,10 @@ func (order *DAOCoinLimitOrderEntry) ToMapKey() DAOCoinLimitOrderMapKey { } } +func (orderMapKey DAOCoinLimitOrderMapKey) Eq(otherOrderMapKey DAOCoinLimitOrderMapKey) bool { + return orderMapKey.OrderID.IsEqual(&otherOrderMapKey.OrderID) +} + func (order *FilledDAOCoinLimitOrder) RawEncodeWithoutMetadata(blockHeight uint64, skipMetadata ...bool) []byte { var data []byte diff --git a/lib/db_utils.go b/lib/db_utils.go index acfa83e82..5ca9ef24d 100644 --- a/lib/db_utils.go +++ b/lib/db_utils.go @@ -10320,6 +10320,54 @@ func DBPutDAOCoinLimitOrderWithTxn(txn *badger.Txn, snap *Snapshot, order *DAOCo return nil } +func DBUpsertDAOCoinLimitOrderWithTxn( + txn *badger.Txn, + snap *Snapshot, + order *DAOCoinLimitOrderEntry, + blockHeight uint64, + eventManager *EventManager, +) error { + if order == nil { + return nil + } + + orderBytes := EncodeToBytes(blockHeight, order) + // Store in index: PrefixDAOCoinLimitOrderByTransactorPKID + key := DBKeyForDAOCoinLimitOrder(order) + + currBytes, err := DBGetWithTxn(txn, snap, key) + if err != nil { + if !errors.Is(err, badger.ErrKeyNotFound) { + return errors.Wrapf(err, "DBUpsertDAOCoinLimitOrderWithTxn: problem getting limit order") + } + } else { + // If the order already exists, we need to compare the bytes. + // If the bytes are the same, we don't need to update. + if bytes.Equal(currBytes, orderBytes) { + // No need to update if the bytes are the same. + return nil + } + } + + if err = DBSetWithTxn(txn, snap, key, orderBytes, eventManager); err != nil { + return errors.Wrapf(err, "DBUpsertDAOCoinLimitOrderWithTxn: problem storing limit order") + } + + // Store in index: PrefixDAOCoinLimitOrderByTransactorPKID + key = DBKeyForDAOCoinLimitOrderByTransactorPKID(order) + if err = DBSetWithTxn(txn, snap, key, orderBytes, eventManager); err != nil { + return errors.Wrapf(err, "DBUpsertDAOCoinLimitOrderWithTxn: problem storing limit order") + } + + // Store in index: PrefixDAOCoinLimitOrderByOrderID + key = DBKeyForDAOCoinLimitOrderByOrderID(order) + if err = DBSetWithTxn(txn, snap, key, orderBytes, eventManager); err != nil { + return errors.Wrapf(err, "DBUpsertDAOCoinLimitOrderWithTxn: problem storing order in index PrefixDAOCoinLimitOrderByOrderID") + } + + return nil +} + func DBDeleteDAOCoinLimitOrderWithTxn(txn *badger.Txn, snap *Snapshot, order *DAOCoinLimitOrderEntry, eventManager *EventManager, entryIsDeleted bool) error { if order == nil { return nil