msgs.gno
4.30 Kb · 175 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 if len(msg.Payloads) == 0 {
42 return ufmt.Errorf("payload length must be greater than 0")
43 }
44
45 for i, pd := range msg.Payloads {
46 if err := pd.ValidateBasic(); err != nil {
47 return ufmt.Errorf("invalid payload #%d: %v", i, err)
48 }
49 }
50 return nil
51}
52
53// MsgRecvPacket receives an incoming IBC packet.
54type MsgRecvPacket struct {
55 Packet Packet
56 ProofCommitment []ics23.CommitmentProof
57 ProofHeight Height
58}
59
60// ValidateBasic performs basic checks on a MsgRecvPacket.
61func (msg *MsgRecvPacket) ValidateBasic() error {
62 if len(msg.ProofCommitment) == 0 {
63 return ufmt.Errorf("proof commitment can not be empty")
64 }
65 return msg.Packet.ValidateBasic()
66}
67
68// MsgAcknowledgement receives incoming IBC acknowledgement.
69type MsgAcknowledgement struct {
70 Packet Packet
71 Acknowledgement Acknowledgement
72 ProofAcked []ics23.CommitmentProof
73 ProofHeight Height
74}
75
76// ValidateBasic performs basic checks on a MsgAcknowledgement.
77func (msg *MsgAcknowledgement) ValidateBasic() error {
78 if len(msg.ProofAcked) == 0 {
79 return errors.New("cannot submit an empty acknowledgement proof")
80 }
81 for i, proof := range msg.ProofAcked {
82 if proof.GetExist() == nil {
83 return ufmt.Errorf("invalid commitment proof #%d: proof.GetExists() is nil", i)
84 }
85 }
86
87 if err := msg.Acknowledgement.Validate(); err != nil {
88 return err
89 }
90
91 return msg.Packet.ValidateBasic()
92}
93
94func UniversalErrorAcknowledgement() []byte {
95 bz := sha256.Sum256([]byte("UNIVERSAL_ERROR_ACKNOWLEDGEMENT"))
96 return bz[:]
97}
98
99// AppAcknowledgement is the recommended acknowledgement format to be used by
100// app-specific protocols.
101type AppAcknowledgement struct {
102 Response AppAcknowledgementResponse
103}
104
105type AppAcknowledgementResponse struct {
106 Result []byte
107 Error string
108}
109
110func NewErrorAppAcknowledgement(err error) AppAcknowledgement {
111 return AppAcknowledgement{Response: AppAcknowledgementResponse{Error: err.Error()}}
112}
113
114func NewResultAppAcknowledgement(result []byte) AppAcknowledgement {
115 return AppAcknowledgement{
116 Response: AppAcknowledgementResponse{
117 Result: result,
118 },
119 }
120}
121
122func (a AppAcknowledgement) Success() bool {
123 return a.Response.Error == ""
124}
125
126func (a *AppAcknowledgement) MarshalJSON() []byte {
127 var node *json.Node
128 if a.Response.Error != "" {
129 node = json.ObjectNode("", map[string]*json.Node{
130 "error": json.StringNode("", a.Response.Error),
131 })
132 } else {
133 node = json.ObjectNode("", map[string]*json.Node{
134 "result": json.StringNode("", base64.StdEncoding.EncodeToString(a.Response.Result)),
135 })
136 }
137 bz, _ := json.Marshal(node)
138 return bz
139}
140
141func (a *AppAcknowledgement) UnmarshalJSON(bz []byte) error {
142 root, err := json.Unmarshal(bz)
143 if err != nil {
144 return err
145 }
146 result, err := root.GetKey("result")
147 if err != nil {
148 rerror, err := root.GetKey("error")
149 if err != nil {
150 return err
151 }
152 a.Response = AppAcknowledgementResponse{Error: rerror.MustString()}
153 return nil
154 }
155 resBz, err := base64.StdEncoding.DecodeString(result.MustString())
156 if err != nil {
157 return err
158 }
159 a.Response = AppAcknowledgementResponse{Result: resBz}
160 return nil
161}
162
163// MsgTimeout receives timed-out packet
164type MsgTimeout struct {
165 Packet Packet
166 ProofUnreceived []ics23.CommitmentProof
167 ProofHeight Height
168}
169
170func (msg *MsgTimeout) ValidateBasic() error {
171 if len(msg.ProofUnreceived) == 0 {
172 return errors.New("cannot submit an empty timeout proof")
173 }
174 return msg.Packet.ValidateBasic()
175}