github.com/s7techlab/cckit@v0.10.5/state/state.go (about) 1 package state 2 3 import ( 4 "fmt" 5 6 "github.com/hyperledger/fabric-chaincode-go/shim" 7 "github.com/hyperledger/fabric-protos-go/ledger/queryresult" 8 "github.com/pkg/errors" 9 "go.uber.org/zap" 10 11 pb "github.com/hyperledger/fabric-protos-go/peer" 12 13 "github.com/s7techlab/cckit/convert" 14 ) 15 16 // HistoryEntry struct containing history information of a single entry 17 type HistoryEntry struct { 18 TxId string `json:"txId"` 19 Timestamp int64 `json:"timestamp"` 20 IsDeleted bool `json:"isDeleted"` 21 Value interface{} `json:"value"` 22 } 23 24 // HistoryEntryList list of history entries 25 type HistoryEntryList []HistoryEntry 26 27 type Impl struct { 28 stub shim.ChaincodeStubInterface 29 logger *zap.Logger 30 31 // wrappers for state access methods 32 PutState func(string, []byte) error 33 GetState func(string) ([]byte, error) 34 DelState func(string) error 35 GetStateByPartialCompositeKey func(objectType string, keys []string) (shim.StateQueryIteratorInterface, error) 36 GetStateByPartialCompositeKeyWithPagination func(objectType string, keys []string, pageSize int32, bookmark string) (shim.StateQueryIteratorInterface, *pb.QueryResponseMetadata, error) 37 38 StateKeyTransformer KeyTransformer 39 StateKeyReverseTransformer KeyTransformer 40 StateGetTransformer FromBytesTransformer 41 StatePutTransformer ToBytesTransformer 42 } 43 44 // NewState creates wrapper on shim.ChaincodeStubInterface for working with state 45 func NewState(stub shim.ChaincodeStubInterface, logger *zap.Logger) *Impl { 46 i := &Impl{ 47 stub: stub, 48 logger: logger, 49 StateKeyTransformer: KeyAsIs, 50 StateKeyReverseTransformer: KeyAsIs, 51 StateGetTransformer: ConvertFromBytes, 52 StatePutTransformer: ConvertToBytes, 53 } 54 55 // Get data by key from state, direct from stub 56 i.GetState = func(key string) ([]byte, error) { 57 return stub.GetState(key) 58 } 59 60 // PutState puts the specified `key` and `value` into the transaction's 61 // writeset as a data-write proposal. 62 i.PutState = func(key string, bb []byte) error { 63 return stub.PutState(key, bb) 64 } 65 66 // DelState records the specified `key` to be deleted in the writeset of 67 // the transaction proposal. 68 i.DelState = func(key string) error { 69 return stub.DelState(key) 70 } 71 72 // GetStateByPartialCompositeKey queries the state in the ledger based on 73 // a given partial composite key 74 i.GetStateByPartialCompositeKey = func(objectType string, keys []string) (shim.StateQueryIteratorInterface, error) { 75 return stub.GetStateByPartialCompositeKey(objectType, keys) 76 } 77 78 i.GetStateByPartialCompositeKeyWithPagination = func( 79 objectType string, keys []string, pageSize int32, bookmark string) ( 80 shim.StateQueryIteratorInterface, *pb.QueryResponseMetadata, error) { 81 return stub.GetStateByPartialCompositeKeyWithPagination(objectType, keys, pageSize, bookmark) 82 } 83 84 return i 85 } 86 87 func (s *Impl) Clone() State { 88 return &Impl{ 89 stub: s.stub, 90 logger: s.logger, 91 PutState: s.PutState, 92 GetState: s.GetState, 93 DelState: s.DelState, 94 GetStateByPartialCompositeKey: s.GetStateByPartialCompositeKey, 95 GetStateByPartialCompositeKeyWithPagination: s.GetStateByPartialCompositeKeyWithPagination, 96 StateKeyTransformer: s.StateKeyTransformer, 97 StateKeyReverseTransformer: s.StateKeyReverseTransformer, 98 StateGetTransformer: s.StateGetTransformer, 99 StatePutTransformer: s.StatePutTransformer, 100 } 101 } 102 103 func (s *Impl) Logger() *zap.Logger { 104 return s.logger 105 } 106 107 func (s *Impl) Key(key interface{}) (*TransformedKey, error) { 108 var ( 109 trKey = &TransformedKey{} 110 err error 111 ) 112 113 if trKey.Origin, err = NormalizeKey(s.stub, key); err != nil { 114 return nil, errors.Wrap(err, `key normalizing`) 115 } 116 117 s.logger.Debug(`state KEY`, zap.String(`key`, trKey.Origin.String())) 118 119 if trKey.Parts, err = s.StateKeyTransformer(trKey.Origin); err != nil { 120 return nil, err 121 } 122 123 if trKey.String, err = KeyToString(s.stub, trKey.Parts); err != nil { 124 return nil, err 125 } 126 127 return trKey, nil 128 } 129 130 // Get data by key from state, trying to convert to target interface 131 func (s *Impl) Get(entry interface{}, config ...interface{}) (interface{}, error) { 132 key, err := s.Key(entry) 133 if err != nil { 134 return nil, err 135 } 136 137 //bytes from state 138 s.logger.Debug(`state GET`, zap.String(`key`, key.String)) 139 bb, err := s.GetState(key.String) 140 if err != nil { 141 return nil, err 142 } 143 if len(bb) == 0 { 144 // config[1] default value 145 if len(config) >= 2 { 146 return config[1], nil 147 } 148 return nil, errors.Errorf(`%s: %s`, ErrKeyNotFound, key.Origin) 149 } 150 151 // config[0] - target type 152 return s.StateGetTransformer(bb, config...) 153 } 154 155 func (s *Impl) GetInt(key interface{}, defaultValue int) (int, error) { 156 val, err := s.Get(key, convert.TypeInt, defaultValue) 157 if err != nil { 158 return 0, err 159 } 160 return val.(int), nil 161 } 162 163 // GetHistory by key from state, trying to convert to target interface 164 func (s *Impl) GetHistory(entry interface{}, target interface{}) (HistoryEntryList, error) { 165 key, err := s.Key(entry) 166 if err != nil { 167 return nil, err 168 } 169 170 iter, err := s.stub.GetHistoryForKey(key.String) 171 if err != nil { 172 return nil, err 173 } 174 175 defer func() { _ = iter.Close() }() 176 177 results := HistoryEntryList{} 178 179 for iter.HasNext() { 180 state, err := iter.Next() 181 if err != nil { 182 return nil, err 183 } 184 value, err := s.StateGetTransformer(state.Value, target) 185 if err != nil { 186 return nil, err 187 } 188 189 entry := HistoryEntry{ 190 TxId: state.GetTxId(), 191 Timestamp: state.GetTimestamp().GetSeconds(), 192 IsDeleted: state.GetIsDelete(), 193 Value: value, 194 } 195 results = append(results, entry) 196 } 197 198 return results, nil 199 } 200 201 // Exists check entry with key exists in chaincode state 202 func (s *Impl) Exists(entry interface{}) (bool, error) { 203 key, err := s.Key(entry) 204 if err != nil { 205 return false, err 206 } 207 208 bb, err := s.GetState(key.String) 209 if err != nil { 210 return false, err 211 } 212 213 exists := len(bb) != 0 214 s.logger.Debug(`state check EXISTENCE`, zap.String(`key`, key.String), zap.Bool(`exists`, exists)) 215 return exists, nil 216 } 217 218 // List data from state using objectType prefix in composite key, trying to convert to target interface. 219 // Keys - additional components of composite key 220 func (s *Impl) List(namespace interface{}, target ...interface{}) (interface{}, error) { 221 stateList, err := NewStateList(target...) 222 if err != nil { 223 return nil, err 224 } 225 226 iter, err := s.createStateQueryIterator(namespace) 227 if err != nil { 228 return nil, errors.Wrap(err, `state iterator`) 229 } 230 231 defer func() { _ = iter.Close() }() 232 233 return stateList.Fill(iter, s.StateGetTransformer) 234 } 235 236 func (s *Impl) createStateQueryIterator(namespace interface{}) (shim.StateQueryIteratorInterface, error) { 237 n, t, err := s.normalizeAndTransformKey(namespace) 238 if err != nil { 239 return nil, err 240 } 241 s.logger.Debug(`state KEYS with composite key`, 242 zap.String(`key`, n.String()), zap.String(`transformed`, t.String())) 243 244 objectType, attrs := t.Parts() 245 if objectType == `` { 246 return s.stub.GetStateByRange(``, ``) // all state entries 247 } 248 249 return s.GetStateByPartialCompositeKey(objectType, attrs) 250 } 251 252 // normalizeAndTransformKey returns normalized and transformed key or error if occur 253 func (s *Impl) normalizeAndTransformKey(namespace interface{}) (Key, Key, error) { 254 normal, err := NormalizeKey(s.stub, namespace) 255 if err != nil { 256 return nil, nil, fmt.Errorf(`list prefix: %w`, err) 257 } 258 259 transformed, err := s.StateKeyTransformer(normal) 260 if err != nil { 261 return nil, nil, err 262 } 263 264 return normal, transformed, nil 265 } 266 267 func (s *Impl) ListPaginated( 268 namespace interface{}, pageSize int32, bookmark string, target ...interface{}) ( 269 interface{}, *pb.QueryResponseMetadata, error) { 270 stateList, err := NewStateList(target...) 271 if err != nil { 272 return nil, nil, err 273 } 274 275 iter, md, err := s.createStateQueryPagedIterator(namespace, pageSize, bookmark) 276 if err != nil { 277 return nil, nil, errors.Wrap(err, `state iterator`) 278 } 279 280 defer func() { _ = iter.Close() }() 281 list, err := stateList.Fill(iter, s.StateGetTransformer) 282 283 return list, md, err 284 } 285 286 func (s *Impl) createStateQueryPagedIterator(namespace interface{}, pageSize int32, bookmark string) ( 287 shim.StateQueryIteratorInterface, *pb.QueryResponseMetadata, error) { 288 n, t, err := s.normalizeAndTransformKey(namespace) 289 if err != nil { 290 return nil, nil, err 291 } 292 293 s.logger.Debug(`state KEYS with composite key`, 294 zap.String(`key`, n.String()), zap.String(`transformed`, t.String()), 295 zap.Int32("pageSize", pageSize), zap.String("bookmark", bookmark)) 296 297 objectType, attrs := t.Parts() 298 if objectType == `` { 299 return s.stub.GetStateByRangeWithPagination(``, ``, pageSize, bookmark) 300 } 301 302 return s.GetStateByPartialCompositeKeyWithPagination(objectType, attrs, pageSize, bookmark) 303 } 304 305 func (s *Impl) Keys(namespace interface{}) ([]string, error) { 306 iter, err := s.createStateQueryIterator(namespace) 307 if err != nil { 308 return nil, errors.Wrap(err, `state iterator`) 309 } 310 311 defer func() { _ = iter.Close() }() 312 313 var keys []string 314 for iter.HasNext() { 315 v, err := iter.Next() 316 if err != nil { 317 return nil, err 318 } 319 320 key, err := KeyFromComposite(s.stub, v.Key) 321 if err != nil { 322 return nil, err 323 } 324 325 reverseTransformedKey, err := s.StateKeyReverseTransformer(key) 326 if err != nil { 327 return nil, fmt.Errorf(`reverse transform key: %w`, err) 328 } 329 330 keyStr, err := KeyToString(s.stub, reverseTransformedKey) 331 if err != nil { 332 return nil, err 333 } 334 335 keys = append(keys, keyStr) 336 } 337 338 return keys, nil 339 } 340 341 func (s *Impl) argKeyValue(arg interface{}, values []interface{}) (key Key, value interface{}, err error) { 342 // key must be 343 if key, err = NormalizeKey(s.stub, arg); err != nil { 344 return 345 } 346 347 switch len(values) { 348 // arg is key and value 349 case 0: 350 return key, arg, nil 351 case 1: 352 return key, values[0], nil 353 default: 354 return nil, nil, ErrAllowOnlyOneValue 355 } 356 } 357 358 // Put data value in state with key, trying to convert data to []byte 359 func (s *Impl) Put(entry interface{}, values ...interface{}) error { 360 entryKey, value, err := s.argKeyValue(entry, values) 361 if err != nil { 362 return err 363 } 364 bb, err := s.StatePutTransformer(value) 365 if err != nil { 366 return err 367 } 368 369 key, err := s.Key(entryKey) 370 if err != nil { 371 return err 372 } 373 374 s.logger.Debug(`state PUT`, zap.String(`key`, key.String)) 375 return s.PutState(key.String, bb) 376 } 377 378 // Insert value into chaincode state, returns error if key already exists 379 func (s *Impl) Insert(entry interface{}, values ...interface{}) error { 380 if exists, err := s.Exists(entry); err != nil { 381 return err 382 } else if exists { 383 key, _ := s.Key(entry) 384 return fmt.Errorf(`%w: %s`, ErrKeyAlreadyExists, key.Origin) 385 } 386 387 key, value, err := s.argKeyValue(entry, values) 388 if err != nil { 389 return err 390 } 391 return s.Put(key, value) 392 } 393 394 // Delete entry from state 395 func (s *Impl) Delete(entry interface{}) error { 396 key, err := s.Key(entry) 397 if err != nil { 398 return errors.Wrap(err, `deleting from state`) 399 } 400 401 s.logger.Debug(`state DELETE`, zap.String(`key`, key.String)) 402 return s.DelState(key.String) 403 } 404 405 func (s *Impl) UseKeyTransformer(kt KeyTransformer) { 406 s.StateKeyTransformer = kt 407 } 408 409 func (s *Impl) UseKeyReverseTransformer(kt KeyTransformer) { 410 s.StateKeyReverseTransformer = kt 411 } 412 413 func (s *Impl) UseStateGetTransformer(fb FromBytesTransformer) { 414 s.StateGetTransformer = fb 415 } 416 417 func (s *Impl) UseStatePutTransformer(tb ToBytesTransformer) { 418 s.StatePutTransformer = tb 419 } 420 421 // GetPrivate data by key from private state, trying to convert to target interface 422 func (s *Impl) GetPrivate(collection string, entry interface{}, config ...interface{}) (interface{}, error) { 423 key, err := s.Key(entry) 424 if err != nil { 425 return nil, err 426 } 427 428 //bytes from private state 429 s.logger.Debug(`private state GET`, zap.String(`key`, key.String)) 430 bb, err := s.stub.GetPrivateData(collection, key.String) 431 if err != nil { 432 return nil, err 433 } 434 if len(bb) == 0 { 435 // config[1] default value 436 if len(config) >= 2 { 437 return config[1], nil 438 } 439 return nil, errors.Errorf(`%s: %s`, ErrKeyNotFound, key.Origin.String()) 440 } 441 442 // config[0] - target type 443 return s.StateGetTransformer(bb, config...) 444 } 445 446 // ExistsPrivate check entry with key exists in chaincode private state 447 func (s *Impl) ExistsPrivate(collection string, entry interface{}) (bool, error) { 448 key, err := s.Key(entry) 449 if err != nil { 450 return false, err 451 } 452 s.logger.Debug(`private state check EXISTENCE`, zap.String(`key`, key.String)) 453 bb, err := s.stub.GetPrivateData(collection, key.String) 454 if err != nil { 455 return false, err 456 } 457 return len(bb) != 0, nil 458 } 459 460 // ListPrivate data from private state using objectType prefix in composite key, trying to convert to target interface. 461 // Keys - additional components of composite key 462 // If usePrivateDataIterator is true, used private state for iterate over objects 463 // if false, used public state for iterate over keys and GetPrivateData for each key 464 func (s *Impl) ListPrivate(collection string, usePrivateDataIterator bool, namespace interface{}, target ...interface{}) (interface{}, error) { 465 stateList, err := NewStateList(target...) 466 if err != nil { 467 return nil, err 468 } 469 key, err := NormalizeKey(s.stub, namespace) 470 if err != nil { 471 return nil, errors.Wrap(err, `prepare list key parts`) 472 } 473 s.logger.Debug(`state LIST`, zap.String(`namespace`, key.String())) 474 475 if key, err = s.StateKeyTransformer(key); err != nil { 476 return nil, err 477 } 478 s.logger.Debug(`state LIST with composite key`, zap.String(`namespace`, key.String())) 479 480 if usePrivateDataIterator { 481 iter, err := s.stub.GetPrivateDataByPartialCompositeKey(collection, key[0], key[1:]) 482 if err != nil { 483 return nil, errors.Wrap(err, `create list iterator`) 484 } 485 defer func() { _ = iter.Close() }() 486 return stateList.Fill(iter, s.StateGetTransformer) 487 } 488 489 iter, err := s.stub.GetStateByPartialCompositeKey(key[0], key[1:]) 490 if err != nil { 491 return nil, errors.Wrap(err, `create list iterator`) 492 } 493 defer func() { _ = iter.Close() }() 494 495 var ( 496 kv *queryresult.KV 497 objKey string 498 keyParts []string 499 ) 500 for iter.HasNext() { 501 if kv, err = iter.Next(); err != nil { 502 return nil, errors.Wrap(err, `get key value`) 503 } 504 if objKey, keyParts, err = s.stub.SplitCompositeKey(kv.Key); err != nil { 505 return nil, err 506 } 507 508 object, err := s.GetPrivate(collection, append([]string{objKey}, keyParts...), target...) 509 if err != nil { 510 return nil, err 511 } 512 stateList.AddElementToList(object) 513 } 514 515 return stateList.Get() 516 } 517 518 // PutPrivate data value in private state with key, trying to convert data to []byte 519 func (s *Impl) PutPrivate(collection string, entry interface{}, values ...interface{}) (err error) { 520 entryKey, value, err := s.argKeyValue(entry, values) 521 if err != nil { 522 return err 523 } 524 bb, err := s.StatePutTransformer(value) 525 if err != nil { 526 return err 527 } 528 529 key, err := s.Key(entryKey) 530 if err != nil { 531 return err 532 } 533 534 s.logger.Debug(`state PUT`, zap.String(`key`, key.String)) 535 return s.stub.PutPrivateData(collection, key.String, bb) 536 } 537 538 // InsertPrivate value into chaincode private state, returns error if key already exists 539 func (s *Impl) InsertPrivate(collection string, entry interface{}, values ...interface{}) (err error) { 540 if exists, err := s.ExistsPrivate(collection, entry); err != nil { 541 return err 542 } else if exists { 543 key, _ := s.Key(entry) 544 return errors.Errorf(`%s: %s`, ErrKeyAlreadyExists, key.Origin) 545 } 546 547 key, value, err := s.argKeyValue(entry, values) 548 if err != nil { 549 return err 550 } 551 return s.PutPrivate(collection, key, value) 552 } 553 554 // DeletePrivate entry from private state 555 func (s *Impl) DeletePrivate(collection string, entry interface{}) error { 556 key, err := s.Key(entry) 557 if err != nil { 558 return errors.Wrap(err, `deleting from private state`) 559 } 560 s.logger.Debug(`private state DELETE`, zap.String(`key`, key.String)) 561 return s.stub.DelPrivateData(collection, key.String) 562 }