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  }