@@ -35,11 +35,8 @@ const (
3535 // blockNamespace is prepended to any stored block.
3636 blockNamespace = "block"
3737
38- // blockHashNamespace is prepended to any stored block hash.
39- // We cannot just use the stored block key to lookup whether
40- // a hash has been used before because it is concatenated
41- // with the index of the stored block.
42- blockHashNamespace = "block-hash"
38+ // blockIndexNamespace is prepended to any stored block index.
39+ blockIndexNamespace = "block-index"
4340
4441 // transactionHashNamespace is prepended to any stored
4542 // transaction hash.
5552 // found in BlockStorage.
5653 ErrBlockNotFound = errors .New ("block not found" )
5754
58- // ErrDuplicateBlockHash is returned when a block hash
55+ // ErrDuplicateKey is returned when a key
5956 // cannot be stored because it is a duplicate.
60- ErrDuplicateBlockHash = errors .New ("duplicate block hash " )
57+ ErrDuplicateKey = errors .New ("duplicate key " )
6158
6259 // ErrDuplicateTransactionHash is returned when a transaction
6360 // hash cannot be stored because it is a duplicate.
@@ -68,14 +65,12 @@ func getHeadBlockKey() []byte {
6865 return []byte (headBlockKey )
6966}
7067
71- func getBlockKey (blockIdentifier * types.BlockIdentifier ) []byte {
72- return []byte (
73- fmt .Sprintf ("%s/%s/%d" , blockNamespace , blockIdentifier .Hash , blockIdentifier .Index ),
74- )
68+ func getBlockHashKey (hash string ) []byte {
69+ return []byte (fmt .Sprintf ("%s/%s" , blockNamespace , hash ))
7570}
7671
77- func getBlockHashKey ( blockIdentifier * types. BlockIdentifier ) []byte {
78- return []byte (fmt .Sprintf ("%s/%s " , blockHashNamespace , blockIdentifier . Hash ))
72+ func getBlockIndexKey ( index int64 ) []byte {
73+ return []byte (fmt .Sprintf ("%s/%d " , blockIndexNamespace , index ))
7974}
8075
8176func getTransactionHashKey (transactionIdentifier * types.TransactionIdentifier ) []byte {
@@ -174,18 +169,42 @@ func (b *BlockStorage) StoreHeadBlockIdentifier(
174169// GetBlock returns a block, if it exists.
175170func (b * BlockStorage ) GetBlock (
176171 ctx context.Context ,
177- blockIdentifier * types.BlockIdentifier ,
172+ blockIdentifier * types.PartialBlockIdentifier ,
178173) (* types.Block , error ) {
179174 transaction := b .db .NewDatabaseTransaction (ctx , false )
180175 defer transaction .Discard (ctx )
181176
182- exists , block , err := transaction .Get (ctx , getBlockKey (blockIdentifier ))
177+ var exists bool
178+ var block []byte
179+ var err error
180+ switch {
181+ case blockIdentifier == nil || (blockIdentifier .Hash == nil && blockIdentifier .Index == nil ):
182+ // Get current block when no blockIdentifier is provided
183+ var head * types.BlockIdentifier
184+ head , err = b .GetHeadBlockIdentifierTransactional (ctx , transaction )
185+ if err != nil {
186+ return nil , fmt .Errorf ("%w: cannot get head block identifier" , err )
187+ }
188+
189+ exists , block , err = transaction .Get (ctx , getBlockHashKey (head .Hash ))
190+ case blockIdentifier .Hash != nil :
191+ // Get block by hash if provided
192+ exists , block , err = transaction .Get (ctx , getBlockHashKey (* blockIdentifier .Hash ))
193+ default :
194+ // Get block by index if hash not provided
195+ var blockKey []byte
196+ exists , blockKey , err = transaction .Get (ctx , getBlockIndexKey (* blockIdentifier .Index ))
197+ if exists {
198+ exists , block , err = transaction .Get (ctx , blockKey )
199+ }
200+ }
201+
183202 if err != nil {
184- return nil , err
203+ return nil , fmt . Errorf ( "%w: unable to get block" , err )
185204 }
186205
187206 if ! exists {
188- return nil , fmt .Errorf ("%w %+v" , ErrBlockNotFound , blockIdentifier )
207+ return nil , fmt .Errorf ("%w: %+v" , ErrBlockNotFound , blockIdentifier )
189208 }
190209
191210 var rosettaBlock types.Block
@@ -197,33 +216,48 @@ func (b *BlockStorage) GetBlock(
197216 return & rosettaBlock , nil
198217}
199218
200- // AddBlock stores a block or returns an error.
201- func (b * BlockStorage ) AddBlock (
219+ func (b * BlockStorage ) storeBlock (
202220 ctx context.Context ,
221+ transaction DatabaseTransaction ,
203222 block * types.Block ,
204223) error {
205- transaction := b .db .NewDatabaseTransaction (ctx , true )
206- defer transaction .Discard (ctx )
207-
208224 buf , err := encode (block )
209225 if err != nil {
210- return err
226+ return fmt . Errorf ( "%w: unable to encode block" , err )
211227 }
212228
213- // Store block
214- err = transaction .Set (ctx , getBlockKey (block .BlockIdentifier ), buf )
215- if err != nil {
216- return err
229+ if err := b .storeUniqueKey (ctx , transaction , getBlockHashKey (block .BlockIdentifier .Hash ), buf ); err != nil {
230+ return fmt .Errorf ("%w: unable to store block" , err )
217231 }
218232
219- if err = b .StoreHeadBlockIdentifier (ctx , transaction , block .BlockIdentifier ); err != nil {
220- return err
233+ if err := b .storeUniqueKey (
234+ ctx ,
235+ transaction ,
236+ getBlockIndexKey (block .BlockIdentifier .Index ),
237+ getBlockHashKey (block .BlockIdentifier .Hash ),
238+ ); err != nil {
239+ return fmt .Errorf ("%w: unable to store block index" , err )
240+ }
241+
242+ if err := b .StoreHeadBlockIdentifier (ctx , transaction , block .BlockIdentifier ); err != nil {
243+ return fmt .Errorf ("%w: unable to update head block identifier" , err )
221244 }
222245
223- // Store block hash
224- err = b .storeBlockHash (ctx , transaction , block .BlockIdentifier )
246+ return nil
247+ }
248+
249+ // AddBlock stores a block or returns an error.
250+ func (b * BlockStorage ) AddBlock (
251+ ctx context.Context ,
252+ block * types.Block ,
253+ ) error {
254+ transaction := b .db .NewDatabaseTransaction (ctx , true )
255+ defer transaction .Discard (ctx )
256+
257+ // Store block
258+ err := b .storeBlock (ctx , transaction , block )
225259 if err != nil {
226- return fmt .Errorf ("%w: unable to store block hash " , err )
260+ return fmt .Errorf ("%w: unable to store block" , err )
227261 }
228262
229263 // Store all transaction hashes
@@ -242,6 +276,27 @@ func (b *BlockStorage) AddBlock(
242276 return b .callWorkersAndCommit (ctx , block , transaction , true )
243277}
244278
279+ func (b * BlockStorage ) deleteBlock (
280+ ctx context.Context ,
281+ transaction DatabaseTransaction ,
282+ block * types.Block ,
283+ ) error {
284+ blockIdentifier := block .BlockIdentifier
285+ if err := transaction .Delete (ctx , getBlockHashKey (blockIdentifier .Hash )); err != nil {
286+ return fmt .Errorf ("%w: unable to delete block" , err )
287+ }
288+
289+ if err := transaction .Delete (ctx , getBlockIndexKey (blockIdentifier .Index )); err != nil {
290+ return fmt .Errorf ("%w: unable to delete block index" , err )
291+ }
292+
293+ if err := b .StoreHeadBlockIdentifier (ctx , transaction , block .ParentBlockIdentifier ); err != nil {
294+ return fmt .Errorf ("%w: unable to update head block identifier" , err )
295+ }
296+
297+ return nil
298+ }
299+
245300// RemoveBlock removes a block or returns an error.
246301// RemoveBlock also removes the block hash and all
247302// its transaction hashes to not break duplicate
@@ -250,7 +305,7 @@ func (b *BlockStorage) RemoveBlock(
250305 ctx context.Context ,
251306 blockIdentifier * types.BlockIdentifier ,
252307) error {
253- block , err := b .GetBlock (ctx , blockIdentifier )
308+ block , err := b .GetBlock (ctx , types . ConstructPartialBlockIdentifier ( blockIdentifier ) )
254309 if err != nil {
255310 return err
256311 }
@@ -266,19 +321,9 @@ func (b *BlockStorage) RemoveBlock(
266321 }
267322 }
268323
269- // Remove block hash
270- err = transaction .Delete (ctx , getBlockHashKey (blockIdentifier ))
271- if err != nil {
272- return err
273- }
274-
275- // Remove block
276- if err := transaction .Delete (ctx , getBlockKey (blockIdentifier )); err != nil {
277- return err
278- }
279-
280- if err = b .StoreHeadBlockIdentifier (ctx , transaction , block .ParentBlockIdentifier ); err != nil {
281- return err
324+ // Delete block
325+ if err := b .deleteBlock (ctx , transaction , block ); err != nil {
326+ return fmt .Errorf ("%w: unable to delete block" , err )
282327 }
283328
284329 return b .callWorkersAndCommit (ctx , block , transaction , false )
@@ -348,7 +393,7 @@ func (b *BlockStorage) SetNewStartIndex(
348393 currBlock := head
349394 for currBlock .Index >= startIndex {
350395 log .Printf ("Removing block %+v\n " , currBlock )
351- block , err := b .GetBlock (ctx , currBlock )
396+ block , err := b .GetBlock (ctx , types . ConstructPartialBlockIdentifier ( currBlock ) )
352397 if err != nil {
353398 return err
354399 }
@@ -373,7 +418,7 @@ func (b *BlockStorage) CreateBlockCache(ctx context.Context) []*types.BlockIdent
373418 }
374419
375420 for len (cache ) < syncer .PastBlockSize {
376- block , err := b .GetBlock (ctx , head )
421+ block , err := b .GetBlock (ctx , types . ConstructPartialBlockIdentifier ( head ) )
377422 if err != nil {
378423 return cache
379424 }
@@ -392,22 +437,22 @@ func (b *BlockStorage) CreateBlockCache(ctx context.Context) []*types.BlockIdent
392437 return cache
393438}
394439
395- func (b * BlockStorage ) storeBlockHash (
440+ func (b * BlockStorage ) storeUniqueKey (
396441 ctx context.Context ,
397442 transaction DatabaseTransaction ,
398- block * types.BlockIdentifier ,
443+ key []byte ,
444+ value []byte ,
399445) error {
400- hashKey := getBlockHashKey (block )
401- exists , _ , err := transaction .Get (ctx , hashKey )
446+ exists , _ , err := transaction .Get (ctx , key )
402447 if err != nil {
403448 return err
404449 }
405450
406451 if exists {
407- return fmt .Errorf ("%w: duplicate block hash %s found" , ErrDuplicateBlockHash , block . Hash )
452+ return fmt .Errorf ("%w: duplicate key %s found" , ErrDuplicateKey , string ( key ) )
408453 }
409454
410- return transaction .Set (ctx , hashKey , [] byte ( "" ) )
455+ return transaction .Set (ctx , key , value )
411456}
412457
413458func (b * BlockStorage ) storeTransactionHash (
@@ -518,7 +563,7 @@ func (b *BlockStorage) FindTransaction(
518563 }
519564 }
520565
521- blockExists , block , err := txn .Get (ctx , getBlockKey (newestBlock ))
566+ blockExists , block , err := txn .Get (ctx , getBlockHashKey (newestBlock . Hash ))
522567 if err != nil {
523568 return nil , nil , fmt .Errorf ("%w: unable to query database for block" , err )
524569 }
@@ -554,15 +599,11 @@ func (b *BlockStorage) AtTip(
554599 ctx context.Context ,
555600 tipDelay int64 ,
556601) (bool , error ) {
557- head , err := b .GetHeadBlockIdentifier (ctx )
602+ block , err := b .GetBlock (ctx , nil )
558603 if errors .Is (err , ErrHeadBlockNotFound ) {
559604 return false , nil
560605 }
561- if err != nil {
562- return false , fmt .Errorf ("%w: unable to get head block identifir" , err )
563- }
564606
565- block , err := b .GetBlock (ctx , head )
566607 if err != nil {
567608 return false , fmt .Errorf ("%w: unable to get head block" , err )
568609 }
0 commit comments