-
Notifications
You must be signed in to change notification settings - Fork 122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat!: optimize pending packets storage on consumer + migration #1037
Changes from 4 commits
5bb3e14
6b6eabe
84e0250
0eafb05
1af896f
cf2359d
1c7e7df
84d4a75
98dd226
35a464b
d4393e9
18f852a
0e1bd28
9737d0f
189c1da
1c33106
394f709
a42229a
05acaba
d918fb4
f517201
e3f2133
747e8aa
d84b29d
8084b49
ab23828
98c64d4
db04b8f
e6f696e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,9 +89,12 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state *consumertypes.GenesisState) | |
k.SetLastTransmissionBlockHeight(ctx, state.LastTransmissionBlockHeight) | ||
} | ||
|
||
// set pending consumer pending packets | ||
// Set pending consumer packets, using the depreciated ConsumerPacketDataList type | ||
// that exists for genesis. | ||
// note that the list includes pending mature VSC packet only if the handshake is completed | ||
k.AppendPendingPacket(ctx, state.PendingConsumerPackets.List...) | ||
for _, packet := range state.PendingConsumerPackets.List { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Genesis methods still expect the depreciated type There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my comment on ccv.proto |
||
k.AppendPendingPacket(ctx, packet.Type, packet.Data) | ||
} | ||
|
||
// set height to valset update id mapping | ||
for _, h2v := range state.HeightToValsetUpdateId { | ||
|
@@ -122,6 +125,11 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt | |
// export the current validator set | ||
valset := k.MustGetCurrentValidatorsAsABCIUpdates(ctx) | ||
|
||
// export pending packets using the depreciated ConsumerPacketDataList type | ||
pendingPackets := k.GetPendingPackets(ctx) | ||
pendingPacketsDepreciated := ccv.ConsumerPacketDataList{} | ||
pendingPacketsDepreciated.List = append(pendingPacketsDepreciated.List, pendingPackets...) | ||
|
||
// export all the states created after a provider channel got established | ||
if channelID, ok := k.GetProviderChannel(ctx); ok { | ||
clientID, found := k.GetProviderClientID(ctx) | ||
|
@@ -136,7 +144,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt | |
k.GetAllPacketMaturityTimes(ctx), | ||
valset, | ||
k.GetAllHeightToValsetUpdateIDs(ctx), | ||
k.GetPendingPackets(ctx), | ||
pendingPacketsDepreciated, | ||
k.GetAllOutstandingDowntimes(ctx), | ||
k.GetLastTransmissionBlockHeight(ctx), | ||
params, | ||
|
@@ -156,7 +164,7 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) (genesis *consumertypes.GenesisSt | |
nil, | ||
valset, | ||
k.GetAllHeightToValsetUpdateIDs(ctx), | ||
k.GetPendingPackets(ctx), | ||
pendingPacketsDepreciated, | ||
nil, | ||
consumertypes.LastTransmissionBlockHeight{}, | ||
params, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -565,48 +565,78 @@ func (k Keeper) GetAllCCValidator(ctx sdk.Context) (validators []types.CrossChai | |
return validators | ||
} | ||
|
||
// SetPendingPackets sets the pending CCV packets | ||
func (k Keeper) SetPendingPackets(ctx sdk.Context, packets ccv.ConsumerPacketDataList) { | ||
store := ctx.KVStore(k.storeKey) | ||
bz, err := packets.Marshal() | ||
if err != nil { | ||
// This should never happen | ||
panic(fmt.Errorf("failed to marshal ConsumerPacketDataList: %w", err)) | ||
} | ||
store.Set(types.PendingDataPacketsKey(), bz) | ||
// Note: PendingDataPacketsBytePrefix is the correct prefix, NOT PendingDataPacketsByteKey. | ||
// See consistency with PendingDataPacketsKey(). | ||
shaspitz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
func PendingDataPacketsIterator(store sdk.KVStore) sdk.Iterator { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The meat of this PR is in this file |
||
return sdk.KVStorePrefixIterator(store, []byte{types.PendingDataPacketsBytePrefix}) | ||
} | ||
|
||
// GetPendingPackets returns the pending CCV packets from the store | ||
func (k Keeper) GetPendingPackets(ctx sdk.Context) ccv.ConsumerPacketDataList { | ||
var packets ccv.ConsumerPacketDataList | ||
|
||
func (k Keeper) getAndIncrementPendingPacketsIdx(ctx sdk.Context) (toReturn uint64) { | ||
store := ctx.KVStore(k.storeKey) | ||
bz := store.Get(types.PendingDataPacketsKey()) | ||
bz := store.Get(types.PendingPacketsIndexKey()) | ||
if bz == nil { | ||
return packets | ||
toReturn = 0 | ||
} else { | ||
toReturn = binary.BigEndian.Uint64(bz) | ||
shaspitz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
toStore := toReturn + 1 | ||
store.Set(types.PendingPacketsIndexKey(), sdk.Uint64ToBigEndian(toStore)) | ||
return toReturn | ||
} | ||
|
||
err := packets.Unmarshal(bz) | ||
if err != nil { | ||
// An error here would indicate something is very wrong, | ||
// the PendingPackets are assumed to be correctly serialized in SetPendingPackets. | ||
panic(fmt.Errorf("failed to unmarshal pending data packets: %w", err)) | ||
// GetPendingPackets returns ALL the pending CCV packets from the store | ||
func (k Keeper) GetPendingPackets(ctx sdk.Context) []ccv.ConsumerPacketData { | ||
var packets []ccv.ConsumerPacketData | ||
store := ctx.KVStore(k.storeKey) | ||
iterator := PendingDataPacketsIterator(store) | ||
shaspitz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer iterator.Close() | ||
for ; iterator.Valid(); iterator.Next() { | ||
var packet ccv.ConsumerPacketData | ||
bz := iterator.Value() | ||
err := packet.Unmarshal(bz) | ||
if err != nil { | ||
// An error here would indicate something is very wrong, | ||
panic(fmt.Errorf("failed to unmarshal pending data packet: %w", err)) | ||
} | ||
packets = append(packets, packet) | ||
} | ||
|
||
return packets | ||
} | ||
|
||
// DeletePendingDataPackets clears the pending data packets in store | ||
func (k Keeper) DeletePendingDataPackets(ctx sdk.Context) { | ||
// DeletePendingDataPackets deletes pending data packets with given indexes | ||
func (k Keeper) DeletePendingDataPackets(ctx sdk.Context, idxs ...uint64) { | ||
store := ctx.KVStore(k.storeKey) | ||
for _, idx := range idxs { | ||
store.Delete(types.PendingDataPacketsKey(idx)) | ||
} | ||
} | ||
|
||
func (k Keeper) DeleteAllPendingDataPackets(ctx sdk.Context) { | ||
shaspitz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
store := ctx.KVStore(k.storeKey) | ||
store.Delete(types.PendingDataPacketsKey()) | ||
// Note: PendingDataPacketsBytePrefix is the correct prefix, NOT PendingDataPacketsByteKey. | ||
// See consistency with PendingDataPacketsKey(). | ||
iterator := PendingDataPacketsIterator(store) | ||
shaspitz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
defer iterator.Close() | ||
for ; iterator.Valid(); iterator.Next() { | ||
store.Delete(iterator.Key()) | ||
} | ||
} | ||
|
||
// AppendPendingDataPacket appends the given data packet to the pending data packets in store | ||
func (k Keeper) AppendPendingPacket(ctx sdk.Context, packet ...ccv.ConsumerPacketData) { | ||
pending := k.GetPendingPackets(ctx) | ||
list := append(pending.GetList(), packet...) | ||
k.SetPendingPackets(ctx, ccv.ConsumerPacketDataList{List: list}) | ||
// AppendPendingPacket enqueues the given data packet to the end of the pending data packets queue | ||
func (k Keeper) AppendPendingPacket(ctx sdk.Context, packetType ccv.ConsumerPacketDataType, data ccv.ExportedIsConsumerPacketData_Data) { | ||
cpd := ccv.NewConsumerPacketData( | ||
packetType, | ||
data, | ||
k.getAndIncrementPendingPacketsIdx(ctx), | ||
) | ||
key := types.PendingDataPacketsKey(cpd.Idx) | ||
store := ctx.KVStore(k.storeKey) | ||
bz, err := cpd.Marshal() | ||
if err != nil { | ||
// This should never happen | ||
panic(fmt.Errorf("failed to marshal ConsumerPacketData: %w", err)) | ||
} | ||
store.Set(key, bz) | ||
} | ||
|
||
func (k Keeper) MarkAsPrevStandaloneChain(ctx sdk.Context) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra care should be taken in reviewing this PR, as it does mutate a proto file. Note this index field was added to the
ConsumerPacketData
type so that we can use that index inPendingDataPacketsKey
, to implement a queue with constant append time. SeeAppendPendingPacket