From 69cee1e6db3363362a6ab1578b5faf9c53f0d247 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Tue, 24 Jun 2025 15:52:24 -0400 Subject: [PATCH 1/5] enforce limit on get nfts for user --- lib/block_view_nft.go | 7 ++++--- lib/db_utils.go | 23 ++++++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/block_view_nft.go b/lib/block_view_nft.go index 0892c2a26..8aaef728a 100644 --- a/lib/block_view_nft.go +++ b/lib/block_view_nft.go @@ -94,15 +94,16 @@ func (bav *UtxoView) GetNFTEntriesForPostHash(nftPostHash *BlockHash) []*NFTEntr return nftEntries } -func (bav *UtxoView) GetNFTEntriesForPKID(ownerPKID *PKID) []*NFTEntry { +func (bav *UtxoView) GetNFTEntriesForPKID(ownerPKID *PKID, limit int, lastKeyBytes []byte) ([]*NFTEntry, []byte) { var dbNFTEntries []*NFTEntry + var lastSeenKey []byte if bav.Postgres != nil { nfts := bav.Postgres.GetNFTsForPKID(ownerPKID) for _, nft := range nfts { dbNFTEntries = append(dbNFTEntries, nft.NewNFTEntry()) } } else { - dbNFTEntries = DBGetNFTEntriesForPKID(bav.Handle, ownerPKID) + dbNFTEntries, lastSeenKey = DBGetNFTEntriesForPKID(bav.Handle, ownerPKID, limit, lastKeyBytes) } // Make sure all of the DB entries are loaded in the view. @@ -122,7 +123,7 @@ func (bav *UtxoView) GetNFTEntriesForPKID(ownerPKID *PKID) []*NFTEntry { nftEntries = append(nftEntries, nftEntry) } } - return nftEntries + return nftEntries, lastSeenKey } func (bav *UtxoView) GetNFTBidEntriesForPKID(bidderPKID *PKID) (_nftBidEntries []*NFTBidEntry) { diff --git a/lib/db_utils.go b/lib/db_utils.go index d1d8bfac7..de61eb52f 100644 --- a/lib/db_utils.go +++ b/lib/db_utils.go @@ -8754,18 +8754,35 @@ func DBGetNFTEntryByNFTOwnershipDetails(db *badger.DB, snap *Snapshot, ownerPKID } // DBGetNFTEntriesForPKID gets NFT Entries *from the DB*. Does not include mempool txns. -func DBGetNFTEntriesForPKID(handle *badger.DB, ownerPKID *PKID) (_nftEntries []*NFTEntry) { +func DBGetNFTEntriesForPKID( + handle *badger.DB, + ownerPKID *PKID, + limit int, + lastKeyBytes []byte, +) ( + _nftEntries []*NFTEntry, + _lastKeyBytes []byte, +) { var nftEntries []*NFTEntry prefix := append([]byte{}, Prefixes.PrefixPKIDIsForSaleBidAmountNanosPostHashSerialNumberToNFTEntry...) keyPrefix := append(prefix, ownerPKID[:]...) - _, entryByteStringsFound := _enumerateKeysForPrefix(handle, keyPrefix, false, false) + var lastSeenKey []byte + if len(lastKeyBytes) > 0 { + lastSeenKey = lastKeyBytes + } + keyBytesFound, entryByteStringsFound, _ := EnumerateKeysForPrefixWithLimitOffsetOrder(handle, keyPrefix, limit, lastSeenKey, false, NewSet[string]([]string{})) + //keyBytesFound, entryByteStringsFound := _enumerateKeysForPrefix(handle, keyPrefix, false, true) for _, byteString := range entryByteStringsFound { currentEntry := &NFTEntry{} rr := bytes.NewReader(byteString) DecodeFromBytes(currentEntry, rr) nftEntries = append(nftEntries, currentEntry) } - return nftEntries + var lastKey []byte + if len(keyBytesFound) > 0 { + lastKey = keyBytesFound[len(keyBytesFound)-1] + } + return nftEntries, lastKey } // ======================================================================================= From 4e5cf86cbbbb802dff3c492c02a6b4d93c0e8513 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Tue, 24 Jun 2025 17:55:22 -0400 Subject: [PATCH 2/5] formatting and use PKID.Eq instead of reflect deepequals --- lib/block_view_nft.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/block_view_nft.go b/lib/block_view_nft.go index 8aaef728a..9945b4711 100644 --- a/lib/block_view_nft.go +++ b/lib/block_view_nft.go @@ -94,7 +94,11 @@ func (bav *UtxoView) GetNFTEntriesForPostHash(nftPostHash *BlockHash) []*NFTEntr return nftEntries } -func (bav *UtxoView) GetNFTEntriesForPKID(ownerPKID *PKID, limit int, lastKeyBytes []byte) ([]*NFTEntry, []byte) { +func (bav *UtxoView) GetNFTEntriesForPKID( + ownerPKID *PKID, + limit int, + lastKeyBytes []byte, +) ([]*NFTEntry, []byte) { var dbNFTEntries []*NFTEntry var lastSeenKey []byte if bav.Postgres != nil { @@ -119,7 +123,7 @@ func (bav *UtxoView) GetNFTEntriesForPKID(ownerPKID *PKID, limit int, lastKeyByt // Loop over the view and build the final set of NFTEntries to return. nftEntries := []*NFTEntry{} for _, nftEntry := range bav.NFTKeyToNFTEntry { - if !nftEntry.isDeleted && reflect.DeepEqual(nftEntry.OwnerPKID, ownerPKID) { + if !nftEntry.isDeleted && nftEntry.OwnerPKID.Eq(ownerPKID) { nftEntries = append(nftEntries, nftEntry) } } From 9d4e03099e3b78b9d5b1601a6a59a3f1a08fcbd1 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Tue, 24 Jun 2025 18:06:30 -0400 Subject: [PATCH 3/5] filter for sale and pending in db --- lib/block_view_nft.go | 4 ++- lib/db_utils.go | 80 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/lib/block_view_nft.go b/lib/block_view_nft.go index 9945b4711..771653759 100644 --- a/lib/block_view_nft.go +++ b/lib/block_view_nft.go @@ -98,6 +98,8 @@ func (bav *UtxoView) GetNFTEntriesForPKID( ownerPKID *PKID, limit int, lastKeyBytes []byte, + isForSale *bool, + isPending *bool, ) ([]*NFTEntry, []byte) { var dbNFTEntries []*NFTEntry var lastSeenKey []byte @@ -107,7 +109,7 @@ func (bav *UtxoView) GetNFTEntriesForPKID( dbNFTEntries = append(dbNFTEntries, nft.NewNFTEntry()) } } else { - dbNFTEntries, lastSeenKey = DBGetNFTEntriesForPKID(bav.Handle, ownerPKID, limit, lastKeyBytes) + dbNFTEntries, lastSeenKey = DBGetNFTEntriesForPKID(bav.Handle, ownerPKID, limit, lastKeyBytes, isForSale, isPending) } // Make sure all of the DB entries are loaded in the view. diff --git a/lib/db_utils.go b/lib/db_utils.go index de61eb52f..5ab86c915 100644 --- a/lib/db_utils.go +++ b/lib/db_utils.go @@ -8759,6 +8759,8 @@ func DBGetNFTEntriesForPKID( ownerPKID *PKID, limit int, lastKeyBytes []byte, + isForSale *bool, + isPending *bool, ) ( _nftEntries []*NFTEntry, _lastKeyBytes []byte, @@ -8766,23 +8768,73 @@ func DBGetNFTEntriesForPKID( var nftEntries []*NFTEntry prefix := append([]byte{}, Prefixes.PrefixPKIDIsForSaleBidAmountNanosPostHashSerialNumberToNFTEntry...) keyPrefix := append(prefix, ownerPKID[:]...) - var lastSeenKey []byte + if isForSale != nil { + keyPrefix = append(keyPrefix, BoolToByte(*isForSale)) + } + lastSeenKey := keyPrefix + haveSeenLastSeenKey := true if len(lastKeyBytes) > 0 { lastSeenKey = lastKeyBytes + if limit > 0 { + limit += 1 + } } - keyBytesFound, entryByteStringsFound, _ := EnumerateKeysForPrefixWithLimitOffsetOrder(handle, keyPrefix, limit, lastSeenKey, false, NewSet[string]([]string{})) - //keyBytesFound, entryByteStringsFound := _enumerateKeysForPrefix(handle, keyPrefix, false, true) - for _, byteString := range entryByteStringsFound { - currentEntry := &NFTEntry{} - rr := bytes.NewReader(byteString) - DecodeFromBytes(currentEntry, rr) - nftEntries = append(nftEntries, currentEntry) - } - var lastKey []byte - if len(keyBytesFound) > 0 { - lastKey = keyBytesFound[len(keyBytesFound)-1] - } - return nftEntries, lastKey + + opts := badger.DefaultIteratorOptions + opts.Prefix = keyPrefix + var lastSeenKeyBytes []byte + dbErr := handle.View(func(txn *badger.Txn) error { + nodeIterator := txn.NewIterator(opts) + defer nodeIterator.Close() + for nodeIterator.Seek(lastSeenKey); nodeIterator.ValidForPrefix(keyPrefix); nodeIterator.Next() { + // Break if at or beyond limit. + if limit > 0 && len(nftEntries) >= limit { + break + } + key := nodeIterator.Item().Key() + // Skip if key is before the last seen key. The caller + // needs to filter out the lastSeenKey in the view as + // we return any key >= the lastSeenKey. + if !haveSeenLastSeenKey { + if !bytes.Equal(key, lastSeenKey) { + continue + } + haveSeenLastSeenKey = true + } + + val, err := nodeIterator.Item().ValueCopy(nil) + if err != nil { + return err + } + currentEntry := &NFTEntry{} + rr := bytes.NewReader(val) + DecodeFromBytes(currentEntry, rr) + // If isPending is specified, filter by it. + if isPending != nil && currentEntry.IsPending != *isPending { + continue + } + nftEntries = append(nftEntries, currentEntry) + lastSeenKeyBytes = append([]byte{}, key...) + } + return nil + }) + if dbErr != nil { + glog.Errorf("DBGetNFTEntriesForPKID: Problem reading NFTEntry, error: (%v)", dbErr) + } + + //keyBytesFound, entryByteStringsFound, _ := EnumerateKeysForPrefixWithLimitOffsetOrder(handle, keyPrefix, limit, lastSeenKey, false, NewSet[string]([]string{})) + ////keyBytesFound, entryByteStringsFound := _enumerateKeysForPrefix(handle, keyPrefix, false, true) + //for _, byteString := range entryByteStringsFound { + // currentEntry := &NFTEntry{} + // rr := bytes.NewReader(byteString) + // DecodeFromBytes(currentEntry, rr) + // nftEntries = append(nftEntries, currentEntry) + //} + //var lastKey []byte + //if len(keyBytesFound) > 0 { + // lastKey = keyBytesFound[len(keyBytesFound)-1] + //} + return nftEntries, lastSeenKeyBytes } // ======================================================================================= From 3a72355b6885e190c22114640127fad51391def8 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Wed, 25 Jun 2025 14:50:14 -0400 Subject: [PATCH 4/5] remove commented out code --- lib/db_utils.go | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/db_utils.go b/lib/db_utils.go index 5ab86c915..33db6bf52 100644 --- a/lib/db_utils.go +++ b/lib/db_utils.go @@ -5486,8 +5486,8 @@ func InitDbWithDeSoGenesisBlock(params *DeSoParams, handle *badger.DB, blockHash, 0, // Height diffTarget, - BytesToBigint(ExpectedWorkForBlockHash(diffTarget)[:]), // CumWork - genesisBlock.Header, // Header + BytesToBigint(ExpectedWorkForBlockHash(diffTarget)[:]), // CumWork + genesisBlock.Header, // Header StatusHeaderValidated|StatusBlockProcessed|StatusBlockStored|StatusBlockValidated|StatusBlockCommitted, // Status ) @@ -8822,18 +8822,6 @@ func DBGetNFTEntriesForPKID( glog.Errorf("DBGetNFTEntriesForPKID: Problem reading NFTEntry, error: (%v)", dbErr) } - //keyBytesFound, entryByteStringsFound, _ := EnumerateKeysForPrefixWithLimitOffsetOrder(handle, keyPrefix, limit, lastSeenKey, false, NewSet[string]([]string{})) - ////keyBytesFound, entryByteStringsFound := _enumerateKeysForPrefix(handle, keyPrefix, false, true) - //for _, byteString := range entryByteStringsFound { - // currentEntry := &NFTEntry{} - // rr := bytes.NewReader(byteString) - // DecodeFromBytes(currentEntry, rr) - // nftEntries = append(nftEntries, currentEntry) - //} - //var lastKey []byte - //if len(keyBytesFound) > 0 { - // lastKey = keyBytesFound[len(keyBytesFound)-1] - //} return nftEntries, lastSeenKeyBytes } @@ -9908,7 +9896,7 @@ func DBGetPaginatedPostsOrderedByTime( postIndexKeys, _, err := DBGetPaginatedKeysAndValuesForPrefix( db, startPostPrefix, Prefixes.PrefixTstampNanosPostHash, /*validForPrefix*/ len(Prefixes.PrefixTstampNanosPostHash)+len(maxUint64Tstamp)+HashSizeBytes, /*keyLen*/ - numToFetch, reverse /*reverse*/, false /*fetchValues*/) + numToFetch, reverse /*reverse*/, false /*fetchValues*/) if err != nil { return nil, nil, nil, fmt.Errorf("DBGetPaginatedPostsOrderedByTime: %v", err) } @@ -10035,7 +10023,7 @@ func DBGetPaginatedProfilesByDeSoLocked( profileIndexKeys, _, err := DBGetPaginatedKeysAndValuesForPrefix( db, startProfilePrefix, Prefixes.PrefixCreatorDeSoLockedNanosCreatorPKID, /*validForPrefix*/ keyLen /*keyLen*/, numToFetch, - true /*reverse*/, false /*fetchValues*/) + true /*reverse*/, false /*fetchValues*/) if err != nil { return nil, nil, fmt.Errorf("DBGetPaginatedProfilesByDeSoLocked: %v", err) } From 64b8d162e18ea7a8fcd42cea11bf9cc76f9e28f9 Mon Sep 17 00:00:00 2001 From: Lazy Nina Date: Wed, 25 Jun 2025 15:01:11 -0400 Subject: [PATCH 5/5] gofmt --- lib/db_utils.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/db_utils.go b/lib/db_utils.go index 33db6bf52..acfa83e82 100644 --- a/lib/db_utils.go +++ b/lib/db_utils.go @@ -5486,8 +5486,8 @@ func InitDbWithDeSoGenesisBlock(params *DeSoParams, handle *badger.DB, blockHash, 0, // Height diffTarget, - BytesToBigint(ExpectedWorkForBlockHash(diffTarget)[:]), // CumWork - genesisBlock.Header, // Header + BytesToBigint(ExpectedWorkForBlockHash(diffTarget)[:]), // CumWork + genesisBlock.Header, // Header StatusHeaderValidated|StatusBlockProcessed|StatusBlockStored|StatusBlockValidated|StatusBlockCommitted, // Status ) @@ -9896,7 +9896,7 @@ func DBGetPaginatedPostsOrderedByTime( postIndexKeys, _, err := DBGetPaginatedKeysAndValuesForPrefix( db, startPostPrefix, Prefixes.PrefixTstampNanosPostHash, /*validForPrefix*/ len(Prefixes.PrefixTstampNanosPostHash)+len(maxUint64Tstamp)+HashSizeBytes, /*keyLen*/ - numToFetch, reverse /*reverse*/, false /*fetchValues*/) + numToFetch, reverse /*reverse*/, false /*fetchValues*/) if err != nil { return nil, nil, nil, fmt.Errorf("DBGetPaginatedPostsOrderedByTime: %v", err) } @@ -10023,7 +10023,7 @@ func DBGetPaginatedProfilesByDeSoLocked( profileIndexKeys, _, err := DBGetPaginatedKeysAndValuesForPrefix( db, startProfilePrefix, Prefixes.PrefixCreatorDeSoLockedNanosCreatorPKID, /*validForPrefix*/ keyLen /*keyLen*/, numToFetch, - true /*reverse*/, false /*fetchValues*/) + true /*reverse*/, false /*fetchValues*/) if err != nil { return nil, nil, fmt.Errorf("DBGetPaginatedProfilesByDeSoLocked: %v", err) }