2021-03-26 06:52:01 +00:00
# beacon_chain
# Copyright (c) 2018-2021 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
{. push raises : [ Defect ] . }
2020-10-27 09:00:57 +00:00
import
std / [ strutils , parseutils ] ,
stew / byteutils ,
2021-03-02 10:27:45 +00:00
.. / beacon_node_common , .. / validators / validator_duties ,
2021-03-04 09:13:44 +00:00
.. / consensus_object_pools / [ block_pools_types , blockchain_dag ] ,
2021-06-23 14:43:18 +00:00
.. / spec / datatypes / base ,
2021-08-12 13:08:20 +00:00
.. / spec / [ forks , helpers ] ,
2021-08-03 15:17:11 +00:00
.. / spec / eth2_apis / [ rpc_types , eth2_json_rpc_serialization ]
2020-10-27 09:00:57 +00:00
2021-10-13 10:20:18 +00:00
export forks , rpc_types , eth2_json_rpc_serialization , blockchain_dag
template raiseNoAltairSupport * ( ) =
raise ( ref ValueError ) ( msg :
" The JSON-RPC interface does not support certain Altair operations due to changes in block structure - see https://nimbus.guide/rest-api.html for full altair support " )
2020-10-27 09:00:57 +00:00
template withStateForStateId * ( stateId : string , body : untyped ) : untyped =
2021-03-17 10:17:15 +00:00
let
bs = node . stateIdToBlockSlot ( stateId )
template isState ( state : StateData ) : bool =
2021-06-11 17:51:46 +00:00
state . blck . atSlot ( getStateField ( state . data , slot ) ) = = bs
2021-03-17 10:17:15 +00:00
2021-06-01 11:13:40 +00:00
if isState ( node . dag . headState ) :
withStateVars ( node . dag . headState ) :
2021-06-29 15:09:29 +00:00
var cache {. inject , used . } : StateCache
2021-03-17 10:17:15 +00:00
body
else :
2021-06-01 11:13:40 +00:00
let rpcState = assignClone ( node . dag . headState )
node . dag . withState ( rpcState [ ] , bs ) :
2021-03-17 10:17:15 +00:00
body
2020-10-27 09:00:57 +00:00
proc toBlockSlot * ( blckRef : BlockRef ) : BlockSlot =
blckRef . atSlot ( blckRef . slot )
2021-03-26 06:52:01 +00:00
proc parseRoot * ( str : string ) : Eth2Digest {. raises : [ Defect , ValueError ] . } =
Eth2Digest ( data : hexToByteArray [ 32 ] ( str ) )
2020-10-27 09:00:57 +00:00
2021-03-26 06:52:01 +00:00
func checkEpochToSlotOverflow * ( epoch : Epoch ) {. raises : [ Defect , ValueError ] . } =
2020-10-27 09:00:57 +00:00
const maxEpoch = compute_epoch_at_slot ( not 0 'u64 )
if epoch > = maxEpoch :
raise newException (
ValueError , " Requesting epoch for which slot would overflow " )
2021-03-26 06:52:01 +00:00
proc doChecksAndGetCurrentHead * ( node : BeaconNode , slot : Slot ) : BlockRef {. raises : [ Defect , CatchableError ] . } =
2021-06-01 11:13:40 +00:00
result = node . dag . head
2020-10-27 09:00:57 +00:00
if not node . isSynced ( result ) :
raise newException ( CatchableError , " Cannot fulfill request until node is synced " )
# TODO for now we limit the requests arbitrarily by up to 2 epochs into the future
if result . slot + uint64 ( 2 * SLOTS_PER_EPOCH ) < slot :
raise newException ( CatchableError , " Requesting way ahead of the current head " )
2021-03-26 06:52:01 +00:00
proc doChecksAndGetCurrentHead * ( node : BeaconNode , epoch : Epoch ) : BlockRef {. raises : [ Defect , CatchableError ] . } =
2020-10-27 09:00:57 +00:00
checkEpochToSlotOverflow ( epoch )
node . doChecksAndGetCurrentHead ( epoch . compute_start_slot_at_epoch )
2021-03-26 06:52:01 +00:00
proc getBlockSlotFromString * ( node : BeaconNode , slot : string ) : BlockSlot {. raises : [ Defect , CatchableError ] . } =
2020-10-27 09:00:57 +00:00
if slot . len = = 0 :
raise newException ( ValueError , " Empty slot number not allowed " )
var parsed : BiggestUInt
if parseBiggestUInt ( slot , parsed ) ! = slot . len :
raise newException ( ValueError , " Not a valid slot number " )
let head = node . doChecksAndGetCurrentHead ( parsed . Slot )
2021-03-26 14:11:06 +00:00
head . atSlot ( parsed . Slot )
2020-10-27 09:00:57 +00:00
2021-03-26 06:52:01 +00:00
proc stateIdToBlockSlot * ( node : BeaconNode , stateId : string ) : BlockSlot {. raises : [ Defect , CatchableError ] . } =
2021-03-26 14:11:06 +00:00
case stateId :
of " head " :
2021-06-01 11:13:40 +00:00
node . dag . head . toBlockSlot ( )
2021-03-26 14:11:06 +00:00
of " genesis " :
2021-06-01 11:13:40 +00:00
node . dag . getGenesisBlockSlot ( )
2021-03-26 14:11:06 +00:00
of " finalized " :
2021-06-01 11:13:40 +00:00
node . dag . finalizedHead
2021-03-26 14:11:06 +00:00
of " justified " :
2021-06-01 11:13:40 +00:00
node . dag . head . atEpochStart (
2021-06-11 17:51:46 +00:00
getStateField ( node . dag . headState . data , current_justified_checkpoint ) . epoch )
2021-03-26 14:11:06 +00:00
else :
if stateId . startsWith ( " 0x " ) :
let blckRoot = parseRoot ( stateId )
2021-06-01 11:13:40 +00:00
let blckRef = node . dag . getRef ( blckRoot )
2021-03-26 14:11:06 +00:00
if blckRef . isNil :
raise newException ( CatchableError , " Block not found " )
blckRef . toBlockSlot ( )
2020-10-27 09:00:57 +00:00
else :
2021-03-26 14:11:06 +00:00
node . getBlockSlotFromString ( stateId )