github.com/hyperledger-labs/bdls@v2.1.1+incompatible/core/chaincode/lifecycle/serializer.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package lifecycle
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"reflect"
    13  
    14  	lb "github.com/hyperledger/fabric-protos-go/peer/lifecycle"
    15  	"github.com/hyperledger/fabric/common/util"
    16  
    17  	"github.com/golang/protobuf/proto"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  const (
    22  	MetadataInfix = "metadata"
    23  	FieldsInfix   = "fields"
    24  )
    25  
    26  type ReadWritableState interface {
    27  	ReadableState
    28  	PutState(key string, value []byte) error
    29  	DelState(key string) error
    30  }
    31  
    32  type ReadableState interface {
    33  	GetState(key string) (value []byte, err error)
    34  }
    35  
    36  type OpaqueState interface {
    37  	GetStateHash(key string) (value []byte, err error)
    38  	CollectionName() string
    39  }
    40  
    41  type RangeableState interface {
    42  	GetStateRange(prefix string) (map[string][]byte, error)
    43  }
    44  
    45  type Marshaler func(proto.Message) ([]byte, error)
    46  
    47  func (m Marshaler) Marshal(msg proto.Message) ([]byte, error) {
    48  	if m != nil {
    49  		return m(msg)
    50  	}
    51  	return proto.Marshal(msg)
    52  }
    53  
    54  var ProtoMessageType = reflect.TypeOf((*proto.Message)(nil)).Elem()
    55  
    56  // Serializer is used to write structures into the db and to read them back out.
    57  // Although it's unfortunate to write a custom serializer, rather than to use something
    58  // pre-written, like protobuf or JSON, in order to produce precise readwrite sets which
    59  // only perform state updates for keys which are actually updated (and not simply set
    60  // to the same value again) custom serialization is required.
    61  type Serializer struct {
    62  	// Marshaler, when nil uses the standard protobuf impl.
    63  	// Can be overridden for test.
    64  	Marshaler Marshaler
    65  }
    66  
    67  // SerializableChecks performs some boilerplate checks to make sure the given structure
    68  // is serializable.  It returns the reflected version of the value and a slice of all
    69  // field names, or an error.
    70  func (s *Serializer) SerializableChecks(structure interface{}) (reflect.Value, []string, error) {
    71  	value := reflect.ValueOf(structure)
    72  	if value.Kind() != reflect.Ptr {
    73  		return reflect.Value{}, nil, errors.Errorf("must be pointer to struct, but got non-pointer %v", value.Kind())
    74  	}
    75  
    76  	value = value.Elem()
    77  	if value.Kind() != reflect.Struct {
    78  		return reflect.Value{}, nil, errors.Errorf("must be pointers to struct, but got pointer to %v", value.Kind())
    79  	}
    80  
    81  	allFields := make([]string, value.NumField())
    82  	for i := 0; i < value.NumField(); i++ {
    83  		fieldName := value.Type().Field(i).Name
    84  		fieldValue := value.Field(i)
    85  		allFields[i] = fieldName
    86  		switch fieldValue.Kind() {
    87  		case reflect.String:
    88  		case reflect.Int64:
    89  		case reflect.Slice:
    90  			if fieldValue.Type().Elem().Kind() != reflect.Uint8 {
    91  				return reflect.Value{}, nil, errors.Errorf("unsupported slice type %v for field %s", fieldValue.Type().Elem().Kind(), fieldName)
    92  			}
    93  		case reflect.Ptr:
    94  			if !fieldValue.Type().Implements(ProtoMessageType) {
    95  				return reflect.Value{}, nil, errors.Errorf("unsupported pointer type %v for field %s (must be proto)", fieldValue.Type().Elem(), fieldName)
    96  			}
    97  		default:
    98  			return reflect.Value{}, nil, errors.Errorf("unsupported structure field kind %v for serialization for field %s", fieldValue.Kind(), fieldName)
    99  		}
   100  	}
   101  	return value, allFields, nil
   102  }
   103  
   104  // Serialize takes a pointer to a struct, and writes each of its fields as keys
   105  // into a namespace.  It also writes the struct metadata (if it needs updating)
   106  // and,  deletes any keys in the namespace which are not found in the struct.
   107  // Note: If a key already exists for the field, and the value is unchanged, then
   108  // the key is _not_ written to.
   109  func (s *Serializer) Serialize(namespace, name string, structure interface{}, state ReadWritableState) error {
   110  	value, allFields, err := s.SerializableChecks(structure)
   111  	if err != nil {
   112  		return errors.WithMessagef(err, "structure for namespace %s/%s is not serializable", namespace, name)
   113  	}
   114  
   115  	metadata, ok, err := s.DeserializeMetadata(namespace, name, state)
   116  	if err != nil {
   117  		return errors.WithMessagef(err, "could not deserialize metadata for namespace %s/%s", namespace, name)
   118  	}
   119  	if !ok {
   120  		metadata = &lb.StateMetadata{}
   121  	}
   122  
   123  	existingKeys := map[string][]byte{}
   124  	for _, existingField := range metadata.Fields {
   125  		fqKey := FieldKey(namespace, name, existingField)
   126  		value, err := state.GetState(fqKey)
   127  		if err != nil {
   128  			return errors.WithMessagef(err, "could not get value for key %s", fqKey)
   129  		}
   130  		existingKeys[fqKey] = value
   131  	}
   132  
   133  	for i := 0; i < value.NumField(); i++ {
   134  		fieldName := value.Type().Field(i).Name
   135  		fieldValue := value.Field(i)
   136  
   137  		keyName := FieldKey(namespace, name, fieldName)
   138  
   139  		stateData := &lb.StateData{}
   140  		switch fieldValue.Kind() {
   141  		case reflect.String:
   142  			stateData.Type = &lb.StateData_String_{String_: fieldValue.String()}
   143  		case reflect.Int64:
   144  			stateData.Type = &lb.StateData_Int64{Int64: fieldValue.Int()}
   145  		case reflect.Slice:
   146  			stateData.Type = &lb.StateData_Bytes{Bytes: fieldValue.Bytes()}
   147  		case reflect.Ptr:
   148  			var bin []byte
   149  			if !fieldValue.IsNil() {
   150  				bin, err = s.Marshaler.Marshal(fieldValue.Interface().(proto.Message))
   151  				if err != nil {
   152  					return errors.Wrapf(err, "could not marshal field %s", fieldName)
   153  				}
   154  			}
   155  			stateData.Type = &lb.StateData_Bytes{Bytes: bin}
   156  			// Note, other field kinds and bad types have already been checked by SerializableChecks
   157  		}
   158  
   159  		marshaledFieldValue, err := s.Marshaler.Marshal(stateData)
   160  		if err != nil {
   161  			return errors.WithMessagef(err, "could not marshal value for key %s", keyName)
   162  		}
   163  
   164  		if existingValue, ok := existingKeys[keyName]; !ok || !bytes.Equal(existingValue, marshaledFieldValue) {
   165  			err := state.PutState(keyName, marshaledFieldValue)
   166  			if err != nil {
   167  				return errors.WithMessage(err, "could not write key into state")
   168  			}
   169  		}
   170  		delete(existingKeys, keyName)
   171  	}
   172  
   173  	typeName := value.Type().Name()
   174  	if len(existingKeys) > 0 || typeName != metadata.Datatype || len(metadata.Fields) != value.NumField() {
   175  		metadata.Datatype = typeName
   176  		metadata.Fields = allFields
   177  		newMetadataBin, err := s.Marshaler.Marshal(metadata)
   178  		if err != nil {
   179  			return errors.WithMessagef(err, "could not marshal metadata for namespace %s/%s", namespace, name)
   180  		}
   181  		err = state.PutState(MetadataKey(namespace, name), newMetadataBin)
   182  		if err != nil {
   183  			return errors.WithMessagef(err, "could not store metadata for namespace %s/%s", namespace, name)
   184  		}
   185  	}
   186  
   187  	for key := range existingKeys {
   188  		err := state.DelState(key)
   189  		if err != nil {
   190  			return errors.WithMessagef(err, "could not delete unneeded key %s", key)
   191  		}
   192  	}
   193  
   194  	return nil
   195  }
   196  
   197  func (s *Serializer) IsMetadataSerialized(namespace, name string, structure interface{}, state OpaqueState) (bool, error) {
   198  	value, allFields, err := s.SerializableChecks(structure)
   199  	if err != nil {
   200  		return false, errors.WithMessagef(err, "structure for namespace %s/%s is not serializable", namespace, name)
   201  	}
   202  
   203  	mdKey := MetadataKey(namespace, name)
   204  	metadata := &lb.StateMetadata{
   205  		Datatype: value.Type().Name(),
   206  		Fields:   allFields,
   207  	}
   208  
   209  	metadataBin, err := s.Marshaler.Marshal(metadata)
   210  	if err != nil {
   211  		return false, errors.WithMessagef(err, "could not marshal metadata for namespace %s/%s", namespace, name)
   212  	}
   213  
   214  	existingMDHash, err := state.GetStateHash(mdKey)
   215  	if err != nil {
   216  		return false, errors.WithMessagef(err, "could not get state hash for metadata key %s", mdKey)
   217  	}
   218  
   219  	return bytes.Equal(util.ComputeSHA256(metadataBin), existingMDHash), nil
   220  }
   221  
   222  // IsSerialized essentially checks if the hashes of a serialized version of a structure matches the hashes
   223  // of the pre-image of some struct serialized into the database.
   224  func (s *Serializer) IsSerialized(namespace, name string, structure interface{}, state OpaqueState) (bool, error) {
   225  	value, allFields, err := s.SerializableChecks(structure)
   226  	if err != nil {
   227  		return false, errors.WithMessagef(err, "structure for namespace %s/%s is not serializable", namespace, name)
   228  	}
   229  
   230  	fqKeys := make([]string, 0, len(allFields)+1)
   231  	fqKeys = append(fqKeys, MetadataKey(namespace, name))
   232  	for _, field := range allFields {
   233  		fqKeys = append(fqKeys, FieldKey(namespace, name, field))
   234  	}
   235  
   236  	existingKeys := map[string][]byte{}
   237  	for _, fqKey := range fqKeys {
   238  		value, err := state.GetStateHash(fqKey)
   239  		if err != nil {
   240  			return false, errors.WithMessagef(err, "could not get value for key %s", fqKey)
   241  		}
   242  		existingKeys[fqKey] = value
   243  	}
   244  
   245  	metadata := &lb.StateMetadata{
   246  		Datatype: value.Type().Name(),
   247  		Fields:   allFields,
   248  	}
   249  	metadataBin, err := s.Marshaler.Marshal(metadata)
   250  	if err != nil {
   251  		return false, errors.WithMessagef(err, "could not marshal metadata for namespace %s/%s", namespace, name)
   252  	}
   253  
   254  	metadataKeyName := MetadataKey(namespace, name)
   255  	if !bytes.Equal(util.ComputeSHA256(metadataBin), existingKeys[metadataKeyName]) {
   256  		return false, nil
   257  	}
   258  
   259  	for i := 0; i < value.NumField(); i++ {
   260  		fieldName := value.Type().Field(i).Name
   261  		fieldValue := value.Field(i)
   262  
   263  		keyName := FieldKey(namespace, name, fieldName)
   264  
   265  		stateData := &lb.StateData{}
   266  		switch fieldValue.Kind() {
   267  		case reflect.String:
   268  			stateData.Type = &lb.StateData_String_{String_: fieldValue.String()}
   269  		case reflect.Int64:
   270  			stateData.Type = &lb.StateData_Int64{Int64: fieldValue.Int()}
   271  		case reflect.Slice:
   272  			stateData.Type = &lb.StateData_Bytes{Bytes: fieldValue.Bytes()}
   273  		case reflect.Ptr:
   274  			var bin []byte
   275  			if !fieldValue.IsNil() {
   276  				bin, err = s.Marshaler.Marshal(fieldValue.Interface().(proto.Message))
   277  				if err != nil {
   278  					return false, errors.Wrapf(err, "could not marshal field %s", fieldName)
   279  				}
   280  			}
   281  			stateData.Type = &lb.StateData_Bytes{Bytes: bin}
   282  			// Note, other field kinds and bad types have already been checked by SerializableChecks
   283  		}
   284  
   285  		marshaledFieldValue, err := s.Marshaler.Marshal(stateData)
   286  		if err != nil {
   287  			return false, errors.WithMessagef(err, "could not marshal value for key %s", keyName)
   288  		}
   289  
   290  		if existingValue, ok := existingKeys[keyName]; !ok || !bytes.Equal(existingValue, util.ComputeSHA256(marshaledFieldValue)) {
   291  			return false, nil
   292  		}
   293  	}
   294  
   295  	return true, nil
   296  }
   297  
   298  // Deserialize accepts a struct (of a type previously serialized) and populates it with the values from the db.
   299  // Note: The struct names for the serialization and deserialization must match exactly.  Unencoded fields are not
   300  // populated, and the extraneous keys are ignored.  The metadata provided should have been returned by a DeserializeMetadata
   301  // call for the same namespace and name.
   302  func (s *Serializer) Deserialize(namespace, name string, metadata *lb.StateMetadata, structure interface{}, state ReadableState) error {
   303  	value, _, err := s.SerializableChecks(structure)
   304  	if err != nil {
   305  		return errors.WithMessagef(err, "could not deserialize namespace %s/%s to unserializable type %T", namespace, name, structure)
   306  	}
   307  
   308  	typeName := value.Type().Name()
   309  	if typeName != metadata.Datatype {
   310  		return errors.Errorf("type name mismatch '%s' != '%s'", typeName, metadata.Datatype)
   311  	}
   312  
   313  	for i := 0; i < value.NumField(); i++ {
   314  		fieldName := value.Type().Field(i).Name
   315  		fieldValue := value.Field(i)
   316  		switch fieldValue.Kind() {
   317  		case reflect.String:
   318  			oneOf, err := s.DeserializeFieldAsString(namespace, name, fieldName, state)
   319  			if err != nil {
   320  				return err
   321  			}
   322  			fieldValue.SetString(oneOf)
   323  		case reflect.Int64:
   324  			oneOf, err := s.DeserializeFieldAsInt64(namespace, name, fieldName, state)
   325  			if err != nil {
   326  				return err
   327  			}
   328  			fieldValue.SetInt(oneOf)
   329  		case reflect.Slice:
   330  			oneOf, err := s.DeserializeFieldAsBytes(namespace, name, fieldName, state)
   331  			if err != nil {
   332  				return err
   333  			}
   334  			if oneOf != nil {
   335  				fieldValue.SetBytes(oneOf)
   336  			}
   337  		case reflect.Ptr:
   338  			// Note, even non-existant keys will decode to an empty proto
   339  			msg := reflect.New(fieldValue.Type().Elem())
   340  			err := s.DeserializeFieldAsProto(namespace, name, fieldName, state, msg.Interface().(proto.Message))
   341  			if err != nil {
   342  				return err
   343  			}
   344  			fieldValue.Set(msg)
   345  			// Note, other field kinds and bad types have already been checked by SerializableChecks
   346  		}
   347  	}
   348  
   349  	return nil
   350  }
   351  
   352  func MetadataKey(namespace, name string) string {
   353  	return fmt.Sprintf("%s/%s/%s", namespace, MetadataInfix, name)
   354  }
   355  
   356  func FieldKey(namespace, name, field string) string {
   357  	return fmt.Sprintf("%s/%s/%s/%s", namespace, FieldsInfix, name, field)
   358  }
   359  
   360  func (s *Serializer) DeserializeMetadata(namespace, name string, state ReadableState) (*lb.StateMetadata, bool, error) {
   361  	metadataBin, err := state.GetState(MetadataKey(namespace, name))
   362  	if err != nil {
   363  		return nil, false, errors.WithMessagef(err, "could not query metadata for namespace %s/%s", namespace, name)
   364  	}
   365  	if metadataBin == nil {
   366  		return nil, false, nil
   367  	}
   368  
   369  	metadata := &lb.StateMetadata{}
   370  	err = proto.Unmarshal(metadataBin, metadata)
   371  	if err != nil {
   372  		return nil, false, errors.Wrapf(err, "could not unmarshal metadata for namespace %s/%s", namespace, name)
   373  	}
   374  
   375  	return metadata, true, nil
   376  }
   377  
   378  func (s *Serializer) DeserializeField(namespace, name, field string, state ReadableState) (*lb.StateData, error) {
   379  	keyName := FieldKey(namespace, name, field)
   380  	value, err := state.GetState(keyName)
   381  	if err != nil {
   382  		return nil, errors.WithMessagef(err, "could not get state for key %s", keyName)
   383  	}
   384  
   385  	stateData := &lb.StateData{}
   386  	err = proto.Unmarshal(value, stateData)
   387  	if err != nil {
   388  		return nil, errors.Wrapf(err, "could not unmarshal state for key %s", keyName)
   389  	}
   390  
   391  	return stateData, nil
   392  }
   393  
   394  func (s *Serializer) DeserializeFieldAsString(namespace, name, field string, state ReadableState) (string, error) {
   395  	value, err := s.DeserializeField(namespace, name, field, state)
   396  	if err != nil {
   397  		return "", err
   398  	}
   399  	if value.Type == nil {
   400  		return "", nil
   401  	}
   402  	oneOf, ok := value.Type.(*lb.StateData_String_)
   403  	if !ok {
   404  		return "", errors.Errorf("expected key %s/fields/%s/%s to encode a value of type String, but was %T", namespace, name, field, value.Type)
   405  	}
   406  	return oneOf.String_, nil
   407  }
   408  
   409  func (s *Serializer) DeserializeFieldAsBytes(namespace, name, field string, state ReadableState) ([]byte, error) {
   410  	value, err := s.DeserializeField(namespace, name, field, state)
   411  	if err != nil {
   412  		return nil, err
   413  	}
   414  	if value.Type == nil {
   415  		return nil, nil
   416  	}
   417  	oneOf, ok := value.Type.(*lb.StateData_Bytes)
   418  	if !ok {
   419  		return nil, errors.Errorf("expected key %s to encode a value of type []byte, but was %T", FieldKey(namespace, name, field), value.Type)
   420  	}
   421  	return oneOf.Bytes, nil
   422  }
   423  
   424  func (s *Serializer) DeserializeFieldAsProto(namespace, name, field string, state ReadableState, msg proto.Message) error {
   425  	bin, err := s.DeserializeFieldAsBytes(namespace, name, field, state)
   426  	if err != nil {
   427  		return err
   428  	}
   429  	err = proto.Unmarshal(bin, msg)
   430  	if err != nil {
   431  		return errors.Wrapf(err, "could not unmarshal key %s to %T", FieldKey(namespace, name, field), msg)
   432  	}
   433  	return nil
   434  }
   435  
   436  func (s *Serializer) DeserializeFieldAsInt64(namespace, name, field string, state ReadableState) (int64, error) {
   437  	value, err := s.DeserializeField(namespace, name, field, state)
   438  	if err != nil {
   439  		return 0, err
   440  	}
   441  	if value.Type == nil {
   442  		return 0, nil
   443  	}
   444  	oneOf, ok := value.Type.(*lb.StateData_Int64)
   445  	if !ok {
   446  		return 0, errors.Errorf("expected key %s to encode a value of type Int64, but was %T", FieldKey(namespace, name, field), value.Type)
   447  	}
   448  	return oneOf.Int64, nil
   449  }
   450  
   451  func (s *Serializer) DeserializeAllMetadata(namespace string, state RangeableState) (map[string]*lb.StateMetadata, error) {
   452  	prefix := fmt.Sprintf("%s/%s/", namespace, MetadataInfix)
   453  	kvs, err := state.GetStateRange(prefix)
   454  	if err != nil {
   455  		return nil, errors.WithMessagef(err, "could not get state range for namespace %s", namespace)
   456  	}
   457  	result := map[string]*lb.StateMetadata{}
   458  	for key, value := range kvs {
   459  		name := key[len(prefix):]
   460  		metadata := &lb.StateMetadata{}
   461  		err = proto.Unmarshal(value, metadata)
   462  		if err != nil {
   463  			return nil, errors.Wrapf(err, "error unmarshaling metadata for key %s", key)
   464  		}
   465  		result[name] = metadata
   466  	}
   467  	return result, nil
   468  }