github.com/tenywen/fabric@v1.0.0-beta.0.20170620030522-a5b1ed380643/core/ledger/kvledger/txmgmt/validator/statebasedval/state_based_validator_test.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package statebasedval 18 19 import ( 20 "os" 21 "testing" 22 23 "github.com/hyperledger/fabric/common/ledger/testutil" 24 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil" 25 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb" 26 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb/stateleveldb" 27 "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" 28 "github.com/hyperledger/fabric/core/ledger/util" 29 "github.com/hyperledger/fabric/protos/common" 30 "github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset" 31 "github.com/hyperledger/fabric/protos/peer" 32 "github.com/spf13/viper" 33 ) 34 35 func TestMain(m *testing.M) { 36 viper.Set("peer.fileSystemPath", "/tmp/fabric/ledgertests/kvledger/txmgmt/validator/statebasedval") 37 os.Exit(m.Run()) 38 } 39 40 func TestValidator(t *testing.T) { 41 testDBEnv := stateleveldb.NewTestVDBEnv(t) 42 defer testDBEnv.Cleanup() 43 44 db, err := testDBEnv.DBProvider.GetDBHandle("TestDB") 45 testutil.AssertNoError(t, err, "") 46 47 //populate db with initial data 48 batch := statedb.NewUpdateBatch() 49 batch.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 0)) 50 batch.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 1)) 51 batch.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 2)) 52 batch.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 3)) 53 batch.Put("ns1", "key5", []byte("value5"), version.NewHeight(1, 4)) 54 db.ApplyUpdates(batch, version.NewHeight(1, 4)) 55 56 validator := NewValidator(db) 57 58 //rwset1 should be valid 59 rwsetBuilder1 := rwsetutil.NewRWSetBuilder() 60 rwsetBuilder1.AddToReadSet("ns1", "key1", version.NewHeight(1, 0)) 61 rwsetBuilder1.AddToReadSet("ns2", "key2", nil) 62 checkValidation(t, validator, []*rwsetutil.TxRwSet{rwsetBuilder1.GetTxReadWriteSet()}, nil, []int{}) 63 64 //rwset2 should not be valid 65 rwsetBuilder2 := rwsetutil.NewRWSetBuilder() 66 rwsetBuilder2.AddToReadSet("ns1", "key1", version.NewHeight(1, 1)) 67 checkValidation(t, validator, []*rwsetutil.TxRwSet{rwsetBuilder2.GetTxReadWriteSet()}, nil, []int{0}) 68 69 //rwset3 should not be valid 70 rwsetBuilder3 := rwsetutil.NewRWSetBuilder() 71 rwsetBuilder3.AddToReadSet("ns1", "key1", nil) 72 checkValidation(t, validator, []*rwsetutil.TxRwSet{rwsetBuilder3.GetTxReadWriteSet()}, nil, []int{0}) 73 74 // rwset4 and rwset5 within same block - rwset4 should be valid and makes rwset5 as invalid 75 rwsetBuilder4 := rwsetutil.NewRWSetBuilder() 76 rwsetBuilder4.AddToReadSet("ns1", "key1", version.NewHeight(1, 0)) 77 rwsetBuilder4.AddToWriteSet("ns1", "key1", []byte("value1_new")) 78 79 rwsetBuilder5 := rwsetutil.NewRWSetBuilder() 80 rwsetBuilder5.AddToReadSet("ns1", "key1", version.NewHeight(1, 0)) 81 checkValidation(t, validator, 82 []*rwsetutil.TxRwSet{rwsetBuilder4.GetTxReadWriteSet(), rwsetBuilder5.GetTxReadWriteSet()}, nil, []int{1}) 83 } 84 85 func TestValidatorSkipInvalidTxs(t *testing.T) { 86 testDBEnv := stateleveldb.NewTestVDBEnv(t) 87 defer testDBEnv.Cleanup() 88 db, err := testDBEnv.DBProvider.GetDBHandle("TestDB") 89 testutil.AssertNoError(t, err, "") 90 validator := NewValidator(db) 91 92 rwsetBuilder1 := rwsetutil.NewRWSetBuilder() 93 rwsetBuilder1.AddToWriteSet("ns1", "key1", []byte("value1")) 94 rwsetBuilder2 := rwsetutil.NewRWSetBuilder() 95 rwsetBuilder2.AddToWriteSet("ns1", "key2", []byte("value2")) 96 rwsetBuilder3 := rwsetutil.NewRWSetBuilder() 97 rwsetBuilder3.AddToWriteSet("ns1", "key3", []byte("value3")) 98 flags := util.NewTxValidationFlags(4) 99 flags.SetFlag(1, peer.TxValidationCode_BAD_CREATOR_SIGNATURE) 100 checkValidation(t, validator, 101 []*rwsetutil.TxRwSet{rwsetBuilder1.GetTxReadWriteSet(), rwsetBuilder2.GetTxReadWriteSet(), rwsetBuilder3.GetTxReadWriteSet()}, 102 flags, []int{1}) 103 } 104 105 func TestPhantomValidation(t *testing.T) { 106 testDBEnv := stateleveldb.NewTestVDBEnv(t) 107 defer testDBEnv.Cleanup() 108 109 db, err := testDBEnv.DBProvider.GetDBHandle("TestDB") 110 testutil.AssertNoError(t, err, "") 111 112 //populate db with initial data 113 batch := statedb.NewUpdateBatch() 114 batch.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 0)) 115 batch.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 1)) 116 batch.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 2)) 117 batch.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 3)) 118 batch.Put("ns1", "key5", []byte("value5"), version.NewHeight(1, 4)) 119 db.ApplyUpdates(batch, version.NewHeight(1, 4)) 120 121 validator := NewValidator(db) 122 123 //rwset1 should be valid 124 rwsetBuilder1 := rwsetutil.NewRWSetBuilder() 125 rqi1 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: true} 126 rqi1.SetRawReads([]*kvrwset.KVRead{ 127 rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)), 128 rwsetutil.NewKVRead("key3", version.NewHeight(1, 2))}) 129 rwsetBuilder1.AddToRangeQuerySet("ns1", rqi1) 130 checkValidation(t, validator, []*rwsetutil.TxRwSet{rwsetBuilder1.GetTxReadWriteSet()}, nil, []int{}) 131 132 //rwset2 should not be valid - Version of key4 changed 133 rwsetBuilder2 := rwsetutil.NewRWSetBuilder() 134 rqi2 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false} 135 rqi2.SetRawReads([]*kvrwset.KVRead{ 136 rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)), 137 rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)), 138 rwsetutil.NewKVRead("key4", version.NewHeight(1, 2))}) 139 rwsetBuilder2.AddToRangeQuerySet("ns1", rqi2) 140 checkValidation(t, validator, []*rwsetutil.TxRwSet{rwsetBuilder2.GetTxReadWriteSet()}, nil, []int{0}) 141 142 //rwset3 should not be valid - simulate key3 got committed to db 143 rwsetBuilder3 := rwsetutil.NewRWSetBuilder() 144 rqi3 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false} 145 rqi3.SetRawReads([]*kvrwset.KVRead{ 146 rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)), 147 rwsetutil.NewKVRead("key4", version.NewHeight(1, 3))}) 148 rwsetBuilder3.AddToRangeQuerySet("ns1", rqi3) 149 checkValidation(t, validator, []*rwsetutil.TxRwSet{rwsetBuilder3.GetTxReadWriteSet()}, nil, []int{0}) 150 151 // //Remove a key in rwset4 and rwset5 should become invalid 152 rwsetBuilder4 := rwsetutil.NewRWSetBuilder() 153 rwsetBuilder4.AddToWriteSet("ns1", "key3", nil) 154 rwsetBuilder5 := rwsetutil.NewRWSetBuilder() 155 rqi5 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false} 156 rqi5.SetRawReads([]*kvrwset.KVRead{ 157 rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)), 158 rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)), 159 rwsetutil.NewKVRead("key4", version.NewHeight(1, 3))}) 160 rwsetBuilder5.AddToRangeQuerySet("ns1", rqi5) 161 checkValidation(t, validator, []*rwsetutil.TxRwSet{ 162 rwsetBuilder4.GetTxReadWriteSet(), rwsetBuilder5.GetTxReadWriteSet()}, nil, []int{1}) 163 164 //Add a key in rwset6 and rwset7 should become invalid 165 rwsetBuilder6 := rwsetutil.NewRWSetBuilder() 166 rwsetBuilder6.AddToWriteSet("ns1", "key2_1", []byte("value2_1")) 167 168 rwsetBuilder7 := rwsetutil.NewRWSetBuilder() 169 rqi7 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key4", ItrExhausted: false} 170 rqi7.SetRawReads([]*kvrwset.KVRead{ 171 rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)), 172 rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)), 173 rwsetutil.NewKVRead("key4", version.NewHeight(1, 3))}) 174 rwsetBuilder7.AddToRangeQuerySet("ns1", rqi7) 175 checkValidation(t, validator, []*rwsetutil.TxRwSet{ 176 rwsetBuilder6.GetTxReadWriteSet(), rwsetBuilder7.GetTxReadWriteSet()}, nil, []int{1}) 177 } 178 179 func TestPhantomHashBasedValidation(t *testing.T) { 180 testDBEnv := stateleveldb.NewTestVDBEnv(t) 181 defer testDBEnv.Cleanup() 182 183 db, err := testDBEnv.DBProvider.GetDBHandle("TestDB") 184 testutil.AssertNoError(t, err, "") 185 186 //populate db with initial data 187 batch := statedb.NewUpdateBatch() 188 batch.Put("ns1", "key1", []byte("value1"), version.NewHeight(1, 0)) 189 batch.Put("ns1", "key2", []byte("value2"), version.NewHeight(1, 1)) 190 batch.Put("ns1", "key3", []byte("value3"), version.NewHeight(1, 2)) 191 batch.Put("ns1", "key4", []byte("value4"), version.NewHeight(1, 3)) 192 batch.Put("ns1", "key5", []byte("value5"), version.NewHeight(1, 4)) 193 batch.Put("ns1", "key6", []byte("value6"), version.NewHeight(1, 5)) 194 batch.Put("ns1", "key7", []byte("value7"), version.NewHeight(1, 6)) 195 batch.Put("ns1", "key8", []byte("value8"), version.NewHeight(1, 7)) 196 batch.Put("ns1", "key9", []byte("value9"), version.NewHeight(1, 8)) 197 db.ApplyUpdates(batch, version.NewHeight(1, 8)) 198 199 validator := NewValidator(db) 200 201 rwsetBuilder1 := rwsetutil.NewRWSetBuilder() 202 rqi1 := &kvrwset.RangeQueryInfo{StartKey: "key2", EndKey: "key9", ItrExhausted: true} 203 kvReadsDuringSimulation1 := []*kvrwset.KVRead{ 204 rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)), 205 rwsetutil.NewKVRead("key3", version.NewHeight(1, 2)), 206 rwsetutil.NewKVRead("key4", version.NewHeight(1, 3)), 207 rwsetutil.NewKVRead("key5", version.NewHeight(1, 4)), 208 rwsetutil.NewKVRead("key6", version.NewHeight(1, 5)), 209 rwsetutil.NewKVRead("key7", version.NewHeight(1, 6)), 210 rwsetutil.NewKVRead("key8", version.NewHeight(1, 7)), 211 } 212 rqi1.SetMerkelSummary(buildTestHashResults(t, 2, kvReadsDuringSimulation1)) 213 rwsetBuilder1.AddToRangeQuerySet("ns1", rqi1) 214 checkValidation(t, validator, []*rwsetutil.TxRwSet{rwsetBuilder1.GetTxReadWriteSet()}, nil, []int{}) 215 216 rwsetBuilder2 := rwsetutil.NewRWSetBuilder() 217 rqi2 := &kvrwset.RangeQueryInfo{StartKey: "key1", EndKey: "key9", ItrExhausted: false} 218 kvReadsDuringSimulation2 := []*kvrwset.KVRead{ 219 rwsetutil.NewKVRead("key1", version.NewHeight(1, 0)), 220 rwsetutil.NewKVRead("key2", version.NewHeight(1, 1)), 221 rwsetutil.NewKVRead("key3", version.NewHeight(1, 1)), 222 rwsetutil.NewKVRead("key4", version.NewHeight(1, 3)), 223 rwsetutil.NewKVRead("key5", version.NewHeight(1, 4)), 224 rwsetutil.NewKVRead("key6", version.NewHeight(1, 5)), 225 rwsetutil.NewKVRead("key7", version.NewHeight(1, 6)), 226 rwsetutil.NewKVRead("key8", version.NewHeight(1, 7)), 227 rwsetutil.NewKVRead("key9", version.NewHeight(1, 8)), 228 } 229 rqi2.SetMerkelSummary(buildTestHashResults(t, 2, kvReadsDuringSimulation2)) 230 rwsetBuilder2.AddToRangeQuerySet("ns1", rqi2) 231 checkValidation(t, validator, []*rwsetutil.TxRwSet{rwsetBuilder2.GetTxReadWriteSet()}, nil, []int{0}) 232 } 233 234 func checkValidation(t *testing.T, validator *Validator, rwsets []*rwsetutil.TxRwSet, 235 alreadyMarkedFlags util.TxValidationFlags, expectedInvalidTxIndexes []int) { 236 simulationResults := [][]byte{} 237 for _, txRWS := range rwsets { 238 sr, err := txRWS.ToProtoBytes() 239 testutil.AssertNoError(t, err, "") 240 simulationResults = append(simulationResults, sr) 241 } 242 block := testutil.ConstructBlock(t, 1, []byte("dummyPreviousHash"), simulationResults, false) 243 block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = alreadyMarkedFlags 244 _, err := validator.ValidateAndPrepareBatch(block, true) 245 txsFltr := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 246 invalidTxs := make([]int, 0) 247 for i := 0; i < len(block.Data.Data); i++ { 248 if txsFltr.IsInvalid(i) { 249 invalidTxs = append(invalidTxs, i) 250 } 251 } 252 testutil.AssertNoError(t, err, "") 253 testutil.AssertEquals(t, len(invalidTxs), len(expectedInvalidTxIndexes)) 254 testutil.AssertContainsAll(t, invalidTxs, expectedInvalidTxIndexes) 255 } 256 257 func buildTestHashResults(t *testing.T, maxDegree int, kvReads []*kvrwset.KVRead) *kvrwset.QueryReadsMerkleSummary { 258 if len(kvReads) <= maxDegree { 259 t.Fatal("This method should be called with number of KVReads more than maxDegree; Else, hashing won't be performedrwset") 260 } 261 helper, _ := rwsetutil.NewRangeQueryResultsHelper(true, uint32(maxDegree)) 262 for _, kvRead := range kvReads { 263 helper.AddResult(kvRead) 264 } 265 _, h, err := helper.Done() 266 testutil.AssertNoError(t, err, "") 267 testutil.AssertNotNil(t, h) 268 return h 269 }