diff --git a/vendor/zkllvm-metacraft-circuits/scripts/docker_run.sh b/vendor/zkllvm-metacraft-circuits/scripts/docker_run.sh index a1e34adc5..80127ac4f 100755 --- a/vendor/zkllvm-metacraft-circuits/scripts/docker_run.sh +++ b/vendor/zkllvm-metacraft-circuits/scripts/docker_run.sh @@ -13,6 +13,9 @@ docker run --rm -it --name zk_executable_tests \ --volume ${SCRIPT_DIR}/../../consensus-spec-tests/:/consensus-spec-tests \ --volume ${SCRIPT_DIR}/../src/tests/verify_attestation_data_test/finalizer-data:/finalizer-data \ --volume ${SCRIPT_DIR}/../src/:/zkllvm-template/src \ + --volume ${SCRIPT_DIR}/../.config:/.config/ \ + --volume ${SCRIPT_DIR}/../.config:/root/.config/ \ + --volume ${SCRIPT_DIR}/../.config:/opt/nil-toolchain/.config/ \ --user $(id -u ${USER}):$(id -g ${USER}) \ -w /zkllvm-template \ zkllvm:latest \ diff --git a/vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt b/vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt index 13fc633ef..62a959f13 100644 --- a/vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt +++ b/vendor/zkllvm-metacraft-circuits/src/CMakeLists.txt @@ -55,3 +55,4 @@ enable_testing() add_subdirectory(tests) add_subdirectory(circuits) +add_subdirectory(circuit_input_generators) diff --git a/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/CMakeLists.txt b/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/CMakeLists.txt new file mode 100644 index 000000000..bcd1f87fe --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/CMakeLists.txt @@ -0,0 +1,38 @@ +add_executable(verify_attestation_data_input_generators verify_attestation_data_input_generators.cpp) + +add_dependencies(template verify_attestation_data_input_generators) + +target_link_libraries (verify_attestation_data_input_generators +crypto3::algebra +crypto3::block +crypto3::codec +crypto3::containers +crypto3::hash +crypto3::kdf +crypto3::mac +marshalling::core +marshalling::crypto3_algebra +marshalling::crypto3_multiprecision +marshalling::crypto3_zk +crypto3::math +crypto3::modes +crypto3::multiprecision +crypto3::passhash +crypto3::pbkdf +crypto3::threshold +crypto3::pkpad +crypto3::pubkey +crypto3::random +crypto3::stream +crypto3::vdf +crypto3::zk + +${Boost_LIBRARIES}) + +target_include_directories(verify_attestation_data_input_generators PRIVATE ${PROJECT_SOURCE_DIR}/src) + +add_custom_command(TARGET verify_attestation_data_input_generators POST_BUILD + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/verify_attestation_data_input_generators ${CMAKE_CURRENT_BINARY_DIR}/../circuits/verify_attestation_data + DEPENDS compile_commands.json + VERBATIM ON +) diff --git a/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/serialization/json_serialization_utils.h b/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/serialization/json_serialization_utils.h new file mode 100644 index 000000000..6a2787de7 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/serialization/json_serialization_utils.h @@ -0,0 +1,117 @@ +#pragma once + +#include + +#include "json/json.hpp" +using namespace nlohmann; + +nlohmann::json pack_int_json(uint64_t val) { + nlohmann::json j; + j["int"] = val; + return j; +} + +std::ostream& operator<<(std::ostream& dest, __uint128_t value) { + std::ostream::sentry s(dest); + if (s) { + char buffer[128]; + char* d = std::end(buffer); + do { + --d; + *d = "0123456789"[value % 10]; + value /= 10; + } while (value != 0); + int len = std::end(buffer) - d; + if (dest.rdbuf()->sputn(d, len) != len) { + dest.setstate(std::ios_base::badbit); + } + } + return dest; +} + +// Example expected output: +// {"vector": [{"field": "326522724692461750427768532537390503835"},{"field": +// "89059515727727869117346995944635890507"}]}, +nlohmann::json bytes32_to_hash_type(const Bytes32& bytes) { + union Convert { + __uint128_t v[2]; + Byte bytes[32]; + } c; + for (size_t i = 0; i < bytes.size(); i++) { + c.bytes[bytes.size() - i - 1] = bytes[i]; + } + std::stringstream val[2]; + nlohmann::json field[2]; + nlohmann::json result; + + for (size_t i = 0; i < 2; i++) { + val[i] << c.v[i]; + field[i]["field"] = val[i].str(); + result["vector"].push_back(field[i]); + } + + return result; +} + +template +static_vector json_to_byte_array(const nlohmann::json& j) { + static_vector result; + size_t i = 0; + for (const auto& v : j["array"]) { + result[i++] = v["int"]; + } + return result; +} + +template +nlohmann::json serialize(const T& val); + +template +nlohmann::json serialize_vector(const static_vector& bytes) { + nlohmann::json res_array; + for (size_t i = 0; i < N; i++) { + res_array["array"].push_back(pack_int_json(bytes[i])); + } + nlohmann::json result; + result["struct"].push_back(res_array); + return result; +} + +nlohmann::json serialize_vector(HashType h) { + return bytes32_to_hash_type(h); +} + +template +nlohmann::json serialize_vector(const static_vector& v) { + nlohmann::json result; + result["struct"].push_back(pack_int_json((size_t)v.size())); + nlohmann::json elements; + for (size_t i = 0; i < S; i++) { + elements["array"].push_back(serialize(v[i])); + } + result["struct"].push_back(elements); + return result; +} + +template +nlohmann::json serialize_vector(const static_vector, S, B>& v) { + nlohmann::json result; + result["struct"].push_back(pack_int_json((size_t)v.size())); + nlohmann::json elements; + for (size_t i = 0; i < S; i++) { + elements["array"].push_back(serialize_vector(v[i])); + } + result["struct"].push_back(elements); + return result; +} + +template +nlohmann::json byte_array_to_json(const static_vector& bytes) { + nlohmann::json res_array; + for (size_t i = 0; i < N; i++) { + res_array["array"].push_back(pack_int_json(bytes[i])); + } + nlohmann::json result; + result["struct"].push_back(res_array); + return result; +} diff --git a/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/serialization/serialize_attestation.h b/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/serialization/serialize_attestation.h new file mode 100644 index 000000000..db8b6c2a7 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/serialization/serialize_attestation.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include +#include + +#include "json_serialization_utils.h" +#include "../../circuits_impl/verify_attestation_data_imp.h" + +template<> +nlohmann::json serialize(const CheckpointVariable& checkpoint) { + nlohmann::json result; + result["struct"].push_back(pack_int_json(checkpoint.epoch)); + result["struct"].push_back(bytes32_to_hash_type(checkpoint.root)); + return result; +} + +template<> +nlohmann::json serialize(const AttestationData& attestationData) { + nlohmann::json result; + result["struct"].push_back(pack_int_json(attestationData.slot)); + result["struct"].push_back(pack_int_json(attestationData.index)); + result["struct"].push_back(bytes32_to_hash_type(attestationData.beacon_block_root)); + result["struct"].push_back(serialize(attestationData.source)); + result["struct"].push_back(serialize(attestationData.target)); + return result; +} + +AttestationData deserializeAttestationData(const nlohmann::json& j) { + AttestationData ad; + // ad.slot = bytes_to_int(bytes); + // ad.index = bytes_to_int(bytes); + return ad; +} + +template<> +nlohmann::json serialize(const Validator& validator) { + nlohmann::json result; + result["struct"].push_back(pack_int_json((int)validator.trusted)); + result["struct"].push_back(pack_int_json(validator.validator_index)); + result["struct"].push_back(byte_array_to_json(validator.pubkey)); + result["struct"].push_back(byte_array_to_json(validator.withdrawal_credentials)); + result["struct"].push_back(pack_int_json(validator.effective_balance)); + result["struct"].push_back(pack_int_json(validator.slashed)); + result["struct"].push_back(pack_int_json(validator.activation_eligibility_epoch)); + result["struct"].push_back(pack_int_json(validator.activation_epoch)); + result["struct"].push_back(pack_int_json(validator.exit_epoch)); + result["struct"].push_back(pack_int_json(validator.withdrawable_epoch)); + result["struct"].push_back(serialize_vector(validator.validator_list_proof)); + return result; +} + +template<> +nlohmann::json serialize(const Fork& fork) { + nlohmann::json result; + result["struct"].push_back(byte_array_to_json(fork.previous_version)); + result["struct"].push_back(byte_array_to_json(fork.current_version)); + result["struct"].push_back(pack_int_json(fork.epoch)); + return result; +} + +template<> +nlohmann::json serialize(const Attestation& attestation) { + nlohmann::json result; + result["struct"].push_back(serialize(attestation.data)); + result["struct"].push_back(byte_array_to_json(attestation.signature)); + result["struct"].push_back(serialize(attestation.fork)); + result["struct"].push_back(byte_array_to_json(attestation.genesis_validators_root)); + result["struct"].push_back(bytes32_to_hash_type(attestation.state_root)); + result["struct"].push_back(serialize_vector(attestation.state_root_proof)); + result["struct"].push_back(bytes32_to_hash_type(attestation.validators_root)); + result["struct"].push_back(serialize_vector(attestation.validators_root_proof)); + result["struct"].push_back(serialize_vector(attestation.validators)); + + return result; +} \ No newline at end of file diff --git a/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/verify_attestation_data_input_generators.cpp b/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/verify_attestation_data_input_generators.cpp new file mode 100644 index 000000000..8fe4b4c9b --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/circuit_input_generators/verify_attestation_data_input_generators.cpp @@ -0,0 +1,61 @@ + +#include "circuit_utils/circuit_byte_utils.h" + +#include +#include +#include + +#include +#include +#include +#include + +#include "utils/picosha2.h" +#include "utils/byte_utils.h" +#include "utils/file_utils.h" +#include "serialization/serialize_attestation.h" + +#include "circuits_impl/verify_attestation_data_imp.h" +#include "utils/attestation_utils.h" + +using namespace circuit_byte_utils; +using namespace byte_utils; +using namespace file_utils; +using namespace attestation_utils; + +using std::cout; + +constexpr size_t MAX_KEYS = 1'000'000; + +int main(int argc, char* argv[]) { + + if (argc < 2) { + std::cerr << "Needed argument for JSON output.\n"; + return -1; + } + std::cout << "processing /finalizer-data/merged_234400.json\n"; + path my_path("/finalizer-data/merged_234400.json"); + std::ifstream f(my_path); + auto data = json::parse(f); + + // Generate JSON representation to pass to circuit for each attestation. + for (const auto& json_attestation : data["attestations"]) { + + Attestation attestation = parse_attestation(json_attestation); + + std::ofstream fout(std::string(argv[1]) + ".json"); + fout << "[" + << bytes32_to_hash_type(hexToBytes<32>("d5c0418465ffab221522a6991c2d4c0041f1b8e91d01b1ea3f6b882369f689b7")) + << ", " << serialize(attestation) //.dump(2) + << ", " + << "{\"field\": 105}" + << "]"; + fout.flush(); + + std::cout << "DONE\n"; + + break; // Temporarily only process 1 attestation. + } + + return 0; +} diff --git a/vendor/zkllvm-metacraft-circuits/src/circuit_utils/static_vector.h b/vendor/zkllvm-metacraft-circuits/src/circuit_utils/static_vector.h index bd7502519..6fbf02d59 100644 --- a/vendor/zkllvm-metacraft-circuits/src/circuit_utils/static_vector.h +++ b/vendor/zkllvm-metacraft-circuits/src/circuit_utils/static_vector.h @@ -9,8 +9,8 @@ using Byte = unsigned char; template struct static_vector { - T content_[CAPACITY]; size_t size_; + T content_[CAPACITY]; constexpr static_vector(std::initializer_list init) { size_ = 0; @@ -43,23 +43,10 @@ struct static_vector { size_ = 0; } } - constexpr static_vector(const static_vector& rhs) { - for (size_t i = 0; i < rhs.size_; i++) { - content_[i] = rhs[i]; - } - size_ = rhs.size_; - } // For some reason, this triggers a circuit compilation error // ~static_vector() { // size_ = 0; // } - constexpr auto operator=(const static_vector& rhs) -> static_vector& { - for (size_t i = 0; i < rhs.size_; i++) { - content_[i] = rhs[i]; - } - size_ = rhs.size_; - return *this; - } constexpr auto data() -> T* { return &content_; } diff --git a/vendor/zkllvm-metacraft-circuits/src/circuits/CMakeLists.txt b/vendor/zkllvm-metacraft-circuits/src/circuits/CMakeLists.txt index c836d4948..c4eb5e0aa 100644 --- a/vendor/zkllvm-metacraft-circuits/src/circuits/CMakeLists.txt +++ b/vendor/zkllvm-metacraft-circuits/src/circuits/CMakeLists.txt @@ -1,8 +1,10 @@ add_example(compute_shuffled_index SOURCES compute_shuffled_index.cpp) add_example(weigh_justification_and_finalization SOURCES weigh_justification_and_finalization.cpp) +add_example(verify_attestation_data SOURCES verify_attestation_data.cpp) add_dependencies(template compute_shuffled_index) add_dependencies(template weigh_justification_and_finalization) +add_dependencies(template verify_attestation_data) add_custom_command(TARGET compute_shuffled_index POST_BUILD COMMAND cp -r ${CMAKE_CURRENT_SOURCE_DIR}/compute_shuffled_index.json ${CMAKE_CURRENT_BINARY_DIR} diff --git a/vendor/zkllvm-metacraft-circuits/src/circuits/compute_shuffled_index.cpp b/vendor/zkllvm-metacraft-circuits/src/circuits/compute_shuffled_index.cpp index 91e5b9624..c80de4876 100644 --- a/vendor/zkllvm-metacraft-circuits/src/circuits/compute_shuffled_index.cpp +++ b/vendor/zkllvm-metacraft-circuits/src/circuits/compute_shuffled_index.cpp @@ -1,5 +1,4 @@ #include "../circuits_impl/compute_shuffled_index_impl.h" -#include [[circuit]] uint64_t compute_shuffled_index(uint64_t index, uint64_t index_count, Bytes32 seed, int SHUFFLE_ROUND_COUNT) { diff --git a/vendor/zkllvm-metacraft-circuits/src/circuits/verify_attestation_data.cpp b/vendor/zkllvm-metacraft-circuits/src/circuits/verify_attestation_data.cpp new file mode 100644 index 000000000..e23d79b73 --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/circuits/verify_attestation_data.cpp @@ -0,0 +1,7 @@ +#include "../circuits_impl/verify_attestation_data_imp.h" + +[[circuit]] base_field_type + verify_attestation_data(HashType block_root, Attestation attestation, base_field_type sigma) { + auto result = verify_attestation_data_imp(block_root, attestation, sigma); + return result.token; +} diff --git a/vendor/zkllvm-metacraft-circuits/src/circuits_impl/verify_attestation_data_imp.h b/vendor/zkllvm-metacraft-circuits/src/circuits_impl/verify_attestation_data_imp.h index 4a7495270..64144eb0e 100644 --- a/vendor/zkllvm-metacraft-circuits/src/circuits_impl/verify_attestation_data_imp.h +++ b/vendor/zkllvm-metacraft-circuits/src/circuits_impl/verify_attestation_data_imp.h @@ -284,6 +284,7 @@ void prove_finality(const VoteToken& token, const int64_t active_validators_count) { assert_true(votedTransition == token.transition); base_field_type reconstructed_token = 0; + uint64_t votes_count = process_votes(trustedKeys, pubkeysCount, sigma, reconstructed_token); assert_true(reconstructed_token == token.token); diff --git a/vendor/zkllvm-metacraft-circuits/src/tests/verify_attestation_data_test/verify_attestation_data_test.cpp b/vendor/zkllvm-metacraft-circuits/src/tests/verify_attestation_data_test/verify_attestation_data_test.cpp index 3314d3101..671be2962 100644 --- a/vendor/zkllvm-metacraft-circuits/src/tests/verify_attestation_data_test/verify_attestation_data_test.cpp +++ b/vendor/zkllvm-metacraft-circuits/src/tests/verify_attestation_data_test/verify_attestation_data_test.cpp @@ -21,12 +21,14 @@ using namespace nlohmann; #include "circuits_impl/verify_attestation_data_imp.h" +#include "utils/attestation_utils.h" using namespace nil::crypto3::algebra::curves; using namespace circuit_byte_utils; using namespace byte_utils; using namespace file_utils; +using namespace attestation_utils; using std::cout; @@ -153,100 +155,6 @@ void basic_tests() { assert_true((bytes_to_int(bytesVal)) == val); } -AttestationData parse_attestation_data(const json& json_attestation_data) { - AttestationData attestation_data; - attestation_data.slot = json_attestation_data["slot"]; - attestation_data.index = json_attestation_data["index"]; - attestation_data.beacon_block_root = hexToBytes<32>(json_attestation_data["beacon_block_root"]); - attestation_data.source.epoch = json_attestation_data["source"]["epoch"]; - attestation_data.source.root = hexToBytes<32>(json_attestation_data["source"]["root"]); - attestation_data.target.epoch = json_attestation_data["target"]["epoch"]; - attestation_data.target.root = hexToBytes<32>(json_attestation_data["target"]["root"]); - return attestation_data; -} - -Fork parse_fork(const json& json_fork) { - Fork fork; - fork.current_version = circuit_byte_utils::expand<32>(hexToBytes<4>(json_fork["current_version"])); - fork.previous_version = circuit_byte_utils::expand<32>(hexToBytes<4>(json_fork["previous_version"])); - fork.epoch = json_fork["epoch"]; - return fork; -} - -Validator parse_validator(const json& json_validator) { - Validator validator; - validator.trusted = json_validator["trusted"]; - validator.validator_index = json_validator["validator_index"]; - validator.pubkey = hexToBytes<48>(json_validator["pubkey"]); - std::string withdrawal_credentials; - if (json_validator.contains("withdrawal_credentials")) { - withdrawal_credentials = json_validator["withdrawal_credentials"]; - } else { - withdrawal_credentials.assign(64, '0'); - } - validator.withdrawal_credentials = hexToBytes<32>(withdrawal_credentials); - if (json_validator.contains("effective_balance")) { - validator.effective_balance = json_validator["effective_balance"]; - } else { - validator.effective_balance = 0; - } - if (json_validator.contains("slashed")) { - validator.slashed = json_validator["slashed"]; - } else { - validator.slashed = false; - } - if (json_validator.contains("activation_eligibility_epoch")) { - validator.activation_eligibility_epoch = json_validator["activation_eligibility_epoch"]; - } else { - validator.activation_eligibility_epoch = 0; - } - if (json_validator.contains("activation_epoch")) { - validator.activation_epoch = json_validator["activation_epoch"]; - } else { - validator.activation_epoch = 0; - } - if (json_validator.contains("exit_epoch")) { - validator.exit_epoch = json_validator["exit_epoch"]; - } else { - validator.exit_epoch = 0; - } - if (json_validator.contains("withdrawable_epoch")) { - validator.withdrawable_epoch = json_validator["withdrawable_epoch"]; - } else { - validator.withdrawable_epoch = 0; - } - if (json_validator.contains("validator_list_proof")) { - for (size_t i = 0; i < json_validator["validator_list_proof"].size(); i++) { - std::string element = json_validator["validator_list_proof"][i]; - if (element.size() == 0) { - element.assign(64, '0'); - } - validator.validator_list_proof.push_back(hexToBytes<32>(element)); - } - } - return validator; -} - -Attestation parse_attestation(const json& json_attestation) { - Attestation attestation; - attestation.data = parse_attestation_data(json_attestation["data"]); - attestation.signature = hexToBytes<96>(json_attestation["signature"]); - attestation.fork = parse_fork(json_attestation["fork"]); - attestation.genesis_validators_root = hexToBytes<32>(json_attestation["genesis_validators_root"]); - attestation.state_root = hexToBytes<32>(json_attestation["state_root"]); - for (size_t i = 0; i < json_attestation["state_root_proof"].size(); i++) { - attestation.state_root_proof[i] = hexToBytes<32>(json_attestation["state_root_proof"][i]); - } - attestation.validators_root = hexToBytes<32>(json_attestation["validators_root"]); - for (size_t i = 0; i < json_attestation["validators_root_proof"].size(); i++) { - attestation.validators_root_proof[i] = hexToBytes<32>(json_attestation["validators_root_proof"][i]); - } - for (size_t i = 0; i < json_attestation["validators"].size(); i++) { - attestation.validators.push_back(parse_validator(json_attestation["validators"][i])); - } - return attestation; -} - void print_attestation(const Attestation& a) { std::cout << "a.data.slot = " << a.data.slot << "\n"; std::cout << "a.data.index = " << a.data.index << "\n"; diff --git a/vendor/zkllvm-metacraft-circuits/src/utils/attestation_utils.h b/vendor/zkllvm-metacraft-circuits/src/utils/attestation_utils.h new file mode 100644 index 000000000..f1f974f9e --- /dev/null +++ b/vendor/zkllvm-metacraft-circuits/src/utils/attestation_utils.h @@ -0,0 +1,107 @@ +#pragma once + +#include "json/json.hpp" +using namespace nlohmann; + +#include "byte_utils.h" +using namespace byte_utils; + +#include "circuits_impl/verify_attestation_data_imp.h" + +namespace attestation_utils { + + AttestationData parse_attestation_data(const json& json_attestation_data) { + AttestationData attestation_data; + attestation_data.slot = json_attestation_data["slot"]; + attestation_data.index = json_attestation_data["index"]; + attestation_data.beacon_block_root = hexToBytes<32>(json_attestation_data["beacon_block_root"]); + attestation_data.source.epoch = json_attestation_data["source"]["epoch"]; + attestation_data.source.root = hexToBytes<32>(json_attestation_data["source"]["root"]); + attestation_data.target.epoch = json_attestation_data["target"]["epoch"]; + attestation_data.target.root = hexToBytes<32>(json_attestation_data["target"]["root"]); + return attestation_data; + } + + Fork parse_fork(const json& json_fork) { + Fork fork; + fork.current_version = circuit_byte_utils::expand<32>(hexToBytes<4>(json_fork["current_version"])); + fork.previous_version = circuit_byte_utils::expand<32>(hexToBytes<4>(json_fork["previous_version"])); + fork.epoch = json_fork["epoch"]; + return fork; + } + + Validator parse_validator(const json& json_validator) { + Validator validator; + validator.trusted = json_validator["trusted"]; + validator.validator_index = json_validator["validator_index"]; + validator.pubkey = hexToBytes<48>(json_validator["pubkey"]); + std::string withdrawal_credentials; + if (json_validator.contains("withdrawal_credentials")) { + withdrawal_credentials = json_validator["withdrawal_credentials"]; + } else { + withdrawal_credentials.assign(64, '0'); + } + validator.withdrawal_credentials = hexToBytes<32>(withdrawal_credentials); + if (json_validator.contains("effective_balance")) { + validator.effective_balance = json_validator["effective_balance"]; + } else { + validator.effective_balance = 0; + } + if (json_validator.contains("slashed")) { + validator.slashed = json_validator["slashed"]; + } else { + validator.slashed = false; + } + if (json_validator.contains("activation_eligibility_epoch")) { + validator.activation_eligibility_epoch = json_validator["activation_eligibility_epoch"]; + } else { + validator.activation_eligibility_epoch = 0; + } + if (json_validator.contains("activation_epoch")) { + validator.activation_epoch = json_validator["activation_epoch"]; + } else { + validator.activation_epoch = 0; + } + if (json_validator.contains("exit_epoch")) { + validator.exit_epoch = json_validator["exit_epoch"]; + } else { + validator.exit_epoch = 0; + } + if (json_validator.contains("withdrawable_epoch")) { + validator.withdrawable_epoch = json_validator["withdrawable_epoch"]; + } else { + validator.withdrawable_epoch = 0; + } + if (json_validator.contains("validator_list_proof")) { + for (size_t i = 0; i < json_validator["validator_list_proof"].size(); i++) { + std::string element = json_validator["validator_list_proof"][i]; + if (element.size() == 0) { + element.assign(64, '0'); + } + validator.validator_list_proof.push_back(hexToBytes<32>(element)); + } + } + return validator; + } + + Attestation parse_attestation(const json& json_attestation) { + Attestation attestation; + attestation.data = parse_attestation_data(json_attestation["data"]); + attestation.signature = hexToBytes<96>(json_attestation["signature"]); + attestation.fork = parse_fork(json_attestation["fork"]); + attestation.genesis_validators_root = hexToBytes<32>(json_attestation["genesis_validators_root"]); + attestation.state_root = hexToBytes<32>(json_attestation["state_root"]); + for (size_t i = 0; i < json_attestation["state_root_proof"].size(); i++) { + attestation.state_root_proof[i] = hexToBytes<32>(json_attestation["state_root_proof"][i]); + } + attestation.validators_root = hexToBytes<32>(json_attestation["validators_root"]); + for (size_t i = 0; i < json_attestation["validators_root_proof"].size(); i++) { + attestation.validators_root_proof[i] = hexToBytes<32>(json_attestation["validators_root_proof"][i]); + } + for (size_t i = 0; i < json_attestation["validators"].size(); i++) { + attestation.validators.push_back(parse_validator(json_attestation["validators"][i])); + } + return attestation; + } + +} // namespace attestation_utils \ No newline at end of file