Skip to content

Commit e49f25f

Browse files
Luis Sanchezdenyeart
Luis Sanchez
authored andcommitted
[FAB-2214] 1st block in chain is block 0, not 1
Made the following changes to fsblkstorage provider: * Block numbers start at 0, not 1. * Blockchain height should be last block number + 1. * A block's Block.Header.Number should be equal to the Blockchain height when AddBlock() is called. * Updated ledger tests to use random temporary dir. * Update core endorser tests to generate valid block numbers. Change-Id: I0208cd6a4b9da462c29d06126fa651f4c0dcd2fc Signed-off-by: Luis Sanchez <[email protected]>
1 parent 351f1b8 commit e49f25f

32 files changed

+564
-436
lines changed

common/ledger/blkstorage/fsblkstorage/block_stream_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestBlockfileStream(t *testing.T) {
3030
}
3131

3232
func testBlockfileStream(t *testing.T, numBlocks int) {
33-
env := newTestEnv(t, NewConf(testPath, 0))
33+
env := newTestEnv(t, NewConf(testPath(), 0))
3434
defer env.Cleanup()
3535
ledgerid := "testledger"
3636
w := newTestBlockfileWrapper(env, ledgerid)
@@ -71,7 +71,7 @@ func TestBlockFileStreamUnexpectedEOF(t *testing.T) {
7171
}
7272

7373
func testBlockFileStreamUnexpectedEOF(t *testing.T, numBlocks int, partialBlockBytes []byte) {
74-
env := newTestEnv(t, NewConf(testPath, 0))
74+
env := newTestEnv(t, NewConf(testPath(), 0))
7575
defer env.Cleanup()
7676
w := newTestBlockfileWrapper(env, "testLedger")
7777
blockfileMgr := w.blockfileMgr
@@ -100,7 +100,7 @@ func TestBlockStream(t *testing.T) {
100100
}
101101

102102
func testBlockStream(t *testing.T, numFiles int) {
103-
env := newTestEnv(t, NewConf(testPath, 0))
103+
env := newTestEnv(t, NewConf(testPath(), 0))
104104
defer env.Cleanup()
105105
w := newTestBlockfileWrapper(env, "testLedger")
106106
defer w.close()

common/ledger/blkstorage/fsblkstorage/blockfile_mgr.go

+41-13
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func newBlockfileMgr(id string, conf *Conf, indexConfig *blkstorage.IndexConfig,
117117
panic(fmt.Sprintf("Could not get block file info for current block file from db: %s", err))
118118
}
119119
if cpInfo == nil { //if no cpInfo stored in db initiate to zero
120-
cpInfo = &checkpointInfo{latestFileChunkSuffixNum: 0, latestFileChunksize: 0}
120+
cpInfo = &checkpointInfo{0, 0, true, 0}
121121
err = mgr.saveCurrentInfo(cpInfo, true)
122122
if err != nil {
123123
panic(fmt.Sprintf("Could not save next block file info to db: %s", err))
@@ -159,15 +159,15 @@ func newBlockfileMgr(id string, conf *Conf, indexConfig *blkstorage.IndexConfig,
159159
PreviousBlockHash: nil}
160160

161161
//If start up is a restart of an existing storage, update BlockchainInfo for external API's
162-
if cpInfo.lastBlockNumber > 0 {
162+
if !cpInfo.isChainEmpty {
163163
lastBlockHeader, err := mgr.retrieveBlockHeaderByNumber(cpInfo.lastBlockNumber)
164164
if err != nil {
165165
panic(fmt.Sprintf("Could not retrieve header of the last block form file: %s", err))
166166
}
167167
lastBlockHash := lastBlockHeader.Hash()
168168
previousBlockHash := lastBlockHeader.PreviousHash
169169
bcInfo = &common.BlockchainInfo{
170-
Height: cpInfo.lastBlockNumber,
170+
Height: cpInfo.lastBlockNumber + 1,
171171
CurrentBlockHash: lastBlockHash,
172172
PreviousBlockHash: previousBlockHash}
173173
}
@@ -202,9 +202,17 @@ func syncCPInfoFromFS(rootDir string, cpInfo *checkpointInfo) {
202202
if err != nil {
203203
panic(fmt.Sprintf("Could not open current file for detecting last block in the file: %s", err))
204204
}
205-
//Updates the checkpoint info for the actual last block number stored and it's end location
206-
cpInfo.lastBlockNumber += uint64(numBlocks)
207205
cpInfo.latestFileChunksize = int(endOffsetLastBlock)
206+
if numBlocks == 0 {
207+
return
208+
}
209+
//Updates the checkpoint info for the actual last block number stored and it's end location
210+
if cpInfo.isChainEmpty {
211+
cpInfo.lastBlockNumber = uint64(numBlocks - 1)
212+
} else {
213+
cpInfo.lastBlockNumber += uint64(numBlocks)
214+
}
215+
cpInfo.isChainEmpty = false
208216
logger.Debugf("Checkpoint after updates by scanning the last file segment:%s", cpInfo)
209217
}
210218

@@ -242,6 +250,9 @@ func (mgr *blockfileMgr) moveToNextFile() {
242250
}
243251

244252
func (mgr *blockfileMgr) addBlock(block *common.Block) error {
253+
if block.Header.Number != mgr.getBlockchainInfo().Height {
254+
return fmt.Errorf("Block number should have been %d but was %d", mgr.getBlockchainInfo().Height, block.Header.Number)
255+
}
245256
blockBytes, info, err := serializeBlock(block)
246257
if err != nil {
247258
return fmt.Errorf("Error while serializing block: %s", err)
@@ -282,6 +293,7 @@ func (mgr *blockfileMgr) addBlock(block *common.Block) error {
282293
newCPInfo := &checkpointInfo{
283294
latestFileChunkSuffixNum: currentCPInfo.latestFileChunkSuffixNum,
284295
latestFileChunksize: currentCPInfo.latestFileChunksize + totalBytesToAppend,
296+
isChainEmpty: false,
285297
lastBlockNumber: block.Header.Number}
286298
//save the checkpoint information in the database
287299
if err = mgr.saveCurrentInfo(newCPInfo, false); err != nil {
@@ -312,20 +324,24 @@ func (mgr *blockfileMgr) addBlock(block *common.Block) error {
312324

313325
func (mgr *blockfileMgr) syncIndex() error {
314326
var lastBlockIndexed uint64
327+
var indexEmpty bool
315328
var err error
316329
//from the database, get the last block that was indexed
317330
if lastBlockIndexed, err = mgr.index.getLastBlockIndexed(); err != nil {
318-
return err
331+
if err != errIndexEmpty {
332+
return err
333+
}
334+
indexEmpty = true
319335
}
320-
//initialize index to file number:zero, offset:zero and block:1
336+
//initialize index to file number:zero, offset:zero and blockNum:0
321337
startFileNum := 0
322338
startOffset := 0
323-
blockNum := uint64(1)
339+
blockNum := uint64(0)
324340
skipFirstBlock := false
325341
//get the last file that blocks were added to using the checkpoint info
326342
endFileNum := mgr.cpInfo.latestFileChunkSuffixNum
327343
//if the index stored in the db has value, update the index information with those values
328-
if lastBlockIndexed != 0 {
344+
if !indexEmpty {
329345
var flp *fileLocPointer
330346
if flp, err = mgr.index.getBlockLocByBlockNum(lastBlockIndexed); err != nil {
331347
return err
@@ -428,7 +444,7 @@ func (mgr *blockfileMgr) retrieveBlockByNumber(blockNum uint64) (*common.Block,
428444

429445
// interpret math.MaxUint64 as a request for last block
430446
if blockNum == math.MaxUint64 {
431-
blockNum = mgr.getBlockchainInfo().Height
447+
blockNum = mgr.getBlockchainInfo().Height - 1
432448
}
433449

434450
loc, err := mgr.index.getBlockLocByBlockNum(blockNum)
@@ -597,6 +613,7 @@ func scanForLastCompleteBlock(rootDir string, fileNum int, startingOffset int64)
597613
type checkpointInfo struct {
598614
latestFileChunkSuffixNum int
599615
latestFileChunksize int
616+
isChainEmpty bool
600617
lastBlockNumber uint64
601618
}
602619

@@ -612,12 +629,20 @@ func (i *checkpointInfo) marshal() ([]byte, error) {
612629
if err = buffer.EncodeVarint(i.lastBlockNumber); err != nil {
613630
return nil, err
614631
}
632+
var chainEmptyMarker uint64
633+
if i.isChainEmpty {
634+
chainEmptyMarker = 1
635+
}
636+
if err = buffer.EncodeVarint(chainEmptyMarker); err != nil {
637+
return nil, err
638+
}
615639
return buffer.Bytes(), nil
616640
}
617641

618642
func (i *checkpointInfo) unmarshal(b []byte) error {
619643
buffer := proto.NewBuffer(b)
620644
var val uint64
645+
var chainEmptyMarker uint64
621646
var err error
622647

623648
if val, err = buffer.DecodeVarint(); err != nil {
@@ -634,11 +659,14 @@ func (i *checkpointInfo) unmarshal(b []byte) error {
634659
return err
635660
}
636661
i.lastBlockNumber = val
637-
662+
if chainEmptyMarker, err = buffer.DecodeVarint(); err != nil {
663+
return err
664+
}
665+
i.isChainEmpty = chainEmptyMarker == 1
638666
return nil
639667
}
640668

641669
func (i *checkpointInfo) String() string {
642-
return fmt.Sprintf("latestFileChunkSuffixNum=[%d], latestFileChunksize=[%d], lastBlockNumber=[%d]",
643-
i.latestFileChunkSuffixNum, i.latestFileChunksize, i.lastBlockNumber)
670+
return fmt.Sprintf("latestFileChunkSuffixNum=[%d], latestFileChunksize=[%d], isChainEmpty=[%t], lastBlockNumber=[%d]",
671+
i.latestFileChunkSuffixNum, i.latestFileChunksize, i.isChainEmpty, i.lastBlockNumber)
644672
}

common/ledger/blkstorage/fsblkstorage/blockfile_mgr_test.go

+25-21
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ import (
2828
)
2929

3030
func TestBlockfileMgrBlockReadWrite(t *testing.T) {
31-
env := newTestEnv(t, NewConf(testPath, 0))
31+
env := newTestEnv(t, NewConf(testPath(), 0))
3232
defer env.Cleanup()
3333
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
3434
defer blkfileMgrWrapper.close()
3535
blocks := testutil.ConstructTestBlocks(t, 10)
3636
blkfileMgrWrapper.addBlocks(blocks)
3737
blkfileMgrWrapper.testGetBlockByHash(blocks)
38-
blkfileMgrWrapper.testGetBlockByNumber(blocks, 1)
38+
blkfileMgrWrapper.testGetBlockByNumber(blocks, 0)
3939
}
4040

4141
func TestBlockfileMgrCrashDuringWriting(t *testing.T) {
@@ -47,7 +47,7 @@ func TestBlockfileMgrCrashDuringWriting(t *testing.T) {
4747

4848
func testBlockfileMgrCrashDuringWriting(t *testing.T, numBlocksBeforeCheckpoint int,
4949
numBlocksAfterCheckpoint int, numLastBlockBytes int, numPartialBytesToWrite int) {
50-
env := newTestEnv(t, NewConf(testPath, 0))
50+
env := newTestEnv(t, NewConf(testPath(), 0))
5151
defer env.Cleanup()
5252
ledgerid := "testLedger"
5353
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
@@ -58,6 +58,7 @@ func testBlockfileMgrCrashDuringWriting(t *testing.T, numBlocksBeforeCheckpoint
5858
cpInfo1 := &checkpointInfo{
5959
currentCPInfo.latestFileChunkSuffixNum,
6060
currentCPInfo.latestFileChunksize,
61+
currentCPInfo.isChainEmpty,
6162
currentCPInfo.lastBlockNumber}
6263

6364
blocksAfterCP := bg.NextTestBlocks(numBlocksAfterCheckpoint)
@@ -88,17 +89,17 @@ func testBlockfileMgrCrashDuringWriting(t *testing.T, numBlocksBeforeCheckpoint
8889
allBlocks = append(allBlocks, blocksBeforeCP...)
8990
allBlocks = append(allBlocks, blocksAfterCP...)
9091
allBlocks = append(allBlocks, blocksAfterRestart...)
91-
testBlockfileMgrBlockIterator(t, blkfileMgrWrapper.blockfileMgr, 1, len(allBlocks), allBlocks)
92+
testBlockfileMgrBlockIterator(t, blkfileMgrWrapper.blockfileMgr, 0, len(allBlocks)-1, allBlocks)
9293
}
9394

9495
func TestBlockfileMgrBlockIterator(t *testing.T) {
95-
env := newTestEnv(t, NewConf(testPath, 0))
96+
env := newTestEnv(t, NewConf(testPath(), 0))
9697
defer env.Cleanup()
9798
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
9899
defer blkfileMgrWrapper.close()
99100
blocks := testutil.ConstructTestBlocks(t, 10)
100101
blkfileMgrWrapper.addBlocks(blocks)
101-
testBlockfileMgrBlockIterator(t, blkfileMgrWrapper.blockfileMgr, 1, 8, blocks[0:8])
102+
testBlockfileMgrBlockIterator(t, blkfileMgrWrapper.blockfileMgr, 0, 7, blocks[0:8])
102103
}
103104

104105
func testBlockfileMgrBlockIterator(t *testing.T, blockfileMgr *blockfileMgr,
@@ -120,7 +121,7 @@ func testBlockfileMgrBlockIterator(t *testing.T, blockfileMgr *blockfileMgr,
120121
}
121122

122123
func TestBlockfileMgrBlockchainInfo(t *testing.T) {
123-
env := newTestEnv(t, NewConf(testPath, 0))
124+
env := newTestEnv(t, NewConf(testPath(), 0))
124125
defer env.Cleanup()
125126
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
126127
defer blkfileMgrWrapper.close()
@@ -135,7 +136,7 @@ func TestBlockfileMgrBlockchainInfo(t *testing.T) {
135136
}
136137

137138
func TestBlockfileMgrGetTxById(t *testing.T) {
138-
env := newTestEnv(t, NewConf(testPath, 0))
139+
env := newTestEnv(t, NewConf(testPath(), 0))
139140
defer env.Cleanup()
140141
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
141142
defer blkfileMgrWrapper.close()
@@ -156,7 +157,7 @@ func TestBlockfileMgrGetTxById(t *testing.T) {
156157
}
157158

158159
func TestBlockfileMgrGetTxByBlockNumTranNum(t *testing.T) {
159-
env := newTestEnv(t, NewConf(testPath, 0))
160+
env := newTestEnv(t, NewConf(testPath(), 0))
160161
defer env.Cleanup()
161162
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
162163
defer blkfileMgrWrapper.close()
@@ -165,7 +166,7 @@ func TestBlockfileMgrGetTxByBlockNumTranNum(t *testing.T) {
165166
for blockIndex, blk := range blocks {
166167
for tranIndex, txEnvelopeBytes := range blk.Data.Data {
167168
// blockNum starts with 1, tranNum starts with 1
168-
txEnvelopeFromFileMgr, err := blkfileMgrWrapper.blockfileMgr.retrieveTransactionByBlockNumTranNum(uint64(blockIndex+1), uint64(tranIndex+1))
169+
txEnvelopeFromFileMgr, err := blkfileMgrWrapper.blockfileMgr.retrieveTransactionByBlockNumTranNum(uint64(blockIndex), uint64(tranIndex+1))
169170
testutil.AssertNoError(t, err, "Error while retrieving tx from blkfileMgr")
170171
txEnvelope, err := putil.GetEnvelopeFromBlock(txEnvelopeBytes)
171172
testutil.AssertNoError(t, err, "Error while unmarshalling tx")
@@ -175,24 +176,27 @@ func TestBlockfileMgrGetTxByBlockNumTranNum(t *testing.T) {
175176
}
176177

177178
func TestBlockfileMgrRestart(t *testing.T) {
178-
env := newTestEnv(t, NewConf(testPath, 0))
179+
env := newTestEnv(t, NewConf(testPath(), 0))
179180
defer env.Cleanup()
180181
ledgerid := "testLedger"
181182
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
182183
blocks := testutil.ConstructTestBlocks(t, 10)
183184
blkfileMgrWrapper.addBlocks(blocks)
185+
expectedHeight := uint64(10)
186+
testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.getBlockchainInfo().Height, expectedHeight)
184187
blkfileMgrWrapper.close()
185188

186189
blkfileMgrWrapper = newTestBlockfileWrapper(env, ledgerid)
187190
defer blkfileMgrWrapper.close()
188-
testutil.AssertEquals(t, int(blkfileMgrWrapper.blockfileMgr.cpInfo.lastBlockNumber), 10)
191+
testutil.AssertEquals(t, int(blkfileMgrWrapper.blockfileMgr.cpInfo.lastBlockNumber), 9)
189192
blkfileMgrWrapper.testGetBlockByHash(blocks)
193+
testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.getBlockchainInfo().Height, expectedHeight)
190194
}
191195

192196
func TestBlockfileMgrFileRolling(t *testing.T) {
193-
blocks := testutil.ConstructTestBlocks(t, 100)
197+
blocks := testutil.ConstructTestBlocks(t, 200)
194198
size := 0
195-
for _, block := range blocks {
199+
for _, block := range blocks[:100] {
196200
by, _, err := serializeBlock(block)
197201
testutil.AssertNoError(t, err, "Error while serializing block")
198202
blockBytesSize := len(by)
@@ -201,31 +205,31 @@ func TestBlockfileMgrFileRolling(t *testing.T) {
201205
}
202206

203207
maxFileSie := int(0.75 * float64(size))
204-
env := newTestEnv(t, NewConf(testPath, maxFileSie))
208+
env := newTestEnv(t, NewConf(testPath(), maxFileSie))
205209
defer env.Cleanup()
206210
ledgerid := "testLedger"
207211
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
208-
blkfileMgrWrapper.addBlocks(blocks)
212+
blkfileMgrWrapper.addBlocks(blocks[:100])
209213
testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.cpInfo.latestFileChunkSuffixNum, 1)
210-
blkfileMgrWrapper.testGetBlockByHash(blocks)
214+
blkfileMgrWrapper.testGetBlockByHash(blocks[:100])
211215
blkfileMgrWrapper.close()
212216

213217
blkfileMgrWrapper = newTestBlockfileWrapper(env, ledgerid)
214218
defer blkfileMgrWrapper.close()
215-
blkfileMgrWrapper.addBlocks(blocks)
219+
blkfileMgrWrapper.addBlocks(blocks[100:])
216220
testutil.AssertEquals(t, blkfileMgrWrapper.blockfileMgr.cpInfo.latestFileChunkSuffixNum, 2)
217-
blkfileMgrWrapper.testGetBlockByHash(blocks)
221+
blkfileMgrWrapper.testGetBlockByHash(blocks[100:])
218222
}
219223

220224
func TestBlockfileMgrGetBlockByTxID(t *testing.T) {
221-
env := newTestEnv(t, NewConf(testPath, 0))
225+
env := newTestEnv(t, NewConf(testPath(), 0))
222226
defer env.Cleanup()
223227
blkfileMgrWrapper := newTestBlockfileWrapper(env, "testLedger")
224228
defer blkfileMgrWrapper.close()
225229
blocks := testutil.ConstructTestBlocks(t, 10)
226230
blkfileMgrWrapper.addBlocks(blocks)
227231
for _, blk := range blocks {
228-
for j, _ := range blk.Data.Data {
232+
for j := range blk.Data.Data {
229233
// blockNum starts with 1
230234
txID, err := extractTxID(blk.Data.Data[j])
231235
testutil.AssertNoError(t, err, "")

common/ledger/blkstorage/fsblkstorage/blockfile_scan_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import (
2727
)
2828

2929
func TestBlockFileScanSmallTxOnly(t *testing.T) {
30-
env := newTestEnv(t, NewConf(testPath, 0))
30+
env := newTestEnv(t, NewConf(testPath(), 0))
3131
defer env.Cleanup()
3232
ledgerid := "testLedger"
3333
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)
@@ -50,7 +50,7 @@ func TestBlockFileScanSmallTxOnly(t *testing.T) {
5050
}
5151

5252
func TestBlockFileScanSmallTxLastTxIncomplete(t *testing.T) {
53-
env := newTestEnv(t, NewConf(testPath, 0))
53+
env := newTestEnv(t, NewConf(testPath(), 0))
5454
defer env.Cleanup()
5555
ledgerid := "testLedger"
5656
blkfileMgrWrapper := newTestBlockfileWrapper(env, ledgerid)

common/ledger/blkstorage/fsblkstorage/blockindex.go

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package fsblkstorage
1818

1919
import (
2020
"bytes"
21+
"errors"
2122
"fmt"
2223

2324
"github.com/golang/protobuf/proto"
@@ -36,6 +37,7 @@ const (
3637
)
3738

3839
var indexCheckpointKey = []byte(indexCheckpointKeyStr)
40+
var errIndexEmpty = errors.New("NoBlockIndexed")
3941

4042
type index interface {
4143
getLastBlockIndexed() (uint64, error)
@@ -75,6 +77,9 @@ func (index *blockIndex) getLastBlockIndexed() (uint64, error) {
7577
if blockNumBytes, err = index.db.Get(indexCheckpointKey); err != nil {
7678
return 0, nil
7779
}
80+
if blockNumBytes == nil {
81+
return 0, errIndexEmpty
82+
}
7883
return decodeBlockNum(blockNumBytes), nil
7984
}
8085

0 commit comments

Comments
 (0)