github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/gossip/privdata/util.go (about) 1 /* 2 Copyright hechain. 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/hechain20/hechain/core/ledger" 14 "github.com/hechain20/hechain/core/ledger/kvledger/txmgmt/rwsetutil" 15 privdatacommon "github.com/hechain20/hechain/gossip/privdata/common" 16 "github.com/hyperledger/fabric-protos-go/common" 17 "github.com/hyperledger/fabric-protos-go/ledger/rwset" 18 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 19 "github.com/hyperledger/fabric-protos-go/msp" 20 "github.com/hyperledger/fabric-protos-go/peer" 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{ 175 NameSpace: ns, 176 KvRwSet: sampleKvRwSet(), 177 } 178 for _, col := range collections { 179 nsRwSet.CollHashedRwSets = append(nsRwSet.CollHashedRwSets, sampleCollHashedRwSet(col, hash, true)) 180 } 181 return nsRwSet 182 } 183 184 func sampleReadOnlyNsRwSet(ns string, hash []byte, collections ...string) *rwsetutil.NsRwSet { 185 nsRwSet := &rwsetutil.NsRwSet{ 186 NameSpace: ns, 187 KvRwSet: sampleKvRwSet(), 188 } 189 for _, col := range collections { 190 nsRwSet.CollHashedRwSets = append(nsRwSet.CollHashedRwSets, sampleCollHashedRwSet(col, hash, false)) 191 } 192 return nsRwSet 193 } 194 195 func sampleKvRwSet() *kvrwset.KVRWSet { 196 rqi1 := &kvrwset.RangeQueryInfo{StartKey: "k0", EndKey: "k9", ItrExhausted: true} 197 rwsetutil.SetRawReads(rqi1, []*kvrwset.KVRead{ 198 {Key: "k1", Version: &kvrwset.Version{BlockNum: 1, TxNum: 1}}, 199 {Key: "k2", Version: &kvrwset.Version{BlockNum: 1, TxNum: 2}}, 200 }) 201 202 rqi2 := &kvrwset.RangeQueryInfo{StartKey: "k00", EndKey: "k90", ItrExhausted: true} 203 rwsetutil.SetMerkelSummary(rqi2, &kvrwset.QueryReadsMerkleSummary{MaxDegree: 5, MaxLevel: 4, MaxLevelHashes: [][]byte{[]byte("Hash-1"), []byte("Hash-2")}}) 204 return &kvrwset.KVRWSet{ 205 Reads: []*kvrwset.KVRead{{Key: "key1", Version: &kvrwset.Version{BlockNum: 1, TxNum: 1}}}, 206 RangeQueriesInfo: []*kvrwset.RangeQueryInfo{rqi1}, 207 Writes: []*kvrwset.KVWrite{{Key: "key2", IsDelete: false, Value: []byte("value2")}}, 208 } 209 } 210 211 func sampleCollHashedRwSet(collectionName string, hash []byte, hasWrites bool) *rwsetutil.CollHashedRwSet { 212 collHashedRwSet := &rwsetutil.CollHashedRwSet{ 213 CollectionName: collectionName, 214 HashedRwSet: &kvrwset.HashedRWSet{ 215 HashedReads: []*kvrwset.KVReadHash{ 216 {KeyHash: []byte("Key-1-hash"), Version: &kvrwset.Version{BlockNum: 1, TxNum: 2}}, 217 {KeyHash: []byte("Key-2-hash"), Version: &kvrwset.Version{BlockNum: 2, TxNum: 3}}, 218 }, 219 }, 220 PvtRwSetHash: hash, 221 } 222 if hasWrites { 223 collHashedRwSet.HashedRwSet.HashedWrites = []*kvrwset.KVWriteHash{ 224 {KeyHash: []byte("Key-3-hash"), ValueHash: []byte("value-3-hash"), IsDelete: false}, 225 {KeyHash: []byte("Key-4-hash"), ValueHash: []byte("value-4-hash"), IsDelete: true}, 226 } 227 } 228 return collHashedRwSet 229 } 230 231 func extractCollectionConfig(configPackage *peer.CollectionConfigPackage, collectionName string) *peer.CollectionConfig { 232 for _, config := range configPackage.Config { 233 switch cconf := config.Payload.(type) { 234 case *peer.CollectionConfig_StaticCollectionConfig: 235 if cconf.StaticCollectionConfig.Name == collectionName { 236 return config 237 } 238 default: 239 return nil 240 } 241 } 242 return nil 243 } 244 245 type pvtDataFactory struct { 246 data []*ledger.TxPvtData 247 } 248 249 func (df *pvtDataFactory) addRWSet() *pvtDataFactory { 250 seqInBlock := uint64(len(df.data)) 251 df.data = append(df.data, &ledger.TxPvtData{ 252 SeqInBlock: seqInBlock, 253 WriteSet: &rwset.TxPvtReadWriteSet{}, 254 }) 255 return df 256 } 257 258 func (df *pvtDataFactory) addNSRWSet(namespace string, collections ...string) *pvtDataFactory { 259 nsrws := &rwset.NsPvtReadWriteSet{ 260 Namespace: namespace, 261 } 262 for _, col := range collections { 263 nsrws.CollectionPvtRwset = append(nsrws.CollectionPvtRwset, &rwset.CollectionPvtReadWriteSet{ 264 CollectionName: col, 265 Rwset: []byte("rws-pre-image"), 266 }) 267 } 268 df.data[len(df.data)-1].WriteSet.NsPvtRwset = append(df.data[len(df.data)-1].WriteSet.NsPvtRwset, nsrws) 269 return df 270 } 271 272 func (df *pvtDataFactory) create() []*ledger.TxPvtData { 273 defer func() { 274 df.data = nil 275 }() 276 return df.data 277 } 278 279 type digestsAndSourceFactory struct { 280 d2s dig2sources 281 lastDig *privdatacommon.DigKey 282 } 283 284 func (f *digestsAndSourceFactory) mapDigest(dig *privdatacommon.DigKey) *digestsAndSourceFactory { 285 f.lastDig = dig 286 return f 287 } 288 289 func (f *digestsAndSourceFactory) toSources(peers ...string) *digestsAndSourceFactory { 290 if f.d2s == nil { 291 f.d2s = make(dig2sources) 292 } 293 var endorsements []*peer.Endorsement 294 for _, p := range peers { 295 endorsements = append(endorsements, &peer.Endorsement{ 296 Endorser: []byte(p), 297 }) 298 } 299 f.d2s[*f.lastDig] = endorsements 300 return f 301 } 302 303 func (f *digestsAndSourceFactory) create() dig2sources { 304 return f.d2s 305 }