Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}