add `libnimbus_lc.a` C library (#5122)

Add a new C library for processing light client data based on the Nimbus
implementation. This can be used from other, non-Nimbus components.
This commit is contained in:
Etan Kissling 2023-07-19 09:48:39 +02:00 committed by GitHub
parent 346d05a95d
commit 971b4483c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 2709 additions and 13 deletions

View File

@ -64,7 +64,8 @@ jobs:
- name: Check copyright year (Linux)
if: github.event_name == 'pull_request' && runner.os == 'Linux'
run: |
excluded_extensions="ans|json|md|png|txt"
excluded_files="config.yaml"
excluded_extensions="ans|json|md|png|ssz|txt"
current_year=$(date +"%Y")
outdated_files=()
@ -72,7 +73,7 @@ jobs:
if ! grep -qE 'Copyright \(c\) .*'$current_year' Status Research & Development GmbH' "$file"; then
outdated_files+=("$file")
fi
done < <(git diff --name-only --diff-filter=AM --ignore-submodules HEAD^ HEAD | grep -vE '\.('$excluded_extensions')$' || true)
done < <(git diff --name-only --diff-filter=AM --ignore-submodules HEAD^ HEAD | grep -vE '(\.('$excluded_extensions')|'$excluded_files')$' || true)
if (( ${#outdated_files[@]} )); then
echo "The following files do not have an up-to-date copyright year:"

2
.gitignore vendored
View File

@ -51,7 +51,7 @@ build/
test_keymanager_api
test_sim
/libnfuzz_linkerArgs.txt
/*linkerArgs.txt
# scripts/geth_binaries.sh
geth-*.tar.gz

View File

@ -54,11 +54,14 @@ endif
# unconditionally built by the default Make target
# TODO re-enable ncli_query if/when it works again
TOOLS_CORE_CUSTOMCOMPILE := \
libnimbus_lc.a
TOOLS_CORE := \
deposit_contract \
resttest \
logtrace \
mev_mock \
mev_mock \
ncli \
ncli_db \
ncli_split_keystore \
@ -69,7 +72,8 @@ TOOLS_CORE := \
nimbus_validator_client \
nimbus_signing_node \
validator_db_aggregator \
ncli_testnet
ncli_testnet \
$(TOOLS_CORE_CUSTOMCOMPILE)
# This TOOLS/TOOLS_CORE decomposition is a workaroud so nimbus_beacon_node can
# build on its own, and if/when that becomes a non-issue, it can be recombined
@ -280,7 +284,8 @@ XML_TEST_BINARIES := \
# test suite
TEST_BINARIES := \
state_sim \
block_sim
block_sim \
test_libnimbus_lc
.PHONY: $(TEST_BINARIES) $(XML_TEST_BINARIES) force_build_alone_all_tests
# Preset-dependent tests
@ -392,14 +397,23 @@ endif
rm -rf 0000-*.json t_slashprot_migration.* *.log block_sim_db
for TEST_BINARY in $(TEST_BINARIES); do \
PARAMS=""; \
REDIRECT=""; \
if [[ "$${TEST_BINARY}" == "state_sim" ]]; then PARAMS="--validators=8000 --slots=160"; \
elif [[ "$${TEST_BINARY}" == "block_sim" ]]; then PARAMS="--validators=8000 --slots=160"; \
elif [[ "$${TEST_BINARY}" == "test_libnimbus_lc" ]]; then REDIRECT="$${TEST_BINARY}.log"; \
fi; \
echo -e "\nRunning $${TEST_BINARY} $${PARAMS}\n"; \
build/$${TEST_BINARY} $${PARAMS} || { \
echo -e "\n$${TEST_BINARY} $${PARAMS} failed; Last 50 lines from the log:"; \
tail -n50 "$${TEST_BINARY}.log"; exit 1; \
}; \
if [[ "$${REDIRECT}" != "" ]]; then \
build/$${TEST_BINARY} $${PARAMS} > "$${REDIRECT}" && echo "OK" || { \
echo -e "\n$${TEST_BINARY} $${PARAMS} failed; Last 50 lines from the log:"; \
tail -n50 "$${TEST_BINARY}.log"; exit 1; \
}; \
else \
build/$${TEST_BINARY} $${PARAMS} || { \
echo -e "\n$${TEST_BINARY} $${PARAMS} failed; Last 50 lines from the log:"; \
tail -n50 "$${TEST_BINARY}.log"; exit 1; \
}; \
fi; \
done; \
rm -rf 0000-*.json t_slashprot_migration.* *.log block_sim_db
@ -419,7 +433,7 @@ build/generate_makefile: tools/generate_makefile.nim | deps-common
# It also requires Make to pass open file descriptors to the GCC process,
# which is not possible if we let Nim handle this, so we generate and use a
# makefile instead.
$(TOOLS): | build deps
$(filter-out $(TOOLS_CORE_CUSTOMCOMPILE),$(TOOLS)): | build deps
+ for D in $(TOOLS_DIRS); do [ -e "$${D}/$@.nim" ] && TOOL_DIR="$${D}" && break; done && \
echo -e $(BUILD_MSG) "build/$@" && \
MAKE="$(MAKE)" V="$(V)" $(ENV_SCRIPT) scripts/compile_nim_program.sh $@ "$${TOOL_DIR}/$@.nim" $(NIM_PARAMS) && \
@ -728,6 +742,34 @@ gnosis-chain-dev-deposit: | gnosis-build deposit_contract
clean-gnosis-chain:
$(call CLEAN_NETWORK,gnosis-chain)
###
### libnimbus_lc
###
libnimbus_lc.a: | build deps
+ echo -e $(BUILD_MSG) "build/$@" && \
set -x && \
rm -f build/$@ && \
$(ENV_SCRIPT) $(NIMC) c -d:disable_libbacktrace -d:release --app:staticlib --noMain --nimcache:nimcache/libnimbus_lc_static -o:build/$@ $(NIM_PARAMS) beacon_chain/libnimbus_lc/libnimbus_lc.nim $(SILENCE_WARNINGS) && \
echo -e $(BUILD_END_MSG) "build/$@"
# `-Wno-maybe-uninitialized` in Linux: https://github.com/nim-lang/Nim/issues/22246
test_libnimbus_lc: libnimbus_lc.a
+ echo -e $(BUILD_MSG) "build/$@" && \
set -x && \
case "$$(uname)" in \
Darwin) \
clang -D__DIR__="\"beacon_chain/libnimbus_lc\"" --std=c17 -Weverything -Werror -Wno-declaration-after-statement -Wno-nullability-extension -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -o build/test_libnimbus_lc beacon_chain/libnimbus_lc/test_libnimbus_lc.c build/libnimbus_lc.a -framework Security; \
;; \
MINGW64_*) \
gcc -D__DIR__="\"beacon_chain/libnimbus_lc\"" --std=c17 -Wall -Wextra -pedantic -Werror -pedantic-errors -flto -o build/test_libnimbus_lc -D_CRT_SECURE_NO_WARNINGS beacon_chain/libnimbus_lc/test_libnimbus_lc.c build/libnimbus_lc.a; \
;; \
*) \
gcc -D__DIR__="\"beacon_chain/libnimbus_lc\"" --std=c17 -Wall -Wextra -pedantic -Werror -pedantic-errors -Wno-maybe-uninitialized -flto -o build/test_libnimbus_lc beacon_chain/libnimbus_lc/test_libnimbus_lc.c build/libnimbus_lc.a; \
;; \
esac && \
echo -e $(BUILD_END_MSG) "build/$@"
###
### Other
###

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,95 @@
# Mainnet config
# Extends the mainnet preset
PRESET_BASE: 'mainnet'
# Free-form short name of the network that this configuration applies to - known
# canonical network names include:
# * 'mainnet' - there can be only one
# * 'prater' - testnet
# Must match the regex: [a-z0-9\-]
CONFIG_NAME: 'mainnet'
# Transition
# ---------------------------------------------------------------
# Estimated on Sept 15, 2022
TERMINAL_TOTAL_DIFFICULTY: 58750000000000000000000
# By default, don't use these params
TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000
TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615
# Genesis
# ---------------------------------------------------------------
# `2**14` (= 16,384)
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384
# Dec 1, 2020, 12pm UTC
MIN_GENESIS_TIME: 1606824000
# Mainnet initial fork version, recommend altering for testnets
GENESIS_FORK_VERSION: 0x00000000
# 604800 seconds (7 days)
GENESIS_DELAY: 604800
# Forking
# ---------------------------------------------------------------
# Some forks are disabled for now:
# - These may be re-assigned to another fork-version later
# - Temporarily set to max uint64 value: 2**64 - 1
# Altair
ALTAIR_FORK_VERSION: 0x01000000
ALTAIR_FORK_EPOCH: 74240 # Oct 27, 2021, 10:56:23am UTC
# Bellatrix
BELLATRIX_FORK_VERSION: 0x02000000
BELLATRIX_FORK_EPOCH: 144896 # Sept 6, 2022, 11:34:47am UTC
# Capella
CAPELLA_FORK_VERSION: 0x03000000
CAPELLA_FORK_EPOCH: 194048 # April 12, 2023, 10:27:35pm UTC
# Deneb
DENEB_FORK_VERSION: 0x04000000
DENEB_FORK_EPOCH: 18446744073709551615
# Time parameters
# ---------------------------------------------------------------
# 12 seconds
SECONDS_PER_SLOT: 12
# 14 (estimate from Eth1 mainnet)
SECONDS_PER_ETH1_BLOCK: 14
# 2**8 (= 256) epochs ~27 hours
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: 256
# 2**8 (= 256) epochs ~27 hours
SHARD_COMMITTEE_PERIOD: 256
# 2**11 (= 2,048) Eth1 blocks ~8 hours
ETH1_FOLLOW_DISTANCE: 2048
# Validator cycle
# ---------------------------------------------------------------
# 2**2 (= 4)
INACTIVITY_SCORE_BIAS: 4
# 2**4 (= 16)
INACTIVITY_SCORE_RECOVERY_RATE: 16
# 2**4 * 10**9 (= 16,000,000,000) Gwei
EJECTION_BALANCE: 16000000000
# 2**2 (= 4)
MIN_PER_EPOCH_CHURN_LIMIT: 4
# 2**16 (= 65,536)
CHURN_LIMIT_QUOTIENT: 65536
# Fork choice
# ---------------------------------------------------------------
# 40%
PROPOSER_SCORE_BOOST: 40
# Deposit contract
# ---------------------------------------------------------------
# Ethereum PoW Mainnet
DEPOSIT_CHAIN_ID: 1
DEPOSIT_NETWORK_ID: 1
DEPOSIT_CONTRACT_ADDRESS: 0x00000000219ab540356cBB839Cbe05303d7705Fa

View File

@ -0,0 +1 @@
{"version":"capella","data":{"attested_header":{"beacon":{"slot":"6730912","proposer_index":"338774","parent_root":"0x08de36a4696c4f4136913ffc8cbc1e4a2f233e66b3102a6e196459ff6f51ef7b","state_root":"0x5528265425c00c6b0be8be960d566ea7a69880dc250692eda32893a9a3bc1e7e","body_root":"0xca24486c1f61926843ef5b175952452a4eab871ebe3e288096cedc7a1e4fcfd9"},"execution":{"parent_hash":"0x853b4c96c5810f1937f8b937681509be006fa0f3c3bacadf1f03e8f090745fa9","fee_recipient":"0x1f9090aae28b8a3dceadf281b0f12828e676c326","state_root":"0x7f1a69ff29e693832968082fe535267c45d51a927c2dad48d2a900865f178016","receipts_root":"0xb10b9d7bf8474462f1062ff0f1f281847b07bb9fd1acc0e660a18d3c7a3824d6","logs_bloom":"0x87e5e40b4100907cb88a6980db5711a39e134c2a55045c002193503217c8ac5ad010a78056e0642047a31b8b181c8bd282ed0a4798017d200c0640b609ffea39c868cc6cc11e1f2c7813421b52c861af88116d0d0556184250227c578861a6808334c0910a03c6bd88d8121424088d69f0104c620088e460e222007d14d8916ede20bb55b29cd003285d7c7083989013148126bda9d90438da6f42615db20cb88e0a1be3e823f6131eaa4dfd9763744fec46a0d9bf131b1790ece075848ac035c08c142390a94852227842309aecd0c0fc6941c8514c9035303501de4e93f004ffb1b00d12014104088d999021aa4886944a92985b7a63c789c40f6691023406","prev_randao":"0xdd9b5fab097278f656b224e5327ac2ea2e92bca66582714573e45bb4c34254de","block_number":"17548171","gas_limit":"30000000","gas_used":"15879704","timestamp":"1687594967","extra_data":"0x7273796e632d6275696c6465722e78797a","base_fee_per_gas":"12434872107","block_hash":"0xdb1d6cb76484b413c9357f6bcc2f2c38aa854e6df41a6fdf856a15b236515598","transactions_root":"0x8212a7dffa03f8838ecebd81c5a59d59200720dd64b7de0401a8d60be22706fc","withdrawals_root":"0x68c4fb463b1bf7e63b8347cbbf003ce10f96f3ef74b77f2da4a896e4dd289e3b"},"execution_branch":["0x7907fbf950b450274b3dbc16ffba288e2d8ed9abd1b06202e7a390b9b9ac7ae2","0x336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0x30bcbea3a71dc7f3ef58b69113b2dffa2def1b54aeee7ca726957f29c6e8afcb"]},"finalized_header":{"beacon":{"slot":"6730848","proposer_index":"169529","parent_root":"0x6f2bd6883b751edc408277a7710fd839b8fcdef92ac8388c855a726a10663d79","state_root":"0xca6912065fbaf9f6ade91f4a3c6363b5e513e5d7a08b854bdbe4c547d54689f5","body_root":"0xdc72c765c2151ea6093724111dd71fdcd5085a5136fdf49aff3eb140ecc4b5ea"},"execution":{"parent_hash":"0x9f2a673aa997f84b8dcaf48204bf8e32ecfff4c950471354090c59aa02e47ad8","fee_recipient":"0x690b9a9e9aa1c9db991c7721a92d351db4fac990","state_root":"0x9b66f5b6f68374a86e3373948146726ab6711d1dc71750d2f48411ed3a74a986","receipts_root":"0x01bdaec4eb4787b7da1550cdf76c388c38f5dc11f5386f302a908aa0b9bfe39e","logs_bloom":"0x1db10687f54003d8b0340020cb11422e84a00a032c0c2572fd29140e14830da36c402bf9580081992190f8220010936002010644e8a13c3c0ad040f0b42e2c0ffcc06b28c628a82a2e4372cac25050a9d4c0201280e2084203935c46a820b6022f5044017266ac815145d10129184d4d221184e0103c5e2048084cd905d817442a4062f0c21013c3885d00784adc00089427e8831954365fc630166a14522c218f5805738331e0910b8f45e59890ccca2d8236c04021080a2ee384610128a023ec1b884680a900a194d84129263f28014a415130c11a30900a0565ca0a09ee116531e908350f08b0c015b0b473225b0684329014f998e06000689911d008f501","prev_randao":"0xcad7f85f1f647efa44a90aada92d1ba4e24e0bd18099450d7bdbf758c40b7087","block_number":"17548108","gas_limit":"30000000","gas_used":"15870907","timestamp":"1687594199","extra_data":"0x627920406275696c64657230783639","base_fee_per_gas":"13417129560","block_hash":"0xe4b939dcf42c7659a62c7d89841d4bea7dd86326581409b4850fdd6c188a2ded","transactions_root":"0x8f92f1610acf9dd2b5510c373d6a7b03b6bf5430998a341b7403eb8072743a51","withdrawals_root":"0xa6b130b3d990158fe0cdb1338e5a5f62f7b15cdd95fd7e7f75f1bd36c833af78"},"execution_branch":["0x6a487c3e35f65f2b2a736e0638e379f682ac9fe3ae077f44cdbed5cab0ee83d6","0x336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0x7140650d46f4ce47555dd8d610d2cad816488aaf24e3c162f66ccb1d4e097eeb"]},"finality_branch":["0xa335030000000000000000000000000000000000000000000000000000000000","0x7a4d2e874c919ee6d9237014dfb6e32738fd56de9753be34687eee11f7d60d4d","0x3510fb835fab1a9149b9199601fb24041e407d54c4d088475bac4baa9b95831c","0xa66768b3c5be2b692507a3debf50f2df7873561a63cc37a95f28bb75f260e3cd","0x32e16b3a14abfce2b458c0065098a05fde3cfac009cd6bf9bdf903087dd9b11a","0xf0b5ef21d7e436ca95b538ed96dc62315aaff5b1ac2ea9e9e032b25fc4cbb7aa"],"sync_aggregate":{"sync_committee_bits":"0xf7ffeffbb7ffefbf7fffffffffdfeffdfffdfffef3f7fffffffffffef7bbfffffffbdfdfdcbdffedfff77dfeffbfffefffffffffffffffffffff7fff3fffffe7","sync_committee_signature":"0x919bce123518b9d071dd76d12c0bbd3ac9204ec4767c71ef4cb4eb7f288ab2c7653ce2bd3d2a301d4b98d345dc4164b40a24408d854f98823449d78e92b6f346ab50ae364b03d86064d0cb15850328411aceca3cf65cd0e06b2254aef95c4cbc"},"signature_slot":"6730913"}}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
{"version":"capella","data":{"attested_header":{"beacon":{"slot":"6730936","proposer_index":"471998","parent_root":"0x707219eb23e75295ae6b34f253d411f549cf9f053c7d6a5fa1cc9cdac4ffaa23","state_root":"0x04559eedba9c1b83b107feaf399b77edf8ed4859978a7fbee4eb38386dc516e0","body_root":"0xab8e22ac1ac86b6e487ac4cf0ab5e0d132ad068b40df439fbbdfae3fa782c9e2"},"execution":{"parent_hash":"0x8aee0bef392c8c09882adfc4da9cca2eeb00d62f075a7581d6006d2f4e07c049","fee_recipient":"0x5124fcc2b3f99f571ad67d075643c743f38f1c34","state_root":"0x8a160ce6f32ddc2a5cba58e18c2a081843cb1b53bf8caad639206b49a17ca003","receipts_root":"0xa9cbf1e627ac0e53163a417aa4665b9889655fe93f134e430ce5f5ad96152d53","logs_bloom":"0x19206ca1468407683a00200c800203e160844a200f2c63067529500a505428091240030444020aa50043bc1339100503023145088a0639286213c576106425080842c1084c8c8dc80a22c0ce4079a0fa82887c409067a98911046508832b6a00983b433166c71d0110c1d41488083c0d001b9421e0194c084a050154901c2821840a02351ec4a1925260005e4ac00a0030ca00c3c94c810950ec004700b348388bc822e2412d683630000acd31838400240815a410080006a37ac92118360060d90310028383a10824c81472183c026105a801a2b9080a102605440a00b6e0a0217ea400030c4327080545a020024740821012707a5c48404051086100415805","prev_randao":"0xf9df27cb70f7641c3eb5c37eaa6c280f947e942a49ba9b8402c822b738e92e9c","block_number":"17548195","gas_limit":"30000000","gas_used":"9038961","timestamp":"1687595255","extra_data":"0x6631622e696f","base_fee_per_gas":"13892976382","block_hash":"0xcadbb9c8f14cf792d387675e6aa2481e448dbf815f6fc45114bca332f7b0b782","transactions_root":"0x0cda78b75e408e0193c55325882f8502fa80a8782084b7d0e76561e7f4bc0788","withdrawals_root":"0xce0b0820e2f718bdc15bf180ece1245efd84631fcd54ecac4f7aae665898a04c"},"execution_branch":["0x2ca90f7f3dd21d05aac1532a30408a87032b79a9c44543af59fb122031e1e350","0x336488033fe5f3ef4ccc12af07b9370b92e553e35ecb4a337a1b1c0e4afe1e0e","0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71","0x1031d488d3fc33675fba01982eac69540b1cab7846066f4396f17e82585c31e2"]},"sync_aggregate":{"sync_committee_bits":"0xfffffffff7ffefff7ffffffffffffffffffdffffffffffffffffffffffffffffffffffffdffffffffff7fffffffffffffffffffffffffffffffffffffffffffd","sync_committee_signature":"0xb5c6a7f6ea62e5ef45c3d2064de67de4dc63cd99ea1647580c6259550e0998fdf439fba837556b3cf3dbe9cf99df022507d29c1b1d2534ff7cecdebdfe9e6e516dd9f95ce1bf7e354648fd69cdb2f2452444114b398026f7ff4d6e1065143d1b"},"signature_slot":"6730937"}}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,354 @@
/**
* beacon_chain
* 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.
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libnimbus_lc.h"
#define check(condition) \
do { \
if (!(condition)) { \
printf("assertion failed: %s - %s @ %s:%d", \
#condition, __func__, __FILE__, __LINE__); \
exit(1); \
} \
} while (0)
#ifndef __DIR__
#define __DIR__ "."
#endif
ETH_RESULT_USE_CHECK
static void *readEntireFile(const char *path, int *numBytes)
{
int err;
FILE *file = fopen(path, "rb");
check(file);
err = fseek(file, 0, SEEK_END);
check(!err);
long size = ftell(file);
check(size >= 0);
err = fseek(file, 0, SEEK_SET);
check(!err);
char *buffer = malloc((size_t) size + 1);
check(buffer);
size_t actualSize = fread(buffer, 1, (size_t) size, file);
check(actualSize == (size_t) size);
buffer[size] = '\0';
fclose(file);
if (numBytes) {
check(size <= INT_MAX);
*numBytes = (int) actualSize;
}
return buffer;
}
ETH_RESULT_USE_CHECK
static ETHConsensusConfig *loadCfg(const char *path)
{
void *fileContent = readEntireFile(path, /* numBytes: */ NULL);
ETHConsensusConfig *cfg = ETHConsensusConfigCreateFromYaml(fileContent);
check(cfg);
free(fileContent);
return cfg;
}
ETH_RESULT_USE_CHECK
static ETHBeaconState *loadGenesis(const ETHConsensusConfig *cfg, const char *path)
{
const char *consensusFork = ETHConsensusConfigGetConsensusVersionAtEpoch(cfg, /* epoch: */ 0);
check(consensusFork);
int numSszBytes;
void *sszBytes = readEntireFile(path, &numSszBytes);
ETHBeaconState *state = ETHBeaconStateCreateFromSsz(
cfg, consensusFork, sszBytes, numSszBytes);
check(state);
free(sszBytes);
return state;
}
static void printHexString(const void *bytes, int numBytes)
{
const uint8_t *bytes_ = bytes;
printf("0x");
for (int i = 0; i < numBytes; i++) {
printf("%02x", bytes_[i]);
}
}
static void printGweiString(const ETHUInt256 *wei)
{
ETHUInt256 value;
memcpy(&value, wei, sizeof value);
char weiString[80];
int o = 0;
for (;;) {
bool isZero = true;
for (size_t i = 0; i < sizeof value; i++) {
if (value.bytes[i]) {
isZero = false;
break;
}
}
if (isZero) {
break;
}
uint8_t remainder = 0;
for (int i = sizeof value - 1; i >= 0; i--) {
uint16_t temp = (uint16_t) ((uint16_t) remainder << 8) | value.bytes[i];
value.bytes[i] = (uint8_t) (temp / 10);
remainder = temp % 10;
}
weiString[o++] = '0' + (char) remainder;
}
if (!o) {
weiString[o++] = '0';
}
if (o < 9) {
printf("0");
} else {
while (o > 9) {
printf("%c", weiString[--o]);
}
}
int z = 0;
while (z < o && weiString[z] == '0') {
z++;
}
if (o > z) {
printf(".");
while (o > z) {
printf("%c", weiString[--o]);
}
}
}
static void visualizeHeader(const ETHLightClientHeader *header, const ETHConsensusConfig *cfg)
{
ETHRoot *beaconRoot = ETHLightClientHeaderCopyBeaconRoot(header, cfg);
printf(" - beacon: ");
printHexString(beaconRoot, sizeof *beaconRoot);
printf("\n");
ETHRootDestroy(beaconRoot);
const ETHBeaconBlockHeader *beacon = ETHLightClientHeaderGetBeacon(header);
int beaconSlot = ETHBeaconBlockHeaderGetSlot(beacon);
printf(" - slot: %d\n", beaconSlot);
int beaconProposerIndex = ETHBeaconBlockHeaderGetProposerIndex(beacon);
printf(" - proposer_index: %d\n", beaconProposerIndex);
const ETHRoot *beaconParentRoot = ETHBeaconBlockHeaderGetParentRoot(beacon);
printf(" - parent_root: ");
printHexString(beaconParentRoot, sizeof *beaconParentRoot);
printf("\n");
const ETHRoot *beaconStateRoot = ETHBeaconBlockHeaderGetStateRoot(beacon);
printf(" - state_root: ");
printHexString(beaconStateRoot, sizeof *beaconStateRoot);
printf("\n");
const ETHRoot *beaconBodyRoot = ETHBeaconBlockHeaderGetBodyRoot(beacon);
printf(" - body_root: ");
printHexString(beaconBodyRoot, sizeof *beaconBodyRoot);
printf("\n");
ETHRoot *executionHash = ETHLightClientHeaderCopyExecutionHash(header, cfg);
printf(" - execution: ");
printHexString(executionHash, sizeof *executionHash);
printf("\n");
ETHRootDestroy(executionHash);
const ETHExecutionPayloadHeader *execution = ETHLightClientHeaderGetExecution(header);
const ETHRoot *executionParentHash = ETHExecutionPayloadHeaderGetParentHash(execution);
printf(" - parent_hash: ");
printHexString(executionParentHash, sizeof *executionParentHash);
printf("\n");
const ETHExecutionAddress *executionFeeRecipient =
ETHExecutionPayloadHeaderGetFeeRecipient(execution);
printf(" - fee_recipient: ");
printHexString(executionFeeRecipient, sizeof *executionFeeRecipient);
printf("\n");
const ETHRoot *executionStateRoot = ETHExecutionPayloadHeaderGetStateRoot(execution);
printf(" - state_root: ");
printHexString(executionStateRoot, sizeof *executionStateRoot);
printf("\n");
const ETHRoot *executionReceiptsRoot = ETHExecutionPayloadHeaderGetReceiptsRoot(execution);
printf(" - receipts_root: ");
printHexString(executionReceiptsRoot, sizeof *executionReceiptsRoot);
printf("\n");
const ETHLogsBloom *executionLogsBloom = ETHExecutionPayloadHeaderGetLogsBloom(execution);
printf(" - logs_bloom: ");
printHexString(executionLogsBloom, sizeof *executionLogsBloom);
printf("\n");
const ETHRoot *executionPrevRandao = ETHExecutionPayloadHeaderGetPrevRandao(execution);
printf(" - prev_randao: ");
printHexString(executionPrevRandao, sizeof *executionPrevRandao);
printf("\n");
int executionBlockNumber = ETHExecutionPayloadHeaderGetBlockNumber(execution);
printf(" - block_number: %d\n", executionBlockNumber);
int executionGasLimit = ETHExecutionPayloadHeaderGetGasLimit(execution);
printf(" - gas_limit: %d\n", executionGasLimit);
int executionGasUsed = ETHExecutionPayloadHeaderGetGasUsed(execution);
printf(" - gas_used: %d\n", executionGasUsed);
int executionTimestamp = ETHExecutionPayloadHeaderGetTimestamp(execution);
printf(" - timestamp: %d\n", executionTimestamp);
const void *executionExtraDataBytes = ETHExecutionPayloadHeaderGetExtraDataBytes(execution);
int numExecutionExtraDataBytes = ETHExecutionPayloadHeaderGetNumExtraDataBytes(execution);
printf(" - extra_data: ");
printHexString(executionExtraDataBytes, numExecutionExtraDataBytes);
printf("\n");
const ETHUInt256 *executionBaseFeePerGas = ETHExecutionPayloadHeaderGetBaseFeePerGas(execution);
printf(" - base_fee_per_gas: ");
printGweiString(executionBaseFeePerGas);
printf(" Gwei\n");
int executionDataGasUsed = ETHExecutionPayloadHeaderGetDataGasUsed(execution);
printf(" - data_gas_used: %d\n", executionDataGasUsed);
int executionExcessDataGas = ETHExecutionPayloadHeaderGetExcessDataGas(execution);
printf(" - excess_data_gas: %d\n", executionExcessDataGas);
}
ETH_RESULT_USE_CHECK
int main(void)
{
NimMain();
ETHRandomNumber *rng = ETHRandomNumberCreate();
check(rng);
ETHConsensusConfig *cfg = loadCfg(__DIR__ "/test_files/config.yaml");
ETHBeaconState *genesisState = loadGenesis(cfg, __DIR__ "/test_files/genesis.ssz");
ETHRoot *genesisValRoot = ETHBeaconStateCopyGenesisValidatorsRoot(genesisState);
ETHForkDigests *forkDigests = ETHForkDigestsCreateFromState(cfg, genesisState);
ETHBeaconClock *beaconClock = ETHBeaconClockCreateFromState(genesisState);
ETHBeaconStateDestroy(genesisState);
printf("Current slot: %d\n", ETHBeaconClockGetSlot(beaconClock));
printf("\n");
const ETHRoot trustedBlockRoot = {{
0x15, 0xcf, 0x56, 0xeb, 0xf8, 0x87, 0xed, 0xe9,
0xcf, 0x3f, 0xc1, 0x0a, 0x26, 0xec, 0x83, 0x82,
0x86, 0x28, 0x93, 0x2c, 0x10, 0x0e, 0x42, 0xc9,
0x8c, 0x84, 0xf8, 0x3d, 0xa7, 0x10, 0xc8, 0x63
}};
int numBootstrapBytes;
void *bootstrapBytes = readEntireFile(__DIR__ "/test_files/bootstrap.ssz", &numBootstrapBytes);
ETHLightClientStore *store = ETHLightClientStoreCreateFromBootstrap(
cfg, &trustedBlockRoot,
"application/octet-stream", "capella", bootstrapBytes, numBootstrapBytes);
check(store);
free(bootstrapBytes);
int startPeriod;
int count;
int syncKind = ETHLightClientStoreGetNextSyncTask(store, beaconClock, &startPeriod, &count);
check(syncKind == kETHLcSyncKind_UpdatesByRange);
check(startPeriod == 800);
check(count > 0 && count <= 128);
printf("Sync task: UpdatesByRange(%d, %d)\n", startPeriod, count);
int latestProcessResult;
int numUpdatesBytes;
void *updatesBytes = readEntireFile(__DIR__ "/test_files/updates.ssz", &numUpdatesBytes);
latestProcessResult = ETHLightClientStoreProcessUpdatesByRange(
store, cfg, forkDigests, genesisValRoot, beaconClock,
startPeriod, count, "application/octet-stream", updatesBytes, numUpdatesBytes);
check(!latestProcessResult);
free(updatesBytes);
int millisecondsToNextSyncTask = ETHLightClientStoreGetMillisecondsToNextSyncTask(
store, rng, beaconClock, latestProcessResult);
printf("Next sync task: %d.%03ds\n",
millisecondsToNextSyncTask / 1000,
millisecondsToNextSyncTask % 1000);
int numFinUpdateBytes;
void *finUpdateBytes = readEntireFile(__DIR__ "/test_files/finUpdate.ssz", &numFinUpdateBytes);
latestProcessResult = ETHLightClientStoreProcessFinalityUpdate(
store, cfg, forkDigests, genesisValRoot, beaconClock,
"application/octet-stream", "capella", finUpdateBytes, numFinUpdateBytes);
check(!latestProcessResult);
free(finUpdateBytes);
int numOptUpdateBytes;
void *optUpdateBytes = readEntireFile(__DIR__ "/test_files/optUpdate.ssz", &numOptUpdateBytes);
latestProcessResult = ETHLightClientStoreProcessOptimisticUpdate(
store, cfg, forkDigests, genesisValRoot, beaconClock,
"application/octet-stream", "capella", optUpdateBytes, numOptUpdateBytes);
check(!latestProcessResult);
free(optUpdateBytes);
finUpdateBytes = readEntireFile(__DIR__ "/test_files/finUpdate.json", &numFinUpdateBytes);
latestProcessResult = ETHLightClientStoreProcessFinalityUpdate(
store, cfg, forkDigests, genesisValRoot, beaconClock,
"application/json", /* consensusVersion: */ NULL, finUpdateBytes, numFinUpdateBytes);
check(!latestProcessResult);
free(finUpdateBytes);
optUpdateBytes = readEntireFile(__DIR__ "/test_files/optUpdate.json", &numOptUpdateBytes);
latestProcessResult = ETHLightClientStoreProcessOptimisticUpdate(
store, cfg, forkDigests, genesisValRoot, beaconClock,
"application/json", /* consensusVersion: */ NULL, optUpdateBytes, numOptUpdateBytes);
check(!latestProcessResult);
free(optUpdateBytes);
printf("\n");
printf("- finalized_header\n");
visualizeHeader(ETHLightClientStoreGetFinalizedHeader(store), cfg);
bool isNextSyncCommitteeKnown = ETHLightClientStoreIsNextSyncCommitteeKnown(store);
printf("- next_sync_committee: %s\n", isNextSyncCommitteeKnown ? "known" : "unknown");
printf("- optimistic_header\n");
visualizeHeader(ETHLightClientStoreGetOptimisticHeader(store), cfg);
int safetyThreshold = ETHLightClientStoreGetSafetyThreshold(store);
printf("- safety_threshold: %d\n", safetyThreshold);
ETHLightClientStoreDestroy(store);
ETHBeaconClockDestroy(beaconClock);
ETHForkDigestsDestroy(forkDigests);
ETHRootDestroy(genesisValRoot);
ETHConsensusConfigDestroy(cfg);
ETHRandomNumberDestroy(rng);
return 0;
}

View File

@ -56,7 +56,7 @@ func decodeSszLightClientObject[T: SomeForkedLightClientObject](
except SerializationError as exc:
raiseRestDecodingBytesError(cstring("Malformed data: " & $exc.msg))
proc decodeJsonLightClientObject[T: SomeForkedLightClientObject](
proc decodeJsonLightClientObject*[T: SomeForkedLightClientObject](
x: typedesc[T],
data: openArray[byte],
consensusFork: Opt[ConsensusFork],

View File

@ -468,7 +468,7 @@ func parse(T: type DomainType, input: string): T
{.raises: [ValueError, Defect].} =
DomainType hexToByteArray(input, 4)
proc readRuntimeConfig(
proc readRuntimeConfig*(
fileContent: string, path: string): (RuntimeConfig, seq[string]) {.
raises: [IOError, PresetFileError, PresetIncompatibleError, Defect].} =
var