Skip to content

Commit c717c4b

Browse files
author
Ruslan Kryukov
committed
[FAB-2086] API method to get block by TxID
https://jira.hyperledger.org/browse/FAB-2086 We need this method for getting information of block in a ledger by txID. Also this method helps to check valid tx or not by getting the validation bit array from the block. Change-Id: I4216635097ecd4cf5de9e3442dfbd5660d44292f Signed-off-by: Ruslan Kryukov <ruslan.kryukov@ru.ibm.com>
1 parent c341fe5 commit c717c4b

File tree

12 files changed

+128
-0
lines changed

12 files changed

+128
-0
lines changed

common/ledger/blkstorage/blockstorage.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const (
3232
IndexableAttrBlockHash = IndexableAttr("BlockHash")
3333
IndexableAttrTxID = IndexableAttr("TxID")
3434
IndexableAttrBlockNumTranNum = IndexableAttr("BlockNumTranNum")
35+
IndexableAttrBlockTxID = IndexableAttr("BlockTxID")
3536
)
3637

3738
// IndexConfig - a configuration that includes a list of attributes that should be indexed
@@ -66,5 +67,6 @@ type BlockStore interface {
6667
RetrieveBlockByNumber(blockNum uint64) (*common.Block, error) // blockNum of math.MaxUint64 will return last block
6768
RetrieveTxByID(txID string) (*common.Envelope, error)
6869
RetrieveTxByBlockNumTranNum(blockNum uint64, tranNum uint64) (*common.Envelope, error)
70+
RetrieveBlockByTxID(txID string) (*common.Block, error)
6971
Shutdown()
7072
}

common/ledger/blkstorage/fsblkstorage/blockfile_mgr.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,17 @@ func (mgr *blockfileMgr) retrieveBlockByNumber(blockNum uint64) (*common.Block,
438438
return mgr.fetchBlock(loc)
439439
}
440440

441+
func (mgr *blockfileMgr) retrieveBlockByTxID(txID string) (*common.Block, error) {
442+
logger.Debugf("retrieveBlockByTxID() - txID = [%s]", txID)
443+
444+
loc, err := mgr.index.getBlockLocByTxID(txID)
445+
446+
if err != nil {
447+
return nil, err
448+
}
449+
return mgr.fetchBlock(loc)
450+
}
451+
441452
func (mgr *blockfileMgr) retrieveBlockHeaderByNumber(blockNum uint64) (*common.BlockHeader, error) {
442453
logger.Debugf("retrieveBlockHeaderByNumber() - blockNum = [%d]", blockNum)
443454
loc, err := mgr.index.getBlockLocByBlockNum(blockNum)

common/ledger/blkstorage/fsblkstorage/blockfile_mgr_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,23 @@ func TestBlockfileMgrFileRolling(t *testing.T) {
216216
testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.cpInfo.latestFileChunkSuffixNum, 2)
217217
blkfileMgrWrapper.testGetBlockByHash(blocks)
218218
}
219+
220+
func TestBlockfileMgrGetBlockByTxID(t *testing.T) {
221+
env := newTestEnv(t, NewConf(testPath, 0))
222+
defer env.Cleanup()
223+
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
224+
defer blkfileMgrWrapper.close()
225+
blocks := testutil.ConstructTestBlocks(t, 10)
226+
blkfileMgrWrapper.addBlocks(blocks)
227+
for _, blk := range blocks {
228+
for j, _ := range blk.Data.Data {
229+
// blockNum starts with 1
230+
txID, err := extractTxID(blk.Data.Data[j])
231+
testutil.AssertNoError(t, err, "")
232+
233+
blockFromFileMgr, err := blkfileMgrWrapper.blockfileMgr.retrieveBlockByTxID(txID)
234+
testutil.AssertNoError(t, err, "Error while retrieving block from blkfileMgr")
235+
testutil.AssertEquals(t, blockFromFileMgr, blk)
236+
}
237+
}
238+
}

common/ledger/blkstorage/fsblkstorage/blockindex.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const (
3131
blockHashIdxKeyPrefix = 'h'
3232
txIDIdxKeyPrefix = 't'
3333
blockNumTranNumIdxKeyPrefix = 'a'
34+
blockTxIDIdxKeyPrefix = 'b'
3435
indexCheckpointKeyStr = "indexCheckpointKey"
3536
)
3637

@@ -43,6 +44,7 @@ type index interface {
4344
getBlockLocByBlockNum(blockNum uint64) (*fileLocPointer, error)
4445
getTxLoc(txID string) (*fileLocPointer, error)
4546
getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint64) (*fileLocPointer, error)
47+
getBlockLocByTxID(txID string) (*fileLocPointer, error)
4648
}
4749

4850
type blockIdxInfo struct {
@@ -127,6 +129,13 @@ func (index *blockIndex) indexBlock(blockIdxInfo *blockIdxInfo) error {
127129
}
128130
}
129131

132+
// Index5 - Store BlockNumber will be used to find block by transaction id
133+
if _, ok := index.indexItemsMap[blkstorage.IndexableAttrBlockTxID]; ok {
134+
for _, txoffset := range txOffsets {
135+
batch.Put(constructBlockTxIDKey(txoffset.txID), flpBytes)
136+
}
137+
}
138+
130139
batch.Put(indexCheckpointKey, encodeBlockNum(blockIdxInfo.blockNum))
131140
if err := index.db.WriteBatch(batch, false); err != nil {
132141
return err
@@ -182,6 +191,22 @@ func (index *blockIndex) getTxLoc(txID string) (*fileLocPointer, error) {
182191
return txFLP, nil
183192
}
184193

194+
func (index *blockIndex) getBlockLocByTxID(txID string) (*fileLocPointer, error) {
195+
if _, ok := index.indexItemsMap[blkstorage.IndexableAttrBlockTxID]; !ok {
196+
return nil, blkstorage.ErrAttrNotIndexed
197+
}
198+
b, err := index.db.Get(constructBlockTxIDKey(txID))
199+
if err != nil {
200+
return nil, err
201+
}
202+
if b == nil {
203+
return nil, blkstorage.ErrNotFoundInIndex
204+
}
205+
txFLP := &fileLocPointer{}
206+
txFLP.unmarshal(b)
207+
return txFLP, nil
208+
}
209+
185210
func (index *blockIndex) getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint64) (*fileLocPointer, error) {
186211
if _, ok := index.indexItemsMap[blkstorage.IndexableAttrBlockNumTranNum]; !ok {
187212
return nil, blkstorage.ErrAttrNotIndexed
@@ -211,6 +236,10 @@ func constructTxIDKey(txID string) []byte {
211236
return append([]byte{txIDIdxKeyPrefix}, []byte(txID)...)
212237
}
213238

239+
func constructBlockTxIDKey(txID string) []byte {
240+
return append([]byte{blockTxIDIdxKeyPrefix}, []byte(txID)...)
241+
}
242+
214243
func constructBlockNumTranNumKey(blockNum uint64, txNum uint64) []byte {
215244
blkNumBytes := util.EncodeOrderPreservingVarUint64(blockNum)
216245
tranNumBytes := util.EncodeOrderPreservingVarUint64(txNum)

common/ledger/blkstorage/fsblkstorage/blockindex_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ func (i *noopIndex) getTXLocByBlockNumTranNum(blockNum uint64, tranNum uint64) (
4747
return nil, nil
4848
}
4949

50+
func (i *noopIndex) getBlockLocByTxID(txID string) (*fileLocPointer, error) {
51+
return nil, nil
52+
}
53+
5054
func TestBlockIndexSync(t *testing.T) {
5155
testBlockIndexSync(t, 10, 5, false)
5256
testBlockIndexSync(t, 10, 5, true)
@@ -111,6 +115,7 @@ func TestBlockIndexSelectiveIndexing(t *testing.T) {
111115
testBlockIndexSelectiveIndexing(t, []blkstorage.IndexableAttr{blkstorage.IndexableAttrBlockNumTranNum})
112116
testBlockIndexSelectiveIndexing(t, []blkstorage.IndexableAttr{blkstorage.IndexableAttrBlockHash, blkstorage.IndexableAttrBlockNum})
113117
testBlockIndexSelectiveIndexing(t, []blkstorage.IndexableAttr{blkstorage.IndexableAttrTxID, blkstorage.IndexableAttrBlockNumTranNum})
118+
testBlockIndexSelectiveIndexing(t, []blkstorage.IndexableAttr{blkstorage.IndexableAttrBlockTxID})
114119
}
115120

116121
func testBlockIndexSelectiveIndexing(t *testing.T, indexItems []blkstorage.IndexableAttr) {
@@ -168,4 +173,15 @@ func testBlockIndexSelectiveIndexing(t *testing.T, indexItems []blkstorage.Index
168173
} else {
169174
testutil.AssertSame(t, err, blkstorage.ErrAttrNotIndexed)
170175
}
176+
177+
// test 'retrieveBlockByTxID'
178+
txid, err = extractTxID(blocks[0].Data.Data[0])
179+
testutil.AssertNoError(t, err, "")
180+
block, err = blockfileMgr.retrieveBlockByTxID(txid)
181+
if testutil.Contains(indexItems, blkstorage.IndexableAttrBlockTxID) {
182+
testutil.AssertNoError(t, err, "Error while retrieving block by txID")
183+
testutil.AssertEquals(t, blocks[0], block)
184+
} else {
185+
testutil.AssertSame(t, err, blkstorage.ErrAttrNotIndexed)
186+
}
171187
}

common/ledger/blkstorage/fsblkstorage/fs_blockstore.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ func (store *fsBlockStore) RetrieveTxByBlockNumTranNum(blockNum uint64, tranNum
7777
return store.fileMgr.retrieveTransactionByBlockNumTranNum(blockNum, tranNum)
7878
}
7979

80+
func (store *fsBlockStore) RetrieveBlockByTxID(txID string) (*common.Block, error) {
81+
return store.fileMgr.retrieveBlockByTxID(txID)
82+
}
83+
8084
// Shutdown shuts down the block store
8185
func (store *fsBlockStore) Shutdown() {
8286
logger.Debugf("closing fs blockStore:%s", store.id)

common/ledger/blkstorage/fsblkstorage/pkg_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func newTestEnv(t testing.TB, conf *Conf) *testEnv {
4141
blkstorage.IndexableAttrBlockNum,
4242
blkstorage.IndexableAttrTxID,
4343
blkstorage.IndexableAttrBlockNumTranNum,
44+
blkstorage.IndexableAttrBlockTxID,
4445
}
4546
return newTestEnvSelectiveIndexing(t, conf, attrsToIndex)
4647
}

core/ledger/kvledger/kv_ledger.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ func (l *kvLedger) GetBlockByHash(blockHash []byte) (*common.Block, error) {
228228
return l.blockStore.RetrieveBlockByHash(blockHash)
229229
}
230230

231+
// GetBlockByTxID returns a block which contains a transaction
232+
func (l *kvLedger) GetBlockByTxID(txID string) (*common.Block, error) {
233+
return l.blockStore.RetrieveBlockByTxID(txID)
234+
}
235+
231236
//Prune prunes the blocks/transactions that satisfy the given policy
232237
func (l *kvLedger) Prune(policy commonledger.PrunePolicy) error {
233238
return errors.New("Not yet implemented")

core/ledger/kvledger/kv_ledger_provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func NewProvider() (ledger.PeerLedgerProvider, error) {
6363
blkstorage.IndexableAttrBlockNum,
6464
blkstorage.IndexableAttrTxID,
6565
blkstorage.IndexableAttrBlockNumTranNum,
66+
blkstorage.IndexableAttrBlockTxID,
6667
}
6768
indexConfig := &blkstorage.IndexConfig{AttrsToIndex: attrsToIndex}
6869
blockStoreProvider := fsblkstorage.NewProvider(

core/ledger/ledger_interface.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ type PeerLedger interface {
4343
GetTransactionByID(txID string) (*common.Envelope, error)
4444
// GetBlockByHash returns a block given it's hash
4545
GetBlockByHash(blockHash []byte) (*common.Block, error)
46+
// GetBlockByTxID returns a block which contains a transaction
47+
GetBlockByTxID(txID string) (*common.Block, error)
4648
// NewTxSimulator gives handle to a transaction simulator.
4749
// A client can obtain more than one 'TxSimulator's for parallel execution.
4850
// Any snapshoting/synchronization should be performed at the implementation level if required

0 commit comments

Comments
 (0)