Skip to content

Commit 7456e0f

Browse files
committed
[FAB-10070] Improve State Validator UT & a fix
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 <cendhu@gmail.com>
1 parent 9e9090e commit 7456e0f

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

core/ledger/kvledger/txmgmt/validator/valimpl/helper_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ import (
1212

1313
"github.com/hyperledger/fabric/common/ledger/testutil"
1414
"github.com/hyperledger/fabric/common/util"
15+
"github.com/hyperledger/fabric/core/ledger"
16+
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/privacyenabledstate"
17+
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
18+
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/validator/valinternal"
19+
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
1520
lutils "github.com/hyperledger/fabric/core/ledger/util"
1621
"github.com/hyperledger/fabric/protos/common"
1722
"github.com/hyperledger/fabric/protos/peer"
@@ -20,6 +25,129 @@ import (
2025
"github.com/stretchr/testify/assert"
2126
)
2227

28+
func getPubAndPvtSimulationResults(t *testing.T, key string) *ledger.TxSimulationResults {
29+
rwSetBuilder := rwsetutil.NewRWSetBuilder()
30+
// public rws ns1 + ns2
31+
rwSetBuilder.AddToReadSet("ns1", key, version.NewHeight(1, 1))
32+
rwSetBuilder.AddToReadSet("ns2", key, version.NewHeight(1, 1))
33+
rwSetBuilder.AddToWriteSet("ns2", key, []byte("ns2-key1-value"))
34+
35+
// pvt rwset ns1
36+
rwSetBuilder.AddToHashedReadSet("ns1", "coll1", key, version.NewHeight(1, 1))
37+
rwSetBuilder.AddToHashedReadSet("ns1", "coll2", key, version.NewHeight(1, 1))
38+
rwSetBuilder.AddToPvtAndHashedWriteSet("ns1", "coll2", key, []byte("pvt-ns1-coll2-key1-value"))
39+
40+
// pvt rwset ns2
41+
rwSetBuilder.AddToHashedReadSet("ns2", "coll1", key, version.NewHeight(1, 1))
42+
rwSetBuilder.AddToHashedReadSet("ns2", "coll2", key, version.NewHeight(1, 1))
43+
rwSetBuilder.AddToPvtAndHashedWriteSet("ns2", "coll2", key, []byte("pvt-ns2-coll2-key1-value"))
44+
rwSetBuilder.AddToPvtAndHashedWriteSet("ns2", "coll3", key, nil)
45+
46+
rwSetBuilder.AddToHashedReadSet("ns3", "coll1", key, version.NewHeight(1, 1))
47+
48+
pubAndPvtSimulationResults, err := rwSetBuilder.GetTxSimulationResults()
49+
if err != nil {
50+
t.Fatalf("ConstructSimulationResultsWithPvtData failed while getting simulation results, err %s", err)
51+
}
52+
53+
return pubAndPvtSimulationResults
54+
}
55+
56+
func TestValidateAndPreparePvtBatch(t *testing.T) {
57+
pubSimulationResults := [][]byte{}
58+
pvtDataMap := make(map[uint64]*ledger.TxPvtData)
59+
60+
txids := []string{"tx1", "tx2", "tx3"}
61+
62+
// 1. Construct a block with three transactions and pre
63+
// process the block by calling preprocessProtoBlock()
64+
// and get a preprocessedBlock.
65+
66+
// Tx 1
67+
// Get simulation results for tx1
68+
tx1SimulationResults := getPubAndPvtSimulationResults(t, "key1")
69+
res, err := tx1SimulationResults.GetPubSimulationBytes()
70+
assert.NoError(t, err)
71+
72+
// Add tx1 public rwset to the set of results
73+
pubSimulationResults = append(pubSimulationResults, res)
74+
75+
// Add tx1 private rwset to the private data map
76+
tx1PvtData := &ledger.TxPvtData{0, tx1SimulationResults.PvtSimulationResults}
77+
pvtDataMap[uint64(0)] = tx1PvtData
78+
79+
// Tx 2
80+
// Get simulation results for tx2
81+
tx2SimulationResults := getPubAndPvtSimulationResults(t, "key2")
82+
res, err = tx2SimulationResults.GetPubSimulationBytes()
83+
assert.NoError(t, err)
84+
85+
// Add tx2 public rwset to the set of results
86+
pubSimulationResults = append(pubSimulationResults, res)
87+
88+
// As tx2 private rwset does not belong to a collection owned by the current peer,
89+
// the private rwset is not added to the private data map
90+
91+
// Tx 3
92+
// Get simulation results for tx3
93+
tx3SimulationResults := getPubAndPvtSimulationResults(t, "key3")
94+
res, err = tx3SimulationResults.GetPubSimulationBytes()
95+
assert.NoError(t, err)
96+
97+
// Add tx3 public rwset to the set of results
98+
pubSimulationResults = append(pubSimulationResults, res)
99+
100+
// Add tx3 private rwset to the private data map
101+
tx3PvtData := &ledger.TxPvtData{2, tx3SimulationResults.PvtSimulationResults}
102+
pvtDataMap[uint64(2)] = tx3PvtData
103+
104+
// Construct a block using all three transactions' simulation results
105+
block := testutil.ConstructBlockWithTxid(t, 10, testutil.ConstructRandomBytes(t, 32), pubSimulationResults, txids, false)
106+
107+
// Construct the expected preprocessed block from preprocessProtoBlock()
108+
expectedPerProcessedBlock := &valinternal.Block{Num: 10}
109+
tx1TxRWSet, err := rwsetutil.TxRwSetFromProtoMsg(tx1SimulationResults.PubSimulationResults)
110+
assert.NoError(t, err)
111+
expectedPerProcessedBlock.Txs = append(expectedPerProcessedBlock.Txs, &valinternal.Transaction{IndexInBlock: 0, ID: "tx1", RWSet: tx1TxRWSet})
112+
113+
tx2TxRWSet, err := rwsetutil.TxRwSetFromProtoMsg(tx2SimulationResults.PubSimulationResults)
114+
assert.NoError(t, err)
115+
expectedPerProcessedBlock.Txs = append(expectedPerProcessedBlock.Txs, &valinternal.Transaction{IndexInBlock: 1, ID: "tx2", RWSet: tx2TxRWSet})
116+
117+
tx3TxRWSet, err := rwsetutil.TxRwSetFromProtoMsg(tx3SimulationResults.PubSimulationResults)
118+
assert.NoError(t, err)
119+
expectedPerProcessedBlock.Txs = append(expectedPerProcessedBlock.Txs, &valinternal.Transaction{IndexInBlock: 2, ID: "tx3", RWSet: tx3TxRWSet})
120+
121+
actualPreProcessedBlock, err := preprocessProtoBlock(nil, block, false)
122+
assert.NoError(t, err)
123+
assert.Equal(t, expectedPerProcessedBlock, actualPreProcessedBlock)
124+
125+
// 2. Assuming that MVCC validation is performed on the preprocessedBlock, set the appropriate validation code
126+
// for each transaction and then call validateAndPreparePvtBatch() to get a validated private update batch.
127+
// Here, validate refers to comparison of hash of pvtRWSet in public rwset with the actual hash of pvtRWSet)
128+
129+
// Set validation code for all three transactions. One of the three transaction is marked invalid
130+
mvccValidatedBlock := actualPreProcessedBlock
131+
mvccValidatedBlock.Txs[0].ValidationCode = peer.TxValidationCode_VALID
132+
mvccValidatedBlock.Txs[1].ValidationCode = peer.TxValidationCode_VALID
133+
mvccValidatedBlock.Txs[2].ValidationCode = peer.TxValidationCode_INVALID_OTHER_REASON
134+
135+
// Construct the expected private updates
136+
expectedPvtUpdates := privacyenabledstate.NewPvtUpdateBatch()
137+
tx1TxPvtRWSet, err := rwsetutil.TxPvtRwSetFromProtoMsg(tx1SimulationResults.PvtSimulationResults)
138+
assert.NoError(t, err)
139+
addPvtRWSetToPvtUpdateBatch(tx1TxPvtRWSet, expectedPvtUpdates, version.NewHeight(uint64(10), uint64(0)))
140+
141+
actualPvtUpdates, err := validateAndPreparePvtBatch(mvccValidatedBlock, pvtDataMap)
142+
assert.NoError(t, err)
143+
assert.Equal(t, expectedPvtUpdates, actualPvtUpdates)
144+
145+
expectedtxsFilter := []uint8{uint8(peer.TxValidationCode_VALID), uint8(peer.TxValidationCode_VALID), uint8(peer.TxValidationCode_INVALID_OTHER_REASON)}
146+
147+
postprocessProtoBlock(block, mvccValidatedBlock)
148+
assert.Equal(t, expectedtxsFilter, block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
149+
}
150+
23151
func TestPreprocessProtoBlock(t *testing.T) {
24152

25153
// good block

core/ledger/kvledger/txmgmt/validator/valinternal/val_internal.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ func (t *Transaction) RetrieveHash(ns string, coll string) []byte {
6969
return nil
7070
}
7171
for _, nsData := range t.RWSet.NsRwSets {
72+
if nsData.NameSpace != ns {
73+
continue
74+
}
75+
7276
for _, collData := range nsData.CollHashedRwSets {
7377
if collData.CollectionName == coll {
7478
return collData.PvtRwSetHash

0 commit comments

Comments
 (0)