go.dedis.ch/onet/v4@v4.0.0-pre1/network/encoding.go (about)

     1  package network
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"reflect"
     8  	"sync"
     9  
    10  	"go.dedis.ch/kyber/v4/pairing/bn256"
    11  	"go.dedis.ch/kyber/v4/suites"
    12  	"golang.org/x/xerrors"
    13  
    14  	"go.dedis.ch/kyber/v4"
    15  	"go.dedis.ch/onet/v4/log"
    16  	"go.dedis.ch/protobuf"
    17  	uuid "gopkg.in/satori/go.uuid.v1"
    18  )
    19  
    20  func init() {
    21  	protobuf.RegisterInterface(func() interface{} { return bn256.NewSuiteG1().Point() })
    22  	protobuf.RegisterInterface(func() interface{} { return bn256.NewSuiteG1().Scalar() })
    23  	protobuf.RegisterInterface(func() interface{} { return bn256.NewSuiteG2().Point() })
    24  	protobuf.RegisterInterface(func() interface{} { return bn256.NewSuiteG2().Scalar() })
    25  	protobuf.RegisterInterface(func() interface{} { return bn256.NewSuiteGT().Point() })
    26  	protobuf.RegisterInterface(func() interface{} { return bn256.NewSuiteGT().Scalar() })
    27  
    28  	ed25519 := suites.MustFind("Ed25519")
    29  	protobuf.RegisterInterface(func() interface{} { return ed25519.Point() })
    30  	protobuf.RegisterInterface(func() interface{} { return ed25519.Scalar() })
    31  }
    32  
    33  /// Encoding part ///
    34  
    35  // Suite functionalities used globally by the network library.
    36  type Suite interface {
    37  	kyber.Group
    38  	kyber.Random
    39  }
    40  
    41  // Message is a type for any message that the user wants to send
    42  type Message interface{}
    43  
    44  // MessageTypeID is the ID used to uniquely identify different registered messages
    45  type MessageTypeID uuid.UUID
    46  
    47  // ErrorType is reserved by the network library. When you receive a message of
    48  // ErrorType, it is generally because an error happened, then you can call
    49  // Error() on it.
    50  var ErrorType = MessageTypeID(uuid.Nil)
    51  
    52  // String returns the name of the structure if it is known, else it returns
    53  // the hexadecimal value of the Id.
    54  func (mId MessageTypeID) String() string {
    55  	t, ok := registry.get(mId)
    56  	if ok {
    57  		return fmt.Sprintf("PTID(%s:%x)", t.String(), uuid.UUID(mId).Bytes())
    58  	}
    59  	return uuid.UUID(mId).String()
    60  }
    61  
    62  // Equal returns true if and only if mID2 equals this MessageTypeID
    63  func (mId MessageTypeID) Equal(mID2 MessageTypeID) bool {
    64  	return uuid.Equal(uuid.UUID(mId), uuid.UUID(mID2))
    65  }
    66  
    67  // IsNil returns true iff the MessageTypeID is Nil
    68  func (mId MessageTypeID) IsNil() bool {
    69  	return mId.Equal(MessageTypeID(uuid.Nil))
    70  }
    71  
    72  // NamespaceURL is the basic namespace used for uuid
    73  // XXX should move that to external of the library as not every
    74  // cothority/packages should be expected to use that.
    75  const NamespaceURL = "https://dedis.epfl.ch/"
    76  
    77  // NamespaceBodyType is the namespace used for PacketTypeID
    78  const NamespaceBodyType = NamespaceURL + "/protocolType/"
    79  
    80  var globalOrder = binary.BigEndian
    81  
    82  // RegisterMessage registers any struct or ptr and returns the
    83  // corresponding MessageTypeID. Once a struct is registered, it can be sent and
    84  // received by the network library.
    85  func RegisterMessage(msg Message) MessageTypeID {
    86  	msgType := computeMessageType(msg)
    87  	val := reflect.ValueOf(msg)
    88  	if val.Kind() == reflect.Ptr {
    89  		val = val.Elem()
    90  	}
    91  	t := val.Type()
    92  	registry.put(msgType, t)
    93  	return msgType
    94  }
    95  
    96  // RegisterMessages is a convenience function to register multiple messages
    97  // together. It returns the MessageTypeIDs of the registered messages. If you
    98  // give the same message more than once, it will register it only once, but return
    99  // it's id as many times as it appears in the arguments.
   100  func RegisterMessages(msg ...Message) []MessageTypeID {
   101  	var ret []MessageTypeID
   102  	for _, m := range msg {
   103  		ret = append(ret, RegisterMessage(m))
   104  	}
   105  	return ret
   106  }
   107  
   108  func computeMessageType(msg Message) MessageTypeID {
   109  	val := reflect.ValueOf(msg)
   110  	if val.Kind() == reflect.Ptr {
   111  		val = val.Elem()
   112  	}
   113  	url := NamespaceBodyType + val.Type().String()
   114  	u := uuid.NewV5(uuid.NamespaceURL, url)
   115  	return MessageTypeID(u)
   116  }
   117  
   118  // MessageType returns a Message's MessageTypeID if registered or ErrorType if
   119  // the message has not been registered with RegisterMessage().
   120  func MessageType(msg Message) MessageTypeID {
   121  	msgType := computeMessageType(msg)
   122  	_, ok := registry.get(msgType)
   123  	if !ok {
   124  		return ErrorType
   125  	}
   126  	return msgType
   127  }
   128  
   129  // Marshal outputs the type and the byte representation of a structure.  It
   130  // first marshals the type as a uuid, i.e. a 16 byte length slice, then the
   131  // struct encoded by protobuf.  That slice of bytes can be then decoded with
   132  // Unmarshal. msg must be a pointer to the message.
   133  func Marshal(msg Message) ([]byte, error) {
   134  	var msgType MessageTypeID
   135  	if msgType = MessageType(msg); msgType == ErrorType {
   136  		return nil, xerrors.Errorf("type of message %s not registered to the network library", reflect.TypeOf(msg))
   137  	}
   138  	b := new(bytes.Buffer)
   139  	if err := binary.Write(b, globalOrder, msgType); err != nil {
   140  		return nil, xerrors.Errorf("buffer write: %v", err)
   141  	}
   142  	var buf []byte
   143  	var err error
   144  	if buf, err = protobuf.Encode(msg); err != nil {
   145  		log.Errorf("Error for protobuf encoding: %s %+v", msg, err)
   146  		if log.DebugVisible() > 0 {
   147  			log.Error(log.Stack())
   148  		}
   149  		return nil, xerrors.Errorf("encoding: %v", err)
   150  	}
   151  	_, err = b.Write(buf)
   152  	if err != nil {
   153  		return nil, xerrors.Errorf("buffer write: %v", err)
   154  	}
   155  	return b.Bytes(), nil
   156  }
   157  
   158  // Unmarshal returns the type and the message out of a buffer. One can cast the
   159  // resulting Message to a *pointer* of the underlying type, i.e. it returns a
   160  // pointer.  The type must be registered to the network library in order to be
   161  // decodable and the buffer must have been generated by Marshal otherwise it
   162  // returns an error.
   163  func Unmarshal(buf []byte, suite Suite) (MessageTypeID, Message, error) {
   164  	b := bytes.NewBuffer(buf)
   165  	var tID MessageTypeID
   166  	if err := binary.Read(b, globalOrder, &tID); err != nil {
   167  		return ErrorType, nil, xerrors.Errorf("buffer read: %v", err)
   168  	}
   169  	typ, ok := registry.get(tID)
   170  	if !ok {
   171  		return ErrorType, nil, xerrors.Errorf("type %s not registered", tID.String())
   172  	}
   173  	ptrVal := reflect.New(typ)
   174  	ptr := ptrVal.Interface()
   175  	constructors := DefaultConstructors(suite)
   176  	if err := protobuf.DecodeWithConstructors(b.Bytes(), ptr, constructors); err != nil {
   177  		return ErrorType, nil, xerrors.Errorf("decoding: %v", err)
   178  	}
   179  	return tID, ptrVal.Interface(), nil
   180  }
   181  
   182  // DumpTypes is used for debugging - it prints out all known types
   183  func DumpTypes() {
   184  	for t, m := range registry.types {
   185  		log.Print("Type", t, "has message", m)
   186  	}
   187  }
   188  
   189  // DefaultConstructors gives a default constructor for protobuf out of the global suite
   190  func DefaultConstructors(suite Suite) protobuf.Constructors {
   191  	constructors := make(protobuf.Constructors)
   192  	if suite != nil {
   193  		var point kyber.Point
   194  		var secret kyber.Scalar
   195  		constructors[reflect.TypeOf(&point).Elem()] = func() interface{} { return suite.Point() }
   196  		constructors[reflect.TypeOf(&secret).Elem()] = func() interface{} { return suite.Scalar() }
   197  	}
   198  	return constructors
   199  }
   200  
   201  var registry = newTypeRegistry()
   202  
   203  type typeRegistry struct {
   204  	types map[MessageTypeID]reflect.Type
   205  	lock  sync.Mutex
   206  }
   207  
   208  func newTypeRegistry() *typeRegistry {
   209  	return &typeRegistry{
   210  		types: make(map[MessageTypeID]reflect.Type),
   211  		lock:  sync.Mutex{},
   212  	}
   213  }
   214  
   215  // get returns the reflect.Type corresponding to the registered PacketTypeID
   216  // an a boolean indicating if the type is actually registered or not.
   217  func (tr *typeRegistry) get(mid MessageTypeID) (reflect.Type, bool) {
   218  	tr.lock.Lock()
   219  	defer tr.lock.Unlock()
   220  	t, ok := tr.types[mid]
   221  	return t, ok
   222  }
   223  
   224  // put stores the given type in the typeRegistry.
   225  func (tr *typeRegistry) put(mid MessageTypeID, typ reflect.Type) {
   226  	tr.lock.Lock()
   227  	defer tr.lock.Unlock()
   228  	tr.types[mid] = typ
   229  }