msgs.gno
4.37 Kb · 176 lines
1package types
2
3import (
4 "crypto/sha256"
5 "encoding/base64"
6 "errors"
7
8 "gno.land/p/aib/ibc/host"
9 "gno.land/p/aib/ics23"
10 "gno.land/p/nt/ufmt/v0"
11 "gno.land/p/onbloc/json"
12)
13
14// MsgSendPacket sends an outgoing IBC packet.
15type MsgSendPacket struct {
16 SourceClient string
17 // TimeoutTimestamp holds the seconds after which the packet times out.
18 TimeoutTimestamp uint64
19 Payloads []Payload
20}
21
22// NewMsgSendPacket creates a new MsgSendPacket instance.
23func NewMsgSendPacket(sourceClient string, timeoutTimestamp uint64, payloads ...Payload) *MsgSendPacket {
24 return &MsgSendPacket{
25 SourceClient: sourceClient,
26 TimeoutTimestamp: timeoutTimestamp,
27 Payloads: payloads,
28 }
29}
30
31// ValidateBasic performs basic checks on a MsgSendPacket.
32func (msg *MsgSendPacket) ValidateBasic() error {
33 if err := host.ClientIdentifierValidator(msg.SourceClient); err != nil {
34 return err
35 }
36
37 if msg.TimeoutTimestamp == 0 {
38 return ufmt.Errorf("timeout must not be 0")
39 }
40
41 // See Packet.ValidateBasic: multi-payload packets are not supported.
42 if len(msg.Payloads) != 1 {
43 return ufmt.Errorf("payloads must contain exactly one payload")
44 }
45
46 for i, pd := range msg.Payloads {
47 if err := pd.ValidateBasic(); err != nil {
48 return ufmt.Errorf("invalid payload #%d: %v", i, err)
49 }
50 }
51 return nil
52}
53
54// MsgRecvPacket receives an incoming IBC packet.
55type MsgRecvPacket struct {
56 Packet Packet
57 ProofCommitment []ics23.CommitmentProof
58 ProofHeight Height
59}
60
61// ValidateBasic performs basic checks on a MsgRecvPacket.
62func (msg *MsgRecvPacket) ValidateBasic() error {
63 if len(msg.ProofCommitment) == 0 {
64 return ufmt.Errorf("proof commitment can not be empty")
65 }
66 return msg.Packet.ValidateBasic()
67}
68
69// MsgAcknowledgement receives incoming IBC acknowledgement.
70type MsgAcknowledgement struct {
71 Packet Packet
72 Acknowledgement Acknowledgement
73 ProofAcked []ics23.CommitmentProof
74 ProofHeight Height
75}
76
77// ValidateBasic performs basic checks on a MsgAcknowledgement.
78func (msg *MsgAcknowledgement) ValidateBasic() error {
79 if len(msg.ProofAcked) == 0 {
80 return errors.New("cannot submit an empty acknowledgement proof")
81 }
82 for i, proof := range msg.ProofAcked {
83 if proof.GetExist() == nil {
84 return ufmt.Errorf("invalid commitment proof #%d: proof.GetExists() is nil", i)
85 }
86 }
87
88 if err := msg.Acknowledgement.Validate(); err != nil {
89 return err
90 }
91
92 return msg.Packet.ValidateBasic()
93}
94
95func UniversalErrorAcknowledgement() []byte {
96 bz := sha256.Sum256([]byte("UNIVERSAL_ERROR_ACKNOWLEDGEMENT"))
97 return bz[:]
98}
99
100// AppAcknowledgement is the recommended acknowledgement format to be used by
101// app-specific protocols.
102type AppAcknowledgement struct {
103 Response AppAcknowledgementResponse
104}
105
106type AppAcknowledgementResponse struct {
107 Result []byte
108 Error string
109}
110
111func NewErrorAppAcknowledgement(err error) AppAcknowledgement {
112 return AppAcknowledgement{Response: AppAcknowledgementResponse{Error: err.Error()}}
113}
114
115func NewResultAppAcknowledgement(result []byte) AppAcknowledgement {
116 return AppAcknowledgement{
117 Response: AppAcknowledgementResponse{
118 Result: result,
119 },
120 }
121}
122
123func (a AppAcknowledgement) Success() bool {
124 return a.Response.Error == ""
125}
126
127func (a *AppAcknowledgement) MarshalJSON() []byte {
128 var node *json.Node
129 if a.Response.Error != "" {
130 node = json.ObjectNode("", map[string]*json.Node{
131 "error": json.StringNode("", a.Response.Error),
132 })
133 } else {
134 node = json.ObjectNode("", map[string]*json.Node{
135 "result": json.StringNode("", base64.StdEncoding.EncodeToString(a.Response.Result)),
136 })
137 }
138 bz, _ := json.Marshal(node)
139 return bz
140}
141
142func (a *AppAcknowledgement) UnmarshalJSON(bz []byte) error {
143 root, err := json.Unmarshal(bz)
144 if err != nil {
145 return err
146 }
147 result, err := root.GetKey("result")
148 if err != nil {
149 rerror, err := root.GetKey("error")
150 if err != nil {
151 return err
152 }
153 a.Response = AppAcknowledgementResponse{Error: rerror.MustString()}
154 return nil
155 }
156 resBz, err := base64.StdEncoding.DecodeString(result.MustString())
157 if err != nil {
158 return err
159 }
160 a.Response = AppAcknowledgementResponse{Result: resBz}
161 return nil
162}
163
164// MsgTimeout receives timed-out packet
165type MsgTimeout struct {
166 Packet Packet
167 ProofUnreceived []ics23.CommitmentProof
168 ProofHeight Height
169}
170
171func (msg *MsgTimeout) ValidateBasic() error {
172 if len(msg.ProofUnreceived) == 0 {
173 return errors.New("cannot submit an empty timeout proof")
174 }
175 return msg.Packet.ValidateBasic()
176}