@@ -598,6 +598,7 @@ func (api *Server) readState(ctx context.Context, in *iotexapi.ReadStateRequest)
598598}
599599
600600// GetActions returns actions within the range
601+ // This is a workaround for the slow access issue if the start index is very big
601602func (api * Server ) getActions (start uint64 , count uint64 ) (* iotexapi.GetActionsResponse , error ) {
602603 if count == 0 || count > api .cfg .RangeQueryLimit {
603604 return nil , status .Error (codes .InvalidArgument , "range exceeds the limit" )
@@ -611,23 +612,30 @@ func (api *Server) getActions(start uint64, count uint64) (*iotexapi.GetActionsR
611612 return nil , status .Error (codes .InvalidArgument , "start exceeds the limit" )
612613 }
613614
615+ // Finding actions in reverse order saves time for querying most recent actions
616+ reverseStart := totalActions - (start + count )
617+ if totalActions < start + count {
618+ reverseStart = uint64 (0 )
619+ count = totalActions - start
620+ }
621+
614622 var res []* iotexapi.ActionInfo
615623 var hit bool
616- for height := uint64 ( 1 ); height <= api . bc . TipHeight () && count > 0 ; height ++ {
624+ for height := api . bc . TipHeight ( ); height >= 1 && count > 0 ; height -- {
617625 blk , err := api .bc .GetBlockByHeight (height )
618626 if err != nil {
619627 return nil , status .Error (codes .NotFound , err .Error ())
620628 }
621- if ! hit && start >= uint64 (len (blk .Actions )) {
622- start -= uint64 (len (blk .Actions ))
629+ if ! hit && reverseStart >= uint64 (len (blk .Actions )) {
630+ reverseStart -= uint64 (len (blk .Actions ))
623631 continue
624632 }
625- // now start < len(blk.Actions), we are going to fetch actions from this block
633+ // now reverseStart < len(blk.Actions), we are going to fetch actions from this block
626634 hit = true
627- act := api .actionsInBlock (blk , start , count )
628- res = append (res , act ... )
635+ act := api .reverseActionsInBlock (blk , reverseStart , count )
636+ res = append (act , res ... )
629637 count -= uint64 (len (act ))
630- start = 0
638+ reverseStart = 0
631639 }
632640 return & iotexapi.GetActionsResponse {
633641 Total : totalActions ,
@@ -919,6 +927,32 @@ func (api *Server) actionsInBlock(blk *block.Block, start, count uint64) []*iote
919927 return res
920928}
921929
930+ func (api * Server ) reverseActionsInBlock (blk * block.Block , reverseStart , count uint64 ) []* iotexapi.ActionInfo {
931+ h := blk .HashBlock ()
932+ blkHash := hex .EncodeToString (h [:])
933+ blkHeight := blk .Height ()
934+ ts := blk .Header .BlockHeaderCoreProto ().Timestamp
935+
936+ var res []* iotexapi.ActionInfo
937+ for i := reverseStart ; i < uint64 (len (blk .Actions )) && i < reverseStart + count ; i ++ {
938+ ri := uint64 (len (blk .Actions )) - 1 - i
939+ selp := blk .Actions [ri ]
940+ actHash := selp .Hash ()
941+ sender , _ := address .FromBytes (selp .SrcPubkey ().Hash ())
942+ res = append ([]* iotexapi.ActionInfo {
943+ {
944+ Action : selp .Proto (),
945+ ActHash : hex .EncodeToString (actHash [:]),
946+ BlkHash : blkHash ,
947+ BlkHeight : blkHeight ,
948+ Sender : sender .String (),
949+ Timestamp : ts ,
950+ },
951+ }, res ... )
952+ }
953+ return res
954+ }
955+
922956func getTranferAmountInBlock (blk * block.Block ) * big.Int {
923957 totalAmount := big .NewInt (0 )
924958 for _ , selp := range blk .Actions {
0 commit comments