@@ -25,6 +25,7 @@ public static class BlockStoreRouteEndPoint
2525 public const string GetVerboseAddressesBalances = "getverboseaddressesbalances" ;
2626 public const string GetAddressIndexerTip = "addressindexertip" ;
2727 public const string GetBlock = "block" ;
28+ public const string GetBlocks = "blocks" ;
2829 public const string GetBlockCount = "getblockcount" ;
2930 public const string GetUtxoSet = "getutxoset" ;
3031 public const string GetUtxoSetForAddress = "getutxosetforaddress" ;
@@ -149,29 +150,55 @@ public IActionResult GetBlock([FromQuery] SearchByHashRequest query)
149150 return this . Json ( block ) ;
150151 }
151152
152- BlockModel blockModel = query . ShowTransactionDetails
153- ? new BlockTransactionDetailsModel ( block , chainedHeader , this . chainIndexer . Tip , this . network )
154- : new BlockModel ( block , chainedHeader , this . chainIndexer . Tip , this . network ) ;
153+ return this . Json ( GetBlockModel ( block , blockId , chainedHeader , query . ShowTransactionDetails ) ) ;
154+ }
155+ catch ( Exception e )
156+ {
157+ this . logger . LogError ( "Exception occurred: {0}" , e . ToString ( ) ) ;
158+ return ErrorHelpers . BuildErrorResponse ( HttpStatusCode . BadRequest , e . Message , e . ToString ( ) ) ;
159+ }
160+ }
155161
156- if ( this . network . Consensus . IsProofOfStake )
157- {
158- var posBlock = block as PosBlock ;
159162
160- blockModel . PosBlockSignature = posBlock . BlockSignature . ToHex ( this . network ) ;
161- blockModel . PosBlockTrust = new Target ( chainedHeader . GetBlockTarget ( ) ) . ToUInt256 ( ) . ToString ( ) ;
162- blockModel . PosChainTrust = chainedHeader . ChainWork . ToString ( ) ; // this should be similar to ChainWork
163+ /// <summary>
164+ /// Retrieves the blocks from a given height onwards.
165+ /// </summary>
166+ /// <param name="query">An object containing the necessary parameters to search for a block.</param>
167+ /// <returns><see cref="BlockModel"/> if block is found, <see cref="NotFoundObjectResult"/> if not found. Returns <see cref="IActionResult"/> with error information if exception thrown.</returns>
168+ /// <response code="200">Returns data about the block or block not found message</response>
169+ /// <response code="400">Block hash invalid, or an unexpected exception occurred</response>
170+ [ Route ( BlockStoreRouteEndPoint . GetBlocks ) ]
171+ [ HttpGet ]
172+ [ ProducesResponseType ( ( int ) HttpStatusCode . OK ) ]
173+ [ ProducesResponseType ( ( int ) HttpStatusCode . BadRequest ) ]
174+ [ ProducesResponseType ( ( int ) HttpStatusCode . NotFound ) ]
175+ public IActionResult GetBlocks ( [ FromQuery ] SearchByHeightRequest query )
176+ {
177+ if ( ! this . ModelState . IsValid )
178+ return ModelStateErrors . BuildErrorResponse ( this . ModelState ) ;
179+
180+ try
181+ {
182+ if ( query . Height > this . chainIndexer . Tip . Height )
183+ return this . NotFound ( "No blocks found" ) ;
163184
164- if ( this . stakeChain != null )
165- {
166- BlockStake blockStake = this . stakeChain . Get ( blockId ) ;
185+ int tip = query . Height + query . NumberOfBlocks - 1 ;
186+ if ( tip > this . chainIndexer . Tip . Height )
187+ {
188+ query . NumberOfBlocks -= ( this . chainIndexer . Tip . Height - tip ) ;
189+ tip = this . chainIndexer . Tip . Height ;
190+ }
167191
168- blockModel . PosModifierv2 = blockStake ? . StakeModifierV2 . ToString ( ) ;
169- blockModel . PosFlags = blockStake ? . Flags == BlockFlag . BLOCK_PROOF_OF_STAKE ? "proof-of-stake" : "proof-of-work" ;
170- blockModel . PosHashProof = blockStake ? . HashProof ? . ToString ( ) ;
171- }
192+ List < ChainedHeader > chainedHeaders = this . chainIndexer [ tip ] . EnumerateToGenesis ( ) . Take ( query . NumberOfBlocks ) . Reverse ( ) . ToList ( ) ;
193+ List < uint256 > blockIds = chainedHeaders . Select ( h => h . HashBlock ) . ToList ( ) ;
194+ List < Block > blocks = this . blockStore . GetBlocks ( blockIds ) ;
195+
196+ if ( ! query . OutputJson )
197+ {
198+ return this . Json ( blocks ) ;
172199 }
173200
174- return this . Json ( blockModel ) ;
201+ return this . Json ( chainedHeaders . Select ( ( h , n ) => GetBlockModel ( blocks [ n ] , blockIds [ n ] , h , query . ShowTransactionDetails ) ) ) ;
175202 }
176203 catch ( Exception e )
177204 {
@@ -180,6 +207,33 @@ public IActionResult GetBlock([FromQuery] SearchByHashRequest query)
180207 }
181208 }
182209
210+ private BlockModel GetBlockModel ( Block block , uint256 blockId , ChainedHeader chainedHeader , bool showTransactionDetails )
211+ {
212+ BlockModel blockModel = showTransactionDetails
213+ ? new BlockTransactionDetailsModel ( block , chainedHeader , this . chainIndexer . Tip , this . network )
214+ : new BlockModel ( block , chainedHeader , this . chainIndexer . Tip , this . network ) ;
215+
216+ if ( this . network . Consensus . IsProofOfStake )
217+ {
218+ var posBlock = block as PosBlock ;
219+
220+ blockModel . PosBlockSignature = posBlock . BlockSignature . ToHex ( this . network ) ;
221+ blockModel . PosBlockTrust = new Target ( chainedHeader . GetBlockTarget ( ) ) . ToUInt256 ( ) . ToString ( ) ;
222+ blockModel . PosChainTrust = chainedHeader . ChainWork . ToString ( ) ; // this should be similar to ChainWork
223+
224+ if ( this . stakeChain != null )
225+ {
226+ BlockStake blockStake = this . stakeChain . Get ( blockId ) ;
227+
228+ blockModel . PosModifierv2 = blockStake ? . StakeModifierV2 . ToString ( ) ;
229+ blockModel . PosFlags = blockStake ? . Flags == BlockFlag . BLOCK_PROOF_OF_STAKE ? "proof-of-stake" : "proof-of-work" ;
230+ blockModel . PosHashProof = blockStake ? . HashProof ? . ToString ( ) ;
231+ }
232+ }
233+
234+ return blockModel ;
235+ }
236+
183237 /// <summary>
184238 /// Gets the current consensus tip height.
185239 /// </summary>
0 commit comments