Skip to content

Commit

Permalink
handle vsc matured acks
Browse files Browse the repository at this point in the history
  • Loading branch information
shaspitz committed Jul 14, 2023
1 parent 0e1df65 commit 46d49e1
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 19 deletions.
29 changes: 17 additions & 12 deletions x/ccv/consumer/keeper/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,26 +239,31 @@ func (k Keeper) OnAcknowledgementPacket(ctx sdk.Context, packet channeltypes.Pac
if len(res) != 1 {
k.Logger(ctx).Error("recv invalid ack; expected length 1", "channel", packet.SourceChannel, "ack", res)
}

// Unmarshal into V1 consumer packet data type. We trust data is formed correctly
// as it was originally marshalled by this module, and consumers must trust the provider
// did not tamper with the data. Note ConsumerPacketData.GetBytes() always JSON marshals to the
// ConsumerPacketDataV1 type which is sent over the wire.
var consumerPacket ccv.ConsumerPacketDataV1
ccv.ModuleCdc.MustUnmarshalJSON(packet.GetData(), &consumerPacket)
// If this ack is regarding a provider handling a vsc matured packet, there's nothing to do.
// As vsc matured packets are popped from the consumer pending packets queue on send.
if consumerPacket.Type == ccv.VscMaturedPacket {
return nil
}

// Otherwise we handle the result of the slash packet acknowledgement.
switch res[0] {
// We treat a v1 result as the provider successfully queuing the slash packet w/o need for retry.
case ccv.V1Result[0]:
// If slash record is found, slash packet is at head of queue.
// But provider is running v1 throttling and has queued the slash packet itself.
// Therefore we can clear the slash record and delete the slash packet from the queue, unblocking packet sending.
// TODO: tests for this scenario with vsc matured.
_, found := k.GetSlashRecord(ctx)
if found {
k.ClearSlashRecord(ctx)
k.DeleteHeadOfPendingPackets(ctx)
}
k.Logger(ctx).Info("recv no-op ack", "channel", packet.SourceChannel, "ack", res)
k.ClearSlashRecord(ctx) // Clears slash record state, unblocks sending of pending packets.
k.DeleteHeadOfPendingPackets(ctx) // Remove slash from head of queue. It's been handled.
case ccv.SlashPacketHandledResult[0]:
k.ClearSlashRecord(ctx) // Clears slash record state, unblocks sending of pending packets.
k.DeleteHeadOfPendingPackets(ctx) // Remove slash from head of queue. It's been handled.
case ccv.SlashPacketBouncedResult[0]:
k.UpdateSlashRecordOnBounce(ctx)
// Note slash is still at head of queue and will now be retried after appropriate delay period.
case ccv.VSCMaturedPacketHandledResult[0]:
// VSC matured are deleted upon sending, nothing to do here.
default:
k.Logger(ctx).Error("recv invalid result ack; expected 1, 2, or 3", "channel", packet.SourceChannel, "ack", res)
}
Expand Down
11 changes: 8 additions & 3 deletions x/ccv/consumer/keeper/relay_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,18 +381,19 @@ func TestOnAcknowledgementPacketResult(t *testing.T) {
// Setup
consumerKeeper, ctx, ctrl, _ := testkeeper.GetConsumerKeeperAndCtx(t, testkeeper.NewInMemKeeperParams(t))
defer ctrl.Finish()
packet := channeltypes.Packet{}

setupSlashBeforeVscMatured(ctx, &consumerKeeper)

// Slash record found, 2 pending packets, slash is at head of queue
_, found := consumerKeeper.GetSlashRecord(ctx)
require.True(t, found)
require.Len(t, consumerKeeper.GetPendingPackets(ctx), 2)
require.Equal(t, types.SlashPacket, consumerKeeper.GetPendingPackets(ctx)[0].Type)
pendingPackets := consumerKeeper.GetPendingPackets(ctx)
require.Len(t, pendingPackets, 2)
require.Equal(t, types.SlashPacket, pendingPackets[0].Type)

// v1 result should delete slash record and head of pending packets. Vsc matured remains
ack := channeltypes.NewResultAcknowledgement(types.V1Result)
packet := channeltypes.Packet{Data: pendingPackets[0].GetBytes()}
err := consumerKeeper.OnAcknowledgementPacket(ctx, packet, ack)
require.Nil(t, err)
_, found = consumerKeeper.GetSlashRecord(ctx)
Expand All @@ -402,6 +403,8 @@ func TestOnAcknowledgementPacketResult(t *testing.T) {

// refresh state
setupSlashBeforeVscMatured(ctx, &consumerKeeper)
pendingPackets = consumerKeeper.GetPendingPackets(ctx)
packet = channeltypes.Packet{Data: pendingPackets[0].GetBytes()}

// Slash packet handled result should delete slash record and head of pending packets
ack = channeltypes.NewResultAcknowledgement(types.SlashPacketHandledResult)
Expand All @@ -414,6 +417,8 @@ func TestOnAcknowledgementPacketResult(t *testing.T) {

// refresh state
setupSlashBeforeVscMatured(ctx, &consumerKeeper)
pendingPackets = consumerKeeper.GetPendingPackets(ctx)
packet = channeltypes.Packet{Data: pendingPackets[0].GetBytes()}

slashRecordBefore, found := consumerKeeper.GetSlashRecord(ctx)
require.True(t, found)
Expand Down
5 changes: 1 addition & 4 deletions x/ccv/types/ccv.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,16 +170,13 @@ type PacketAckResult []byte
var ( // slice types can't be const

// The result ack that has historically been sent from the provider.
// A provider with v1 throttling sends these acks for both slash and vsc matured packets.
// A provider with v1 throttling sends these acks for all successfully recv packets.
V1Result = PacketAckResult([]byte{byte(1)})
// Slash packet handled result ack, sent by a throttling v2 provider to indicate that a slash packet was handled.
SlashPacketHandledResult = PacketAckResult([]byte{byte(2)})
// Slash packet bounced result ack, sent by a throttling v2 provider to indicate that a slash packet was NOT handled
// and should eventually be retried.
SlashPacketBouncedResult = PacketAckResult([]byte{byte(3)})
// VSC matured packet handled result ack, sent by a throttling v2 provider
// to indicate that a vsc matured packet was handled.
VSCMaturedPacketHandledResult = PacketAckResult([]byte{byte(4)})
)

// An exported wrapper around the auto generated isConsumerPacketData_Data interface, only for
Expand Down

0 comments on commit 46d49e1

Please sign in to comment.