@@ -159,7 +159,7 @@ public enum RequestSource {
159159
160160 private static final String JSON_ERROR = "invalid json request" ;
161161 private static final String TAG_NOT_SUPPORT_ERROR =
162- "TAG [earliest | pending | finalized] not supported" ;
162+ "TAG [earliest | pending | finalized | safe ] not supported" ;
163163 private static final String QUANTITY_NOT_SUPPORT_ERROR =
164164 "QUANTITY not supported, just support TAG as latest" ;
165165 private static final String NO_BLOCK_HEADER = "header not found" ;
@@ -305,20 +305,7 @@ public String ethGetBlockTransactionCountByHash(String blockHash)
305305 @ Override
306306 public String ethGetBlockTransactionCountByNumber (String blockNumOrTag )
307307 throws JsonRpcInvalidParamsException {
308- long blockNum ;
309- if (JsonRpcApiUtil .isBlockTag (blockNumOrTag )) {
310- blockNum = JsonRpcApiUtil .parseBlockTag (blockNumOrTag , wallet );
311- } else {
312- try {
313- // hexToBigInteger: 0x -> hex, bare number -> decimal.
314- // Preserving original behavior. LogFilterWrapper uses
315- // strict jsonHexToLong (0x required) via parseBlockNumber.
316- blockNum = ByteArray .hexToBigInteger (blockNumOrTag ).longValue ();
317- } catch (Exception e ) {
318- throw new JsonRpcInvalidParamsException (BLOCK_NUM_ERROR );
319- }
320- }
321- Block block = wallet .getBlockByNum (blockNum );
308+ Block block = getBlockByNumOrTag (blockNumOrTag );
322309 if (block == null ) {
323310 return null ;
324311 }
@@ -337,17 +324,7 @@ public BlockResult ethGetBlockByHash(String blockHash, Boolean fullTransactionOb
337324 @ Override
338325 public BlockResult ethGetBlockByNumber (String blockNumOrTag , Boolean fullTransactionObjects )
339326 throws JsonRpcInvalidParamsException {
340- long blockNum ;
341- if (JsonRpcApiUtil .isBlockTag (blockNumOrTag )) {
342- blockNum = JsonRpcApiUtil .parseBlockTag (blockNumOrTag , wallet );
343- } else {
344- try {
345- blockNum = ByteArray .hexToBigInteger (blockNumOrTag ).longValue ();
346- } catch (Exception e ) {
347- throw new JsonRpcInvalidParamsException (BLOCK_NUM_ERROR );
348- }
349- }
350- final Block b = wallet .getBlockByNum (blockNum );
327+ final Block b = getBlockByNumOrTag (blockNumOrTag );
351328 return (b == null ? null : getBlockResult (b , fullTransactionObjects ));
352329 }
353330
@@ -390,6 +367,24 @@ private Block getBlockByJsonHash(String blockHash) throws JsonRpcInvalidParamsEx
390367 return wallet .getBlockById (ByteString .copyFrom (bHash ));
391368 }
392369
370+ private Block getBlockByNumOrTag (String blockNumOrTag ) throws JsonRpcInvalidParamsException {
371+ long blockNum ;
372+ if (JsonRpcApiUtil .isBlockTag (blockNumOrTag )) {
373+ if (LATEST_STR .equalsIgnoreCase (blockNumOrTag )) {
374+ // Read the head block directly from blockStore to avoid the window where
375+ // getNowBlock() already sees the new head but getBlockByNum() still misses it.
376+ return wallet .getNowBlock ();
377+ }
378+ return wallet .getBlockByNum (JsonRpcApiUtil .parseBlockTag (blockNumOrTag , wallet ));
379+ }
380+ try {
381+ blockNum = ByteArray .hexToBigInteger (blockNumOrTag ).longValueExact ();
382+ } catch (Exception e ) {
383+ throw new JsonRpcInvalidParamsException (BLOCK_NUM_ERROR );
384+ }
385+ return wallet .getBlockByNum (blockNum );
386+ }
387+
393388 private BlockResult getBlockResult (Block block , boolean fullTx ) {
394389 if (block == null ) {
395390 return null ;
@@ -806,17 +801,7 @@ public TransactionResult getTransactionByBlockHashAndIndex(String blockHash, Str
806801 @ Override
807802 public TransactionResult getTransactionByBlockNumberAndIndex (String blockNumOrTag , String index )
808803 throws JsonRpcInvalidParamsException {
809- long blockNum ;
810- if (JsonRpcApiUtil .isBlockTag (blockNumOrTag )) {
811- blockNum = JsonRpcApiUtil .parseBlockTag (blockNumOrTag , wallet );
812- } else {
813- try {
814- blockNum = ByteArray .hexToBigInteger (blockNumOrTag ).longValue ();
815- } catch (Exception e ) {
816- throw new JsonRpcInvalidParamsException (BLOCK_NUM_ERROR );
817- }
818- }
819- Block block = wallet .getBlockByNum (blockNum );
804+ Block block = getBlockByNumOrTag (blockNumOrTag );
820805 if (block == null ) {
821806 return null ;
822807 }
@@ -907,17 +892,7 @@ public List<TransactionReceipt> getBlockReceipts(String blockNumOrHashOrTag)
907892 if (Pattern .matches (HASH_REGEX , blockNumOrHashOrTag )) {
908893 block = getBlockByJsonHash (blockNumOrHashOrTag );
909894 } else {
910- long blockNum ;
911- if (JsonRpcApiUtil .isBlockTag (blockNumOrHashOrTag )) {
912- blockNum = JsonRpcApiUtil .parseBlockTag (blockNumOrHashOrTag , wallet );
913- } else {
914- try {
915- blockNum = ByteArray .hexToBigInteger (blockNumOrHashOrTag ).longValue ();
916- } catch (Exception e ) {
917- throw new JsonRpcInvalidParamsException (BLOCK_NUM_ERROR );
918- }
919- }
920- block = wallet .getBlockByNum (blockNum );
895+ block = getBlockByNumOrTag (blockNumOrHashOrTag );
921896 }
922897
923898 // block receipts not available: block is genesis, not produced yet, or pruned in light node
0 commit comments