-
Notifications
You must be signed in to change notification settings - Fork 108
/
ordered_outbox.go
114 lines (104 loc) · 3.88 KB
/
ordered_outbox.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package simibc
import channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
// Ack represents a (sent) ack committed to block state
type Ack struct {
Ack []byte
// The packet to which this ack is a response
Packet channeltypes.Packet
// The number of App.Commits that have occurred since this ack was sent
// For example, if the ack was sent at height h, and the blockchain
// has headers ..., h, h+1, h+2 then Commits = 3
Commits int
}
// Packet represents a (sent) packet committed to block state
type Packet struct {
Packet channeltypes.Packet
// The number of App.Commits that have occurred since this packet was sent
// For example, if the ack was sent at height h, and the blockchain
// has headers ..., h, h+1, h+2 then Commits = 3
Commits int
}
// OrderedOutbox is a collection of ORDERED packets and acks that have been sent
// by different chains, but have not yet been delivered to their target.
// The methods take care of bookkeeping, making it easier to simulate
// a real relayed IBC connection.
//
// Each sent packet or ack can be added here. When a sufficient number of
// block commits have followed each sent packet or ack, they can be consumed:
// delivered to their target. Since the sequences are ordered, this is useful
// for testing ORDERED ibc channels.
//
// NOTE: OrderedOutbox MAY be used independently of the rest of simibc.
type OrderedOutbox struct {
// An ordered sequence of packets from each sender
OutboxPackets map[string][]Packet
// An ordered sequence of acks from each sender
OutboxAcks map[string][]Ack
}
// MakeOrderedOutbox creates a new empty OrderedOutbox.
func MakeOrderedOutbox() OrderedOutbox {
return OrderedOutbox{
OutboxPackets: map[string][]Packet{},
OutboxAcks: map[string][]Ack{},
}
}
// AddPacket adds an outbound packet from the sender.
func (n OrderedOutbox) AddPacket(sender string, packet channeltypes.Packet) {
n.OutboxPackets[sender] = append(n.OutboxPackets[sender], Packet{packet, 0})
}
// AddAck adds an outbound ack from the sender. The ack is a response to the packet.
func (n OrderedOutbox) AddAck(sender string, ack []byte, packet channeltypes.Packet) {
n.OutboxAcks[sender] = append(n.OutboxAcks[sender], Ack{ack, packet, 0})
}
// ConsumePackets returns the first num packets with 2 or more commits. Returned
// packets are removed from the outbox and will not be returned again (consumed).
func (n OrderedOutbox) ConsumePackets(sender string, num int) []Packet {
ret := []Packet{}
sz := len(n.OutboxPackets[sender])
if sz < num {
num = sz
}
for _, p := range n.OutboxPackets[sender][:num] {
if 1 < p.Commits {
ret = append(ret, p)
} else {
break
}
}
n.OutboxPackets[sender] = n.OutboxPackets[sender][len(ret):]
return ret
}
// ConsumerAcks returns the first num packets with 2 or more commits. Returned
// acks are removed from the outbox and will not be returned again (consumed).
func (n OrderedOutbox) ConsumeAcks(sender string, num int) []Ack {
ret := []Ack{}
sz := len(n.OutboxAcks[sender])
if sz < num {
num = sz
}
for _, a := range n.OutboxAcks[sender][:num] {
if 1 < a.Commits {
ret = append(ret, a)
} else {
break
}
}
n.OutboxAcks[sender] = n.OutboxAcks[sender][len(ret):]
return ret
}
// Commit marks a block commit, increasing the commit count for all
// packets and acks in the sender's outbox.
// When a packet or ack has 2 or more commits, it is available for
// delivery to the counterparty chain.
// Note that 2 commits are necessary instead of 1:
// - 1st commit is necessary for the packet to included in the block
// - 2nd commit is necessary because in practice the ibc light client
// needs to have block h + 1 to be able to verify the packet in block h.
func (n OrderedOutbox) Commit(sender string) {
for i := range n.OutboxPackets[sender] {
n.OutboxPackets[sender][i].Commits += 1
}
for i := range n.OutboxAcks[sender] {
n.OutboxAcks[sender][i].Commits += 1
}
}