From cb4669694d3e6e1b0ff74b4c277df6970e35b384 Mon Sep 17 00:00:00 2001 From: denyeart Date: Fri, 27 Jan 2017 17:59:40 -0500 Subject: [PATCH] Fix history panic on config blocks Getting a panic error when committer receives a config block and attempts to write the tran to history db. Fixed by only writing to history db for endorsement transactions. Change-Id: I32d5e414199d85355eeae84f3e1ae680fe0811f0 Signed-off-by: denyeart --- .../historyleveldb/historyleveldb.go | 60 ++++++++++++------- .../historyleveldb/historyleveldb_test.go | 15 +++++ 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go b/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go index 04e2d76ad91..1071b5f6816 100644 --- a/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go +++ b/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb.go @@ -24,7 +24,7 @@ import ( "github.com/hyperledger/fabric/core/ledger/ledgerconfig" "github.com/hyperledger/fabric/core/ledger/util/leveldbhelper" "github.com/hyperledger/fabric/protos/common" - "github.com/hyperledger/fabric/protos/utils" + putils "github.com/hyperledger/fabric/protos/utils" logging "github.com/op/go-logging" ) @@ -97,41 +97,57 @@ func (historyDB *historyDB) Commit(block *common.Block) error { //TODO add check for invalid trans in bit array for _, envBytes := range block.Data.Data { tranNo++ - logger.Debugf("Updating history for tranNo: %v", tranNo) - // extract actions from the envelope message - respPayload, err := utils.GetActionFromEnvelope(envBytes) + env, err := putils.GetEnvelopeFromBlock(envBytes) if err != nil { return err } - //preparation for extracting RWSet from transaction - txRWSet := &rwset.TxReadWriteSet{} - - // Get the Result from the Action and then Unmarshal - // it into a TxReadWriteSet using custom unmarshalling - if err = txRWSet.Unmarshal(respPayload.Results); err != nil { + payload, err := putils.GetPayload(env) + if err != nil { return err } - // for each transaction, loop through the namespaces and writesets - // and add a history record for each write - for _, nsRWSet := range txRWSet.NsRWs { - ns := nsRWSet.NameSpace + if common.HeaderType(payload.Header.ChainHeader.Type) == common.HeaderType_ENDORSER_TRANSACTION { - for _, kvWrite := range nsRWSet.Writes { - writeKey := kvWrite.Key + logger.Debugf("Updating history for tranNo: %d", tranNo) + // extract actions from the envelope message + respPayload, err := putils.GetActionFromEnvelope(envBytes) + if err != nil { + return err + } - logger.Debugf("Writing history record for: ns=%s, key=%s, blockNo=%d tranNo=%d", - ns, writeKey, blockNo, tranNo) + //preparation for extracting RWSet from transaction + txRWSet := &rwset.TxReadWriteSet{} + + // Get the Result from the Action and then Unmarshal + // it into a TxReadWriteSet using custom unmarshalling + if err = txRWSet.Unmarshal(respPayload.Results); err != nil { + return err + } + // for each transaction, loop through the namespaces and writesets + // and add a history record for each write + for _, nsRWSet := range txRWSet.NsRWs { + ns := nsRWSet.NameSpace - //composite key for history records is in the form ns~key~blockNo~tranNo - compositeHistoryKey := historydb.ConstructCompositeHistoryKey(ns, writeKey, blockNo, tranNo) + for _, kvWrite := range nsRWSet.Writes { + writeKey := kvWrite.Key - // No value is required, write an empty byte array (emptyValue) since Put() of nil is not allowed - dbBatch.Put(compositeHistoryKey, emptyValue) + logger.Debugf("Writing history record for: ns=%s, key=%s, blockNo=%d tranNo=%d", + ns, writeKey, blockNo, tranNo) + + //composite key for history records is in the form ns~key~blockNo~tranNo + compositeHistoryKey := historydb.ConstructCompositeHistoryKey(ns, writeKey, blockNo, tranNo) + + // No value is required, write an empty byte array (emptyValue) since Put() of nil is not allowed + dbBatch.Put(compositeHistoryKey, emptyValue) + } } + + } else { + logger.Debugf("Skipping transaction %d since it is not an endorsement transaction\n", tranNo) } + } // add savepoint for recovery purpose diff --git a/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go b/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go index 49df0abec43..2edbf045db0 100644 --- a/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go +++ b/core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go @@ -20,6 +20,7 @@ import ( "os" "testing" + configtxtest "github.com/hyperledger/fabric/common/configtx/test" "github.com/hyperledger/fabric/core/ledger" "github.com/hyperledger/fabric/core/ledger/testutil" "github.com/spf13/viper" @@ -125,3 +126,17 @@ func TestHistoryDisabled(t *testing.T) { _, err2 := qhistory.GetHistoryForKey("ns1", "key7") testutil.AssertError(t, err2, "Error should have been returned for GetHistoryForKey() when history disabled") } + +//TestGenesisBlockNoError tests that Genesis blocks are ignored by history processing +// since we only persist history of chaincode key writes +func TestGenesisBlockNoError(t *testing.T) { + + env := NewTestHistoryEnv(t) + defer env.cleanup() + + block, err := configtxtest.MakeGenesisBlock("test_chainid") + testutil.AssertNoError(t, err, "") + + err = env.TestHistoryDB.Commit(block) + testutil.AssertNoError(t, err, "") +}