cosmos-sdk/x/ibc/04-channel/types/packet.go

121 lines
4.7 KiB
Go

package types
import (
"github.com/tendermint/tendermint/crypto/tmhash"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/cosmos/cosmos-sdk/x/ibc/04-channel/exported"
host "github.com/cosmos/cosmos-sdk/x/ibc/24-host"
)
// CommitPacket return the hash of commitment bytes
// TODO: no specification for packet commitment currently,
// make it spec compatible once we have it
func CommitPacket(packet exported.PacketI) []byte {
buf := sdk.Uint64ToBigEndian(packet.GetTimeoutHeight())
buf = append(buf, packet.GetData()...)
return tmhash.Sum(buf)
}
// CommitAcknowledgement returns the hash of commitment bytes
func CommitAcknowledgement(data []byte) []byte {
return tmhash.Sum(data)
}
var _ exported.PacketI = Packet{}
// Packet defines a type that carries data across different chains through IBC
type Packet struct {
Data []byte `json:"data" yaml:"data"` // Actual opaque bytes transferred directly to the application module
Sequence uint64 `json:"sequence" yaml:"sequence"` // number corresponds to the order of sends and receives, where a Packet with an earlier sequence number must be sent and received before a Packet with a later sequence number.
SourcePort string `json:"source_port" yaml:"source_port"` // identifies the port on the sending chain.
SourceChannel string `json:"source_channel" yaml:"source_channel"` // identifies the channel end on the sending chain.
DestinationPort string `json:"destination_port" yaml:"destination_port"` // identifies the port on the receiving chain.
DestinationChannel string `json:"destination_channel" yaml:"destination_channel"` // identifies the channel end on the receiving chain.
TimeoutHeight uint64 `json:"timeout_height" yaml:"timeout_height"` // block height after which the packet times out
TimeoutTimestamp uint64 `json:"timeout_timestamp" yaml:"timeout_timestamp"` // block timestamp (in nanoseconds) after which the packet times out
}
// NewPacket creates a new Packet instance
func NewPacket(
data []byte,
sequence uint64, sourcePort, sourceChannel,
destinationPort, destinationChannel string,
timeoutHeight uint64, timeoutTimestamp uint64,
) Packet {
return Packet{
Data: data,
Sequence: sequence,
SourcePort: sourcePort,
SourceChannel: sourceChannel,
DestinationPort: destinationPort,
DestinationChannel: destinationChannel,
TimeoutHeight: timeoutHeight,
TimeoutTimestamp: timeoutTimestamp,
}
}
// GetSequence implements PacketI interface
func (p Packet) GetSequence() uint64 { return p.Sequence }
// GetSourcePort implements PacketI interface
func (p Packet) GetSourcePort() string { return p.SourcePort }
// GetSourceChannel implements PacketI interface
func (p Packet) GetSourceChannel() string { return p.SourceChannel }
// GetDestPort implements PacketI interface
func (p Packet) GetDestPort() string { return p.DestinationPort }
// GetDestChannel implements PacketI interface
func (p Packet) GetDestChannel() string { return p.DestinationChannel }
// GetData implements PacketI interface
func (p Packet) GetData() []byte { return p.Data }
// GetTimeoutHeight implements PacketI interface
func (p Packet) GetTimeoutHeight() uint64 { return p.TimeoutHeight }
// GetTimeoutTimestamp implements PacketI interface
func (p Packet) GetTimeoutTimestamp() uint64 { return p.TimeoutTimestamp }
// ValidateBasic implements PacketI interface
func (p Packet) ValidateBasic() error {
if err := host.DefaultPortIdentifierValidator(p.SourcePort); err != nil {
return sdkerrors.Wrapf(
ErrInvalidPacket,
sdkerrors.Wrapf(err, "invalid source port ID: %s", p.SourcePort).Error(),
)
}
if err := host.DefaultPortIdentifierValidator(p.DestinationPort); err != nil {
return sdkerrors.Wrapf(
ErrInvalidPacket,
sdkerrors.Wrapf(err, "invalid destination port ID: %s", p.DestinationPort).Error(),
)
}
if err := host.DefaultChannelIdentifierValidator(p.SourceChannel); err != nil {
return sdkerrors.Wrapf(
ErrInvalidPacket,
sdkerrors.Wrapf(err, "invalid source channel ID: %s", p.SourceChannel).Error(),
)
}
if err := host.DefaultChannelIdentifierValidator(p.DestinationChannel); err != nil {
return sdkerrors.Wrapf(
ErrInvalidPacket,
sdkerrors.Wrapf(err, "invalid destination channel ID: %s", p.DestinationChannel).Error(),
)
}
if p.Sequence == 0 {
return sdkerrors.Wrap(ErrInvalidPacket, "packet sequence cannot be 0")
}
if p.TimeoutHeight == 0 && p.TimeoutTimestamp == 0 {
return sdkerrors.Wrap(ErrInvalidPacket, "packet timeout height and packet timeout timestamp cannot both be 0")
}
if len(p.Data) == 0 {
return sdkerrors.Wrap(ErrInvalidPacket, "packet data bytes cannot be empty")
}
return nil
}