github.com/celestiaorg/celestia-node@v0.15.0-beta.1/header/serde.go (about)

     1  package header
     2  
     3  import (
     4  	pb "github.com/libp2p/go-libp2p-pubsub/pb"
     5  	core "github.com/tendermint/tendermint/types"
     6  	"golang.org/x/crypto/blake2b"
     7  
     8  	"github.com/celestiaorg/celestia-app/pkg/da"
     9  
    10  	header_pb "github.com/celestiaorg/celestia-node/header/pb"
    11  )
    12  
    13  // MarshalExtendedHeader serializes given ExtendedHeader to bytes using protobuf.
    14  // Paired with UnmarshalExtendedHeader.
    15  func MarshalExtendedHeader(in *ExtendedHeader) (_ []byte, err error) {
    16  	out := &header_pb.ExtendedHeader{
    17  		Header: in.RawHeader.ToProto(),
    18  		Commit: in.Commit.ToProto(),
    19  	}
    20  
    21  	out.ValidatorSet, err = in.ValidatorSet.ToProto()
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  
    26  	out.Dah, err = in.DAH.ToProto()
    27  	if err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	return out.Marshal()
    32  }
    33  
    34  // UnmarshalExtendedHeader deserializes given data into a new ExtendedHeader using protobuf.
    35  // Paired with MarshalExtendedHeader.
    36  func UnmarshalExtendedHeader(data []byte) (*ExtendedHeader, error) {
    37  	in := &header_pb.ExtendedHeader{}
    38  	err := in.Unmarshal(data)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	out := &ExtendedHeader{}
    44  	out.RawHeader, err = core.HeaderFromProto(in.Header)
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	out.Commit, err = core.CommitFromProto(in.Commit)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	out.ValidatorSet, err = core.ValidatorSetFromProto(in.ValidatorSet)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	out.DAH, err = da.DataAvailabilityHeaderFromProto(in.Dah)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  
    64  	return out, nil
    65  }
    66  
    67  func ExtendedHeaderToProto(eh *ExtendedHeader) (*header_pb.ExtendedHeader, error) {
    68  	pb := &header_pb.ExtendedHeader{
    69  		Header: eh.RawHeader.ToProto(),
    70  		Commit: eh.Commit.ToProto(),
    71  	}
    72  	valSet, err := eh.ValidatorSet.ToProto()
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	pb.ValidatorSet = valSet
    77  	dah, err := eh.DAH.ToProto()
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	pb.Dah = dah
    82  	return pb, nil
    83  }
    84  
    85  func ProtoToExtendedHeader(pb *header_pb.ExtendedHeader) (*ExtendedHeader, error) {
    86  	bin, err := pb.Marshal()
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	header := new(ExtendedHeader)
    91  	err = header.UnmarshalBinary(bin)
    92  	if err != nil {
    93  		return nil, err
    94  	}
    95  	return header, nil
    96  }
    97  
    98  // msgID computes an id for a pubsub message
    99  // TODO(@Wondertan): This cause additional allocations per each recvd message in the topic
   100  //
   101  //	Find a way to avoid those.
   102  func MsgID(pmsg *pb.Message) string {
   103  	mID := func(data []byte) string {
   104  		hash := blake2b.Sum256(data)
   105  		return string(hash[:])
   106  	}
   107  
   108  	h, _ := UnmarshalExtendedHeader(pmsg.Data)
   109  	if h == nil || h.RawHeader.ValidateBasic() != nil {
   110  		// There is nothing we can do about the error, and it will be anyway caught during validation.
   111  		// We also *have* to return some ID for the msg, so give the hash of even faulty msg
   112  		return mID(pmsg.Data)
   113  	}
   114  
   115  	// IMPORTANT NOTE:
   116  	// Due to the nature of the Tendermint consensus, validators don't necessarily collect commit
   117  	// signatures from the entire validator set, but only the minimum required amount of them (>2/3 of
   118  	// voting power). In addition, signatures are collected asynchronously. Therefore, each validator
   119  	// may have a different set of signatures that pass the minimum required voting power threshold,
   120  	// causing nondeterminism in the header message gossiped over the network. Subsequently, this
   121  	// causes message duplicates as each Bridge Node, connected to a personal validator, sends the
   122  	// validator's own view of commits of effectively the same header.
   123  	//
   124  	// To solve the nondeterminism problem above, we don't compute msg id on message body and take
   125  	// the actual header hash as an id.
   126  	return h.Commit.BlockID.String()
   127  }