Skip to content

Commit 29d7fc0

Browse files
Ruslan Kryukovdenyeart
Ruslan Kryukov
authored andcommitted
[FAB-2243] Replace Tx Validation bit-array by flags
https://jira.hyperledger.org/browse/FAB-2243 Switch valid flag from a boolean to an enum, so that we can indicate the reason for the invalidation (txid already exists, vscc validation failure (endorsement policy failure), mvcc validation failure, etc) This change adds invalidation reason codes, sets them in the block as a uint8 (byte) array, and returns validation result in GetTransactionById. Change-Id: I3593bf6aa4f35bb01b14f8fb3d9950b405f84660 Signed-off-by: Ruslan Kryukov <[email protected]>
1 parent 9a09ac0 commit 29d7fc0

27 files changed

+606
-290
lines changed

common/ledger/blkstorage/blockstorage.go

+8-5
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,20 @@ import (
2121

2222
"github.com/hyperledger/fabric/common/ledger"
2323
"github.com/hyperledger/fabric/protos/common"
24+
"github.com/hyperledger/fabric/protos/peer"
2425
)
2526

2627
// IndexableAttr represents an indexable attribute
2728
type IndexableAttr string
2829

2930
// constants for indexable attributes
3031
const (
31-
IndexableAttrBlockNum = IndexableAttr("BlockNum")
32-
IndexableAttrBlockHash = IndexableAttr("BlockHash")
33-
IndexableAttrTxID = IndexableAttr("TxID")
34-
IndexableAttrBlockNumTranNum = IndexableAttr("BlockNumTranNum")
35-
IndexableAttrBlockTxID = IndexableAttr("BlockTxID")
32+
IndexableAttrBlockNum = IndexableAttr("BlockNum")
33+
IndexableAttrBlockHash = IndexableAttr("BlockHash")
34+
IndexableAttrTxID = IndexableAttr("TxID")
35+
IndexableAttrBlockNumTranNum = IndexableAttr("BlockNumTranNum")
36+
IndexableAttrBlockTxID = IndexableAttr("BlockTxID")
37+
IndexableAttrTxValidationCode = IndexableAttr("TxValidationCode")
3638
)
3739

3840
// IndexConfig - a configuration that includes a list of attributes that should be indexed
@@ -68,5 +70,6 @@ type BlockStore interface {
6870
RetrieveTxByID(txID string) (*common.Envelope, error)
6971
RetrieveTxByBlockNumTranNum(blockNum uint64, tranNum uint64) (*common.Envelope, error)
7072
RetrieveBlockByTxID(txID string) (*common.Block, error)
73+
RetrieveTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error)
7174
Shutdown()
7275
}

common/ledger/blkstorage/fsblkstorage/block_serialization.go

+8
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
type serializedBlockInfo struct {
2929
blockHeader *common.BlockHeader
3030
txOffsets []*txindexInfo
31+
metadata *common.BlockMetadata
3132
}
3233

3334
//The order of the transactions must be maintained for history
@@ -41,6 +42,7 @@ func serializeBlock(block *common.Block) ([]byte, *serializedBlockInfo, error) {
4142
var err error
4243
info := &serializedBlockInfo{}
4344
info.blockHeader = block.Header
45+
info.metadata = block.Metadata
4446
if err = addHeaderBytes(block.Header, buf); err != nil {
4547
return nil, nil, err
4648
}
@@ -84,6 +86,12 @@ func extractSerializedBlockInfo(serializedBlockBytes []byte) (*serializedBlockIn
8486
if err != nil {
8587
return nil, err
8688
}
89+
90+
info.metadata, err = extractMetadata(b)
91+
if err != nil {
92+
return nil, err
93+
}
94+
8795
return info, nil
8896
}
8997

common/ledger/blkstorage/fsblkstorage/blockfile_mgr.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/hyperledger/fabric/common/ledger/util"
2828
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
2929
"github.com/hyperledger/fabric/protos/common"
30+
"github.com/hyperledger/fabric/protos/peer"
3031
putil "github.com/hyperledger/fabric/protos/utils"
3132
"github.com/op/go-logging"
3233
)
@@ -314,7 +315,7 @@ func (mgr *blockfileMgr) addBlock(block *common.Block) error {
314315
//save the index in the database
315316
mgr.index.indexBlock(&blockIdxInfo{
316317
blockNum: block.Header.Number, blockHash: blockHash,
317-
flp: blockFLP, txOffsets: txOffsets})
318+
flp: blockFLP, txOffsets: txOffsets, metadata: block.Metadata})
318319

319320
//update the checkpoint info (for storage) and the blockchain info (for APIs) in the manager
320321
mgr.updateCheckpoint(newCPInfo)
@@ -399,6 +400,8 @@ func (mgr *blockfileMgr) syncIndex() error {
399400
blockIdxInfo.flp = &fileLocPointer{fileSuffixNum: blockPlacementInfo.fileNum,
400401
locPointer: locPointer{offset: int(blockPlacementInfo.blockStartOffset)}}
401402
blockIdxInfo.txOffsets = info.txOffsets
403+
blockIdxInfo.metadata = info.metadata
404+
402405
logger.Debugf("syncIndex() indexing block [%d]", blockIdxInfo.blockNum)
403406
if err = mgr.index.indexBlock(blockIdxInfo); err != nil {
404407
return err
@@ -465,6 +468,11 @@ func (mgr *blockfileMgr) retrieveBlockByTxID(txID string) (*common.Block, error)
465468
return mgr.fetchBlock(loc)
466469
}
467470

471+
func (mgr *blockfileMgr) retrieveTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) {
472+
logger.Debugf("retrieveTxValidationCodeByTxID() - txID = [%s]", txID)
473+
return mgr.index.getTxValidationCodeByTxID(txID)
474+
}
475+
468476
func (mgr *blockfileMgr) retrieveBlockHeaderByNumber(blockNum uint64) (*common.BlockHeader, error) {
469477
logger.Debugf("retrieveBlockHeaderByNumber() - blockNum = [%d]", blockNum)
470478
loc, err := mgr.index.getBlockLocByBlockNum(blockNum)

common/ledger/blkstorage/fsblkstorage/blockindex.go

+44-6
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,19 @@ import (
2525
"github.com/hyperledger/fabric/common/ledger/blkstorage"
2626
"github.com/hyperledger/fabric/common/ledger/util"
2727
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
28+
ledgerUtil "github.com/hyperledger/fabric/core/ledger/util"
29+
"github.com/hyperledger/fabric/protos/common"
30+
"github.com/hyperledger/fabric/protos/peer"
2831
)
2932

3033
const (
31-
blockNumIdxKeyPrefix = 'n'
32-
blockHashIdxKeyPrefix = 'h'
33-
txIDIdxKeyPrefix = 't'
34-
blockNumTranNumIdxKeyPrefix = 'a'
35-
blockTxIDIdxKeyPrefix = 'b'
36-
indexCheckpointKeyStr = "indexCheckpointKey"
34+
blockNumIdxKeyPrefix = 'n'
35+
blockHashIdxKeyPrefix = 'h'
36+
txIDIdxKeyPrefix = 't'
37+
blockNumTranNumIdxKeyPrefix = 'a'
38+
blockTxIDIdxKeyPrefix = 'b'
39+
txValidationResultIdxKeyPrefix = 'v'
40+
indexCheckpointKeyStr = "indexCheckpointKey"
3741
)
3842

3943
var indexCheckpointKey = []byte(indexCheckpointKeyStr)
@@ -47,13 +51,15 @@ type index interface {
4751
getTxLoc(txID string) (*fileLocPointer, error)
4852
getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint64) (*fileLocPointer, error)
4953
getBlockLocByTxID(txID string) (*fileLocPointer, error)
54+
getTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error)
5055
}
5156

5257
type blockIdxInfo struct {
5358
blockNum uint64
5459
blockHash []byte
5560
flp *fileLocPointer
5661
txOffsets []*txindexInfo
62+
metadata *common.BlockMetadata
5763
}
5864

5965
type blockIndex struct {
@@ -92,6 +98,7 @@ func (index *blockIndex) indexBlock(blockIdxInfo *blockIdxInfo) error {
9298
logger.Debugf("Indexing block [%s]", blockIdxInfo)
9399
flp := blockIdxInfo.flp
94100
txOffsets := blockIdxInfo.txOffsets
101+
txsfltr := ledgerUtil.TxValidationFlags(blockIdxInfo.metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
95102
batch := leveldbhelper.NewUpdateBatch()
96103
flpBytes, err := flp.marshal()
97104
if err != nil {
@@ -141,6 +148,13 @@ func (index *blockIndex) indexBlock(blockIdxInfo *blockIdxInfo) error {
141148
}
142149
}
143150

151+
// Index6 - Store transaction validation result by transaction id
152+
if _, ok := index.indexItemsMap[blkstorage.IndexableAttrTxValidationCode]; ok {
153+
for idx, txoffset := range txOffsets {
154+
batch.Put(constructTxValidationCodeIDKey(txoffset.txID), []byte{byte(txsfltr.Flag(idx))})
155+
}
156+
}
157+
144158
batch.Put(indexCheckpointKey, encodeBlockNum(blockIdxInfo.blockNum))
145159
if err := index.db.WriteBatch(batch, false); err != nil {
146160
return err
@@ -228,6 +242,26 @@ func (index *blockIndex) getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint
228242
return txFLP, nil
229243
}
230244

245+
func (index *blockIndex) getTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) {
246+
if _, ok := index.indexItemsMap[blkstorage.IndexableAttrTxValidationCode]; !ok {
247+
return peer.TxValidationCode(-1), blkstorage.ErrAttrNotIndexed
248+
}
249+
250+
raw, err := index.db.Get(constructTxValidationCodeIDKey(txID))
251+
252+
if err != nil {
253+
return peer.TxValidationCode(-1), err
254+
} else if raw == nil {
255+
return peer.TxValidationCode(-1), blkstorage.ErrAttrNotIndexed
256+
} else if len(raw) != 1 {
257+
return peer.TxValidationCode(-1), errors.New("Invalid value in indexItems")
258+
}
259+
260+
result := peer.TxValidationCode(int32(raw[0]))
261+
262+
return result, nil
263+
}
264+
231265
func constructBlockNumKey(blockNum uint64) []byte {
232266
blkNumBytes := util.EncodeOrderPreservingVarUint64(blockNum)
233267
return append([]byte{blockNumIdxKeyPrefix}, blkNumBytes...)
@@ -245,6 +279,10 @@ func constructBlockTxIDKey(txID string) []byte {
245279
return append([]byte{blockTxIDIdxKeyPrefix}, []byte(txID)...)
246280
}
247281

282+
func constructTxValidationCodeIDKey(txID string) []byte {
283+
return append([]byte{txValidationResultIdxKeyPrefix}, []byte(txID)...)
284+
}
285+
248286
func constructBlockNumTranNumKey(blockNum uint64, txNum uint64) []byte {
249287
blkNumBytes := util.EncodeOrderPreservingVarUint64(blockNum)
250288
tranNumBytes := util.EncodeOrderPreservingVarUint64(txNum)

common/ledger/blkstorage/fsblkstorage/blockindex_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import (
2222

2323
"github.com/hyperledger/fabric/common/ledger/blkstorage"
2424
"github.com/hyperledger/fabric/common/ledger/testutil"
25+
"github.com/hyperledger/fabric/core/ledger/util"
26+
"github.com/hyperledger/fabric/protos/common"
27+
"github.com/hyperledger/fabric/protos/peer"
2528
putil "github.com/hyperledger/fabric/protos/utils"
2629
)
2730

@@ -51,6 +54,10 @@ func (i *noopIndex) getBlockLocByTxID(txID string) (*fileLocPointer, error) {
5154
return nil, nil
5255
}
5356

57+
func (i *noopIndex) getTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) {
58+
return peer.TxValidationCode(-1), nil
59+
}
60+
5461
func TestBlockIndexSync(t *testing.T) {
5562
testBlockIndexSync(t, 10, 5, false)
5663
testBlockIndexSync(t, 10, 5, true)
@@ -119,6 +126,7 @@ func TestBlockIndexSelectiveIndexing(t *testing.T) {
119126
testBlockIndexSelectiveIndexing(t, []blkstorage.IndexableAttr{blkstorage.IndexableAttrBlockHash, blkstorage.IndexableAttrBlockNum})
120127
testBlockIndexSelectiveIndexing(t, []blkstorage.IndexableAttr{blkstorage.IndexableAttrTxID, blkstorage.IndexableAttrBlockNumTranNum})
121128
testBlockIndexSelectiveIndexing(t, []blkstorage.IndexableAttr{blkstorage.IndexableAttrBlockTxID})
129+
testBlockIndexSelectiveIndexing(t, []blkstorage.IndexableAttr{blkstorage.IndexableAttrTxValidationCode})
122130
}
123131

124132
func testBlockIndexSelectiveIndexing(t *testing.T, indexItems []blkstorage.IndexableAttr) {
@@ -192,5 +200,26 @@ func testBlockIndexSelectiveIndexing(t *testing.T, indexItems []blkstorage.Index
192200
} else {
193201
testutil.AssertSame(t, err, blkstorage.ErrAttrNotIndexed)
194202
}
203+
204+
for _, block := range blocks {
205+
flags := util.TxValidationFlags(block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER])
206+
207+
for idx, d := range block.Data.Data {
208+
txid, err = extractTxID(d)
209+
testutil.AssertNoError(t, err, "")
210+
211+
reason, err := blockfileMgr.retrieveTxValidationCodeByTxID(txid)
212+
213+
if testutil.Contains(indexItems, blkstorage.IndexableAttrTxValidationCode) {
214+
testutil.AssertNoError(t, err, "Error while retrieving tx validation code by txID")
215+
216+
reasonFromFlags := flags.Flag(idx)
217+
218+
testutil.AssertEquals(t, reason, reasonFromFlags)
219+
} else {
220+
testutil.AssertSame(t, err, blkstorage.ErrAttrNotIndexed)
221+
}
222+
}
223+
}
195224
})
196225
}

common/ledger/blkstorage/fsblkstorage/fs_blockstore.go

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
2323

2424
"github.com/hyperledger/fabric/protos/common"
25+
"github.com/hyperledger/fabric/protos/peer"
2526
)
2627

2728
// fsBlockStore - filesystem based implementation for `BlockStore`
@@ -81,6 +82,10 @@ func (store *fsBlockStore) RetrieveBlockByTxID(txID string) (*common.Block, erro
8182
return store.fileMgr.retrieveBlockByTxID(txID)
8283
}
8384

85+
func (store *fsBlockStore) RetrieveTxValidationCodeByTxID(txID string) (peer.TxValidationCode, error) {
86+
return store.fileMgr.retrieveTxValidationCodeByTxID(txID)
87+
}
88+
8489
// Shutdown shuts down the block store
8590
func (store *fsBlockStore) Shutdown() {
8691
logger.Debugf("closing fs blockStore:%s", store.id)

common/ledger/blkstorage/fsblkstorage/pkg_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func newTestEnv(t testing.TB, conf *Conf) *testEnv {
4949
blkstorage.IndexableAttrTxID,
5050
blkstorage.IndexableAttrBlockNumTranNum,
5151
blkstorage.IndexableAttrBlockTxID,
52+
blkstorage.IndexableAttrTxValidationCode,
5253
}
5354
return newTestEnvSelectiveIndexing(t, conf, attrsToIndex)
5455
}

common/ledger/testutil/test_helper.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import (
2121

2222
"github.com/golang/protobuf/proto"
2323
"github.com/hyperledger/fabric/common/util"
24+
lutils "github.com/hyperledger/fabric/core/ledger/util"
2425
"github.com/hyperledger/fabric/protos/common"
2526
ptestutils "github.com/hyperledger/fabric/protos/testutils"
27+
"github.com/hyperledger/fabric/protos/utils"
2628
)
2729

2830
//BlockGenerator generates a series of blocks for testing
@@ -90,7 +92,7 @@ func ConstructTestBlocks(t *testing.T, numBlocks int) []*common.Block {
9092
}
9193

9294
// ConstructTransaction constructs a transaction for testing
93-
func ConstructTransaction(t *testing.T, simulationResults []byte, sign bool) (*common.Envelope, string, error) {
95+
func ConstructTransaction(_ *testing.T, simulationResults []byte, sign bool) (*common.Envelope, string, error) {
9496
ccName := "foo"
9597
//response := &pb.Response{Status: 200}
9698
var txID string
@@ -111,5 +113,9 @@ func newBlock(env []*common.Envelope, blockNum uint64, previousHash []byte) *com
111113
block.Data.Data = append(block.Data.Data, txEnvBytes)
112114
}
113115
block.Header.DataHash = block.Data.Hash()
116+
utils.InitBlockMetadata(block)
117+
118+
block.Metadata.Metadata[common.BlockMetadataIndex_TRANSACTIONS_FILTER] = lutils.NewTxValidationFlags(len(env))
119+
114120
return block
115121
}

0 commit comments

Comments
 (0)