Skip to content

Commit f8e22b7

Browse files
authored
include entire wrapped transaction in notifications (#742)
* include entire wrapped transaction in notifications * revert changes in getDBNotifications and getMempoolNotifications to flatten atomic inner txns
1 parent 3279a4a commit f8e22b7

File tree

1 file changed

+166
-130
lines changed

1 file changed

+166
-130
lines changed

routes/user.go

Lines changed: 166 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"encoding/hex"
77
"encoding/json"
88
"fmt"
9+
"github.com/deso-protocol/core/collections"
910
"github.com/deso-protocol/uint256"
1011
"io"
1112
"math"
@@ -2331,56 +2332,7 @@ func (fes *APIServer) GetNotifications(ww http.ResponseWriter, req *http.Request
23312332
}
23322333

23332334
for _, txnMeta := range finalTxnMetadataList {
2334-
postMetadata := txnMeta.Metadata.SubmitPostTxindexMetadata
2335-
likeMetadata := txnMeta.Metadata.LikeTxindexMetadata
2336-
transferCreatorCoinMetadata := txnMeta.Metadata.CreatorCoinTransferTxindexMetadata
2337-
nftBidMetadata := txnMeta.Metadata.NFTBidTxindexMetadata
2338-
acceptNFTBidMetadata := txnMeta.Metadata.AcceptNFTBidTxindexMetadata
2339-
nftTransferMetadata := txnMeta.Metadata.NFTTransferTxindexMetadata
2340-
basicTransferMetadata := txnMeta.Metadata.BasicTransferTxindexMetadata
2341-
createNFTMetadata := txnMeta.Metadata.CreateNFTTxindexMetadata
2342-
updateNFTMetadata := txnMeta.Metadata.UpdateNFTTxindexMetadata
2343-
postAssociationMetadata := txnMeta.Metadata.CreatePostAssociationTxindexMetadata
2344-
2345-
if postMetadata != nil {
2346-
addPostForHash(postMetadata.PostHashBeingModifiedHex, userPublicKeyBytes)
2347-
addPostForHash(postMetadata.ParentPostHashHex, userPublicKeyBytes)
2348-
} else if likeMetadata != nil {
2349-
addPostForHash(likeMetadata.PostHashHex, userPublicKeyBytes)
2350-
} else if transferCreatorCoinMetadata != nil {
2351-
if transferCreatorCoinMetadata.PostHashHex != "" {
2352-
addPostForHash(transferCreatorCoinMetadata.PostHashHex, userPublicKeyBytes)
2353-
}
2354-
} else if nftBidMetadata != nil {
2355-
addPostForHash(nftBidMetadata.NFTPostHashHex, userPublicKeyBytes)
2356-
} else if acceptNFTBidMetadata != nil {
2357-
addPostForHash(acceptNFTBidMetadata.NFTPostHashHex, userPublicKeyBytes)
2358-
} else if nftTransferMetadata != nil {
2359-
addPostForHash(nftTransferMetadata.NFTPostHashHex, userPublicKeyBytes)
2360-
} else if createNFTMetadata != nil {
2361-
addPostForHash(createNFTMetadata.NFTPostHashHex, userPublicKeyBytes)
2362-
} else if updateNFTMetadata != nil {
2363-
addPostForHash(updateNFTMetadata.NFTPostHashHex, userPublicKeyBytes)
2364-
} else if postAssociationMetadata != nil {
2365-
addPostForHash(postAssociationMetadata.PostHashHex, userPublicKeyBytes)
2366-
} else if basicTransferMetadata != nil {
2367-
txnOutputs := txnMeta.Metadata.TxnOutputs
2368-
for _, output := range txnOutputs {
2369-
txnMeta.TxnOutputResponses = append(
2370-
txnMeta.TxnOutputResponses,
2371-
&OutputResponse{
2372-
PublicKeyBase58Check: lib.PkToString(output.PublicKey, fes.Params),
2373-
AmountNanos: output.AmountNanos,
2374-
})
2375-
}
2376-
if basicTransferMetadata.PostHashHex != "" {
2377-
addPostForHash(basicTransferMetadata.PostHashHex, userPublicKeyBytes)
2378-
}
2379-
}
2380-
2381-
// Delete the UTXO ops because they aren't needed for the frontend
2382-
basicTransferMetadata.UtxoOps = nil
2383-
basicTransferMetadata.UtxoOpsDump = ""
2335+
fes.addPostForHashForNotification(txnMeta, txnMeta.Metadata, userPublicKeyBytes, addPostForHash, nil)
23842336
}
23852337

23862338
var lastSeenIndex int64
@@ -2399,12 +2351,100 @@ func (fes *APIServer) GetNotifications(ww http.ResponseWriter, req *http.Request
23992351
LastSeenIndex: lastSeenIndex,
24002352
}
24012353
if err = json.NewEncoder(ww).Encode(res); err != nil {
2354+
fmt.Printf("%#v\n", res)
24022355
_AddBadRequestError(ww, fmt.Sprintf(
24032356
"GetNotifications: Problem encoding response as JSON: %v", err))
24042357
return
24052358
}
24062359
}
24072360

2361+
func (fes *APIServer) addPostForHashForNotification(
2362+
txnMetaRes *TransactionMetadataResponse,
2363+
txnMeta *lib.TransactionMetadata,
2364+
userPublicKeyBytes []byte,
2365+
addPostForHash func(postHashHex string, readerPK []byte),
2366+
indexInAtomic *int,
2367+
) {
2368+
postMetadata := txnMeta.SubmitPostTxindexMetadata
2369+
likeMetadata := txnMeta.LikeTxindexMetadata
2370+
transferCreatorCoinMetadata := txnMeta.CreatorCoinTransferTxindexMetadata
2371+
nftBidMetadata := txnMeta.NFTBidTxindexMetadata
2372+
acceptNFTBidMetadata := txnMeta.AcceptNFTBidTxindexMetadata
2373+
nftTransferMetadata := txnMeta.NFTTransferTxindexMetadata
2374+
basicTransferMetadata := txnMeta.BasicTransferTxindexMetadata
2375+
createNFTMetadata := txnMeta.CreateNFTTxindexMetadata
2376+
updateNFTMetadata := txnMeta.UpdateNFTTxindexMetadata
2377+
postAssociationMetadata := txnMeta.CreatePostAssociationTxindexMetadata
2378+
atomicTxnMetadata := txnMeta.AtomicTxnsWrapperTxindexMetadata
2379+
if atomicTxnMetadata != nil {
2380+
for ii, innerTxn := range atomicTxnMetadata.InnerTxnsTransactionMetadata {
2381+
fes.addPostForHashForNotification(txnMetaRes, innerTxn, userPublicKeyBytes, addPostForHash, &ii)
2382+
innerTxn.BasicTransferTxindexMetadata.UtxoOps = nil
2383+
innerTxn.BasicTransferTxindexMetadata.UtxoOpsDump = ""
2384+
}
2385+
}
2386+
if atomicTxnMetadata != nil {
2387+
for ii, innerTxn := range atomicTxnMetadata.InnerTxnsTransactionMetadata {
2388+
fes.addPostForHashForNotification(txnMetaRes, innerTxn, userPublicKeyBytes, addPostForHash, &ii)
2389+
innerTxn.BasicTransferTxindexMetadata.UtxoOps = nil
2390+
innerTxn.BasicTransferTxindexMetadata.UtxoOpsDump = ""
2391+
}
2392+
}
2393+
2394+
if postMetadata != nil {
2395+
addPostForHash(postMetadata.PostHashBeingModifiedHex, userPublicKeyBytes)
2396+
addPostForHash(postMetadata.ParentPostHashHex, userPublicKeyBytes)
2397+
} else if likeMetadata != nil {
2398+
addPostForHash(likeMetadata.PostHashHex, userPublicKeyBytes)
2399+
} else if transferCreatorCoinMetadata != nil {
2400+
if transferCreatorCoinMetadata.PostHashHex != "" {
2401+
addPostForHash(transferCreatorCoinMetadata.PostHashHex, userPublicKeyBytes)
2402+
}
2403+
} else if nftBidMetadata != nil {
2404+
addPostForHash(nftBidMetadata.NFTPostHashHex, userPublicKeyBytes)
2405+
} else if acceptNFTBidMetadata != nil {
2406+
addPostForHash(acceptNFTBidMetadata.NFTPostHashHex, userPublicKeyBytes)
2407+
} else if nftTransferMetadata != nil {
2408+
addPostForHash(nftTransferMetadata.NFTPostHashHex, userPublicKeyBytes)
2409+
} else if createNFTMetadata != nil {
2410+
addPostForHash(createNFTMetadata.NFTPostHashHex, userPublicKeyBytes)
2411+
} else if updateNFTMetadata != nil {
2412+
addPostForHash(updateNFTMetadata.NFTPostHashHex, userPublicKeyBytes)
2413+
} else if postAssociationMetadata != nil {
2414+
addPostForHash(postAssociationMetadata.PostHashHex, userPublicKeyBytes)
2415+
} else if basicTransferMetadata != nil {
2416+
txnOutputs := txnMeta.TxnOutputs
2417+
for _, output := range txnOutputs {
2418+
txnMetaRes.TxnOutputResponses = append(
2419+
txnMetaRes.TxnOutputResponses,
2420+
&OutputResponse{
2421+
PublicKeyBase58Check: lib.PkToString(output.PublicKey, fes.Params),
2422+
AmountNanos: output.AmountNanos,
2423+
})
2424+
if indexInAtomic != nil {
2425+
if txnMetaRes.InnerTxnOutputResponses == nil {
2426+
txnMetaRes.InnerTxnOutputResponses = make(map[int][]*OutputResponse)
2427+
}
2428+
txnMetaRes.InnerTxnOutputResponses[*indexInAtomic] = append(
2429+
txnMetaRes.InnerTxnOutputResponses[*indexInAtomic],
2430+
&OutputResponse{
2431+
PublicKeyBase58Check: lib.PkToString(output.PublicKey, fes.Params),
2432+
AmountNanos: output.AmountNanos,
2433+
})
2434+
}
2435+
}
2436+
if basicTransferMetadata.PostHashHex != "" {
2437+
addPostForHash(basicTransferMetadata.PostHashHex, userPublicKeyBytes)
2438+
}
2439+
}
2440+
2441+
// Delete the UTXO ops because they aren't needed for the frontend
2442+
txnMeta.BasicTransferTxindexMetadata.UtxoOps = nil
2443+
txnMeta.BasicTransferTxindexMetadata.UtxoOpsDump = ""
2444+
basicTransferMetadata.UtxoOps = nil
2445+
basicTransferMetadata.UtxoOpsDump = ""
2446+
}
2447+
24082448
type SetNotificationMetadataRequest struct {
24092449
PublicKeyBase58Check string
24102450
// The last notification index the user has seen
@@ -2520,46 +2560,38 @@ func (fes *APIServer) _getDBNotifications(request *GetNotificationsRequest, bloc
25202560

25212561
// In this case we need to look up the full transaction and convert
25222562
// it into a proper transaction response.
2523-
dbTxnMeta := lib.DbGetTxindexTransactionRefByTxID(fes.TXIndex.TXIndexChain.DB(), nil, txID)
2524-
if dbTxnMeta == nil {
2563+
txnMeta := lib.DbGetTxindexTransactionRefByTxID(fes.TXIndex.TXIndexChain.DB(), nil, txID)
2564+
if txnMeta == nil {
25252565
// We should never be missing a transaction for a given txid, but
25262566
// just continue in this case.
25272567
glog.Errorf("GetNotifications: Missing TransactionMetadata for txid %v", txID)
25282568
continue
25292569
}
2530-
txnMetas := []*lib.TransactionMetadata{dbTxnMeta}
2531-
if dbTxnMeta.AtomicTxnsWrapperTxindexMetadata != nil {
2532-
// If this is an atomic transaction, we need to iterate over the inner transactions
2533-
// and convert them into TransactionMetadata objects.
2534-
txnMetas = dbTxnMeta.AtomicTxnsWrapperTxindexMetadata.InnerTxnsTransactionMetadata
2570+
// Skip transactions that aren't notifications
2571+
if !TxnMetaIsNotification(txnMeta, request.PublicKeyBase58Check, utxoView) {
2572+
continue
25352573
}
2536-
for _, txnMeta := range txnMetas {
2537-
// Skip transactions that aren't notifications
2538-
if !TxnMetaIsNotification(txnMeta, request.PublicKeyBase58Check, utxoView) {
2539-
continue
2540-
}
2541-
transactorPkBytes, _, err := lib.Base58CheckDecode(txnMeta.TransactorPublicKeyBase58Check)
2542-
if err != nil {
2543-
glog.Errorf("GetNotifications: unable to decode public key %v", txnMeta.TransactorPublicKeyBase58Check)
2544-
continue
2545-
}
2546-
// Skip transactions from blocked users.
2547-
if _, ok := blockedPubKeys[lib.PkToString(transactorPkBytes, fes.Params)]; ok {
2548-
continue
2549-
}
2550-
// Skip transactions from blacklisted public keys
2551-
transactorPKID := utxoView.GetPKIDForPublicKey(transactorPkBytes)
2552-
if transactorPKID == nil || fes.IsUserBlacklisted(transactorPKID.PKID, utxoView) {
2553-
continue
2554-
}
2555-
currentIndexBytes := keysFound[ii][len(lib.DbTxindexPublicKeyPrefix(pkBytes)):]
2556-
res := &TransactionMetadataResponse{
2557-
Metadata: txnMeta,
2558-
Index: int64(lib.DecodeUint32(currentIndexBytes)),
2559-
}
2560-
if NotificationTxnShouldBeIncluded(res.Metadata, &filteredOutCategories) {
2561-
dbTxnMetadataFound = append(dbTxnMetadataFound, res)
2562-
}
2574+
transactorPkBytes, _, err := lib.Base58CheckDecode(txnMeta.TransactorPublicKeyBase58Check)
2575+
if err != nil {
2576+
glog.Errorf("GetNotifications: unable to decode public key %v", txnMeta.TransactorPublicKeyBase58Check)
2577+
continue
2578+
}
2579+
// Skip transactions from blocked users.
2580+
if _, ok := blockedPubKeys[lib.PkToString(transactorPkBytes, fes.Params)]; ok {
2581+
continue
2582+
}
2583+
// Skip transactions from blacklisted public keys
2584+
transactorPKID := utxoView.GetPKIDForPublicKey(transactorPkBytes)
2585+
if transactorPKID == nil || fes.IsUserBlacklisted(transactorPKID.PKID, utxoView) {
2586+
continue
2587+
}
2588+
currentIndexBytes := keysFound[ii][len(lib.DbTxindexPublicKeyPrefix(pkBytes)):]
2589+
res := &TransactionMetadataResponse{
2590+
Metadata: txnMeta,
2591+
Index: int64(lib.DecodeUint32(currentIndexBytes)),
2592+
}
2593+
if NotificationTxnShouldBeIncluded(res.Metadata, &filteredOutCategories) {
2594+
dbTxnMetadataFound = append(dbTxnMetadataFound, res)
25632595
}
25642596
}
25652597

@@ -2633,60 +2665,51 @@ func (fes *APIServer) _getMempoolNotifications(request *GetNotificationsRequest,
26332665

26342666
mempoolTxnMetadata := []*TransactionMetadataResponse{}
26352667
for _, poolTx := range poolTxns {
2636-
poolTxnMeta := poolTx.TxMeta
2637-
if poolTxnMeta == nil {
2668+
txnMeta := poolTx.TxMeta
2669+
if txnMeta == nil {
26382670
continue
26392671
}
26402672

26412673
// Set the current index we will use to identify this transaction.
26422674
currentIndex := NextIndex
26432675

2644-
txnMetas := []*lib.TransactionMetadata{poolTxnMeta}
2645-
if poolTxnMeta.AtomicTxnsWrapperTxindexMetadata != nil {
2646-
// If this is an atomic transaction, we need to iterate over the inner transactions
2647-
// and convert them into TransactionMetadata objects.
2648-
txnMetas = poolTxnMeta.AtomicTxnsWrapperTxindexMetadata.InnerTxnsTransactionMetadata
2676+
// Increment the NextIndex if this transaction is associated with the user's
2677+
// public key in any way. This is what the db would do when storing it, and so
2678+
// this treatment should be consistent.
2679+
if TxnIsAssociatedWithPublicKey(txnMeta, request.PublicKeyBase58Check) {
2680+
NextIndex++
26492681
}
2650-
for _, txnMeta := range txnMetas {
26512682

2652-
// Increment the NextIndex if this transaction is associated with the user's
2653-
// public key in any way. This is what the db would do when storing it, and so
2654-
// this treatment should be consistent.
2655-
if TxnIsAssociatedWithPublicKey(txnMeta, request.PublicKeyBase58Check) {
2656-
NextIndex++
2683+
// If the transaction is a notification then add it to our list with the proper
2684+
// index value if the transactor is not a blocked public key
2685+
if TxnMetaIsNotification(txnMeta, request.PublicKeyBase58Check, utxoView) {
2686+
transactorPkBytes, _, err := lib.Base58CheckDecode(txnMeta.TransactorPublicKeyBase58Check)
2687+
if err != nil {
2688+
glog.Errorf("GetNotifications: unable to decode public key %v", txnMeta.TransactorPublicKeyBase58Check)
2689+
continue
26572690
}
26582691

2659-
// If the transaction is a notification then add it to our list with the proper
2660-
// index value if the transactor is not a blocked public key
2661-
if TxnMetaIsNotification(txnMeta, request.PublicKeyBase58Check, utxoView) {
2662-
transactorPkBytes, _, err := lib.Base58CheckDecode(txnMeta.TransactorPublicKeyBase58Check)
2663-
if err != nil {
2664-
glog.Errorf("GetNotifications: unable to decode public key %v", txnMeta.TransactorPublicKeyBase58Check)
2665-
continue
2666-
}
2667-
2668-
// Skip transactions from blocked users.
2669-
if _, ok := blockedPubKeys[lib.PkToString(transactorPkBytes, fes.Params)]; ok {
2670-
continue
2671-
}
2672-
// Skip blacklisted public keys
2673-
transactorPKID := utxoView.GetPKIDForPublicKey(transactorPkBytes)
2674-
if transactorPKID == nil || fes.IsUserBlacklisted(transactorPKID.PKID, utxoView) {
2675-
continue
2676-
}
2692+
// Skip transactions from blocked users.
2693+
if _, ok := blockedPubKeys[lib.PkToString(transactorPkBytes, fes.Params)]; ok {
2694+
continue
2695+
}
2696+
// Skip blacklisted public keys
2697+
transactorPKID := utxoView.GetPKIDForPublicKey(transactorPkBytes)
2698+
if transactorPKID == nil || fes.IsUserBlacklisted(transactorPKID.PKID, utxoView) {
2699+
continue
2700+
}
26772701

2678-
// Skip transactions when notification should not be included based on filter
2679-
if !NotificationTxnShouldBeIncluded(txnMeta, &filteredOutCategories) {
2680-
continue
2681-
}
2702+
// Skip transactions when notification should not be included based on filter
2703+
if !NotificationTxnShouldBeIncluded(txnMeta, &filteredOutCategories) {
2704+
continue
2705+
}
26822706

2683-
// Only include transactions that occur on or after the start index, if defined
2684-
if request.FetchStartIndex < 0 || (request.FetchStartIndex >= currentIndex && iterateReverse) || (request.FetchStartIndex <= currentIndex && !iterateReverse) {
2685-
mempoolTxnMetadata = append(mempoolTxnMetadata, &TransactionMetadataResponse{
2686-
Metadata: txnMeta,
2687-
Index: currentIndex,
2688-
})
2689-
}
2707+
// Only include transactions that occur on or after the start index, if defined
2708+
if request.FetchStartIndex < 0 || (request.FetchStartIndex >= currentIndex && iterateReverse) || (request.FetchStartIndex <= currentIndex && !iterateReverse) {
2709+
mempoolTxnMetadata = append(mempoolTxnMetadata, &TransactionMetadataResponse{
2710+
Metadata: txnMeta,
2711+
Index: currentIndex,
2712+
})
26902713
}
26912714
}
26922715

@@ -2876,6 +2899,12 @@ func NotificationTxnShouldBeIncluded(txnMeta *lib.TransactionMetadata, filteredO
28762899
} else if txnMeta.TxnType == lib.TxnTypeCreateUserAssociation.String() ||
28772900
txnMeta.TxnType == lib.TxnTypeDeleteUserAssociation.String() {
28782901
return !filteredOutCategories["user association"]
2902+
} else if txnMeta.TxnType == lib.TxnTypeAtomicTxnsWrapper.String() {
2903+
// If any of the component transactions would be included, then this atomic txn should be included.
2904+
return collections.Any(txnMeta.AtomicTxnsWrapperTxindexMetadata.InnerTxnsTransactionMetadata,
2905+
func(innerTxnMeta *lib.TransactionMetadata) bool {
2906+
return NotificationTxnShouldBeIncluded(innerTxnMeta, filteredOutCategoriesPointer)
2907+
})
28792908
}
28802909
// If the transaction type doesn't fall into any of the previous steps, we don't want it
28812910
return false
@@ -2972,6 +3001,12 @@ func TxnMetaIsNotification(txnMeta *lib.TransactionMetadata, publicKeyBase58Chec
29723001
} else if txnMeta.CreatePostAssociationTxindexMetadata != nil {
29733002
// Some created an association referring to one of your posts
29743003
return true
3004+
} else if txnMeta.AtomicTxnsWrapperTxindexMetadata != nil {
3005+
// If any of the component transactions would trigger a notification, then this atomic txn should trigger a notification.
3006+
return collections.Any(txnMeta.AtomicTxnsWrapperTxindexMetadata.InnerTxnsTransactionMetadata,
3007+
func(innerTxnMeta *lib.TransactionMetadata) bool {
3008+
return TxnMetaIsNotification(innerTxnMeta, publicKeyBase58Check, utxoView)
3009+
})
29753010
}
29763011
return false
29773012
}
@@ -2989,10 +3024,11 @@ func TxnIsAssociatedWithPublicKey(txnMeta *lib.TransactionMetadata, publicKeyBas
29893024
}
29903025

29913026
type TransactionMetadataResponse struct {
2992-
Metadata *lib.TransactionMetadata
2993-
TxnOutputResponses []*OutputResponse
2994-
Txn *TransactionResponse
2995-
Index int64
3027+
Metadata *lib.TransactionMetadata
3028+
TxnOutputResponses []*OutputResponse
3029+
InnerTxnOutputResponses map[int][]*OutputResponse
3030+
Txn *TransactionResponse
3031+
Index int64
29963032
}
29973033

29983034
type BlockPublicKeyRequest struct {

0 commit comments

Comments
 (0)