package types import ( "crypto/sha256" "encoding/base64" "errors" "gno.land/p/aib/ibc/host" "gno.land/p/aib/ics23" "gno.land/p/nt/ufmt/v0" "gno.land/p/onbloc/json" ) // MsgSendPacket sends an outgoing IBC packet. type MsgSendPacket struct { SourceClient string // TimeoutTimestamp holds the seconds after which the packet times out. TimeoutTimestamp uint64 Payloads []Payload } // NewMsgSendPacket creates a new MsgSendPacket instance. func NewMsgSendPacket(sourceClient string, timeoutTimestamp uint64, payloads ...Payload) *MsgSendPacket { return &MsgSendPacket{ SourceClient: sourceClient, TimeoutTimestamp: timeoutTimestamp, Payloads: payloads, } } // ValidateBasic performs basic checks on a MsgSendPacket. func (msg *MsgSendPacket) ValidateBasic() error { if err := host.ClientIdentifierValidator(msg.SourceClient); err != nil { return err } if msg.TimeoutTimestamp == 0 { return ufmt.Errorf("timeout must not be 0") } if len(msg.Payloads) == 0 { return ufmt.Errorf("payload length must be greater than 0") } for i, pd := range msg.Payloads { if err := pd.ValidateBasic(); err != nil { return ufmt.Errorf("invalid payload #%d: %v", i, err) } } return nil } // MsgRecvPacket receives an incoming IBC packet. type MsgRecvPacket struct { Packet Packet ProofCommitment []ics23.CommitmentProof ProofHeight Height } // ValidateBasic performs basic checks on a MsgRecvPacket. func (msg *MsgRecvPacket) ValidateBasic() error { if len(msg.ProofCommitment) == 0 { return ufmt.Errorf("proof commitment can not be empty") } return msg.Packet.ValidateBasic() } // MsgAcknowledgement receives incoming IBC acknowledgement. type MsgAcknowledgement struct { Packet Packet Acknowledgement Acknowledgement ProofAcked []ics23.CommitmentProof ProofHeight Height } // ValidateBasic performs basic checks on a MsgAcknowledgement. func (msg *MsgAcknowledgement) ValidateBasic() error { if len(msg.ProofAcked) == 0 { return errors.New("cannot submit an empty acknowledgement proof") } for i, proof := range msg.ProofAcked { if proof.GetExist() == nil { return ufmt.Errorf("invalid commitment proof #%d: proof.GetExists() is nil", i) } } if err := msg.Acknowledgement.Validate(); err != nil { return err } return msg.Packet.ValidateBasic() } func UniversalErrorAcknowledgement() []byte { bz := sha256.Sum256([]byte("UNIVERSAL_ERROR_ACKNOWLEDGEMENT")) return bz[:] } // AppAcknowledgement is the recommended acknowledgement format to be used by // app-specific protocols. type AppAcknowledgement struct { Response AppAcknowledgementResponse } type AppAcknowledgementResponse struct { Result []byte Error string } func NewErrorAppAcknowledgement(err error) AppAcknowledgement { return AppAcknowledgement{Response: AppAcknowledgementResponse{Error: err.Error()}} } func NewResultAppAcknowledgement(result []byte) AppAcknowledgement { return AppAcknowledgement{ Response: AppAcknowledgementResponse{ Result: result, }, } } func (a AppAcknowledgement) Success() bool { return a.Response.Error == "" } func (a *AppAcknowledgement) MarshalJSON() []byte { var node *json.Node if a.Response.Error != "" { node = json.ObjectNode("", map[string]*json.Node{ "error": json.StringNode("", a.Response.Error), }) } else { node = json.ObjectNode("", map[string]*json.Node{ "result": json.StringNode("", base64.StdEncoding.EncodeToString(a.Response.Result)), }) } bz, _ := json.Marshal(node) return bz } func (a *AppAcknowledgement) UnmarshalJSON(bz []byte) error { root, err := json.Unmarshal(bz) if err != nil { return err } result, err := root.GetKey("result") if err != nil { rerror, err := root.GetKey("error") if err != nil { return err } a.Response = AppAcknowledgementResponse{Error: rerror.MustString()} return nil } resBz, err := base64.StdEncoding.DecodeString(result.MustString()) if err != nil { return err } a.Response = AppAcknowledgementResponse{Result: resBz} return nil } // MsgTimeout receives timed-out packet type MsgTimeout struct { Packet Packet ProofUnreceived []ics23.CommitmentProof ProofHeight Height } func (msg *MsgTimeout) ValidateBasic() error { if len(msg.ProofUnreceived) == 0 { return errors.New("cannot submit an empty timeout proof") } return msg.Packet.ValidateBasic() }