Skip to content

Commit

Permalink
[FAB-10070] Improve State Validator UT & a fix
Browse files Browse the repository at this point in the history
The current UT coverage of kvledger/txmgmt/validator/valimpl
is only 23%. This CR would cover the helper function, i.e., helper.go.
The coverage is increased to 66% from 28% (for helper.go alone).

A minor fix to hash retrieval.

FAB-10077 would increase the coverage even further

Change-Id: I941da06f5e1c7318ce348a67e9c0d05e4c2c6203
Signed-off-by: senthil <[email protected]>
  • Loading branch information
cendhu committed May 16, 2018
1 parent 9e9090e commit 7456e0f
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 0 deletions.
128 changes: 128 additions & 0 deletions core/ledger/kvledger/txmgmt/validator/valimpl/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ import (

"github.com/hyperledger/fabric/common/ledger/testutil"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/validator/valinternal"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
lutils "github.com/hyperledger/fabric/core/ledger/util"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/peer"
Expand All @@ -20,6 +25,129 @@ import (
"github.com/stretchr/testify/assert"
)

func getPubAndPvtSimulationResults(t *testing.T, key string) *ledger.TxSimulationResults {
rwSetBuilder := rwsetutil.NewRWSetBuilder()
// public rws ns1 + ns2
rwSetBuilder.AddToReadSet("ns1", key, version.NewHeight(1, 1))
rwSetBuilder.AddToReadSet("ns2", key, version.NewHeight(1, 1))
rwSetBuilder.AddToWriteSet("ns2", key, []byte("ns2-key1-value"))

// pvt rwset ns1
rwSetBuilder.AddToHashedReadSet("ns1", "coll1", key, version.NewHeight(1, 1))
rwSetBuilder.AddToHashedReadSet("ns1", "coll2", key, version.NewHeight(1, 1))
rwSetBuilder.AddToPvtAndHashedWriteSet("ns1", "coll2", key, []byte("pvt-ns1-coll2-key1-value"))

// pvt rwset ns2
rwSetBuilder.AddToHashedReadSet("ns2", "coll1", key, version.NewHeight(1, 1))
rwSetBuilder.AddToHashedReadSet("ns2", "coll2", key, version.NewHeight(1, 1))
rwSetBuilder.AddToPvtAndHashedWriteSet("ns2", "coll2", key, []byte("pvt-ns2-coll2-key1-value"))
rwSetBuilder.AddToPvtAndHashedWriteSet("ns2", "coll3", key, nil)

rwSetBuilder.AddToHashedReadSet("ns3", "coll1", key, version.NewHeight(1, 1))

pubAndPvtSimulationResults, err := rwSetBuilder.GetTxSimulationResults()
if err != nil {
t.Fatalf("ConstructSimulationResultsWithPvtData failed while getting simulation results, err %s", err)
}

return pubAndPvtSimulationResults
}

func TestValidateAndPreparePvtBatch(t *testing.T) {
pubSimulationResults := [][]byte{}
pvtDataMap := make(map[uint64]*ledger.TxPvtData)

txids := []string{"tx1", "tx2", "tx3"}

// 1. Construct a block with three transactions and pre
// process the block by calling preprocessProtoBlock()
// and get a preprocessedBlock.

// Tx 1
// Get simulation results for tx1
tx1SimulationResults := getPubAndPvtSimulationResults(t, "key1")
res, err := tx1SimulationResults.GetPubSimulationBytes()
assert.NoError(t, err)

// Add tx1 public rwset to the set of results
pubSimulationResults = append(pubSimulationResults, res)

// Add tx1 private rwset to the private data map
tx1PvtData := &ledger.TxPvtData{0, tx1SimulationResults.PvtSimulationResults}
pvtDataMap[uint64(0)] = tx1PvtData

// Tx 2
// Get simulation results for tx2
tx2SimulationResults := getPubAndPvtSimulationResults(t, "key2")
res, err = tx2SimulationResults.GetPubSimulationBytes()
assert.NoError(t, err)

// Add tx2 public rwset to the set of results
pubSimulationResults = append(pubSimulationResults, res)

// As tx2 private rwset does not belong to a collection owned by the current peer,
// the private rwset is not added to the private data map

// Tx 3
// Get simulation results for tx3
tx3SimulationResults := getPubAndPvtSimulationResults(t, "key3")
res, err = tx3SimulationResults.GetPubSimulationBytes()
assert.NoError(t, err)

// Add tx3 public rwset to the set of results
pubSimulationResults = append(pubSimulationResults, res)

// Add tx3 private rwset to the private data map
tx3PvtData := &ledger.TxPvtData{2, tx3SimulationResults.PvtSimulationResults}
pvtDataMap[uint64(2)] = tx3PvtData

// Construct a block using all three transactions' simulation results
block := testutil.ConstructBlockWithTxid(t, 10, testutil.ConstructRandomBytes(t, 32), pubSimulationResults, txids, false)

// Construct the expected preprocessed block from preprocessProtoBlock()
expectedPerProcessedBlock := &valinternal.Block{Num: 10}
tx1TxRWSet, err := rwsetutil.TxRwSetFromProtoMsg(tx1SimulationResults.PubSimulationResults)
assert.NoError(t, err)
expectedPerProcessedBlock.Txs = append(expectedPerProcessedBlock.Txs, &valinternal.Transaction{IndexInBlock: 0, ID: "tx1", RWSet: tx1TxRWSet})

tx2TxRWSet, err := rwsetutil.TxRwSetFromProtoMsg(tx2SimulationResults.PubSimulationResults)
assert.NoError(t, err)
expectedPerProcessedBlock.Txs = append(expectedPerProcessedBlock.Txs, &valinternal.Transaction{IndexInBlock: 1, ID: "tx2", RWSet: tx2TxRWSet})

tx3TxRWSet, err := rwsetutil.TxRwSetFromProtoMsg(tx3SimulationResults.PubSimulationResults)
assert.NoError(t, err)
expectedPerProcessedBlock.Txs = append(expectedPerProcessedBlock.Txs, &valinternal.Transaction{IndexInBlock: 2, ID: "tx3", RWSet: tx3TxRWSet})

actualPreProcessedBlock, err := preprocessProtoBlock(nil, block, false)
assert.NoError(t, err)
assert.Equal(t, expectedPerProcessedBlock, actualPreProcessedBlock)

// 2. Assuming that MVCC validation is performed on the preprocessedBlock, set the appropriate validation code
// for each transaction and then call validateAndPreparePvtBatch() to get a validated private update batch.
// Here, validate refers to comparison of hash of pvtRWSet in public rwset with the actual hash of pvtRWSet)

// Set validation code for all three transactions. One of the three transaction is marked invalid
mvccValidatedBlock := actualPreProcessedBlock
mvccValidatedBlock.Txs[0].ValidationCode = peer.TxValidationCode_VALID
mvccValidatedBlock.Txs[1].ValidationCode = peer.TxValidationCode_VALID
mvccValidatedBlock.Txs[2].ValidationCode = peer.TxValidationCode_INVALID_OTHER_REASON

// Construct the expected private updates
expectedPvtUpdates := privacyenabledstate.NewPvtUpdateBatch()
tx1TxPvtRWSet, err := rwsetutil.TxPvtRwSetFromProtoMsg(tx1SimulationResults.PvtSimulationResults)
assert.NoError(t, err)
addPvtRWSetToPvtUpdateBatch(tx1TxPvtRWSet, expectedPvtUpdates, version.NewHeight(uint64(10), uint64(0)))

actualPvtUpdates, err := validateAndPreparePvtBatch(mvccValidatedBlock, pvtDataMap)
assert.NoError(t, err)
assert.Equal(t, expectedPvtUpdates, actualPvtUpdates)

expectedtxsFilter := []uint8{uint8(peer.TxValidationCode_VALID), uint8(peer.TxValidationCode_VALID), uint8(peer.TxValidationCode_INVALID_OTHER_REASON)}

postprocessProtoBlock(block, mvccValidatedBlock)
assert.Equal(t, expectedtxsFilter, block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
}

func TestPreprocessProtoBlock(t *testing.T) {

// good block
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ func (t *Transaction) RetrieveHash(ns string, coll string) []byte {
return nil
}
for _, nsData := range t.RWSet.NsRwSets {
if nsData.NameSpace != ns {
continue
}

for _, collData := range nsData.CollHashedRwSets {
if collData.CollectionName == coll {
return collData.PvtRwSetHash
Expand Down

0 comments on commit 7456e0f

Please sign in to comment.