github.com/true-sqn/fabric@v2.1.1+incompatible/core/ledger/kvledger/tests/sample_data_helper.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package tests
     8  
     9  import (
    10  	"fmt"
    11  	"testing"
    12  
    13  	protopeer "github.com/hyperledger/fabric-protos-go/peer"
    14  	"github.com/hyperledger/fabric/core/ledger"
    15  	"github.com/stretchr/testify/assert"
    16  )
    17  
    18  type submittedData map[string]*submittedLedgerData
    19  
    20  type submittedLedgerData struct {
    21  	Blocks []*ledger.BlockAndPvtData
    22  	Txs    []*txAndPvtdata
    23  }
    24  
    25  func (s submittedData) initForLedger(lgrid string) {
    26  	ld := s[lgrid]
    27  	if ld == nil {
    28  		ld = &submittedLedgerData{}
    29  		s[lgrid] = ld
    30  	}
    31  }
    32  
    33  func (s submittedData) recordSubmittedBlks(lgrid string, blk ...*ledger.BlockAndPvtData) {
    34  	s.initForLedger(lgrid)
    35  	s[lgrid].Blocks = append(s[lgrid].Blocks, blk...)
    36  }
    37  
    38  func (s submittedData) recordSubmittedTxs(lgrid string, tx ...*txAndPvtdata) {
    39  	s.initForLedger(lgrid)
    40  	s[lgrid].Txs = append(s[lgrid].Txs, tx...)
    41  }
    42  
    43  type sampleDataHelper struct {
    44  	submittedData submittedData
    45  	assert        *assert.Assertions
    46  	t             *testing.T
    47  }
    48  
    49  func newSampleDataHelper(t *testing.T) *sampleDataHelper {
    50  	return &sampleDataHelper{make(submittedData), assert.New(t), t}
    51  }
    52  
    53  func (d *sampleDataHelper) populateLedger(h *testhelper) {
    54  	lgrid := h.lgrid
    55  	// blk1 deploys 2 chaincodes
    56  	txdeploy1 := h.simulateDeployTx("cc1", nil)
    57  	txdeploy2 := h.simulateDeployTx("cc2", nil)
    58  	blk1 := h.cutBlockAndCommitLegacy()
    59  
    60  	// blk2 contains 2 public data txs
    61  	txdata1 := h.simulateDataTx("txid1", func(s *simulator) {
    62  		s.setState("cc1", "key1", d.sampleVal("value01", lgrid))
    63  		s.setState("cc1", "key2", d.sampleVal("value02", lgrid))
    64  	})
    65  
    66  	txdata2 := h.simulateDataTx("txid2", func(s *simulator) {
    67  		s.setState("cc2", "key1", d.sampleVal("value03", lgrid))
    68  		s.setState("cc2", "key2", d.sampleVal("value04", lgrid))
    69  	})
    70  	blk2 := h.cutBlockAndCommitLegacy()
    71  
    72  	// blk3 upgrades both chaincodes
    73  	txupgrade1 := h.simulateUpgradeTx("cc1", d.sampleCollConf1(lgrid, "cc1"))
    74  	txupgrade2 := h.simulateUpgradeTx("cc2", d.sampleCollConf1(lgrid, "cc2"))
    75  	blk3 := h.cutBlockAndCommitLegacy()
    76  
    77  	// blk4 contains 2 data txs with private data
    78  	txdata3 := h.simulateDataTx("txid3", func(s *simulator) {
    79  		s.setPvtdata("cc1", "coll1", "key3", d.sampleVal("value05", lgrid))
    80  		s.setPvtdata("cc1", "coll1", "key4", d.sampleVal("value06", lgrid))
    81  	})
    82  	txdata4 := h.simulateDataTx("txid4", func(s *simulator) {
    83  		s.setPvtdata("cc2", "coll1", "key3", d.sampleVal("value07", lgrid))
    84  		s.setPvtdata("cc2", "coll1", "key4", d.sampleVal("value08", lgrid))
    85  	})
    86  	blk4 := h.cutBlockAndCommitLegacy()
    87  
    88  	// blk5 upgrades both chaincodes
    89  	txupgrade3 := h.simulateUpgradeTx("cc1", d.sampleCollConf2(lgrid, "cc1"))
    90  	txupgrade4 := h.simulateDeployTx("cc2", d.sampleCollConf2(lgrid, "cc2"))
    91  	blk5 := h.cutBlockAndCommitLegacy()
    92  
    93  	// blk6 contains 2 data txs with private data
    94  	txdata5 := h.simulateDataTx("txid5", func(s *simulator) {
    95  		s.setPvtdata("cc1", "coll2", "key3", d.sampleVal("value09", lgrid))
    96  		s.setPvtdata("cc1", "coll2", "key4", d.sampleVal("value10", lgrid))
    97  	})
    98  	txdata6 := h.simulateDataTx("txid6", func(s *simulator) {
    99  		s.setPvtdata("cc2", "coll2", "key3", d.sampleVal("value11", lgrid))
   100  		s.setPvtdata("cc2", "coll2", "key4", d.sampleVal("value12", lgrid))
   101  	})
   102  	blk6 := h.cutBlockAndCommitLegacy()
   103  
   104  	// blk7 contains one data txs
   105  	txdata7 := h.simulateDataTx("txid7", func(s *simulator) {
   106  		s.setState("cc1", "key1", d.sampleVal("value13", lgrid))
   107  		s.DeleteState("cc1", "key2")
   108  		s.setPvtdata("cc1", "coll1", "key3", d.sampleVal("value14", lgrid))
   109  		s.DeletePrivateData("cc1", "coll1", "key4")
   110  	})
   111  	h.simulatedTrans = nil
   112  
   113  	// blk8 contains one data txs that should be marked as invalid because of mvcc conflict with tx in blk7
   114  	txdata8 := h.simulateDataTx("txid8", func(s *simulator) {
   115  		s.getState("cc1", "key1")
   116  		s.setState("cc1", "key1", d.sampleVal("value15", lgrid))
   117  	})
   118  	blk7 := h.committer.cutBlockAndCommitLegacy([]*txAndPvtdata{txdata7}, nil)
   119  	blk8 := h.cutBlockAndCommitLegacy()
   120  
   121  	d.submittedData.recordSubmittedBlks(lgrid,
   122  		blk1, blk2, blk3, blk4, blk5, blk6, blk7, blk8)
   123  	d.submittedData.recordSubmittedTxs(lgrid,
   124  		txdeploy1, txdeploy2, txdata1, txdata2, txupgrade1, txupgrade2,
   125  		txdata3, txdata4, txupgrade3, txupgrade4, txdata5, txdata6, txdata7, txdata8)
   126  }
   127  
   128  func (d *sampleDataHelper) verifyLedgerContent(h *testhelper) {
   129  	d.verifyState(h)
   130  	d.verifyConfigHistory(h)
   131  	d.verifyBlockAndPvtdata(h)
   132  	d.verifyGetTransactionByID(h)
   133  	// TODO: add verifyHistory() -- FAB-15733
   134  
   135  	// the submitted data could not be available if the test ledger is loaded from disk in a fresh run
   136  	// (e.g., a backup of a test lesger from a previous fabric version)
   137  	if len(d.submittedData) != 0 {
   138  		d.t.Log("Verifying using submitted data")
   139  		d.verifyBlockAndPvtdataUsingSubmittedData(h)
   140  		d.verifyGetTransactionByIDUsingSubmittedData(h)
   141  	} else {
   142  		d.t.Log("Skipping verifying using submitted data")
   143  	}
   144  }
   145  
   146  func (d *sampleDataHelper) verifyState(h *testhelper) {
   147  	lgrid := h.lgrid
   148  	h.verifyPubState("cc1", "key1", d.sampleVal("value13", lgrid))
   149  	h.verifyPubState("cc1", "key2", "")
   150  	h.verifyPvtState("cc1", "coll1", "key3", d.sampleVal("value14", lgrid))
   151  	h.verifyPvtState("cc1", "coll1", "key4", "")
   152  	h.verifyPvtState("cc1", "coll2", "key3", d.sampleVal("value09", lgrid))
   153  	h.verifyPvtState("cc1", "coll2", "key4", d.sampleVal("value10", lgrid))
   154  
   155  	h.verifyPubState("cc2", "key1", d.sampleVal("value03", lgrid))
   156  	h.verifyPubState("cc2", "key2", d.sampleVal("value04", lgrid))
   157  	h.verifyPvtState("cc2", "coll1", "key3", d.sampleVal("value07", lgrid))
   158  	h.verifyPvtState("cc2", "coll1", "key4", d.sampleVal("value08", lgrid))
   159  	h.verifyPvtState("cc2", "coll2", "key3", d.sampleVal("value11", lgrid))
   160  	h.verifyPvtState("cc2", "coll2", "key4", d.sampleVal("value12", lgrid))
   161  }
   162  
   163  func (d *sampleDataHelper) verifyConfigHistory(h *testhelper) {
   164  	lgrid := h.lgrid
   165  	h.verifyMostRecentCollectionConfigBelow(10, "cc1",
   166  		&expectedCollConfInfo{5, d.sampleCollConf2(lgrid, "cc1")})
   167  
   168  	h.verifyMostRecentCollectionConfigBelow(5, "cc1",
   169  		&expectedCollConfInfo{3, d.sampleCollConf1(lgrid, "cc1")})
   170  
   171  	h.verifyMostRecentCollectionConfigBelow(10, "cc2",
   172  		&expectedCollConfInfo{5, d.sampleCollConf2(lgrid, "cc2")})
   173  
   174  	h.verifyMostRecentCollectionConfigBelow(5, "cc2",
   175  		&expectedCollConfInfo{3, d.sampleCollConf1(lgrid, "cc2")})
   176  }
   177  
   178  func (d *sampleDataHelper) verifyBlockAndPvtdata(h *testhelper) {
   179  	lgrid := h.lgrid
   180  	h.verifyBlockAndPvtData(2, nil, func(r *retrievedBlockAndPvtdata) {
   181  		r.hasNumTx(2)
   182  		r.hasNoPvtdata()
   183  	})
   184  
   185  	h.verifyBlockAndPvtData(4, nil, func(r *retrievedBlockAndPvtdata) {
   186  		r.hasNumTx(2)
   187  		r.pvtdataShouldContain(0, "cc1", "coll1", "key3", d.sampleVal("value05", lgrid))
   188  		r.pvtdataShouldContain(1, "cc2", "coll1", "key3", d.sampleVal("value07", lgrid))
   189  	})
   190  }
   191  
   192  func (d *sampleDataHelper) verifyGetTransactionByID(h *testhelper) {
   193  	h.verifyTxValidationCode("txid7", protopeer.TxValidationCode_VALID)
   194  	h.verifyTxValidationCode("txid8", protopeer.TxValidationCode_MVCC_READ_CONFLICT)
   195  }
   196  
   197  func (d *sampleDataHelper) verifyBlockAndPvtdataUsingSubmittedData(h *testhelper) {
   198  	lgrid := h.lgrid
   199  	submittedData := d.submittedData[lgrid]
   200  	for _, submittedBlk := range submittedData.Blocks {
   201  		blkNum := submittedBlk.Block.Header.Number
   202  		if blkNum != 8 {
   203  			h.verifyBlockAndPvtDataSameAs(uint64(blkNum), submittedBlk)
   204  		} else {
   205  			h.verifyBlockAndPvtData(uint64(8), nil, func(r *retrievedBlockAndPvtdata) {
   206  				r.sameBlockHeaderAndData(submittedBlk.Block)
   207  				r.containsValidationCode(0, protopeer.TxValidationCode_MVCC_READ_CONFLICT)
   208  			})
   209  		}
   210  	}
   211  }
   212  
   213  func (d *sampleDataHelper) verifyGetTransactionByIDUsingSubmittedData(h *testhelper) {
   214  	lgrid := h.lgrid
   215  	for _, submittedTx := range d.submittedData[lgrid].Txs {
   216  		expectedValidationCode := protopeer.TxValidationCode_VALID
   217  		if submittedTx.Txid == "txid8" {
   218  			expectedValidationCode = protopeer.TxValidationCode_MVCC_READ_CONFLICT
   219  		}
   220  		h.verifyGetTransactionByID(submittedTx.Txid,
   221  			&protopeer.ProcessedTransaction{TransactionEnvelope: submittedTx.Envelope, ValidationCode: int32(expectedValidationCode)})
   222  	}
   223  }
   224  
   225  func (d *sampleDataHelper) sampleVal(val, ledgerid string) string {
   226  	return fmt.Sprintf("%s:%s", val, ledgerid)
   227  }
   228  
   229  func (d *sampleDataHelper) sampleCollConf1(ledgerid, ccName string) []*collConf {
   230  	return []*collConf{
   231  		{name: "coll1", members: []string{"org1", "org2"}},
   232  		{name: ledgerid, members: []string{"org1", "org2"}},
   233  		{name: ccName, members: []string{"org1", "org2"}},
   234  	}
   235  }
   236  
   237  func (d *sampleDataHelper) sampleCollConf2(ledgerid string, ccName string) []*collConf {
   238  	return []*collConf{
   239  		{name: "coll1", members: []string{"org1", "org2"}},
   240  		{name: "coll2", members: []string{"org1", "org2"}},
   241  		{name: ledgerid, members: []string{"org1", "org2"}},
   242  		{name: ccName, members: []string{"org1", "org2"}},
   243  	}
   244  }