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  }