github.com/kaituanwang/hyperledger@v2.0.1+incompatible/core/ledger/kvledger/history/db_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 SPDX-License-Identifier: Apache-2.0 4 */ 5 6 package history 7 8 import ( 9 "bytes" 10 "fmt" 11 "os" 12 "strconv" 13 "testing" 14 15 "github.com/hyperledger/fabric-protos-go/common" 16 "github.com/hyperledger/fabric-protos-go/ledger/queryresult" 17 "github.com/hyperledger/fabric-protos-go/peer" 18 configtxtest "github.com/hyperledger/fabric/common/configtx/test" 19 "github.com/hyperledger/fabric/common/flogging" 20 "github.com/hyperledger/fabric/common/ledger/testutil" 21 util2 "github.com/hyperledger/fabric/common/util" 22 "github.com/hyperledger/fabric/core/ledger" 23 "github.com/hyperledger/fabric/core/ledger/util" 24 "github.com/stretchr/testify/assert" 25 ) 26 27 func TestMain(m *testing.M) { 28 flogging.ActivateSpec("leveldbhelper,history=debug") 29 os.Exit(m.Run()) 30 } 31 32 //TestSavepoint tests that save points get written after each block and get returned via GetBlockNumfromSavepoint 33 func TestSavepoint(t *testing.T) { 34 env := newTestHistoryEnv(t) 35 defer env.cleanup() 36 37 // read the savepoint, it should not exist and should return nil Height object 38 savepoint, err := env.testHistoryDB.GetLastSavepoint() 39 assert.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()") 40 assert.Nil(t, savepoint) 41 42 // ShouldRecover should return true when no savepoint is found and recovery from block 0 43 status, blockNum, err := env.testHistoryDB.ShouldRecover(0) 44 assert.NoError(t, err, "Error upon historyDatabase.ShouldRecover()") 45 assert.True(t, status) 46 assert.Equal(t, uint64(0), blockNum) 47 48 bg, gb := testutil.NewBlockGenerator(t, "testLedger", false) 49 assert.NoError(t, env.testHistoryDB.Commit(gb)) 50 // read the savepoint, it should now exist and return a Height object with BlockNum 0 51 savepoint, err = env.testHistoryDB.GetLastSavepoint() 52 assert.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()") 53 assert.Equal(t, uint64(0), savepoint.BlockNum) 54 55 // create the next block (block 1) 56 txid := util2.GenerateUUID() 57 simulator, _ := env.txmgr.NewTxSimulator(txid) 58 simulator.SetState("ns1", "key1", []byte("value1")) 59 simulator.Done() 60 simRes, _ := simulator.GetTxSimulationResults() 61 pubSimResBytes, _ := simRes.GetPubSimulationBytes() 62 block1 := bg.NextBlock([][]byte{pubSimResBytes}) 63 assert.NoError(t, env.testHistoryDB.Commit(block1)) 64 savepoint, err = env.testHistoryDB.GetLastSavepoint() 65 assert.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()") 66 assert.Equal(t, uint64(1), savepoint.BlockNum) 67 68 // Should Recover should return false 69 status, blockNum, err = env.testHistoryDB.ShouldRecover(1) 70 assert.NoError(t, err, "Error upon historyDatabase.ShouldRecover()") 71 assert.False(t, status) 72 assert.Equal(t, uint64(2), blockNum) 73 74 // create the next block (block 2) 75 txid = util2.GenerateUUID() 76 simulator, _ = env.txmgr.NewTxSimulator(txid) 77 simulator.SetState("ns1", "key1", []byte("value2")) 78 simulator.Done() 79 simRes, _ = simulator.GetTxSimulationResults() 80 pubSimResBytes, _ = simRes.GetPubSimulationBytes() 81 block2 := bg.NextBlock([][]byte{pubSimResBytes}) 82 83 // assume that the peer failed to commit this block to historyDB and is being recovered now 84 env.testHistoryDB.CommitLostBlock(&ledger.BlockAndPvtData{Block: block2}) 85 savepoint, err = env.testHistoryDB.GetLastSavepoint() 86 assert.NoError(t, err, "Error upon historyDatabase.GetLastSavepoint()") 87 assert.Equal(t, uint64(2), savepoint.BlockNum) 88 89 //Pass high blockNum, ShouldRecover should return true with 3 as blocknum to recover from 90 status, blockNum, err = env.testHistoryDB.ShouldRecover(10) 91 assert.NoError(t, err, "Error upon historyDatabase.ShouldRecover()") 92 assert.True(t, status) 93 assert.Equal(t, uint64(3), blockNum) 94 } 95 96 func TestHistory(t *testing.T) { 97 env := newTestHistoryEnv(t) 98 defer env.cleanup() 99 provider := env.testBlockStorageEnv.provider 100 ledger1id := "ledger1" 101 store1, err := provider.OpenBlockStore(ledger1id) 102 assert.NoError(t, err, "Error upon provider.OpenBlockStore()") 103 defer store1.Shutdown() 104 assert.Equal(t, "history", env.testHistoryDB.Name()) 105 106 bg, gb := testutil.NewBlockGenerator(t, ledger1id, false) 107 assert.NoError(t, store1.AddBlock(gb)) 108 assert.NoError(t, env.testHistoryDB.Commit(gb)) 109 110 //block1 111 txid := util2.GenerateUUID() 112 simulator, _ := env.txmgr.NewTxSimulator(txid) 113 value1 := []byte("value1") 114 simulator.SetState("ns1", "key7", value1) 115 simulator.Done() 116 simRes, _ := simulator.GetTxSimulationResults() 117 pubSimResBytes, _ := simRes.GetPubSimulationBytes() 118 block1 := bg.NextBlock([][]byte{pubSimResBytes}) 119 err = store1.AddBlock(block1) 120 assert.NoError(t, err) 121 err = env.testHistoryDB.Commit(block1) 122 assert.NoError(t, err) 123 124 //block2 tran1 125 simulationResults := [][]byte{} 126 txid = util2.GenerateUUID() 127 simulator, _ = env.txmgr.NewTxSimulator(txid) 128 value2 := []byte("value2") 129 simulator.SetState("ns1", "key7", value2) 130 simulator.Done() 131 simRes, _ = simulator.GetTxSimulationResults() 132 pubSimResBytes, _ = simRes.GetPubSimulationBytes() 133 simulationResults = append(simulationResults, pubSimResBytes) 134 //block2 tran2 135 txid2 := util2.GenerateUUID() 136 simulator2, _ := env.txmgr.NewTxSimulator(txid2) 137 value3 := []byte("value3") 138 simulator2.SetState("ns1", "key7", value3) 139 simulator2.Done() 140 simRes2, _ := simulator2.GetTxSimulationResults() 141 pubSimResBytes2, _ := simRes2.GetPubSimulationBytes() 142 simulationResults = append(simulationResults, pubSimResBytes2) 143 block2 := bg.NextBlock(simulationResults) 144 err = store1.AddBlock(block2) 145 assert.NoError(t, err) 146 err = env.testHistoryDB.Commit(block2) 147 assert.NoError(t, err) 148 149 //block3 150 txid = util2.GenerateUUID() 151 simulator, _ = env.txmgr.NewTxSimulator(txid) 152 simulator.DeleteState("ns1", "key7") 153 simulator.Done() 154 simRes, _ = simulator.GetTxSimulationResults() 155 pubSimResBytes, _ = simRes.GetPubSimulationBytes() 156 block3 := bg.NextBlock([][]byte{pubSimResBytes}) 157 err = store1.AddBlock(block3) 158 assert.NoError(t, err) 159 err = env.testHistoryDB.Commit(block3) 160 assert.NoError(t, err) 161 t.Logf("Inserted all 3 blocks") 162 163 qhistory, err := env.testHistoryDB.NewQueryExecutor(store1) 164 assert.NoError(t, err, "Error upon NewQueryExecutor") 165 166 itr, err2 := qhistory.GetHistoryForKey("ns1", "key7") 167 assert.NoError(t, err2, "Error upon GetHistoryForKey()") 168 169 count := 0 170 for { 171 // iterator will return entries in the order of newest to oldest 172 kmod, _ := itr.Next() 173 if kmod == nil { 174 break 175 } 176 txid = kmod.(*queryresult.KeyModification).TxId 177 retrievedValue := kmod.(*queryresult.KeyModification).Value 178 retrievedTimestamp := kmod.(*queryresult.KeyModification).Timestamp 179 retrievedIsDelete := kmod.(*queryresult.KeyModification).IsDelete 180 t.Logf("Retrieved history record for key=key7 at TxId=%s with value %v and timestamp %v", 181 txid, retrievedValue, retrievedTimestamp) 182 count++ 183 if count != 1 { 184 // entries 2, 3, 4 are block2:tran2, block2:tran1 and block1:tran1 185 expectedValue := []byte("value" + strconv.Itoa(5-count)) 186 assert.Equal(t, expectedValue, retrievedValue) 187 assert.NotNil(t, retrievedTimestamp) 188 assert.False(t, retrievedIsDelete) 189 } else { 190 // entry 1 is block3:tran1 191 assert.Equal(t, []uint8(nil), retrievedValue) 192 assert.NotNil(t, retrievedTimestamp) 193 assert.True(t, retrievedIsDelete) 194 } 195 } 196 assert.Equal(t, 4, count) 197 } 198 199 func TestHistoryForInvalidTran(t *testing.T) { 200 env := newTestHistoryEnv(t) 201 defer env.cleanup() 202 provider := env.testBlockStorageEnv.provider 203 ledger1id := "ledger1" 204 store1, err := provider.OpenBlockStore(ledger1id) 205 assert.NoError(t, err, "Error upon provider.OpenBlockStore()") 206 defer store1.Shutdown() 207 208 bg, gb := testutil.NewBlockGenerator(t, ledger1id, false) 209 assert.NoError(t, store1.AddBlock(gb)) 210 assert.NoError(t, env.testHistoryDB.Commit(gb)) 211 212 //block1 213 txid := util2.GenerateUUID() 214 simulator, _ := env.txmgr.NewTxSimulator(txid) 215 value1 := []byte("value1") 216 simulator.SetState("ns1", "key7", value1) 217 simulator.Done() 218 simRes, _ := simulator.GetTxSimulationResults() 219 pubSimResBytes, _ := simRes.GetPubSimulationBytes() 220 block1 := bg.NextBlock([][]byte{pubSimResBytes}) 221 222 //for this invalid tran test, set the transaction to invalid 223 txsFilter := util.TxValidationFlags(block1.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) 224 txsFilter.SetFlag(0, peer.TxValidationCode_INVALID_OTHER_REASON) 225 block1.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter 226 227 err = store1.AddBlock(block1) 228 assert.NoError(t, err) 229 err = env.testHistoryDB.Commit(block1) 230 assert.NoError(t, err) 231 232 qhistory, err := env.testHistoryDB.NewQueryExecutor(store1) 233 assert.NoError(t, err, "Error upon NewQueryExecutor") 234 235 itr, err2 := qhistory.GetHistoryForKey("ns1", "key7") 236 assert.NoError(t, err2, "Error upon GetHistoryForKey()") 237 238 // test that there are no history values, since the tran was marked as invalid 239 kmod, _ := itr.Next() 240 assert.Nil(t, kmod) 241 } 242 243 //TestGenesisBlockNoError tests that Genesis blocks are ignored by history processing 244 // since we only persist history of chaincode key writes 245 func TestGenesisBlockNoError(t *testing.T) { 246 env := newTestHistoryEnv(t) 247 defer env.cleanup() 248 block, err := configtxtest.MakeGenesisBlock("test_chainid") 249 assert.NoError(t, err) 250 err = env.testHistoryDB.Commit(block) 251 assert.NoError(t, err) 252 } 253 254 // TestHistoryWithKeyContainingNilBytes tests historydb when keys contains nil bytes (FAB-11244) - 255 // which happens to be used as a separator in the composite keys that is formed for the entries in the historydb 256 func TestHistoryWithKeyContainingNilBytes(t *testing.T) { 257 env := newTestHistoryEnv(t) 258 defer env.cleanup() 259 provider := env.testBlockStorageEnv.provider 260 ledger1id := "ledger1" 261 store1, err := provider.OpenBlockStore(ledger1id) 262 assert.NoError(t, err, "Error upon provider.OpenBlockStore()") 263 defer store1.Shutdown() 264 265 bg, gb := testutil.NewBlockGenerator(t, ledger1id, false) 266 assert.NoError(t, store1.AddBlock(gb)) 267 assert.NoError(t, env.testHistoryDB.Commit(gb)) 268 269 //block1 270 txid := util2.GenerateUUID() 271 simulator, _ := env.txmgr.NewTxSimulator(txid) 272 simulator.SetState("ns1", "key", []byte("value1")) // add a key <key> that contains no nil byte 273 simulator.Done() 274 simRes, _ := simulator.GetTxSimulationResults() 275 pubSimResBytes, _ := simRes.GetPubSimulationBytes() 276 block1 := bg.NextBlock([][]byte{pubSimResBytes}) 277 err = store1.AddBlock(block1) 278 assert.NoError(t, err) 279 err = env.testHistoryDB.Commit(block1) 280 assert.NoError(t, err) 281 282 //block2 tran1 283 simulationResults := [][]byte{} 284 txid = util2.GenerateUUID() 285 simulator, _ = env.txmgr.NewTxSimulator(txid) 286 simulator.SetState("ns1", "key", []byte("value2")) // add another value for the key <key> 287 simulator.Done() 288 simRes, _ = simulator.GetTxSimulationResults() 289 pubSimResBytes, _ = simRes.GetPubSimulationBytes() 290 simulationResults = append(simulationResults, pubSimResBytes) 291 292 //block2 tran2 293 txid2 := util2.GenerateUUID() 294 simulator2, _ := env.txmgr.NewTxSimulator(txid2) 295 296 // key1 should not fall in the range 297 key1 := "\x00key\x00\x01\x01\x15" 298 simulator2.SetState("ns1", key1, []byte("dummyVal1")) 299 300 // add other keys that contain nil byte(s) - such that when a range query is formed, these keys fall in the range 301 // key2 is skipped due to tran num decoding error (decode size 21 > 8) 302 // blockNumTranNumBytes are 0x1, 0x1, 0x15, 0x0 (separator), 0x1, 0x2, 0x1, 0x1 303 key2 := "key\x00\x01\x01\x15" // \x15 is 21 304 simulator2.SetState("ns1", key2, []byte("dummyVal2")) 305 306 // key3 is skipped due to block num decoding error (decoded size 12 > 8) 307 // blockNumTranNumBytes are 0xc, 0x0 (separtor), 0x1, 0x2, 0x1, 0x1 308 key3 := "key\x00\x0c" // \x0c is 12 309 simulator2.SetState("ns1", key3, []byte("dummyVal3")) 310 311 // key4 is skipped because blockBytesConsumed (2) + tranBytesConsumed (2) != len(blockNumTranNum) (6) 312 // blockNumTranNumBytes are 0x1, 0x0 (separator), 0x1, 0x2, 0x1, 0x1 313 key4 := "key\x00\x01" 314 simulator2.SetState("ns1", key4, []byte("dummyVal4")) 315 316 // key5 is skipped due to ErrNotFoundInIndex, where history key is <ns, key\x00\x04\x01, 2, 1>, same as <ns, key, 16777474, 1>. 317 // blockNumTranNumBytes are 0x4, 0x1, 0x0 (separator), 0x1, 0x2, 0x1, 0x1 318 key5 := "key\x00\x04\x01" 319 simulator2.SetState("ns1", key5, []byte("dummyVal5")) 320 321 // commit block2 322 simulator2.Done() 323 simRes2, _ := simulator2.GetTxSimulationResults() 324 pubSimResBytes2, _ := simRes2.GetPubSimulationBytes() 325 simulationResults = append(simulationResults, pubSimResBytes2) 326 block2 := bg.NextBlock(simulationResults) 327 err = store1.AddBlock(block2) 328 assert.NoError(t, err) 329 err = env.testHistoryDB.Commit(block2) 330 assert.NoError(t, err) 331 332 qhistory, err := env.testHistoryDB.NewQueryExecutor(store1) 333 assert.NoError(t, err, "Error upon NewQueryExecutor") 334 335 // verify the results for each key, in the order of newest to oldest 336 testutilVerifyResults(t, qhistory, "ns1", "key", []string{"value2", "value1"}) 337 testutilVerifyResults(t, qhistory, "ns1", key1, []string{"dummyVal1"}) 338 testutilVerifyResults(t, qhistory, "ns1", key2, []string{"dummyVal2"}) 339 testutilVerifyResults(t, qhistory, "ns1", key3, []string{"dummyVal3"}) 340 testutilVerifyResults(t, qhistory, "ns1", key4, []string{"dummyVal4"}) 341 testutilVerifyResults(t, qhistory, "ns1", key5, []string{"dummyVal5"}) 342 343 // verify none of key1-key5 falls in the range of history query for "key" 344 testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key1) 345 testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key2) 346 testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key3) 347 testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key4) 348 testutilCheckKeyNotInRange(t, qhistory, "ns1", "key", key5) 349 } 350 351 // TestHistoryWithBlockNumber256 creates 256 blocks and then 352 // queries historydb to verify that all 256 blocks are returned in the right orderer. 353 // This test also verifies that block256 is returned correctly even if its key contains nil byte. 354 func TestHistoryWithBlockNumber256(t *testing.T) { 355 env := newTestHistoryEnv(t) 356 defer env.cleanup() 357 provider := env.testBlockStorageEnv.provider 358 ledger1id := "ledger1" 359 store1, err := provider.OpenBlockStore(ledger1id) 360 assert.NoError(t, err, "Error upon provider.OpenBlockStore()") 361 defer store1.Shutdown() 362 363 bg, gb := testutil.NewBlockGenerator(t, ledger1id, false) 364 assert.NoError(t, store1.AddBlock(gb)) 365 assert.NoError(t, env.testHistoryDB.Commit(gb)) 366 367 // add 256 blocks, each block has 1 transaction setting state for "ns1" and "key", value is "value<blockNum>" 368 for i := 1; i <= 256; i++ { 369 txid := util2.GenerateUUID() 370 simulator, _ := env.txmgr.NewTxSimulator(txid) 371 value := fmt.Sprintf("value%d", i) 372 simulator.SetState("ns1", "key", []byte(value)) 373 simulator.Done() 374 simRes, _ := simulator.GetTxSimulationResults() 375 pubSimResBytes, _ := simRes.GetPubSimulationBytes() 376 block := bg.NextBlock([][]byte{pubSimResBytes}) 377 err = store1.AddBlock(block) 378 assert.NoError(t, err) 379 err = env.testHistoryDB.Commit(block) 380 assert.NoError(t, err) 381 } 382 383 // query history db for "ns1", "key" 384 qhistory, err := env.testHistoryDB.NewQueryExecutor(store1) 385 assert.NoError(t, err, "Error upon NewQueryExecutor") 386 387 // verify history query returns the expected results in the orderer of block256, 255, 254 .... 1. 388 expectedHistoryResults := make([]string, 0) 389 for i := 256; i >= 1; i-- { 390 expectedHistoryResults = append(expectedHistoryResults, fmt.Sprintf("value%d", i)) 391 } 392 testutilVerifyResults(t, qhistory, "ns1", "key", expectedHistoryResults) 393 } 394 395 func TestName(t *testing.T) { 396 env := newTestHistoryEnv(t) 397 defer env.cleanup() 398 assert.Equal(t, "history", env.testHistoryDB.Name()) 399 } 400 401 // verify history results 402 func testutilVerifyResults(t *testing.T, hqe ledger.HistoryQueryExecutor, ns, key string, expectedVals []string) { 403 itr, err := hqe.GetHistoryForKey(ns, key) 404 assert.NoError(t, err, "Error upon GetHistoryForKey()") 405 retrievedVals := []string{} 406 for { 407 kmod, _ := itr.Next() 408 if kmod == nil { 409 break 410 } 411 txid := kmod.(*queryresult.KeyModification).TxId 412 retrievedValue := string(kmod.(*queryresult.KeyModification).Value) 413 retrievedVals = append(retrievedVals, retrievedValue) 414 t.Logf("Retrieved history record at TxId=%s with value %s", txid, retrievedValue) 415 } 416 assert.Equal(t, expectedVals, retrievedVals) 417 } 418 419 // testutilCheckKeyNotInRange verifies that a (false) key is not returned in range query when searching for the desired key 420 func testutilCheckKeyNotInRange(t *testing.T, hqe ledger.HistoryQueryExecutor, ns, desiredKey, falseKey string) { 421 itr, err := hqe.GetHistoryForKey(ns, desiredKey) 422 assert.NoError(t, err, "Error upon GetHistoryForKey()") 423 scanner := itr.(*historyScanner) 424 rangeScanKeys := constructRangeScan(ns, falseKey) 425 for { 426 if !scanner.dbItr.Next() { 427 break 428 } 429 historyKey := scanner.dbItr.Key() 430 if bytes.Contains(historyKey, rangeScanKeys.startKey) { 431 assert.Failf(t, "false key %s should not be returned in range query for key %s", falseKey, desiredKey) 432 } 433 } 434 }