github.com/kaituanwang/hyperledger@v2.0.1+incompatible/gossip/privdata/util.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package privdata 8 9 import ( 10 "fmt" 11 12 "github.com/golang/protobuf/proto" 13 "github.com/hyperledger/fabric-protos-go/common" 14 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 15 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 16 "github.com/hyperledger/fabric-protos-go/msp" 17 "github.com/hyperledger/fabric-protos-go/peer" 18 "github.com/hyperledger/fabric/core/ledger" 19 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil" 20 privdatacommon "github.com/hyperledger/fabric/gossip/privdata/common" 21 ) 22 23 type txValidationFlags []uint8 24 25 type blockFactory struct { 26 channelID string 27 transactions [][]byte 28 metadataSize int 29 lacksMetadata bool 30 invalidTxns map[int]struct{} 31 } 32 33 func (bf *blockFactory) AddTxn(txID string, nsName string, hash []byte, collections ...string) *blockFactory { 34 return bf.AddTxnWithEndorsement(txID, nsName, hash, "", true, collections...) 35 } 36 37 func (bf *blockFactory) AddReadOnlyTxn(txID string, nsName string, hash []byte, collections ...string) *blockFactory { 38 return bf.AddTxnWithEndorsement(txID, nsName, hash, "", false, collections...) 39 } 40 41 func (bf *blockFactory) AddTxnWithEndorsement(txID string, nsName string, hash []byte, org string, hasWrites bool, collections ...string) *blockFactory { 42 txn := &peer.Transaction{ 43 Actions: []*peer.TransactionAction{ 44 {}, 45 }, 46 } 47 nsRWSet := sampleNsRwSet(nsName, hash, collections...) 48 if !hasWrites { 49 nsRWSet = sampleReadOnlyNsRwSet(nsName, hash, collections...) 50 } 51 txrws := rwsetutil.TxRwSet{ 52 NsRwSets: []*rwsetutil.NsRwSet{nsRWSet}, 53 } 54 55 b, err := txrws.ToProtoBytes() 56 if err != nil { 57 panic(err) 58 } 59 ccAction := &peer.ChaincodeAction{ 60 Results: b, 61 } 62 63 ccActionBytes, err := proto.Marshal(ccAction) 64 if err != nil { 65 panic(err) 66 } 67 pRespPayload := &peer.ProposalResponsePayload{ 68 Extension: ccActionBytes, 69 } 70 71 respPayloadBytes, err := proto.Marshal(pRespPayload) 72 if err != nil { 73 panic(err) 74 } 75 76 ccPayload := &peer.ChaincodeActionPayload{ 77 Action: &peer.ChaincodeEndorsedAction{ 78 ProposalResponsePayload: respPayloadBytes, 79 }, 80 } 81 82 if org != "" { 83 sID := &msp.SerializedIdentity{Mspid: org, IdBytes: []byte(fmt.Sprintf("p0%s", org))} 84 b, _ := proto.Marshal(sID) 85 ccPayload.Action.Endorsements = []*peer.Endorsement{ 86 { 87 Endorser: b, 88 }, 89 } 90 } 91 92 ccPayloadBytes, err := proto.Marshal(ccPayload) 93 if err != nil { 94 panic(err) 95 } 96 97 txn.Actions[0].Payload = ccPayloadBytes 98 txBytes, _ := proto.Marshal(txn) 99 100 cHdr := &common.ChannelHeader{ 101 TxId: txID, 102 Type: int32(common.HeaderType_ENDORSER_TRANSACTION), 103 ChannelId: bf.channelID, 104 } 105 cHdrBytes, _ := proto.Marshal(cHdr) 106 commonPayload := &common.Payload{ 107 Header: &common.Header{ 108 ChannelHeader: cHdrBytes, 109 }, 110 Data: txBytes, 111 } 112 113 payloadBytes, _ := proto.Marshal(commonPayload) 114 envp := &common.Envelope{ 115 Payload: payloadBytes, 116 } 117 envelopeBytes, _ := proto.Marshal(envp) 118 119 bf.transactions = append(bf.transactions, envelopeBytes) 120 return bf 121 } 122 123 func (bf *blockFactory) create() *common.Block { 124 defer func() { 125 *bf = blockFactory{channelID: bf.channelID} 126 }() 127 block := &common.Block{ 128 Header: &common.BlockHeader{ 129 Number: 1, 130 }, 131 Data: &common.BlockData{ 132 Data: bf.transactions, 133 }, 134 } 135 136 if bf.lacksMetadata { 137 return block 138 } 139 block.Metadata = &common.BlockMetadata{ 140 Metadata: make([][]byte, common.BlockMetadataIndex_TRANSACTIONS_FILTER+1), 141 } 142 if bf.metadataSize > 0 { 143 block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = make([]uint8, bf.metadataSize) 144 } else { 145 block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = make([]uint8, len(block.Data.Data)) 146 } 147 148 for txSeqInBlock := range bf.invalidTxns { 149 block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER][txSeqInBlock] = uint8(peer.TxValidationCode_INVALID_ENDORSER_TRANSACTION) 150 } 151 152 return block 153 } 154 155 func (bf *blockFactory) withoutMetadata() *blockFactory { 156 bf.lacksMetadata = true 157 return bf 158 } 159 160 func (bf *blockFactory) withMetadataSize(mdSize int) *blockFactory { 161 bf.metadataSize = mdSize 162 return bf 163 } 164 165 func (bf *blockFactory) withInvalidTxns(sequences ...int) *blockFactory { 166 bf.invalidTxns = make(map[int]struct{}) 167 for _, seq := range sequences { 168 bf.invalidTxns[seq] = struct{}{} 169 } 170 return bf 171 } 172 173 func sampleNsRwSet(ns string, hash []byte, collections ...string) *rwsetutil.NsRwSet { 174 nsRwSet := &rwsetutil.NsRwSet{NameSpace: ns, 175 KvRwSet: sampleKvRwSet(), 176 } 177 for _, col := range collections { 178 nsRwSet.CollHashedRwSets = append(nsRwSet.CollHashedRwSets, sampleCollHashedRwSet(col, hash, true)) 179 } 180 return nsRwSet 181 } 182 183 func sampleReadOnlyNsRwSet(ns string, hash []byte, collections ...string) *rwsetutil.NsRwSet { 184 nsRwSet := &rwsetutil.NsRwSet{NameSpace: ns, 185 KvRwSet: sampleKvRwSet(), 186 } 187 for _, col := range collections { 188 nsRwSet.CollHashedRwSets = append(nsRwSet.CollHashedRwSets, sampleCollHashedRwSet(col, hash, false)) 189 } 190 return nsRwSet 191 } 192 193 func sampleKvRwSet() *kvrwset.KVRWSet { 194 rqi1 := &kvrwset.RangeQueryInfo{StartKey: "k0", EndKey: "k9", ItrExhausted: true} 195 rwsetutil.SetRawReads(rqi1, []*kvrwset.KVRead{ 196 {Key: "k1", Version: &kvrwset.Version{BlockNum: 1, TxNum: 1}}, 197 {Key: "k2", Version: &kvrwset.Version{BlockNum: 1, TxNum: 2}}, 198 }) 199 200 rqi2 := &kvrwset.RangeQueryInfo{StartKey: "k00", EndKey: "k90", ItrExhausted: true} 201 rwsetutil.SetMerkelSummary(rqi2, &kvrwset.QueryReadsMerkleSummary{MaxDegree: 5, MaxLevel: 4, MaxLevelHashes: [][]byte{[]byte("Hash-1"), []byte("Hash-2")}}) 202 return &kvrwset.KVRWSet{ 203 Reads: []*kvrwset.KVRead{{Key: "key1", Version: &kvrwset.Version{BlockNum: 1, TxNum: 1}}}, 204 RangeQueriesInfo: []*kvrwset.RangeQueryInfo{rqi1}, 205 Writes: []*kvrwset.KVWrite{{Key: "key2", IsDelete: false, Value: []byte("value2")}}, 206 } 207 } 208 209 func sampleCollHashedRwSet(collectionName string, hash []byte, hasWrites bool) *rwsetutil.CollHashedRwSet { 210 collHashedRwSet := &rwsetutil.CollHashedRwSet{ 211 CollectionName: collectionName, 212 HashedRwSet: &kvrwset.HashedRWSet{ 213 HashedReads: []*kvrwset.KVReadHash{ 214 {KeyHash: []byte("Key-1-hash"), Version: &kvrwset.Version{BlockNum: 1, TxNum: 2}}, 215 {KeyHash: []byte("Key-2-hash"), Version: &kvrwset.Version{BlockNum: 2, TxNum: 3}}, 216 }, 217 }, 218 PvtRwSetHash: hash, 219 } 220 if hasWrites { 221 collHashedRwSet.HashedRwSet.HashedWrites = []*kvrwset.KVWriteHash{ 222 {KeyHash: []byte("Key-3-hash"), ValueHash: []byte("value-3-hash"), IsDelete: false}, 223 {KeyHash: []byte("Key-4-hash"), ValueHash: []byte("value-4-hash"), IsDelete: true}, 224 } 225 } 226 return collHashedRwSet 227 } 228 229 func extractCollectionConfig(configPackage *peer.CollectionConfigPackage, collectionName string) *peer.CollectionConfig { 230 for _, config := range configPackage.Config { 231 switch cconf := config.Payload.(type) { 232 case *peer.CollectionConfig_StaticCollectionConfig: 233 if cconf.StaticCollectionConfig.Name == collectionName { 234 return config 235 } 236 default: 237 return nil 238 } 239 } 240 return nil 241 } 242 243 type pvtDataFactory struct { 244 data []*ledger.TxPvtData 245 } 246 247 func (df *pvtDataFactory) addRWSet() *pvtDataFactory { 248 seqInBlock := uint64(len(df.data)) 249 df.data = append(df.data, &ledger.TxPvtData{ 250 SeqInBlock: seqInBlock, 251 WriteSet: &rwset.TxPvtReadWriteSet{}, 252 }) 253 return df 254 } 255 256 func (df *pvtDataFactory) addNSRWSet(namespace string, collections ...string) *pvtDataFactory { 257 nsrws := &rwset.NsPvtReadWriteSet{ 258 Namespace: namespace, 259 } 260 for _, col := range collections { 261 nsrws.CollectionPvtRwset = append(nsrws.CollectionPvtRwset, &rwset.CollectionPvtReadWriteSet{ 262 CollectionName: col, 263 Rwset: []byte("rws-pre-image"), 264 }) 265 } 266 df.data[len(df.data)-1].WriteSet.NsPvtRwset = append(df.data[len(df.data)-1].WriteSet.NsPvtRwset, nsrws) 267 return df 268 } 269 270 func (df *pvtDataFactory) create() []*ledger.TxPvtData { 271 defer func() { 272 df.data = nil 273 }() 274 return df.data 275 } 276 277 type digestsAndSourceFactory struct { 278 d2s dig2sources 279 lastDig *privdatacommon.DigKey 280 } 281 282 func (f *digestsAndSourceFactory) mapDigest(dig *privdatacommon.DigKey) *digestsAndSourceFactory { 283 f.lastDig = dig 284 return f 285 } 286 287 func (f *digestsAndSourceFactory) toSources(peers ...string) *digestsAndSourceFactory { 288 if f.d2s == nil { 289 f.d2s = make(dig2sources) 290 } 291 var endorsements []*peer.Endorsement 292 for _, p := range peers { 293 endorsements = append(endorsements, &peer.Endorsement{ 294 Endorser: []byte(p), 295 }) 296 } 297 f.d2s[*f.lastDig] = endorsements 298 return f 299 } 300 301 func (f *digestsAndSourceFactory) create() dig2sources { 302 return f.d2s 303 }