2023-07-05 18:17:03 +00:00
# Nimbus
# Copyright (c) 2023 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 : [ ] . }
import
std / [ os , uri ] ,
confutils , chronicles ,
beacon_chain / spec / digest
proc defaultDataDir * ( ) : string =
let dataDir = when defined ( windows ) :
" AppData " / " Roaming " / " EthData "
elif defined ( macosx ) :
" Library " / " Application Support " / " EthData "
else :
" .cache " / " eth-data "
getHomeDir ( ) / dataDir
type
Web3UrlKind * = enum
HttpUrl , WsUrl
Web3Url * = object
kind * : Web3UrlKind
url * : string
StorageMode * = enum
JsonStorage , DbStorage
const
defaultDataDirDesc * = defaultDataDir ( )
defaultBlockFileName * = " eth-block-data "
defaultAccumulatorFileName * = " mainnet-master-accumulator.ssz "
defaultWeb3Url * = Web3Url ( kind : HttpUrl , url : " http://127.0.0.1:8545 " )
type
ExporterCmd * = enum
history ,
beacon
HistoryCmd * = enum
# TODO: Multiline strings doesn't work here anymore with 1.6, and concat of
# several lines gives the error: Error: Invalid node kind nnkInfix for macros.`$`
exportBlockData =
" Export block data (headers, bodies and receipts) to a json format or a database. Some of this functionality is likely to get deprecated "
exportEpochHeaders =
" Export block headers from an Ethereum JSON RPC Execution endpoint to *.e2s files arranged per epoch (8192 blocks) "
verifyEpochHeaders =
" Verify *.e2s files containing block headers. Verify currently only means being able to RLP decode the block headers "
exportAccumulatorData =
" Build and export the master accumulator and historical epoch accumulators. Requires *.e2s block header files generated with the exportHeaders command up until the merge block "
printAccumulatorData =
" Print the root hash of the master accumulator and of all historical epoch accumulators. Requires data generated by exportAccumulatorData command "
exportHeaderRange =
" Export block headers from an Ethereum JSON RPC Execution endpoint to *.e2s files (unlimited amount) "
exportHeadersWithProof =
" Export block headers with proof from *.e2s headers file and epochAccumulator files "
2024-02-09 10:13:12 +00:00
exportEra1 = " Export historical data to era1 store "
verifyEra1 = " Read and verify historical data from era1 store "
2023-07-05 18:17:03 +00:00
BeaconCmd * = enum
exportLCBootstrap = " Export Light Client Bootstrap "
exportLCUpdates = " Export Light Client Updates "
exportLCFinalityUpdate = " Export Light Client Finality Update "
exportLCOptimisticUpdate = " Export Light Client Optimistic Update "
ExporterConf * = object
logLevel * {.
defaultValue : LogLevel . INFO
defaultValueDesc : $ LogLevel . INFO
desc : " Sets the log level "
name : " log-level " . } : LogLevel
dataDir * {.
desc : " The directory where generated data files will be exported to "
defaultValue : defaultDataDir ( )
defaultValueDesc : $ defaultDataDirDesc
name : " data-dir " . } : OutDir
case cmd * {. command . } : ExporterCmd
of ExporterCmd . history :
web3Url * {.
desc : " Execution layer JSON-RPC API URL "
defaultValue : defaultWeb3Url
name : " web3-url " . } : Web3Url
case historyCmd * {. command . } : HistoryCmd
of exportBlockData :
startBlock * {.
desc : " Number of the first block to be exported "
defaultValue : 0
name : " start-block " . } : uint64
endBlock * {.
desc : " Number of the last block to be exported "
defaultValue : 0
name : " end-block " . } : uint64
fileName * {.
desc : " File name (minus extension) where block data will be exported to "
defaultValue : defaultBlockFileName
defaultValueDesc : $ defaultBlockFileName
name : " file-name " . } : string
storageMode * {.
desc : " Storage mode of block data export "
defaultValue : JsonStorage
name : " storage-mode " . } : StorageMode
headersOnly * {.
desc : " Only export the headers instead of full blocks and receipts "
defaultValue : false
name : " headers-only " . } : bool
of exportEpochHeaders :
startEpoch * {.
desc : " Number of the first epoch which should be downloaded "
defaultValue : 0
name : " start-epoch " . } : uint64
endEpoch * {.
desc : " Number of the last epoch which should be downloaded "
defaultValue : 1896
name : " end-epoch " . } : uint64
# TODO:
# Although options are the same as for exportHeaders, we can't drop them
# under the same case of as confutils does not agree with that.
of verifyEpochHeaders :
startEpochVerify * {.
desc : " Number of the first epoch which should be downloaded "
defaultValue : 0
name : " start-epoch " . } : uint64
endEpochVerify * {.
desc : " Number of the last epoch which should be downloaded "
defaultValue : 1896
name : " end-epoch " . } : uint64
of exportAccumulatorData :
accumulatorFileName * {.
desc : " File to which the serialized accumulator is written "
defaultValue : defaultAccumulatorFileName
defaultValueDesc : $ defaultAccumulatorFileName
name : " accumulator-file-name " . } : string
writeEpochAccumulators * {.
desc : " Write also the SSZ encoded epoch accumulators to specific files "
defaultValue : false
name : " write-epoch-accumulators " . } : bool
of printAccumulatorData :
accumulatorFileNamePrint * {.
desc : " File from which the serialized accumulator is read "
defaultValue : defaultAccumulatorFileName
defaultValueDesc : $ defaultAccumulatorFileName
name : " accumulator-file-name " . } : string
of exportHeaderRange :
startBlockNumber * {.
desc : " Number of the first block header to be exported "
name : " start-block " . } : uint64
endBlockNumber * {.
desc : " Number of the last block header to be exported "
name : " end-block " . } : uint64
of exportHeadersWithProof :
startBlockNumber2 * {.
desc : " Number of the first block header to be exported "
name : " start-block " . } : uint64
endBlockNumber2 * {.
desc : " Number of the last block header to be exported "
name : " end-block " . } : uint64
2024-02-09 10:13:12 +00:00
of exportEra1 :
era * {.
defaultValue : 0
desc : " The era number to write " . } : uint64
eraCount * {.
defaultValue : 0
name : " count "
desc : " Number of eras to write (0=all) " . } : uint64
of verifyEra1 :
era1FileName * {.
desc : " Era1 file to read and verify "
name : " era1-file-name " . } : string
2023-07-05 18:17:03 +00:00
of ExporterCmd . beacon :
restUrl * {.
desc : " URL of the beacon node REST service "
defaultValue : " http://127.0.0.1:5052 "
name : " rest-url " . } : string
case beaconCmd * {. command . } : BeaconCmd
of exportLCBootstrap :
trustedBlockRoot * {.
desc : " Trusted finalized block root of the requested bootstrap "
name : " trusted-block-root " . } : Eth2Digest
of exportLCUpdates :
startPeriod * {.
desc : " Period of the first LC update "
defaultValue : 0
name : " start-period " . } : uint64
count * {.
desc : " Amount of LC updates to request "
defaultValue : 1
name : " count " . } : uint64
of exportLCFinalityUpdate :
discard
of exportLCOptimisticUpdate :
discard
proc parseCmdArg * (
2023-08-04 12:43:30 +00:00
T : type Web3Url , p : string ) : T {. raises : [ ValueError ] . } =
2023-07-05 18:17:03 +00:00
let
url = parseUri ( p )
normalizedScheme = url . scheme . toLowerAscii ( )
if ( normalizedScheme = = " http " or normalizedScheme = = " https " ) :
Web3Url ( kind : HttpUrl , url : p )
elif ( normalizedScheme = = " ws " or normalizedScheme = = " wss " ) :
Web3Url ( kind : WsUrl , url : p )
else :
raise newException (
2023-08-04 12:43:30 +00:00
ValueError ,
2023-07-05 18:17:03 +00:00
" The Web3 URL must specify one of following protocols: http/https/ws/wss "
)
proc completeCmdArg * ( T : type Web3Url , val : string ) : seq [ string ] =
return @ [ ]
proc parseCmdArg * ( T : type StorageMode , p : string ) : T
2023-08-04 12:43:30 +00:00
{. raises : [ ValueError ] . } =
2023-07-05 18:17:03 +00:00
if p = = " db " :
return DbStorage
elif p = = " json " :
return JsonStorage
else :
let msg = " Provided mode: " & p & " is not a valid. Should be `json` or `db` "
2023-08-04 12:43:30 +00:00
raise newException ( ValueError , msg )
2023-07-05 18:17:03 +00:00
proc completeCmdArg * ( T : type StorageMode , val : string ) : seq [ string ] =
return @ [ ]
func parseCmdArg * ( T : type Eth2Digest , input : string ) : T
{. raises : [ ValueError , Defect ] . } =
Eth2Digest . fromHex ( input )
func completeCmdArg * ( T : type Eth2Digest , input : string ) : seq [ string ] =
return @ [ ]