@@ -296,8 +296,10 @@ func (k Keeper) instantiate(ctx sdk.Context, codeID uint64, creator, admin sdk.A
296
296
}
297
297
298
298
// store contract before dispatch so that contract could be called back
299
+ historyEntry := contractInfo .InitialHistory (initMsg )
300
+ k .addToContractCodeSecondaryIndex (ctx , contractAddress , historyEntry )
301
+ k .appendToContractHistory (ctx , contractAddress , historyEntry )
299
302
k .storeContractInfo (ctx , contractAddress , & contractInfo )
300
- k .appendToContractHistory (ctx , contractAddress , contractInfo .InitialHistory (initMsg ))
301
303
302
304
// dispatch submessages then messages
303
305
err = k .dispatchAll (ctx , contractAddress , contractInfo .IBCPortID , res .Submessages , res .Messages )
@@ -408,10 +410,11 @@ func (k Keeper) migrate(ctx sdk.Context, contractAddress sdk.AccAddress, caller
408
410
ctx .EventManager ().EmitEvents (events )
409
411
410
412
// delete old secondary index entry
411
- k .deleteContractSecondIndex (ctx , contractAddress , contractInfo )
413
+ k .removeFromContractCodeSecondaryIndex (ctx , contractAddress , k . getLastContractHistoryEntry ( ctx , contractAddress ) )
412
414
// persist migration updates
413
415
historyEntry := contractInfo .AddMigration (ctx , newCodeID , msg )
414
416
k .appendToContractHistory (ctx , contractAddress , historyEntry )
417
+ k .addToContractCodeSecondaryIndex (ctx , contractAddress , historyEntry )
415
418
k .storeContractInfo (ctx , contractAddress , contractInfo )
416
419
417
420
// dispatch submessages then messages
@@ -507,8 +510,26 @@ func (k Keeper) reply(ctx sdk.Context, contractAddress sdk.AccAddress, reply was
507
510
}, nil
508
511
}
509
512
510
- func (k Keeper ) deleteContractSecondIndex (ctx sdk.Context , contractAddress sdk.AccAddress , contractInfo * types.ContractInfo ) {
511
- ctx .KVStore (k .storeKey ).Delete (types .GetContractByCreatedSecondaryIndexKey (contractAddress , contractInfo ))
513
+ // addToContractCodeSecondaryIndex adds element to the index for contracts-by-codeid queries
514
+ func (k Keeper ) addToContractCodeSecondaryIndex (ctx sdk.Context , contractAddress sdk.AccAddress , entry types.ContractCodeHistoryEntry ) {
515
+ store := ctx .KVStore (k .storeKey )
516
+ store .Set (types .GetContractByCreatedSecondaryIndexKey (contractAddress , entry ), []byte {})
517
+ }
518
+
519
+ // removeFromContractCodeSecondaryIndex removes element to the index for contracts-by-codeid queries
520
+ func (k Keeper ) removeFromContractCodeSecondaryIndex (ctx sdk.Context , contractAddress sdk.AccAddress , entry types.ContractCodeHistoryEntry ) {
521
+ ctx .KVStore (k .storeKey ).Delete (types .GetContractByCreatedSecondaryIndexKey (contractAddress , entry ))
522
+ }
523
+
524
+ // IterateContractsByCode iterates over all contracts with given codeID ASC on code update time.
525
+ func (k Keeper ) IterateContractsByCode (ctx sdk.Context , codeID uint64 , cb func (address sdk.AccAddress ) bool ) {
526
+ prefixStore := prefix .NewStore (ctx .KVStore (k .storeKey ), types .GetContractByCodeIDSecondaryIndexPrefix (codeID ))
527
+ for iter := prefixStore .Iterator (nil , nil ); iter .Valid (); iter .Next () {
528
+ key := iter .Key ()
529
+ if cb (key [types .AbsoluteTxPositionLen :]) {
530
+ return
531
+ }
532
+ }
512
533
}
513
534
514
535
func (k Keeper ) setContractAdmin (ctx sdk.Context , contractAddress , caller , newAdmin sdk.AccAddress , authZ AuthorizationPolicy ) error {
@@ -552,6 +573,19 @@ func (k Keeper) GetContractHistory(ctx sdk.Context, contractAddr sdk.AccAddress)
552
573
return r
553
574
}
554
575
576
+ // getLastContractHistoryEntry returns the last element from history. To be used internally only as it panics when none exists
577
+ func (k Keeper ) getLastContractHistoryEntry (ctx sdk.Context , contractAddr sdk.AccAddress ) types.ContractCodeHistoryEntry {
578
+ prefixStore := prefix .NewStore (ctx .KVStore (k .storeKey ), types .GetContractCodeHistoryElementPrefix (contractAddr ))
579
+ iter := prefixStore .ReverseIterator (nil , nil )
580
+ var r types.ContractCodeHistoryEntry
581
+ if ! iter .Valid () {
582
+ // all contracts have a history
583
+ panic (fmt .Sprintf ("no history for %s" , contractAddr .String ()))
584
+ }
585
+ k .cdc .MustUnmarshalBinaryBare (iter .Value (), & r )
586
+ return r
587
+ }
588
+
555
589
// QuerySmart queries the smart contract itself.
556
590
func (k Keeper ) QuerySmart (ctx sdk.Context , contractAddr sdk.AccAddress , req []byte ) ([]byte , error ) {
557
591
defer telemetry .MeasureSince (time .Now (), "wasm" , "contract" , "query-smart" )
@@ -623,10 +657,10 @@ func (k Keeper) HasContractInfo(ctx sdk.Context, contractAddress sdk.AccAddress)
623
657
return store .Has (types .GetContractAddressKey (contractAddress ))
624
658
}
625
659
660
+ // storeContractInfo persists the ContractInfo. No secondary index updated here.
626
661
func (k Keeper ) storeContractInfo (ctx sdk.Context , contractAddress sdk.AccAddress , contract * types.ContractInfo ) {
627
662
store := ctx .KVStore (k .storeKey )
628
663
store .Set (types .GetContractAddressKey (contractAddress ), k .cdc .MustMarshalBinaryBare (contract ))
629
- store .Set (types .GetContractByCreatedSecondaryIndexKey (contractAddress , contract ), []byte {})
630
664
}
631
665
632
666
func (k Keeper ) IterateContractInfo (ctx sdk.Context , cb func (sdk.AccAddress , types.ContractInfo ) bool ) {
@@ -1003,6 +1037,7 @@ func (k Keeper) importContract(ctx sdk.Context, contractAddr sdk.AccAddress, c *
1003
1037
historyEntry := c .ResetFromGenesis (ctx )
1004
1038
k .appendToContractHistory (ctx , contractAddr , historyEntry )
1005
1039
k .storeContractInfo (ctx , contractAddr , c )
1040
+ k .addToContractCodeSecondaryIndex (ctx , contractAddr , historyEntry )
1006
1041
return k .importContractState (ctx , contractAddr , state )
1007
1042
}
1008
1043
0 commit comments