@@ -47,8 +47,11 @@ const (
4747)
4848
4949const (
50- stateKey = "state"
51- swingStoreKeyPrefix = "swingStore."
50+ stateKey = "state"
51+ pendingChunkDataKeyPrefix = "pendingChunkData."
52+ pendingBundleInstallKeyPrefix = "pendingBundleInstall."
53+ pendingNodeKeyPrefix = "pending."
54+ swingStoreKeyPrefix = "swingStore."
5255)
5356
5457// Keeper maintains the link to data vstorage and exposes getter/setter methods for the various parts of the state machine
@@ -485,6 +488,162 @@ func (k Keeper) SetMailbox(ctx sdk.Context, peer string, mailbox string) {
485488 k .vstorageKeeper .LegacySetStorageAndNotify (ctx , agoric .NewKVEntry (path , mailbox ))
486489}
487490
491+ func (k Keeper ) GetPendingChunkData (ctx sdk.Context , pendingId uint64 , chunkIndex uint64 ) []byte {
492+ store := ctx .KVStore (k .storeKey )
493+ pendingChunkData := prefix .NewStore (store , []byte (pendingChunkDataKeyPrefix ))
494+
495+ key := append (sdk .Uint64ToBigEndian (pendingId ), sdk .Uint64ToBigEndian (chunkIndex )... )
496+ if ! pendingChunkData .Has (key ) {
497+ return nil
498+ }
499+ return pendingChunkData .Get (key )
500+ }
501+
502+ func (k Keeper ) SetPendingChunkData (ctx sdk.Context , pendingId uint64 , chunkIndex uint64 , data []byte ) {
503+ store := ctx .KVStore (k .storeKey )
504+ pendingChunkData := prefix .NewStore (store , []byte (pendingChunkDataKeyPrefix ))
505+
506+ key := append (sdk .Uint64ToBigEndian (pendingId ), sdk .Uint64ToBigEndian (chunkIndex )... )
507+ if len (data ) == 0 {
508+ pendingChunkData .Delete (key )
509+ return
510+ }
511+ pendingChunkData .Set (key , data )
512+ }
513+
514+ func (k Keeper ) GetPendingBundleInstall (ctx sdk.Context , pendingId uint64 ) * types.MsgInstallBundle {
515+ store := ctx .KVStore (k .storeKey )
516+ pendingStore := prefix .NewStore (store , []byte (pendingBundleInstallKeyPrefix ))
517+ key := sdk .Uint64ToBigEndian (pendingId )
518+ if ! pendingStore .Has (key ) {
519+ return nil
520+ }
521+ bz := pendingStore .Get (key )
522+ msg := & types.MsgInstallBundle {}
523+ k .cdc .MustUnmarshal (bz , msg )
524+ return msg
525+ }
526+
527+ func (k Keeper ) AddPendingBundleInstall (ctx sdk.Context , msg * types.MsgInstallBundle ) uint64 {
528+ state := k .GetState (ctx )
529+ state .LastPendingId ++
530+ k .SetState (ctx , state )
531+
532+ pendingId := state .LastPendingId
533+ k .SetPendingBundleInstall (ctx , pendingId , msg )
534+
535+ // Attach the pending install node to the linked list.
536+ node := & types.PendingInstallNode {
537+ PendingId : pendingId ,
538+ StartTime : ctx .BlockTime ().Unix (),
539+ StartBlock : ctx .BlockHeight (),
540+ }
541+ store := ctx .KVStore (k .storeKey )
542+ key := sdk .Uint64ToBigEndian (pendingId )
543+ startStore := prefix .NewStore (store , []byte (pendingNodeKeyPrefix ))
544+ bz := k .cdc .MustMarshal (node )
545+ startStore .Set (key , bz )
546+
547+ return pendingId
548+ }
549+
550+ // PruneExpiredBundleInstalls removes pending bundle installs that have passed
551+ // their deadline, as set by the keeper parameters.
552+ func (k Keeper ) PruneExpiredBundleInstalls (ctx sdk.Context ) {
553+ params := k .GetParams (ctx )
554+ currentSeconds := ctx .BlockTime ().Unix ()
555+ currentBlocks := ctx .BlockHeight ()
556+ deadlineSeconds := params .PendingInstallationDeadlineSeconds
557+ deadlineBlocks := params .PendingInstallationDeadlineBlocks
558+
559+ store := ctx .KVStore (k .storeKey )
560+ startStore := prefix .NewStore (store , []byte (pendingNodeKeyPrefix ))
561+
562+ state := k .GetState (ctx )
563+ for state .FirstPendingId != 0 {
564+ pendingId := state .FirstPendingId
565+ key := sdk .Uint64ToBigEndian (pendingId )
566+ bz := startStore .Get (key )
567+ node := & types.PendingInstallNode {}
568+ k .cdc .MustUnmarshal (bz , node )
569+
570+ if deadlineSeconds < 0 || currentSeconds - node .StartTime < deadlineSeconds {
571+ if deadlineBlocks < 0 || currentBlocks - node .StartBlock < deadlineBlocks {
572+ // Still alive. Stop the search.
573+ break
574+ }
575+ }
576+
577+ // This pending bundle install is dead. Remove it.
578+ k .SetPendingBundleInstall (ctx , pendingId , nil )
579+
580+ // Advance to the next node.
581+ state .FirstPendingId = node .NextId
582+ }
583+
584+ k .SetState (ctx , state )
585+ }
586+
587+ func (k Keeper ) makeListTools (ctx sdk.Context ) * types.ListTools {
588+ store := ctx .KVStore (k .storeKey )
589+ listStore := prefix .NewStore (store , []byte (pendingNodeKeyPrefix ))
590+ return types .NewListTools (ctx , listStore , k .cdc )
591+ }
592+
593+ func (k Keeper ) SetPendingBundleInstall (ctx sdk.Context , pendingId uint64 , newMsg * types.MsgInstallBundle ) {
594+ store := ctx .KVStore (k .storeKey )
595+ pendingStore := prefix .NewStore (store , []byte (pendingBundleInstallKeyPrefix ))
596+
597+ key := sdk .Uint64ToBigEndian (pendingId )
598+ if newMsg != nil {
599+ bz := k .cdc .MustMarshal (newMsg )
600+ pendingStore .Set (key , bz )
601+ return
602+ }
603+
604+ var msg types.MsgInstallBundle
605+ k .cdc .MustUnmarshal (pendingStore .Get (key ), & msg )
606+ if msg .BundleChunks != nil && len (msg .BundleChunks .Chunks ) > 0 {
607+ // Remove the chunks.
608+ for i := range msg .BundleChunks .Chunks {
609+ k .SetPendingChunkData (ctx , pendingId , uint64 (i ), nil )
610+ }
611+ }
612+ pendingStore .Delete (key )
613+
614+ // Remove auxilliary data structure entries.
615+ k .RemovePendingInstallNode (ctx , pendingId )
616+ }
617+
618+ // RemovePendingInstallNode removes this pending install from the keeper's
619+ // ordered linked list structures, and deletes it from the store.
620+ func (k Keeper ) RemovePendingInstallNode (ctx sdk.Context , pendingId uint64 ) {
621+ lt := k .makeListTools (ctx )
622+
623+ victimKey := lt .Key (pendingId )
624+ victimNode := lt .Fetch (victimKey )
625+
626+ // Remove the victim from the linked list, keeping the structure intact.
627+ lt .Unlink (victimNode , func (firstp , lastp * uint64 ) {
628+ state := k .GetState (ctx )
629+ if firstp != nil {
630+ state .FirstPendingId = * firstp
631+ }
632+ if lastp != nil {
633+ state .LastPendingId = * lastp
634+ }
635+ k .SetState (ctx , state )
636+ })
637+
638+ // Finally, delete the victim node's storage.
639+ lt .Delete (victimKey )
640+ }
641+
642+ func (k Keeper ) GetPendingInstallNode (ctx sdk.Context , pendingId uint64 ) * types.PendingInstallNode {
643+ lt := k .makeListTools (ctx )
644+ return lt .Fetch (lt .Key (pendingId ))
645+ }
646+
488647func (k Keeper ) GetSwingStore (ctx sdk.Context ) sdk.KVStore {
489648 store := ctx .KVStore (k .storeKey )
490649 return prefix .NewStore (store , []byte (swingStoreKeyPrefix ))
0 commit comments