Skip to content

Commit 47dd043

Browse files
author
Jason Yellick
committed
FAB-13502 Add deserializers for individual fields
Sometimes, unmarshaling an entire serialized struct is undesirable, for instance, to only create a read dependency on the chaincode hash, but not on its endorsement policy. This CR adds deserialization methods to retrieve serialized fields individually. Change-Id: I2937c603ce0073bdf89cc0e22d570cca43a84869 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent e6d5c72 commit 47dd043

File tree

2 files changed

+344
-30
lines changed

2 files changed

+344
-30
lines changed

core/chaincode/lifecycle/serializer.go

Lines changed: 111 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -183,51 +183,133 @@ func (s *Serializer) Deserialize(namespace, name string, structure interface{},
183183

184184
for i := 0; i < value.NumField(); i++ {
185185
fieldName := value.Type().Field(i).Name
186-
keyName := fmt.Sprintf("%s/fields/%s/%s", namespace, name, fieldName)
187-
stateDataBin, err := state.GetState(keyName)
188-
if err != nil {
189-
return errors.WithMessage(err, fmt.Sprintf("could not get state for key %s", keyName))
190-
}
191-
stateData := &lb.StateData{}
192-
err = proto.Unmarshal(stateDataBin, stateData)
193-
if err != nil {
194-
return errors.Wrapf(err, "could not unmarshal state for key %s", keyName)
195-
}
196-
197186
fieldValue := value.Field(i)
198187
switch fieldValue.Kind() {
199188
case reflect.String:
200-
oneOf, ok := stateData.Type.(*lb.StateData_String_)
201-
if !ok {
202-
return errors.Errorf("expected key %s to encode a value of type String, but was %T", keyName, stateData.Type)
189+
oneOf, err := s.DeserializeFieldAsString(namespace, name, fieldName, state)
190+
if err != nil {
191+
return err
203192
}
204-
fieldValue.SetString(oneOf.String_)
193+
fieldValue.SetString(oneOf)
205194
case reflect.Int64:
206-
oneOf, ok := stateData.Type.(*lb.StateData_Int64)
207-
if !ok {
208-
return errors.Errorf("expected key %s to encode a value of type Int64, but was %T", keyName, stateData.Type)
195+
oneOf, err := s.DeserializeFieldAsInt64(namespace, name, fieldName, state)
196+
if err != nil {
197+
return err
209198
}
210-
fieldValue.SetInt(oneOf.Int64)
199+
fieldValue.SetInt(oneOf)
211200
case reflect.Uint64:
212-
oneOf, ok := stateData.Type.(*lb.StateData_Uint64)
213-
if !ok {
214-
return errors.Errorf("expected key %s to encode a value of type Uint64, but was %T", keyName, stateData.Type)
201+
oneOf, err := s.DeserializeFieldAsUint64(namespace, name, fieldName, state)
202+
if err != nil {
203+
return err
215204
}
216-
fieldValue.SetUint(oneOf.Uint64)
205+
fieldValue.SetUint(oneOf)
217206
case reflect.Slice:
218207
if fieldValue.Type().Elem().Kind() != reflect.Uint8 {
219208
return errors.Errorf("unsupported slice type %v for field %s", fieldValue.Type().Elem().Kind(), fieldName)
220209
}
221-
222-
oneOf, ok := stateData.Type.(*lb.StateData_Bytes)
223-
if !ok {
224-
return errors.Errorf("expected key %s to encode a value of type []byte, but was %T", keyName, stateData.Type)
210+
oneOf, err := s.DeserializeFieldAsBytes(namespace, name, fieldName, state)
211+
if err != nil {
212+
return err
225213
}
226-
fieldValue.SetBytes(oneOf.Bytes)
214+
fieldValue.SetBytes(oneOf)
227215
default:
228-
return errors.Errorf("unsupported structure field kind %v for deserialization for key %s", fieldValue.Kind(), keyName)
216+
return errors.Errorf("unsupported structure field kind %v for deserialization for field %s", fieldValue.Kind(), fieldName)
229217
}
230218
}
231219

232220
return nil
233221
}
222+
223+
func (s *Serializer) DeserializeMetadata(namespace, name string, state ReadableState) (*lb.StateMetadata, error) {
224+
metadataBin, err := state.GetState(fmt.Sprintf("%s/metadata/%s", namespace, name))
225+
if err != nil {
226+
return nil, errors.WithMessage(err, fmt.Sprintf("could not query metadata for namespace %s/%s", namespace, name))
227+
}
228+
if metadataBin == nil {
229+
return nil, errors.Errorf("no existing serialized message found")
230+
}
231+
232+
metadata := &lb.StateMetadata{}
233+
err = proto.Unmarshal(metadataBin, metadata)
234+
if err != nil {
235+
return nil, errors.Wrapf(err, "could not unmarshal metadata for namespace %s/%s", namespace, name)
236+
}
237+
238+
return metadata, nil
239+
}
240+
241+
func (s *Serializer) DeserializeField(namespace, name, field string, state ReadableState) (*lb.StateData, error) {
242+
keyName := fmt.Sprintf("%s/fields/%s/%s", namespace, name, field)
243+
value, err := state.GetState(keyName)
244+
if err != nil {
245+
return nil, errors.WithMessage(err, fmt.Sprintf("could not get state for key %s", keyName))
246+
}
247+
248+
stateData := &lb.StateData{}
249+
err = proto.Unmarshal(value, stateData)
250+
if err != nil {
251+
return nil, errors.Wrapf(err, "could not unmarshal state for key %s", keyName)
252+
}
253+
254+
return stateData, nil
255+
}
256+
257+
func (s *Serializer) DeserializeFieldAsString(namespace, name, field string, state ReadableState) (string, error) {
258+
value, err := s.DeserializeField(namespace, name, field, state)
259+
if err != nil {
260+
return "", err
261+
}
262+
if value.Type == nil {
263+
return "", nil
264+
}
265+
oneOf, ok := value.Type.(*lb.StateData_String_)
266+
if !ok {
267+
return "", errors.Errorf("expected key %s/fields/%s/%s to encode a value of type String, but was %T", namespace, name, field, value.Type)
268+
}
269+
return oneOf.String_, nil
270+
}
271+
272+
func (s *Serializer) DeserializeFieldAsBytes(namespace, name, field string, state ReadableState) ([]byte, error) {
273+
value, err := s.DeserializeField(namespace, name, field, state)
274+
if err != nil {
275+
return nil, err
276+
}
277+
if value.Type == nil {
278+
return nil, nil
279+
}
280+
oneOf, ok := value.Type.(*lb.StateData_Bytes)
281+
if !ok {
282+
return nil, errors.Errorf("expected key %s/fields/%s/%s to encode a value of type []byte, but was %T", namespace, name, field, value.Type)
283+
}
284+
return oneOf.Bytes, nil
285+
}
286+
287+
func (s *Serializer) DeserializeFieldAsInt64(namespace, name, field string, state ReadableState) (int64, error) {
288+
value, err := s.DeserializeField(namespace, name, field, state)
289+
if err != nil {
290+
return 0, err
291+
}
292+
if value.Type == nil {
293+
return 0, nil
294+
}
295+
oneOf, ok := value.Type.(*lb.StateData_Int64)
296+
if !ok {
297+
return 0, errors.Errorf("expected key %s/fields/%s/%s to encode a value of type Int64, but was %T", namespace, name, field, value.Type)
298+
}
299+
return oneOf.Int64, nil
300+
}
301+
302+
func (s *Serializer) DeserializeFieldAsUint64(namespace, name, field string, state ReadableState) (uint64, error) {
303+
value, err := s.DeserializeField(namespace, name, field, state)
304+
if err != nil {
305+
return 0, err
306+
}
307+
if value.Type == nil {
308+
return 0, nil
309+
}
310+
oneOf, ok := value.Type.(*lb.StateData_Uint64)
311+
if !ok {
312+
return 0, errors.Errorf("expected key %s/fields/%s/%s to encode a value of type Uint64, but was %T", namespace, name, field, value.Type)
313+
}
314+
return oneOf.Uint64, nil
315+
}

0 commit comments

Comments
 (0)