diff --git a/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go b/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go index 7d9c7b7c19d..4c0cabe852a 100644 --- a/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go +++ b/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go @@ -24,6 +24,7 @@ import ( "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwset" "github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version" "github.com/hyperledger/fabric/core/ledger/ledgerconfig" + "github.com/hyperledger/fabric/core/ledger/util" "github.com/hyperledger/fabric/protos/common" putils "github.com/hyperledger/fabric/protos/utils" logging "github.com/op/go-logging" @@ -92,10 +93,26 @@ func (historyDB *historyDB) Commit(block *common.Block) error { logger.Debugf("Channel [%s]: Updating history database for blockNo [%v] with [%d] transactions", historyDB.dbName, blockNo, len(block.Data.Data)) - //TODO add check for invalid trans in bit array + // Get the invalidation byte array for the block + txsFilter := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) + // Initialize txsFilter if it does not yet exist (e.g. during testing, for genesis block, etc) + if len(txsFilter) == 0 { + txsFilter = util.NewTxValidationFlags(len(block.Data.Data)) + block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter + } + + // write each tran's write set to history db for _, envBytes := range block.Data.Data { tranNo++ + // If the tran is marked as invalid, skip it + // Note, tranNo starts at 1 for height, while tranIndex starts at 0 for invalid array + if txsFilter.IsInvalid(int(tranNo) - 1) { + logger.Debugf("Channel [%s]: Skipping history write for invalid transaction number %d", + historyDB.dbName, tranNo) + continue + } + env, err := putils.GetEnvelopeFromBlock(envBytes) if err != nil { return err diff --git a/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go b/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go index b4d289e3e67..b8741d6241a 100644 --- a/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go +++ b/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go @@ -24,6 +24,9 @@ import ( configtxtest "github.com/hyperledger/fabric/common/configtx/test" "github.com/hyperledger/fabric/common/ledger/testutil" "github.com/hyperledger/fabric/core/ledger" + "github.com/hyperledger/fabric/core/ledger/util" + "github.com/hyperledger/fabric/protos/common" + "github.com/hyperledger/fabric/protos/peer" "github.com/spf13/viper" ) @@ -124,6 +127,45 @@ func TestHistory(t *testing.T) { testutil.AssertEquals(t, count, 3) } +func TestHistoryForInvalidTran(t *testing.T) { + + env := NewTestHistoryEnv(t) + defer env.cleanup() + provider := env.testBlockStorageEnv.provider + store1, err := provider.OpenBlockStore("ledger1") + testutil.AssertNoError(t, err, "Error upon provider.OpenBlockStore()") + defer store1.Shutdown() + + //block1 + simulator, _ := env.txmgr.NewTxSimulator() + value1 := []byte("value1") + simulator.SetState("ns1", "key7", value1) + simulator.Done() + simRes, _ := simulator.GetTxSimulationResults() + bg := testutil.NewBlockGenerator(t) + block1 := bg.NextBlock([][]byte{simRes}, false) + + //for this invalid tran test, set the transaction to invalid + txsFilter := util.TxValidationFlags(block1.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER]) + txsFilter.SetFlag(0, peer.TxValidationCode_INVALID_OTHER_REASON) + block1.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = txsFilter + + err = store1.AddBlock(block1) + testutil.AssertNoError(t, err, "") + err = env.testHistoryDB.Commit(block1) + testutil.AssertNoError(t, err, "") + + qhistory, err := env.testHistoryDB.NewHistoryQueryExecutor(store1) + testutil.AssertNoError(t, err, "Error upon NewHistoryQueryExecutor") + + itr, err2 := qhistory.GetHistoryForKey("ns1", "key7") + testutil.AssertNoError(t, err2, "Error upon GetHistoryForKey()") + + // test that there are no history values, since the tran was marked as invalid + kmod, _ := itr.Next() + testutil.AssertNil(t, kmod) +} + //TestSavepoint tests that save points get written after each block and get returned via GetBlockNumfromSavepoint func TestHistoryDisabled(t *testing.T) {