Skip to content

Commit 19c7670

Browse files
committed
[FAB-3556] Throw error for invalid keys at simulation
This CR makes changes in the simulation such that the simulator raises an error if an invalid key is passed in. The validity of the key is decided based on the configured db. For instance, couchdb allows only valid utf-8 strings to be the key. In the current code, this check is not made during simulation. This causes to defer the issue at the commit time in which situation, peer has no option other than raising a panic becasue, it simply cannot commit the block. Change-Id: Id1439c36e3a142f8ca47574d391ee10b366acd69 Signed-off-by: manish <[email protected]>
1 parent d25b994 commit 19c7670

File tree

5 files changed

+37
-6
lines changed

5 files changed

+37
-6
lines changed

core/ledger/kvledger/txmgmt/statedb/statecouchdb/statecouchdb.go

+9
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"strconv"
2525
"strings"
2626
"sync"
27+
"unicode/utf8"
2728

2829
"github.com/hyperledger/fabric/common/flogging"
2930
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
@@ -113,6 +114,14 @@ func (vdb *VersionedDB) Close() {
113114
// no need to close db since a shared couch instance is used
114115
}
115116

117+
// ValidateKey implements method in VersionedDB interface
118+
func (vdb *VersionedDB) ValidateKey(key string) error {
119+
if !utf8.ValidString(key) {
120+
return fmt.Errorf("Key should be a valid utf8 string: [%x]", key)
121+
}
122+
return nil
123+
}
124+
116125
// GetState implements method in VersionedDB interface
117126
func (vdb *VersionedDB) GetState(namespace string, key string) (*statedb.VersionedValue, error) {
118127
logger.Debugf("GetState(). ns=%s, key=%s", namespace, key)

core/ledger/kvledger/txmgmt/statedb/statedb.go

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ type VersionedDB interface {
5151
// GetLatestSavePoint returns the height of the highest transaction upto which
5252
// the state db is consistent
5353
GetLatestSavePoint() (*version.Height, error)
54+
// ValidateKey tests whether the key is supported by the db implementation.
55+
// For instance, leveldb supports any bytes for the key while the couchdb supports only valid utf-8 string
56+
ValidateKey(key string) error
5457
// Open opens the db
5558
Open() error
5659
// Close closes the db

core/ledger/kvledger/txmgmt/statedb/stateleveldb/stateleveldb.go

+5
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ func (vdb *versionedDB) Close() {
7979
// do nothing because shared db is used
8080
}
8181

82+
// ValidateKey implements method in VersionedDB interface
83+
func (vdb *versionedDB) ValidateKey(key string) error {
84+
return nil
85+
}
86+
8287
// GetState implements method in VersionedDB interface
8388
func (vdb *versionedDB) GetState(namespace string, key string) (*statedb.VersionedValue, error) {
8489
logger.Debugf("GetState(). ns=%s, key=%s", namespace, key)

core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/lockbased_tx_simulator.go

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ func (s *lockBasedTxSimulator) GetState(ns string, key string) ([]byte, error) {
4545
// SetState implements method in interface `ledger.TxSimulator`
4646
func (s *lockBasedTxSimulator) SetState(ns string, key string, value []byte) error {
4747
s.helper.checkDone()
48+
if err := s.helper.txmgr.db.ValidateKey(key); err != nil {
49+
return err
50+
}
4851
s.rwsetBuilder.AddToWriteSet(ns, key, value)
4952
return nil
5053
}

core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/txmgr_test.go

+17-6
Original file line numberDiff line numberDiff line change
@@ -587,26 +587,37 @@ func testExecuteQuery(t *testing.T, env testEnv) {
587587

588588
itr, err := queryExecuter.ExecuteQuery("ns1", queryString)
589589
testutil.AssertNoError(t, err, "Error upon ExecuteQuery()")
590-
591590
counter := 0
592591
for {
593592
queryRecord, _ := itr.Next()
594593
if queryRecord == nil {
595594
break
596595
}
597-
598596
//Unmarshal the document to Asset structure
599597
assetResp := &Asset{}
600598
json.Unmarshal(queryRecord.(*queryresult.KV).Value, &assetResp)
601-
602599
//Verify the owner retrieved matches
603600
testutil.AssertEquals(t, assetResp.Owner, "bob")
604-
605601
counter++
606-
607602
}
608-
609603
//Ensure the query returns 3 documents
610604
testutil.AssertEquals(t, counter, 3)
605+
}
611606

607+
func TestValidateKey(t *testing.T) {
608+
nonUTF8Key := string([]byte{0xff, 0xff})
609+
dummyValue := []byte("dummyValue")
610+
for _, testEnv := range testEnvs {
611+
testLedgerID := "TestValidateKey"
612+
testEnv.init(t, testLedgerID)
613+
txSimulator, _ := testEnv.getTxMgr().NewTxSimulator()
614+
err := txSimulator.SetState("ns1", nonUTF8Key, dummyValue)
615+
if testEnv.getName() == levelDBtestEnvName {
616+
testutil.AssertNoError(t, err, "")
617+
}
618+
if testEnv.getName() == couchDBtestEnvName {
619+
testutil.AssertError(t, err, "")
620+
}
621+
testEnv.cleanup()
622+
}
612623
}

0 commit comments

Comments
 (0)