@@ -12,6 +12,11 @@ import (
12
12
13
13
"github.com/hyperledger/fabric/common/ledger/testutil"
14
14
"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"
15
20
lutils "github.com/hyperledger/fabric/core/ledger/util"
16
21
"github.com/hyperledger/fabric/protos/common"
17
22
"github.com/hyperledger/fabric/protos/peer"
@@ -20,6 +25,129 @@ import (
20
25
"github.com/stretchr/testify/assert"
21
26
)
22
27
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
+
23
151
func TestPreprocessProtoBlock (t * testing.T ) {
24
152
25
153
// good block
0 commit comments