From 2a617879c8ad1d9696f0df4957429efdf8388700 Mon Sep 17 00:00:00 2001 From: Vlad Date: Tue, 25 Oct 2022 14:42:45 +0300 Subject: [PATCH] move bad encoding fraud proof to share pkg --- das/daser.go | 6 +- fraud/bad_encoding_test.go | 29 -- fraud/pb/proof.pb.go | 413 +---------------- fraud/pb/proof.proto | 15 - fraud/service_test.go | 51 +-- fraud/testing.go | 52 ++- .../eds/byzantine}/bad_encoding.go | 24 +- share/{ => eds/byzantine}/byzantine.go | 3 +- share/{ => eds/byzantine}/pb/share.pb.go | 427 ++++++++++++++++-- share/eds/byzantine/pb/share.proto | 30 ++ share/eds/byzantine/share_proof.go | 105 +++++ share/eds/byzantine/share_proof_test.go | 81 ++++ share/eds/retriever.go | 3 +- share/eds/retriever_test.go | 36 +- share/get.go | 29 -- share/get_test.go | 67 --- share/pb/share.proto | 17 - share/share.go | 67 --- 18 files changed, 733 insertions(+), 722 deletions(-) delete mode 100644 fraud/bad_encoding_test.go rename {fraud => share/eds/byzantine}/bad_encoding.go (91%) rename share/{ => eds/byzantine}/byzantine.go (98%) rename share/{ => eds/byzantine}/pb/share.pb.go (56%) create mode 100644 share/eds/byzantine/pb/share.proto create mode 100644 share/eds/byzantine/share_proof.go create mode 100644 share/eds/byzantine/share_proof_test.go delete mode 100644 share/pb/share.proto diff --git a/das/daser.go b/das/daser.go index 8ca54d594e..86b3b3557b 100644 --- a/das/daser.go +++ b/das/daser.go @@ -7,6 +7,8 @@ import ( "sync/atomic" "time" + "github.com/celestiaorg/celestia-node/share/eds/byzantine" + "github.com/ipfs/go-datastore" logging "github.com/ipfs/go-log/v2" @@ -153,10 +155,10 @@ func (d *DASer) sample(ctx context.Context, h *header.ExtendedHeader) error { if err == context.Canceled { return err } - var byzantineErr *share.ErrByzantine + var byzantineErr *byzantine.ErrByzantine if errors.As(err, &byzantineErr) { log.Warn("Propagating proof...") - sendErr := d.bcast.Broadcast(ctx, fraud.CreateBadEncodingProof(h.Hash(), uint64(h.Height), byzantineErr)) + sendErr := d.bcast.Broadcast(ctx, byzantine.CreateBadEncodingProof(h.Hash(), uint64(h.Height), byzantineErr)) if sendErr != nil { log.Errorw("fraud proof propagating failed", "err", sendErr) } diff --git a/fraud/bad_encoding_test.go b/fraud/bad_encoding_test.go deleted file mode 100644 index ebb5a95692..0000000000 --- a/fraud/bad_encoding_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package fraud - -import ( - "context" - "errors" - "testing" - "time" - - mdutils "github.com/ipfs/go-merkledag/test" - "github.com/stretchr/testify/require" - - "github.com/celestiaorg/celestia-node/share" -) - -func TestFraudProofValidation(t *testing.T) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) - defer t.Cleanup(cancel) - bServ := mdutils.Bserv() - _, store := createService(t, false) - h, err := store.GetByHeight(ctx, 1) - require.NoError(t, err) - - faultDAH, err := generateByzantineError(ctx, t, h, bServ) - var errByz *share.ErrByzantine - require.True(t, errors.As(err, &errByz)) - p := CreateBadEncodingProof([]byte("hash"), uint64(faultDAH.Height), errByz) - err = p.Validate(faultDAH) - require.NoError(t, err) -} diff --git a/fraud/pb/proof.pb.go b/fraud/pb/proof.pb.go index 8ca49c4410..d5e992ab63 100644 --- a/fraud/pb/proof.pb.go +++ b/fraud/pb/proof.pb.go @@ -5,13 +5,10 @@ package fraud_pb import ( fmt "fmt" + proto "github.com/gogo/protobuf/proto" io "io" math "math" math_bits "math/bits" - - proto "github.com/gogo/protobuf/proto" - - pb "github.com/celestiaorg/celestia-node/share/pb" ) // Reference imports to suppress errors if they are not otherwise used. @@ -25,107 +22,6 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -type Axis int32 - -const ( - Axis_ROW Axis = 0 - Axis_COL Axis = 1 -) - -var Axis_name = map[int32]string{ - 0: "ROW", - 1: "COL", -} - -var Axis_value = map[string]int32{ - "ROW": 0, - "COL": 1, -} - -func (x Axis) String() string { - return proto.EnumName(Axis_name, int32(x)) -} - -func (Axis) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_318cb87a8bb2d394, []int{0} -} - -type BadEncoding struct { - HeaderHash []byte `protobuf:"bytes,1,opt,name=HeaderHash,proto3" json:"HeaderHash,omitempty"` - Height uint64 `protobuf:"varint,2,opt,name=Height,proto3" json:"Height,omitempty"` - Shares []*pb.Share `protobuf:"bytes,3,rep,name=Shares,proto3" json:"Shares,omitempty"` - Index uint32 `protobuf:"varint,4,opt,name=Index,proto3" json:"Index,omitempty"` - Axis Axis `protobuf:"varint,5,opt,name=Axis,proto3,enum=fraud.pb.Axis" json:"Axis,omitempty"` -} - -func (m *BadEncoding) Reset() { *m = BadEncoding{} } -func (m *BadEncoding) String() string { return proto.CompactTextString(m) } -func (*BadEncoding) ProtoMessage() {} -func (*BadEncoding) Descriptor() ([]byte, []int) { - return fileDescriptor_318cb87a8bb2d394, []int{0} -} -func (m *BadEncoding) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *BadEncoding) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_BadEncoding.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 *BadEncoding) XXX_Merge(src proto.Message) { - xxx_messageInfo_BadEncoding.Merge(m, src) -} -func (m *BadEncoding) XXX_Size() int { - return m.Size() -} -func (m *BadEncoding) XXX_DiscardUnknown() { - xxx_messageInfo_BadEncoding.DiscardUnknown(m) -} - -var xxx_messageInfo_BadEncoding proto.InternalMessageInfo - -func (m *BadEncoding) GetHeaderHash() []byte { - if m != nil { - return m.HeaderHash - } - return nil -} - -func (m *BadEncoding) GetHeight() uint64 { - if m != nil { - return m.Height - } - return 0 -} - -func (m *BadEncoding) GetShares() []*pb.Share { - if m != nil { - return m.Shares - } - return nil -} - -func (m *BadEncoding) GetIndex() uint32 { - if m != nil { - return m.Index - } - return 0 -} - -func (m *BadEncoding) GetAxis() Axis { - if m != nil { - return m.Axis - } - return Axis_ROW -} - type FraudMessageRequest struct { RequestedProofType []string `protobuf:"bytes,1,rep,name=RequestedProofType,proto3" json:"RequestedProofType,omitempty"` } @@ -134,7 +30,7 @@ func (m *FraudMessageRequest) Reset() { *m = FraudMessageRequest{} } func (m *FraudMessageRequest) String() string { return proto.CompactTextString(m) } func (*FraudMessageRequest) ProtoMessage() {} func (*FraudMessageRequest) Descriptor() ([]byte, []int) { - return fileDescriptor_318cb87a8bb2d394, []int{1} + return fileDescriptor_318cb87a8bb2d394, []int{0} } func (m *FraudMessageRequest) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -179,7 +75,7 @@ func (m *ProofResponse) Reset() { *m = ProofResponse{} } func (m *ProofResponse) String() string { return proto.CompactTextString(m) } func (*ProofResponse) ProtoMessage() {} func (*ProofResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_318cb87a8bb2d394, []int{2} + return fileDescriptor_318cb87a8bb2d394, []int{1} } func (m *ProofResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -230,7 +126,7 @@ func (m *FraudMessageResponse) Reset() { *m = FraudMessageResponse{} } func (m *FraudMessageResponse) String() string { return proto.CompactTextString(m) } func (*FraudMessageResponse) ProtoMessage() {} func (*FraudMessageResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_318cb87a8bb2d394, []int{3} + return fileDescriptor_318cb87a8bb2d394, []int{2} } func (m *FraudMessageResponse) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -267,8 +163,6 @@ func (m *FraudMessageResponse) GetProofs() []*ProofResponse { } func init() { - proto.RegisterEnum("fraud.pb.Axis", Axis_name, Axis_value) - proto.RegisterType((*BadEncoding)(nil), "fraud.pb.BadEncoding") proto.RegisterType((*FraudMessageRequest)(nil), "fraud.pb.FraudMessageRequest") proto.RegisterType((*ProofResponse)(nil), "fraud.pb.ProofResponse") proto.RegisterType((*FraudMessageResponse)(nil), "fraud.pb.FraudMessageResponse") @@ -277,88 +171,20 @@ func init() { func init() { proto.RegisterFile("fraud/pb/proof.proto", fileDescriptor_318cb87a8bb2d394) } var fileDescriptor_318cb87a8bb2d394 = []byte{ - // 350 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x51, 0xcd, 0x4a, 0xeb, 0x40, - 0x18, 0xcd, 0x34, 0x69, 0xee, 0xed, 0xd7, 0x1f, 0xca, 0xb4, 0xdc, 0x3b, 0xb8, 0x08, 0x21, 0x0b, - 0x19, 0x5c, 0x4c, 0xa1, 0xae, 0x5c, 0x5a, 0xa9, 0x56, 0x50, 0x2a, 0xa3, 0xe8, 0x7a, 0x62, 0xa6, - 0x6d, 0xa0, 0x24, 0x63, 0xa6, 0x85, 0xfa, 0x16, 0xbe, 0x85, 0xaf, 0xe2, 0xb2, 0x4b, 0x97, 0xd2, - 0xbe, 0x88, 0xcc, 0x34, 0xa2, 0x05, 0x77, 0xe7, 0x27, 0x39, 0xe7, 0x7c, 0x0c, 0x74, 0x27, 0x85, - 0x58, 0x26, 0x3d, 0x15, 0xf7, 0x54, 0x91, 0xe7, 0x13, 0xa6, 0x8a, 0x7c, 0x91, 0xe3, 0xbf, 0x56, - 0x65, 0x2a, 0x3e, 0xe8, 0xa4, 0x6a, 0x6e, 0x6d, 0x3d, 0x13, 0x85, 0xdc, 0xd9, 0xd1, 0x2b, 0x82, - 0xfa, 0x40, 0x24, 0xc3, 0xec, 0x31, 0x4f, 0xd2, 0x6c, 0x8a, 0x03, 0x80, 0x91, 0x14, 0x89, 0x2c, - 0x46, 0x42, 0xcf, 0x08, 0x0a, 0x11, 0x6d, 0xf0, 0x1f, 0x0a, 0xfe, 0x07, 0xfe, 0x48, 0xa6, 0xd3, - 0xd9, 0x82, 0x54, 0x42, 0x44, 0x3d, 0x5e, 0x32, 0x7c, 0x08, 0xfe, 0xad, 0x89, 0xd5, 0xc4, 0x0d, - 0x5d, 0x5a, 0xef, 0xb7, 0x98, 0x69, 0x63, 0x2a, 0x66, 0x56, 0xe6, 0xa5, 0x8b, 0xbb, 0x50, 0xbd, - 0xcc, 0x12, 0xb9, 0x22, 0x5e, 0x88, 0x68, 0x93, 0xef, 0x08, 0x8e, 0xc0, 0x3b, 0x5d, 0xa5, 0x9a, - 0x54, 0x43, 0x44, 0x5b, 0xfd, 0x16, 0xfb, 0xda, 0xcc, 0xc4, 0x2a, 0xd5, 0xdc, 0x7a, 0xd1, 0x10, - 0x3a, 0xe7, 0x46, 0xbe, 0x96, 0x5a, 0x8b, 0xa9, 0xe4, 0xf2, 0x69, 0x29, 0xf5, 0x02, 0x33, 0xc0, - 0x25, 0x94, 0xc9, 0x8d, 0xb9, 0xfb, 0xee, 0x59, 0x49, 0x82, 0x42, 0x97, 0xd6, 0xf8, 0x2f, 0x4e, - 0x74, 0x02, 0x4d, 0x4b, 0xb8, 0xd4, 0x2a, 0xcf, 0xb4, 0xc4, 0x18, 0xbc, 0xf2, 0x17, 0x44, 0x6b, - 0xdc, 0x62, 0xb3, 0xf2, 0x5e, 0xcc, 0x97, 0x92, 0x54, 0x42, 0x97, 0x36, 0xf8, 0x8e, 0x44, 0x17, - 0xd0, 0xdd, 0x5f, 0x50, 0x26, 0xf4, 0xc0, 0xb7, 0x91, 0xda, 0xd6, 0xd6, 0xfb, 0xff, 0xbf, 0xf7, - 0xef, 0x55, 0xf1, 0xf2, 0xb3, 0x23, 0x02, 0x9e, 0x39, 0x0c, 0xff, 0x01, 0x97, 0x8f, 0x1f, 0xda, - 0x8e, 0x01, 0x67, 0xe3, 0xab, 0x36, 0x1a, 0x90, 0xb7, 0x4d, 0x80, 0xd6, 0x9b, 0x00, 0x7d, 0x6c, - 0x02, 0xf4, 0xb2, 0x0d, 0x9c, 0xf5, 0x36, 0x70, 0xde, 0xb7, 0x81, 0x13, 0xfb, 0xf6, 0xbd, 0x8e, - 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x6e, 0x3b, 0x05, 0xe6, 0x01, 0x00, 0x00, -} - -func (m *BadEncoding) 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 *BadEncoding) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *BadEncoding) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Axis != 0 { - i = encodeVarintProof(dAtA, i, uint64(m.Axis)) - i-- - dAtA[i] = 0x28 - } - if m.Index != 0 { - i = encodeVarintProof(dAtA, i, uint64(m.Index)) - i-- - dAtA[i] = 0x20 - } - if len(m.Shares) > 0 { - for iNdEx := len(m.Shares) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Shares[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintProof(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x1a - } - } - if m.Height != 0 { - i = encodeVarintProof(dAtA, i, uint64(m.Height)) - i-- - dAtA[i] = 0x10 - } - if len(m.HeaderHash) > 0 { - i -= len(m.HeaderHash) - copy(dAtA[i:], m.HeaderHash) - i = encodeVarintProof(dAtA, i, uint64(len(m.HeaderHash))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil + // 203 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x49, 0x2b, 0x4a, 0x2c, + 0x4d, 0xd1, 0x2f, 0x48, 0xd2, 0x2f, 0x28, 0xca, 0xcf, 0x4f, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, + 0x17, 0xe2, 0x00, 0x8b, 0xea, 0x15, 0x24, 0x29, 0xb9, 0x72, 0x09, 0xbb, 0x81, 0xd8, 0xbe, 0xa9, + 0xc5, 0xc5, 0x89, 0xe9, 0xa9, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x7a, 0x5c, 0x42, + 0x50, 0x66, 0x6a, 0x4a, 0x00, 0x48, 0x63, 0x48, 0x65, 0x41, 0xaa, 0x04, 0xa3, 0x02, 0xb3, 0x06, + 0x67, 0x10, 0x16, 0x19, 0x25, 0x4b, 0x2e, 0x5e, 0x30, 0x27, 0x28, 0xb5, 0xb8, 0x20, 0x3f, 0xaf, + 0x38, 0x55, 0x48, 0x88, 0x8b, 0x05, 0xaa, 0x85, 0x51, 0x83, 0x33, 0x08, 0xcc, 0x16, 0x12, 0xe1, + 0x62, 0x0d, 0x4b, 0xcc, 0x29, 0x4d, 0x95, 0x60, 0x52, 0x60, 0xd6, 0xe0, 0x09, 0x82, 0x70, 0x94, + 0xdc, 0xb9, 0x44, 0x50, 0x5d, 0x00, 0x35, 0x41, 0x9f, 0x8b, 0x0d, 0x6c, 0x64, 0x31, 0xd8, 0x5a, + 0x6e, 0x23, 0x71, 0x3d, 0x98, 0xa3, 0xf5, 0x50, 0xac, 0x0a, 0x82, 0x2a, 0x73, 0x92, 0x38, 0xf1, + 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, + 0xf0, 0x58, 0x8e, 0xe1, 0xc6, 0x63, 0x39, 0x86, 0x24, 0x36, 0xb0, 0xaf, 0x8d, 0x01, 0x01, 0x00, + 0x00, 0xff, 0xff, 0xa2, 0xc2, 0x65, 0x25, 0x0d, 0x01, 0x00, 0x00, } func (m *FraudMessageRequest) Marshal() (dAtA []byte, err error) { @@ -480,34 +306,6 @@ func encodeVarintProof(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } -func (m *BadEncoding) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.HeaderHash) - if l > 0 { - n += 1 + l + sovProof(uint64(l)) - } - if m.Height != 0 { - n += 1 + sovProof(uint64(m.Height)) - } - if len(m.Shares) > 0 { - for _, e := range m.Shares { - l = e.Size() - n += 1 + l + sovProof(uint64(l)) - } - } - if m.Index != 0 { - n += 1 + sovProof(uint64(m.Index)) - } - if m.Axis != 0 { - n += 1 + sovProof(uint64(m.Axis)) - } - return n -} - func (m *FraudMessageRequest) Size() (n int) { if m == nil { return 0 @@ -563,181 +361,6 @@ func sovProof(x uint64) (n int) { func sozProof(x uint64) (n int) { return sovProof(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (m *BadEncoding) 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 ErrIntOverflowProof - } - 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: BadEncoding: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: BadEncoding: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field HeaderHash", wireType) - } - var byteLen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProof - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - byteLen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if byteLen < 0 { - return ErrInvalidLengthProof - } - postIndex := iNdEx + byteLen - if postIndex < 0 { - return ErrInvalidLengthProof - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.HeaderHash = append(m.HeaderHash[:0], dAtA[iNdEx:postIndex]...) - if m.HeaderHash == nil { - m.HeaderHash = []byte{} - } - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) - } - m.Height = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProof - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Height |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProof - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthProof - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthProof - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Shares = append(m.Shares, &pb.Share{}) - if err := m.Shares[len(m.Shares)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 4: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) - } - m.Index = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProof - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Index |= uint32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 5: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Axis", wireType) - } - m.Axis = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowProof - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Axis |= Axis(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipProof(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthProof - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *FraudMessageRequest) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/fraud/pb/proof.proto b/fraud/pb/proof.proto index e68d52193e..95715c89c8 100644 --- a/fraud/pb/proof.proto +++ b/fraud/pb/proof.proto @@ -2,21 +2,6 @@ syntax = "proto3"; package fraud.pb; -import "ipld/pb/share.proto"; - -enum axis { - ROW = 0; - COL = 1; -} - -message BadEncoding { - bytes HeaderHash = 1; - uint64 Height = 2; - repeated ipld.pb.Share Shares = 3; - uint32 Index = 4; - axis Axis = 5; -} - message FraudMessageRequest { repeated string RequestedProofType = 1; } diff --git a/fraud/service_test.go b/fraud/service_test.go index ec750e68ec..33326beda2 100644 --- a/fraud/service_test.go +++ b/fraud/service_test.go @@ -6,8 +6,6 @@ import ( "testing" "time" - "github.com/stretchr/testify/require" - "github.com/ipfs/go-datastore" "github.com/ipfs/go-datastore/namespace" "github.com/ipfs/go-datastore/sync" @@ -15,6 +13,7 @@ import ( pubsub "github.com/libp2p/go-libp2p-pubsub" pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb" mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + "github.com/stretchr/testify/require" "github.com/celestiaorg/celestia-node/header" ) @@ -22,7 +21,7 @@ import ( func TestService_Subscribe(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*1) t.Cleanup(cancel) - s, _ := createService(t, false) + s, _ := CreateTestService(t, false) proof := newValidProof() require.NoError(t, s.Start(ctx)) _, err := s.Subscribe(proof.Type()) @@ -30,7 +29,7 @@ func TestService_Subscribe(t *testing.T) { } func TestService_SubscribeFails(t *testing.T) { - s, _ := createService(t, false) + s, _ := CreateTestService(t, false) proof := newValidProof() _, err := s.Subscribe(proof.Type()) require.Error(t, err) @@ -39,7 +38,7 @@ func TestService_SubscribeFails(t *testing.T) { func TestService_BroadcastFails(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*1) t.Cleanup(cancel) - s, _ := createService(t, false) + s, _ := CreateTestService(t, false) p := newValidProof() require.Error(t, s.Broadcast(ctx, p)) } @@ -48,7 +47,7 @@ func TestService_Broadcast(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) t.Cleanup(cancel) - s, _ := createService(t, false) + s, _ := CreateTestService(t, false) proof := newValidProof() require.NoError(t, s.Start(ctx)) subs, err := s.Subscribe(proof.Type()) @@ -94,7 +93,7 @@ func TestService_processIncoming(t *testing.T) { bin, err := test.proof.MarshalBinary() require.NoError(t, err) // create first fraud service that will broadcast incorrect Fraud Proof - service, _ := createServiceWithHost(ctx, t, net.Hosts()[0], false) + service, _ := createTestServiceWithHost(ctx, t, net.Hosts()[0], false) msg := &pubsub.Message{ Message: &pubsubpb.Message{ Data: bin, @@ -118,7 +117,7 @@ func TestService_ReGossiping(t *testing.T) { require.NoError(t, err) // create first fraud service that will broadcast incorrect Fraud Proof - pserviceA, _ := createServiceWithHost(ctx, t, net.Hosts()[0], false) + pserviceA, _ := createTestServiceWithHost(ctx, t, net.Hosts()[0], false) require.NoError(t, err) // create pub sub in order to listen for Fraud Proof psB, err := pubsub.NewGossipSub(ctx, net.Hosts()[1], // -> B @@ -195,7 +194,7 @@ func TestService_Get(t *testing.T) { proof := newValidProof() bin, err := proof.MarshalBinary() require.NoError(t, err) - pService, _ := createService(t, false) + pService, _ := CreateTestService(t, false) // try to fetch proof _, err = pService.Get(ctx, proof.Type()) // error is expected here because storage is empty @@ -217,8 +216,8 @@ func TestService_Sync(t *testing.T) { net, err := mocknet.FullMeshLinked(2) require.NoError(t, err) - pserviceA, _ := createServiceWithHost(ctx, t, net.Hosts()[0], false) - pserviceB, _ := createServiceWithHost(ctx, t, net.Hosts()[1], true) + pserviceA, _ := createTestServiceWithHost(ctx, t, net.Hosts()[0], false) + pserviceB, _ := createTestServiceWithHost(ctx, t, net.Hosts()[1], true) proof := newValidProof() require.NoError(t, pserviceA.Start(ctx)) require.NoError(t, pserviceB.Start(ctx)) @@ -235,33 +234,3 @@ func TestService_Sync(t *testing.T) { _, err = subs.Proof(ctx) require.NoError(t, err) } - -func createService(t *testing.T, enabledSyncer bool) (*ProofService, *mockStore) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) - t.Cleanup(cancel) - - // create mock network - net, err := mocknet.FullMeshLinked(1) - require.NoError(t, err) - return createServiceWithHost(ctx, t, net.Hosts()[0], enabledSyncer) -} - -func createServiceWithHost( - ctx context.Context, - t *testing.T, - host host.Host, - enabledSyncer bool, -) (*ProofService, *mockStore) { - // create pubsub for host - ps, err := pubsub.NewGossipSub(ctx, host, - pubsub.WithMessageSignaturePolicy(pubsub.StrictNoSign)) - require.NoError(t, err) - store := createStore(t, 10) - return NewProofService( - ps, - host, - store.GetByHeight, - sync.MutexWrap(datastore.NewMapDatastore()), - enabledSyncer, - ), store -} diff --git a/fraud/testing.go b/fraud/testing.go index c066631585..7ac4eb8f3a 100644 --- a/fraud/testing.go +++ b/fraud/testing.go @@ -5,10 +5,14 @@ import ( "encoding/json" "errors" "testing" + "time" - "github.com/celestiaorg/celestia-node/share/eds" - - "github.com/ipfs/go-blockservice" + "github.com/ipfs/go-datastore" + "github.com/ipfs/go-datastore/sync" + "github.com/libp2p/go-libp2p-core/host" + pubsub "github.com/libp2p/go-libp2p-pubsub" + mocknet "github.com/libp2p/go-libp2p/p2p/net/mock" + "github.com/stretchr/testify/require" "github.com/celestiaorg/celestia-node/header" ) @@ -60,18 +64,6 @@ func (m *mockStore) GetByHeight(_ context.Context, height uint64) (*header.Exten func (m *mockStore) Close() error { return nil } -func generateByzantineError( - ctx context.Context, - t *testing.T, - h *header.ExtendedHeader, - bServ blockservice.BlockService, -) (*header.ExtendedHeader, error) { - faultHeader := header.CreateFraudExtHeader(t, h, bServ) - rtrv := eds.NewRetriever(bServ) - _, err := rtrv.Retrieve(ctx, faultHeader.DAH) - return faultHeader, err -} - const ( mockProofType ProofType = "mockProof" ) @@ -122,3 +114,33 @@ func (m *mockProof) MarshalBinary() (data []byte, err error) { func (m *mockProof) UnmarshalBinary(data []byte) error { return json.Unmarshal(data, m) } + +func CreateTestService(t *testing.T, enabledSyncer bool) (*ProofService, *mockStore) { //nolint:revive + ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) + t.Cleanup(cancel) + + // create mock network + net, err := mocknet.FullMeshLinked(1) + require.NoError(t, err) + return createTestServiceWithHost(ctx, t, net.Hosts()[0], enabledSyncer) +} + +func createTestServiceWithHost( + ctx context.Context, + t *testing.T, + host host.Host, + enabledSyncer bool, +) (*ProofService, *mockStore) { + // create pubsub for host + ps, err := pubsub.NewGossipSub(ctx, host, + pubsub.WithMessageSignaturePolicy(pubsub.StrictNoSign)) + require.NoError(t, err) + store := createStore(t, 10) + return NewProofService( + ps, + host, + store.GetByHeight, + sync.MutexWrap(datastore.NewMapDatastore()), + enabledSyncer, + ), store +} diff --git a/fraud/bad_encoding.go b/share/eds/byzantine/bad_encoding.go similarity index 91% rename from fraud/bad_encoding.go rename to share/eds/byzantine/bad_encoding.go index fefd4eba0b..122628d741 100644 --- a/fraud/bad_encoding.go +++ b/share/eds/byzantine/bad_encoding.go @@ -1,4 +1,4 @@ -package fraud +package byzantine import ( "bytes" @@ -7,17 +7,15 @@ import ( "github.com/celestiaorg/celestia-app/pkg/appconsts" "github.com/celestiaorg/celestia-app/pkg/wrapper" - - pb "github.com/celestiaorg/celestia-node/fraud/pb" + "github.com/celestiaorg/celestia-node/fraud" "github.com/celestiaorg/celestia-node/header" - "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/byzantine/pb" "github.com/celestiaorg/celestia-node/share/ipld" - ipld_pb "github.com/celestiaorg/celestia-node/share/pb" "github.com/celestiaorg/rsmt2d" ) func init() { - Register(&BadEncodingProof{}) + fraud.Register(&BadEncodingProof{}) } type BadEncodingProof struct { @@ -26,7 +24,7 @@ type BadEncodingProof struct { // ShareWithProof contains all shares from row or col. // Shares that did not pass verification in rsmt2d will be nil. // For non-nil shares MerkleProofs are computed. - Shares []*share.ShareWithProof + Shares []*ShareWithProof // Index represents the row/col index where ErrByzantineRow/ErrByzantineColl occurred. Index uint32 // Axis represents the axis that verification failed on. @@ -38,8 +36,8 @@ type BadEncodingProof struct { func CreateBadEncodingProof( hash []byte, height uint64, - errByzantine *share.ErrByzantine, -) Proof { + errByzantine *ErrByzantine, +) fraud.Proof { return &BadEncodingProof{ headerHash: hash, @@ -51,8 +49,8 @@ func CreateBadEncodingProof( } // Type returns type of fraud proof. -func (p *BadEncodingProof) Type() ProofType { - return BadEncoding +func (p *BadEncodingProof) Type() fraud.ProofType { + return fraud.BadEncoding } // HeaderHash returns block hash. @@ -67,7 +65,7 @@ func (p *BadEncodingProof) Height() uint64 { // MarshalBinary converts BadEncodingProof to binary. func (p *BadEncodingProof) MarshalBinary() ([]byte, error) { - shares := make([]*ipld_pb.Share, 0, len(p.Shares)) + shares := make([]*pb.Share, 0, len(p.Shares)) for _, share := range p.Shares { shares = append(shares, share.ShareWithProofToProto()) } @@ -91,7 +89,7 @@ func (p *BadEncodingProof) UnmarshalBinary(data []byte) error { befp := &BadEncodingProof{ headerHash: in.HeaderHash, BlockHeight: in.Height, - Shares: share.ProtoToShare(in.Shares), + Shares: ProtoToShare(in.Shares), Index: in.Index, Axis: rsmt2d.Axis(in.Axis), } diff --git a/share/byzantine.go b/share/eds/byzantine/byzantine.go similarity index 98% rename from share/byzantine.go rename to share/eds/byzantine/byzantine.go index 8e9e7f4b8d..5f13f06f17 100644 --- a/share/byzantine.go +++ b/share/eds/byzantine/byzantine.go @@ -1,4 +1,4 @@ -package share +package byzantine import ( "context" @@ -7,7 +7,6 @@ import ( "github.com/ipfs/go-blockservice" "github.com/celestiaorg/celestia-app/pkg/da" - "github.com/celestiaorg/celestia-node/share/ipld" "github.com/celestiaorg/rsmt2d" ) diff --git a/share/pb/share.pb.go b/share/eds/byzantine/pb/share.pb.go similarity index 56% rename from share/pb/share.pb.go rename to share/eds/byzantine/pb/share.pb.go index b3e32f8baa..18d982b1f8 100644 --- a/share/pb/share.pb.go +++ b/share/eds/byzantine/pb/share.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ipld/pb/share.proto +// source: share/validation/pb/share.proto package pb @@ -22,6 +22,31 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package +type Axis int32 + +const ( + Axis_ROW Axis = 0 + Axis_COL Axis = 1 +) + +var Axis_name = map[int32]string{ + 0: "ROW", + 1: "COL", +} + +var Axis_value = map[string]int32{ + "ROW": 0, + "COL": 1, +} + +func (x Axis) String() string { + return proto.EnumName(Axis_name, int32(x)) +} + +func (Axis) EnumDescriptor() ([]byte, []int) { + return fileDescriptor_809b930156a12991, []int{0} +} + type MerkleProof struct { Start int64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` End int64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` @@ -33,7 +58,7 @@ func (m *MerkleProof) Reset() { *m = MerkleProof{} } func (m *MerkleProof) String() string { return proto.CompactTextString(m) } func (*MerkleProof) ProtoMessage() {} func (*MerkleProof) Descriptor() ([]byte, []int) { - return fileDescriptor_f1f041c2d5c8eb54, []int{0} + return fileDescriptor_809b930156a12991, []int{0} } func (m *MerkleProof) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -99,7 +124,7 @@ func (m *Share) Reset() { *m = Share{} } func (m *Share) String() string { return proto.CompactTextString(m) } func (*Share) ProtoMessage() {} func (*Share) Descriptor() ([]byte, []int) { - return fileDescriptor_f1f041c2d5c8eb54, []int{1} + return fileDescriptor_809b930156a12991, []int{1} } func (m *Share) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -142,31 +167,117 @@ func (m *Share) GetProof() *MerkleProof { return nil } +type BadEncoding struct { + HeaderHash []byte `protobuf:"bytes,1,opt,name=HeaderHash,proto3" json:"HeaderHash,omitempty"` + Height uint64 `protobuf:"varint,2,opt,name=Height,proto3" json:"Height,omitempty"` + Shares []*Share `protobuf:"bytes,3,rep,name=Shares,proto3" json:"Shares,omitempty"` + Index uint32 `protobuf:"varint,4,opt,name=Index,proto3" json:"Index,omitempty"` + Axis Axis `protobuf:"varint,5,opt,name=Axis,proto3,enum=share.validation.pb.Axis" json:"Axis,omitempty"` +} + +func (m *BadEncoding) Reset() { *m = BadEncoding{} } +func (m *BadEncoding) String() string { return proto.CompactTextString(m) } +func (*BadEncoding) ProtoMessage() {} +func (*BadEncoding) Descriptor() ([]byte, []int) { + return fileDescriptor_809b930156a12991, []int{2} +} +func (m *BadEncoding) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *BadEncoding) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_BadEncoding.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 *BadEncoding) XXX_Merge(src proto.Message) { + xxx_messageInfo_BadEncoding.Merge(m, src) +} +func (m *BadEncoding) XXX_Size() int { + return m.Size() +} +func (m *BadEncoding) XXX_DiscardUnknown() { + xxx_messageInfo_BadEncoding.DiscardUnknown(m) +} + +var xxx_messageInfo_BadEncoding proto.InternalMessageInfo + +func (m *BadEncoding) GetHeaderHash() []byte { + if m != nil { + return m.HeaderHash + } + return nil +} + +func (m *BadEncoding) GetHeight() uint64 { + if m != nil { + return m.Height + } + return 0 +} + +func (m *BadEncoding) GetShares() []*Share { + if m != nil { + return m.Shares + } + return nil +} + +func (m *BadEncoding) GetIndex() uint32 { + if m != nil { + return m.Index + } + return 0 +} + +func (m *BadEncoding) GetAxis() Axis { + if m != nil { + return m.Axis + } + return Axis_ROW +} + func init() { - proto.RegisterType((*MerkleProof)(nil), "ipld.pb.MerkleProof") - proto.RegisterType((*Share)(nil), "ipld.pb.Share") -} - -func init() { proto.RegisterFile("ipld/pb/share.proto", fileDescriptor_f1f041c2d5c8eb54) } - -var fileDescriptor_f1f041c2d5c8eb54 = []byte{ - // 247 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xce, 0x2c, 0xc8, 0x49, - 0xd1, 0x2f, 0x48, 0xd2, 0x2f, 0xce, 0x48, 0x2c, 0x4a, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, - 0x62, 0x07, 0x09, 0xea, 0x15, 0x24, 0x29, 0x65, 0x70, 0x71, 0xfb, 0xa6, 0x16, 0x65, 0xe7, 0xa4, - 0x06, 0x14, 0xe5, 0xe7, 0xa7, 0x09, 0x89, 0x70, 0xb1, 0x16, 0x97, 0x24, 0x16, 0x95, 0x48, 0x30, - 0x2a, 0x30, 0x6a, 0x30, 0x07, 0x41, 0x38, 0x42, 0x02, 0x5c, 0xcc, 0xa9, 0x79, 0x29, 0x12, 0x4c, - 0x60, 0x31, 0x10, 0x13, 0xa4, 0x2e, 0x2f, 0x3f, 0x25, 0xb5, 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, - 0x27, 0x08, 0xc2, 0x11, 0x92, 0xe6, 0xe2, 0xcc, 0x49, 0x4d, 0x4c, 0x8b, 0xcf, 0x48, 0x2c, 0xce, - 0x90, 0x60, 0x51, 0x60, 0xd4, 0xe0, 0x09, 0xe2, 0x00, 0x09, 0x78, 0x24, 0x16, 0x67, 0x28, 0xb9, - 0x73, 0xb1, 0x06, 0x83, 0x5c, 0x20, 0x24, 0xc4, 0xc5, 0xe2, 0x92, 0x58, 0x92, 0x08, 0xb6, 0x82, - 0x27, 0x08, 0xcc, 0x16, 0xd2, 0xe2, 0x62, 0x05, 0x3b, 0x00, 0x6c, 0x07, 0xb7, 0x91, 0x88, 0x1e, - 0xd4, 0x7d, 0x7a, 0x48, 0x8e, 0x0b, 0x82, 0x28, 0x71, 0x72, 0x3b, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, - 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0xb8, 0xf0, 0x58, 0x8e, 0xe1, - 0xc6, 0x63, 0x39, 0x86, 0x28, 0x9d, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, - 0xfd, 0xe4, 0xd4, 0x9c, 0xd4, 0xe2, 0x92, 0xcc, 0xc4, 0xfc, 0xa2, 0x74, 0x38, 0x5b, 0x17, 0xe4, - 0x4c, 0x7d, 0x68, 0x78, 0x24, 0xb1, 0x81, 0x83, 0xc2, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x7f, - 0x2b, 0x98, 0xa2, 0x21, 0x01, 0x00, 0x00, + proto.RegisterEnum("share.validation.pb.Axis", Axis_name, Axis_value) + proto.RegisterType((*MerkleProof)(nil), "share.validation.pb.MerkleProof") + proto.RegisterType((*Share)(nil), "share.validation.pb.Share") + proto.RegisterType((*BadEncoding)(nil), "share.validation.pb.BadEncoding") +} + +func init() { proto.RegisterFile("share/validation/pb/share.proto", fileDescriptor_809b930156a12991) } + +var fileDescriptor_809b930156a12991 = []byte{ + // 371 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0x41, 0x6b, 0xdb, 0x30, + 0x18, 0xb5, 0x66, 0x3b, 0xdb, 0x3e, 0x67, 0x23, 0x68, 0x63, 0x78, 0x1b, 0x78, 0x26, 0x27, 0x33, + 0x88, 0x0d, 0x1e, 0x8c, 0x5e, 0x9b, 0xb6, 0x90, 0x42, 0x4b, 0x8a, 0x72, 0x28, 0xf4, 0x52, 0xe4, + 0x58, 0xb1, 0x45, 0x5d, 0x2b, 0x58, 0x6a, 0xc9, 0xcf, 0xe8, 0x2f, 0xea, 0xb9, 0xc7, 0x1c, 0x7b, + 0x2c, 0xc9, 0x1f, 0x29, 0x92, 0x43, 0x9b, 0x83, 0x6f, 0xef, 0x3d, 0x1e, 0x7a, 0xef, 0xd3, 0xf7, + 0xc1, 0x1f, 0x59, 0xd2, 0x86, 0x25, 0xf7, 0xb4, 0xe2, 0x39, 0x55, 0x5c, 0xd4, 0xc9, 0x32, 0x4b, + 0x8c, 0x16, 0x2f, 0x1b, 0xa1, 0x04, 0xfe, 0xd6, 0x92, 0x77, 0x43, 0xbc, 0xcc, 0x86, 0x25, 0x78, + 0xe7, 0xac, 0xb9, 0xa9, 0xd8, 0x45, 0x23, 0xc4, 0x02, 0x7f, 0x07, 0x57, 0x2a, 0xda, 0x28, 0x1f, + 0x85, 0x28, 0xb2, 0x49, 0x4b, 0xf0, 0x00, 0x6c, 0x56, 0xe7, 0xfe, 0x07, 0xa3, 0x69, 0xa8, 0x7d, + 0xb5, 0xc8, 0x99, 0xf4, 0xed, 0xd0, 0x8e, 0xfa, 0xa4, 0x25, 0xf8, 0x37, 0x7c, 0xae, 0x18, 0x5d, + 0x5c, 0x97, 0x54, 0x96, 0xbe, 0x13, 0xa2, 0xa8, 0x4f, 0x3e, 0x69, 0x61, 0x42, 0x65, 0x39, 0x9c, + 0x81, 0x3b, 0xd3, 0x05, 0x30, 0x06, 0xe7, 0x98, 0x2a, 0x6a, 0x22, 0xfa, 0xc4, 0x60, 0xfc, 0x1f, + 0x5c, 0x53, 0xc0, 0x64, 0x78, 0x69, 0x18, 0x77, 0x74, 0x8d, 0xf7, 0x8a, 0x92, 0xd6, 0x3e, 0x7c, + 0x44, 0xe0, 0x8d, 0x69, 0x7e, 0x52, 0xcf, 0x45, 0xce, 0xeb, 0x02, 0x07, 0x00, 0x13, 0x46, 0x73, + 0xd6, 0xe8, 0xc8, 0x5d, 0xc2, 0x9e, 0x82, 0x7f, 0x40, 0x6f, 0xc2, 0x78, 0x51, 0x2a, 0x13, 0xe4, + 0x90, 0x1d, 0xc3, 0x29, 0xf4, 0x4c, 0xb9, 0x76, 0x20, 0x2f, 0xfd, 0xd5, 0x59, 0xc0, 0x58, 0xc8, + 0xce, 0xa9, 0xff, 0xe0, 0xb4, 0xce, 0xd9, 0xca, 0x4c, 0xfa, 0x85, 0xb4, 0x04, 0x8f, 0xc0, 0x39, + 0x5c, 0x71, 0xe9, 0xbb, 0x21, 0x8a, 0xbe, 0xa6, 0x3f, 0x3b, 0xdf, 0xa1, 0x2b, 0x2e, 0x89, 0xb1, + 0xfd, 0xf5, 0xc1, 0xd1, 0x0c, 0x7f, 0x04, 0x9b, 0x4c, 0x2f, 0x07, 0x96, 0x06, 0x47, 0xd3, 0xb3, + 0x01, 0x1a, 0x93, 0xa7, 0x4d, 0x80, 0xd6, 0x9b, 0x00, 0xbd, 0x6c, 0x02, 0xf4, 0xb0, 0x0d, 0xac, + 0xf5, 0x36, 0xb0, 0x9e, 0xb7, 0x81, 0x75, 0x75, 0x50, 0x70, 0x55, 0xde, 0x65, 0xf1, 0x5c, 0xdc, + 0x26, 0x73, 0x56, 0x31, 0xa9, 0x38, 0x15, 0x4d, 0xf1, 0x86, 0x47, 0x7a, 0x1b, 0x49, 0xc7, 0x39, + 0x64, 0x3d, 0x73, 0x09, 0xff, 0x5e, 0x03, 0x00, 0x00, 0xff, 0xff, 0x6c, 0xfd, 0x11, 0x26, 0x2c, + 0x02, 0x00, 0x00, } func (m *MerkleProof) Marshal() (dAtA []byte, err error) { @@ -260,6 +371,65 @@ func (m *Share) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *BadEncoding) 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 *BadEncoding) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *BadEncoding) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Axis != 0 { + i = encodeVarintShare(dAtA, i, uint64(m.Axis)) + i-- + dAtA[i] = 0x28 + } + if m.Index != 0 { + i = encodeVarintShare(dAtA, i, uint64(m.Index)) + i-- + dAtA[i] = 0x20 + } + if len(m.Shares) > 0 { + for iNdEx := len(m.Shares) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Shares[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintShare(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x1a + } + } + if m.Height != 0 { + i = encodeVarintShare(dAtA, i, uint64(m.Height)) + i-- + dAtA[i] = 0x10 + } + if len(m.HeaderHash) > 0 { + i -= len(m.HeaderHash) + copy(dAtA[i:], m.HeaderHash) + i = encodeVarintShare(dAtA, i, uint64(len(m.HeaderHash))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintShare(dAtA []byte, offset int, v uint64) int { offset -= sovShare(v) base := offset @@ -313,6 +483,34 @@ func (m *Share) Size() (n int) { return n } +func (m *BadEncoding) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.HeaderHash) + if l > 0 { + n += 1 + l + sovShare(uint64(l)) + } + if m.Height != 0 { + n += 1 + sovShare(uint64(m.Height)) + } + if len(m.Shares) > 0 { + for _, e := range m.Shares { + l = e.Size() + n += 1 + l + sovShare(uint64(l)) + } + } + if m.Index != 0 { + n += 1 + sovShare(uint64(m.Index)) + } + if m.Axis != 0 { + n += 1 + sovShare(uint64(m.Axis)) + } + return n +} + func sovShare(x uint64) (n int) { return (math_bits.Len64(x|1) + 6) / 7 } @@ -593,6 +791,181 @@ func (m *Share) Unmarshal(dAtA []byte) error { } return nil } +func (m *BadEncoding) 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 ErrIntOverflowShare + } + 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: BadEncoding: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: BadEncoding: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field HeaderHash", wireType) + } + var byteLen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowShare + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + byteLen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if byteLen < 0 { + return ErrInvalidLengthShare + } + postIndex := iNdEx + byteLen + if postIndex < 0 { + return ErrInvalidLengthShare + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.HeaderHash = append(m.HeaderHash[:0], dAtA[iNdEx:postIndex]...) + if m.HeaderHash == nil { + m.HeaderHash = []byte{} + } + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) + } + m.Height = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowShare + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Height |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Shares", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowShare + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthShare + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthShare + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Shares = append(m.Shares, &Share{}) + if err := m.Shares[len(m.Shares)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) + } + m.Index = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowShare + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Index |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Axis", wireType) + } + m.Axis = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowShare + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Axis |= Axis(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipShare(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthShare + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skipShare(dAtA []byte) (n int, err error) { l := len(dAtA) iNdEx := 0 diff --git a/share/eds/byzantine/pb/share.proto b/share/eds/byzantine/pb/share.proto new file mode 100644 index 0000000000..bb202c6ad8 --- /dev/null +++ b/share/eds/byzantine/pb/share.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package share.validation.pb; + +option go_package="github.com/celestiaorg/celestia-node/share/proof/pb"; + +enum axis { + ROW = 0; + COL = 1; +} + +message MerkleProof { + int64 start = 1; + int64 end = 2; + repeated bytes nodes = 3; + bytes leaf_hash = 4; +} + +message Share { + bytes Data = 1; + MerkleProof Proof = 2; +} + +message BadEncoding { + bytes HeaderHash = 1; + uint64 Height = 2; + repeated Share Shares = 3; + uint32 Index = 4; + axis Axis = 5; +} \ No newline at end of file diff --git a/share/eds/byzantine/share_proof.go b/share/eds/byzantine/share_proof.go new file mode 100644 index 0000000000..6b151fc5c7 --- /dev/null +++ b/share/eds/byzantine/share_proof.go @@ -0,0 +1,105 @@ +package byzantine + +import ( + "context" + + "github.com/ipfs/go-blockservice" + "github.com/ipfs/go-cid" + logging "github.com/ipfs/go-log/v2" + "github.com/minio/sha256-simd" + + "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/byzantine/pb" + "github.com/celestiaorg/celestia-node/share/ipld" + "github.com/celestiaorg/nmt" +) + +var log = logging.Logger("share/validation") + +// ShareWithProof contains data with corresponding Merkle Proof +type ShareWithProof struct { + // Share is a full data including namespace + share.Share + // Proof is a Merkle Proof of current share + Proof *nmt.Proof +} + +// NewShareWithProof takes the given leaf and its path, starting from the tree root, +// and computes the nmt.Proof for it. +func NewShareWithProof(index int, share share.Share, pathToLeaf []cid.Cid) *ShareWithProof { + rangeProofs := make([][]byte, 0, len(pathToLeaf)) + for i := len(pathToLeaf) - 1; i >= 0; i-- { + node := ipld.NamespacedSha256FromCID(pathToLeaf[i]) + rangeProofs = append(rangeProofs, node) + } + + proof := nmt.NewInclusionProof(index, index+1, rangeProofs, true) + return &ShareWithProof{ + share, + &proof, + } +} + +// Validate validates inclusion of the share under the given root CID. +func (s *ShareWithProof) Validate(root cid.Cid) bool { + return s.Proof.VerifyInclusion( + sha256.New(), // TODO(@Wondertan): This should be defined somewhere globally + share.ID(s.Share), + [][]byte{share.Data(s.Share)}, + ipld.NamespacedSha256FromCID(root), + ) +} + +func (s *ShareWithProof) ShareWithProofToProto() *pb.Share { + return &pb.Share{ + Data: s.Share, + Proof: &pb.MerkleProof{ + Start: int64(s.Proof.Start()), + End: int64(s.Proof.End()), + Nodes: s.Proof.Nodes(), + LeafHash: s.Proof.LeafHash(), + }, + } +} + +// GetProofsForShares fetches Merkle proofs for the given shares +// and returns the result as an array of ShareWithProof. +func GetProofsForShares( + ctx context.Context, + bGetter blockservice.BlockGetter, + root cid.Cid, + shares [][]byte, +) ([]*ShareWithProof, error) { + proofs := make([]*ShareWithProof, len(shares)) + for index, share := range shares { + if share != nil { + proof := make([]cid.Cid, 0) + // TODO(@vgonkivs): Combine GetLeafData and GetProof in one function as the are traversing the same tree. + // Add options that will control what data will be fetched. + s, err := ipld.GetLeaf(ctx, bGetter, root, index, len(shares)) + if err != nil { + return nil, err + } + proof, err = ipld.GetProof(ctx, bGetter, root, proof, index, len(shares)) + if err != nil { + return nil, err + } + proofs[index] = NewShareWithProof(index, s.RawData(), proof) + } + } + + return proofs, nil +} + +func ProtoToShare(protoShares []*pb.Share) []*ShareWithProof { + shares := make([]*ShareWithProof, len(protoShares)) + for i, share := range protoShares { + proof := ProtoToProof(share.Proof) + shares[i] = &ShareWithProof{share.Data, &proof} + } + return shares +} + +func ProtoToProof(protoProof *pb.MerkleProof) nmt.Proof { + return nmt.NewInclusionProof(int(protoProof.Start), int(protoProof.End), protoProof.Nodes, true) +} diff --git a/share/eds/byzantine/share_proof_test.go b/share/eds/byzantine/share_proof_test.go new file mode 100644 index 0000000000..e98c424597 --- /dev/null +++ b/share/eds/byzantine/share_proof_test.go @@ -0,0 +1,81 @@ +package byzantine + +import ( + "context" + "strconv" + "testing" + "time" + + "github.com/ipfs/go-cid" + mdutils "github.com/ipfs/go-merkledag/test" + "github.com/stretchr/testify/require" + + "github.com/celestiaorg/celestia-app/pkg/da" + "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/ipld" +) + +func TestGetProof(t *testing.T) { + const width = 4 + + ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) + defer cancel() + bServ := mdutils.Bserv() + + shares := share.RandShares(t, width*width) + in, err := share.AddShares(ctx, shares, bServ) + require.NoError(t, err) + + dah := da.NewDataAvailabilityHeader(in) + var tests = []struct { + roots [][]byte + }{ + {dah.RowsRoots}, + {dah.ColumnRoots}, + } + + for i, tt := range tests { + t.Run(strconv.Itoa(i), func(t *testing.T) { + for _, root := range tt.roots { + rootCid := ipld.MustCidFromNamespacedSha256(root) + for index := 0; uint(index) < in.Width(); index++ { + proof := make([]cid.Cid, 0) + proof, err = ipld.GetProof(ctx, bServ, rootCid, proof, index, int(in.Width())) + require.NoError(t, err) + node, err := ipld.GetLeaf(ctx, bServ, rootCid, index, int(in.Width())) + require.NoError(t, err) + inclusion := NewShareWithProof(index, node.RawData(), proof) + require.True(t, inclusion.Validate(rootCid)) + } + } + }) + } +} + +func TestGetProofs(t *testing.T) { + const width = 4 + ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) + defer cancel() + bServ := mdutils.Bserv() + + shares := share.RandShares(t, width*width) + in, err := share.AddShares(ctx, shares, bServ) + require.NoError(t, err) + + dah := da.NewDataAvailabilityHeader(in) + for _, root := range dah.ColumnRoots { + rootCid := ipld.MustCidFromNamespacedSha256(root) + data := make([][]byte, 0, in.Width()) + for index := 0; uint(index) < in.Width(); index++ { + node, err := ipld.GetLeaf(ctx, bServ, rootCid, index, int(in.Width())) + require.NoError(t, err) + data = append(data, node.RawData()[9:]) + } + + proves, err := GetProofsForShares(ctx, bServ, rootCid, data) + require.NoError(t, err) + for _, proof := range proves { + require.True(t, proof.Validate(rootCid)) + } + } +} diff --git a/share/eds/retriever.go b/share/eds/retriever.go index 19ba7f07d4..ac473ede96 100644 --- a/share/eds/retriever.go +++ b/share/eds/retriever.go @@ -19,6 +19,7 @@ import ( "github.com/celestiaorg/celestia-app/pkg/da" "github.com/celestiaorg/celestia-app/pkg/wrapper" "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/byzantine" "github.com/celestiaorg/celestia-node/share/ipld" "github.com/celestiaorg/nmt" "github.com/celestiaorg/rsmt2d" @@ -88,7 +89,7 @@ func (r *Retriever) Retrieve(ctx context.Context, dah *da.DataAvailabilityHeader var errByz *rsmt2d.ErrByzantineData if errors.As(err, &errByz) { span.RecordError(err) - return nil, share.NewErrByzantine(ctx, r.bServ, dah, errByz) + return nil, byzantine.NewErrByzantine(ctx, r.bServ, dah, errByz) } log.Warnw("not enough shares to reconstruct data square, requesting more...", "err", err) diff --git a/share/eds/retriever_test.go b/share/eds/retriever_test.go index 7d773b4c8c..90f8a2665f 100644 --- a/share/eds/retriever_test.go +++ b/share/eds/retriever_test.go @@ -2,18 +2,22 @@ package eds import ( "context" + "errors" "math/rand" "testing" "time" + "github.com/ipfs/go-blockservice" mdutils "github.com/ipfs/go-merkledag/test" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/celestiaorg/celestia-app/pkg/da" "github.com/celestiaorg/celestia-app/pkg/wrapper" - + "github.com/celestiaorg/celestia-node/fraud" + "github.com/celestiaorg/celestia-node/header" "github.com/celestiaorg/celestia-node/share" + "github.com/celestiaorg/celestia-node/share/eds/byzantine" "github.com/celestiaorg/celestia-node/share/ipld" "github.com/celestiaorg/nmt" "github.com/celestiaorg/rsmt2d" @@ -90,7 +94,7 @@ func TestRetriever_ByzantineError(t *testing.T) { dah := da.NewDataAvailabilityHeader(attackerEDS) r := NewRetriever(bserv) _, err = r.Retrieve(ctx, &dah) - var errByz *share.ErrByzantine + var errByz *byzantine.ErrByzantine require.ErrorAs(t, err, &errByz) } @@ -123,3 +127,31 @@ func TestRetriever_MultipleRandQuadrants(t *testing.T) { _, err = ses.Reconstruct(ctx) assert.NoError(t, err) } + +func TestFraudProofValidation(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*15) + defer t.Cleanup(cancel) + bServ := mdutils.Bserv() + + var errByz *byzantine.ErrByzantine + faultHeader, err := generateByzantineError(ctx, t, bServ) + require.True(t, errors.As(err, &errByz)) + + p := byzantine.CreateBadEncodingProof([]byte("hash"), uint64(faultHeader.Height), errByz) + err = p.Validate(faultHeader) + require.NoError(t, err) +} + +func generateByzantineError( + ctx context.Context, + t *testing.T, + bServ blockservice.BlockService, +) (*header.ExtendedHeader, error) { + _, store := fraud.CreateTestService(t, false) + h, err := store.GetByHeight(ctx, 1) + require.NoError(t, err) + + faultHeader := header.CreateFraudExtHeader(t, h, bServ) + _, err = NewRetriever(bServ).Retrieve(ctx, faultHeader.DAH) + return faultHeader, err +} diff --git a/share/get.go b/share/get.go index 219b73c50c..b6734562e7 100644 --- a/share/get.go +++ b/share/get.go @@ -68,35 +68,6 @@ func GetSharesByNamespace( return shares, err } -// GetProofsForShares fetches Merkle proofs for the given shares -// and returns the result as an array of ShareWithProof. -func GetProofsForShares( - ctx context.Context, - bGetter blockservice.BlockGetter, - root cid.Cid, - shares [][]byte, -) ([]*ShareWithProof, error) { - proofs := make([]*ShareWithProof, len(shares)) - for index, share := range shares { - if share != nil { - proof := make([]cid.Cid, 0) - // TODO(@vgonkivs): Combine GetLeafData and GetProof in one function as the are traversing the same tree. - // Add options that will control what data will be fetched. - s, err := ipld.GetLeaf(ctx, bGetter, root, index, len(shares)) - if err != nil { - return nil, err - } - proof, err = ipld.GetProof(ctx, bGetter, root, proof, index, len(shares)) - if err != nil { - return nil, err - } - proofs[index] = NewShareWithProof(index, s.RawData(), proof) - } - } - - return proofs, nil -} - // leafToShare converts an NMT leaf into a Share. func leafToShare(nd format.Node) Share { // * Additional namespace is prepended so that parity data can be identified with a parity namespace, which we cut off diff --git a/share/get_test.go b/share/get_test.go index 714d1c62ef..41f3219854 100644 --- a/share/get_test.go +++ b/share/get_test.go @@ -18,9 +18,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/celestiaorg/celestia-app/pkg/da" "github.com/celestiaorg/celestia-app/pkg/wrapper" - "github.com/celestiaorg/celestia-node/share/ipld" "github.com/celestiaorg/nmt/namespace" "github.com/celestiaorg/rsmt2d" @@ -370,68 +368,3 @@ func assertNoRowContainsNID( assert.Nil(t, err) } } - -func TestGetProof(t *testing.T) { - const width = 4 - - ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) - defer cancel() - bServ := mdutils.Bserv() - - shares := RandShares(t, width*width) - in, err := AddShares(ctx, shares, bServ) - require.NoError(t, err) - - dah := da.NewDataAvailabilityHeader(in) - var tests = []struct { - roots [][]byte - }{ - {dah.RowsRoots}, - {dah.ColumnRoots}, - } - - for i, tt := range tests { - t.Run(strconv.Itoa(i), func(t *testing.T) { - for _, root := range tt.roots { - rootCid := ipld.MustCidFromNamespacedSha256(root) - for index := 0; uint(index) < in.Width(); index++ { - proof := make([]cid.Cid, 0) - proof, err = ipld.GetProof(ctx, bServ, rootCid, proof, index, int(in.Width())) - require.NoError(t, err) - node, err := ipld.GetLeaf(ctx, bServ, rootCid, index, int(in.Width())) - require.NoError(t, err) - inclusion := NewShareWithProof(index, node.RawData(), proof) - require.True(t, inclusion.Validate(rootCid)) - } - } - }) - } -} - -func TestGetProofs(t *testing.T) { - const width = 4 - ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) - defer cancel() - bServ := mdutils.Bserv() - - shares := RandShares(t, width*width) - in, err := AddShares(ctx, shares, bServ) - require.NoError(t, err) - - dah := da.NewDataAvailabilityHeader(in) - for _, root := range dah.ColumnRoots { - rootCid := ipld.MustCidFromNamespacedSha256(root) - data := make([][]byte, 0, in.Width()) - for index := 0; uint(index) < in.Width(); index++ { - node, err := ipld.GetLeaf(ctx, bServ, rootCid, index, int(in.Width())) - require.NoError(t, err) - data = append(data, node.RawData()[9:]) - } - - proves, err := GetProofsForShares(ctx, bServ, rootCid, data) - require.NoError(t, err) - for _, proof := range proves { - require.True(t, proof.Validate(rootCid)) - } - } -} diff --git a/share/pb/share.proto b/share/pb/share.proto deleted file mode 100644 index 7838d069f4..0000000000 --- a/share/pb/share.proto +++ /dev/null @@ -1,17 +0,0 @@ -syntax = "proto3"; - -package ipld.pb; - -option go_package="github.com/celestiaorg/celestia-node/ipld/pb"; - -message MerkleProof { - int64 start = 1; - int64 end = 2; - repeated bytes nodes = 3; - bytes leaf_hash = 4; -} - -message Share { - bytes Data = 1; - MerkleProof Proof = 2; -} diff --git a/share/share.go b/share/share.go index 604a531386..8b05791e02 100644 --- a/share/share.go +++ b/share/share.go @@ -1,21 +1,13 @@ package share import ( - "crypto/sha256" - - "github.com/ipfs/go-cid" - logging "github.com/ipfs/go-log/v2" "go.opentelemetry.io/otel" "github.com/celestiaorg/celestia-app/pkg/appconsts" - "github.com/celestiaorg/celestia-node/share/ipld" - "github.com/celestiaorg/celestia-node/share/pb" - "github.com/celestiaorg/nmt" "github.com/celestiaorg/nmt/namespace" ) var ( - log = logging.Logger("share") tracer = otel.Tracer("share") // DefaultRSMT2DCodec sets the default rsmt2d.Codec for shares. @@ -45,62 +37,3 @@ func ID(s Share) namespace.ID { func Data(s Share) []byte { return s[NamespaceSize:] } - -// ShareWithProof contains data with corresponding Merkle Proof -type ShareWithProof struct { //nolint:revive - // Share is a full data including namespace - Share - // Proof is a Merkle Proof of current share - Proof *nmt.Proof -} - -// NewShareWithProof takes the given leaf and its path, starting from the tree root, -// and computes the nmt.Proof for it. -func NewShareWithProof(index int, share Share, pathToLeaf []cid.Cid) *ShareWithProof { - rangeProofs := make([][]byte, 0, len(pathToLeaf)) - for i := len(pathToLeaf) - 1; i >= 0; i-- { - node := ipld.NamespacedSha256FromCID(pathToLeaf[i]) - rangeProofs = append(rangeProofs, node) - } - - proof := nmt.NewInclusionProof(index, index+1, rangeProofs, true) - return &ShareWithProof{ - share, - &proof, - } -} - -// Validate validates inclusion of the share under the given root CID. -func (s *ShareWithProof) Validate(root cid.Cid) bool { - return s.Proof.VerifyInclusion( - sha256.New(), // TODO(@Wondertan): This should be defined somewhere globally - ID(s.Share), - [][]byte{Data(s.Share)}, - ipld.NamespacedSha256FromCID(root), - ) -} - -func (s *ShareWithProof) ShareWithProofToProto() *pb.Share { - return &pb.Share{ - Data: s.Share, - Proof: &pb.MerkleProof{ - Start: int64(s.Proof.Start()), - End: int64(s.Proof.End()), - Nodes: s.Proof.Nodes(), - LeafHash: s.Proof.LeafHash(), - }, - } -} - -func ProtoToShare(protoShares []*pb.Share) []*ShareWithProof { - shares := make([]*ShareWithProof, len(protoShares)) - for i, share := range protoShares { - proof := ProtoToProof(share.Proof) - shares[i] = &ShareWithProof{share.Data, &proof} - } - return shares -} - -func ProtoToProof(protoProof *pb.MerkleProof) nmt.Proof { - return nmt.NewInclusionProof(int(protoProof.Start), int(protoProof.End), protoProof.Nodes, true) -}