github.com/deso-protocol/core@v1.2.9/lib/block_view_flush.go (about) 1 package lib 2 3 import ( 4 "fmt" 5 "github.com/btcsuite/btcd/btcec" 6 "github.com/dgraph-io/badger/v3" 7 "github.com/golang/glog" 8 "github.com/pkg/errors" 9 "reflect" 10 ) 11 12 func (bav *UtxoView) FlushToDb() error { 13 // Make sure everything happens inside a single transaction. 14 var err error 15 if bav.Postgres != nil { 16 err = bav.Postgres.FlushView(bav) 17 if err != nil { 18 return err 19 } 20 } 21 22 err = bav.Handle.Update(func(txn *badger.Txn) error { 23 return bav.FlushToDbWithTxn(txn) 24 }) 25 if err != nil { 26 return err 27 } 28 29 // After a successful flush, reset the in-memory mappings for the view 30 // so that it can be re-used if desired. 31 // 32 // Note that the TipHash does not get reset as part of _ResetViewMappingsAfterFlush because 33 // it is not something that is affected by a flush operation. Moreover, its value 34 // is consistent with the view regardless of whether or not the view is flushed or 35 // not. 36 bav._ResetViewMappingsAfterFlush() 37 38 return nil 39 } 40 41 func (bav *UtxoView) FlushToDbWithTxn(txn *badger.Txn) error { 42 // Only flush to BadgerDB if Postgres is disabled 43 if bav.Postgres == nil { 44 if err := bav._flushUtxosToDbWithTxn(txn); err != nil { 45 return err 46 } 47 if err := bav._flushProfileEntriesToDbWithTxn(txn); err != nil { 48 return err 49 } 50 if err := bav._flushPKIDEntriesToDbWithTxn(txn); err != nil { 51 return err 52 } 53 if err := bav._flushPostEntriesToDbWithTxn(txn); err != nil { 54 return err 55 } 56 if err := bav._flushLikeEntriesToDbWithTxn(txn); err != nil { 57 return err 58 } 59 if err := bav._flushFollowEntriesToDbWithTxn(txn); err != nil { 60 return err 61 } 62 if err := bav._flushDiamondEntriesToDbWithTxn(txn); err != nil { 63 return err 64 } 65 if err := bav._flushMessageEntriesToDbWithTxn(txn); err != nil { 66 return err 67 } 68 if err := bav._flushBalanceEntriesToDbWithTxn(txn); err != nil { 69 return err 70 } 71 if err := bav._flushDeSoBalancesToDbWithTxn(txn); err != nil { 72 return err 73 } 74 if err := bav._flushForbiddenPubKeyEntriesToDbWithTxn(txn); err != nil { 75 return err 76 } 77 if err := bav._flushNFTEntriesToDbWithTxn(txn); err != nil { 78 return err 79 } 80 if err := bav._flushNFTBidEntriesToDbWithTxn(txn); err != nil { 81 return err 82 } 83 if err := bav._flushDerivedKeyEntryToDbWithTxn(txn); err != nil { 84 return err 85 } 86 } 87 88 // Always flush to BadgerDB. 89 if err := bav._flushBitcoinExchangeDataWithTxn(txn); err != nil { 90 return err 91 } 92 if err := bav._flushGlobalParamsEntryToDbWithTxn(txn); err != nil { 93 return err 94 } 95 if err := bav._flushAcceptedBidEntriesToDbWithTxn(txn); err != nil { 96 return err 97 } 98 if err := bav._flushRepostEntriesToDbWithTxn(txn); err != nil { 99 return err 100 } 101 102 return nil 103 } 104 105 func (bav *UtxoView) _flushUtxosToDbWithTxn(txn *badger.Txn) error { 106 glog.V(1).Infof("_flushUtxosToDbWithTxn: flushing %d mappings", len(bav.UtxoKeyToUtxoEntry)) 107 108 for utxoKeyIter, utxoEntry := range bav.UtxoKeyToUtxoEntry { 109 // Make a copy of the iterator since it might change from under us. 110 utxoKey := utxoKeyIter 111 112 // As a sanity-check, make sure the back-reference for each entry 113 // points to its key. 114 if utxoEntry.UtxoKey == nil || *utxoEntry.UtxoKey != utxoKey { 115 return fmt.Errorf("_flushUtxosToDbWithTxn: Found utxoEntry %+v for "+ 116 "utxoKey %v has invalid back-refernce utxoKey %v", 117 utxoEntry, utxoKey, utxoEntry.UtxoKey) 118 } 119 120 // Start by deleting the pre-existing mappings in the db for this key if they 121 // have not yet been modified. 122 if err := DeleteUnmodifiedMappingsForUtxoWithTxn(txn, &utxoKey); err != nil { 123 return err 124 } 125 } 126 numDeleted := 0 127 numPut := 0 128 for utxoKeyIter, utxoEntry := range bav.UtxoKeyToUtxoEntry { 129 // Make a copy of the iterator since it might change from under us. 130 utxoKey := utxoKeyIter 131 132 if utxoEntry.isSpent { 133 numDeleted++ 134 // If an entry is spent then there's nothing to do, since the mappings in 135 // the db have already been deleted. 136 } else { 137 numPut++ 138 // If the entry is unspent, then we need to re-set its mappings in the db 139 // appropriately. 140 if err := PutMappingsForUtxoWithTxn(txn, &utxoKey, utxoEntry); err != nil { 141 return err 142 } 143 } 144 } 145 146 glog.V(1).Infof("_flushUtxosToDbWithTxn: deleted %d mappings, put %d mappings", numDeleted, numPut) 147 148 // Now update the number of entries in the db with confidence. 149 if err := PutUtxoNumEntriesWithTxn(txn, bav.NumUtxoEntries); err != nil { 150 return err 151 } 152 153 // At this point, the db's position index should be updated and the (key -> entry) 154 // index should be updated to remove all spent utxos. The number of entries field 155 // in the db should also be accurate. 156 157 return nil 158 } 159 160 func (bav *UtxoView) _flushDeSoBalancesToDbWithTxn(txn *badger.Txn) error { 161 glog.V(1).Infof("_flushDeSoBalancesToDbWithTxn: flushing %d mappings", 162 len(bav.PublicKeyToDeSoBalanceNanos)) 163 164 for pubKeyIter := range bav.PublicKeyToDeSoBalanceNanos { 165 // Make a copy of the iterator since it might change from under us. 166 pubKey := pubKeyIter[:] 167 168 // Start by deleting the pre-existing mappings in the db for this key if they 169 // have not yet been modified. 170 if err := DbDeletePublicKeyToDeSoBalanceWithTxn(txn, pubKey); err != nil { 171 return err 172 } 173 } 174 for pubKeyIter, balanceNanos := range bav.PublicKeyToDeSoBalanceNanos { 175 // Make a copy of the iterator since it might change from under us. 176 pubKey := pubKeyIter[:] 177 178 if balanceNanos > 0 { 179 if err := DbPutDeSoBalanceForPublicKeyWithTxn(txn, pubKey, balanceNanos); err != nil { 180 return err 181 } 182 } 183 } 184 185 return nil 186 } 187 188 func (bav *UtxoView) _flushGlobalParamsEntryToDbWithTxn(txn *badger.Txn) error { 189 globalParamsEntry := bav.GlobalParamsEntry 190 if err := DbPutGlobalParamsEntryWithTxn(txn, *globalParamsEntry); err != nil { 191 return errors.Wrapf(err, "_flushGlobalParamsEntryToDbWithTxn: Problem putting global params entry in DB") 192 } 193 return nil 194 } 195 196 func (bav *UtxoView) _flushForbiddenPubKeyEntriesToDbWithTxn(txn *badger.Txn) error { 197 198 // Go through all the entries in the KeyTorepostEntry map. 199 for _, forbiddenPubKeyEntry := range bav.ForbiddenPubKeyToForbiddenPubKeyEntry { 200 // Delete the existing mappings in the db for this ForbiddenPubKeyEntry. They will be re-added 201 // if the corresponding entry in memory has isDeleted=false. 202 if err := DbDeleteForbiddenBlockSignaturePubKeyWithTxn( 203 txn, forbiddenPubKeyEntry.PubKey[:]); err != nil { 204 205 return errors.Wrapf( 206 err, "_flushForbiddenPubKeyEntriesToDbWithTxn: Problem deleting "+ 207 "forbidden public key: %v: ", &forbiddenPubKeyEntry.PubKey) 208 } 209 } 210 for _, forbiddenPubKeyEntry := range bav.ForbiddenPubKeyToForbiddenPubKeyEntry { 211 if forbiddenPubKeyEntry.isDeleted { 212 // If the ForbiddenPubKeyEntry has isDeleted=true then there's nothing to do because 213 // we already deleted the entry above. 214 } else { 215 // If the ForbiddenPubKeyEntry has (isDeleted = false) then we put the corresponding 216 // mappings for it into the db. 217 if err := DbPutForbiddenBlockSignaturePubKeyWithTxn(txn, forbiddenPubKeyEntry.PubKey); err != nil { 218 return err 219 } 220 } 221 } 222 223 return nil 224 } 225 226 func (bav *UtxoView) _flushBitcoinExchangeDataWithTxn(txn *badger.Txn) error { 227 // Iterate through our in-memory map. If anything has a value of false it means 228 // that particular mapping should be expunged from the db. If anything has a value 229 // of true it means that mapping should be added to the db. 230 for bitcoinBurnTxIDIter, mappingExists := range bav.BitcoinBurnTxIDs { 231 // Be paranoid and copy the iterator in case anything takes a reference below. 232 bitcoinBurnTxID := bitcoinBurnTxIDIter 233 234 if mappingExists { 235 // In this case we should add the mapping to the db. 236 if err := DbPutBitcoinBurnTxIDWithTxn(txn, &bitcoinBurnTxID); err != nil { 237 return errors.Wrapf(err, "UtxoView._flushBitcoinExchangeDataWithTxn: "+ 238 "Problem putting BitcoinBurnTxID %v to db", &bitcoinBurnTxID) 239 } 240 } else { 241 // In this case we should delete the mapping from the db. 242 if err := DbDeleteBitcoinBurnTxIDWithTxn(txn, &bitcoinBurnTxID); err != nil { 243 return errors.Wrapf(err, "UtxoView._flushBitcoinExchangeDataWithTxn: "+ 244 "Problem deleting BitcoinBurnTxID %v to db", &bitcoinBurnTxID) 245 } 246 } 247 } 248 249 // Update NanosPurchased 250 if err := DbPutNanosPurchasedWithTxn(txn, bav.NanosPurchased); err != nil { 251 errors.Wrapf(err, "UtxoView._flushBitcoinExchangeDataWithTxn: "+ 252 "Problem putting NanosPurchased %d to db", bav.NanosPurchased) 253 } 254 255 // Update the BitcoinUSDExchangeRate in the db 256 if err := DbPutUSDCentsPerBitcoinExchangeRateWithTxn(txn, bav.USDCentsPerBitcoin); err != nil { 257 errors.Wrapf(err, "UtxoView.FlushToDBWithTxn: "+ 258 "Problem putting USDCentsPerBitcoin %d to db", bav.USDCentsPerBitcoin) 259 } 260 261 // DB should be fully up to date as far as BitcoinBurnTxIDs and NanosPurchased go. 262 return nil 263 } 264 265 func (bav *UtxoView) _flushMessageEntriesToDbWithTxn(txn *badger.Txn) error { 266 // Go through all the entries in the MessageKeyToMessageEntry map. 267 for messageKeyIter, messageEntry := range bav.MessageKeyToMessageEntry { 268 // Make a copy of the iterator since we take references to it below. 269 messageKey := messageKeyIter 270 271 // Sanity-check that one of the MessageKey computed from the MEssageEntry is 272 // equal to the MessageKey that maps to that entry. 273 senderMessageKeyInEntry := MakeMessageKey( 274 messageEntry.SenderPublicKey, messageEntry.TstampNanos) 275 recipientMessageKeyInEntry := MakeMessageKey( 276 messageEntry.RecipientPublicKey, messageEntry.TstampNanos) 277 if senderMessageKeyInEntry != messageKey && recipientMessageKeyInEntry != messageKey { 278 return fmt.Errorf("_flushMessageEntriesToDbWithTxn: MessageEntry has "+ 279 "SenderMessageKey: %v and RecipientMessageKey %v, neither of which match "+ 280 "the MessageKeyToMessageEntry map key %v", 281 &senderMessageKeyInEntry, &recipientMessageKeyInEntry, &messageKey) 282 } 283 284 // Delete the existing mappings in the db for this MessageKey. They will be re-added 285 // if the corresponding entry in memory has isDeleted=false. 286 if err := DbDeleteMessageEntryMappingsWithTxn( 287 txn, messageKey.PublicKey[:], messageKey.TstampNanos); err != nil { 288 289 return errors.Wrapf( 290 err, "_flushMessageEntriesToDbWithTxn: Problem deleting mappings "+ 291 "for MessageKey: %v: ", &messageKey) 292 } 293 } 294 // Go through all the entries in the MessageKeyToMessageEntry map. 295 for _, messageEntry := range bav.MessageKeyToMessageEntry { 296 if messageEntry.isDeleted { 297 // If the MessageEntry has isDeleted=true then there's nothing to do because 298 // we already deleted the entry above. 299 } else { 300 // If the MessageEntry has (isDeleted = false) then we put the corresponding 301 // mappings for it into the db. 302 if err := DbPutMessageEntryWithTxn(txn, messageEntry); err != nil { 303 304 return err 305 } 306 } 307 } 308 309 // At this point all of the MessageEntry mappings in the db should be up-to-date. 310 311 return nil 312 } 313 314 func (bav *UtxoView) _flushRepostEntriesToDbWithTxn(txn *badger.Txn) error { 315 316 // Go through all the entries in the repostKeyTorepostEntry map. 317 for repostKeyIter, repostEntry := range bav.RepostKeyToRepostEntry { 318 // Make a copy of the iterator since we make references to it below. 319 repostKey := repostKeyIter 320 321 // Sanity-check that the RepostKey computed from the RepostEntry is 322 // equal to the RepostKey that maps to that entry. 323 repostKeyInEntry := MakeRepostKey(repostEntry.ReposterPubKey, *repostEntry.RepostedPostHash) 324 if repostKeyInEntry != repostKey { 325 return fmt.Errorf("_flushRepostEntriesToDbWithTxn: RepostEntry has "+ 326 "RepostKey: %v, which doesn't match the RepostKeyToRepostEntry map key %v", 327 &repostKeyInEntry, &repostKey) 328 } 329 330 // Delete the existing mappings in the db for this RepostKey. They will be re-added 331 // if the corresponding entry in memory has isDeleted=false. 332 if err := DbDeleteRepostMappingsWithTxn( 333 txn, repostKey.ReposterPubKey[:], repostKey.RepostedPostHash); err != nil { 334 335 return errors.Wrapf( 336 err, "_flushRepostEntriesToDbWithTxn: Problem deleting mappings "+ 337 "for RepostKey: %v: ", &repostKey) 338 } 339 } 340 for _, repostEntry := range bav.RepostKeyToRepostEntry { 341 if repostEntry.isDeleted { 342 // If the RepostedEntry has isDeleted=true then there's nothing to do because 343 // we already deleted the entry above. 344 } else { 345 // If the RepostEntry has (isDeleted = false) then we put the corresponding 346 // mappings for it into the db. 347 if err := DbPutRepostMappingsWithTxn( 348 txn, repostEntry.ReposterPubKey, *repostEntry.RepostedPostHash, *repostEntry); err != nil { 349 return err 350 } 351 } 352 } 353 354 // At this point all of the RepostEntry mappings in the db should be up-to-date. 355 356 return nil 357 } 358 359 func (bav *UtxoView) _flushLikeEntriesToDbWithTxn(txn *badger.Txn) error { 360 361 // Go through all the entries in the LikeKeyToLikeEntry map. 362 for likeKeyIter, likeEntry := range bav.LikeKeyToLikeEntry { 363 // Make a copy of the iterator since we make references to it below. 364 likeKey := likeKeyIter 365 366 // Sanity-check that the LikeKey computed from the LikeEntry is 367 // equal to the LikeKey that maps to that entry. 368 likeKeyInEntry := MakeLikeKey(likeEntry.LikerPubKey, *likeEntry.LikedPostHash) 369 if likeKeyInEntry != likeKey { 370 return fmt.Errorf("_flushLikeEntriesToDbWithTxn: LikeEntry has "+ 371 "LikeKey: %v, which doesn't match the LikeKeyToLikeEntry map key %v", 372 &likeKeyInEntry, &likeKey) 373 } 374 375 // Delete the existing mappings in the db for this LikeKey. They will be re-added 376 // if the corresponding entry in memory has isDeleted=false. 377 if err := DbDeleteLikeMappingsWithTxn( 378 txn, likeKey.LikerPubKey[:], likeKey.LikedPostHash); err != nil { 379 380 return errors.Wrapf( 381 err, "_flushLikeEntriesToDbWithTxn: Problem deleting mappings "+ 382 "for LikeKey: %v: ", &likeKey) 383 } 384 } 385 386 // Go through all the entries in the LikeKeyToLikeEntry map. 387 for _, likeEntry := range bav.LikeKeyToLikeEntry { 388 389 if likeEntry.isDeleted { 390 // If the LikeEntry has isDeleted=true then there's nothing to do because 391 // we already deleted the entry above. 392 } else { 393 // If the LikeEntry has (isDeleted = false) then we put the corresponding 394 // mappings for it into the db. 395 if err := DbPutLikeMappingsWithTxn( 396 txn, likeEntry.LikerPubKey, *likeEntry.LikedPostHash); err != nil { 397 398 return err 399 } 400 } 401 } 402 403 return nil 404 } 405 406 func (bav *UtxoView) _flushFollowEntriesToDbWithTxn(txn *badger.Txn) error { 407 408 // Go through all the entries in the FollowKeyToFollowEntry map. 409 for followKeyIter, followEntry := range bav.FollowKeyToFollowEntry { 410 // Make a copy of the iterator since we make references to it below. 411 followKey := followKeyIter 412 413 // Sanity-check that the FollowKey computed from the FollowEntry is 414 // equal to the FollowKey that maps to that entry. 415 followKeyInEntry := MakeFollowKey( 416 followEntry.FollowerPKID, followEntry.FollowedPKID) 417 if followKeyInEntry != followKey { 418 return fmt.Errorf("_flushFollowEntriesToDbWithTxn: FollowEntry has "+ 419 "FollowKey: %v, which doesn't match the FollowKeyToFollowEntry map key %v", 420 &followKeyInEntry, &followKey) 421 } 422 423 // Delete the existing mappings in the db for this FollowKey. They will be re-added 424 // if the corresponding entry in memory has isDeleted=false. 425 if err := DbDeleteFollowMappingsWithTxn( 426 txn, followEntry.FollowerPKID, followEntry.FollowedPKID); err != nil { 427 428 return errors.Wrapf( 429 err, "_flushFollowEntriesToDbWithTxn: Problem deleting mappings "+ 430 "for FollowKey: %v: ", &followKey) 431 } 432 } 433 434 // Go through all the entries in the FollowKeyToFollowEntry map. 435 for _, followEntry := range bav.FollowKeyToFollowEntry { 436 if followEntry.isDeleted { 437 // If the FollowEntry has isDeleted=true then there's nothing to do because 438 // we already deleted the entry above. 439 } else { 440 // If the FollowEntry has (isDeleted = false) then we put the corresponding 441 // mappings for it into the db. 442 if err := DbPutFollowMappingsWithTxn( 443 txn, followEntry.FollowerPKID, followEntry.FollowedPKID); err != nil { 444 445 return err 446 } 447 } 448 } 449 450 return nil 451 } 452 453 func (bav *UtxoView) _flushNFTEntriesToDbWithTxn(txn *badger.Txn) error { 454 455 // Go through and delete all the entries so they can be added back fresh. 456 for nftKeyIter, nftEntry := range bav.NFTKeyToNFTEntry { 457 // Make a copy of the iterator since we make references to it below. 458 nftKey := nftKeyIter 459 460 // Sanity-check that the NFTKey computed from the NFTEntry is 461 // equal to the NFTKey that maps to that entry. 462 nftKeyInEntry := MakeNFTKey(nftEntry.NFTPostHash, nftEntry.SerialNumber) 463 if nftKeyInEntry != nftKey { 464 return fmt.Errorf("_flushNFTEntriesToDbWithTxn: NFTEntry has "+ 465 "NFTKey: %v, which doesn't match the NFTKeyToNFTEntry map key %v", 466 &nftKeyInEntry, &nftKey) 467 } 468 469 // Delete the existing mappings in the db for this NFTKey. They will be re-added 470 // if the corresponding entry in memory has isDeleted=false. 471 if err := DBDeleteNFTMappingsWithTxn(txn, nftEntry.NFTPostHash, nftEntry.SerialNumber); err != nil { 472 473 return errors.Wrapf( 474 err, "_flushNFTEntriesToDbWithTxn: Problem deleting mappings "+ 475 "for NFTKey: %v: ", &nftKey) 476 } 477 } 478 479 // Add back all of the entries that aren't deleted. 480 for _, nftEntry := range bav.NFTKeyToNFTEntry { 481 if nftEntry.isDeleted { 482 // If the NFTEntry has isDeleted=true then there's nothing to do because 483 // we already deleted the entry above. 484 } else { 485 // If the NFTEntry has (isDeleted = false) then we put the corresponding 486 // mappings for it into the db. 487 if err := DBPutNFTEntryMappingsWithTxn(txn, nftEntry); err != nil { 488 return err 489 } 490 } 491 } 492 493 return nil 494 } 495 496 func (bav *UtxoView) _flushAcceptedBidEntriesToDbWithTxn(txn *badger.Txn) error { 497 498 // Go through and delete all the entries so they can be added back fresh. 499 for nftKeyIter, _ := range bav.NFTKeyToAcceptedNFTBidHistory { 500 // Make a copy of the iterator since we make references to it below. 501 nftKey := nftKeyIter 502 503 // We skip the standard sanity check. Since it is possible to accept a bid on serial number 0, it is possible 504 // that none of the accepted bids have the same serial number as the key. 505 506 // Delete the existing mappings in the db for this NFTKey. They will be re-added 507 // if the corresponding entry in memory has isDeleted=false. 508 if err := DBDeleteAcceptedNFTBidEntriesMappingsWithTxn(txn, &nftKey.NFTPostHash, nftKey.SerialNumber); err != nil { 509 510 return errors.Wrapf( 511 err, "_flushAcceptedBidEntriesToDbWithTxn: Problem deleting mappings "+ 512 "for NFTKey: %v: ", &nftKey) 513 } 514 } 515 516 // Add back all of the entries that aren't nil or of length 0 517 for nftKey, acceptedNFTBidEntries := range bav.NFTKeyToAcceptedNFTBidHistory { 518 if acceptedNFTBidEntries == nil || len(*acceptedNFTBidEntries) == 0 { 519 // If the acceptedNFTBidEntries is nil or has length 0 then there's nothing to do because 520 // we already deleted the entry above. length 0 means that there are no accepted bids yet. 521 } else { 522 // If the NFTEntry has (isDeleted = false) then we put the corresponding 523 // mappings for it into the db. 524 if err := DBPutAcceptedNFTBidEntriesMappingWithTxn(txn, nftKey, acceptedNFTBidEntries); err != nil { 525 return err 526 } 527 } 528 } 529 530 return nil 531 } 532 533 func (bav *UtxoView) _flushNFTBidEntriesToDbWithTxn(txn *badger.Txn) error { 534 535 // Go through and delete all the entries so they can be added back fresh. 536 for nftBidKeyIter, nftBidEntry := range bav.NFTBidKeyToNFTBidEntry { 537 // Make a copy of the iterator since we make references to it below. 538 nftBidKey := nftBidKeyIter 539 540 // Sanity-check that the NFTBidKey computed from the NFTBidEntry is 541 // equal to the NFTBidKey that maps to that entry. 542 nftBidKeyInEntry := MakeNFTBidKey( 543 nftBidEntry.BidderPKID, nftBidEntry.NFTPostHash, nftBidEntry.SerialNumber) 544 if nftBidKeyInEntry != nftBidKey { 545 return fmt.Errorf("_flushNFTBidEntriesToDbWithTxn: NFTBidEntry has "+ 546 "NFTBidKey: %v, which doesn't match the NFTBidKeyToNFTEntry map key %v", 547 &nftBidKeyInEntry, &nftBidKey) 548 } 549 550 // Delete the existing mappings in the db for this NFTBidKey. They will be re-added 551 // if the corresponding entry in memory has isDeleted=false. 552 if err := DBDeleteNFTBidMappingsWithTxn(txn, &nftBidKey); err != nil { 553 554 return errors.Wrapf( 555 err, "_flushNFTBidEntriesToDbWithTxn: Problem deleting mappings "+ 556 "for NFTBidKey: %v: ", &nftBidKey) 557 } 558 } 559 560 // Add back all of the entries that aren't deleted. 561 for _, nftBidEntry := range bav.NFTBidKeyToNFTBidEntry { 562 if nftBidEntry.isDeleted { 563 // If the NFTEntry has isDeleted=true then there's nothing to do because 564 // we already deleted the entry above. 565 } else { 566 // If the NFTEntry has (isDeleted = false) then we put the corresponding 567 // mappings for it into the db. 568 if err := DBPutNFTBidEntryMappingsWithTxn(txn, nftBidEntry); err != nil { 569 return err 570 } 571 } 572 } 573 574 return nil 575 } 576 577 func (bav *UtxoView) _flushDiamondEntriesToDbWithTxn(txn *badger.Txn) error { 578 579 // Go through and delete all the entries so they can be added back fresh. 580 for diamondKeyIter, diamondEntry := range bav.DiamondKeyToDiamondEntry { 581 // Make a copy of the iterator since we make references to it below. 582 diamondKey := diamondKeyIter 583 584 // Sanity-check that the DiamondKey computed from the DiamondEntry is 585 // equal to the DiamondKey that maps to that entry. 586 diamondKeyInEntry := MakeDiamondKey( 587 diamondEntry.SenderPKID, diamondEntry.ReceiverPKID, diamondEntry.DiamondPostHash) 588 if diamondKeyInEntry != diamondKey { 589 return fmt.Errorf("_flushDiamondEntriesToDbWithTxn: DiamondEntry has "+ 590 "DiamondKey: %v, which doesn't match the DiamondKeyToDiamondEntry map key %v", 591 &diamondKeyInEntry, &diamondKey) 592 } 593 594 // Delete the existing mappings in the db for this DiamondKey. They will be re-added 595 // if the corresponding entry in memory has isDeleted=false. 596 if err := DbDeleteDiamondMappingsWithTxn(txn, diamondEntry); err != nil { 597 598 return errors.Wrapf( 599 err, "_flushDiamondEntriesToDbWithTxn: Problem deleting mappings "+ 600 "for DiamondKey: %v: ", &diamondKey) 601 } 602 } 603 604 // Add back all of the entries that aren't deleted. 605 for _, diamondEntry := range bav.DiamondKeyToDiamondEntry { 606 if diamondEntry.isDeleted { 607 // If the DiamondEntry has isDeleted=true then there's nothing to do because 608 // we already deleted the entry above. 609 } else { 610 // If the DiamondEntry has (isDeleted = false) then we put the corresponding 611 // mappings for it into the db. 612 if err := DbPutDiamondMappingsWithTxn( 613 txn, 614 diamondEntry); err != nil { 615 return err 616 } 617 } 618 } 619 620 // At this point all of the MessageEntry mappings in the db should be up-to-date. 621 622 return nil 623 } 624 625 func (bav *UtxoView) _flushPostEntriesToDbWithTxn(txn *badger.Txn) error { 626 // TODO(DELETEME): Remove flush logging after debugging MarkBlockInvalid bug. 627 glog.V(1).Infof("_flushPostEntriesToDbWithTxn: flushing %d mappings", len(bav.PostHashToPostEntry)) 628 629 // Go through all the entries in the PostHashToPostEntry map. 630 for postHashIter, postEntry := range bav.PostHashToPostEntry { 631 // Make a copy of the iterator since we take references to it below. 632 postHash := postHashIter 633 634 // Sanity-check that the hash in the post is the same as the hash in the 635 // entry 636 if postHash != *postEntry.PostHash { 637 return fmt.Errorf("_flushPostEntriesToDbWithTxn: PostEntry has "+ 638 "PostHash: %v, neither of which match "+ 639 "the PostHashToPostEntry map key %v", 640 postHash, postEntry.PostHash) 641 } 642 643 // Delete the existing mappings in the db for this PostHash. They will be re-added 644 // if the corresponding entry in memory has isDeleted=false. 645 if err := DBDeletePostEntryMappingsWithTxn(txn, &postHash, bav.Params); err != nil { 646 return errors.Wrapf( 647 err, "_flushPostEntriesToDbWithTxn: Problem deleting mappings "+ 648 "for PostHash: %v: ", postHash) 649 } 650 } 651 numDeleted := 0 652 numPut := 0 653 for _, postEntry := range bav.PostHashToPostEntry { 654 if postEntry.isDeleted { 655 numDeleted++ 656 // If the PostEntry has isDeleted=true then there's nothing to do because 657 // we already deleted the entry above. 658 } else { 659 numPut++ 660 // If the PostEntry has (isDeleted = false) then we put the corresponding 661 // mappings for it into the db. 662 if err := DBPutPostEntryMappingsWithTxn(txn, postEntry, bav.Params); err != nil { 663 664 return err 665 } 666 } 667 } 668 669 // TODO(DELETEME): Remove flush logging after debugging MarkBlockInvalid bug. 670 glog.V(1).Infof("_flushPostEntriesToDbWithTxn: deleted %d mappings, put %d mappings", numDeleted, numPut) 671 672 // At this point all of the PostEntry mappings in the db should be up-to-date. 673 674 return nil 675 } 676 func (bav *UtxoView) _flushPKIDEntriesToDbWithTxn(txn *badger.Txn) error { 677 for pubKeyIter, pkidEntry := range bav.PublicKeyToPKIDEntry { 678 pubKeyCopy := make([]byte, btcec.PubKeyBytesLenCompressed) 679 copy(pubKeyCopy, pubKeyIter[:]) 680 681 // Delete the existing mappings in the db for this PKID. They will be re-added 682 // if the corresponding entry in memory has isDeleted=false. 683 if err := DBDeletePKIDMappingsWithTxn(txn, pubKeyCopy, bav.Params); err != nil { 684 return errors.Wrapf( 685 err, "_flushPKIDEntriesToDbWithTxn: Problem deleting mappings "+ 686 "for pkid: %v, public key: %v: ", PkToString(pkidEntry.PKID[:], bav.Params), 687 PkToString(pubKeyCopy, bav.Params)) 688 } 689 } 690 691 // Go through all the entries in the ProfilePublicKeyToProfileEntry map. 692 for pubKeyIter, pkidEntry := range bav.PublicKeyToPKIDEntry { 693 pubKeyCopy := make([]byte, btcec.PubKeyBytesLenCompressed) 694 copy(pubKeyCopy, pubKeyIter[:]) 695 696 if pkidEntry.isDeleted { 697 // If the ProfileEntry has isDeleted=true then there's nothing to do because 698 // we already deleted the entry above. 699 } else { 700 // Sanity-check that the public key in the entry matches the public key in 701 // the mapping. 702 if !reflect.DeepEqual(pubKeyCopy, pkidEntry.PublicKey) { 703 return fmt.Errorf("_flushPKIDEntriesToDbWithTxn: Sanity-check failed. "+ 704 "Public key in entry %v does not match public key in mapping %v ", 705 PkToString(pkidEntry.PublicKey[:], bav.Params), 706 PkToString(pubKeyCopy, bav.Params)) 707 } 708 // Sanity-check that the mapping in the public key map lines up with the mapping 709 // in the PKID map. 710 if _, pkidEntryExists := bav.PKIDToPublicKey[*pkidEntry.PKID]; !pkidEntryExists { 711 return fmt.Errorf("_flushPKIDEntriesToDbWithTxn: Sanity-check failed. "+ 712 "PKID %v for public key %v does not exist in PKIDToPublicKey map.", 713 PkToString(pkidEntry.PKID[:], bav.Params), 714 PkToString(pubKeyCopy, bav.Params)) 715 } 716 717 // If the ProfileEntry has (isDeleted = false) then we put the corresponding 718 // mappings for it into the db. 719 if err := DBPutPKIDMappingsWithTxn(txn, pubKeyCopy, pkidEntry, bav.Params); err != nil { 720 return err 721 } 722 } 723 } 724 725 // At this point all of the PKIDEntry mappings in the db should be up-to-date. 726 return nil 727 } 728 729 func (bav *UtxoView) _flushProfileEntriesToDbWithTxn(txn *badger.Txn) error { 730 glog.V(1).Infof("_flushProfilesToDbWithTxn: flushing %d mappings", len(bav.ProfilePKIDToProfileEntry)) 731 732 // Go through all the entries in the ProfilePublicKeyToProfileEntry map. 733 for profilePKIDIter, profileEntry := range bav.ProfilePKIDToProfileEntry { 734 // Make a copy of the iterator since we take references to it below. 735 profilePKID := profilePKIDIter 736 737 // Delete the existing mappings in the db for this PKID. They will be re-added 738 // if the corresponding entry in memory has isDeleted=false. 739 if err := DBDeleteProfileEntryMappingsWithTxn(txn, &profilePKID, bav.Params); err != nil { 740 return errors.Wrapf( 741 err, "_flushProfileEntriesToDbWithTxn: Problem deleting mappings "+ 742 "for pkid: %v, public key: %v: ", PkToString(profilePKID[:], bav.Params), 743 PkToString(profileEntry.PublicKey, bav.Params)) 744 } 745 } 746 numDeleted := 0 747 numPut := 0 748 for profilePKIDIter, profileEntry := range bav.ProfilePKIDToProfileEntry { 749 // Make a copy of the iterator since we take references to it below. 750 profilePKID := profilePKIDIter 751 752 if profileEntry.isDeleted { 753 numDeleted++ 754 // If the ProfileEntry has isDeleted=true then there's nothing to do because 755 // we already deleted the entry above. 756 } else { 757 numPut++ 758 // Get the PKID according to another map in the view and 759 // sanity-check that it lines up. 760 viewPKIDEntry := bav.GetPKIDForPublicKey(profileEntry.PublicKey) 761 if viewPKIDEntry == nil || viewPKIDEntry.isDeleted || *viewPKIDEntry.PKID != profilePKID { 762 return fmt.Errorf("_flushProfileEntriesToDbWithTxn: Sanity-check failed: PKID %v does "+ 763 "not exist in view mapping for profile with public key %v", 764 PkToString(profilePKID[:], bav.Params), 765 PkToString(profileEntry.PublicKey, bav.Params)) 766 } 767 768 // If the ProfileEntry has (isDeleted = false) then we put the corresponding 769 // mappings for it into the db. 770 if err := DBPutProfileEntryMappingsWithTxn( 771 txn, profileEntry, &profilePKID, bav.Params); err != nil { 772 773 return err 774 } 775 } 776 } 777 778 glog.V(1).Infof("_flushProfilesToDbWithTxn: deleted %d mappings, put %d mappings", numDeleted, numPut) 779 780 // At this point all of the PostEntry mappings in the db should be up-to-date. 781 782 return nil 783 } 784 785 func (bav *UtxoView) _flushBalanceEntriesToDbWithTxn(txn *badger.Txn) error { 786 glog.V(1).Infof("_flushBalanceEntriesToDbWithTxn: flushing %d mappings", len(bav.HODLerPKIDCreatorPKIDToBalanceEntry)) 787 788 // Go through all the entries in the HODLerPubKeyCreatorPubKeyToBalanceEntry map. 789 for balanceKeyIter, balanceEntry := range bav.HODLerPKIDCreatorPKIDToBalanceEntry { 790 // Make a copy of the iterator since we take references to it below. 791 balanceKey := balanceKeyIter 792 793 // Sanity-check that the balance key in the map is the same 794 // as the public key in the entry. 795 computedBalanceKey := MakeCreatorCoinBalanceKey( 796 balanceEntry.HODLerPKID, balanceEntry.CreatorPKID) 797 if !reflect.DeepEqual(balanceKey, computedBalanceKey) { 798 return fmt.Errorf("_flushBalanceEntriesToDbWithTxn: BalanceEntry has "+ 799 "map key: %v which does not match match "+ 800 "the HODLerPubKeyCreatorPubKeyToBalanceEntry map key %v", 801 balanceKey, computedBalanceKey) 802 } 803 804 // Delete the existing mappings in the db for this balance key. They will be re-added 805 // if the corresponding entry in memory has isDeleted=false. 806 if err := DBDeleteCreatorCoinBalanceEntryMappingsWithTxn( 807 txn, &(balanceKey.HODLerPKID), &(balanceKey.CreatorPKID), bav.Params); err != nil { 808 809 return errors.Wrapf( 810 err, "_flushBalanceEntriesToDbWithTxn: Problem deleting mappings "+ 811 "for public key: %v: ", balanceKey) 812 } 813 } 814 numDeleted := 0 815 numPut := 0 816 // Go through all the entries in the HODLerPubKeyCreatorPubKeyToBalanceEntry map. 817 for _, balanceEntry := range bav.HODLerPKIDCreatorPKIDToBalanceEntry { 818 // Make a copy of the iterator since we take references to it below. 819 if balanceEntry.isDeleted { 820 numDeleted++ 821 // If the ProfileEntry has isDeleted=true then there's nothing to do because 822 // we already deleted the entry above. 823 } else { 824 numPut++ 825 // If the ProfileEntry has (isDeleted = false) then we put the corresponding 826 // mappings for it into the db. 827 if err := DBPutCreatorCoinBalanceEntryMappingsWithTxn( 828 txn, balanceEntry, bav.Params); err != nil { 829 830 return err 831 } 832 } 833 } 834 835 glog.V(1).Infof("_flushBalanceEntriesToDbWithTxn: deleted %d mappings, put %d mappings", numDeleted, numPut) 836 837 // At this point all of the PostEntry mappings in the db should be up-to-date. 838 839 return nil 840 } 841 842 func (bav *UtxoView) _flushDerivedKeyEntryToDbWithTxn(txn *badger.Txn) error { 843 glog.V(1).Infof("_flushDerivedKeyEntryToDbWithTxn: flushing %d mappings", len(bav.DerivedKeyToDerivedEntry)) 844 845 // Go through all entries in the DerivedKeyToDerivedEntry map and add them to the DB. 846 for derivedKeyMapKey, derivedKeyEntry := range bav.DerivedKeyToDerivedEntry { 847 // Delete the existing mapping in the DB for this map key, this will be re-added 848 // later if isDeleted=false. 849 if err := DBDeleteDerivedKeyMappingWithTxn(txn, derivedKeyMapKey.OwnerPublicKey, 850 derivedKeyMapKey.DerivedPublicKey); err != nil { 851 return errors.Wrapf(err, "UtxoView._flushDerivedKeyEntryToDbWithTxn: "+ 852 "Problem deleting DerivedKeyEntry %v from db", *derivedKeyEntry) 853 } 854 855 numDeleted := 0 856 numPut := 0 857 if derivedKeyEntry.isDeleted { 858 // Since entry is deleted, there's nothing to do. 859 numDeleted++ 860 } else { 861 // In this case we add the mapping to the DB. 862 if err := DBPutDerivedKeyMappingWithTxn(txn, derivedKeyMapKey.OwnerPublicKey, 863 derivedKeyMapKey.DerivedPublicKey, derivedKeyEntry); err != nil { 864 return errors.Wrapf(err, "UtxoView._flushDerivedKeyEntryToDbWithTxn: "+ 865 "Problem putting DerivedKeyEntry %v to db", *derivedKeyEntry) 866 } 867 numPut++ 868 } 869 glog.V(1).Infof("_flushDerivedKeyEntryToDbWithTxn: deleted %d mappings, put %d mappings", numDeleted, numPut) 870 } 871 872 return nil 873 }