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 }