mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-13 15:07:01 +00:00
When the connect_to_testnet script is invoked it will first verify that the genesis file of the testnet hasn't changed. If it has changed, any previously created database associated with the testnet will be erased. To facilitate this, the genesis file of each network is written to the data folder of the beacon node. The beacon node will refuse to start if it detects a discrepancy between the data folder and any state snapshot specified on the command-line. Since the testnet sharing spec requires us to use SSZ snapshots, the Json support is now phased out. To help with the transition and to preserve the functionality of the multinet scripts, the beacon node now supports a CLI query command that can extract any data from the genesis state. This is based on new developments in the SSZ navigators.
128 lines
4.2 KiB
Nim
128 lines
4.2 KiB
Nim
import
|
|
stew/objects, stew/ranges/ptr_arith,
|
|
./types, ./bytes_reader
|
|
|
|
type
|
|
MemRange* = object
|
|
startAddr*: ptr byte
|
|
length*: int
|
|
|
|
SszNavigator*[T] = object
|
|
m: MemRange
|
|
|
|
func sszMount*(data: openarray[byte], T: type): SszNavigator[T] =
|
|
let startAddr = unsafeAddr data[0]
|
|
SszNavigator[T](m: MemRange(startAddr: startAddr, length: data.len))
|
|
|
|
template sszMount*(data: MemRange, T: type): SszNavigator[T] =
|
|
SszNavigator[T](m: data)
|
|
|
|
template getMemRange*(n: SszNavigator): MemRange =
|
|
# Please note that this accessor was created intentionally.
|
|
# We don't want to expose the `m` field, because the navigated
|
|
# type may have a field by that name. We wan't any dot field
|
|
# access to be redirected to the navigated type.
|
|
# For this reason, this template should always be used with
|
|
# the function call syntax `getMemRange(n)`.
|
|
n.m
|
|
|
|
template checkBounds(m: MemRange, offset: int) =
|
|
if offset > m.length:
|
|
raise newException(MalformedSszError, "Malformed SSZ")
|
|
|
|
template toOpenArray(m: MemRange): auto =
|
|
makeOpenArray(m.startAddr, m.length)
|
|
|
|
func navigateToField*[T](n: SszNavigator[T],
|
|
fieldName: static string,
|
|
FieldType: type): SszNavigator[FieldType] =
|
|
mixin toSszType
|
|
type SszFieldType = type toSszType(default FieldType)
|
|
|
|
const boundingOffsets = getFieldBoundingOffsets(T, fieldName)
|
|
checkBounds(n.m, boundingOffsets[1])
|
|
|
|
when isFixedSize(SszFieldType):
|
|
SszNavigator[FieldType](m: MemRange(
|
|
startAddr: shift(n.m.startAddr, boundingOffsets[0]),
|
|
length: boundingOffsets[1] - boundingOffsets[0]))
|
|
else:
|
|
template readOffset(offset): int =
|
|
int fromSszBytes(uint32, makeOpenArray(shift(n.m.startAddr, offset),
|
|
sizeof(uint32)))
|
|
let
|
|
startOffset = readOffset boundingOffsets[0]
|
|
endOffset = when boundingOffsets[1] == -1: n.m.length
|
|
else: readOffset boundingOffsets[1]
|
|
|
|
if endOffset < startOffset or endOffset > n.m.length:
|
|
raise newException(MalformedSszError, "Incorrect offset values")
|
|
|
|
SszNavigator[FieldType](m: MemRange(
|
|
startAddr: shift(n.m.startAddr, startOffset),
|
|
length: endOffset - startOffset))
|
|
|
|
template `.`*[T](n: SszNavigator[T], field: untyped): auto =
|
|
type RecType = T
|
|
type FieldType = type(default(RecType).field)
|
|
navigateToField(n, astToStr(field), FieldType)
|
|
|
|
func indexVarSizeList(m: MemRange, idx: int): MemRange =
|
|
template readOffset(pos): int =
|
|
int fromSszBytes(uint32, makeOpenArray(shift(m.startAddr, pos), offsetSize))
|
|
|
|
let offsetPos = offsetSize * idx
|
|
checkBounds(m, offsetPos + offsetSize)
|
|
|
|
let firstOffset = readOffset 0
|
|
let listLen = firstOffset div offsetSize
|
|
|
|
if idx >= listLen:
|
|
# TODO: Use a RangeError here?
|
|
# This would require the user to check the `len` upfront
|
|
raise newException(MalformedSszError, "Indexing past the end")
|
|
|
|
let elemPos = readOffset offsetPos
|
|
checkBounds(m, elemPos)
|
|
|
|
let endPos = if idx < listLen - 1:
|
|
let nextOffsetPos = offsetPos + offsetSize
|
|
# TODO. Is there a way to remove this bounds check?
|
|
checkBounds(m, nextOffsetPos + offsetSize)
|
|
readOffset(offsetPos + nextOffsetPos)
|
|
else:
|
|
m.length
|
|
|
|
MemRange(startAddr: m.startAddr.shift(elemPos), length: endPos - elemPos)
|
|
|
|
template indexList(n, idx, T: untyped): untyped =
|
|
type R = T
|
|
mixin toSszType
|
|
type ElemType = type toSszType(default R)
|
|
when isFixedSize(ElemType):
|
|
const elemSize = fixedPortionSize(ElemType)
|
|
let elemPos = idx * elemSize
|
|
checkBounds(n.m, elemPos + elemSize)
|
|
SszNavigator[R](m: MemRange(startAddr: shift(n.m.startAddr, elemPos),
|
|
length: elemSize))
|
|
else:
|
|
SszNavigator[R](m: indexVarSizeList(n.m, idx))
|
|
|
|
template `[]`*[T](n: SszNavigator[seq[T]], idx: int): SszNavigator[T] =
|
|
indexList n, idx, T
|
|
|
|
template `[]`*[R, T](n: SszNavigator[array[R, T]], idx: int): SszNavigator[T] =
|
|
indexList(n, idx, T)
|
|
|
|
func `[]`*[T](n: SszNavigator[T]): T =
|
|
mixin toSszType, fromSszBytes
|
|
type SszRepr = type(toSszType default(T))
|
|
when type(SszRepr) is type(T):
|
|
readSszValue(toOpenArray(n.m), T)
|
|
else:
|
|
fromSszBytes(T, toOpenArray(n.m))
|
|
|
|
converter derefNavigator*[T](n: SszNavigator[T]): T =
|
|
n[]
|
|
|