-
Notifications
You must be signed in to change notification settings - Fork 8.8k
/
ledger_shim.go
192 lines (160 loc) · 6.13 KB
/
ledger_shim.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package lifecycle
import (
"github.com/hyperledger/fabric-chaincode-go/shim"
"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
commonledger "github.com/hyperledger/fabric/common/ledger"
validatorstate "github.com/hyperledger/fabric/core/handlers/validation/api/state"
"github.com/hyperledger/fabric/core/ledger"
"github.com/pkg/errors"
)
type StateIterator interface {
Close() error
Next() (*queryresult.KV, error)
}
// StateIteratorToMap takes an iterator, and iterates over the entire thing, encoding the KVs
// into a map, and then closes it.
func StateIteratorToMap(itr StateIterator) (map[string][]byte, error) {
defer itr.Close()
result := map[string][]byte{}
for {
entry, err := itr.Next()
if err != nil {
return nil, errors.WithMessage(err, "could not iterate over range")
}
if entry == nil {
return result, nil
}
result[entry.Key] = entry.Value
}
}
// ChaincodePublicLedgerShim decorates the chaincode shim to support the state interfaces
// required by the serialization code.
type ChaincodePublicLedgerShim struct {
shim.ChaincodeStubInterface
}
// GetStateRange performs a range query for keys beginning with a particular prefix, and
// returns it as a map. This function assumes that keys contain only ascii chars from \x00 to \x7e.
func (cls *ChaincodePublicLedgerShim) GetStateRange(prefix string) (map[string][]byte, error) {
itr, err := cls.GetStateByRange(prefix, prefix+"\x7f")
if err != nil {
return nil, errors.WithMessage(err, "could not get state iterator")
}
return StateIteratorToMap(&ChaincodeResultIteratorShim{ResultsIterator: itr})
}
type ChaincodeResultIteratorShim struct {
ResultsIterator shim.StateQueryIteratorInterface
}
func (cris *ChaincodeResultIteratorShim) Next() (*queryresult.KV, error) {
if !cris.ResultsIterator.HasNext() {
return nil, nil
}
return cris.ResultsIterator.Next()
}
func (cris *ChaincodeResultIteratorShim) Close() error {
return cris.ResultsIterator.Close()
}
// ChaincodePrivateLedgerShim wraps the chaincode shim to make access to keys in a collection
// have the same semantics as normal public keys.
type ChaincodePrivateLedgerShim struct {
Stub shim.ChaincodeStubInterface
Collection string
}
// GetStateRange performs a range query in the configured collection for all keys beginning
// with a particular prefix. This function assumes that keys contain only ascii chars from \x00 to \x7e.
func (cls *ChaincodePrivateLedgerShim) GetStateRange(prefix string) (map[string][]byte, error) {
itr, err := cls.Stub.GetPrivateDataByRange(cls.Collection, prefix, prefix+"\x7f")
if err != nil {
return nil, errors.WithMessage(err, "could not get state iterator")
}
return StateIteratorToMap(&ChaincodeResultIteratorShim{ResultsIterator: itr})
}
// GetState returns the value for the key in the configured collection.
func (cls *ChaincodePrivateLedgerShim) GetState(key string) ([]byte, error) {
return cls.Stub.GetPrivateData(cls.Collection, key)
}
// GetStateHash return the hash of the pre-image for the key in the configured collection.
func (cls *ChaincodePrivateLedgerShim) GetStateHash(key string) ([]byte, error) {
return cls.Stub.GetPrivateDataHash(cls.Collection, key)
}
// PutState sets the value for the key in the configured collection.
func (cls *ChaincodePrivateLedgerShim) PutState(key string, value []byte) error {
return cls.Stub.PutPrivateData(cls.Collection, key, value)
}
// DelState deletes the key in the configured collection.
func (cls *ChaincodePrivateLedgerShim) DelState(key string) error {
return cls.Stub.DelPrivateData(cls.Collection, key)
}
func (cls *ChaincodePrivateLedgerShim) CollectionName() string {
return cls.Collection
}
// SimpleQueryExecutorShim implements the ReadableState and RangeableState interfaces
// based on an underlying ledger.SimpleQueryExecutor
type SimpleQueryExecutorShim struct {
Namespace string
SimpleQueryExecutor ledger.SimpleQueryExecutor
}
func (sqes *SimpleQueryExecutorShim) GetState(key string) ([]byte, error) {
return sqes.SimpleQueryExecutor.GetState(sqes.Namespace, key)
}
func (sqes *SimpleQueryExecutorShim) GetStateRange(prefix string) (map[string][]byte, error) {
itr, err := sqes.SimpleQueryExecutor.GetStateRangeScanIterator(sqes.Namespace, prefix, prefix+"\x7f")
if err != nil {
return nil, errors.WithMessage(err, "could not get state iterator")
}
return StateIteratorToMap(&ResultsIteratorShim{ResultsIterator: itr})
}
type ResultsIteratorShim struct {
ResultsIterator commonledger.ResultsIterator
}
func (ris *ResultsIteratorShim) Next() (*queryresult.KV, error) {
res, err := ris.ResultsIterator.Next()
if err != nil {
return nil, err
}
if res == nil {
return nil, nil
}
return res.(*queryresult.KV), err
}
func (ris *ResultsIteratorShim) Close() error {
ris.ResultsIterator.Close()
return nil
}
type ValidatorStateShim struct {
ValidatorState validatorstate.State
Namespace string
}
func (vss *ValidatorStateShim) GetState(key string) ([]byte, error) {
result, err := vss.ValidatorState.GetStateMultipleKeys(vss.Namespace, []string{key})
if err != nil {
return nil, errors.WithMessage(err, "could not get state thought validatorstate shim")
}
return result[0], nil
}
type PrivateQueryExecutor interface {
GetPrivateDataHash(namespace, collection, key string) (value []byte, err error)
}
type PrivateQueryExecutorShim struct {
Namespace string
Collection string
State PrivateQueryExecutor
}
func (pqes *PrivateQueryExecutorShim) GetStateHash(key string) ([]byte, error) {
return pqes.State.GetPrivateDataHash(pqes.Namespace, pqes.Collection, key)
}
func (pqes *PrivateQueryExecutorShim) CollectionName() string {
return pqes.Collection
}
// DummyQueryExecutorShim implements the ReadableState interface. It is
// used to ensure channel-less system chaincode calls don't panic and return
// and error when an invalid operation is attempted (i.e. an InstallChaincode
// invocation against a chaincode other than _lifecycle)
type DummyQueryExecutorShim struct {
}
func (*DummyQueryExecutorShim) GetState(key string) ([]byte, error) {
return nil, errors.New("invalid channel-less operation")
}