From 67c380f779bfd081c2c6e5baa9a88346f6887ca4 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 14:29:41 +0100 Subject: [PATCH 01/14] feat: add initial protobuf defs for celestia da client --- .../light-clients/07-celestia/celestia.pb.go | 604 ++++++++++++++++++ modules/light-clients/07-celestia/codec.go | 20 + modules/light-clients/07-celestia/keys.go | 5 + modules/light-clients/07-celestia/module.go | 84 +++ .../lightclients/celestia/v1/celestia.proto | 30 + 5 files changed, 743 insertions(+) create mode 100644 modules/light-clients/07-celestia/celestia.pb.go create mode 100644 modules/light-clients/07-celestia/codec.go create mode 100644 modules/light-clients/07-celestia/keys.go create mode 100644 modules/light-clients/07-celestia/module.go create mode 100644 proto/ibc/lightclients/celestia/v1/celestia.proto diff --git a/modules/light-clients/07-celestia/celestia.pb.go b/modules/light-clients/07-celestia/celestia.pb.go new file mode 100644 index 00000000000..9f84fdb0274 --- /dev/null +++ b/modules/light-clients/07-celestia/celestia.pb.go @@ -0,0 +1,604 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: ibc/lightclients/celestia/v1/celestia.proto + +package celestia + +import ( + fmt "fmt" + github_com_cometbft_cometbft_libs_bytes "github.com/cometbft/cometbft/libs/bytes" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" + types "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + _07_tendermint "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" + _ "google.golang.org/protobuf/types/known/timestamppb" + io "io" + math "math" + math_bits "math/bits" + time "time" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf +var _ = time.Kitchen + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +// ClientState from Tendermint tracks the current validator set, latest height, +// and a possible frozen height. +type ClientState struct { + BaseClient *_07_tendermint.ClientState `protobuf:"bytes,1,opt,name=base_client,json=baseClient,proto3" json:"base_client,omitempty"` +} + +func (m *ClientState) Reset() { *m = ClientState{} } +func (m *ClientState) String() string { return proto.CompactTextString(m) } +func (*ClientState) ProtoMessage() {} +func (*ClientState) Descriptor() ([]byte, []int) { + return fileDescriptor_1a7b0753ec3219d3, []int{0} +} +func (m *ClientState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ClientState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ClientState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ClientState) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClientState.Merge(m, src) +} +func (m *ClientState) XXX_Size() int { + return m.Size() +} +func (m *ClientState) XXX_DiscardUnknown() { + xxx_messageInfo_ClientState.DiscardUnknown(m) +} + +var xxx_messageInfo_ClientState proto.InternalMessageInfo + +// ConsensusState defines the consensus state from Tendermint. +type ConsensusState struct { + // timestamp that corresponds to the block height in which the ConsensusState + // was stored. + Timestamp time.Time `protobuf:"bytes,1,opt,name=timestamp,proto3,stdtime" json:"timestamp"` + // commitment root (i.e data availability root) + Root types.MerkleRoot `protobuf:"bytes,2,opt,name=root,proto3" json:"root"` + NextValidatorsHash github_com_cometbft_cometbft_libs_bytes.HexBytes `protobuf:"bytes,3,opt,name=next_validators_hash,json=nextValidatorsHash,proto3,casttype=github.com/cometbft/cometbft/libs/bytes.HexBytes" json:"next_validators_hash,omitempty"` +} + +func (m *ConsensusState) Reset() { *m = ConsensusState{} } +func (m *ConsensusState) String() string { return proto.CompactTextString(m) } +func (*ConsensusState) ProtoMessage() {} +func (*ConsensusState) Descriptor() ([]byte, []int) { + return fileDescriptor_1a7b0753ec3219d3, []int{1} +} +func (m *ConsensusState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ConsensusState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ConsensusState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ConsensusState) XXX_Merge(src proto.Message) { + xxx_messageInfo_ConsensusState.Merge(m, src) +} +func (m *ConsensusState) XXX_Size() int { + return m.Size() +} +func (m *ConsensusState) XXX_DiscardUnknown() { + xxx_messageInfo_ConsensusState.DiscardUnknown(m) +} + +var xxx_messageInfo_ConsensusState proto.InternalMessageInfo + +func init() { + proto.RegisterType((*ClientState)(nil), "ibc.lightclients.celestia.v1.ClientState") + proto.RegisterType((*ConsensusState)(nil), "ibc.lightclients.celestia.v1.ConsensusState") +} + +func init() { + proto.RegisterFile("ibc/lightclients/celestia/v1/celestia.proto", fileDescriptor_1a7b0753ec3219d3) +} + +var fileDescriptor_1a7b0753ec3219d3 = []byte{ + // 430 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x52, 0x3f, 0x6f, 0xd3, 0x40, + 0x14, 0xb7, 0x4b, 0x84, 0xc0, 0x41, 0x0c, 0x56, 0x87, 0x28, 0x42, 0x76, 0x95, 0x85, 0x4a, 0x55, + 0xee, 0x1a, 0x40, 0x02, 0x01, 0x93, 0x2b, 0xa1, 0x0e, 0xb0, 0x18, 0xc4, 0xc0, 0x12, 0xee, 0x9c, + 0x17, 0xfb, 0x84, 0xed, 0x57, 0xf9, 0x5e, 0xac, 0xb2, 0x31, 0x32, 0xf6, 0x23, 0xf0, 0x71, 0x3a, + 0x76, 0x64, 0x2a, 0x28, 0xf9, 0x16, 0x4c, 0xe8, 0x7c, 0xb1, 0xe3, 0x2a, 0xdb, 0xef, 0x4e, 0xbf, + 0x3f, 0xf7, 0x7e, 0xef, 0xbc, 0x13, 0x25, 0x13, 0x9e, 0xab, 0x34, 0xa3, 0x24, 0x57, 0x50, 0x92, + 0xe6, 0x09, 0xe4, 0xa0, 0x49, 0x09, 0x5e, 0xcf, 0x3a, 0xcc, 0x2e, 0x2a, 0x24, 0xf4, 0x9f, 0x28, + 0x99, 0xb0, 0x3e, 0x99, 0x75, 0x84, 0x7a, 0x36, 0x0e, 0x53, 0xc4, 0x34, 0x07, 0xde, 0x70, 0xe5, + 0x6a, 0xc9, 0x49, 0x15, 0xa0, 0x49, 0x14, 0x17, 0x56, 0x3e, 0x7e, 0x6a, 0xb2, 0x12, 0xac, 0x80, + 0x27, 0x58, 0x14, 0x8a, 0x0a, 0x28, 0xa9, 0x49, 0xe9, 0x4e, 0x5b, 0x22, 0xdf, 0x7b, 0x14, 0x41, + 0xb9, 0x80, 0xaa, 0x50, 0x56, 0xb0, 0x3b, 0x6d, 0x05, 0x87, 0x29, 0xa6, 0xd8, 0x40, 0x6e, 0x90, + 0xbd, 0x9d, 0x08, 0x6f, 0x78, 0xd6, 0xe8, 0x3f, 0x92, 0x20, 0xf0, 0xdf, 0x7b, 0x43, 0x29, 0x34, + 0xcc, 0xad, 0xe7, 0xc8, 0x3d, 0x72, 0x8f, 0x87, 0xcf, 0x4e, 0xd8, 0xde, 0x4c, 0x3d, 0xf7, 0x7a, + 0xc6, 0x7a, 0x0e, 0xb1, 0x67, 0xf4, 0xf6, 0xe2, 0xf5, 0xe0, 0xe7, 0xaf, 0xd0, 0x99, 0xfc, 0x38, + 0xf0, 0x1e, 0x9f, 0x61, 0xa9, 0xa1, 0xd4, 0x2b, 0x6d, 0x63, 0x22, 0xef, 0x61, 0x37, 0xf8, 0x36, + 0x64, 0xcc, 0x6c, 0x35, 0xac, 0xad, 0x86, 0x7d, 0x6a, 0x19, 0xd1, 0x83, 0xeb, 0xdb, 0xd0, 0xb9, + 0xfa, 0x13, 0xba, 0xf1, 0x4e, 0xe6, 0xbf, 0xf5, 0x06, 0x15, 0x22, 0x8d, 0x0e, 0x1a, 0xf9, 0xa4, + 0x79, 0xa3, 0x29, 0x8e, 0xf5, 0xaa, 0xaa, 0x67, 0xec, 0x03, 0x54, 0xdf, 0x72, 0x88, 0x11, 0x29, + 0x1a, 0x18, 0x9b, 0xb8, 0x51, 0xf9, 0x4b, 0xef, 0xb0, 0x84, 0x4b, 0x9a, 0xd7, 0x22, 0x57, 0x0b, + 0x41, 0x58, 0xe9, 0x79, 0x26, 0x74, 0x36, 0xba, 0x77, 0xe4, 0x1e, 0x3f, 0x8a, 0x5e, 0xfc, 0xbb, + 0x0d, 0x4f, 0x53, 0x45, 0xd9, 0x4a, 0x1a, 0x3b, 0xd3, 0x3e, 0x90, 0x5c, 0xd2, 0x0e, 0xe4, 0x4a, + 0x6a, 0x2e, 0xbf, 0x13, 0x68, 0x76, 0x0e, 0x97, 0x91, 0x01, 0xb1, 0x6f, 0x1c, 0x3f, 0x77, 0x86, + 0xe7, 0x42, 0x67, 0xb6, 0x82, 0xe8, 0xeb, 0xf5, 0x3a, 0x70, 0x6f, 0xd6, 0x81, 0xfb, 0x77, 0x1d, + 0xb8, 0x57, 0x9b, 0xc0, 0xb9, 0xd9, 0x04, 0xce, 0xef, 0x4d, 0xe0, 0x7c, 0x79, 0x77, 0x27, 0x45, + 0x17, 0xa8, 0xcd, 0x62, 0xa7, 0x29, 0xf2, 0xfa, 0x15, 0x2f, 0x70, 0xb1, 0xca, 0x41, 0xdb, 0x35, + 0x4f, 0xdb, 0x3d, 0x9f, 0xbe, 0x9c, 0xb6, 0x5f, 0xea, 0x4d, 0x0b, 0xe4, 0xfd, 0xa6, 0xb6, 0xe7, + 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd6, 0xf5, 0x63, 0xc6, 0xac, 0x02, 0x00, 0x00, +} + +func (m *ClientState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ClientState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.BaseClient != nil { + { + size, err := m.BaseClient.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCelestia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *ConsensusState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ConsensusState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ConsensusState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.NextValidatorsHash) > 0 { + i -= len(m.NextValidatorsHash) + copy(dAtA[i:], m.NextValidatorsHash) + i = encodeVarintCelestia(dAtA, i, uint64(len(m.NextValidatorsHash))) + i-- + dAtA[i] = 0x1a + } + { + size, err := m.Root.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCelestia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + n3, err3 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) + if err3 != nil { + return 0, err3 + } + i -= n3 + i = encodeVarintCelestia(dAtA, i, uint64(n3)) + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintCelestia(dAtA []byte, offset int, v uint64) int { + offset -= sovCelestia(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *ClientState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.BaseClient != nil { + l = m.BaseClient.Size() + n += 1 + l + sovCelestia(uint64(l)) + } + return n +} + +func (m *ConsensusState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) + n += 1 + l + sovCelestia(uint64(l)) + l = m.Root.Size() + n += 1 + l + sovCelestia(uint64(l)) + l = len(m.NextValidatorsHash) + if l > 0 { + n += 1 + l + sovCelestia(uint64(l)) + } + return n +} + +func sovCelestia(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozCelestia(x uint64) (n int) { + return sovCelestia(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ClientState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClientState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseClient", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.BaseClient == nil { + m.BaseClient = &_07_tendermint.ClientState{} + } + if err := m.BaseClient.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCelestia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCelestia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *ConsensusState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ConsensusState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ConsensusState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Root", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Root.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) + if m.NextValidatorsHash == nil { + m.NextValidatorsHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCelestia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCelestia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipCelestia(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCelestia + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCelestia + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowCelestia + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthCelestia + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupCelestia + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthCelestia + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthCelestia = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowCelestia = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupCelestia = fmt.Errorf("proto: unexpected end of group") +) diff --git a/modules/light-clients/07-celestia/codec.go b/modules/light-clients/07-celestia/codec.go new file mode 100644 index 00000000000..c4669b139f6 --- /dev/null +++ b/modules/light-clients/07-celestia/codec.go @@ -0,0 +1,20 @@ +package celestia + +import ( + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + + "github.com/cosmos/ibc-go/v8/modules/core/exported" +) + +// RegisterInterfaces registers the tendermint concrete client-related +// implementations and interfaces. +func RegisterInterfaces(registry codectypes.InterfaceRegistry) { + registry.RegisterImplementations( + (*exported.ClientState)(nil), + &ClientState{}, + ) + registry.RegisterImplementations( + (*exported.ConsensusState)(nil), + &ConsensusState{}, + ) +} diff --git a/modules/light-clients/07-celestia/keys.go b/modules/light-clients/07-celestia/keys.go new file mode 100644 index 00000000000..652b7cc3cbf --- /dev/null +++ b/modules/light-clients/07-celestia/keys.go @@ -0,0 +1,5 @@ +package celestia + +const ( + ModuleName = "07-celestia" +) diff --git a/modules/light-clients/07-celestia/module.go b/modules/light-clients/07-celestia/module.go new file mode 100644 index 00000000000..b82e70451af --- /dev/null +++ b/modules/light-clients/07-celestia/module.go @@ -0,0 +1,84 @@ +package celestia + +import ( + "encoding/json" + + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + "cosmossdk.io/core/appmodule" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/types/module" +) + +var ( + _ module.AppModuleBasic = (*AppModuleBasic)(nil) + _ appmodule.AppModule = (*AppModule)(nil) +) + +// AppModuleBasic defines the basic application module used by the tendermint light client. +// Only the RegisterInterfaces function needs to be implemented. All other function perform +// a no-op. +type AppModuleBasic struct{} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (AppModuleBasic) IsOnePerModuleType() {} + +// IsAppModule implements the appmodule.AppModule interface. +func (AppModuleBasic) IsAppModule() {} + +// Name returns the tendermint module name. +func (AppModuleBasic) Name() string { + return ModuleName +} + +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (AppModule) IsOnePerModuleType() {} + +// IsAppModule implements the appmodule.AppModule interface. +func (AppModule) IsAppModule() {} + +// RegisterLegacyAminoCodec performs a no-op. The Tendermint client does not support amino. +func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} + +// RegisterInterfaces registers module concrete types into protobuf Any. This allows core IBC +// to unmarshal tendermint light client types. +func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { + RegisterInterfaces(registry) +} + +// DefaultGenesis performs a no-op. Genesis is not supported for the tendermint light client. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return nil +} + +// ValidateGenesis performs a no-op. Genesis is not supported for the tendermint light client. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + return nil +} + +// RegisterGRPCGatewayRoutes performs a no-op. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {} + +// GetTxCmd performs a no-op. Please see the 02-client cli commands. +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return nil +} + +// GetQueryCmd performs a no-op. Please see the 02-client cli commands. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return nil +} + +// AppModule is the application module for the Tendermint client module +type AppModule struct { + AppModuleBasic +} + +// NewAppModule creates a new Tendermint client module +func NewAppModule() AppModule { + return AppModule{} +} diff --git a/proto/ibc/lightclients/celestia/v1/celestia.proto b/proto/ibc/lightclients/celestia/v1/celestia.proto new file mode 100644 index 00000000000..bdd2bfd783f --- /dev/null +++ b/proto/ibc/lightclients/celestia/v1/celestia.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package ibc.lightclients.celestia.v1; + +option go_package = "github.com/cosmos/ibc-go/v8/modules/light-clients/07-celestia;celestia"; + +import "google/protobuf/timestamp.proto"; +import "ibc/core/commitment/v1/commitment.proto"; +import "ibc/lightclients/tendermint/v1/tendermint.proto"; +import "gogoproto/gogo.proto"; + +// ClientState from Tendermint tracks the current validator set, latest height, +// and a possible frozen height. +message ClientState { + option (gogoproto.goproto_getters) = false; + + ibc.lightclients.tendermint.v1.ClientState base_client = 1; +} + +// ConsensusState defines the consensus state from Tendermint. +message ConsensusState { + option (gogoproto.goproto_getters) = false; + + // timestamp that corresponds to the block height in which the ConsensusState + // was stored. + google.protobuf.Timestamp timestamp = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; + // commitment root (i.e data availability root) + ibc.core.commitment.v1.MerkleRoot root = 2 [(gogoproto.nullable) = false]; + bytes next_validators_hash = 3 [(gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes"]; +} From 4c992a4b24cfca8d8d5659bcf7cfff6df09bb47e Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 14:41:14 +0100 Subject: [PATCH 02/14] chore: generate method stubs for interface impl and update godocs --- .../light-clients/07-celestia/client_state.go | 91 +++++++++++++++++++ modules/light-clients/07-celestia/codec.go | 2 +- .../07-celestia/consensus_state.go | 58 ++++++++++++ modules/light-clients/07-celestia/module.go | 16 ++-- 4 files changed, 158 insertions(+), 9 deletions(-) create mode 100644 modules/light-clients/07-celestia/client_state.go create mode 100644 modules/light-clients/07-celestia/consensus_state.go diff --git a/modules/light-clients/07-celestia/client_state.go b/modules/light-clients/07-celestia/client_state.go new file mode 100644 index 00000000000..6cfacf2441a --- /dev/null +++ b/modules/light-clients/07-celestia/client_state.go @@ -0,0 +1,91 @@ +package celestia + +import ( + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/cosmos/ibc-go/v8/modules/core/exported" +) + +var _ exported.ClientState = (*ClientState)(nil) + +// CheckForMisbehaviour implements exported.ClientState. +func (*ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) bool { + panic("unimplemented") +} + +// CheckSubstituteAndUpdateState implements exported.ClientState. +func (*ClientState) CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore storetypes.KVStore, substituteClientStore storetypes.KVStore, substituteClient exported.ClientState) error { + panic("unimplemented") +} + +// ClientType implements exported.ClientState. +func (*ClientState) ClientType() string { + panic("unimplemented") +} + +// ExportMetadata implements exported.ClientState. +func (*ClientState) ExportMetadata(clientStore storetypes.KVStore) []exported.GenesisMetadata { + panic("unimplemented") +} + +// GetLatestHeight implements exported.ClientState. +func (*ClientState) GetLatestHeight() exported.Height { + panic("unimplemented") +} + +// GetTimestampAtHeight implements exported.ClientState. +func (*ClientState) GetTimestampAtHeight(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height) (uint64, error) { + panic("unimplemented") +} + +// Initialize implements exported.ClientState. +func (*ClientState) Initialize(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, consensusState exported.ConsensusState) error { + panic("unimplemented") +} + +// Status implements exported.ClientState. +func (*ClientState) Status(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec) exported.Status { + panic("unimplemented") +} + +// UpdateState implements exported.ClientState. +func (*ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) []exported.Height { + panic("unimplemented") +} + +// UpdateStateOnMisbehaviour implements exported.ClientState. +func (*ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) { + panic("unimplemented") +} + +// Validate implements exported.ClientState. +func (*ClientState) Validate() error { + panic("unimplemented") +} + +// VerifyClientMessage implements exported.ClientState. +func (*ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) error { + panic("unimplemented") +} + +// VerifyMembership implements exported.ClientState. +func (*ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path exported.Path, value []byte) error { + panic("unimplemented") +} + +// VerifyNonMembership implements exported.ClientState. +func (*ClientState) VerifyNonMembership(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path exported.Path) error { + panic("unimplemented") +} + +// VerifyUpgradeAndUpdateState implements exported.ClientState. +func (*ClientState) VerifyUpgradeAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, store storetypes.KVStore, newClient exported.ClientState, newConsState exported.ConsensusState, upgradeClientProof []byte, upgradeConsensusStateProof []byte) error { + panic("unimplemented") +} + +// ZeroCustomFields implements exported.ClientState. +func (*ClientState) ZeroCustomFields() exported.ClientState { + panic("unimplemented") +} diff --git a/modules/light-clients/07-celestia/codec.go b/modules/light-clients/07-celestia/codec.go index c4669b139f6..06276c51320 100644 --- a/modules/light-clients/07-celestia/codec.go +++ b/modules/light-clients/07-celestia/codec.go @@ -6,7 +6,7 @@ import ( "github.com/cosmos/ibc-go/v8/modules/core/exported" ) -// RegisterInterfaces registers the tendermint concrete client-related +// RegisterInterfaces registers the celestia concrete client-related // implementations and interfaces. func RegisterInterfaces(registry codectypes.InterfaceRegistry) { registry.RegisterImplementations( diff --git a/modules/light-clients/07-celestia/consensus_state.go b/modules/light-clients/07-celestia/consensus_state.go new file mode 100644 index 00000000000..ee90846b07b --- /dev/null +++ b/modules/light-clients/07-celestia/consensus_state.go @@ -0,0 +1,58 @@ +package celestia + +import ( + "time" + + errorsmod "cosmossdk.io/errors" + + cmtbytes "github.com/cometbft/cometbft/libs/bytes" + cmttypes "github.com/cometbft/cometbft/types" + + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" +) + +var _ exported.ConsensusState = (*ConsensusState)(nil) + +// NewConsensusState creates a new ConsensusState instance. +func NewConsensusState( + timestamp time.Time, root commitmenttypes.MerkleRoot, nextValsHash cmtbytes.HexBytes, +) *ConsensusState { + return &ConsensusState{ + Timestamp: timestamp, + Root: root, + NextValidatorsHash: nextValsHash, + } +} + +// ClientType returns Celestia +func (ConsensusState) ClientType() string { + return ModuleName +} + +// GetRoot returns the commitment Root for the specific +func (cs ConsensusState) GetRoot() exported.Root { + return cs.Root +} + +// GetTimestamp returns block time in nanoseconds of the header that created consensus state +func (cs ConsensusState) GetTimestamp() uint64 { + return uint64(cs.Timestamp.UnixNano()) +} + +// ValidateBasic defines a basic validation for the tendermint consensus state. +// NOTE: ProcessedTimestamp may be zero if this is an initial consensus state passed in by relayer +// as opposed to a consensus state constructed by the chain. +func (cs ConsensusState) ValidateBasic() error { + if cs.Root.Empty() { + return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, "root cannot be empty") + } + if err := cmttypes.ValidateHash(cs.NextValidatorsHash); err != nil { + return errorsmod.Wrap(err, "next validators hash is invalid") + } + if cs.Timestamp.Unix() <= 0 { + return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, "timestamp must be a positive Unix time") + } + return nil +} diff --git a/modules/light-clients/07-celestia/module.go b/modules/light-clients/07-celestia/module.go index b82e70451af..db618a57dd0 100644 --- a/modules/light-clients/07-celestia/module.go +++ b/modules/light-clients/07-celestia/module.go @@ -19,7 +19,7 @@ var ( _ appmodule.AppModule = (*AppModule)(nil) ) -// AppModuleBasic defines the basic application module used by the tendermint light client. +// AppModuleBasic defines the basic application module used by the celestia light client. // Only the RegisterInterfaces function needs to be implemented. All other function perform // a no-op. type AppModuleBasic struct{} @@ -30,7 +30,7 @@ func (AppModuleBasic) IsOnePerModuleType() {} // IsAppModule implements the appmodule.AppModule interface. func (AppModuleBasic) IsAppModule() {} -// Name returns the tendermint module name. +// Name returns the celestia module name. func (AppModuleBasic) Name() string { return ModuleName } @@ -41,21 +41,21 @@ func (AppModule) IsOnePerModuleType() {} // IsAppModule implements the appmodule.AppModule interface. func (AppModule) IsAppModule() {} -// RegisterLegacyAminoCodec performs a no-op. The Tendermint client does not support amino. +// RegisterLegacyAminoCodec performs a no-op. The celestia client does not support amino. func (AppModuleBasic) RegisterLegacyAminoCodec(*codec.LegacyAmino) {} // RegisterInterfaces registers module concrete types into protobuf Any. This allows core IBC -// to unmarshal tendermint light client types. +// to unmarshal celestia light client types. func (AppModuleBasic) RegisterInterfaces(registry codectypes.InterfaceRegistry) { RegisterInterfaces(registry) } -// DefaultGenesis performs a no-op. Genesis is not supported for the tendermint light client. +// DefaultGenesis performs a no-op. Genesis is not supported for the celestia light client. func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { return nil } -// ValidateGenesis performs a no-op. Genesis is not supported for the tendermint light client. +// ValidateGenesis performs a no-op. Genesis is not supported for the celestia light client. func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { return nil } @@ -73,12 +73,12 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { return nil } -// AppModule is the application module for the Tendermint client module +// AppModule is the application module for the celestia client module type AppModule struct { AppModuleBasic } -// NewAppModule creates a new Tendermint client module +// NewAppModule creates a new celestia client module func NewAppModule() AppModule { return AppModule{} } From 815a7292a8abdf18696328b33bc3bd64573a69e4 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 14:49:38 +0100 Subject: [PATCH 03/14] chore: restructure methods to various files to improve readability --- .../light-clients/07-celestia/client_state.go | 44 +------------------ modules/light-clients/07-celestia/genesis.go | 11 +++++ modules/light-clients/07-celestia/update.go | 28 ++++++++++++ modules/light-clients/07-celestia/upgrade.go | 23 ++++++++++ 4 files changed, 64 insertions(+), 42 deletions(-) create mode 100644 modules/light-clients/07-celestia/genesis.go create mode 100644 modules/light-clients/07-celestia/update.go create mode 100644 modules/light-clients/07-celestia/upgrade.go diff --git a/modules/light-clients/07-celestia/client_state.go b/modules/light-clients/07-celestia/client_state.go index 6cfacf2441a..2757637d564 100644 --- a/modules/light-clients/07-celestia/client_state.go +++ b/modules/light-clients/07-celestia/client_state.go @@ -10,26 +10,11 @@ import ( var _ exported.ClientState = (*ClientState)(nil) -// CheckForMisbehaviour implements exported.ClientState. -func (*ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) bool { - panic("unimplemented") -} - -// CheckSubstituteAndUpdateState implements exported.ClientState. -func (*ClientState) CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore storetypes.KVStore, substituteClientStore storetypes.KVStore, substituteClient exported.ClientState) error { - panic("unimplemented") -} - // ClientType implements exported.ClientState. func (*ClientState) ClientType() string { panic("unimplemented") } -// ExportMetadata implements exported.ClientState. -func (*ClientState) ExportMetadata(clientStore storetypes.KVStore) []exported.GenesisMetadata { - panic("unimplemented") -} - // GetLatestHeight implements exported.ClientState. func (*ClientState) GetLatestHeight() exported.Height { panic("unimplemented") @@ -40,23 +25,13 @@ func (*ClientState) GetTimestampAtHeight(ctx sdk.Context, clientStore storetypes panic("unimplemented") } -// Initialize implements exported.ClientState. -func (*ClientState) Initialize(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, consensusState exported.ConsensusState) error { - panic("unimplemented") -} - // Status implements exported.ClientState. func (*ClientState) Status(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec) exported.Status { panic("unimplemented") } -// UpdateState implements exported.ClientState. -func (*ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) []exported.Height { - panic("unimplemented") -} - -// UpdateStateOnMisbehaviour implements exported.ClientState. -func (*ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) { +// Initialize implements exported.ClientState. +func (*ClientState) Initialize(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, consensusState exported.ConsensusState) error { panic("unimplemented") } @@ -65,11 +40,6 @@ func (*ClientState) Validate() error { panic("unimplemented") } -// VerifyClientMessage implements exported.ClientState. -func (*ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) error { - panic("unimplemented") -} - // VerifyMembership implements exported.ClientState. func (*ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path exported.Path, value []byte) error { panic("unimplemented") @@ -79,13 +49,3 @@ func (*ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes.KVS func (*ClientState) VerifyNonMembership(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path exported.Path) error { panic("unimplemented") } - -// VerifyUpgradeAndUpdateState implements exported.ClientState. -func (*ClientState) VerifyUpgradeAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, store storetypes.KVStore, newClient exported.ClientState, newConsState exported.ConsensusState, upgradeClientProof []byte, upgradeConsensusStateProof []byte) error { - panic("unimplemented") -} - -// ZeroCustomFields implements exported.ClientState. -func (*ClientState) ZeroCustomFields() exported.ClientState { - panic("unimplemented") -} diff --git a/modules/light-clients/07-celestia/genesis.go b/modules/light-clients/07-celestia/genesis.go new file mode 100644 index 00000000000..8a0e1226ac3 --- /dev/null +++ b/modules/light-clients/07-celestia/genesis.go @@ -0,0 +1,11 @@ +package celestia + +import ( + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" +) + +// ExportMetadata implements exported.ClientState. +func (*ClientState) ExportMetadata(clientStore storetypes.KVStore) []exported.GenesisMetadata { + panic("unimplemented") +} diff --git a/modules/light-clients/07-celestia/update.go b/modules/light-clients/07-celestia/update.go new file mode 100644 index 00000000000..d9d73449af0 --- /dev/null +++ b/modules/light-clients/07-celestia/update.go @@ -0,0 +1,28 @@ +package celestia + +import ( + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" +) + +// VerifyClientMessage implements exported.ClientState. +func (*ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) error { + panic("unimplemented") +} + +// UpdateState implements exported.ClientState. +func (*ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) []exported.Height { + panic("unimplemented") +} + +// CheckForMisbehaviour implements exported.ClientState. +func (*ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) bool { + panic("unimplemented") +} + +// UpdateStateOnMisbehaviour implements exported.ClientState. +func (*ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) { + panic("unimplemented") +} diff --git a/modules/light-clients/07-celestia/upgrade.go b/modules/light-clients/07-celestia/upgrade.go new file mode 100644 index 00000000000..ad520a4f98c --- /dev/null +++ b/modules/light-clients/07-celestia/upgrade.go @@ -0,0 +1,23 @@ +package celestia + +import ( + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" +) + +// CheckSubstituteAndUpdateState implements exported.ClientState. +func (*ClientState) CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore storetypes.KVStore, substituteClientStore storetypes.KVStore, substituteClient exported.ClientState) error { + panic("unimplemented") +} + +// VerifyUpgradeAndUpdateState implements exported.ClientState. +func (*ClientState) VerifyUpgradeAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, store storetypes.KVStore, newClient exported.ClientState, newConsState exported.ConsensusState, upgradeClientProof []byte, upgradeConsensusStateProof []byte) error { + panic("unimplemented") +} + +// ZeroCustomFields implements exported.ClientState. +func (*ClientState) ZeroCustomFields() exported.ClientState { + panic("unimplemented") +} From e221ebbddc3a4a2ecf66075d66b1b09ae21419fe Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 15:01:28 +0100 Subject: [PATCH 04/14] chore: adding note about redefining consensus state --- modules/light-clients/07-celestia/consensus_state.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/light-clients/07-celestia/consensus_state.go b/modules/light-clients/07-celestia/consensus_state.go index ee90846b07b..92948d6bd14 100644 --- a/modules/light-clients/07-celestia/consensus_state.go +++ b/modules/light-clients/07-celestia/consensus_state.go @@ -13,6 +13,11 @@ import ( "github.com/cosmos/ibc-go/v8/modules/core/exported" ) +// TODO: Maybe we cannot redefine consensus state if we are delegate client state calls to base client. +// See: GetConsensusState() func of 07-tendermint used in many method of ClientState implementaiton. Type assertion performed. +// Should be possible to reuse tendermint consensus state and these methods should continue to work. +// Root of 07-tendermint ConsensusState is just the data availability root instead of app hash. + var _ exported.ConsensusState = (*ConsensusState)(nil) // NewConsensusState creates a new ConsensusState instance. From 6c9e79dbc1df290ab4708f9748607a319737f704 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 15:01:55 +0100 Subject: [PATCH 05/14] chore: begin delegate func calls to base tm client --- modules/light-clients/07-celestia/client_state.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/light-clients/07-celestia/client_state.go b/modules/light-clients/07-celestia/client_state.go index 2757637d564..7864f59f59a 100644 --- a/modules/light-clients/07-celestia/client_state.go +++ b/modules/light-clients/07-celestia/client_state.go @@ -12,22 +12,22 @@ var _ exported.ClientState = (*ClientState)(nil) // ClientType implements exported.ClientState. func (*ClientState) ClientType() string { - panic("unimplemented") + return ModuleName } // GetLatestHeight implements exported.ClientState. -func (*ClientState) GetLatestHeight() exported.Height { - panic("unimplemented") +func (cs *ClientState) GetLatestHeight() exported.Height { + return cs.BaseClient.GetLatestHeight() } // GetTimestampAtHeight implements exported.ClientState. -func (*ClientState) GetTimestampAtHeight(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height) (uint64, error) { - panic("unimplemented") +func (cs *ClientState) GetTimestampAtHeight(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height) (uint64, error) { + return cs.BaseClient.GetTimestampAtHeight(ctx, clientStore, cdc, height) } // Status implements exported.ClientState. -func (*ClientState) Status(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec) exported.Status { - panic("unimplemented") +func (cs *ClientState) Status(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec) exported.Status { + return cs.BaseClient.Status(ctx, clientStore, cdc) } // Initialize implements exported.ClientState. From c58fc5ed612bcb2cf39fc212bc045175ec60c46d Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 15:06:15 +0100 Subject: [PATCH 06/14] chore: delegate more func calls to base client --- modules/light-clients/07-celestia/client_state.go | 8 ++++---- modules/light-clients/07-celestia/genesis.go | 4 ++-- modules/light-clients/07-celestia/upgrade.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/light-clients/07-celestia/client_state.go b/modules/light-clients/07-celestia/client_state.go index 7864f59f59a..617de563615 100644 --- a/modules/light-clients/07-celestia/client_state.go +++ b/modules/light-clients/07-celestia/client_state.go @@ -31,13 +31,13 @@ func (cs *ClientState) Status(ctx sdk.Context, clientStore storetypes.KVStore, c } // Initialize implements exported.ClientState. -func (*ClientState) Initialize(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, consensusState exported.ConsensusState) error { - panic("unimplemented") +func (cs *ClientState) Initialize(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, consensusState exported.ConsensusState) error { + return cs.BaseClient.Initialize(ctx, cdc, clientStore, consensusState) } // Validate implements exported.ClientState. -func (*ClientState) Validate() error { - panic("unimplemented") +func (cs *ClientState) Validate() error { + return cs.BaseClient.Validate() } // VerifyMembership implements exported.ClientState. diff --git a/modules/light-clients/07-celestia/genesis.go b/modules/light-clients/07-celestia/genesis.go index 8a0e1226ac3..83ad27ed18f 100644 --- a/modules/light-clients/07-celestia/genesis.go +++ b/modules/light-clients/07-celestia/genesis.go @@ -6,6 +6,6 @@ import ( ) // ExportMetadata implements exported.ClientState. -func (*ClientState) ExportMetadata(clientStore storetypes.KVStore) []exported.GenesisMetadata { - panic("unimplemented") +func (cs *ClientState) ExportMetadata(clientStore storetypes.KVStore) []exported.GenesisMetadata { + return cs.BaseClient.ExportMetadata(clientStore) } diff --git a/modules/light-clients/07-celestia/upgrade.go b/modules/light-clients/07-celestia/upgrade.go index ad520a4f98c..20b18f306b0 100644 --- a/modules/light-clients/07-celestia/upgrade.go +++ b/modules/light-clients/07-celestia/upgrade.go @@ -8,8 +8,8 @@ import ( ) // CheckSubstituteAndUpdateState implements exported.ClientState. -func (*ClientState) CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore storetypes.KVStore, substituteClientStore storetypes.KVStore, substituteClient exported.ClientState) error { - panic("unimplemented") +func (cs *ClientState) CheckSubstituteAndUpdateState(ctx sdk.Context, cdc codec.BinaryCodec, subjectClientStore storetypes.KVStore, substituteClientStore storetypes.KVStore, substituteClient exported.ClientState) error { + return cs.BaseClient.CheckSubstituteAndUpdateState(ctx, cdc, subjectClientStore, subjectClientStore, substituteClient) } // VerifyUpgradeAndUpdateState implements exported.ClientState. From bdf09036c3d466e3a3176a216aa6ec323236d319 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 15:57:56 +0100 Subject: [PATCH 07/14] imp: rm celestia consensus state and implement updateState handler --- .../light-clients/07-celestia/celestia.pb.go | 310 +----------------- .../07-celestia/consensus_state.go | 63 ---- modules/light-clients/07-celestia/update.go | 48 ++- .../lightclients/celestia/v1/celestia.proto | 14 - 4 files changed, 57 insertions(+), 378 deletions(-) delete mode 100644 modules/light-clients/07-celestia/consensus_state.go diff --git a/modules/light-clients/07-celestia/celestia.pb.go b/modules/light-clients/07-celestia/celestia.pb.go index 9f84fdb0274..c702d6c5090 100644 --- a/modules/light-clients/07-celestia/celestia.pb.go +++ b/modules/light-clients/07-celestia/celestia.pb.go @@ -5,24 +5,18 @@ package celestia import ( fmt "fmt" - github_com_cometbft_cometbft_libs_bytes "github.com/cometbft/cometbft/libs/bytes" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" - github_com_cosmos_gogoproto_types "github.com/cosmos/gogoproto/types" - types "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" _07_tendermint "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" - _ "google.golang.org/protobuf/types/known/timestamppb" io "io" math "math" math_bits "math/bits" - time "time" ) // Reference imports to suppress errors if they are not otherwise used. var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf -var _ = time.Kitchen // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. @@ -69,52 +63,8 @@ func (m *ClientState) XXX_DiscardUnknown() { var xxx_messageInfo_ClientState proto.InternalMessageInfo -// ConsensusState defines the consensus state from Tendermint. -type ConsensusState struct { - // timestamp that corresponds to the block height in which the ConsensusState - // was stored. - Timestamp time.Time `protobuf:"bytes,1,opt,name=timestamp,proto3,stdtime" json:"timestamp"` - // commitment root (i.e data availability root) - Root types.MerkleRoot `protobuf:"bytes,2,opt,name=root,proto3" json:"root"` - NextValidatorsHash github_com_cometbft_cometbft_libs_bytes.HexBytes `protobuf:"bytes,3,opt,name=next_validators_hash,json=nextValidatorsHash,proto3,casttype=github.com/cometbft/cometbft/libs/bytes.HexBytes" json:"next_validators_hash,omitempty"` -} - -func (m *ConsensusState) Reset() { *m = ConsensusState{} } -func (m *ConsensusState) String() string { return proto.CompactTextString(m) } -func (*ConsensusState) ProtoMessage() {} -func (*ConsensusState) Descriptor() ([]byte, []int) { - return fileDescriptor_1a7b0753ec3219d3, []int{1} -} -func (m *ConsensusState) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ConsensusState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ConsensusState.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ConsensusState) XXX_Merge(src proto.Message) { - xxx_messageInfo_ConsensusState.Merge(m, src) -} -func (m *ConsensusState) XXX_Size() int { - return m.Size() -} -func (m *ConsensusState) XXX_DiscardUnknown() { - xxx_messageInfo_ConsensusState.DiscardUnknown(m) -} - -var xxx_messageInfo_ConsensusState proto.InternalMessageInfo - func init() { proto.RegisterType((*ClientState)(nil), "ibc.lightclients.celestia.v1.ClientState") - proto.RegisterType((*ConsensusState)(nil), "ibc.lightclients.celestia.v1.ConsensusState") } func init() { @@ -122,34 +72,23 @@ func init() { } var fileDescriptor_1a7b0753ec3219d3 = []byte{ - // 430 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x52, 0x3f, 0x6f, 0xd3, 0x40, - 0x14, 0xb7, 0x4b, 0x84, 0xc0, 0x41, 0x0c, 0x56, 0x87, 0x28, 0x42, 0x76, 0x95, 0x85, 0x4a, 0x55, - 0xee, 0x1a, 0x40, 0x02, 0x01, 0x93, 0x2b, 0xa1, 0x0e, 0xb0, 0x18, 0xc4, 0xc0, 0x12, 0xee, 0x9c, - 0x17, 0xfb, 0x84, 0xed, 0x57, 0xf9, 0x5e, 0xac, 0xb2, 0x31, 0x32, 0xf6, 0x23, 0xf0, 0x71, 0x3a, - 0x76, 0x64, 0x2a, 0x28, 0xf9, 0x16, 0x4c, 0xe8, 0x7c, 0xb1, 0xe3, 0x2a, 0xdb, 0xef, 0x4e, 0xbf, - 0x3f, 0xf7, 0x7e, 0xef, 0xbc, 0x13, 0x25, 0x13, 0x9e, 0xab, 0x34, 0xa3, 0x24, 0x57, 0x50, 0x92, - 0xe6, 0x09, 0xe4, 0xa0, 0x49, 0x09, 0x5e, 0xcf, 0x3a, 0xcc, 0x2e, 0x2a, 0x24, 0xf4, 0x9f, 0x28, - 0x99, 0xb0, 0x3e, 0x99, 0x75, 0x84, 0x7a, 0x36, 0x0e, 0x53, 0xc4, 0x34, 0x07, 0xde, 0x70, 0xe5, - 0x6a, 0xc9, 0x49, 0x15, 0xa0, 0x49, 0x14, 0x17, 0x56, 0x3e, 0x7e, 0x6a, 0xb2, 0x12, 0xac, 0x80, - 0x27, 0x58, 0x14, 0x8a, 0x0a, 0x28, 0xa9, 0x49, 0xe9, 0x4e, 0x5b, 0x22, 0xdf, 0x7b, 0x14, 0x41, - 0xb9, 0x80, 0xaa, 0x50, 0x56, 0xb0, 0x3b, 0x6d, 0x05, 0x87, 0x29, 0xa6, 0xd8, 0x40, 0x6e, 0x90, - 0xbd, 0x9d, 0x08, 0x6f, 0x78, 0xd6, 0xe8, 0x3f, 0x92, 0x20, 0xf0, 0xdf, 0x7b, 0x43, 0x29, 0x34, - 0xcc, 0xad, 0xe7, 0xc8, 0x3d, 0x72, 0x8f, 0x87, 0xcf, 0x4e, 0xd8, 0xde, 0x4c, 0x3d, 0xf7, 0x7a, - 0xc6, 0x7a, 0x0e, 0xb1, 0x67, 0xf4, 0xf6, 0xe2, 0xf5, 0xe0, 0xe7, 0xaf, 0xd0, 0x99, 0xfc, 0x38, - 0xf0, 0x1e, 0x9f, 0x61, 0xa9, 0xa1, 0xd4, 0x2b, 0x6d, 0x63, 0x22, 0xef, 0x61, 0x37, 0xf8, 0x36, - 0x64, 0xcc, 0x6c, 0x35, 0xac, 0xad, 0x86, 0x7d, 0x6a, 0x19, 0xd1, 0x83, 0xeb, 0xdb, 0xd0, 0xb9, - 0xfa, 0x13, 0xba, 0xf1, 0x4e, 0xe6, 0xbf, 0xf5, 0x06, 0x15, 0x22, 0x8d, 0x0e, 0x1a, 0xf9, 0xa4, - 0x79, 0xa3, 0x29, 0x8e, 0xf5, 0xaa, 0xaa, 0x67, 0xec, 0x03, 0x54, 0xdf, 0x72, 0x88, 0x11, 0x29, - 0x1a, 0x18, 0x9b, 0xb8, 0x51, 0xf9, 0x4b, 0xef, 0xb0, 0x84, 0x4b, 0x9a, 0xd7, 0x22, 0x57, 0x0b, - 0x41, 0x58, 0xe9, 0x79, 0x26, 0x74, 0x36, 0xba, 0x77, 0xe4, 0x1e, 0x3f, 0x8a, 0x5e, 0xfc, 0xbb, - 0x0d, 0x4f, 0x53, 0x45, 0xd9, 0x4a, 0x1a, 0x3b, 0xd3, 0x3e, 0x90, 0x5c, 0xd2, 0x0e, 0xe4, 0x4a, - 0x6a, 0x2e, 0xbf, 0x13, 0x68, 0x76, 0x0e, 0x97, 0x91, 0x01, 0xb1, 0x6f, 0x1c, 0x3f, 0x77, 0x86, - 0xe7, 0x42, 0x67, 0xb6, 0x82, 0xe8, 0xeb, 0xf5, 0x3a, 0x70, 0x6f, 0xd6, 0x81, 0xfb, 0x77, 0x1d, - 0xb8, 0x57, 0x9b, 0xc0, 0xb9, 0xd9, 0x04, 0xce, 0xef, 0x4d, 0xe0, 0x7c, 0x79, 0x77, 0x27, 0x45, - 0x17, 0xa8, 0xcd, 0x62, 0xa7, 0x29, 0xf2, 0xfa, 0x15, 0x2f, 0x70, 0xb1, 0xca, 0x41, 0xdb, 0x35, - 0x4f, 0xdb, 0x3d, 0x9f, 0xbe, 0x9c, 0xb6, 0x5f, 0xea, 0x4d, 0x0b, 0xe4, 0xfd, 0xa6, 0xb6, 0xe7, - 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xd6, 0xf5, 0x63, 0xc6, 0xac, 0x02, 0x00, 0x00, + // 243 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xce, 0x4c, 0x4a, 0xd6, + 0xcf, 0xc9, 0x4c, 0xcf, 0x28, 0x49, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0x29, 0xd6, 0x4f, 0x4e, 0xcd, + 0x49, 0x2d, 0x2e, 0xc9, 0x4c, 0xd4, 0x2f, 0x33, 0x84, 0xb3, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, + 0x85, 0x64, 0x32, 0x93, 0x92, 0xf5, 0x90, 0x15, 0xeb, 0xc1, 0x15, 0x94, 0x19, 0x4a, 0xe9, 0x63, + 0x18, 0x55, 0x92, 0x9a, 0x97, 0x92, 0x5a, 0x94, 0x9b, 0x99, 0x57, 0x02, 0x32, 0x0c, 0xc1, 0x83, + 0x18, 0x27, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x66, 0xea, 0x83, 0x58, 0x10, 0x51, 0xa5, 0x44, + 0x2e, 0x6e, 0x67, 0xb0, 0xfe, 0xe0, 0x92, 0xc4, 0x92, 0x54, 0x21, 0x1f, 0x2e, 0xee, 0xa4, 0xc4, + 0xe2, 0xd4, 0x78, 0x88, 0x99, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0xda, 0x7a, 0x18, 0x2e, + 0x41, 0x32, 0xbd, 0xcc, 0x50, 0x0f, 0xc9, 0x84, 0x20, 0x2e, 0x90, 0x7e, 0x88, 0x80, 0x15, 0x4b, + 0xc7, 0x02, 0x79, 0x06, 0xa7, 0x84, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, + 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, + 0x72, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0xce, + 0xcd, 0x2f, 0x06, 0xf9, 0x4a, 0x37, 0x3d, 0x5f, 0xbf, 0xcc, 0x42, 0x3f, 0x37, 0x3f, 0xa5, 0x34, + 0x27, 0xb5, 0x18, 0xe2, 0x47, 0x5d, 0x98, 0x27, 0x0d, 0xcc, 0x75, 0x61, 0xa1, 0x60, 0x0d, 0x63, + 0x24, 0xb1, 0x81, 0xfd, 0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x4d, 0xa7, 0x5d, 0x5f, + 0x01, 0x00, 0x00, } func (m *ClientState) Marshal() (dAtA []byte, err error) { @@ -187,54 +126,6 @@ func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ConsensusState) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ConsensusState) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ConsensusState) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.NextValidatorsHash) > 0 { - i -= len(m.NextValidatorsHash) - copy(dAtA[i:], m.NextValidatorsHash) - i = encodeVarintCelestia(dAtA, i, uint64(len(m.NextValidatorsHash))) - i-- - dAtA[i] = 0x1a - } - { - size, err := m.Root.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintCelestia(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - n3, err3 := github_com_cosmos_gogoproto_types.StdTimeMarshalTo(m.Timestamp, dAtA[i-github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp):]) - if err3 != nil { - return 0, err3 - } - i -= n3 - i = encodeVarintCelestia(dAtA, i, uint64(n3)) - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil -} - func encodeVarintCelestia(dAtA []byte, offset int, v uint64) int { offset -= sovCelestia(v) base := offset @@ -259,23 +150,6 @@ func (m *ClientState) Size() (n int) { return n } -func (m *ConsensusState) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = github_com_cosmos_gogoproto_types.SizeOfStdTime(m.Timestamp) - n += 1 + l + sovCelestia(uint64(l)) - l = m.Root.Size() - n += 1 + l + sovCelestia(uint64(l)) - l = len(m.NextValidatorsHash) - if l > 0 { - n += 1 + l + sovCelestia(uint64(l)) - } - return n -} - func sovCelestia(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -368,156 +242,6 @@ func (m *ClientState) Unmarshal(dAtA []byte) error { } return nil } -func (m *ConsensusState) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCelestia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ConsensusState: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ConsensusState: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCelestia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthCelestia - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthCelestia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := github_com_cosmos_gogoproto_types.StdTimeUnmarshal(&m.Timestamp, dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Root", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCelestia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthCelestia - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthCelestia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Root.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field NextValidatorsHash", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCelestia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthCelestia - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthCelestia - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.NextValidatorsHash = append(m.NextValidatorsHash[:0], dAtA[iNdEx:postIndex]...) - if m.NextValidatorsHash == nil { - m.NextValidatorsHash = []byte{} - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipCelestia(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthCelestia - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func skipCelestia(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/modules/light-clients/07-celestia/consensus_state.go b/modules/light-clients/07-celestia/consensus_state.go deleted file mode 100644 index 92948d6bd14..00000000000 --- a/modules/light-clients/07-celestia/consensus_state.go +++ /dev/null @@ -1,63 +0,0 @@ -package celestia - -import ( - "time" - - errorsmod "cosmossdk.io/errors" - - cmtbytes "github.com/cometbft/cometbft/libs/bytes" - cmttypes "github.com/cometbft/cometbft/types" - - clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" - commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" - "github.com/cosmos/ibc-go/v8/modules/core/exported" -) - -// TODO: Maybe we cannot redefine consensus state if we are delegate client state calls to base client. -// See: GetConsensusState() func of 07-tendermint used in many method of ClientState implementaiton. Type assertion performed. -// Should be possible to reuse tendermint consensus state and these methods should continue to work. -// Root of 07-tendermint ConsensusState is just the data availability root instead of app hash. - -var _ exported.ConsensusState = (*ConsensusState)(nil) - -// NewConsensusState creates a new ConsensusState instance. -func NewConsensusState( - timestamp time.Time, root commitmenttypes.MerkleRoot, nextValsHash cmtbytes.HexBytes, -) *ConsensusState { - return &ConsensusState{ - Timestamp: timestamp, - Root: root, - NextValidatorsHash: nextValsHash, - } -} - -// ClientType returns Celestia -func (ConsensusState) ClientType() string { - return ModuleName -} - -// GetRoot returns the commitment Root for the specific -func (cs ConsensusState) GetRoot() exported.Root { - return cs.Root -} - -// GetTimestamp returns block time in nanoseconds of the header that created consensus state -func (cs ConsensusState) GetTimestamp() uint64 { - return uint64(cs.Timestamp.UnixNano()) -} - -// ValidateBasic defines a basic validation for the tendermint consensus state. -// NOTE: ProcessedTimestamp may be zero if this is an initial consensus state passed in by relayer -// as opposed to a consensus state constructed by the chain. -func (cs ConsensusState) ValidateBasic() error { - if cs.Root.Empty() { - return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, "root cannot be empty") - } - if err := cmttypes.ValidateHash(cs.NextValidatorsHash); err != nil { - return errorsmod.Wrap(err, "next validators hash is invalid") - } - if cs.Timestamp.Unix() <= 0 { - return errorsmod.Wrap(clienttypes.ErrInvalidConsensus, "timestamp must be a positive Unix time") - } - return nil -} diff --git a/modules/light-clients/07-celestia/update.go b/modules/light-clients/07-celestia/update.go index d9d73449af0..9010382a46f 100644 --- a/modules/light-clients/07-celestia/update.go +++ b/modules/light-clients/07-celestia/update.go @@ -1,28 +1,60 @@ package celestia import ( + fmt "fmt" + storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + commitmenttypes "github.com/cosmos/ibc-go/v8/modules/core/23-commitment/types" + host "github.com/cosmos/ibc-go/v8/modules/core/24-host" "github.com/cosmos/ibc-go/v8/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" ) // VerifyClientMessage implements exported.ClientState. -func (*ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) error { - panic("unimplemented") +func (cs *ClientState) VerifyClientMessage(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) error { + return cs.BaseClient.VerifyClientMessage(ctx, cdc, clientStore, clientMsg) } // UpdateState implements exported.ClientState. -func (*ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) []exported.Height { - panic("unimplemented") +func (cs *ClientState) UpdateState(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) []exported.Height { + header, ok := clientMsg.(*ibctm.Header) + if !ok { + panic(fmt.Errorf("expected type %T, got %T", &ibctm.Header{}, clientMsg)) + } + + // perform regular 07-tendermint client update step + heights := cs.BaseClient.UpdateState(ctx, cdc, clientStore, clientMsg) + + // overwrite the consensus state with a new consensus state containing the data hash as commitment root + consensusState := &ibctm.ConsensusState{ + Timestamp: header.GetTime(), + Root: commitmenttypes.NewMerkleRoot(header.Header.GetDataHash()), + NextValidatorsHash: header.Header.NextValidatorsHash, + } + + setConsensusState(clientStore, cdc, consensusState, header.GetHeight()) + + return heights +} + +// setConsensusState stores the consensus state at the given height. +func setConsensusState(clientStore storetypes.KVStore, cdc codec.BinaryCodec, consensusState *ibctm.ConsensusState, height exported.Height) { + key := host.ConsensusStateKey(height) + val := clienttypes.MustMarshalConsensusState(cdc, consensusState) + clientStore.Set(key, val) } // CheckForMisbehaviour implements exported.ClientState. -func (*ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) bool { - panic("unimplemented") +func (cs *ClientState) CheckForMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) bool { + return cs.BaseClient.CheckForMisbehaviour(ctx, cdc, clientStore, clientMsg) } // UpdateStateOnMisbehaviour implements exported.ClientState. -func (*ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) { - panic("unimplemented") +func (cs *ClientState) UpdateStateOnMisbehaviour(ctx sdk.Context, cdc codec.BinaryCodec, clientStore storetypes.KVStore, clientMsg exported.ClientMessage) { + cs.BaseClient.UpdateStateOnMisbehaviour(ctx, cdc, clientStore, clientMsg) } diff --git a/proto/ibc/lightclients/celestia/v1/celestia.proto b/proto/ibc/lightclients/celestia/v1/celestia.proto index bdd2bfd783f..96011f66e02 100644 --- a/proto/ibc/lightclients/celestia/v1/celestia.proto +++ b/proto/ibc/lightclients/celestia/v1/celestia.proto @@ -4,8 +4,6 @@ package ibc.lightclients.celestia.v1; option go_package = "github.com/cosmos/ibc-go/v8/modules/light-clients/07-celestia;celestia"; -import "google/protobuf/timestamp.proto"; -import "ibc/core/commitment/v1/commitment.proto"; import "ibc/lightclients/tendermint/v1/tendermint.proto"; import "gogoproto/gogo.proto"; @@ -16,15 +14,3 @@ message ClientState { ibc.lightclients.tendermint.v1.ClientState base_client = 1; } - -// ConsensusState defines the consensus state from Tendermint. -message ConsensusState { - option (gogoproto.goproto_getters) = false; - - // timestamp that corresponds to the block height in which the ConsensusState - // was stored. - google.protobuf.Timestamp timestamp = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true]; - // commitment root (i.e data availability root) - ibc.core.commitment.v1.MerkleRoot root = 2 [(gogoproto.nullable) = false]; - bytes next_validators_hash = 3 [(gogoproto.casttype) = "github.com/cometbft/cometbft/libs/bytes.HexBytes"]; -} From b6e8ec995212a6e0a767594fd7ef4f0a4dd5a03d Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 15:58:48 +0100 Subject: [PATCH 08/14] chore: rm codec registration of removed consensus state type --- modules/light-clients/07-celestia/codec.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/light-clients/07-celestia/codec.go b/modules/light-clients/07-celestia/codec.go index 06276c51320..5f2b85f11ae 100644 --- a/modules/light-clients/07-celestia/codec.go +++ b/modules/light-clients/07-celestia/codec.go @@ -13,8 +13,4 @@ func RegisterInterfaces(registry codectypes.InterfaceRegistry) { (*exported.ClientState)(nil), &ClientState{}, ) - registry.RegisterImplementations( - (*exported.ConsensusState)(nil), - &ConsensusState{}, - ) } From 8d238f830d894201861333fd526fc0241bcd2ad9 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 16:24:59 +0100 Subject: [PATCH 09/14] wip: begin putting code into verifyMembership --- .../light-clients/07-celestia/client_state.go | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/modules/light-clients/07-celestia/client_state.go b/modules/light-clients/07-celestia/client_state.go index 617de563615..06b1afb3943 100644 --- a/modules/light-clients/07-celestia/client_state.go +++ b/modules/light-clients/07-celestia/client_state.go @@ -1,11 +1,16 @@ package celestia import ( + errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + clienttypes "github.com/cosmos/ibc-go/v8/modules/core/02-client/types" + ibcerrors "github.com/cosmos/ibc-go/v8/modules/core/errors" "github.com/cosmos/ibc-go/v8/modules/core/exported" + ibctm "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" ) var _ exported.ClientState = (*ClientState)(nil) @@ -41,11 +46,75 @@ func (cs *ClientState) Validate() error { } // VerifyMembership implements exported.ClientState. -func (*ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path exported.Path, value []byte) error { - panic("unimplemented") +func (cs *ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path exported.Path, value []byte) error { + if cs.BaseClient.GetLatestHeight().LT(height) { + return errorsmod.Wrapf( + ibcerrors.ErrInvalidHeight, + "client state height < proof height (%d < %d), please ensure the client has been updated", cs.GetLatestHeight(), height, + ) + } + + // TODO: revise and look into delay periods for this + if err := verifyDelayPeriodPassed(ctx, clientStore, height, delayTimePeriod, delayBlockPeriod); err != nil { + return err + } + + // var shareProof celestiatypes.ShareProof + // if err := cdc.Unmarshal(proof, &shareProof); err != nil { + // return err + // } + + // consensusState, found := ibctm.GetConsensusState(clientStore, cdc, height) + // if !found { + // return errorsmod.Wrap(clienttypes.ErrConsensusStateNotFound, "please ensure the proof was constructed against a height that exists on the client") + // } + + // return shareProof.Validate(consensusState.GetRoot()) + return nil } // VerifyNonMembership implements exported.ClientState. func (*ClientState) VerifyNonMembership(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path exported.Path) error { panic("unimplemented") } + +// verifyDelayPeriodPassed will ensure that at least delayTimePeriod amount of time and delayBlockPeriod number of blocks have passed +// since consensus state was submitted before allowing verification to continue. +func verifyDelayPeriodPassed(ctx sdk.Context, store storetypes.KVStore, proofHeight exported.Height, delayTimePeriod, delayBlockPeriod uint64) error { + if delayTimePeriod != 0 { + // check that executing chain's timestamp has passed consensusState's processed time + delay time period + processedTime, ok := ibctm.GetProcessedTime(store, proofHeight) + if !ok { + return errorsmod.Wrapf(ibctm.ErrProcessedTimeNotFound, "processed time not found for height: %s", proofHeight) + } + + currentTimestamp := uint64(ctx.BlockTime().UnixNano()) + validTime := processedTime + delayTimePeriod + + // NOTE: delay time period is inclusive, so if currentTimestamp is validTime, then we return no error + if currentTimestamp < validTime { + return errorsmod.Wrapf(ibctm.ErrDelayPeriodNotPassed, "cannot verify packet until time: %d, current time: %d", + validTime, currentTimestamp) + } + + } + + if delayBlockPeriod != 0 { + // check that executing chain's height has passed consensusState's processed height + delay block period + processedHeight, ok := ibctm.GetProcessedHeight(store, proofHeight) + if !ok { + return errorsmod.Wrapf(ibctm.ErrProcessedHeightNotFound, "processed height not found for height: %s", proofHeight) + } + + currentHeight := clienttypes.GetSelfHeight(ctx) + validHeight := clienttypes.NewHeight(processedHeight.GetRevisionNumber(), processedHeight.GetRevisionHeight()+delayBlockPeriod) + + // NOTE: delay block period is inclusive, so if currentHeight is validHeight, then we return no error + if currentHeight.LT(validHeight) { + return errorsmod.Wrapf(ibctm.ErrDelayPeriodNotPassed, "cannot verify packet until height: %s, current height: %s", + validHeight, currentHeight) + } + } + + return nil +} From 1e9470493da3a109f428c6f0763aa500c28b3745 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 16:46:46 +0100 Subject: [PATCH 10/14] chore: add share proof protos and code to celestia pkg --- go.mod | 1 + go.sum | 2 + .../light-clients/07-celestia/celestia.pb.go | 1185 ++++++++++++++++- .../light-clients/07-celestia/row_proof.go | 75 ++ .../light-clients/07-celestia/share_proof.go | 132 ++ .../lightclients/celestia/v1/celestia.proto | 45 +- 6 files changed, 1385 insertions(+), 55 deletions(-) create mode 100644 modules/light-clients/07-celestia/row_proof.go create mode 100644 modules/light-clients/07-celestia/share_proof.go diff --git a/go.mod b/go.mod index f14f6fc5ebe..24ed0f738ab 100644 --- a/go.mod +++ b/go.mod @@ -55,6 +55,7 @@ require ( github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.8.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/celestiaorg/nmt v0.20.0 // indirect github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect diff --git a/go.sum b/go.sum index bd7481ce651..aa4065d2934 100644 --- a/go.sum +++ b/go.sum @@ -283,6 +283,8 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/celestiaorg/nmt v0.20.0 h1:9i7ultZ8Wv5ytt8ZRaxKQ5KOOMo4A2K2T/aPGjIlSas= +github.com/celestiaorg/nmt v0.20.0/go.mod h1:Oz15Ub6YPez9uJV0heoU4WpFctxazuIhKyUtaYNio7E= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= diff --git a/modules/light-clients/07-celestia/celestia.pb.go b/modules/light-clients/07-celestia/celestia.pb.go index c702d6c5090..41f7416c7cc 100644 --- a/modules/light-clients/07-celestia/celestia.pb.go +++ b/modules/light-clients/07-celestia/celestia.pb.go @@ -5,6 +5,7 @@ package celestia import ( fmt "fmt" + crypto "github.com/cometbft/cometbft/proto/tendermint/crypto" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" _07_tendermint "github.com/cosmos/ibc-go/v8/modules/light-clients/07-tendermint" @@ -63,8 +64,250 @@ func (m *ClientState) XXX_DiscardUnknown() { var xxx_messageInfo_ClientState proto.InternalMessageInfo +// ShareProof is an NMT proof that a set of shares exist in a set of rows and a +// Merkle proof that those rows exist in a Merkle tree with a given data root. +type ShareProof struct { + Data [][]byte `protobuf:"bytes,1,rep,name=data,proto3" json:"data,omitempty"` + ShareProofs []*NMTProof `protobuf:"bytes,2,rep,name=share_proofs,json=shareProofs,proto3" json:"share_proofs,omitempty"` + NamespaceId []byte `protobuf:"bytes,3,opt,name=namespace_id,json=namespaceId,proto3" json:"namespace_id,omitempty"` + RowProof *RowProof `protobuf:"bytes,4,opt,name=row_proof,json=rowProof,proto3" json:"row_proof,omitempty"` + NamespaceVersion uint32 `protobuf:"varint,5,opt,name=namespace_version,json=namespaceVersion,proto3" json:"namespace_version,omitempty"` +} + +func (m *ShareProof) Reset() { *m = ShareProof{} } +func (m *ShareProof) String() string { return proto.CompactTextString(m) } +func (*ShareProof) ProtoMessage() {} +func (*ShareProof) Descriptor() ([]byte, []int) { + return fileDescriptor_1a7b0753ec3219d3, []int{1} +} +func (m *ShareProof) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *ShareProof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_ShareProof.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *ShareProof) XXX_Merge(src proto.Message) { + xxx_messageInfo_ShareProof.Merge(m, src) +} +func (m *ShareProof) XXX_Size() int { + return m.Size() +} +func (m *ShareProof) XXX_DiscardUnknown() { + xxx_messageInfo_ShareProof.DiscardUnknown(m) +} + +var xxx_messageInfo_ShareProof proto.InternalMessageInfo + +func (m *ShareProof) GetData() [][]byte { + if m != nil { + return m.Data + } + return nil +} + +func (m *ShareProof) GetShareProofs() []*NMTProof { + if m != nil { + return m.ShareProofs + } + return nil +} + +func (m *ShareProof) GetNamespaceId() []byte { + if m != nil { + return m.NamespaceId + } + return nil +} + +func (m *ShareProof) GetRowProof() *RowProof { + if m != nil { + return m.RowProof + } + return nil +} + +func (m *ShareProof) GetNamespaceVersion() uint32 { + if m != nil { + return m.NamespaceVersion + } + return 0 +} + +// RowProof is a Merkle proof that a set of rows exist in a Merkle tree with a +// given data root. +type RowProof struct { + RowRoots [][]byte `protobuf:"bytes,1,rep,name=row_roots,json=rowRoots,proto3" json:"row_roots,omitempty"` + Proofs []*crypto.Proof `protobuf:"bytes,2,rep,name=proofs,proto3" json:"proofs,omitempty"` + Root []byte `protobuf:"bytes,3,opt,name=root,proto3" json:"root,omitempty"` + StartRow uint32 `protobuf:"varint,4,opt,name=start_row,json=startRow,proto3" json:"start_row,omitempty"` + EndRow uint32 `protobuf:"varint,5,opt,name=end_row,json=endRow,proto3" json:"end_row,omitempty"` +} + +func (m *RowProof) Reset() { *m = RowProof{} } +func (m *RowProof) String() string { return proto.CompactTextString(m) } +func (*RowProof) ProtoMessage() {} +func (*RowProof) Descriptor() ([]byte, []int) { + return fileDescriptor_1a7b0753ec3219d3, []int{2} +} +func (m *RowProof) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *RowProof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_RowProof.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *RowProof) XXX_Merge(src proto.Message) { + xxx_messageInfo_RowProof.Merge(m, src) +} +func (m *RowProof) XXX_Size() int { + return m.Size() +} +func (m *RowProof) XXX_DiscardUnknown() { + xxx_messageInfo_RowProof.DiscardUnknown(m) +} + +var xxx_messageInfo_RowProof proto.InternalMessageInfo + +func (m *RowProof) GetRowRoots() [][]byte { + if m != nil { + return m.RowRoots + } + return nil +} + +func (m *RowProof) GetProofs() []*crypto.Proof { + if m != nil { + return m.Proofs + } + return nil +} + +func (m *RowProof) GetRoot() []byte { + if m != nil { + return m.Root + } + return nil +} + +func (m *RowProof) GetStartRow() uint32 { + if m != nil { + return m.StartRow + } + return 0 +} + +func (m *RowProof) GetEndRow() uint32 { + if m != nil { + return m.EndRow + } + return 0 +} + +// NMTProof is a proof of a namespace.ID in an NMT. +// In case this proof proves the absence of a namespace.ID +// in a tree it also contains the leaf hashes of the range +// where that namespace would be. +type NMTProof struct { + // Start index of this proof. + Start int32 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` + // End index of this proof. + End int32 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` + // Nodes that together with the corresponding leaf values can be used to + // recompute the root and verify this proof. Nodes should consist of the max + // and min namespaces along with the actual hash, resulting in each being 48 + // bytes each + Nodes [][]byte `protobuf:"bytes,3,rep,name=nodes,proto3" json:"nodes,omitempty"` + // leafHash are nil if the namespace is present in the NMT. In case the + // namespace to be proved is in the min/max range of the tree but absent, this + // will contain the leaf hash necessary to verify the proof of absence. Leaf + // hashes should consist of the namespace along with the actual hash, + // resulting 40 bytes total. + LeafHash []byte `protobuf:"bytes,4,opt,name=leaf_hash,json=leafHash,proto3" json:"leaf_hash,omitempty"` +} + +func (m *NMTProof) Reset() { *m = NMTProof{} } +func (m *NMTProof) String() string { return proto.CompactTextString(m) } +func (*NMTProof) ProtoMessage() {} +func (*NMTProof) Descriptor() ([]byte, []int) { + return fileDescriptor_1a7b0753ec3219d3, []int{3} +} +func (m *NMTProof) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *NMTProof) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_NMTProof.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *NMTProof) XXX_Merge(src proto.Message) { + xxx_messageInfo_NMTProof.Merge(m, src) +} +func (m *NMTProof) XXX_Size() int { + return m.Size() +} +func (m *NMTProof) XXX_DiscardUnknown() { + xxx_messageInfo_NMTProof.DiscardUnknown(m) +} + +var xxx_messageInfo_NMTProof proto.InternalMessageInfo + +func (m *NMTProof) GetStart() int32 { + if m != nil { + return m.Start + } + return 0 +} + +func (m *NMTProof) GetEnd() int32 { + if m != nil { + return m.End + } + return 0 +} + +func (m *NMTProof) GetNodes() [][]byte { + if m != nil { + return m.Nodes + } + return nil +} + +func (m *NMTProof) GetLeafHash() []byte { + if m != nil { + return m.LeafHash + } + return nil +} + func init() { proto.RegisterType((*ClientState)(nil), "ibc.lightclients.celestia.v1.ClientState") + proto.RegisterType((*ShareProof)(nil), "ibc.lightclients.celestia.v1.ShareProof") + proto.RegisterType((*RowProof)(nil), "ibc.lightclients.celestia.v1.RowProof") + proto.RegisterType((*NMTProof)(nil), "ibc.lightclients.celestia.v1.NMTProof") } func init() { @@ -72,23 +315,40 @@ func init() { } var fileDescriptor_1a7b0753ec3219d3 = []byte{ - // 243 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0xce, 0x4c, 0x4a, 0xd6, - 0xcf, 0xc9, 0x4c, 0xcf, 0x28, 0x49, 0xce, 0xc9, 0x4c, 0xcd, 0x2b, 0x29, 0xd6, 0x4f, 0x4e, 0xcd, - 0x49, 0x2d, 0x2e, 0xc9, 0x4c, 0xd4, 0x2f, 0x33, 0x84, 0xb3, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, - 0x85, 0x64, 0x32, 0x93, 0x92, 0xf5, 0x90, 0x15, 0xeb, 0xc1, 0x15, 0x94, 0x19, 0x4a, 0xe9, 0x63, - 0x18, 0x55, 0x92, 0x9a, 0x97, 0x92, 0x5a, 0x94, 0x9b, 0x99, 0x57, 0x02, 0x32, 0x0c, 0xc1, 0x83, - 0x18, 0x27, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x66, 0xea, 0x83, 0x58, 0x10, 0x51, 0xa5, 0x44, - 0x2e, 0x6e, 0x67, 0xb0, 0xfe, 0xe0, 0x92, 0xc4, 0x92, 0x54, 0x21, 0x1f, 0x2e, 0xee, 0xa4, 0xc4, - 0xe2, 0xd4, 0x78, 0x88, 0x99, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0xda, 0x7a, 0x18, 0x2e, - 0x41, 0x32, 0xbd, 0xcc, 0x50, 0x0f, 0xc9, 0x84, 0x20, 0x2e, 0x90, 0x7e, 0x88, 0x80, 0x15, 0x4b, - 0xc7, 0x02, 0x79, 0x06, 0xa7, 0x84, 0x13, 0x8f, 0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, - 0x48, 0x8e, 0x71, 0xc2, 0x63, 0x39, 0x86, 0x0b, 0x8f, 0xe5, 0x18, 0x6e, 0x3c, 0x96, 0x63, 0x88, - 0x72, 0x4b, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0x2f, 0xce, - 0xcd, 0x2f, 0x06, 0xf9, 0x4a, 0x37, 0x3d, 0x5f, 0xbf, 0xcc, 0x42, 0x3f, 0x37, 0x3f, 0xa5, 0x34, - 0x27, 0xb5, 0x18, 0xe2, 0x47, 0x5d, 0x98, 0x27, 0x0d, 0xcc, 0x75, 0x61, 0xa1, 0x60, 0x0d, 0x63, - 0x24, 0xb1, 0x81, 0xfd, 0x62, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x1c, 0x4d, 0xa7, 0x5d, 0x5f, - 0x01, 0x00, 0x00, + // 523 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x52, 0xcf, 0x8b, 0xd3, 0x40, + 0x14, 0x6e, 0xb6, 0x3f, 0xac, 0x93, 0x2e, 0xac, 0xc3, 0x82, 0x61, 0xd5, 0x58, 0x7b, 0x90, 0x42, + 0x69, 0x66, 0xbb, 0x1e, 0x14, 0xbd, 0xb9, 0x20, 0x2e, 0xa8, 0xc8, 0xac, 0x78, 0xf0, 0x52, 0xa7, + 0xc9, 0x6c, 0x13, 0x48, 0xf2, 0xca, 0xcc, 0x6c, 0x82, 0x37, 0x8f, 0x1e, 0xfd, 0x13, 0x04, 0xff, + 0x19, 0x8f, 0x7b, 0xf4, 0x28, 0xed, 0x3f, 0x22, 0x33, 0x93, 0xc4, 0xc8, 0x82, 0xde, 0xbe, 0xf7, + 0xcd, 0x7b, 0xdf, 0xf7, 0xde, 0x9b, 0x87, 0x66, 0xc9, 0x2a, 0x24, 0x69, 0xb2, 0x8e, 0x55, 0x98, + 0x26, 0x3c, 0x57, 0x92, 0x84, 0x3c, 0xe5, 0x52, 0x25, 0x8c, 0x14, 0x8b, 0x06, 0x07, 0x1b, 0x01, + 0x0a, 0xf0, 0xdd, 0x64, 0x15, 0x06, 0xed, 0xe4, 0xa0, 0x49, 0x28, 0x16, 0x47, 0xf7, 0x14, 0xcf, + 0x23, 0x2e, 0xb2, 0x24, 0x57, 0x24, 0x14, 0x9f, 0x36, 0x0a, 0xc8, 0x46, 0x00, 0x5c, 0xd8, 0xe2, + 0xa3, 0xc3, 0x35, 0xac, 0xc1, 0x40, 0xa2, 0x51, 0xc5, 0x92, 0x6b, 0xfe, 0x2d, 0x95, 0x62, 0xd1, + 0x8a, 0x6c, 0xc1, 0x84, 0x21, 0xf7, 0xd4, 0x64, 0x9e, 0x2b, 0xa6, 0x38, 0x7e, 0x85, 0xdc, 0x15, + 0x93, 0x7c, 0x69, 0xab, 0x3d, 0x67, 0xec, 0x4c, 0xdd, 0x93, 0x59, 0x70, 0xad, 0xd1, 0x96, 0x4e, + 0xb1, 0x08, 0x5a, 0x0a, 0x14, 0xe9, 0x7a, 0x4b, 0x3c, 0xed, 0x7d, 0xf9, 0x76, 0xbf, 0x33, 0xf9, + 0xbc, 0x87, 0xd0, 0x79, 0xcc, 0x04, 0x7f, 0xab, 0xdb, 0xc7, 0x18, 0xf5, 0x22, 0xa6, 0x98, 0xe7, + 0x8c, 0xbb, 0xd3, 0x11, 0x35, 0x18, 0x9f, 0xa1, 0x91, 0xd4, 0x19, 0x4b, 0x33, 0xa1, 0xf4, 0xf6, + 0xc6, 0xdd, 0xa9, 0x7b, 0xf2, 0x30, 0xf8, 0xd7, 0x82, 0x82, 0x37, 0xaf, 0xdf, 0x19, 0x45, 0xea, + 0xca, 0x46, 0x5d, 0xe2, 0x07, 0x68, 0x94, 0xb3, 0x8c, 0xcb, 0x0d, 0x0b, 0xf9, 0x32, 0x89, 0xbc, + 0xee, 0xd8, 0x99, 0x8e, 0xa8, 0xdb, 0x70, 0x67, 0x11, 0x3e, 0x45, 0x37, 0x05, 0x94, 0xd6, 0xcb, + 0xeb, 0x99, 0x11, 0xff, 0x63, 0x45, 0xa1, 0xb4, 0x56, 0x43, 0x51, 0x21, 0x3c, 0x43, 0xb7, 0xfe, + 0xf8, 0x14, 0x5c, 0xc8, 0x04, 0x72, 0xaf, 0x3f, 0x76, 0xa6, 0xfb, 0xf4, 0xa0, 0x79, 0x78, 0x6f, + 0xf9, 0xc9, 0x77, 0x07, 0x0d, 0x6b, 0x0d, 0x7c, 0xc7, 0xda, 0x0b, 0x00, 0x25, 0xab, 0x2d, 0x68, + 0x59, 0xaa, 0x63, 0x7c, 0x8c, 0x06, 0x7f, 0xed, 0xc0, 0x6b, 0xaf, 0xda, 0x9e, 0x41, 0x60, 0x5b, + 0xa9, 0xf2, 0xf4, 0x3e, 0xb5, 0x54, 0x35, 0xa8, 0xc1, 0xda, 0x42, 0x2a, 0x26, 0xd4, 0x52, 0x40, + 0x69, 0x26, 0xdc, 0xa7, 0x43, 0x43, 0x50, 0x28, 0xf1, 0x6d, 0x74, 0x83, 0xe7, 0x91, 0x79, 0xb2, + 0xfd, 0x0e, 0x78, 0x1e, 0x51, 0x28, 0x27, 0x1c, 0x0d, 0xeb, 0x9d, 0xe2, 0x43, 0xd4, 0x37, 0x05, + 0xe6, 0x04, 0xfa, 0xd4, 0x06, 0xf8, 0x00, 0x75, 0x79, 0x1e, 0x79, 0x7b, 0x86, 0xd3, 0x50, 0xe7, + 0xe5, 0x10, 0x71, 0xe9, 0x75, 0xcd, 0x20, 0x36, 0xd0, 0xfe, 0x29, 0x67, 0x17, 0xcb, 0x98, 0xc9, + 0xd8, 0xf8, 0x8f, 0xe8, 0x50, 0x13, 0x2f, 0x99, 0x8c, 0x9f, 0x7f, 0xfc, 0xb1, 0xf5, 0x9d, 0xab, + 0xad, 0xef, 0xfc, 0xda, 0xfa, 0xce, 0xd7, 0x9d, 0xdf, 0xb9, 0xda, 0xf9, 0x9d, 0x9f, 0x3b, 0xbf, + 0xf3, 0xe1, 0xc5, 0x3a, 0x51, 0xf1, 0xe5, 0x2a, 0x08, 0x21, 0x23, 0x21, 0xc8, 0x0c, 0xa4, 0xbe, + 0xe7, 0xf9, 0x1a, 0x48, 0xf1, 0x84, 0x64, 0x10, 0x5d, 0xa6, 0x5c, 0xda, 0xeb, 0x9e, 0xd7, 0xe7, + 0x7d, 0xfc, 0x78, 0x5e, 0x7f, 0xd4, 0xb3, 0x1a, 0xac, 0x06, 0xe6, 0xb6, 0x1f, 0xfd, 0x0e, 0x00, + 0x00, 0xff, 0xff, 0xbd, 0xdc, 0x10, 0x6a, 0x8e, 0x03, 0x00, 0x00, } func (m *ClientState) Marshal() (dAtA []byte, err error) { @@ -126,6 +386,188 @@ func (m *ClientState) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *ShareProof) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *ShareProof) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *ShareProof) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.NamespaceVersion != 0 { + i = encodeVarintCelestia(dAtA, i, uint64(m.NamespaceVersion)) + i-- + dAtA[i] = 0x28 + } + if m.RowProof != nil { + { + size, err := m.RowProof.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCelestia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x22 + } + if len(m.NamespaceId) > 0 { + i -= len(m.NamespaceId) + copy(dAtA[i:], m.NamespaceId) + i = encodeVarintCelestia(dAtA, i, uint64(len(m.NamespaceId))) + i-- + dAtA[i] = 0x1a + } + if len(m.ShareProofs) > 0 { + for iNdEx := len(m.ShareProofs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ShareProofs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCelestia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.Data) > 0 { + for iNdEx := len(m.Data) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Data[iNdEx]) + copy(dAtA[i:], m.Data[iNdEx]) + i = encodeVarintCelestia(dAtA, i, uint64(len(m.Data[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *RowProof) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *RowProof) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *RowProof) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.EndRow != 0 { + i = encodeVarintCelestia(dAtA, i, uint64(m.EndRow)) + i-- + dAtA[i] = 0x28 + } + if m.StartRow != 0 { + i = encodeVarintCelestia(dAtA, i, uint64(m.StartRow)) + i-- + dAtA[i] = 0x20 + } + if len(m.Root) > 0 { + i -= len(m.Root) + copy(dAtA[i:], m.Root) + i = encodeVarintCelestia(dAtA, i, uint64(len(m.Root))) + i-- + dAtA[i] = 0x1a + } + if len(m.Proofs) > 0 { + for iNdEx := len(m.Proofs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Proofs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintCelestia(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } + if len(m.RowRoots) > 0 { + for iNdEx := len(m.RowRoots) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.RowRoots[iNdEx]) + copy(dAtA[i:], m.RowRoots[iNdEx]) + i = encodeVarintCelestia(dAtA, i, uint64(len(m.RowRoots[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func (m *NMTProof) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *NMTProof) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *NMTProof) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.LeafHash) > 0 { + i -= len(m.LeafHash) + copy(dAtA[i:], m.LeafHash) + i = encodeVarintCelestia(dAtA, i, uint64(len(m.LeafHash))) + i-- + dAtA[i] = 0x22 + } + if len(m.Nodes) > 0 { + for iNdEx := len(m.Nodes) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Nodes[iNdEx]) + copy(dAtA[i:], m.Nodes[iNdEx]) + i = encodeVarintCelestia(dAtA, i, uint64(len(m.Nodes[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if m.End != 0 { + i = encodeVarintCelestia(dAtA, i, uint64(m.End)) + i-- + dAtA[i] = 0x10 + } + if m.Start != 0 { + i = encodeVarintCelestia(dAtA, i, uint64(m.Start)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func encodeVarintCelestia(dAtA []byte, offset int, v uint64) int { offset -= sovCelestia(v) base := offset @@ -150,45 +592,133 @@ func (m *ClientState) Size() (n int) { return n } -func sovCelestia(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozCelestia(x uint64) (n int) { - return sovCelestia(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *ClientState) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowCelestia - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ClientState: wiretype end group for non-group") +func (m *ShareProof) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.Data) > 0 { + for _, b := range m.Data { + l = len(b) + n += 1 + l + sovCelestia(uint64(l)) } - if fieldNum <= 0 { - return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire) + } + if len(m.ShareProofs) > 0 { + for _, e := range m.ShareProofs { + l = e.Size() + n += 1 + l + sovCelestia(uint64(l)) } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field BaseClient", wireType) - } + } + l = len(m.NamespaceId) + if l > 0 { + n += 1 + l + sovCelestia(uint64(l)) + } + if m.RowProof != nil { + l = m.RowProof.Size() + n += 1 + l + sovCelestia(uint64(l)) + } + if m.NamespaceVersion != 0 { + n += 1 + sovCelestia(uint64(m.NamespaceVersion)) + } + return n +} + +func (m *RowProof) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.RowRoots) > 0 { + for _, b := range m.RowRoots { + l = len(b) + n += 1 + l + sovCelestia(uint64(l)) + } + } + if len(m.Proofs) > 0 { + for _, e := range m.Proofs { + l = e.Size() + n += 1 + l + sovCelestia(uint64(l)) + } + } + l = len(m.Root) + if l > 0 { + n += 1 + l + sovCelestia(uint64(l)) + } + if m.StartRow != 0 { + n += 1 + sovCelestia(uint64(m.StartRow)) + } + if m.EndRow != 0 { + n += 1 + sovCelestia(uint64(m.EndRow)) + } + return n +} + +func (m *NMTProof) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Start != 0 { + n += 1 + sovCelestia(uint64(m.Start)) + } + if m.End != 0 { + n += 1 + sovCelestia(uint64(m.End)) + } + if len(m.Nodes) > 0 { + for _, b := range m.Nodes { + l = len(b) + n += 1 + l + sovCelestia(uint64(l)) + } + } + l = len(m.LeafHash) + if l > 0 { + n += 1 + l + sovCelestia(uint64(l)) + } + return n +} + +func sovCelestia(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozCelestia(x uint64) (n int) { + return sovCelestia(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *ClientState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ClientState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ClientState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BaseClient", wireType) + } var msglen int for shift := uint(0); ; shift += 7 { if shift >= 64 { @@ -242,6 +772,553 @@ func (m *ClientState) Unmarshal(dAtA []byte) error { } return nil } +func (m *ShareProof) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: ShareProof: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: ShareProof: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Data = append(m.Data, make([]byte, postIndex-iNdEx)) + copy(m.Data[len(m.Data)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ShareProofs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ShareProofs = append(m.ShareProofs, &NMTProof{}) + if err := m.ShareProofs[len(m.ShareProofs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field NamespaceId", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.NamespaceId = append(m.NamespaceId[:0], dAtA[iNdEx:postIndex]...) + if m.NamespaceId == nil { + m.NamespaceId = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RowProof", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.RowProof == nil { + m.RowProof = &RowProof{} + } + if err := m.RowProof.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field NamespaceVersion", wireType) + } + m.NamespaceVersion = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.NamespaceVersion |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipCelestia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCelestia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *RowProof) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: RowProof: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: RowProof: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field RowRoots", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.RowRoots = append(m.RowRoots, make([]byte, postIndex-iNdEx)) + copy(m.RowRoots[len(m.RowRoots)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Proofs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Proofs = append(m.Proofs, &crypto.Proof{}) + if err := m.Proofs[len(m.Proofs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Root", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Root = append(m.Root[:0], dAtA[iNdEx:postIndex]...) + if m.Root == nil { + m.Root = []byte{} + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field StartRow", wireType) + } + m.StartRow = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.StartRow |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field EndRow", wireType) + } + m.EndRow = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.EndRow |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipCelestia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCelestia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *NMTProof) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: NMTProof: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: NMTProof: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Start", wireType) + } + m.Start = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Start |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field End", wireType) + } + m.End = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.End |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Nodes", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Nodes = append(m.Nodes, make([]byte, postIndex-iNdEx)) + copy(m.Nodes[len(m.Nodes)-1], dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field LeafHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowCelestia + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthCelestia + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthCelestia + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.LeafHash = append(m.LeafHash[:0], dAtA[iNdEx:postIndex]...) + if m.LeafHash == nil { + m.LeafHash = []byte{} + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipCelestia(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthCelestia + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipCelestia(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/modules/light-clients/07-celestia/row_proof.go b/modules/light-clients/07-celestia/row_proof.go new file mode 100644 index 00000000000..c75b7e81e68 --- /dev/null +++ b/modules/light-clients/07-celestia/row_proof.go @@ -0,0 +1,75 @@ +package celestia + +import ( + "errors" + "fmt" + + "github.com/cometbft/cometbft/crypto/merkle" + tmbytes "github.com/cometbft/cometbft/libs/bytes" +) + +// RowProof is a Merkle proof that a set of rows exist in a Merkle tree with a +// given data root. +type rowProof struct { + // RowRoots are the roots of the rows being proven. + RowRoots []tmbytes.HexBytes `json:"row_roots"` + // Proofs is a list of Merkle proofs where each proof proves that a row + // exists in a Merkle tree with a given data root. + Proofs []*merkle.Proof `json:"proofs"` + StartRow uint32 `json:"start_row"` + EndRow uint32 `json:"end_row"` +} + +// Validate performs checks on the fields of this RowProof. Returns an error if +// the proof fails validation. If the proof passes validation, this function +// attempts to verify the proof. It returns nil if the proof is valid. +func (rp rowProof) Validate(root []byte) error { + // HACKHACK performing subtraction with unsigned integers is unsafe. + if int(rp.EndRow-rp.StartRow+1) != len(rp.RowRoots) { + return fmt.Errorf("the number of rows %d must equal the number of row roots %d", int(rp.EndRow-rp.StartRow+1), len(rp.RowRoots)) + } + if len(rp.Proofs) != len(rp.RowRoots) { + return fmt.Errorf("the number of proofs %d must equal the number of row roots %d", len(rp.Proofs), len(rp.RowRoots)) + } + if !rp.VerifyProof(root) { + return errors.New("row proof failed to verify") + } + + return nil +} + +// VerifyProof verifies that all the row roots in this RowProof exist in a +// Merkle tree with the given root. Returns true if all proofs are valid. +func (rp rowProof) VerifyProof(root []byte) bool { + for i, proof := range rp.Proofs { + err := proof.Verify(root, rp.RowRoots[i]) + if err != nil { + return false + } + } + return true +} + +func RowProofFromProto(p *RowProof) rowProof { + if p == nil { + return rowProof{} + } + rowRoots := make([]tmbytes.HexBytes, len(p.RowRoots)) + rowProofs := make([]*merkle.Proof, len(p.Proofs)) + for i := range p.Proofs { + rowRoots[i] = p.RowRoots[i] + rowProofs[i] = &merkle.Proof{ + Total: p.Proofs[i].Total, + Index: p.Proofs[i].Index, + LeafHash: p.Proofs[i].LeafHash, + Aunts: p.Proofs[i].Aunts, + } + } + + return rowProof{ + RowRoots: rowRoots, + Proofs: rowProofs, + StartRow: p.StartRow, + EndRow: p.EndRow, + } +} diff --git a/modules/light-clients/07-celestia/share_proof.go b/modules/light-clients/07-celestia/share_proof.go new file mode 100644 index 00000000000..fc780ec8f04 --- /dev/null +++ b/modules/light-clients/07-celestia/share_proof.go @@ -0,0 +1,132 @@ +package celestia + +import ( + "crypto/sha256" + "errors" + "fmt" + "math" + + "github.com/celestiaorg/nmt" + "github.com/cometbft/cometbft/proto/tendermint/crypto" +) + +// ShareProof is an NMT proof that a set of shares exist in a set of rows and a +// Merkle proof that those rows exist in a Merkle tree with a given data root. +type shareProof struct { + // Data are the raw shares that are being proven. + Data [][]byte `json:"data"` + // ShareProofs are NMT proofs that the shares in Data exist in a set of + // rows. There will be one ShareProof per row that the shares occupy. + ShareProofs []*NMTProof `json:"share_proofs"` + // NamespaceID is the namespace id of the shares being proven. This + // namespace id is used when verifying the proof. If the namespace id doesn't + // match the namespace of the shares, the proof will fail verification. + NamespaceID []byte `json:"namespace_id"` + RowProof rowProof `json:"row_proof"` + NamespaceVersion uint32 `json:"namespace_version"` +} + +func (sp shareProof) ToProto() ShareProof { + // TODO consider extracting a ToProto function for RowProof + rowRoots := make([][]byte, len(sp.RowProof.RowRoots)) + rowProofs := make([]*crypto.Proof, len(sp.RowProof.Proofs)) + for i := range sp.RowProof.RowRoots { + rowRoots[i] = sp.RowProof.RowRoots[i].Bytes() + rowProofs[i] = sp.RowProof.Proofs[i].ToProto() + } + pbtp := ShareProof{ + Data: sp.Data, + ShareProofs: sp.ShareProofs, + NamespaceId: sp.NamespaceID, + RowProof: &RowProof{ + RowRoots: rowRoots, + Proofs: rowProofs, + StartRow: sp.RowProof.StartRow, + EndRow: sp.RowProof.EndRow, + }, + NamespaceVersion: sp.NamespaceVersion, + } + + return pbtp +} + +// ShareProofFromProto creates a ShareProof from a proto message. +// Expects the proof to be pre-validated. +func ShareProofFromProto(pb ShareProof) (shareProof, error) { + return shareProof{ + RowProof: RowProofFromProto(pb.RowProof), + Data: pb.Data, + ShareProofs: pb.ShareProofs, + NamespaceID: pb.NamespaceId, + NamespaceVersion: pb.NamespaceVersion, + }, nil +} + +// Validate runs basic validations on the proof then verifies if it is consistent. +// It returns nil if the proof is valid. Otherwise, it returns a sensible error. +// The `root` is the block data root that the shares to be proven belong to. +// Note: these proofs are tested on the app side. +func (sp shareProof) Validate(root []byte) error { + numberOfSharesInProofs := int32(0) + for _, proof := range sp.ShareProofs { + // the range is not inclusive from the left. + numberOfSharesInProofs += proof.End - proof.Start + } + + if len(sp.ShareProofs) != len(sp.RowProof.RowRoots) { + return fmt.Errorf("the number of share proofs %d must equal the number of row roots %d", len(sp.ShareProofs), len(sp.RowProof.RowRoots)) + + } + if len(sp.Data) != int(numberOfSharesInProofs) { + return fmt.Errorf("the number of shares %d must equal the number of shares in share proofs %d", len(sp.Data), numberOfSharesInProofs) + } + + for _, proof := range sp.ShareProofs { + if proof.Start < 0 { + return errors.New("proof index cannot be negative") + } + if (proof.End - proof.Start) <= 0 { + return errors.New("proof total must be positive") + } + } + + if err := sp.RowProof.Validate(root); err != nil { + return err + } + + if ok := sp.VerifyProof(); !ok { + return errors.New("share proof failed to verify") + } + + return nil +} + +func (sp shareProof) VerifyProof() bool { + cursor := int32(0) + for i, proof := range sp.ShareProofs { + nmtProof := nmt.NewInclusionProof( + int(proof.Start), + int(proof.End), + proof.Nodes, + true, + ) + sharesUsed := proof.End - proof.Start + if sp.NamespaceVersion > math.MaxUint8 { + return false + } + // Consider extracting celestia-app's namespace package. We can't use it + // here because that would introduce a circulcar import. + namespace := append([]byte{uint8(sp.NamespaceVersion)}, sp.NamespaceID...) + valid := nmtProof.VerifyInclusion( + sha256.New(), + namespace, + sp.Data[cursor:sharesUsed+cursor], + sp.RowProof.RowRoots[i], + ) + if !valid { + return false + } + cursor += sharesUsed + } + return true +} diff --git a/proto/ibc/lightclients/celestia/v1/celestia.proto b/proto/ibc/lightclients/celestia/v1/celestia.proto index 96011f66e02..c608b9ef531 100644 --- a/proto/ibc/lightclients/celestia/v1/celestia.proto +++ b/proto/ibc/lightclients/celestia/v1/celestia.proto @@ -4,8 +4,9 @@ package ibc.lightclients.celestia.v1; option go_package = "github.com/cosmos/ibc-go/v8/modules/light-clients/07-celestia;celestia"; -import "ibc/lightclients/tendermint/v1/tendermint.proto"; +import "tendermint/crypto/proof.proto"; import "gogoproto/gogo.proto"; +import "ibc/lightclients/tendermint/v1/tendermint.proto"; // ClientState from Tendermint tracks the current validator set, latest height, // and a possible frozen height. @@ -14,3 +15,45 @@ message ClientState { ibc.lightclients.tendermint.v1.ClientState base_client = 1; } + +// ShareProof is an NMT proof that a set of shares exist in a set of rows and a +// Merkle proof that those rows exist in a Merkle tree with a given data root. +message ShareProof { + repeated bytes data = 1; + repeated NMTProof share_proofs = 2; + bytes namespace_id = 3; + RowProof row_proof = 4; + uint32 namespace_version = 5; +} + +// RowProof is a Merkle proof that a set of rows exist in a Merkle tree with a +// given data root. +message RowProof { + repeated bytes row_roots = 1; + repeated .tendermint.crypto.Proof proofs = 2; + bytes root = 3; + uint32 start_row = 4; + uint32 end_row = 5; +} + +// NMTProof is a proof of a namespace.ID in an NMT. +// In case this proof proves the absence of a namespace.ID +// in a tree it also contains the leaf hashes of the range +// where that namespace would be. +message NMTProof { + // Start index of this proof. + int32 start = 1; + // End index of this proof. + int32 end = 2; + // Nodes that together with the corresponding leaf values can be used to + // recompute the root and verify this proof. Nodes should consist of the max + // and min namespaces along with the actual hash, resulting in each being 48 + // bytes each + repeated bytes nodes = 3; + // leafHash are nil if the namespace is present in the NMT. In case the + // namespace to be proved is in the min/max range of the tree but absent, this + // will contain the leaf hash necessary to verify the proof of absence. Leaf + // hashes should consist of the namespace along with the actual hash, + // resulting 40 bytes total. + bytes leaf_hash = 4; +} \ No newline at end of file From e57b31fca26ca638942ffe37bd098dbe4c1fd4d2 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 16:50:36 +0100 Subject: [PATCH 11/14] chore: unmarshal share proof bytes and convert from proto to verify --- .../light-clients/07-celestia/client_state.go | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/modules/light-clients/07-celestia/client_state.go b/modules/light-clients/07-celestia/client_state.go index 06b1afb3943..68bdb030d79 100644 --- a/modules/light-clients/07-celestia/client_state.go +++ b/modules/light-clients/07-celestia/client_state.go @@ -46,6 +46,8 @@ func (cs *ClientState) Validate() error { } // VerifyMembership implements exported.ClientState. +// TODO: Revise and look into delay periods for this. +// TODO: Validate key path and value against the shareProof extracted from proof bytes. func (cs *ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes.KVStore, cdc codec.BinaryCodec, height exported.Height, delayTimePeriod uint64, delayBlockPeriod uint64, proof []byte, path exported.Path, value []byte) error { if cs.BaseClient.GetLatestHeight().LT(height) { return errorsmod.Wrapf( @@ -54,23 +56,26 @@ func (cs *ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes. ) } - // TODO: revise and look into delay periods for this if err := verifyDelayPeriodPassed(ctx, clientStore, height, delayTimePeriod, delayBlockPeriod); err != nil { return err } - // var shareProof celestiatypes.ShareProof - // if err := cdc.Unmarshal(proof, &shareProof); err != nil { - // return err - // } + var shareProofPB ShareProof + if err := cdc.Unmarshal(proof, &shareProofPB); err != nil { + return err + } - // consensusState, found := ibctm.GetConsensusState(clientStore, cdc, height) - // if !found { - // return errorsmod.Wrap(clienttypes.ErrConsensusStateNotFound, "please ensure the proof was constructed against a height that exists on the client") - // } + shareProof, err := ShareProofFromProto(shareProofPB) + if err != nil { + return err + } - // return shareProof.Validate(consensusState.GetRoot()) - return nil + consensusState, found := ibctm.GetConsensusState(clientStore, cdc, height) + if !found { + return errorsmod.Wrap(clienttypes.ErrConsensusStateNotFound, "please ensure the proof was constructed against a height that exists on the client") + } + + return shareProof.Validate(consensusState.GetRoot().GetHash()) } // VerifyNonMembership implements exported.ClientState. From a347e02d03896bf1144eddb798edae780d282468 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 17:05:39 +0100 Subject: [PATCH 12/14] lint: make lint-fix --- modules/light-clients/07-celestia/genesis.go | 1 + modules/light-clients/07-celestia/share_proof.go | 2 +- modules/light-clients/07-celestia/upgrade.go | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/light-clients/07-celestia/genesis.go b/modules/light-clients/07-celestia/genesis.go index 83ad27ed18f..8750c71ba88 100644 --- a/modules/light-clients/07-celestia/genesis.go +++ b/modules/light-clients/07-celestia/genesis.go @@ -2,6 +2,7 @@ package celestia import ( storetypes "cosmossdk.io/store/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" ) diff --git a/modules/light-clients/07-celestia/share_proof.go b/modules/light-clients/07-celestia/share_proof.go index fc780ec8f04..c86328c759e 100644 --- a/modules/light-clients/07-celestia/share_proof.go +++ b/modules/light-clients/07-celestia/share_proof.go @@ -7,6 +7,7 @@ import ( "math" "github.com/celestiaorg/nmt" + "github.com/cometbft/cometbft/proto/tendermint/crypto" ) @@ -75,7 +76,6 @@ func (sp shareProof) Validate(root []byte) error { if len(sp.ShareProofs) != len(sp.RowProof.RowRoots) { return fmt.Errorf("the number of share proofs %d must equal the number of row roots %d", len(sp.ShareProofs), len(sp.RowProof.RowRoots)) - } if len(sp.Data) != int(numberOfSharesInProofs) { return fmt.Errorf("the number of shares %d must equal the number of shares in share proofs %d", len(sp.Data), numberOfSharesInProofs) diff --git a/modules/light-clients/07-celestia/upgrade.go b/modules/light-clients/07-celestia/upgrade.go index 20b18f306b0..ab0981f1cac 100644 --- a/modules/light-clients/07-celestia/upgrade.go +++ b/modules/light-clients/07-celestia/upgrade.go @@ -2,8 +2,10 @@ package celestia import ( storetypes "cosmossdk.io/store/types" + "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/ibc-go/v8/modules/core/exported" ) From 73310cd31e9f6c818911ddc698669f6222d9c845 Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Mon, 5 Feb 2024 17:08:53 +0100 Subject: [PATCH 13/14] lint: silence linter badmon --- modules/light-clients/07-celestia/client_state.go | 2 +- modules/light-clients/07-celestia/row_proof.go | 2 +- modules/light-clients/07-celestia/share_proof.go | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/light-clients/07-celestia/client_state.go b/modules/light-clients/07-celestia/client_state.go index 68bdb030d79..4f94e2b8def 100644 --- a/modules/light-clients/07-celestia/client_state.go +++ b/modules/light-clients/07-celestia/client_state.go @@ -65,7 +65,7 @@ func (cs *ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes. return err } - shareProof, err := ShareProofFromProto(shareProofPB) + shareProof, err := shareProofFromProto(shareProofPB) if err != nil { return err } diff --git a/modules/light-clients/07-celestia/row_proof.go b/modules/light-clients/07-celestia/row_proof.go index c75b7e81e68..50ae7f2e12d 100644 --- a/modules/light-clients/07-celestia/row_proof.go +++ b/modules/light-clients/07-celestia/row_proof.go @@ -50,7 +50,7 @@ func (rp rowProof) VerifyProof(root []byte) bool { return true } -func RowProofFromProto(p *RowProof) rowProof { +func rowProofFromProto(p *RowProof) rowProof { if p == nil { return rowProof{} } diff --git a/modules/light-clients/07-celestia/share_proof.go b/modules/light-clients/07-celestia/share_proof.go index c86328c759e..4b456e399b6 100644 --- a/modules/light-clients/07-celestia/share_proof.go +++ b/modules/light-clients/07-celestia/share_proof.go @@ -51,11 +51,11 @@ func (sp shareProof) ToProto() ShareProof { return pbtp } -// ShareProofFromProto creates a ShareProof from a proto message. +// shareProofFromProto creates a ShareProof from a proto message. // Expects the proof to be pre-validated. -func ShareProofFromProto(pb ShareProof) (shareProof, error) { +func shareProofFromProto(pb ShareProof) (shareProof, error) { return shareProof{ - RowProof: RowProofFromProto(pb.RowProof), + RowProof: rowProofFromProto(pb.RowProof), Data: pb.Data, ShareProofs: pb.ShareProofs, NamespaceID: pb.NamespaceId, From 0090f2696c263eab3ca0d25dcc357bb63bd6e73a Mon Sep 17 00:00:00 2001 From: Damian Nolan Date: Tue, 6 Feb 2024 11:15:03 +0100 Subject: [PATCH 14/14] lint: final --- modules/light-clients/07-celestia/client_state.go | 6 +++--- modules/light-clients/07-celestia/share_proof.go | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/modules/light-clients/07-celestia/client_state.go b/modules/light-clients/07-celestia/client_state.go index 4f94e2b8def..cb4bee24b41 100644 --- a/modules/light-clients/07-celestia/client_state.go +++ b/modules/light-clients/07-celestia/client_state.go @@ -60,12 +60,12 @@ func (cs *ClientState) VerifyMembership(ctx sdk.Context, clientStore storetypes. return err } - var shareProofPB ShareProof - if err := cdc.Unmarshal(proof, &shareProofPB); err != nil { + var shareProofProto ShareProof + if err := cdc.Unmarshal(proof, &shareProofProto); err != nil { return err } - shareProof, err := shareProofFromProto(shareProofPB) + shareProof, err := shareProofFromProto(&shareProofProto) if err != nil { return err } diff --git a/modules/light-clients/07-celestia/share_proof.go b/modules/light-clients/07-celestia/share_proof.go index 4b456e399b6..9aa0483b142 100644 --- a/modules/light-clients/07-celestia/share_proof.go +++ b/modules/light-clients/07-celestia/share_proof.go @@ -53,7 +53,11 @@ func (sp shareProof) ToProto() ShareProof { // shareProofFromProto creates a ShareProof from a proto message. // Expects the proof to be pre-validated. -func shareProofFromProto(pb ShareProof) (shareProof, error) { +func shareProofFromProto(pb *ShareProof) (shareProof, error) { + if pb == nil { + return shareProof{}, fmt.Errorf("nil share proof protobuf") + } + return shareProof{ RowProof: rowProofFromProto(pb.RowProof), Data: pb.Data,