github.com/defanghe/fabric@v2.1.1+incompatible/core/ledger/kvledger/hashcheck_pvtdata_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package kvledger
     8  
     9  import (
    10  	"fmt"
    11  	"strings"
    12  	"testing"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
    16  	"github.com/hyperledger/fabric/common/ledger/testutil"
    17  	"github.com/hyperledger/fabric/core/ledger"
    18  	"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
    19  	"github.com/hyperledger/fabric/protoutil"
    20  	"github.com/stretchr/testify/assert"
    21  )
    22  
    23  func TestConstructValidInvalidBlocksPvtData(t *testing.T) {
    24  	conf, cleanup := testConfig(t)
    25  	defer cleanup()
    26  	provider := testutilNewProvider(conf, t)
    27  	defer provider.Close()
    28  
    29  	_, gb := testutil.NewBlockGenerator(t, "testLedger", false)
    30  	gbHash := protoutil.BlockHeaderHash(gb.Header)
    31  	lg, _ := provider.Create(gb)
    32  	defer lg.Close()
    33  
    34  	// construct pvtData and pubRwSet (i.e., hashed rw set)
    35  	v0 := []byte{0}
    36  	pvtDataBlk1Tx0, pubSimResBytesBlk1Tx0 := produceSamplePvtdata(t, 0, []string{"ns-1:coll-1", "ns-1:coll-2"}, [][]byte{v0, v0})
    37  	v1 := []byte{1}
    38  	pvtDataBlk1Tx1, pubSimResBytesBlk1Tx1 := produceSamplePvtdata(t, 1, []string{"ns-1:coll-1", "ns-1:coll-2"}, [][]byte{v1, v1})
    39  	v2 := []byte{2}
    40  	pvtDataBlk1Tx2, pubSimResBytesBlk1Tx2 := produceSamplePvtdata(t, 2, []string{"ns-1:coll-1", "ns-2:coll-2"}, [][]byte{v2, v2})
    41  	v3 := []byte{3}
    42  	pvtDataBlk1Tx3, pubSimResBytesBlk1Tx3 := produceSamplePvtdata(t, 3, []string{"ns-1:coll-1", "ns-1:coll-2"}, [][]byte{v3, v3})
    43  	v4 := []byte{4}
    44  	pvtDataBlk1Tx4, pubSimResBytesBlk1Tx4 := produceSamplePvtdata(t, 4, []string{"ns-1:coll-1", "ns-4:coll-2"}, [][]byte{v4, v4})
    45  	v5 := []byte{5}
    46  	pvtDataBlk1Tx5, pubSimResBytesBlk1Tx5 := produceSamplePvtdata(t, 5, []string{"ns-1:coll-1", "ns-1:coll-2"}, [][]byte{v5, v5})
    47  	v6 := []byte{6}
    48  	pvtDataBlk1Tx6, pubSimResBytesBlk1Tx6 := produceSamplePvtdata(t, 6, []string{"ns-6:coll-2"}, [][]byte{v6})
    49  	v7 := []byte{7}
    50  	_, pubSimResBytesBlk1Tx7 := produceSamplePvtdata(t, 7, []string{"ns-1:coll-2"}, [][]byte{v7})
    51  	wrongPvtDataBlk1Tx7, _ := produceSamplePvtdata(t, 7, []string{"ns-6:coll-2"}, [][]byte{v6})
    52  
    53  	pubSimulationResults := &rwset.TxReadWriteSet{}
    54  	err := proto.Unmarshal(pubSimResBytesBlk1Tx7, pubSimulationResults)
    55  	assert.NoError(t, err)
    56  	tx7PvtdataHash := pubSimulationResults.NsRwset[0].CollectionHashedRwset[0].PvtRwsetHash
    57  
    58  	// construct block1
    59  	simulationResultsBlk1 := [][]byte{pubSimResBytesBlk1Tx0, pubSimResBytesBlk1Tx1, pubSimResBytesBlk1Tx2,
    60  		pubSimResBytesBlk1Tx3, pubSimResBytesBlk1Tx4, pubSimResBytesBlk1Tx5,
    61  		pubSimResBytesBlk1Tx6, pubSimResBytesBlk1Tx7}
    62  	blk1 := testutil.ConstructBlock(t, 1, gbHash, simulationResultsBlk1, false)
    63  
    64  	// construct a pvtData list for block1
    65  	pvtDataBlk1 := map[uint64]*ledger.TxPvtData{
    66  		0: pvtDataBlk1Tx0,
    67  		1: pvtDataBlk1Tx1,
    68  		2: pvtDataBlk1Tx2,
    69  		4: pvtDataBlk1Tx4,
    70  		5: pvtDataBlk1Tx5,
    71  	}
    72  
    73  	// construct a missingData list for block1
    74  	missingData := make(ledger.TxMissingPvtDataMap)
    75  	missingData.Add(3, "ns-1", "coll-1", true)
    76  	missingData.Add(3, "ns-1", "coll-2", true)
    77  	missingData.Add(6, "ns-6", "coll-2", true)
    78  	missingData.Add(7, "ns-1", "coll-2", true)
    79  
    80  	// commit block1
    81  	blockAndPvtData1 := &ledger.BlockAndPvtData{
    82  		Block:          blk1,
    83  		PvtData:        pvtDataBlk1,
    84  		MissingPvtData: missingData}
    85  	assert.NoError(t, lg.(*kvLedger).blockStore.CommitWithPvtData(blockAndPvtData1))
    86  
    87  	// construct pvtData from missing data in tx3, tx6, and tx7
    88  	pvtdata := []*ledger.ReconciledPvtdata{
    89  		{
    90  			BlockNum: 1,
    91  			WriteSets: map[uint64]*ledger.TxPvtData{
    92  				3: pvtDataBlk1Tx3,
    93  				6: pvtDataBlk1Tx6,
    94  				7: wrongPvtDataBlk1Tx7,
    95  				// ns-6:coll-2 does not present in tx7
    96  			},
    97  		},
    98  	}
    99  
   100  	expectedValidBlocksPvtData := map[uint64][]*ledger.TxPvtData{
   101  		1: {
   102  			pvtDataBlk1Tx3,
   103  			pvtDataBlk1Tx6,
   104  		},
   105  	}
   106  
   107  	blocksValidPvtData, hashMismatched, err := constructValidAndInvalidPvtData(pvtdata, lg.(*kvLedger).blockStore)
   108  	assert.NoError(t, err)
   109  	assert.Equal(t, len(expectedValidBlocksPvtData), len(blocksValidPvtData))
   110  	assert.ElementsMatch(t, expectedValidBlocksPvtData[1], blocksValidPvtData[1])
   111  	// should not include the pvtData passed for the tx7 even in hashmismatched as ns-6:coll-2 does not exist in tx7
   112  	assert.Len(t, hashMismatched, 0)
   113  
   114  	// construct pvtData from missing data in tx7 with wrong pvtData
   115  	wrongPvtDataBlk1Tx7, pubSimResBytesBlk1Tx7 = produceSamplePvtdata(t, 7, []string{"ns-1:coll-2"}, [][]byte{v6})
   116  	pvtdata = []*ledger.ReconciledPvtdata{
   117  		{
   118  			BlockNum: 1,
   119  			WriteSets: map[uint64]*ledger.TxPvtData{
   120  				7: wrongPvtDataBlk1Tx7,
   121  				// ns-1:coll-1 exists in tx7 but the passed pvtData is incorrect
   122  			},
   123  		},
   124  	}
   125  
   126  	expectedHashMismatches := []*ledger.PvtdataHashMismatch{
   127  		{
   128  			BlockNum:     1,
   129  			TxNum:        7,
   130  			Namespace:    "ns-1",
   131  			Collection:   "coll-2",
   132  			ExpectedHash: tx7PvtdataHash,
   133  		},
   134  	}
   135  
   136  	blocksValidPvtData, hashMismatches, err := constructValidAndInvalidPvtData(pvtdata, lg.(*kvLedger).blockStore)
   137  	assert.NoError(t, err)
   138  	assert.Len(t, blocksValidPvtData, 0)
   139  
   140  	assert.ElementsMatch(t, expectedHashMismatches, hashMismatches)
   141  }
   142  
   143  func produceSamplePvtdata(t *testing.T, txNum uint64, nsColls []string, values [][]byte) (*ledger.TxPvtData, []byte) {
   144  	builder := rwsetutil.NewRWSetBuilder()
   145  	for index, nsColl := range nsColls {
   146  		nsCollSplit := strings.Split(nsColl, ":")
   147  		ns := nsCollSplit[0]
   148  		coll := nsCollSplit[1]
   149  		key := fmt.Sprintf("key-%s-%s", ns, coll)
   150  		value := values[index]
   151  		builder.AddToPvtAndHashedWriteSet(ns, coll, key, value)
   152  	}
   153  	simRes, err := builder.GetTxSimulationResults()
   154  	assert.NoError(t, err)
   155  	pubSimulationResultsBytes, err := proto.Marshal(simRes.PubSimulationResults)
   156  	assert.NoError(t, err)
   157  	return &ledger.TxPvtData{SeqInBlock: txNum, WriteSet: simRes.PvtSimulationResults}, pubSimulationResultsBytes
   158  }
   159  
   160  func TestRemoveCollFromTxPvtReadWriteSet(t *testing.T) {
   161  	txpvtrwset := testutilConstructSampleTxPvtRwset(
   162  		[]*testNsColls{
   163  			{ns: "ns-1", colls: []string{"coll-1", "coll-2"}},
   164  			{ns: "ns-2", colls: []string{"coll-3", "coll-4"}},
   165  		},
   166  	)
   167  
   168  	removeCollFromTxPvtReadWriteSet(txpvtrwset, "ns-1", "coll-1")
   169  	assert.Equal(
   170  		t,
   171  		testutilConstructSampleTxPvtRwset(
   172  			[]*testNsColls{
   173  				{ns: "ns-1", colls: []string{"coll-2"}},
   174  				{ns: "ns-2", colls: []string{"coll-3", "coll-4"}},
   175  			},
   176  		),
   177  		txpvtrwset,
   178  	)
   179  
   180  	removeCollFromTxPvtReadWriteSet(txpvtrwset, "ns-1", "coll-2")
   181  	assert.Equal(
   182  		t,
   183  		testutilConstructSampleTxPvtRwset(
   184  			[]*testNsColls{
   185  				{ns: "ns-2", colls: []string{"coll-3", "coll-4"}},
   186  			},
   187  		),
   188  		txpvtrwset,
   189  	)
   190  }
   191  
   192  func testutilConstructSampleTxPvtRwset(nsCollsList []*testNsColls) *rwset.TxPvtReadWriteSet {
   193  	txPvtRwset := &rwset.TxPvtReadWriteSet{}
   194  	for _, nsColls := range nsCollsList {
   195  		ns := nsColls.ns
   196  		nsdata := &rwset.NsPvtReadWriteSet{
   197  			Namespace:          ns,
   198  			CollectionPvtRwset: []*rwset.CollectionPvtReadWriteSet{},
   199  		}
   200  		txPvtRwset.NsPvtRwset = append(txPvtRwset.NsPvtRwset, nsdata)
   201  		for _, coll := range nsColls.colls {
   202  			nsdata.CollectionPvtRwset = append(nsdata.CollectionPvtRwset,
   203  				&rwset.CollectionPvtReadWriteSet{
   204  					CollectionName: coll,
   205  					Rwset:          []byte(fmt.Sprintf("pvtrwset-for-%s-%s", ns, coll)),
   206  				},
   207  			)
   208  		}
   209  	}
   210  	return txPvtRwset
   211  }
   212  
   213  type testNsColls struct {
   214  	ns    string
   215  	colls []string
   216  }