diff --git a/.bazelignore b/.bazelignore new file mode 100644 index 000000000000..7b7803117d38 --- /dev/null +++ b/.bazelignore @@ -0,0 +1,7 @@ +# Directories to exclude from Bazel's file watching +.git +node_modules +.avalanchego +build +.direnv +result diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 000000000000..7dba04158631 --- /dev/null +++ b/.bazelrc @@ -0,0 +1,30 @@ +# Bazel configuration for avalanchego + +# Enable bzlmod (default in Bazel 7+, explicit for clarity) +common --enable_bzlmod + +# Build settings +build --incompatible_enable_cc_toolchain_resolution + +# CGO flags for BLST cryptography library +# Must match scripts/build.sh: CGO_CFLAGS="-O2 -D__BLST_PORTABLE__" +build --action_env=CGO_CFLAGS="-O2 -D__BLST_PORTABLE__" +build --action_env=CGO_ENABLED=1 + +# Use purego build tag for gnark-crypto to avoid assembly include path issues +# gnark-crypto's assembly files use cross-package #include which Bazel doesn't support +build --define gotags=purego + +# Test settings +test --test_output=errors + +# Performance +build --jobs=auto + +# Nix integration - allow network for nix-build +# This may need adjustment based on your Bazel sandbox configuration +build --sandbox_add_mount_pair=/nix + +# Version injection - provides STABLE_GIT_COMMIT for x_defs +build --workspace_status_command=tools/bazel/workspace_status.sh +build --stamp diff --git a/.gitignore b/.gitignore index f2c2f521d92f..a166c1457938 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,6 @@ vendor # debug files __debug_* + +# Bazel symlinks +/bazel-* diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 000000000000..275a4237c9a8 --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,49 @@ +load("@gazelle//:def.bzl", "gazelle") + +# Gazelle configuration +# gazelle:prefix github.com/ava-labs/avalanchego +# gazelle:exclude .git +# gazelle:exclude build +# gazelle:exclude .direnv + +# Resolve coreth imports to local packages (handle replace directive) +# gazelle:resolve go github.com/ava-labs/avalanchego/graft/coreth //graft/coreth +# gazelle:resolve go github.com/ava-labs/avalanchego/graft/coreth/plugin/evm //graft/coreth/plugin/evm + +# Resolve proto pb imports - prefer the pb versions +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/p2p //proto/pb/p2p +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/rpcdb //proto/pb/rpcdb +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/sharedmemory //proto/pb/sharedmemory +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/aliasreader //proto/pb/aliasreader +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/appsender //proto/pb/appsender +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/validatorstate //proto/pb/validatorstate +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/sdk //proto/pb/sdk +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/platformvm //proto/pb/platformvm +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/warp //proto/pb/warp +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/sync //proto/pb/sync +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/vm //proto/pb/vm +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/http //proto/pb/http +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/http/responsewriter //proto/pb/http/responsewriter +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/io/reader //proto/pb/io/reader +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/io/writer //proto/pb/io/writer +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/net/conn //proto/pb/net/conn +# gazelle:resolve go github.com/ava-labs/avalanchego/proto/pb/signer //proto/pb/signer +# gazelle:resolve go github.com/ava-labs/avalanchego/connectproto/pb/proposervm //connectproto/pb/proposervm +# gazelle:resolve go github.com/ava-labs/avalanchego/connectproto/pb/xsvm //connectproto/pb/xsvm + +# Resolve firewood imports to local build (handle both module names) +# gazelle:resolve go github.com/ava-labs/firewood-go-ethhash/ffi //firewood/ffi:ffi +# gazelle:resolve go github.com/ava-labs/firewood/ffi //firewood/ffi:ffi + +gazelle(name = "gazelle") + +# Target to update external Go dependencies +gazelle( + name = "gazelle-update-repos", + args = [ + "-from_file=go.mod", + "-to_macro=deps.bzl%go_dependencies", + "-prune", + ], + command = "update-repos", +) diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 000000000000..389ecc253f38 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,193 @@ +"""Bazel module definition for avalanchego.""" + +module( + name = "avalanchego", + version = "0.0.0", +) + +# Core dependencies from Bazel Central Registry +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "1.0.0") +bazel_dep(name = "rules_go", version = "0.59.0") +bazel_dep(name = "gazelle", version = "0.47.0") +bazel_dep(name = "rules_rust", version = "0.67.0") + +# Rust toolchain for firewood +rust = use_extension("@rules_rust//rust:extensions.bzl", "rust") +rust.toolchain( + edition = "2024", + versions = ["1.91.0"], +) +use_repo(rust, "rust_toolchains") +register_toolchains("@rust_toolchains//:all") + +# Crate universe for firewood Rust dependencies +crate = use_extension("@rules_rust//crate_universe:extensions.bzl", "crate") +crate.from_cargo( + name = "firewood_crates", + cargo_lockfile = "//firewood:Cargo.lock", + manifests = [ + "//firewood:Cargo.toml", + "//firewood/ffi:Cargo.toml", + "//firewood/firewood:Cargo.toml", + "//firewood/storage:Cargo.toml", + "//firewood/firewood-macros:Cargo.toml", + "//firewood/triehash:Cargo.toml", + ], +) + +# Add extra crates needed for ethhash feature that aren't auto-detected +crate.spec( + package = "bytes", + version = "1.11.0", +) +use_repo(crate, "firewood_crates") + +# Go SDK registration +# Uses same SHA256 checksums as nix/go/default.nix for identical binaries +go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") +go_sdk.download( + name = "go_sdk", + sdks = { + # SHA256s from nix/go/default.nix lines 24-29 + "linux_amd64": ("go1.24.9.linux-amd64.tar.gz", "5b7899591c2dd6e9da1809fde4a2fad842c45d3f6b9deb235ba82216e31e34a6"), + "linux_arm64": ("go1.24.9.linux-arm64.tar.gz", "9aa1243d51d41e2f93e895c89c0a2daf7166768c4a4c3ac79db81029d295a540"), + "darwin_amd64": ("go1.24.9.darwin-amd64.tar.gz", "961aa2ae2b97e428d6d8991367e7c98cb403bac54276b8259aead42a0081591c"), + "darwin_arm64": ("go1.24.9.darwin-arm64.tar.gz", "af451b40651d7fb36db1bbbd9c66ddbed28b96d7da48abea50a19f82c6e9d1d6"), + }, + version = "1.24.9", +) +use_repo(go_sdk, "go_sdk") + +# Go dependencies from go.mod +go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") +go_deps.from_file(go_mod = "//:go.mod") + +# Override libevm's secp256k1 BUILD file to include C source files for CGO +# The gazelle-generated BUILD file doesn't include the libsecp256k1 C sources +go_deps.module_override( + patch_strip = 1, + patches = ["//patches:libevm_secp256k1.patch"], + path = "github.com/ava-labs/libevm", +) + +# Disable gazelle for blst and use custom BUILD file via patch +# blst has complex CGO with assembly that gazelle cannot handle automatically +# The patch creates BUILD.bazel from /dev/null (new file) based on Prysm's blst.BUILD +go_deps.gazelle_override( + build_file_generation = "off", + path = "github.com/supranational/blst", +) +go_deps.module_override( + patch_strip = 1, + patches = ["//patches:blst_build.patch"], + path = "github.com/supranational/blst", +) + +# Use purego build tag for gnark-crypto to avoid assembly include path issues +# gnark-crypto's assembly files use cross-package #include which Bazel doesn't support +# The purego implementation is slower but avoids the complex assembly setup +go_deps.gazelle_override( + directives = [ + "gazelle:build_tags purego", + ], + path = "github.com/consensys/gnark-crypto", +) + +# Additional dependencies from graft/coreth/go.mod that aren't in the main go.mod +go_deps.module( + path = "github.com/go-cmd/cmd", + sum = "h1:6y3G+3UqPerXvPcXvj+5QNPHT02BUw7p6PsqRxLNA7Y=", + version = "v1.4.3", +) +go_deps.module( + path = "github.com/google/go-cmp", + sum = "h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=", + version = "v0.7.0", +) +use_repo( + go_deps, + "com_connectrpc_connect", + "com_connectrpc_grpcreflect", + "com_github_antithesishq_antithesis_sdk_go", + "com_github_ava_labs_avalanchego_graft_coreth", + "com_github_ava_labs_libevm", + "com_github_ava_labs_simplex", + "com_github_ava_labs_subnet_evm", + "com_github_btcsuite_btcd_btcutil", + "com_github_cespare_xxhash_v2", + "com_github_cockroachdb_pebble", + "com_github_compose_spec_compose_go", + "com_github_datadog_zstd", + "com_github_davecgh_go_spew", + "com_github_deckarep_golang_set_v2", + "com_github_decred_dcrd_dcrec_secp256k1_v4", + "com_github_go_cmd_cmd", + "com_github_google_btree", + "com_github_google_go_cmp", + "com_github_google_renameio_v2", + "com_github_google_uuid", + "com_github_gorilla_mux", + "com_github_gorilla_rpc", + "com_github_gorilla_websocket", + "com_github_grpc_ecosystem_go_grpc_prometheus", + "com_github_hashicorp_go_bexpr", + "com_github_hashicorp_golang_lru", + "com_github_holiman_billy", + "com_github_holiman_bloomfilter_v2", + "com_github_holiman_uint256", + "com_github_huin_goupnp", + "com_github_jackpal_gateway", + "com_github_jackpal_go_nat_pmp", + "com_github_leanovate_gopter", + "com_github_mattn_go_colorable", + "com_github_mattn_go_isatty", + "com_github_mitchellh_mapstructure", + "com_github_mr_tron_base58", + "com_github_nbutton23_zxcvbn_go", + "com_github_onsi_ginkgo_v2", + "com_github_pires_go_proxyproto", + "com_github_prometheus_client_golang", + "com_github_prometheus_client_model", + "com_github_prometheus_common", + "com_github_rs_cors", + "com_github_shirou_gopsutil", + "com_github_spf13_cast", + "com_github_spf13_cobra", + "com_github_spf13_pflag", + "com_github_spf13_viper", + "com_github_stephenbuttolph_canoto", + "com_github_stretchr_testify", + "com_github_supranational_blst", + "com_github_syndtr_goleveldb", + "com_github_thepudds_fzgen", + "com_github_tyler_smith_go_bip39", + "com_github_urfave_cli_v2", + "com_github_victoriametrics_fastcache", + "in_gopkg_natefinch_lumberjack_v2", + "in_gopkg_yaml_v3", + "io_k8s_api", + "io_k8s_apimachinery", + "io_k8s_client_go", + "io_k8s_utils", + "io_opentelemetry_go_otel", + "io_opentelemetry_go_otel_exporters_otlp_otlptrace", + "io_opentelemetry_go_otel_exporters_otlp_otlptrace_otlptracegrpc", + "io_opentelemetry_go_otel_exporters_otlp_otlptrace_otlptracehttp", + "io_opentelemetry_go_otel_sdk", + "io_opentelemetry_go_otel_trace", + "org_golang_google_genproto_googleapis_rpc", + "org_golang_google_grpc", + "org_golang_google_protobuf", + "org_golang_x_crypto", + "org_golang_x_exp", + "org_golang_x_net", + "org_golang_x_sync", + "org_golang_x_term", + "org_golang_x_time", + "org_golang_x_tools", + "org_gonum_v1_gonum", + "org_uber_go_goleak", + "org_uber_go_mock", + "org_uber_go_zap", +) diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock new file mode 100644 index 000000000000..63c375ed96f5 --- /dev/null +++ b/MODULE.bazel.lock @@ -0,0 +1,10863 @@ +{ + "lockFileVersion": 13, + "registryFileHashes": { + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da", + "https://bcr.bazel.build/modules/apple_support/1.24.1/MODULE.bazel": "f46e8ddad60aef170ee92b2f3d00ef66c147ceafea68b6877cb45bd91737f5f8", + "https://bcr.bazel.build/modules/apple_support/1.24.1/source.json": "cf725267cbacc5f028ef13bb77e7f2c2e0066923a4dab1025e4a0511b1ed258a", + "https://bcr.bazel.build/modules/apple_support/1.5.0/MODULE.bazel": "50341a62efbc483e8a2a6aec30994a58749bd7b885e18dd96aa8c33031e558ef", + "https://bcr.bazel.build/modules/bazel_features/1.1.0/MODULE.bazel": "cfd42ff3b815a5f39554d97182657f8c4b9719568eb7fded2b9135f084bf760b", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65", + "https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d", + "https://bcr.bazel.build/modules/bazel_features/1.32.0/MODULE.bazel": "095d67022a58cb20f7e20e1aefecfa65257a222c18a938e2914fd257b5f1ccdc", + "https://bcr.bazel.build/modules/bazel_features/1.32.0/source.json": "2546c766986a6541f0bacd3e8542a1f621e2b14a80ea9e88c6f89f7eedf64ae1", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb", + "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", + "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/gazelle/0.32.0/MODULE.bazel": "b499f58a5d0d3537f3cf5b76d8ada18242f64ec474d8391247438bf04f58c7b8", + "https://bcr.bazel.build/modules/gazelle/0.33.0/MODULE.bazel": "a13a0f279b462b784fb8dd52a4074526c4a2afe70e114c7d09066097a46b3350", + "https://bcr.bazel.build/modules/gazelle/0.34.0/MODULE.bazel": "abdd8ce4d70978933209db92e436deb3a8b737859e9354fb5fd11fb5c2004c8a", + "https://bcr.bazel.build/modules/gazelle/0.36.0/MODULE.bazel": "e375d5d6e9a6ca59b0cb38b0540bc9a05b6aa926d322f2de268ad267a2ee74c0", + "https://bcr.bazel.build/modules/gazelle/0.47.0/MODULE.bazel": "b61bb007c4efad134aa30ee7f4a8e2a39b22aa5685f005edaa022fbd1de43ebc", + "https://bcr.bazel.build/modules/gazelle/0.47.0/source.json": "aeb2e5df14b7fb298625d75d08b9c65bdb0b56014c5eb89da9e5dd0572280ae6", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/package_metadata/0.0.5/MODULE.bazel": "ef4f9439e3270fdd6b9fd4dbc3d2f29d13888e44c529a1b243f7a31dfbc2e8e4", + "https://bcr.bazel.build/modules/package_metadata/0.0.5/source.json": "2326db2f6592578177751c3e1f74786b79382cd6008834c9d01ec865b9126a85", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", + "https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc", + "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", + "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", + "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2.bcr.1/MODULE.bazel": "52f4126f63a2f0bbf36b99c2a87648f08467a4eaf92ba726bc7d6a500bbf770c", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2.bcr.1/source.json": "cfbee3381201f20e35c304041b4abb3b793e66c9b1829b5478d033ad4a5e3aef", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573", + "https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8", + "https://bcr.bazel.build/modules/rules_cc/0.2.4/MODULE.bazel": "1ff1223dfd24f3ecf8f028446d4a27608aa43c3f41e346d22838a4223980b8cc", + "https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642", + "https://bcr.bazel.build/modules/rules_cc/0.2.8/source.json": "85087982aca15f31307bd52698316b28faa31bd2c3095a41f456afec0131344c", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", + "https://bcr.bazel.build/modules/rules_go/0.41.0/MODULE.bazel": "55861d8e8bb0e62cbd2896f60ff303f62ffcb0eddb74ecb0e5c0cbe36fc292c8", + "https://bcr.bazel.build/modules/rules_go/0.42.0/MODULE.bazel": "8cfa875b9aa8c6fce2b2e5925e73c1388173ea3c32a0db4d2b4804b453c14270", + "https://bcr.bazel.build/modules/rules_go/0.46.0/MODULE.bazel": "3477df8bdcc49e698b9d25f734c4f3a9f5931ff34ee48a2c662be168f5f2d3fd", + "https://bcr.bazel.build/modules/rules_go/0.53.0/MODULE.bazel": "a4ed760d3ac0dbc0d7b967631a9a3fd9100d28f7d9fcf214b4df87d4bfff5f9a", + "https://bcr.bazel.build/modules/rules_go/0.59.0/MODULE.bazel": "b7e43e7414a3139a7547d1b4909b29085fbe5182b6c58cbe1ed4c6272815aeae", + "https://bcr.bazel.build/modules/rules_go/0.59.0/source.json": "1df17bb7865cfc029492c30163cee891d0dd8658ea0d5bfdf252c4b6db5c1ef6", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.12.2/source.json": "b0890f9cda8ff1b8e691a3ac6037b5c14b7fd4134765a3946b89f31ea02e5884", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/7.6.5/MODULE.bazel": "481164be5e02e4cab6e77a36927683263be56b7e36fef918b458d7a8a1ebadb1", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/6.0.0/MODULE.bazel": "b531d7f09f58dce456cd61b4579ce8c86b38544da75184eadaf0a7cb7966453f", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.22.1/MODULE.bazel": "26114f0c0b5e93018c0c066d6673f1a2c3737c7e90af95eff30cfee38d0bbac7", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.31.0/source.json": "a41c836d4065888eef4377f2f27b6eea0fedb9b5adb1bab1970437373fe90dc7", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_rust/0.67.0/MODULE.bazel": "87c3816c4321352dcfd9e9e26b58e84efc5b21351ae3ef8fb5d0d57bde7237f5", + "https://bcr.bazel.build/modules/rules_rust/0.67.0/source.json": "a8ef4d3be30eb98e060cad9e5875a55b603195487f76e01b619b51a1df4641cc", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b", + "https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/MODULE.bazel": "af322bc08976524477c79d1e45e241b6efbeb918c497e8840b8ab116802dda79", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.3/source.json": "2be409ac3c7601245958cd4fcdff4288be79ed23bd690b4b951f500d54ee6e7d", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" + }, + "selectedYankedVersions": {}, + "moduleExtensions": { + "@@pybind11_bazel~//:python_configure.bzl%extension": { + "general": { + "bzlTransitiveDigest": "whINYge95GgPtysKDbNHQ0ZlWYdtKybHs5y2tLF+x7Q=", + "usagesDigest": "gNvOHVcAlwgDsNXD0amkv2CC96mnaCThPQoE44y8K+w=", + "recordedFileInputs": { + "@@pybind11_bazel~//MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e" + }, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "local_config_python": { + "bzlFile": "@@pybind11_bazel~//:python_configure.bzl", + "ruleClassName": "python_configure", + "attributes": {} + }, + "pybind11": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "build_file": "@@pybind11_bazel~//:pybind11.BUILD", + "strip_prefix": "pybind11-2.11.1", + "urls": [ + "https://github.com/pybind/pybind11/archive/v2.11.1.zip" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "pybind11_bazel~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_fuzzing~//fuzzing/private:extensions.bzl%non_module_dependencies": { + "general": { + "bzlTransitiveDigest": "hVgJRQ3Er45/UUAgNn1Yp2Khcp/Y8WyafA2kXIYmQ5M=", + "usagesDigest": "YnIrdgwnf3iCLfChsltBdZ7yOJh706lpa2vww/i2pDI=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "platforms": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "urls": [ + "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz", + "https://github.com/bazelbuild/platforms/releases/download/0.0.8/platforms-0.0.8.tar.gz" + ], + "sha256": "8150406605389ececb6da07cbcb509d5637a3ab9a24bc69b1101531367d89d74" + } + }, + "rules_python": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "d70cd72a7a4880f0000a6346253414825c19cdd40a28289bdf67b8e6480edff8", + "strip_prefix": "rules_python-0.28.0", + "url": "https://github.com/bazelbuild/rules_python/releases/download/0.28.0/rules_python-0.28.0.tar.gz" + } + }, + "bazel_skylib": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "cd55a062e763b9349921f0f5db8c3933288dc8ba4f76dd9416aac68acee3cb94", + "urls": [ + "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz", + "https://github.com/bazelbuild/bazel-skylib/releases/download/1.5.0/bazel-skylib-1.5.0.tar.gz" + ] + } + }, + "com_google_absl": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "urls": [ + "https://github.com/abseil/abseil-cpp/archive/refs/tags/20240116.1.zip" + ], + "strip_prefix": "abseil-cpp-20240116.1", + "integrity": "sha256-7capMWOvWyoYbUaHF/b+I2U6XLMaHmky8KugWvfXYuk=" + } + }, + "rules_fuzzing_oss_fuzz": { + "bzlFile": "@@rules_fuzzing~//fuzzing/private/oss_fuzz:repository.bzl", + "ruleClassName": "oss_fuzz_repository", + "attributes": {} + }, + "honggfuzz": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "build_file": "@@rules_fuzzing~//:honggfuzz.BUILD", + "sha256": "6b18ba13bc1f36b7b950c72d80f19ea67fbadc0ac0bb297ec89ad91f2eaa423e", + "url": "https://github.com/google/honggfuzz/archive/2.5.zip", + "strip_prefix": "honggfuzz-2.5" + } + }, + "rules_fuzzing_jazzer": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_jar", + "attributes": { + "sha256": "ee6feb569d88962d59cb59e8a31eb9d007c82683f3ebc64955fd5b96f277eec2", + "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer/0.20.1/jazzer-0.20.1.jar" + } + }, + "rules_fuzzing_jazzer_api": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_jar", + "attributes": { + "sha256": "f5a60242bc408f7fa20fccf10d6c5c5ea1fcb3c6f44642fec5af88373ae7aa1b", + "url": "https://repo1.maven.org/maven2/com/code-intelligence/jazzer-api/0.20.1/jazzer-api-0.20.1.jar" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_fuzzing~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_kotlin~//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { + "general": { + "bzlTransitiveDigest": "fus14IFJ/1LGWWGKPH/U18VnJCoMjfDt1ckahqCnM0A=", + "usagesDigest": "aJF6fLy82rR95Ff5CZPAqxNoFgOMLMN5ImfBS0nhnkg=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "com_github_jetbrains_kotlin_git": { + "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:compiler.bzl", + "ruleClassName": "kotlin_compiler_git_repository", + "attributes": { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" + ], + "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" + } + }, + "com_github_jetbrains_kotlin": { + "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:compiler.bzl", + "ruleClassName": "kotlin_capabilities_repository", + "attributes": { + "git_repository_name": "com_github_jetbrains_kotlin_git", + "compiler_version": "1.9.23" + } + }, + "com_github_google_ksp": { + "bzlFile": "@@rules_kotlin~//src/main/starlark/core/repositories:ksp.bzl", + "ruleClassName": "ksp_compiler_plugin_repository", + "attributes": { + "urls": [ + "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" + ], + "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", + "strip_version": "1.9.23-1.0.20" + } + }, + "com_github_pinterest_ktlint": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_file", + "attributes": { + "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", + "urls": [ + "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" + ], + "executable": true + } + }, + "rules_android": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + "strip_prefix": "rules_android-0.1.1", + "urls": [ + "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" + ] + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_kotlin~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_python~//python/extensions:pip.bzl%pip": { + "os:linux,arch:aarch64": { + "bzlTransitiveDigest": "KMo99TwNLOdfK/7ueUAPKftzh7swgLQOAvGS8weGD00=", + "usagesDigest": "KebG+ouEJqkTn3X39Yws2LuZ61wmGGuqEyVESsFSAEc=", + "recordedFileInputs": { + "@@rules_fuzzing~//fuzzing/requirements.txt": "ab04664be026b632a0d2a2446c4f65982b7654f5b6851d2f9d399a19b7242a5b", + "@@protobuf~//python/requirements.txt": "983be60d3cec4b319dcab6d48aeb3f5b2f7c3350f26b3a9e97486c37967c73c5" + }, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "pip_deps_38__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "pip_deps_38_", + "groups": {} + } + }, + "pip_deps_38_numpy": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "numpy<=1.26.1", + "repo": "pip_deps_38", + "repo_prefix": "pip_deps_38_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_8_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_38_setuptools": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "setuptools<=70.3.0", + "repo": "pip_deps_38", + "repo_prefix": "pip_deps_38_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_8_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_39__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "pip_deps_39_", + "groups": {} + } + }, + "pip_deps_39_numpy": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "numpy<=1.26.1", + "repo": "pip_deps_39", + "repo_prefix": "pip_deps_39_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_9_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_39_setuptools": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "setuptools<=70.3.0", + "repo": "pip_deps_39", + "repo_prefix": "pip_deps_39_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_9_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_310__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "pip_deps_310_", + "groups": {} + } + }, + "pip_deps_310_numpy": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "numpy<=1.26.1", + "repo": "pip_deps_310", + "repo_prefix": "pip_deps_310_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_10_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_310_setuptools": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "setuptools<=70.3.0", + "repo": "pip_deps_310", + "repo_prefix": "pip_deps_310_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_10_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_311__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "pip_deps_311_", + "groups": {} + } + }, + "pip_deps_311_numpy": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "numpy<=1.26.1", + "repo": "pip_deps_311", + "repo_prefix": "pip_deps_311_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_311_setuptools": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "setuptools<=70.3.0", + "repo": "pip_deps_311", + "repo_prefix": "pip_deps_311_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_312__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "pip_deps_312_", + "groups": {} + } + }, + "pip_deps_312_numpy": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "numpy<=1.26.1", + "repo": "pip_deps_312", + "repo_prefix": "pip_deps_312_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_12_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps_312_setuptools": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "setuptools<=70.3.0", + "repo": "pip_deps_312", + "repo_prefix": "pip_deps_312_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_12_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_38__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "rules_fuzzing_py_deps_38_", + "groups": {} + } + }, + "rules_fuzzing_py_deps_38_absl_py": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3", + "repo": "rules_fuzzing_py_deps_38", + "repo_prefix": "rules_fuzzing_py_deps_38_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_8_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_38_six": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + "repo": "rules_fuzzing_py_deps_38", + "repo_prefix": "rules_fuzzing_py_deps_38_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_8_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_39__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "rules_fuzzing_py_deps_39_", + "groups": {} + } + }, + "rules_fuzzing_py_deps_39_absl_py": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3", + "repo": "rules_fuzzing_py_deps_39", + "repo_prefix": "rules_fuzzing_py_deps_39_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_9_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_39_six": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + "repo": "rules_fuzzing_py_deps_39", + "repo_prefix": "rules_fuzzing_py_deps_39_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_9_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_310__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "rules_fuzzing_py_deps_310_", + "groups": {} + } + }, + "rules_fuzzing_py_deps_310_absl_py": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3", + "repo": "rules_fuzzing_py_deps_310", + "repo_prefix": "rules_fuzzing_py_deps_310_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_10_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_310_six": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + "repo": "rules_fuzzing_py_deps_310", + "repo_prefix": "rules_fuzzing_py_deps_310_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_10_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_311__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "rules_fuzzing_py_deps_311_", + "groups": {} + } + }, + "rules_fuzzing_py_deps_311_absl_py": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3", + "repo": "rules_fuzzing_py_deps_311", + "repo_prefix": "rules_fuzzing_py_deps_311_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_311_six": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + "repo": "rules_fuzzing_py_deps_311", + "repo_prefix": "rules_fuzzing_py_deps_311_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_11_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_312__groups": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "group_library", + "attributes": { + "repo_prefix": "rules_fuzzing_py_deps_312_", + "groups": {} + } + }, + "rules_fuzzing_py_deps_312_absl_py": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "absl-py==2.0.0 --hash=sha256:9a28abb62774ae4e8edbe2dd4c49ffcd45a6a848952a5eccc6a49f3f0fc1e2f3", + "repo": "rules_fuzzing_py_deps_312", + "repo_prefix": "rules_fuzzing_py_deps_312_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_12_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "rules_fuzzing_py_deps_312_six": { + "bzlFile": "@@rules_python~//python/pip_install:pip_repository.bzl", + "ruleClassName": "whl_library", + "attributes": { + "requirement": "six==1.16.0 --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", + "repo": "rules_fuzzing_py_deps_312", + "repo_prefix": "rules_fuzzing_py_deps_312_", + "whl_patches": {}, + "experimental_target_platforms": [], + "python_interpreter": "", + "python_interpreter_target": "@@rules_python~~python~python_3_12_host//:python", + "quiet": true, + "timeout": 600, + "isolated": true, + "extra_pip_args": [ + "--require-hashes" + ], + "download_only": false, + "pip_data_exclude": [], + "enable_implicit_namespace_pkgs": false, + "environment": {}, + "envsubst": [], + "group_name": "", + "group_deps": [] + } + }, + "pip_deps": { + "bzlFile": "@@rules_python~//python/private/bzlmod:pip_repository.bzl", + "ruleClassName": "pip_repository", + "attributes": { + "repo_name": "pip_deps", + "whl_map": { + "numpy": [ + "3.8", + "3.9", + "3.10", + "3.11", + "3.12" + ], + "setuptools": [ + "3.8", + "3.9", + "3.10", + "3.11", + "3.12" + ] + }, + "default_version": "3.11" + } + }, + "rules_fuzzing_py_deps": { + "bzlFile": "@@rules_python~//python/private/bzlmod:pip_repository.bzl", + "ruleClassName": "pip_repository", + "attributes": { + "repo_name": "rules_fuzzing_py_deps", + "whl_map": { + "absl_py": [ + "3.8", + "3.9", + "3.10", + "3.11", + "3.12" + ], + "six": [ + "3.8", + "3.9", + "3.10", + "3.11", + "3.12" + ] + }, + "default_version": "3.11" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "bazel_features~", + "bazel_features_globals", + "bazel_features~~version_extension~bazel_features_globals" + ], + [ + "bazel_features~", + "bazel_features_version", + "bazel_features~~version_extension~bazel_features_version" + ], + [ + "rules_python~", + "bazel_features", + "bazel_features~" + ], + [ + "rules_python~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "rules_python~", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_python~", + "pypi__build", + "rules_python~~internal_deps~pypi__build" + ], + [ + "rules_python~", + "pypi__click", + "rules_python~~internal_deps~pypi__click" + ], + [ + "rules_python~", + "pypi__colorama", + "rules_python~~internal_deps~pypi__colorama" + ], + [ + "rules_python~", + "pypi__importlib_metadata", + "rules_python~~internal_deps~pypi__importlib_metadata" + ], + [ + "rules_python~", + "pypi__installer", + "rules_python~~internal_deps~pypi__installer" + ], + [ + "rules_python~", + "pypi__more_itertools", + "rules_python~~internal_deps~pypi__more_itertools" + ], + [ + "rules_python~", + "pypi__packaging", + "rules_python~~internal_deps~pypi__packaging" + ], + [ + "rules_python~", + "pypi__pep517", + "rules_python~~internal_deps~pypi__pep517" + ], + [ + "rules_python~", + "pypi__pip", + "rules_python~~internal_deps~pypi__pip" + ], + [ + "rules_python~", + "pypi__pip_tools", + "rules_python~~internal_deps~pypi__pip_tools" + ], + [ + "rules_python~", + "pypi__pyproject_hooks", + "rules_python~~internal_deps~pypi__pyproject_hooks" + ], + [ + "rules_python~", + "pypi__setuptools", + "rules_python~~internal_deps~pypi__setuptools" + ], + [ + "rules_python~", + "pypi__tomli", + "rules_python~~internal_deps~pypi__tomli" + ], + [ + "rules_python~", + "pypi__wheel", + "rules_python~~internal_deps~pypi__wheel" + ], + [ + "rules_python~", + "pypi__zipp", + "rules_python~~internal_deps~pypi__zipp" + ], + [ + "rules_python~", + "pythons_hub", + "rules_python~~python~pythons_hub" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_10_aarch64-unknown-linux-gnu", + "rules_python~~python~python_3_10_aarch64-unknown-linux-gnu" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_10_host", + "rules_python~~python~python_3_10_host" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_11_aarch64-unknown-linux-gnu", + "rules_python~~python~python_3_11_aarch64-unknown-linux-gnu" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_11_host", + "rules_python~~python~python_3_11_host" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_12_aarch64-unknown-linux-gnu", + "rules_python~~python~python_3_12_aarch64-unknown-linux-gnu" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_12_host", + "rules_python~~python~python_3_12_host" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_8_aarch64-unknown-linux-gnu", + "rules_python~~python~python_3_8_aarch64-unknown-linux-gnu" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_8_host", + "rules_python~~python~python_3_8_host" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_9_aarch64-unknown-linux-gnu", + "rules_python~~python~python_3_9_aarch64-unknown-linux-gnu" + ], + [ + "rules_python~~python~pythons_hub", + "python_3_9_host", + "rules_python~~python~python_3_9_host" + ] + ] + } + }, + "@@rules_python~//python/extensions:python.bzl%python": { + "general": { + "bzlTransitiveDigest": "8vDKUdCc6qEk2/YsFiPsFO1Jqgl+XPFRklapOxMAbE8=", + "usagesDigest": "dhjp1hteIlxSdhYDivRRdp1JyPeEip+5RuKlqD4X27w=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": { + "RULES_PYTHON_BZLMOD_DEBUG": null + }, + "generatedRepoSpecs": { + "python_3_8_aarch64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "1825b1f7220bc93ff143f2e70b5c6a79c6469e0eeb40824e07a7277f59aabfda", + "patches": [], + "platform": "aarch64-apple-darwin", + "python_version": "3.8.18", + "release_filename": "20231002/cpython-3.8.18+20231002-aarch64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.8.18+20231002-aarch64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_8_aarch64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "236a300f386ead02ca98dbddbc026ff4ef4de6701a394106e291ff8b75445ee1", + "patches": [], + "platform": "aarch64-unknown-linux-gnu", + "python_version": "3.8.18", + "release_filename": "20231002/cpython-3.8.18+20231002-aarch64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.8.18+20231002-aarch64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_8_x86_64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "fcf04532e644644213977242cd724fe5e84c0a5ac92ae038e07f1b01b474fca3", + "patches": [], + "platform": "x86_64-apple-darwin", + "python_version": "3.8.18", + "release_filename": "20231002/cpython-3.8.18+20231002-x86_64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.8.18+20231002-x86_64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_8_x86_64-pc-windows-msvc": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "a9d203e78caed94de368d154e841610cef6f6b484738573f4ae9059d37e898a5", + "patches": [], + "platform": "x86_64-pc-windows-msvc", + "python_version": "3.8.18", + "release_filename": "20231002/cpython-3.8.18+20231002-x86_64-pc-windows-msvc-shared-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.8.18+20231002-x86_64-pc-windows-msvc-shared-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_8_x86_64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "1e8a3babd1500111359b0f5675d770984bcbcb2cc8890b117394f0ed342fb9ec", + "patches": [], + "platform": "x86_64-unknown-linux-gnu", + "python_version": "3.8.18", + "release_filename": "20231002/cpython-3.8.18+20231002-x86_64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.8.18+20231002-x86_64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_8_host": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "host_toolchain", + "attributes": { + "python_version": "3.8.18", + "user_repository_name": "python_3_8", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_8": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "toolchain_aliases", + "attributes": { + "python_version": "3.8.18", + "user_repository_name": "python_3_8", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_9_aarch64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "fdc4054837e37b69798c2ef796222a480bc1f80e8ad3a01a95d0168d8282a007", + "patches": [], + "platform": "aarch64-apple-darwin", + "python_version": "3.9.18", + "release_filename": "20231002/cpython-3.9.18+20231002-aarch64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.9.18+20231002-aarch64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_9_aarch64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "1e0a3e8ce8e58901a259748c0ab640d2b8294713782d14229e882c6898b2fb36", + "patches": [], + "platform": "aarch64-unknown-linux-gnu", + "python_version": "3.9.18", + "release_filename": "20231002/cpython-3.9.18+20231002-aarch64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.9.18+20231002-aarch64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_9_ppc64le-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "101c38b22fb2f5a0945156da4259c8e9efa0c08de9d7f59afa51e7ce6e22a1cc", + "patches": [], + "platform": "ppc64le-unknown-linux-gnu", + "python_version": "3.9.18", + "release_filename": "20231002/cpython-3.9.18+20231002-ppc64le-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.9.18+20231002-ppc64le-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_9_s390x-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "eee31e55ffbc1f460d7b17f05dd89e45a2636f374a6f8dc29ea13d0497f7f586", + "patches": [], + "platform": "s390x-unknown-linux-gnu", + "python_version": "3.9.18", + "release_filename": "20231002/cpython-3.9.18+20231002-s390x-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.9.18+20231002-s390x-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_9_x86_64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "82231cb77d4a5c8081a1a1d5b8ae440abe6993514eb77a926c826e9a69a94fb1", + "patches": [], + "platform": "x86_64-apple-darwin", + "python_version": "3.9.18", + "release_filename": "20231002/cpython-3.9.18+20231002-x86_64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.9.18+20231002-x86_64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_9_x86_64-pc-windows-msvc": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "02ea7bb64524886bd2b05d6b6be4401035e4ba4319146f274f0bcd992822cd75", + "patches": [], + "platform": "x86_64-pc-windows-msvc", + "python_version": "3.9.18", + "release_filename": "20231002/cpython-3.9.18+20231002-x86_64-pc-windows-msvc-shared-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.9.18+20231002-x86_64-pc-windows-msvc-shared-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_9_x86_64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "f3ff38b1ccae7dcebd8bbf2e533c9a984fac881de0ffd1636fbb61842bd924de", + "patches": [], + "platform": "x86_64-unknown-linux-gnu", + "python_version": "3.9.18", + "release_filename": "20231002/cpython-3.9.18+20231002-x86_64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.9.18+20231002-x86_64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_9_host": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "host_toolchain", + "attributes": { + "python_version": "3.9.18", + "user_repository_name": "python_3_9", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_9": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "toolchain_aliases", + "attributes": { + "python_version": "3.9.18", + "user_repository_name": "python_3_9", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_10_aarch64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "fd027b1dedf1ea034cdaa272e91771bdf75ddef4c8653b05d224a0645aa2ca3c", + "patches": [], + "platform": "aarch64-apple-darwin", + "python_version": "3.10.13", + "release_filename": "20231002/cpython-3.10.13+20231002-aarch64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.10.13+20231002-aarch64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_10_aarch64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "8675915ff454ed2f1597e27794bc7df44f5933c26b94aa06af510fe91b58bb97", + "patches": [], + "platform": "aarch64-unknown-linux-gnu", + "python_version": "3.10.13", + "release_filename": "20231002/cpython-3.10.13+20231002-aarch64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.10.13+20231002-aarch64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_10_ppc64le-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "f3f9c43eec1a0c3f72845d0b705da17a336d3906b7df212d2640b8f47e8ff375", + "patches": [], + "platform": "ppc64le-unknown-linux-gnu", + "python_version": "3.10.13", + "release_filename": "20231002/cpython-3.10.13+20231002-ppc64le-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.10.13+20231002-ppc64le-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_10_s390x-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "859f6cfe9aedb6e8858892fdc124037e83ab05f28d42a7acd314c6a16d6bd66c", + "patches": [], + "platform": "s390x-unknown-linux-gnu", + "python_version": "3.10.13", + "release_filename": "20231002/cpython-3.10.13+20231002-s390x-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.10.13+20231002-s390x-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_10_x86_64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "be0b19b6af1f7d8c667e5abef5505ad06cf72e5a11bb5844970c395a7e5b1275", + "patches": [], + "platform": "x86_64-apple-darwin", + "python_version": "3.10.13", + "release_filename": "20231002/cpython-3.10.13+20231002-x86_64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.10.13+20231002-x86_64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_10_x86_64-pc-windows-msvc": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "b8d930ce0d04bda83037ad3653d7450f8907c88e24bb8255a29b8dab8930d6f1", + "patches": [], + "platform": "x86_64-pc-windows-msvc", + "python_version": "3.10.13", + "release_filename": "20231002/cpython-3.10.13+20231002-x86_64-pc-windows-msvc-shared-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.10.13+20231002-x86_64-pc-windows-msvc-shared-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_10_x86_64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "5d0429c67c992da19ba3eb58b3acd0b35ec5e915b8cae9a4aa8ca565c423847a", + "patches": [], + "platform": "x86_64-unknown-linux-gnu", + "python_version": "3.10.13", + "release_filename": "20231002/cpython-3.10.13+20231002-x86_64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20231002/cpython-3.10.13+20231002-x86_64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_10_host": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "host_toolchain", + "attributes": { + "python_version": "3.10.13", + "user_repository_name": "python_3_10", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_10": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "toolchain_aliases", + "attributes": { + "python_version": "3.10.13", + "user_repository_name": "python_3_10", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_11_aarch64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "b042c966920cf8465385ca3522986b12d745151a72c060991088977ca36d3883", + "patches": [], + "platform": "aarch64-apple-darwin", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-aarch64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-aarch64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_aarch64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "b102eaf865eb715aa98a8a2ef19037b6cc3ae7dfd4a632802650f29de635aa13", + "patches": [], + "platform": "aarch64-unknown-linux-gnu", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-aarch64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-aarch64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_ppc64le-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "b44e1b74afe75c7b19143413632c4386708ae229117f8f950c2094e9681d34c7", + "patches": [], + "platform": "ppc64le-unknown-linux-gnu", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_s390x-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "49520e3ff494708020f306e30b0964f079170be83e956be4504f850557378a22", + "patches": [], + "platform": "s390x-unknown-linux-gnu", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-s390x-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-s390x-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_x86_64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "a0e615eef1fafdc742da0008425a9030b7ea68a4ae4e73ac557ef27b112836d4", + "patches": [], + "platform": "x86_64-apple-darwin", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-x86_64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-x86_64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_x86_64-pc-windows-msvc": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "67077e6fa918e4f4fd60ba169820b00be7c390c497bf9bc9cab2c255ea8e6f3e", + "patches": [], + "platform": "x86_64-pc-windows-msvc", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_x86_64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "4a51ce60007a6facf64e5495f4cf322e311ba9f39a8cd3f3e4c026eae488e140", + "patches": [], + "platform": "x86_64-unknown-linux-gnu", + "python_version": "3.11.7", + "release_filename": "20240107/cpython-3.11.7+20240107-x86_64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.11.7+20240107-x86_64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_11_host": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "host_toolchain", + "attributes": { + "python_version": "3.11.7", + "user_repository_name": "python_3_11", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_11": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "toolchain_aliases", + "attributes": { + "python_version": "3.11.7", + "user_repository_name": "python_3_11", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_12_aarch64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "f93f8375ca6ac0a35d58ff007043cbd3a88d9609113f1cb59cf7c8d215f064af", + "patches": [], + "platform": "aarch64-apple-darwin", + "python_version": "3.12.1", + "release_filename": "20240107/cpython-3.12.1+20240107-aarch64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1+20240107-aarch64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_12_aarch64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "236533ef20e665007a111c2f36efb59c87ae195ad7dca223b6dc03fb07064f0b", + "patches": [], + "platform": "aarch64-unknown-linux-gnu", + "python_version": "3.12.1", + "release_filename": "20240107/cpython-3.12.1+20240107-aarch64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1+20240107-aarch64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_12_ppc64le-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "78051f0d1411ee62bc2af5edfccf6e8400ac4ef82887a2affc19a7ace6a05267", + "patches": [], + "platform": "ppc64le-unknown-linux-gnu", + "python_version": "3.12.1", + "release_filename": "20240107/cpython-3.12.1+20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1+20240107-ppc64le-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_12_s390x-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "60631211c701f8d2c56e5dd7b154e68868128a019b9db1d53a264f56c0d4aee2", + "patches": [], + "platform": "s390x-unknown-linux-gnu", + "python_version": "3.12.1", + "release_filename": "20240107/cpython-3.12.1+20240107-s390x-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1+20240107-s390x-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_12_x86_64-apple-darwin": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "eca96158c1568dedd9a0b3425375637a83764d1fa74446438293089a8bfac1f8", + "patches": [], + "platform": "x86_64-apple-darwin", + "python_version": "3.12.1", + "release_filename": "20240107/cpython-3.12.1+20240107-x86_64-apple-darwin-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1+20240107-x86_64-apple-darwin-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_12_x86_64-pc-windows-msvc": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "fd5a9e0f41959d0341246d3643f2b8794f638adc0cec8dd5e1b6465198eae08a", + "patches": [], + "platform": "x86_64-pc-windows-msvc", + "python_version": "3.12.1", + "release_filename": "20240107/cpython-3.12.1+20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1+20240107-x86_64-pc-windows-msvc-shared-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_12_x86_64-unknown-linux-gnu": { + "bzlFile": "@@rules_python~//python:repositories.bzl", + "ruleClassName": "python_repository", + "attributes": { + "sha256": "74e330b8212ca22fd4d9a2003b9eec14892155566738febc8e5e572f267b9472", + "patches": [], + "platform": "x86_64-unknown-linux-gnu", + "python_version": "3.12.1", + "release_filename": "20240107/cpython-3.12.1+20240107-x86_64-unknown-linux-gnu-install_only.tar.gz", + "urls": [ + "https://github.com/indygreg/python-build-standalone/releases/download/20240107/cpython-3.12.1+20240107-x86_64-unknown-linux-gnu-install_only.tar.gz" + ], + "distutils_content": "", + "strip_prefix": "python", + "coverage_tool": "", + "ignore_root_user_error": false + } + }, + "python_3_12_host": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "host_toolchain", + "attributes": { + "python_version": "3.12.1", + "user_repository_name": "python_3_12", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "python_3_12": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "toolchain_aliases", + "attributes": { + "python_version": "3.12.1", + "user_repository_name": "python_3_12", + "platforms": [ + "aarch64-apple-darwin", + "aarch64-unknown-linux-gnu", + "ppc64le-unknown-linux-gnu", + "s390x-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-pc-windows-msvc", + "x86_64-unknown-linux-gnu" + ] + } + }, + "pythons_hub": { + "bzlFile": "@@rules_python~//python/private/bzlmod:pythons_hub.bzl", + "ruleClassName": "hub_repo", + "attributes": { + "default_python_version": "3.11", + "toolchain_prefixes": [ + "_0000_python_3_8_", + "_0001_python_3_9_", + "_0002_python_3_10_", + "_0003_python_3_12_", + "_0004_python_3_11_" + ], + "toolchain_python_versions": [ + "3.8", + "3.9", + "3.10", + "3.12", + "3.11" + ], + "toolchain_set_python_version_constraints": [ + "True", + "True", + "True", + "True", + "False" + ], + "toolchain_user_repository_names": [ + "python_3_8", + "python_3_9", + "python_3_10", + "python_3_12", + "python_3_11" + ] + } + }, + "python_versions": { + "bzlFile": "@@rules_python~//python/private:toolchains_repo.bzl", + "ruleClassName": "multi_toolchain_aliases", + "attributes": { + "python_versions": { + "3.8": "python_3_8", + "3.9": "python_3_9", + "3.10": "python_3_10", + "3.11": "python_3_11", + "3.12": "python_3_12" + } + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_python~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "rules_python~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_python~//python/private/bzlmod:internal_deps.bzl%internal_deps": { + "general": { + "bzlTransitiveDigest": "7yogJIhmw7i9Wq/n9sQB8N0F84220dJbw64SjOwrmQk=", + "usagesDigest": "r7vtlnQfWxEwrL+QFXux06yzeWEkq/hrcwAssoCoSLY=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "rules_python_internal": { + "bzlFile": "@@rules_python~//python/private:internal_config_repo.bzl", + "ruleClassName": "internal_config_repo", + "attributes": {} + }, + "pypi__build": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/58/91/17b00d5fac63d3dca605f1b8269ba3c65e98059e1fd99d00283e42a454f0/build-0.10.0-py3-none-any.whl", + "sha256": "af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__click": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl", + "sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__colorama": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", + "sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__importlib_metadata": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/cc/37/db7ba97e676af155f5fcb1a35466f446eadc9104e25b83366e8088c9c926/importlib_metadata-6.8.0-py3-none-any.whl", + "sha256": "3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__installer": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl", + "sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__more_itertools": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/5a/cb/6dce742ea14e47d6f565589e859ad225f2a5de576d7696e0623b784e226b/more_itertools-10.1.0-py3-none-any.whl", + "sha256": "64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__packaging": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/ab/c3/57f0601a2d4fe15de7a553c00adbc901425661bf048f2a22dfc500caf121/packaging-23.1-py3-none-any.whl", + "sha256": "994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pep517": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/ee/2f/ef63e64e9429111e73d3d6cbee80591672d16f2725e648ebc52096f3d323/pep517-0.13.0-py3-none-any.whl", + "sha256": "4ba4446d80aed5b5eac6509ade100bff3e7943a8489de249654a5ae9b33ee35b", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/50/c2/e06851e8cc28dcad7c155f4753da8833ac06a5c704c109313b8d5a62968a/pip-23.2.1-py3-none-any.whl", + "sha256": "7ccf472345f20d35bdc9d1841ff5f313260c2c33fe417f48c30ac46cccabf5be", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pip_tools": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/e8/df/47e6267c6b5cdae867adbdd84b437393e6202ce4322de0a5e0b92960e1d6/pip_tools-7.3.0-py3-none-any.whl", + "sha256": "8717693288720a8c6ebd07149c93ab0be1fced0b5191df9e9decd3263e20d85e", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__pyproject_hooks": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/d5/ea/9ae603de7fbb3df820b23a70f6aff92bf8c7770043254ad8d2dc9d6bcba4/pyproject_hooks-1.0.0-py3-none-any.whl", + "sha256": "283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__setuptools": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/4f/ab/0bcfebdfc3bfa8554b2b2c97a555569c4c1ebc74ea288741ea8326c51906/setuptools-68.1.2-py3-none-any.whl", + "sha256": "3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__tomli": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl", + "sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__wheel": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/b8/8b/31273bf66016be6ad22bb7345c37ff350276cfd46e389a0c2ac5da9d9073/wheel-0.41.2-py3-none-any.whl", + "sha256": "75909db2664838d015e3d9139004ee16711748a52c8f336b52882266540215d8", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + }, + "pypi__zipp": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "url": "https://files.pythonhosted.org/packages/8c/08/d3006317aefe25ea79d3b76c9650afabaf6d63d1c8443b236e7405447503/zipp-3.16.2-py3-none-any.whl", + "sha256": "679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0", + "type": "zip", + "build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:defs.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude in /python/pip_install/tools/bazel.py\n # to avoid non-determinism following pip install's behavior.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/* *\",\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n" + } + } + }, + "recordedRepoMappingEntries": [ + [ + "rules_python~", + "bazel_tools", + "bazel_tools" + ] + ] + } + }, + "@@rules_rust~//crate_universe:extensions.bzl%crate": { + "general": { + "bzlTransitiveDigest": "1azVd6gpXQg9x3bekeu+IGdkmemcfxLY9DaTmaHAxrA=", + "usagesDigest": "L8U+lw26jVlIaJrnJfy5CBKygS6HrWBBx3Awi/9FlgI=", + "recordedFileInputs": { + "@@//firewood/ffi/Cargo.toml": "a6c8893e3a1e7c63b454b563ee1071179758175bf99339d1861c638cf21186dc", + "@@//firewood/firewood/Cargo.toml": "85ee84082a924315691f3bdee5ff915f947587c2eafa44ed311390a1ea81aa9b", + "@@//firewood/firewood-macros/Cargo.toml": "9b3bb43ec604e10a1462e9a0a2abe062f4aabe4dd15f0e86815f57d50429ce16", + "@@//firewood/Cargo.lock": "77ddbda024f564ba0990c0ecc4ef03024d9c787b98188ce5b07531e51c5afc98", + "@@//firewood/triehash/Cargo.toml": "550839ddb3ca61414681843185b47464023ede9f1d575a7cf44580e810c6a686", + "@@//firewood/storage/Cargo.toml": "98cbb8044c967c335a2e0d212fa6735fdd5a7c1c473ebd88a13b7ca106fc87cd", + "@@//firewood/Cargo.toml": "1251caa48ba8b498a932cbead1eb4f8fb6f0852d1d41dbaa955b06189370ed40", + "@@//firewood/fwdctl/Cargo.toml": "0a34f265c3d6dc767f4146e7f99019548af8329d22492f931c6bd1e784e375da", + "@@//MODULE.bazel": "8f9763b0b150604df04c7dcf3939f88368874b0c6b1b73853fdea696f692fef7", + "@@rules_rust~~rust_host_tools~rust_host_tools//rust_host_tools": "ENOENT", + "@@//firewood/benchmark/Cargo.toml": "8f6665728370082c9968311e75c1ba92f457eb5398487eb8e4749e83fe6086d9" + }, + "recordedDirentsInputs": {}, + "envVariables": { + "CARGO_BAZEL_DEBUG": null, + "CARGO_BAZEL_GENERATOR_SHA256": null, + "CARGO_BAZEL_GENERATOR_URL": null, + "CARGO_BAZEL_ISOLATED": null, + "CARGO_BAZEL_REPIN": null, + "CARGO_BAZEL_REPIN_ONLY": null, + "CARGO_BAZEL_TIMEOUT": null, + "REPIN": null + }, + "generatedRepoSpecs": { + "firewood_crates": { + "bzlFile": "@@rules_rust~//crate_universe:extensions.bzl", + "ruleClassName": "_generate_repo", + "attributes": { + "contents": { + "BUILD.bazel": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\npackage(default_visibility = [\"//visibility:public\"])\n\nexports_files(\n [\n \"cargo-bazel.json\",\n \"crates.bzl\",\n \"defs.bzl\",\n ] + glob(\n allow_empty = True,\n include = [\"*.bazel\"],\n ),\n)\n\nfilegroup(\n name = \"srcs\",\n srcs = glob(\n allow_empty = True,\n include = [\n \"*.bazel\",\n \"*.bzl\",\n ],\n ),\n)\n\n# Workspace Member Dependencies\nalias(\n name = \"anyhow-1.0.100\",\n actual = \"@firewood_crates__anyhow-1.0.100//:anyhow\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"anyhow\",\n actual = \"@firewood_crates__anyhow-1.0.100//:anyhow\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"aquamarine-0.6.0\",\n actual = \"@firewood_crates__aquamarine-0.6.0//:aquamarine\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"aquamarine\",\n actual = \"@firewood_crates__aquamarine-0.6.0//:aquamarine\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"askama-0.14.0\",\n actual = \"@firewood_crates__askama-0.14.0//:askama\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"askama\",\n actual = \"@firewood_crates__askama-0.14.0//:askama\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"assert_cmd-2.1.1\",\n actual = \"@firewood_crates__assert_cmd-2.1.1//:assert_cmd\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"assert_cmd\",\n actual = \"@firewood_crates__assert_cmd-2.1.1//:assert_cmd\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bitfield-0.19.4\",\n actual = \"@firewood_crates__bitfield-0.19.4//:bitfield\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bitfield\",\n actual = \"@firewood_crates__bitfield-0.19.4//:bitfield\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bitflags-2.10.0\",\n actual = \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bitflags\",\n actual = \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bumpalo-3.19.0\",\n actual = \"@firewood_crates__bumpalo-3.19.0//:bumpalo\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bumpalo\",\n actual = \"@firewood_crates__bumpalo-3.19.0//:bumpalo\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bytemuck-1.24.0\",\n actual = \"@firewood_crates__bytemuck-1.24.0//:bytemuck\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bytemuck\",\n actual = \"@firewood_crates__bytemuck-1.24.0//:bytemuck\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bytemuck_derive-1.10.2\",\n actual = \"@firewood_crates__bytemuck_derive-1.10.2//:bytemuck_derive\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bytemuck_derive\",\n actual = \"@firewood_crates__bytemuck_derive-1.10.2//:bytemuck_derive\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bytes-1.11.0\",\n actual = \"@firewood_crates__bytes-1.11.0//:bytes\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"bytes\",\n actual = \"@firewood_crates__bytes-1.11.0//:bytes\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"cbindgen-0.29.2\",\n actual = \"@firewood_crates__cbindgen-0.29.2//:cbindgen\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"cbindgen\",\n actual = \"@firewood_crates__cbindgen-0.29.2//:cbindgen\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"chrono-0.4.42\",\n actual = \"@firewood_crates__chrono-0.4.42//:chrono\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"chrono\",\n actual = \"@firewood_crates__chrono-0.4.42//:chrono\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"clap-4.5.52\",\n actual = \"@firewood_crates__clap-4.5.52//:clap\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"clap\",\n actual = \"@firewood_crates__clap-4.5.52//:clap\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"coarsetime-0.1.36\",\n actual = \"@firewood_crates__coarsetime-0.1.36//:coarsetime\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"coarsetime\",\n actual = \"@firewood_crates__coarsetime-0.1.36//:coarsetime\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"criterion-0.7.0\",\n actual = \"@firewood_crates__criterion-0.7.0//:criterion\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"criterion\",\n actual = \"@firewood_crates__criterion-0.7.0//:criterion\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"csv-1.4.0\",\n actual = \"@firewood_crates__csv-1.4.0//:csv\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"csv\",\n actual = \"@firewood_crates__csv-1.4.0//:csv\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"ctor-0.6.1\",\n actual = \"@firewood_crates__ctor-0.6.1//:ctor\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"ctor\",\n actual = \"@firewood_crates__ctor-0.6.1//:ctor\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"derive-where-1.6.0\",\n actual = \"@firewood_crates__derive-where-1.6.0//:derive_where\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"derive-where\",\n actual = \"@firewood_crates__derive-where-1.6.0//:derive_where\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"enum-as-inner-0.6.1\",\n actual = \"@firewood_crates__enum-as-inner-0.6.1//:enum_as_inner\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"enum-as-inner\",\n actual = \"@firewood_crates__enum-as-inner-0.6.1//:enum_as_inner\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"env_logger-0.11.8\",\n actual = \"@firewood_crates__env_logger-0.11.8//:env_logger\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"env_logger\",\n actual = \"@firewood_crates__env_logger-0.11.8//:env_logger\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"ethereum-types-0.16.0\",\n actual = \"@firewood_crates__ethereum-types-0.16.0//:ethereum_types\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"ethereum-types\",\n actual = \"@firewood_crates__ethereum-types-0.16.0//:ethereum_types\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"fastrace-0.7.14\",\n actual = \"@firewood_crates__fastrace-0.7.14//:fastrace\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"fastrace\",\n actual = \"@firewood_crates__fastrace-0.7.14//:fastrace\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"fastrace-opentelemetry-0.14.0\",\n actual = \"@firewood_crates__fastrace-opentelemetry-0.14.0//:fastrace_opentelemetry\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"fastrace-opentelemetry\",\n actual = \"@firewood_crates__fastrace-opentelemetry-0.14.0//:fastrace_opentelemetry\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"fjall-2.11.2\",\n actual = \"@firewood_crates__fjall-2.11.2//:fjall\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"fjall\",\n actual = \"@firewood_crates__fjall-2.11.2//:fjall\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"hash-db-0.16.0\",\n actual = \"@firewood_crates__hash-db-0.16.0//:hash_db\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"hash-db\",\n actual = \"@firewood_crates__hash-db-0.16.0//:hash_db\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"hex-0.4.3\",\n actual = \"@firewood_crates__hex-0.4.3//:hex\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"hex\",\n actual = \"@firewood_crates__hex-0.4.3//:hex\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"hex-literal-1.1.0\",\n actual = \"@firewood_crates__hex-literal-1.1.0//:hex_literal\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"hex-literal\",\n actual = \"@firewood_crates__hex-literal-1.1.0//:hex_literal\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"indicatif-0.18.3\",\n actual = \"@firewood_crates__indicatif-0.18.3//:indicatif\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"indicatif\",\n actual = \"@firewood_crates__indicatif-0.18.3//:indicatif\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"integer-encoding-4.1.0\",\n actual = \"@firewood_crates__integer-encoding-4.1.0//:integer_encoding\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"integer-encoding\",\n actual = \"@firewood_crates__integer-encoding-4.1.0//:integer_encoding\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"io-uring-0.7.11\",\n actual = \"@firewood_crates__io-uring-0.7.11//:io_uring\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"io-uring\",\n actual = \"@firewood_crates__io-uring-0.7.11//:io_uring\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"keccak-hasher-0.16.0\",\n actual = \"@firewood_crates__keccak-hasher-0.16.0//:keccak_hasher\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"keccak-hasher\",\n actual = \"@firewood_crates__keccak-hasher-0.16.0//:keccak_hasher\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"log-0.4.28\",\n actual = \"@firewood_crates__log-0.4.28//:log\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"log\",\n actual = \"@firewood_crates__log-0.4.28//:log\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"lru-0.16.2\",\n actual = \"@firewood_crates__lru-0.16.2//:lru\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"lru\",\n actual = \"@firewood_crates__lru-0.16.2//:lru\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"metrics-0.24.2\",\n actual = \"@firewood_crates__metrics-0.24.2//:metrics\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"metrics\",\n actual = \"@firewood_crates__metrics-0.24.2//:metrics\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"metrics-exporter-prometheus-0.17.2\",\n actual = \"@firewood_crates__metrics-exporter-prometheus-0.17.2//:metrics_exporter_prometheus\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"metrics-exporter-prometheus\",\n actual = \"@firewood_crates__metrics-exporter-prometheus-0.17.2//:metrics_exporter_prometheus\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"metrics-util-0.20.0\",\n actual = \"@firewood_crates__metrics-util-0.20.0//:metrics_util\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"metrics-util\",\n actual = \"@firewood_crates__metrics-util-0.20.0//:metrics_util\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"nonzero_ext-0.3.0\",\n actual = \"@firewood_crates__nonzero_ext-0.3.0//:nonzero_ext\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"nonzero_ext\",\n actual = \"@firewood_crates__nonzero_ext-0.3.0//:nonzero_ext\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"num-format-0.4.4\",\n actual = \"@firewood_crates__num-format-0.4.4//:num_format\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"num-format\",\n actual = \"@firewood_crates__num-format-0.4.4//:num_format\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"opentelemetry-0.31.0\",\n actual = \"@firewood_crates__opentelemetry-0.31.0//:opentelemetry\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"opentelemetry\",\n actual = \"@firewood_crates__opentelemetry-0.31.0//:opentelemetry\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"opentelemetry-otlp-0.31.0\",\n actual = \"@firewood_crates__opentelemetry-otlp-0.31.0//:opentelemetry_otlp\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"opentelemetry-otlp\",\n actual = \"@firewood_crates__opentelemetry-otlp-0.31.0//:opentelemetry_otlp\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"opentelemetry-proto-0.31.0\",\n actual = \"@firewood_crates__opentelemetry-proto-0.31.0//:opentelemetry_proto\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"opentelemetry-proto\",\n actual = \"@firewood_crates__opentelemetry-proto-0.31.0//:opentelemetry_proto\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"opentelemetry_sdk-0.31.0\",\n actual = \"@firewood_crates__opentelemetry_sdk-0.31.0//:opentelemetry_sdk\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"opentelemetry_sdk\",\n actual = \"@firewood_crates__opentelemetry_sdk-0.31.0//:opentelemetry_sdk\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"oxhttp-0.3.1\",\n actual = \"@firewood_crates__oxhttp-0.3.1//:oxhttp\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"oxhttp\",\n actual = \"@firewood_crates__oxhttp-0.3.1//:oxhttp\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"parking_lot-0.12.5\",\n actual = \"@firewood_crates__parking_lot-0.12.5//:parking_lot\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"parking_lot\",\n actual = \"@firewood_crates__parking_lot-0.12.5//:parking_lot\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"plain_hasher-0.2.3\",\n actual = \"@firewood_crates__plain_hasher-0.2.3//:plain_hasher\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"plain_hasher\",\n actual = \"@firewood_crates__plain_hasher-0.2.3//:plain_hasher\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"pprof-0.15.0\",\n actual = \"@firewood_crates__pprof-0.15.0//:pprof\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"pprof\",\n actual = \"@firewood_crates__pprof-0.15.0//:pprof\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"predicates-3.1.3\",\n actual = \"@firewood_crates__predicates-3.1.3//:predicates\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"predicates\",\n actual = \"@firewood_crates__predicates-3.1.3//:predicates\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"pretty-duration-0.1.1\",\n actual = \"@firewood_crates__pretty-duration-0.1.1//:pretty_duration\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"pretty-duration\",\n actual = \"@firewood_crates__pretty-duration-0.1.1//:pretty_duration\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"proc-macro2-1.0.103\",\n actual = \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"proc-macro2\",\n actual = \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"quote-1.0.42\",\n actual = \"@firewood_crates__quote-1.0.42//:quote\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"quote\",\n actual = \"@firewood_crates__quote-1.0.42//:quote\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"rand-0.9.2\",\n actual = \"@firewood_crates__rand-0.9.2//:rand\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"rand\",\n actual = \"@firewood_crates__rand-0.9.2//:rand\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"rand_distr-0.5.1\",\n actual = \"@firewood_crates__rand_distr-0.5.1//:rand_distr\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"rand_distr\",\n actual = \"@firewood_crates__rand_distr-0.5.1//:rand_distr\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"rayon-1.11.0\",\n actual = \"@firewood_crates__rayon-1.11.0//:rayon\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"rayon\",\n actual = \"@firewood_crates__rayon-1.11.0//:rayon\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"rlp-0.6.1\",\n actual = \"@firewood_crates__rlp-0.6.1//:rlp\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"rlp\",\n actual = \"@firewood_crates__rlp-0.6.1//:rlp\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"semver-1.0.27\",\n actual = \"@firewood_crates__semver-1.0.27//:semver\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"semver\",\n actual = \"@firewood_crates__semver-1.0.27//:semver\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"serial_test-3.2.0\",\n actual = \"@firewood_crates__serial_test-3.2.0//:serial_test\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"serial_test\",\n actual = \"@firewood_crates__serial_test-3.2.0//:serial_test\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"sha2-0.10.9\",\n actual = \"@firewood_crates__sha2-0.10.9//:sha2\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"sha2\",\n actual = \"@firewood_crates__sha2-0.10.9//:sha2\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"sha3-0.10.8\",\n actual = \"@firewood_crates__sha3-0.10.8//:sha3\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"sha3\",\n actual = \"@firewood_crates__sha3-0.10.8//:sha3\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"smallvec-1.15.1\",\n actual = \"@firewood_crates__smallvec-1.15.1//:smallvec\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"smallvec\",\n actual = \"@firewood_crates__smallvec-1.15.1//:smallvec\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"syn-2.0.110\",\n actual = \"@firewood_crates__syn-2.0.110//:syn\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"syn\",\n actual = \"@firewood_crates__syn-2.0.110//:syn\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"tempfile-3.23.0\",\n actual = \"@firewood_crates__tempfile-3.23.0//:tempfile\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"tempfile\",\n actual = \"@firewood_crates__tempfile-3.23.0//:tempfile\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"test-case-3.3.1\",\n actual = \"@firewood_crates__test-case-3.3.1//:test_case\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"test-case\",\n actual = \"@firewood_crates__test-case-3.3.1//:test_case\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"thiserror-2.0.17\",\n actual = \"@firewood_crates__thiserror-2.0.17//:thiserror\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"thiserror\",\n actual = \"@firewood_crates__thiserror-2.0.17//:thiserror\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"tikv-jemallocator-0.6.1\",\n actual = \"@firewood_crates__tikv-jemallocator-0.6.1//:tikv_jemallocator\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"tikv-jemallocator\",\n actual = \"@firewood_crates__tikv-jemallocator-0.6.1//:tikv_jemallocator\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"tiny-keccak-2.0.2\",\n actual = \"@firewood_crates__tiny-keccak-2.0.2//:tiny_keccak\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"tiny-keccak\",\n actual = \"@firewood_crates__tiny-keccak-2.0.2//:tiny_keccak\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"tokio-1.48.0\",\n actual = \"@firewood_crates__tokio-1.48.0//:tokio\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"tokio\",\n actual = \"@firewood_crates__tokio-1.48.0//:tokio\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"trie-standardmap-0.16.0\",\n actual = \"@firewood_crates__trie-standardmap-0.16.0//:trie_standardmap\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"trie-standardmap\",\n actual = \"@firewood_crates__trie-standardmap-0.16.0//:trie_standardmap\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"triomphe-0.1.15\",\n actual = \"@firewood_crates__triomphe-0.1.15//:triomphe\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"triomphe\",\n actual = \"@firewood_crates__triomphe-0.1.15//:triomphe\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"trybuild-1.0.114\",\n actual = \"@firewood_crates__trybuild-1.0.114//:trybuild\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"trybuild\",\n actual = \"@firewood_crates__trybuild-1.0.114//:trybuild\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"typed-builder-0.23.1\",\n actual = \"@firewood_crates__typed-builder-0.23.1//:typed_builder\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"typed-builder\",\n actual = \"@firewood_crates__typed-builder-0.23.1//:typed_builder\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"weak-table-0.3.2\",\n actual = \"@firewood_crates__weak-table-0.3.2//:weak_table\",\n tags = [\"manual\"],\n)\n\nalias(\n name = \"weak-table\",\n actual = \"@firewood_crates__weak-table-0.3.2//:weak_table\",\n tags = [\"manual\"],\n)\n", + "alias_rules.bzl": "\"\"\"Alias that transitions its target to `compilation_mode=opt`. Use `transition_alias=\"opt\"` to enable.\"\"\"\n\nload(\"@rules_cc//cc:defs.bzl\", \"CcInfo\")\nload(\"@rules_rust//rust:rust_common.bzl\", \"COMMON_PROVIDERS\")\n\ndef _transition_alias_impl(ctx):\n # `ctx.attr.actual` is a list of 1 item due to the transition\n providers = [ctx.attr.actual[0][provider] for provider in COMMON_PROVIDERS]\n if CcInfo in ctx.attr.actual[0]:\n providers.append(ctx.attr.actual[0][CcInfo])\n return providers\n\ndef _change_compilation_mode(compilation_mode):\n def _change_compilation_mode_impl(_settings, _attr):\n return {\n \"//command_line_option:compilation_mode\": compilation_mode,\n }\n\n return transition(\n implementation = _change_compilation_mode_impl,\n inputs = [],\n outputs = [\n \"//command_line_option:compilation_mode\",\n ],\n )\n\ndef _transition_alias_rule(compilation_mode):\n return rule(\n implementation = _transition_alias_impl,\n provides = COMMON_PROVIDERS,\n attrs = {\n \"actual\": attr.label(\n mandatory = True,\n doc = \"`rust_library()` target to transition to `compilation_mode=opt`.\",\n providers = COMMON_PROVIDERS,\n cfg = _change_compilation_mode(compilation_mode),\n ),\n \"_allowlist_function_transition\": attr.label(\n default = \"@bazel_tools//tools/allowlists/function_transition_allowlist\",\n ),\n },\n doc = \"Transitions a Rust library crate to the `compilation_mode=opt`.\",\n )\n\ntransition_alias_dbg = _transition_alias_rule(\"dbg\")\ntransition_alias_fastbuild = _transition_alias_rule(\"fastbuild\")\ntransition_alias_opt = _transition_alias_rule(\"opt\")\n", + "defs.bzl": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\"\"\"\n# `crates_repository` API\n\n- [aliases](#aliases)\n- [crate_deps](#crate_deps)\n- [all_crate_deps](#all_crate_deps)\n- [crate_repositories](#crate_repositories)\n\n\"\"\"\n\nload(\"@bazel_tools//tools/build_defs/repo:git.bzl\", \"new_git_repository\")\nload(\"@bazel_tools//tools/build_defs/repo:http.bzl\", \"http_archive\")\nload(\"@bazel_tools//tools/build_defs/repo:utils.bzl\", \"maybe\")\nload(\"@bazel_skylib//lib:selects.bzl\", \"selects\")\nload(\"@rules_rust//crate_universe/private:local_crate_mirror.bzl\", \"local_crate_mirror\")\n\n###############################################################################\n# MACROS API\n###############################################################################\n\n# An identifier that represent common dependencies (unconditional).\n_COMMON_CONDITION = \"\"\n\ndef _flatten_dependency_maps(all_dependency_maps):\n \"\"\"Flatten a list of dependency maps into one dictionary.\n\n Dependency maps have the following structure:\n\n ```python\n DEPENDENCIES_MAP = {\n # The first key in the map is a Bazel package\n # name of the workspace this file is defined in.\n \"workspace_member_package\": {\n\n # Not all dependencies are supported for all platforms.\n # the condition key is the condition required to be true\n # on the host platform.\n \"condition\": {\n\n # An alias to a crate target. # The label of the crate target the\n # Aliases are only crate names. # package name refers to.\n \"package_name\": \"@full//:label\",\n }\n }\n }\n ```\n\n Args:\n all_dependency_maps (list): A list of dicts as described above\n\n Returns:\n dict: A dictionary as described above\n \"\"\"\n dependencies = {}\n\n for workspace_deps_map in all_dependency_maps:\n for pkg_name, conditional_deps_map in workspace_deps_map.items():\n if pkg_name not in dependencies:\n non_frozen_map = dict()\n for key, values in conditional_deps_map.items():\n non_frozen_map.update({key: dict(values.items())})\n dependencies.setdefault(pkg_name, non_frozen_map)\n continue\n\n for condition, deps_map in conditional_deps_map.items():\n # If the condition has not been recorded, do so and continue\n if condition not in dependencies[pkg_name]:\n dependencies[pkg_name].setdefault(condition, dict(deps_map.items()))\n continue\n\n # Alert on any miss-matched dependencies\n inconsistent_entries = []\n for crate_name, crate_label in deps_map.items():\n existing = dependencies[pkg_name][condition].get(crate_name)\n if existing and existing != crate_label:\n inconsistent_entries.append((crate_name, existing, crate_label))\n dependencies[pkg_name][condition].update({crate_name: crate_label})\n\n return dependencies\n\ndef crate_deps(deps, package_name = None):\n \"\"\"Finds the fully qualified label of the requested crates for the package where this macro is called.\n\n Args:\n deps (list): The desired list of crate targets.\n package_name (str, optional): The package name of the set of dependencies to look up.\n Defaults to `native.package_name()`.\n\n Returns:\n list: A list of labels to generated rust targets (str)\n \"\"\"\n\n if not deps:\n return []\n\n if package_name == None:\n package_name = native.package_name()\n\n # Join both sets of dependencies\n dependencies = _flatten_dependency_maps([\n _NORMAL_DEPENDENCIES,\n _NORMAL_DEV_DEPENDENCIES,\n _PROC_MACRO_DEPENDENCIES,\n _PROC_MACRO_DEV_DEPENDENCIES,\n _BUILD_DEPENDENCIES,\n _BUILD_PROC_MACRO_DEPENDENCIES,\n ]).pop(package_name, {})\n\n # Combine all conditional packages so we can easily index over a flat list\n # TODO: Perhaps this should actually return select statements and maintain\n # the conditionals of the dependencies\n flat_deps = {}\n for deps_set in dependencies.values():\n for crate_name, crate_label in deps_set.items():\n flat_deps.update({crate_name: crate_label})\n\n missing_crates = []\n crate_targets = []\n for crate_target in deps:\n if crate_target not in flat_deps:\n missing_crates.append(crate_target)\n else:\n crate_targets.append(flat_deps[crate_target])\n\n if missing_crates:\n fail(\"Could not find crates `{}` among dependencies of `{}`. Available dependencies were `{}`\".format(\n missing_crates,\n package_name,\n dependencies,\n ))\n\n return crate_targets\n\ndef all_crate_deps(\n normal = False, \n normal_dev = False, \n proc_macro = False, \n proc_macro_dev = False,\n build = False,\n build_proc_macro = False,\n package_name = None):\n \"\"\"Finds the fully qualified label of all requested direct crate dependencies \\\n for the package where this macro is called.\n\n If no parameters are set, all normal dependencies are returned. Setting any one flag will\n otherwise impact the contents of the returned list.\n\n Args:\n normal (bool, optional): If True, normal dependencies are included in the\n output list.\n normal_dev (bool, optional): If True, normal dev dependencies will be\n included in the output list..\n proc_macro (bool, optional): If True, proc_macro dependencies are included\n in the output list.\n proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are\n included in the output list.\n build (bool, optional): If True, build dependencies are included\n in the output list.\n build_proc_macro (bool, optional): If True, build proc_macro dependencies are\n included in the output list.\n package_name (str, optional): The package name of the set of dependencies to look up.\n Defaults to `native.package_name()` when unset.\n\n Returns:\n list: A list of labels to generated rust targets (str)\n \"\"\"\n\n if package_name == None:\n package_name = native.package_name()\n\n # Determine the relevant maps to use\n all_dependency_maps = []\n if normal:\n all_dependency_maps.append(_NORMAL_DEPENDENCIES)\n if normal_dev:\n all_dependency_maps.append(_NORMAL_DEV_DEPENDENCIES)\n if proc_macro:\n all_dependency_maps.append(_PROC_MACRO_DEPENDENCIES)\n if proc_macro_dev:\n all_dependency_maps.append(_PROC_MACRO_DEV_DEPENDENCIES)\n if build:\n all_dependency_maps.append(_BUILD_DEPENDENCIES)\n if build_proc_macro:\n all_dependency_maps.append(_BUILD_PROC_MACRO_DEPENDENCIES)\n\n # Default to always using normal dependencies\n if not all_dependency_maps:\n all_dependency_maps.append(_NORMAL_DEPENDENCIES)\n\n dependencies = _flatten_dependency_maps(all_dependency_maps).pop(package_name, None)\n\n if not dependencies:\n if dependencies == None:\n fail(\"Tried to get all_crate_deps for package \" + package_name + \" but that package had no Cargo.toml file\")\n else:\n return []\n\n crate_deps = list(dependencies.pop(_COMMON_CONDITION, {}).values())\n for condition, deps in dependencies.items():\n crate_deps += selects.with_or({\n tuple(_CONDITIONS[condition]): deps.values(),\n \"//conditions:default\": [],\n })\n\n return crate_deps\n\ndef aliases(\n normal = False,\n normal_dev = False,\n proc_macro = False,\n proc_macro_dev = False,\n build = False,\n build_proc_macro = False,\n package_name = None):\n \"\"\"Produces a map of Crate alias names to their original label\n\n If no dependency kinds are specified, `normal` and `proc_macro` are used by default.\n Setting any one flag will otherwise determine the contents of the returned dict.\n\n Args:\n normal (bool, optional): If True, normal dependencies are included in the\n output list.\n normal_dev (bool, optional): If True, normal dev dependencies will be\n included in the output list..\n proc_macro (bool, optional): If True, proc_macro dependencies are included\n in the output list.\n proc_macro_dev (bool, optional): If True, dev proc_macro dependencies are\n included in the output list.\n build (bool, optional): If True, build dependencies are included\n in the output list.\n build_proc_macro (bool, optional): If True, build proc_macro dependencies are\n included in the output list.\n package_name (str, optional): The package name of the set of dependencies to look up.\n Defaults to `native.package_name()` when unset.\n\n Returns:\n dict: The aliases of all associated packages\n \"\"\"\n if package_name == None:\n package_name = native.package_name()\n\n # Determine the relevant maps to use\n all_aliases_maps = []\n if normal:\n all_aliases_maps.append(_NORMAL_ALIASES)\n if normal_dev:\n all_aliases_maps.append(_NORMAL_DEV_ALIASES)\n if proc_macro:\n all_aliases_maps.append(_PROC_MACRO_ALIASES)\n if proc_macro_dev:\n all_aliases_maps.append(_PROC_MACRO_DEV_ALIASES)\n if build:\n all_aliases_maps.append(_BUILD_ALIASES)\n if build_proc_macro:\n all_aliases_maps.append(_BUILD_PROC_MACRO_ALIASES)\n\n # Default to always using normal aliases\n if not all_aliases_maps:\n all_aliases_maps.append(_NORMAL_ALIASES)\n all_aliases_maps.append(_PROC_MACRO_ALIASES)\n\n aliases = _flatten_dependency_maps(all_aliases_maps).pop(package_name, None)\n\n if not aliases:\n return dict()\n\n common_items = aliases.pop(_COMMON_CONDITION, {}).items()\n\n # If there are only common items in the dictionary, immediately return them\n if not len(aliases.keys()) == 1:\n return dict(common_items)\n\n # Build a single select statement where each conditional has accounted for the\n # common set of aliases.\n crate_aliases = {\"//conditions:default\": dict(common_items)}\n for condition, deps in aliases.items():\n condition_triples = _CONDITIONS[condition]\n for triple in condition_triples:\n if triple in crate_aliases:\n crate_aliases[triple].update(deps)\n else:\n crate_aliases.update({triple: dict(deps.items() + common_items)})\n\n return select(crate_aliases)\n\n###############################################################################\n# WORKSPACE MEMBER DEPS AND ALIASES\n###############################################################################\n\n_NORMAL_DEPENDENCIES = {\n \"firewood\": {\n _COMMON_CONDITION: {\n \"bytes\": Label(\"@firewood_crates//:bytes-1.11.0\"),\n },\n },\n \"firewood/firewood\": {\n _COMMON_CONDITION: {\n \"bytemuck\": Label(\"@firewood_crates//:bytemuck-1.24.0\"),\n \"coarsetime\": Label(\"@firewood_crates//:coarsetime-0.1.36\"),\n \"fastrace\": Label(\"@firewood_crates//:fastrace-0.7.14\"),\n \"fjall\": Label(\"@firewood_crates//:fjall-2.11.2\"),\n \"hex\": Label(\"@firewood_crates//:hex-0.4.3\"),\n \"integer-encoding\": Label(\"@firewood_crates//:integer-encoding-4.1.0\"),\n \"metrics\": Label(\"@firewood_crates//:metrics-0.24.2\"),\n \"parking_lot\": Label(\"@firewood_crates//:parking_lot-0.12.5\"),\n \"rayon\": Label(\"@firewood_crates//:rayon-1.11.0\"),\n \"thiserror\": Label(\"@firewood_crates//:thiserror-2.0.17\"),\n \"typed-builder\": Label(\"@firewood_crates//:typed-builder-0.23.1\"),\n \"weak-table\": Label(\"@firewood_crates//:weak-table-0.3.2\"),\n },\n },\n \"firewood/benchmark\": {\n _COMMON_CONDITION: {\n \"clap\": Label(\"@firewood_crates//:clap-4.5.52\"),\n \"env_logger\": Label(\"@firewood_crates//:env_logger-0.11.8\"),\n \"fastrace\": Label(\"@firewood_crates//:fastrace-0.7.14\"),\n \"fastrace-opentelemetry\": Label(\"@firewood_crates//:fastrace-opentelemetry-0.14.0\"),\n \"hex\": Label(\"@firewood_crates//:hex-0.4.3\"),\n \"log\": Label(\"@firewood_crates//:log-0.4.28\"),\n \"metrics\": Label(\"@firewood_crates//:metrics-0.24.2\"),\n \"metrics-exporter-prometheus\": Label(\"@firewood_crates//:metrics-exporter-prometheus-0.17.2\"),\n \"metrics-util\": Label(\"@firewood_crates//:metrics-util-0.20.0\"),\n \"opentelemetry\": Label(\"@firewood_crates//:opentelemetry-0.31.0\"),\n \"opentelemetry-otlp\": Label(\"@firewood_crates//:opentelemetry-otlp-0.31.0\"),\n \"opentelemetry-proto\": Label(\"@firewood_crates//:opentelemetry-proto-0.31.0\"),\n \"opentelemetry_sdk\": Label(\"@firewood_crates//:opentelemetry_sdk-0.31.0\"),\n \"pretty-duration\": Label(\"@firewood_crates//:pretty-duration-0.1.1\"),\n \"rand\": Label(\"@firewood_crates//:rand-0.9.2\"),\n \"rand_distr\": Label(\"@firewood_crates//:rand_distr-0.5.1\"),\n \"sha2\": Label(\"@firewood_crates//:sha2-0.10.9\"),\n \"tokio\": Label(\"@firewood_crates//:tokio-1.48.0\"),\n },\n \"cfg(unix)\": {\n \"tikv-jemallocator\": Label(\"@firewood_crates//:tikv-jemallocator-0.6.1\"),\n },\n },\n \"firewood/ffi\": {\n _COMMON_CONDITION: {\n \"chrono\": Label(\"@firewood_crates//:chrono-0.4.42\"),\n \"coarsetime\": Label(\"@firewood_crates//:coarsetime-0.1.36\"),\n \"metrics\": Label(\"@firewood_crates//:metrics-0.24.2\"),\n \"metrics-util\": Label(\"@firewood_crates//:metrics-util-0.20.0\"),\n \"oxhttp\": Label(\"@firewood_crates//:oxhttp-0.3.1\"),\n \"parking_lot\": Label(\"@firewood_crates//:parking_lot-0.12.5\"),\n },\n \"cfg(unix)\": {\n \"tikv-jemallocator\": Label(\"@firewood_crates//:tikv-jemallocator-0.6.1\"),\n },\n },\n \"firewood/fwdctl\": {\n _COMMON_CONDITION: {\n \"askama\": Label(\"@firewood_crates//:askama-0.14.0\"),\n \"clap\": Label(\"@firewood_crates//:clap-4.5.52\"),\n \"csv\": Label(\"@firewood_crates//:csv-1.4.0\"),\n \"env_logger\": Label(\"@firewood_crates//:env_logger-0.11.8\"),\n \"hex\": Label(\"@firewood_crates//:hex-0.4.3\"),\n \"indicatif\": Label(\"@firewood_crates//:indicatif-0.18.3\"),\n \"log\": Label(\"@firewood_crates//:log-0.4.28\"),\n \"nonzero_ext\": Label(\"@firewood_crates//:nonzero_ext-0.3.0\"),\n \"num-format\": Label(\"@firewood_crates//:num-format-0.4.4\"),\n },\n },\n \"firewood/firewood-macros\": {\n _COMMON_CONDITION: {\n \"proc-macro2\": Label(\"@firewood_crates//:proc-macro2-1.0.103\"),\n \"quote\": Label(\"@firewood_crates//:quote-1.0.42\"),\n \"syn\": Label(\"@firewood_crates//:syn-2.0.110\"),\n },\n },\n \"firewood/storage\": {\n _COMMON_CONDITION: {\n \"bitfield\": Label(\"@firewood_crates//:bitfield-0.19.4\"),\n \"bitflags\": Label(\"@firewood_crates//:bitflags-2.10.0\"),\n \"bumpalo\": Label(\"@firewood_crates//:bumpalo-3.19.0\"),\n \"bytemuck\": Label(\"@firewood_crates//:bytemuck-1.24.0\"),\n \"coarsetime\": Label(\"@firewood_crates//:coarsetime-0.1.36\"),\n \"fastrace\": Label(\"@firewood_crates//:fastrace-0.7.14\"),\n \"hex\": Label(\"@firewood_crates//:hex-0.4.3\"),\n \"indicatif\": Label(\"@firewood_crates//:indicatif-0.18.3\"),\n \"integer-encoding\": Label(\"@firewood_crates//:integer-encoding-4.1.0\"),\n \"lru\": Label(\"@firewood_crates//:lru-0.16.2\"),\n \"metrics\": Label(\"@firewood_crates//:metrics-0.24.2\"),\n \"nonzero_ext\": Label(\"@firewood_crates//:nonzero_ext-0.3.0\"),\n \"parking_lot\": Label(\"@firewood_crates//:parking_lot-0.12.5\"),\n \"rand\": Label(\"@firewood_crates//:rand-0.9.2\"),\n \"semver\": Label(\"@firewood_crates//:semver-1.0.27\"),\n \"sha2\": Label(\"@firewood_crates//:sha2-0.10.9\"),\n \"smallvec\": Label(\"@firewood_crates//:smallvec-1.15.1\"),\n \"thiserror\": Label(\"@firewood_crates//:thiserror-2.0.17\"),\n \"triomphe\": Label(\"@firewood_crates//:triomphe-0.1.15\"),\n },\n \"aarch64-unknown-linux-gnu\": {\n \"io-uring\": Label(\"@firewood_crates//:io-uring-0.7.11\"),\n },\n \"x86_64-unknown-linux-gnu\": {\n \"io-uring\": Label(\"@firewood_crates//:io-uring-0.7.11\"),\n },\n \"x86_64-unknown-nixos-gnu\": {\n \"io-uring\": Label(\"@firewood_crates//:io-uring-0.7.11\"),\n },\n },\n \"firewood/triehash\": {\n _COMMON_CONDITION: {\n \"hash-db\": Label(\"@firewood_crates//:hash-db-0.16.0\"),\n \"rlp\": Label(\"@firewood_crates//:rlp-0.6.1\"),\n },\n },\n}\n\n\n_NORMAL_ALIASES = {\n \"firewood\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/firewood\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/benchmark\": {\n _COMMON_CONDITION: {\n },\n \"cfg(unix)\": {\n },\n },\n \"firewood/ffi\": {\n _COMMON_CONDITION: {\n },\n \"cfg(unix)\": {\n },\n },\n \"firewood/fwdctl\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/firewood-macros\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/storage\": {\n _COMMON_CONDITION: {\n },\n \"aarch64-unknown-linux-gnu\": {\n },\n \"x86_64-unknown-linux-gnu\": {\n },\n \"x86_64-unknown-nixos-gnu\": {\n },\n },\n \"firewood/triehash\": {\n _COMMON_CONDITION: {\n },\n },\n}\n\n\n_NORMAL_DEV_DEPENDENCIES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n _COMMON_CONDITION: {\n \"clap\": Label(\"@firewood_crates//:clap-4.5.52\"),\n \"criterion\": Label(\"@firewood_crates//:criterion-0.7.0\"),\n \"ctor\": Label(\"@firewood_crates//:ctor-0.6.1\"),\n \"env_logger\": Label(\"@firewood_crates//:env_logger-0.11.8\"),\n \"ethereum-types\": Label(\"@firewood_crates//:ethereum-types-0.16.0\"),\n \"hash-db\": Label(\"@firewood_crates//:hash-db-0.16.0\"),\n \"hex-literal\": Label(\"@firewood_crates//:hex-literal-1.1.0\"),\n \"plain_hasher\": Label(\"@firewood_crates//:plain_hasher-0.2.3\"),\n \"pprof\": Label(\"@firewood_crates//:pprof-0.15.0\"),\n \"rand\": Label(\"@firewood_crates//:rand-0.9.2\"),\n \"rlp\": Label(\"@firewood_crates//:rlp-0.6.1\"),\n \"sha3\": Label(\"@firewood_crates//:sha3-0.10.8\"),\n \"tempfile\": Label(\"@firewood_crates//:tempfile-3.23.0\"),\n \"test-case\": Label(\"@firewood_crates//:test-case-3.3.1\"),\n },\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n _COMMON_CONDITION: {\n \"test-case\": Label(\"@firewood_crates//:test-case-3.3.1\"),\n },\n },\n \"firewood/fwdctl\": {\n _COMMON_CONDITION: {\n \"anyhow\": Label(\"@firewood_crates//:anyhow-1.0.100\"),\n \"assert_cmd\": Label(\"@firewood_crates//:assert_cmd-2.1.1\"),\n \"predicates\": Label(\"@firewood_crates//:predicates-3.1.3\"),\n \"rand\": Label(\"@firewood_crates//:rand-0.9.2\"),\n \"serial_test\": Label(\"@firewood_crates//:serial_test-3.2.0\"),\n },\n },\n \"firewood/firewood-macros\": {\n _COMMON_CONDITION: {\n \"coarsetime\": Label(\"@firewood_crates//:coarsetime-0.1.36\"),\n \"metrics\": Label(\"@firewood_crates//:metrics-0.24.2\"),\n \"trybuild\": Label(\"@firewood_crates//:trybuild-1.0.114\"),\n },\n },\n \"firewood/storage\": {\n _COMMON_CONDITION: {\n \"criterion\": Label(\"@firewood_crates//:criterion-0.7.0\"),\n \"pprof\": Label(\"@firewood_crates//:pprof-0.15.0\"),\n \"tempfile\": Label(\"@firewood_crates//:tempfile-3.23.0\"),\n \"test-case\": Label(\"@firewood_crates//:test-case-3.3.1\"),\n },\n },\n \"firewood/triehash\": {\n _COMMON_CONDITION: {\n \"criterion\": Label(\"@firewood_crates//:criterion-0.7.0\"),\n \"ethereum-types\": Label(\"@firewood_crates//:ethereum-types-0.16.0\"),\n \"hex-literal\": Label(\"@firewood_crates//:hex-literal-1.1.0\"),\n \"keccak-hasher\": Label(\"@firewood_crates//:keccak-hasher-0.16.0\"),\n \"tiny-keccak\": Label(\"@firewood_crates//:tiny-keccak-2.0.2\"),\n \"trie-standardmap\": Label(\"@firewood_crates//:trie-standardmap-0.16.0\"),\n },\n },\n}\n\n\n_NORMAL_DEV_ALIASES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/fwdctl\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/firewood-macros\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/storage\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/triehash\": {\n _COMMON_CONDITION: {\n },\n },\n}\n\n\n_PROC_MACRO_DEPENDENCIES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n _COMMON_CONDITION: {\n \"bytemuck_derive\": Label(\"@firewood_crates//:bytemuck_derive-1.10.2\"),\n \"derive-where\": Label(\"@firewood_crates//:derive-where-1.6.0\"),\n },\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n _COMMON_CONDITION: {\n \"derive-where\": Label(\"@firewood_crates//:derive-where-1.6.0\"),\n },\n },\n \"firewood/fwdctl\": {\n },\n \"firewood/firewood-macros\": {\n },\n \"firewood/storage\": {\n _COMMON_CONDITION: {\n \"aquamarine\": Label(\"@firewood_crates//:aquamarine-0.6.0\"),\n \"bytemuck_derive\": Label(\"@firewood_crates//:bytemuck_derive-1.10.2\"),\n \"derive-where\": Label(\"@firewood_crates//:derive-where-1.6.0\"),\n \"enum-as-inner\": Label(\"@firewood_crates//:enum-as-inner-0.6.1\"),\n },\n },\n \"firewood/triehash\": {\n },\n}\n\n\n_PROC_MACRO_ALIASES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n },\n \"firewood/fwdctl\": {\n },\n \"firewood/firewood-macros\": {\n },\n \"firewood/storage\": {\n },\n \"firewood/triehash\": {\n },\n}\n\n\n_PROC_MACRO_DEV_DEPENDENCIES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n },\n \"firewood/fwdctl\": {\n },\n \"firewood/firewood-macros\": {\n },\n \"firewood/storage\": {\n },\n \"firewood/triehash\": {\n },\n}\n\n\n_PROC_MACRO_DEV_ALIASES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/fwdctl\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/firewood-macros\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/storage\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/triehash\": {\n _COMMON_CONDITION: {\n },\n },\n}\n\n\n_BUILD_DEPENDENCIES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n _COMMON_CONDITION: {\n \"cbindgen\": Label(\"@firewood_crates//:cbindgen-0.29.2\"),\n },\n },\n \"firewood/fwdctl\": {\n },\n \"firewood/firewood-macros\": {\n },\n \"firewood/storage\": {\n },\n \"firewood/triehash\": {\n },\n}\n\n\n_BUILD_ALIASES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n _COMMON_CONDITION: {\n },\n },\n \"firewood/fwdctl\": {\n },\n \"firewood/firewood-macros\": {\n },\n \"firewood/storage\": {\n },\n \"firewood/triehash\": {\n },\n}\n\n\n_BUILD_PROC_MACRO_DEPENDENCIES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n },\n \"firewood/fwdctl\": {\n },\n \"firewood/firewood-macros\": {\n },\n \"firewood/storage\": {\n },\n \"firewood/triehash\": {\n },\n}\n\n\n_BUILD_PROC_MACRO_ALIASES = {\n \"firewood\": {\n },\n \"firewood/firewood\": {\n },\n \"firewood/benchmark\": {\n },\n \"firewood/ffi\": {\n },\n \"firewood/fwdctl\": {\n },\n \"firewood/firewood-macros\": {\n },\n \"firewood/storage\": {\n },\n \"firewood/triehash\": {\n },\n}\n\n\n_CONDITIONS = {\n \"aarch64-apple-darwin\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n \"aarch64-linux-android\": [],\n \"aarch64-pc-windows-gnullvm\": [],\n \"aarch64-unknown-linux-gnu\": [\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\"],\n \"cfg(all(all(target_arch = \\\"aarch64\\\", target_endian = \\\"little\\\"), target_os = \\\"windows\\\"))\": [],\n \"cfg(all(all(target_arch = \\\"aarch64\\\", target_endian = \\\"little\\\"), target_vendor = \\\"apple\\\", any(target_os = \\\"ios\\\", target_os = \\\"macos\\\", target_os = \\\"tvos\\\", target_os = \\\"visionos\\\", target_os = \\\"watchos\\\")))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n \"cfg(all(any(all(target_arch = \\\"aarch64\\\", target_endian = \\\"little\\\"), all(target_arch = \\\"arm\\\", target_endian = \\\"little\\\")), any(target_os = \\\"android\\\", target_os = \\\"linux\\\")))\": [\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\"],\n \"cfg(all(any(target_arch = \\\"wasm32\\\", target_arch = \\\"wasm64\\\"), target_os = \\\"unknown\\\"))\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\"],\n \"cfg(all(any(target_arch = \\\"x86_64\\\", target_arch = \\\"arm64ec\\\"), target_env = \\\"msvc\\\", not(windows_raw_dylib)))\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\"],\n \"cfg(all(any(target_os = \\\"linux\\\"), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\": [],\n \"cfg(all(any(target_os = \\\"linux\\\", target_os = \\\"android\\\"), not(any(all(target_os = \\\"linux\\\", target_env = \\\"\\\"), getrandom_backend = \\\"custom\\\", getrandom_backend = \\\"linux_raw\\\", getrandom_backend = \\\"rdrand\\\", getrandom_backend = \\\"rndr\\\"))))\": [\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(all(not(rustix_use_libc), not(miri), target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\"))))\": [\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \\\"linux\\\", any(target_endian = \\\"little\\\", any(target_arch = \\\"s390x\\\", target_arch = \\\"powerpc\\\")), any(target_arch = \\\"arm\\\", all(target_arch = \\\"aarch64\\\", target_pointer_width = \\\"64\\\"), target_arch = \\\"riscv64\\\", all(rustix_use_experimental_asm, target_arch = \\\"powerpc\\\"), all(rustix_use_experimental_asm, target_arch = \\\"powerpc64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"s390x\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips32r6\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64\\\"), all(rustix_use_experimental_asm, target_arch = \\\"mips64r6\\\"), target_arch = \\\"x86\\\", all(target_arch = \\\"x86_64\\\", target_pointer_width = \\\"64\\\")))))))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:wasm32-unknown-unknown\",\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"cfg(all(target_arch = \\\"aarch64\\\", target_env = \\\"msvc\\\", not(windows_raw_dylib)))\": [],\n \"cfg(all(target_arch = \\\"aarch64\\\", target_os = \\\"linux\\\"))\": [\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\"],\n \"cfg(all(target_arch = \\\"aarch64\\\", target_vendor = \\\"apple\\\"))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n \"cfg(all(target_arch = \\\"loongarch64\\\", target_os = \\\"linux\\\"))\": [],\n \"cfg(all(target_arch = \\\"wasm32\\\", not(target_os = \\\"wasi\\\")))\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\"],\n \"cfg(all(target_arch = \\\"wasm32\\\", target_os = \\\"unknown\\\"))\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\"],\n \"cfg(all(target_arch = \\\"wasm32\\\", target_os = \\\"wasi\\\"))\": [\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"cfg(all(target_arch = \\\"wasm32\\\", target_os = \\\"wasi\\\", target_env = \\\"p2\\\"))\": [],\n \"cfg(all(target_arch = \\\"x86\\\", target_env = \\\"gnu\\\", not(target_abi = \\\"llvm\\\"), not(windows_raw_dylib)))\": [],\n \"cfg(all(target_arch = \\\"x86\\\", target_env = \\\"msvc\\\", not(windows_raw_dylib)))\": [],\n \"cfg(all(target_arch = \\\"x86_64\\\", target_env = \\\"gnu\\\", not(target_abi = \\\"llvm\\\"), not(windows_raw_dylib)))\": [\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(all(target_family = \\\"wasm\\\", target_os = \\\"unknown\\\"))\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\"],\n \"cfg(all(target_os = \\\"uefi\\\", getrandom_backend = \\\"efi_rng\\\"))\": [],\n \"cfg(all(unix, not(target_os = \\\"macos\\\")))\": [\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(any())\": [],\n \"cfg(any(target_arch = \\\"aarch64\\\", target_arch = \\\"x86_64\\\", target_arch = \\\"x86\\\"))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(any(target_arch = \\\"x86\\\", target_arch = \\\"x86_64\\\"))\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(any(target_os = \\\"dragonfly\\\", target_os = \\\"freebsd\\\", target_os = \\\"hurd\\\", target_os = \\\"illumos\\\", target_os = \\\"cygwin\\\", all(target_os = \\\"horizon\\\", target_arch = \\\"arm\\\")))\": [],\n \"cfg(any(target_os = \\\"haiku\\\", target_os = \\\"redox\\\", target_os = \\\"nto\\\", target_os = \\\"aix\\\"))\": [],\n \"cfg(any(target_os = \\\"ios\\\", target_os = \\\"visionos\\\", target_os = \\\"watchos\\\", target_os = \\\"tvos\\\"))\": [],\n \"cfg(any(target_os = \\\"macos\\\", target_os = \\\"ios\\\"))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n \"cfg(any(target_os = \\\"macos\\\", target_os = \\\"openbsd\\\", target_os = \\\"vita\\\", target_os = \\\"emscripten\\\"))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n \"cfg(any(target_os = \\\"wasix\\\", target_os = \\\"wasi\\\"))\": [\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"cfg(any(unix, target_os = \\\"wasi\\\"))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:wasm32-wasip1\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(any(windows, target_os = \\\"cygwin\\\"))\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\"],\n \"cfg(not(all(target_arch = \\\"arm\\\", target_os = \\\"none\\\")))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:wasm32-unknown-unknown\",\"@rules_rust//rust/platform:wasm32-wasip1\",\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(not(all(windows, target_env = \\\"msvc\\\", not(target_vendor = \\\"uwp\\\"))))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:wasm32-unknown-unknown\",\"@rules_rust//rust/platform:wasm32-wasip1\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(not(any(all(any(target_arch = \\\"x86_64\\\", target_arch = \\\"aarch64\\\"), any(target_os = \\\"linux\\\", target_os = \\\"macos\\\", target_os = \\\"windows\\\"), any(target_env = \\\"gnu\\\", target_env = \\\"musl\\\", target_env = \\\"msvc\\\", target_env = \\\"\\\")), all(target_arch = \\\"x86\\\", target_os = \\\"windows\\\", target_env = \\\"msvc\\\"), all(target_arch = \\\"x86\\\", target_os = \\\"linux\\\", target_env = \\\"gnu\\\"))))\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\",\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"cfg(not(any(target_os = \\\"wasix\\\", target_os = \\\"wasi\\\")))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:wasm32-unknown-unknown\",\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(not(any(target_os = \\\"windows\\\", target_arch = \\\"wasm32\\\")))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(not(target_arch = \\\"wasm32\\\"))\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(not(target_has_atomic = \\\"ptr\\\"))\": [],\n \"cfg(target_arch = \\\"aarch64\\\")\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\"],\n \"cfg(target_arch = \\\"spirv\\\")\": [],\n \"cfg(target_arch = \\\"wasm32\\\")\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\",\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"cfg(target_arch = \\\"x86\\\")\": [],\n \"cfg(target_arch = \\\"x86_64\\\")\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(target_feature = \\\"atomics\\\")\": [],\n \"cfg(target_os = \\\"android\\\")\": [],\n \"cfg(target_os = \\\"haiku\\\")\": [],\n \"cfg(target_os = \\\"hermit\\\")\": [],\n \"cfg(target_os = \\\"macos\\\")\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n \"cfg(target_os = \\\"netbsd\\\")\": [],\n \"cfg(target_os = \\\"redox\\\")\": [],\n \"cfg(target_os = \\\"solaris\\\")\": [],\n \"cfg(target_os = \\\"vxworks\\\")\": [],\n \"cfg(target_os = \\\"wasi\\\")\": [\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"cfg(target_os = \\\"windows\\\")\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\"],\n \"cfg(target_pointer_width = \\\"32\\\")\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\",\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"cfg(target_vendor = \\\"apple\\\")\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\"],\n \"cfg(unix)\": [\"@rules_rust//rust/platform:aarch64-apple-darwin\",\"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"cfg(windows)\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\"],\n \"cfg(windows_raw_dylib)\": [],\n \"i686-pc-windows-gnu\": [],\n \"i686-pc-windows-gnullvm\": [],\n \"wasm32-unknown-unknown\": [\"@rules_rust//rust/platform:wasm32-unknown-unknown\"],\n \"wasm32-wasip1\": [\"@rules_rust//rust/platform:wasm32-wasip1\"],\n \"x86_64-pc-windows-gnu\": [],\n \"x86_64-pc-windows-gnullvm\": [],\n \"x86_64-pc-windows-msvc\": [\"@rules_rust//rust/platform:x86_64-pc-windows-msvc\"],\n \"x86_64-unknown-linux-gnu\": [\"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\",\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n \"x86_64-unknown-nixos-gnu\": [\"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\"],\n}\n\n###############################################################################\n\ndef crate_repositories():\n \"\"\"A macro for defining repositories for all generated crates.\n\n Returns:\n A list of repos visible to the module through the module extension.\n \"\"\"\n maybe(\n http_archive,\n name = \"firewood_crates__addr2line-0.25.1\",\n sha256 = \"1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/addr2line/0.25.1/download\"],\n strip_prefix = \"addr2line-0.25.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.addr2line-0.25.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__adler2-2.0.1\",\n sha256 = \"320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/adler2/2.0.1/download\"],\n strip_prefix = \"adler2-2.0.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.adler2-2.0.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ahash-0.8.12\",\n sha256 = \"5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ahash/0.8.12/download\"],\n strip_prefix = \"ahash-0.8.12\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ahash-0.8.12.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__aho-corasick-1.1.4\",\n sha256 = \"ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/aho-corasick/1.1.4/download\"],\n strip_prefix = \"aho-corasick-1.1.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.aho-corasick-1.1.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__aligned-vec-0.6.4\",\n sha256 = \"dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/aligned-vec/0.6.4/download\"],\n strip_prefix = \"aligned-vec-0.6.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.aligned-vec-0.6.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__allocator-api2-0.2.21\",\n sha256 = \"683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/allocator-api2/0.2.21/download\"],\n strip_prefix = \"allocator-api2-0.2.21\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.allocator-api2-0.2.21.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__android_system_properties-0.1.5\",\n sha256 = \"819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/android_system_properties/0.1.5/download\"],\n strip_prefix = \"android_system_properties-0.1.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.android_system_properties-0.1.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__anes-0.1.6\",\n sha256 = \"4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/anes/0.1.6/download\"],\n strip_prefix = \"anes-0.1.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.anes-0.1.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__anstream-0.6.21\",\n sha256 = \"43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/anstream/0.6.21/download\"],\n strip_prefix = \"anstream-0.6.21\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.anstream-0.6.21.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__anstyle-1.0.13\",\n sha256 = \"5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/anstyle/1.0.13/download\"],\n strip_prefix = \"anstyle-1.0.13\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.anstyle-1.0.13.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__anstyle-parse-0.2.7\",\n sha256 = \"4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/anstyle-parse/0.2.7/download\"],\n strip_prefix = \"anstyle-parse-0.2.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.anstyle-parse-0.2.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__anstyle-query-1.1.5\",\n sha256 = \"40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/anstyle-query/1.1.5/download\"],\n strip_prefix = \"anstyle-query-1.1.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.anstyle-query-1.1.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__anstyle-wincon-3.0.11\",\n sha256 = \"291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/anstyle-wincon/3.0.11/download\"],\n strip_prefix = \"anstyle-wincon-3.0.11\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.anstyle-wincon-3.0.11.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__anyhow-1.0.100\",\n sha256 = \"a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/anyhow/1.0.100/download\"],\n strip_prefix = \"anyhow-1.0.100\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.anyhow-1.0.100.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__aquamarine-0.6.0\",\n sha256 = \"0f50776554130342de4836ba542aa85a4ddb361690d7e8df13774d7284c3d5c2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/aquamarine/0.6.0/download\"],\n strip_prefix = \"aquamarine-0.6.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.aquamarine-0.6.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__arrayvec-0.7.6\",\n sha256 = \"7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/arrayvec/0.7.6/download\"],\n strip_prefix = \"arrayvec-0.7.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.arrayvec-0.7.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__askama-0.14.0\",\n sha256 = \"f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/askama/0.14.0/download\"],\n strip_prefix = \"askama-0.14.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.askama-0.14.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__askama_derive-0.14.0\",\n sha256 = \"129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/askama_derive/0.14.0/download\"],\n strip_prefix = \"askama_derive-0.14.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.askama_derive-0.14.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__askama_parser-0.14.0\",\n sha256 = \"d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/askama_parser/0.14.0/download\"],\n strip_prefix = \"askama_parser-0.14.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.askama_parser-0.14.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__assert_cmd-2.1.1\",\n sha256 = \"bcbb6924530aa9e0432442af08bbcafdad182db80d2e560da42a6d442535bf85\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/assert_cmd/2.1.1/download\"],\n strip_prefix = \"assert_cmd-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.assert_cmd-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__async-trait-0.1.89\",\n sha256 = \"9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/async-trait/0.1.89/download\"],\n strip_prefix = \"async-trait-0.1.89\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.async-trait-0.1.89.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__atomic-waker-1.1.2\",\n sha256 = \"1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/atomic-waker/1.1.2/download\"],\n strip_prefix = \"atomic-waker-1.1.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.atomic-waker-1.1.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__autocfg-1.5.0\",\n sha256 = \"c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/autocfg/1.5.0/download\"],\n strip_prefix = \"autocfg-1.5.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.autocfg-1.5.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__aws-lc-rs-1.15.0\",\n sha256 = \"5932a7d9d28b0d2ea34c6b3779d35e3dd6f6345317c34e73438c4f1f29144151\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/aws-lc-rs/1.15.0/download\"],\n strip_prefix = \"aws-lc-rs-1.15.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.aws-lc-rs-1.15.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__aws-lc-sys-0.33.0\",\n sha256 = \"1826f2e4cfc2cd19ee53c42fbf68e2f81ec21108e0b7ecf6a71cf062137360fc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/aws-lc-sys/0.33.0/download\"],\n strip_prefix = \"aws-lc-sys-0.33.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.aws-lc-sys-0.33.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__backtrace-0.3.76\",\n sha256 = \"bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/backtrace/0.3.76/download\"],\n strip_prefix = \"backtrace-0.3.76\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.backtrace-0.3.76.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__base64-0.22.1\",\n sha256 = \"72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/base64/0.22.1/download\"],\n strip_prefix = \"base64-0.22.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.base64-0.22.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__basic-toml-0.1.10\",\n sha256 = \"ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/basic-toml/0.1.10/download\"],\n strip_prefix = \"basic-toml-0.1.10\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.basic-toml-0.1.10.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bindgen-0.72.1\",\n sha256 = \"993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bindgen/0.72.1/download\"],\n strip_prefix = \"bindgen-0.72.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bindgen-0.72.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bitfield-0.19.4\",\n sha256 = \"21ba6517c6b0f2bf08be60e187ab64b038438f22dd755614d8fe4d4098c46419\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bitfield/0.19.4/download\"],\n strip_prefix = \"bitfield-0.19.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bitfield-0.19.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bitfield-macros-0.19.4\",\n sha256 = \"f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bitfield-macros/0.19.4/download\"],\n strip_prefix = \"bitfield-macros-0.19.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bitfield-macros-0.19.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bitflags-1.3.2\",\n sha256 = \"bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bitflags/1.3.2/download\"],\n strip_prefix = \"bitflags-1.3.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bitflags-1.3.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bitflags-2.10.0\",\n sha256 = \"812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bitflags/2.10.0/download\"],\n strip_prefix = \"bitflags-2.10.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bitflags-2.10.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bitvec-1.0.1\",\n sha256 = \"1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bitvec/1.0.1/download\"],\n strip_prefix = \"bitvec-1.0.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bitvec-1.0.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__block-buffer-0.10.4\",\n sha256 = \"3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/block-buffer/0.10.4/download\"],\n strip_prefix = \"block-buffer-0.10.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.block-buffer-0.10.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bstr-1.12.1\",\n sha256 = \"63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bstr/1.12.1/download\"],\n strip_prefix = \"bstr-1.12.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bstr-1.12.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bumpalo-3.19.0\",\n sha256 = \"46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bumpalo/3.19.0/download\"],\n strip_prefix = \"bumpalo-3.19.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bumpalo-3.19.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__byte-slice-cast-1.2.3\",\n sha256 = \"7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/byte-slice-cast/1.2.3/download\"],\n strip_prefix = \"byte-slice-cast-1.2.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.byte-slice-cast-1.2.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bytemuck-1.24.0\",\n sha256 = \"1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bytemuck/1.24.0/download\"],\n strip_prefix = \"bytemuck-1.24.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bytemuck-1.24.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bytemuck_derive-1.10.2\",\n sha256 = \"f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bytemuck_derive/1.10.2/download\"],\n strip_prefix = \"bytemuck_derive-1.10.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bytemuck_derive-1.10.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__byteorder-1.5.0\",\n sha256 = \"1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/byteorder/1.5.0/download\"],\n strip_prefix = \"byteorder-1.5.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.byteorder-1.5.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__bytes-1.11.0\",\n sha256 = \"b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/bytes/1.11.0/download\"],\n strip_prefix = \"bytes-1.11.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.bytes-1.11.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__byteview-0.6.1\",\n sha256 = \"6236364b88b9b6d0bc181ba374cf1ab55ba3ef97a1cb6f8cddad48a273767fb5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/byteview/0.6.1/download\"],\n strip_prefix = \"byteview-0.6.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.byteview-0.6.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__cast-0.3.0\",\n sha256 = \"37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/cast/0.3.0/download\"],\n strip_prefix = \"cast-0.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.cast-0.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__cbindgen-0.29.2\",\n sha256 = \"befbfd072a8e81c02f8c507aefce431fe5e7d051f83d48a23ffc9b9fe5a11799\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/cbindgen/0.29.2/download\"],\n strip_prefix = \"cbindgen-0.29.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.cbindgen-0.29.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__cc-1.2.46\",\n sha256 = \"b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/cc/1.2.46/download\"],\n strip_prefix = \"cc-1.2.46\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.cc-1.2.46.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__cexpr-0.6.0\",\n sha256 = \"6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/cexpr/0.6.0/download\"],\n strip_prefix = \"cexpr-0.6.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.cexpr-0.6.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__cfg-if-1.0.4\",\n sha256 = \"9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/cfg-if/1.0.4/download\"],\n strip_prefix = \"cfg-if-1.0.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.cfg-if-1.0.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__chrono-0.4.42\",\n sha256 = \"145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/chrono/0.4.42/download\"],\n strip_prefix = \"chrono-0.4.42\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.chrono-0.4.42.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ciborium-0.2.2\",\n sha256 = \"42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ciborium/0.2.2/download\"],\n strip_prefix = \"ciborium-0.2.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ciborium-0.2.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ciborium-io-0.2.2\",\n sha256 = \"05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ciborium-io/0.2.2/download\"],\n strip_prefix = \"ciborium-io-0.2.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ciborium-io-0.2.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ciborium-ll-0.2.2\",\n sha256 = \"57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ciborium-ll/0.2.2/download\"],\n strip_prefix = \"ciborium-ll-0.2.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ciborium-ll-0.2.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__clang-sys-1.8.1\",\n sha256 = \"0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/clang-sys/1.8.1/download\"],\n strip_prefix = \"clang-sys-1.8.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.clang-sys-1.8.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__clap-4.5.52\",\n sha256 = \"aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/clap/4.5.52/download\"],\n strip_prefix = \"clap-4.5.52\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.clap-4.5.52.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__clap_builder-4.5.52\",\n sha256 = \"02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/clap_builder/4.5.52/download\"],\n strip_prefix = \"clap_builder-4.5.52\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.clap_builder-4.5.52.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__clap_derive-4.5.49\",\n sha256 = \"2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/clap_derive/4.5.49/download\"],\n strip_prefix = \"clap_derive-4.5.49\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.clap_derive-4.5.49.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__clap_lex-0.7.6\",\n sha256 = \"a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/clap_lex/0.7.6/download\"],\n strip_prefix = \"clap_lex-0.7.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.clap_lex-0.7.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__cmake-0.1.54\",\n sha256 = \"e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/cmake/0.1.54/download\"],\n strip_prefix = \"cmake-0.1.54\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.cmake-0.1.54.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__coarsetime-0.1.36\",\n sha256 = \"91849686042de1b41cd81490edc83afbcb0abe5a9b6f2c4114f23ce8cca1bcf4\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/coarsetime/0.1.36/download\"],\n strip_prefix = \"coarsetime-0.1.36\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.coarsetime-0.1.36.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__colorchoice-1.0.4\",\n sha256 = \"b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/colorchoice/1.0.4/download\"],\n strip_prefix = \"colorchoice-1.0.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.colorchoice-1.0.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__compare-0.0.6\",\n sha256 = \"ea0095f6103c2a8b44acd6fd15960c801dafebf02e21940360833e0673f48ba7\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/compare/0.0.6/download\"],\n strip_prefix = \"compare-0.0.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.compare-0.0.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__console-0.16.1\",\n sha256 = \"b430743a6eb14e9764d4260d4c0d8123087d504eeb9c48f2b2a5e810dd369df4\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/console/0.16.1/download\"],\n strip_prefix = \"console-0.16.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.console-0.16.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__const-hex-1.17.0\",\n sha256 = \"3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/const-hex/1.17.0/download\"],\n strip_prefix = \"const-hex-1.17.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.const-hex-1.17.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__const_format-0.2.35\",\n sha256 = \"7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/const_format/0.2.35/download\"],\n strip_prefix = \"const_format-0.2.35\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.const_format-0.2.35.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__const_format_proc_macros-0.2.34\",\n sha256 = \"1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/const_format_proc_macros/0.2.34/download\"],\n strip_prefix = \"const_format_proc_macros-0.2.34\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.const_format_proc_macros-0.2.34.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__core-foundation-0.10.1\",\n sha256 = \"b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/core-foundation/0.10.1/download\"],\n strip_prefix = \"core-foundation-0.10.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.core-foundation-0.10.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__core-foundation-sys-0.8.7\",\n sha256 = \"773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/core-foundation-sys/0.8.7/download\"],\n strip_prefix = \"core-foundation-sys-0.8.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.core-foundation-sys-0.8.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__cpp_demangle-0.4.5\",\n sha256 = \"f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/cpp_demangle/0.4.5/download\"],\n strip_prefix = \"cpp_demangle-0.4.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.cpp_demangle-0.4.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__cpufeatures-0.2.17\",\n sha256 = \"59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/cpufeatures/0.2.17/download\"],\n strip_prefix = \"cpufeatures-0.2.17\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.cpufeatures-0.2.17.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__criterion-0.7.0\",\n sha256 = \"e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/criterion/0.7.0/download\"],\n strip_prefix = \"criterion-0.7.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.criterion-0.7.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__criterion-plot-0.6.0\",\n sha256 = \"9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/criterion-plot/0.6.0/download\"],\n strip_prefix = \"criterion-plot-0.6.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.criterion-plot-0.6.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__crossbeam-deque-0.8.6\",\n sha256 = \"9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/crossbeam-deque/0.8.6/download\"],\n strip_prefix = \"crossbeam-deque-0.8.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.crossbeam-deque-0.8.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__crossbeam-epoch-0.9.18\",\n sha256 = \"5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/crossbeam-epoch/0.9.18/download\"],\n strip_prefix = \"crossbeam-epoch-0.9.18\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.crossbeam-epoch-0.9.18.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__crossbeam-skiplist-0.1.3\",\n sha256 = \"df29de440c58ca2cc6e587ec3d22347551a32435fbde9d2bff64e78a9ffa151b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/crossbeam-skiplist/0.1.3/download\"],\n strip_prefix = \"crossbeam-skiplist-0.1.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.crossbeam-skiplist-0.1.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__crossbeam-utils-0.8.21\",\n sha256 = \"d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/crossbeam-utils/0.8.21/download\"],\n strip_prefix = \"crossbeam-utils-0.8.21\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.crossbeam-utils-0.8.21.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__crunchy-0.2.4\",\n sha256 = \"460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/crunchy/0.2.4/download\"],\n strip_prefix = \"crunchy-0.2.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.crunchy-0.2.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__crypto-common-0.1.7\",\n sha256 = \"78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/crypto-common/0.1.7/download\"],\n strip_prefix = \"crypto-common-0.1.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.crypto-common-0.1.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__csv-1.4.0\",\n sha256 = \"52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/csv/1.4.0/download\"],\n strip_prefix = \"csv-1.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.csv-1.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__csv-core-0.1.13\",\n sha256 = \"704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/csv-core/0.1.13/download\"],\n strip_prefix = \"csv-core-0.1.13\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.csv-core-0.1.13.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ctor-0.6.1\",\n sha256 = \"3ffc71fcdcdb40d6f087edddf7f8f1f8f79e6cf922f555a9ee8779752d4819bd\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ctor/0.6.1/download\"],\n strip_prefix = \"ctor-0.6.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ctor-0.6.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ctor-proc-macro-0.0.7\",\n sha256 = \"52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ctor-proc-macro/0.0.7/download\"],\n strip_prefix = \"ctor-proc-macro-0.0.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ctor-proc-macro-0.0.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__dashmap-6.1.0\",\n sha256 = \"5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/dashmap/6.1.0/download\"],\n strip_prefix = \"dashmap-6.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.dashmap-6.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__debugid-0.8.0\",\n sha256 = \"bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/debugid/0.8.0/download\"],\n strip_prefix = \"debugid-0.8.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.debugid-0.8.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__derive-where-1.6.0\",\n sha256 = \"ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/derive-where/1.6.0/download\"],\n strip_prefix = \"derive-where-1.6.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.derive-where-1.6.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__difflib-0.4.0\",\n sha256 = \"6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/difflib/0.4.0/download\"],\n strip_prefix = \"difflib-0.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.difflib-0.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__digest-0.10.7\",\n sha256 = \"9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/digest/0.10.7/download\"],\n strip_prefix = \"digest-0.10.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.digest-0.10.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__displaydoc-0.2.5\",\n sha256 = \"97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/displaydoc/0.2.5/download\"],\n strip_prefix = \"displaydoc-0.2.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.displaydoc-0.2.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__double-ended-peekable-0.1.0\",\n sha256 = \"c0d05e1c0dbad51b52c38bda7adceef61b9efc2baf04acfe8726a8c4630a6f57\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/double-ended-peekable/0.1.0/download\"],\n strip_prefix = \"double-ended-peekable-0.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.double-ended-peekable-0.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__dtor-0.1.1\",\n sha256 = \"404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/dtor/0.1.1/download\"],\n strip_prefix = \"dtor-0.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.dtor-0.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__dtor-proc-macro-0.0.6\",\n sha256 = \"f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/dtor-proc-macro/0.0.6/download\"],\n strip_prefix = \"dtor-proc-macro-0.0.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.dtor-proc-macro-0.0.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__dunce-1.0.5\",\n sha256 = \"92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/dunce/1.0.5/download\"],\n strip_prefix = \"dunce-1.0.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.dunce-1.0.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__either-1.15.0\",\n sha256 = \"48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/either/1.15.0/download\"],\n strip_prefix = \"either-1.15.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.either-1.15.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__encode_unicode-1.0.0\",\n sha256 = \"34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/encode_unicode/1.0.0/download\"],\n strip_prefix = \"encode_unicode-1.0.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.encode_unicode-1.0.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__endian-type-0.1.2\",\n sha256 = \"c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/endian-type/0.1.2/download\"],\n strip_prefix = \"endian-type-0.1.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.endian-type-0.1.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__enum-as-inner-0.6.1\",\n sha256 = \"a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/enum-as-inner/0.6.1/download\"],\n strip_prefix = \"enum-as-inner-0.6.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.enum-as-inner-0.6.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__enum_dispatch-0.3.13\",\n sha256 = \"aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/enum_dispatch/0.3.13/download\"],\n strip_prefix = \"enum_dispatch-0.3.13\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.enum_dispatch-0.3.13.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__env_filter-0.1.4\",\n sha256 = \"1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/env_filter/0.1.4/download\"],\n strip_prefix = \"env_filter-0.1.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.env_filter-0.1.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__env_logger-0.11.8\",\n sha256 = \"13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/env_logger/0.11.8/download\"],\n strip_prefix = \"env_logger-0.11.8\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.env_logger-0.11.8.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__equator-0.4.2\",\n sha256 = \"4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/equator/0.4.2/download\"],\n strip_prefix = \"equator-0.4.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.equator-0.4.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__equator-macro-0.4.2\",\n sha256 = \"44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/equator-macro/0.4.2/download\"],\n strip_prefix = \"equator-macro-0.4.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.equator-macro-0.4.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__equivalent-1.0.2\",\n sha256 = \"877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/equivalent/1.0.2/download\"],\n strip_prefix = \"equivalent-1.0.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.equivalent-1.0.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__errno-0.3.14\",\n sha256 = \"39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/errno/0.3.14/download\"],\n strip_prefix = \"errno-0.3.14\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.errno-0.3.14.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ethbloom-0.14.1\",\n sha256 = \"8c321610643004cf908ec0f5f2aa0d8f1f8e14b540562a2887a1111ff1ecbf7b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ethbloom/0.14.1/download\"],\n strip_prefix = \"ethbloom-0.14.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ethbloom-0.14.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ethereum-types-0.16.0\",\n sha256 = \"f7326303c6c18bb03c7a3c4c22d4032ae60dfe673ca9109602aa4d8154b2637e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ethereum-types/0.16.0/download\"],\n strip_prefix = \"ethereum-types-0.16.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ethereum-types-0.16.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fastant-0.1.10\",\n sha256 = \"62bf7fa928ce0c4a43bd6e7d1235318fc32ac3a3dea06a2208c44e729449471a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fastant/0.1.10/download\"],\n strip_prefix = \"fastant-0.1.10\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fastant-0.1.10.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fastrace-0.7.14\",\n sha256 = \"318783b9fefe06130ab664ff1779215657586b004c0c7f3d6ece16d658936d06\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fastrace/0.7.14/download\"],\n strip_prefix = \"fastrace-0.7.14\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fastrace-0.7.14.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fastrace-macro-0.7.14\",\n sha256 = \"c7079009cf129d63c850dee732b58d7639d278a47ad99c607954ac94cfd57ef4\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fastrace-macro/0.7.14/download\"],\n strip_prefix = \"fastrace-macro-0.7.14\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fastrace-macro-0.7.14.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fastrace-opentelemetry-0.14.0\",\n sha256 = \"b7e8ec7cff0ea398352764b6ee15c0902ccabf23d823525254b52d7f878fcf60\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fastrace-opentelemetry/0.14.0/download\"],\n strip_prefix = \"fastrace-opentelemetry-0.14.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fastrace-opentelemetry-0.14.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fastrand-2.3.0\",\n sha256 = \"37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fastrand/2.3.0/download\"],\n strip_prefix = \"fastrand-2.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fastrand-2.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__find-msvc-tools-0.1.5\",\n sha256 = \"3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/find-msvc-tools/0.1.5/download\"],\n strip_prefix = \"find-msvc-tools-0.1.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.find-msvc-tools-0.1.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__findshlibs-0.10.2\",\n sha256 = \"40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/findshlibs/0.10.2/download\"],\n strip_prefix = \"findshlibs-0.10.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.findshlibs-0.10.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fixed-hash-0.8.0\",\n sha256 = \"835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fixed-hash/0.8.0/download\"],\n strip_prefix = \"fixed-hash-0.8.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fixed-hash-0.8.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fjall-2.11.2\",\n sha256 = \"0b25ad44cd4360a0448a9b5a0a6f1c7a621101cca4578706d43c9a821418aebc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fjall/2.11.2/download\"],\n strip_prefix = \"fjall-2.11.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fjall-2.11.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__float-cmp-0.10.0\",\n sha256 = \"b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/float-cmp/0.10.0/download\"],\n strip_prefix = \"float-cmp-0.10.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.float-cmp-0.10.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fnv-1.0.7\",\n sha256 = \"3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fnv/1.0.7/download\"],\n strip_prefix = \"fnv-1.0.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fnv-1.0.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__foldhash-0.1.5\",\n sha256 = \"d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/foldhash/0.1.5/download\"],\n strip_prefix = \"foldhash-0.1.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.foldhash-0.1.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__foldhash-0.2.0\",\n sha256 = \"77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/foldhash/0.2.0/download\"],\n strip_prefix = \"foldhash-0.2.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.foldhash-0.2.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__form_urlencoded-1.2.2\",\n sha256 = \"cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/form_urlencoded/1.2.2/download\"],\n strip_prefix = \"form_urlencoded-1.2.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.form_urlencoded-1.2.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__fs_extra-1.3.0\",\n sha256 = \"42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/fs_extra/1.3.0/download\"],\n strip_prefix = \"fs_extra-1.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.fs_extra-1.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__funty-2.0.0\",\n sha256 = \"e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/funty/2.0.0/download\"],\n strip_prefix = \"funty-2.0.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.funty-2.0.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-0.3.31\",\n sha256 = \"65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures/0.3.31/download\"],\n strip_prefix = \"futures-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-channel-0.3.31\",\n sha256 = \"2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures-channel/0.3.31/download\"],\n strip_prefix = \"futures-channel-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-channel-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-core-0.3.31\",\n sha256 = \"05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures-core/0.3.31/download\"],\n strip_prefix = \"futures-core-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-core-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-executor-0.3.31\",\n sha256 = \"1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures-executor/0.3.31/download\"],\n strip_prefix = \"futures-executor-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-executor-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-io-0.3.31\",\n sha256 = \"9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures-io/0.3.31/download\"],\n strip_prefix = \"futures-io-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-io-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-macro-0.3.31\",\n sha256 = \"162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures-macro/0.3.31/download\"],\n strip_prefix = \"futures-macro-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-macro-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-sink-0.3.31\",\n sha256 = \"e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures-sink/0.3.31/download\"],\n strip_prefix = \"futures-sink-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-sink-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-task-0.3.31\",\n sha256 = \"f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures-task/0.3.31/download\"],\n strip_prefix = \"futures-task-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-task-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__futures-util-0.3.31\",\n sha256 = \"9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/futures-util/0.3.31/download\"],\n strip_prefix = \"futures-util-0.3.31\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.futures-util-0.3.31.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__generic-array-0.14.7\",\n sha256 = \"85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/generic-array/0.14.7/download\"],\n strip_prefix = \"generic-array-0.14.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.generic-array-0.14.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__getrandom-0.2.16\",\n sha256 = \"335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/getrandom/0.2.16/download\"],\n strip_prefix = \"getrandom-0.2.16\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.getrandom-0.2.16.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__getrandom-0.3.4\",\n sha256 = \"899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/getrandom/0.3.4/download\"],\n strip_prefix = \"getrandom-0.3.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.getrandom-0.3.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__gimli-0.32.3\",\n sha256 = \"e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/gimli/0.32.3/download\"],\n strip_prefix = \"gimli-0.32.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.gimli-0.32.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__glob-0.3.3\",\n sha256 = \"0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/glob/0.3.3/download\"],\n strip_prefix = \"glob-0.3.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.glob-0.3.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__guardian-1.3.0\",\n sha256 = \"17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/guardian/1.3.0/download\"],\n strip_prefix = \"guardian-1.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.guardian-1.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__h2-0.4.12\",\n sha256 = \"f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/h2/0.4.12/download\"],\n strip_prefix = \"h2-0.4.12\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.h2-0.4.12.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__half-2.7.1\",\n sha256 = \"6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/half/2.7.1/download\"],\n strip_prefix = \"half-2.7.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.half-2.7.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hash-db-0.16.0\",\n sha256 = \"8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hash-db/0.16.0/download\"],\n strip_prefix = \"hash-db-0.16.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hash-db-0.16.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hash256-std-hasher-0.15.2\",\n sha256 = \"92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hash256-std-hasher/0.15.2/download\"],\n strip_prefix = \"hash256-std-hasher-0.15.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hash256-std-hasher-0.15.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hashbrown-0.14.5\",\n sha256 = \"e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hashbrown/0.14.5/download\"],\n strip_prefix = \"hashbrown-0.14.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hashbrown-0.14.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hashbrown-0.15.5\",\n sha256 = \"9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hashbrown/0.15.5/download\"],\n strip_prefix = \"hashbrown-0.15.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hashbrown-0.15.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hashbrown-0.16.0\",\n sha256 = \"5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hashbrown/0.16.0/download\"],\n strip_prefix = \"hashbrown-0.16.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hashbrown-0.16.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__heck-0.5.0\",\n sha256 = \"2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/heck/0.5.0/download\"],\n strip_prefix = \"heck-0.5.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.heck-0.5.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hermit-abi-0.5.2\",\n sha256 = \"fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hermit-abi/0.5.2/download\"],\n strip_prefix = \"hermit-abi-0.5.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hermit-abi-0.5.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hex-0.4.3\",\n sha256 = \"7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hex/0.4.3/download\"],\n strip_prefix = \"hex-0.4.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hex-0.4.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hex-literal-1.1.0\",\n sha256 = \"e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hex-literal/1.1.0/download\"],\n strip_prefix = \"hex-literal-1.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hex-literal-1.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__http-1.3.1\",\n sha256 = \"f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/http/1.3.1/download\"],\n strip_prefix = \"http-1.3.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.http-1.3.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__http-body-1.0.1\",\n sha256 = \"1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/http-body/1.0.1/download\"],\n strip_prefix = \"http-body-1.0.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.http-body-1.0.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__http-body-util-0.1.3\",\n sha256 = \"b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/http-body-util/0.1.3/download\"],\n strip_prefix = \"http-body-util-0.1.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.http-body-util-0.1.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__httparse-1.10.1\",\n sha256 = \"6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/httparse/1.10.1/download\"],\n strip_prefix = \"httparse-1.10.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.httparse-1.10.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__httpdate-1.0.3\",\n sha256 = \"df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/httpdate/1.0.3/download\"],\n strip_prefix = \"httpdate-1.0.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.httpdate-1.0.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hyper-1.8.1\",\n sha256 = \"2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hyper/1.8.1/download\"],\n strip_prefix = \"hyper-1.8.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hyper-1.8.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hyper-rustls-0.27.7\",\n sha256 = \"e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hyper-rustls/0.27.7/download\"],\n strip_prefix = \"hyper-rustls-0.27.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hyper-rustls-0.27.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hyper-timeout-0.5.2\",\n sha256 = \"2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hyper-timeout/0.5.2/download\"],\n strip_prefix = \"hyper-timeout-0.5.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hyper-timeout-0.5.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__hyper-util-0.1.18\",\n sha256 = \"52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/hyper-util/0.1.18/download\"],\n strip_prefix = \"hyper-util-0.1.18\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.hyper-util-0.1.18.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__iana-time-zone-0.1.64\",\n sha256 = \"33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/iana-time-zone/0.1.64/download\"],\n strip_prefix = \"iana-time-zone-0.1.64\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.iana-time-zone-0.1.64.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__iana-time-zone-haiku-0.1.2\",\n sha256 = \"f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/iana-time-zone-haiku/0.1.2/download\"],\n strip_prefix = \"iana-time-zone-haiku-0.1.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.iana-time-zone-haiku-0.1.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__icu_collections-2.1.1\",\n sha256 = \"4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/icu_collections/2.1.1/download\"],\n strip_prefix = \"icu_collections-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.icu_collections-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__icu_locale_core-2.1.1\",\n sha256 = \"edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/icu_locale_core/2.1.1/download\"],\n strip_prefix = \"icu_locale_core-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.icu_locale_core-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__icu_normalizer-2.1.1\",\n sha256 = \"5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/icu_normalizer/2.1.1/download\"],\n strip_prefix = \"icu_normalizer-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.icu_normalizer-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__icu_normalizer_data-2.1.1\",\n sha256 = \"7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/icu_normalizer_data/2.1.1/download\"],\n strip_prefix = \"icu_normalizer_data-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.icu_normalizer_data-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__icu_properties-2.1.1\",\n sha256 = \"e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/icu_properties/2.1.1/download\"],\n strip_prefix = \"icu_properties-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.icu_properties-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__icu_properties_data-2.1.1\",\n sha256 = \"02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/icu_properties_data/2.1.1/download\"],\n strip_prefix = \"icu_properties_data-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.icu_properties_data-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__icu_provider-2.1.1\",\n sha256 = \"85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/icu_provider/2.1.1/download\"],\n strip_prefix = \"icu_provider-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.icu_provider-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__idna-1.1.0\",\n sha256 = \"3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/idna/1.1.0/download\"],\n strip_prefix = \"idna-1.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.idna-1.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__idna_adapter-1.2.1\",\n sha256 = \"3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/idna_adapter/1.2.1/download\"],\n strip_prefix = \"idna_adapter-1.2.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.idna_adapter-1.2.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__impl-codec-0.7.1\",\n sha256 = \"2d40b9d5e17727407e55028eafc22b2dc68781786e6d7eb8a21103f5058e3a14\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/impl-codec/0.7.1/download\"],\n strip_prefix = \"impl-codec-0.7.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.impl-codec-0.7.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__impl-rlp-0.4.0\",\n sha256 = \"54ed8ad1f3877f7e775b8cbf30ed1bd3209a95401817f19a0eb4402d13f8cf90\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/impl-rlp/0.4.0/download\"],\n strip_prefix = \"impl-rlp-0.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.impl-rlp-0.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__impl-serde-0.5.0\",\n sha256 = \"4a143eada6a1ec4aefa5049037a26a6d597bfd64f8c026d07b77133e02b7dd0b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/impl-serde/0.5.0/download\"],\n strip_prefix = \"impl-serde-0.5.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.impl-serde-0.5.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__impl-trait-for-tuples-0.2.3\",\n sha256 = \"a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/impl-trait-for-tuples/0.2.3/download\"],\n strip_prefix = \"impl-trait-for-tuples-0.2.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.impl-trait-for-tuples-0.2.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__include_dir-0.7.4\",\n sha256 = \"923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/include_dir/0.7.4/download\"],\n strip_prefix = \"include_dir-0.7.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.include_dir-0.7.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__include_dir_macros-0.7.4\",\n sha256 = \"7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/include_dir_macros/0.7.4/download\"],\n strip_prefix = \"include_dir_macros-0.7.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.include_dir_macros-0.7.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__indexmap-2.12.0\",\n sha256 = \"6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/indexmap/2.12.0/download\"],\n strip_prefix = \"indexmap-2.12.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.indexmap-2.12.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__indicatif-0.18.3\",\n sha256 = \"9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/indicatif/0.18.3/download\"],\n strip_prefix = \"indicatif-0.18.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.indicatif-0.18.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__inferno-0.11.21\",\n sha256 = \"232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/inferno/0.11.21/download\"],\n strip_prefix = \"inferno-0.11.21\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.inferno-0.11.21.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__integer-encoding-4.1.0\",\n sha256 = \"14c00403deb17c3221a1fe4fb571b9ed0370b3dcd116553c77fa294a3d918699\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/integer-encoding/4.1.0/download\"],\n strip_prefix = \"integer-encoding-4.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.integer-encoding-4.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__interval-heap-0.0.5\",\n sha256 = \"11274e5e8e89b8607cfedc2910b6626e998779b48a019151c7604d0adcb86ac6\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/interval-heap/0.0.5/download\"],\n strip_prefix = \"interval-heap-0.0.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.interval-heap-0.0.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__io-uring-0.7.11\",\n sha256 = \"fdd7bddefd0a8833b88a4b68f90dae22c7450d11b354198baee3874fd811b344\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/io-uring/0.7.11/download\"],\n strip_prefix = \"io-uring-0.7.11\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.io-uring-0.7.11.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ipnet-2.11.0\",\n sha256 = \"469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ipnet/2.11.0/download\"],\n strip_prefix = \"ipnet-2.11.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ipnet-2.11.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__iri-string-0.7.9\",\n sha256 = \"4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/iri-string/0.7.9/download\"],\n strip_prefix = \"iri-string-0.7.9\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.iri-string-0.7.9.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__is-terminal-0.4.17\",\n sha256 = \"3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/is-terminal/0.4.17/download\"],\n strip_prefix = \"is-terminal-0.4.17\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.is-terminal-0.4.17.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__is_terminal_polyfill-1.70.2\",\n sha256 = \"a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/is_terminal_polyfill/1.70.2/download\"],\n strip_prefix = \"is_terminal_polyfill-1.70.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.is_terminal_polyfill-1.70.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__itertools-0.10.5\",\n sha256 = \"b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/itertools/0.10.5/download\"],\n strip_prefix = \"itertools-0.10.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.itertools-0.10.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__itertools-0.13.0\",\n sha256 = \"413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/itertools/0.13.0/download\"],\n strip_prefix = \"itertools-0.13.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.itertools-0.13.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__itertools-0.14.0\",\n sha256 = \"2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/itertools/0.14.0/download\"],\n strip_prefix = \"itertools-0.14.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.itertools-0.14.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__itoa-1.0.15\",\n sha256 = \"4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/itoa/1.0.15/download\"],\n strip_prefix = \"itoa-1.0.15\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.itoa-1.0.15.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__jiff-0.2.16\",\n sha256 = \"49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/jiff/0.2.16/download\"],\n strip_prefix = \"jiff-0.2.16\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.jiff-0.2.16.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__jiff-static-0.2.16\",\n sha256 = \"980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/jiff-static/0.2.16/download\"],\n strip_prefix = \"jiff-static-0.2.16\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.jiff-static-0.2.16.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__jobserver-0.1.34\",\n sha256 = \"9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/jobserver/0.1.34/download\"],\n strip_prefix = \"jobserver-0.1.34\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.jobserver-0.1.34.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__js-sys-0.3.82\",\n sha256 = \"b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/js-sys/0.3.82/download\"],\n strip_prefix = \"js-sys-0.3.82\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.js-sys-0.3.82.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__keccak-0.1.5\",\n sha256 = \"ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/keccak/0.1.5/download\"],\n strip_prefix = \"keccak-0.1.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.keccak-0.1.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__keccak-hasher-0.16.0\",\n sha256 = \"19ea4653859ca2266a86419d3f592d3f22e7a854b482f99180d2498507902048\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/keccak-hasher/0.16.0/download\"],\n strip_prefix = \"keccak-hasher-0.16.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.keccak-hasher-0.16.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__lazy_static-1.5.0\",\n sha256 = \"bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/lazy_static/1.5.0/download\"],\n strip_prefix = \"lazy_static-1.5.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.lazy_static-1.5.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__libc-0.2.177\",\n sha256 = \"2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/libc/0.2.177/download\"],\n strip_prefix = \"libc-0.2.177\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.libc-0.2.177.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__libloading-0.8.9\",\n sha256 = \"d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/libloading/0.8.9/download\"],\n strip_prefix = \"libloading-0.8.9\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.libloading-0.8.9.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__libm-0.2.15\",\n sha256 = \"f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/libm/0.2.15/download\"],\n strip_prefix = \"libm-0.2.15\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.libm-0.2.15.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__linux-raw-sys-0.11.0\",\n sha256 = \"df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/linux-raw-sys/0.11.0/download\"],\n strip_prefix = \"linux-raw-sys-0.11.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.linux-raw-sys-0.11.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__litemap-0.8.1\",\n sha256 = \"6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/litemap/0.8.1/download\"],\n strip_prefix = \"litemap-0.8.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.litemap-0.8.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__lock_api-0.4.14\",\n sha256 = \"224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/lock_api/0.4.14/download\"],\n strip_prefix = \"lock_api-0.4.14\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.lock_api-0.4.14.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__log-0.4.28\",\n sha256 = \"34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/log/0.4.28/download\"],\n strip_prefix = \"log-0.4.28\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.log-0.4.28.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__lru-0.16.2\",\n sha256 = \"96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/lru/0.16.2/download\"],\n strip_prefix = \"lru-0.16.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.lru-0.16.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__lsm-tree-2.10.4\",\n sha256 = \"799399117a2bfb37660e08be33f470958babb98386b04185288d829df362ea15\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/lsm-tree/2.10.4/download\"],\n strip_prefix = \"lsm-tree-2.10.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.lsm-tree-2.10.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__lz4_flex-0.11.5\",\n sha256 = \"08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/lz4_flex/0.11.5/download\"],\n strip_prefix = \"lz4_flex-0.11.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.lz4_flex-0.11.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__memchr-2.7.6\",\n sha256 = \"f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/memchr/2.7.6/download\"],\n strip_prefix = \"memchr-2.7.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.memchr-2.7.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__memmap2-0.9.9\",\n sha256 = \"744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/memmap2/0.9.9/download\"],\n strip_prefix = \"memmap2-0.9.9\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.memmap2-0.9.9.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__metrics-0.24.2\",\n sha256 = \"25dea7ac8057892855ec285c440160265225438c3c45072613c25a4b26e98ef5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/metrics/0.24.2/download\"],\n strip_prefix = \"metrics-0.24.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.metrics-0.24.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__metrics-exporter-prometheus-0.17.2\",\n sha256 = \"2b166dea96003ee2531cf14833efedced545751d800f03535801d833313f8c15\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/metrics-exporter-prometheus/0.17.2/download\"],\n strip_prefix = \"metrics-exporter-prometheus-0.17.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.metrics-exporter-prometheus-0.17.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__metrics-util-0.20.0\",\n sha256 = \"fe8db7a05415d0f919ffb905afa37784f71901c9a773188876984b4f769ab986\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/metrics-util/0.20.0/download\"],\n strip_prefix = \"metrics-util-0.20.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.metrics-util-0.20.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__minimal-lexical-0.2.1\",\n sha256 = \"68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/minimal-lexical/0.2.1/download\"],\n strip_prefix = \"minimal-lexical-0.2.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.minimal-lexical-0.2.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__miniz_oxide-0.8.9\",\n sha256 = \"1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/miniz_oxide/0.8.9/download\"],\n strip_prefix = \"miniz_oxide-0.8.9\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.miniz_oxide-0.8.9.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__mio-1.1.0\",\n sha256 = \"69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/mio/1.1.0/download\"],\n strip_prefix = \"mio-1.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.mio-1.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__nibble_vec-0.1.0\",\n sha256 = \"77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/nibble_vec/0.1.0/download\"],\n strip_prefix = \"nibble_vec-0.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.nibble_vec-0.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__nix-0.26.4\",\n sha256 = \"598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/nix/0.26.4/download\"],\n strip_prefix = \"nix-0.26.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.nix-0.26.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__nom-7.1.3\",\n sha256 = \"d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/nom/7.1.3/download\"],\n strip_prefix = \"nom-7.1.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.nom-7.1.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__nonzero_ext-0.3.0\",\n sha256 = \"38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/nonzero_ext/0.3.0/download\"],\n strip_prefix = \"nonzero_ext-0.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.nonzero_ext-0.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__normalize-line-endings-0.3.0\",\n sha256 = \"61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/normalize-line-endings/0.3.0/download\"],\n strip_prefix = \"normalize-line-endings-0.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.normalize-line-endings-0.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__num-format-0.4.4\",\n sha256 = \"a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/num-format/0.4.4/download\"],\n strip_prefix = \"num-format-0.4.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.num-format-0.4.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__num-traits-0.2.19\",\n sha256 = \"071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/num-traits/0.2.19/download\"],\n strip_prefix = \"num-traits-0.2.19\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.num-traits-0.2.19.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__object-0.37.3\",\n sha256 = \"ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/object/0.37.3/download\"],\n strip_prefix = \"object-0.37.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.object-0.37.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__once_cell-1.21.3\",\n sha256 = \"42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/once_cell/1.21.3/download\"],\n strip_prefix = \"once_cell-1.21.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.once_cell-1.21.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__once_cell_polyfill-1.70.2\",\n sha256 = \"384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/once_cell_polyfill/1.70.2/download\"],\n strip_prefix = \"once_cell_polyfill-1.70.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.once_cell_polyfill-1.70.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__oorandom-11.1.5\",\n sha256 = \"d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/oorandom/11.1.5/download\"],\n strip_prefix = \"oorandom-11.1.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.oorandom-11.1.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__openssl-probe-0.1.6\",\n sha256 = \"d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/openssl-probe/0.1.6/download\"],\n strip_prefix = \"openssl-probe-0.1.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.openssl-probe-0.1.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__opentelemetry-0.31.0\",\n sha256 = \"b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/opentelemetry/0.31.0/download\"],\n strip_prefix = \"opentelemetry-0.31.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.opentelemetry-0.31.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__opentelemetry-http-0.31.0\",\n sha256 = \"d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/opentelemetry-http/0.31.0/download\"],\n strip_prefix = \"opentelemetry-http-0.31.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.opentelemetry-http-0.31.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__opentelemetry-otlp-0.31.0\",\n sha256 = \"7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/opentelemetry-otlp/0.31.0/download\"],\n strip_prefix = \"opentelemetry-otlp-0.31.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.opentelemetry-otlp-0.31.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__opentelemetry-proto-0.31.0\",\n sha256 = \"a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/opentelemetry-proto/0.31.0/download\"],\n strip_prefix = \"opentelemetry-proto-0.31.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.opentelemetry-proto-0.31.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__opentelemetry_sdk-0.31.0\",\n sha256 = \"e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/opentelemetry_sdk/0.31.0/download\"],\n strip_prefix = \"opentelemetry_sdk-0.31.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.opentelemetry_sdk-0.31.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ordered-float-4.6.0\",\n sha256 = \"7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ordered-float/4.6.0/download\"],\n strip_prefix = \"ordered-float-4.6.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ordered-float-4.6.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__oxhttp-0.3.1\",\n sha256 = \"971c03797806d47915950e62816a8f365e3ddc8800310e3200ec666934d0f7c9\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/oxhttp/0.3.1/download\"],\n strip_prefix = \"oxhttp-0.3.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.oxhttp-0.3.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__parity-scale-codec-3.7.5\",\n sha256 = \"799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/parity-scale-codec/3.7.5/download\"],\n strip_prefix = \"parity-scale-codec-3.7.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.parity-scale-codec-3.7.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__parity-scale-codec-derive-3.7.5\",\n sha256 = \"34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/parity-scale-codec-derive/3.7.5/download\"],\n strip_prefix = \"parity-scale-codec-derive-3.7.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.parity-scale-codec-derive-3.7.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__parking_lot-0.12.5\",\n sha256 = \"93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/parking_lot/0.12.5/download\"],\n strip_prefix = \"parking_lot-0.12.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.parking_lot-0.12.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__parking_lot_core-0.9.12\",\n sha256 = \"2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/parking_lot_core/0.9.12/download\"],\n strip_prefix = \"parking_lot_core-0.9.12\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.parking_lot_core-0.9.12.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__path-absolutize-3.1.1\",\n sha256 = \"e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/path-absolutize/3.1.1/download\"],\n strip_prefix = \"path-absolutize-3.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.path-absolutize-3.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__path-dedot-3.1.1\",\n sha256 = \"07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/path-dedot/3.1.1/download\"],\n strip_prefix = \"path-dedot-3.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.path-dedot-3.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__percent-encoding-2.3.2\",\n sha256 = \"9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/percent-encoding/2.3.2/download\"],\n strip_prefix = \"percent-encoding-2.3.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.percent-encoding-2.3.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__pin-project-1.1.10\",\n sha256 = \"677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/pin-project/1.1.10/download\"],\n strip_prefix = \"pin-project-1.1.10\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.pin-project-1.1.10.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__pin-project-internal-1.1.10\",\n sha256 = \"6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/pin-project-internal/1.1.10/download\"],\n strip_prefix = \"pin-project-internal-1.1.10\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.pin-project-internal-1.1.10.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__pin-project-lite-0.2.16\",\n sha256 = \"3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/pin-project-lite/0.2.16/download\"],\n strip_prefix = \"pin-project-lite-0.2.16\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.pin-project-lite-0.2.16.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__pin-utils-0.1.0\",\n sha256 = \"8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/pin-utils/0.1.0/download\"],\n strip_prefix = \"pin-utils-0.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.pin-utils-0.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__plain_hasher-0.2.3\",\n sha256 = \"1e19e6491bdde87c2c43d70f4c194bc8a758f2eb732df00f61e43f7362e3b4cc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/plain_hasher/0.2.3/download\"],\n strip_prefix = \"plain_hasher-0.2.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.plain_hasher-0.2.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__plotters-0.3.7\",\n sha256 = \"5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/plotters/0.3.7/download\"],\n strip_prefix = \"plotters-0.3.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.plotters-0.3.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__plotters-backend-0.3.7\",\n sha256 = \"df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/plotters-backend/0.3.7/download\"],\n strip_prefix = \"plotters-backend-0.3.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.plotters-backend-0.3.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__plotters-svg-0.3.7\",\n sha256 = \"51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/plotters-svg/0.3.7/download\"],\n strip_prefix = \"plotters-svg-0.3.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.plotters-svg-0.3.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__pollster-0.4.0\",\n sha256 = \"2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/pollster/0.4.0/download\"],\n strip_prefix = \"pollster-0.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.pollster-0.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__portable-atomic-1.11.1\",\n sha256 = \"f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/portable-atomic/1.11.1/download\"],\n strip_prefix = \"portable-atomic-1.11.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.portable-atomic-1.11.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__portable-atomic-util-0.2.4\",\n sha256 = \"d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/portable-atomic-util/0.2.4/download\"],\n strip_prefix = \"portable-atomic-util-0.2.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.portable-atomic-util-0.2.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__potential_utf-0.1.4\",\n sha256 = \"b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/potential_utf/0.1.4/download\"],\n strip_prefix = \"potential_utf-0.1.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.potential_utf-0.1.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__pprof-0.15.0\",\n sha256 = \"38a01da47675efa7673b032bf8efd8214f1917d89685e07e395ab125ea42b187\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/pprof/0.15.0/download\"],\n strip_prefix = \"pprof-0.15.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.pprof-0.15.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ppv-lite86-0.2.21\",\n sha256 = \"85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ppv-lite86/0.2.21/download\"],\n strip_prefix = \"ppv-lite86-0.2.21\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ppv-lite86-0.2.21.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__predicates-3.1.3\",\n sha256 = \"a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/predicates/3.1.3/download\"],\n strip_prefix = \"predicates-3.1.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.predicates-3.1.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__predicates-core-1.0.9\",\n sha256 = \"727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/predicates-core/1.0.9/download\"],\n strip_prefix = \"predicates-core-1.0.9\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.predicates-core-1.0.9.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__predicates-tree-1.0.12\",\n sha256 = \"72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/predicates-tree/1.0.12/download\"],\n strip_prefix = \"predicates-tree-1.0.12\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.predicates-tree-1.0.12.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__pretty-duration-0.1.1\",\n sha256 = \"d8868e7264af614b3634ff0abbe37b178e61000611b8a75221aea40221924aba\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/pretty-duration/0.1.1/download\"],\n strip_prefix = \"pretty-duration-0.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.pretty-duration-0.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__prettyplease-0.2.37\",\n sha256 = \"479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/prettyplease/0.2.37/download\"],\n strip_prefix = \"prettyplease-0.2.37\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.prettyplease-0.2.37.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__primitive-types-0.14.0\",\n sha256 = \"721a1da530b5a2633218dc9f75713394c983c352be88d2d7c9ee85e2c4c21794\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/primitive-types/0.14.0/download\"],\n strip_prefix = \"primitive-types-0.14.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.primitive-types-0.14.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__proc-macro-crate-3.4.0\",\n sha256 = \"219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/proc-macro-crate/3.4.0/download\"],\n strip_prefix = \"proc-macro-crate-3.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.proc-macro-crate-3.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__proc-macro-error-attr2-2.0.0\",\n sha256 = \"96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/proc-macro-error-attr2/2.0.0/download\"],\n strip_prefix = \"proc-macro-error-attr2-2.0.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.proc-macro-error-attr2-2.0.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__proc-macro-error2-2.0.1\",\n sha256 = \"11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/proc-macro-error2/2.0.1/download\"],\n strip_prefix = \"proc-macro-error2-2.0.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.proc-macro-error2-2.0.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__proc-macro2-1.0.103\",\n sha256 = \"5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/proc-macro2/1.0.103/download\"],\n strip_prefix = \"proc-macro2-1.0.103\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.proc-macro2-1.0.103.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__proptest-1.9.0\",\n sha256 = \"bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/proptest/1.9.0/download\"],\n strip_prefix = \"proptest-1.9.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.proptest-1.9.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__prost-0.14.1\",\n sha256 = \"7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/prost/0.14.1/download\"],\n strip_prefix = \"prost-0.14.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.prost-0.14.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__prost-derive-0.14.1\",\n sha256 = \"9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/prost-derive/0.14.1/download\"],\n strip_prefix = \"prost-derive-0.14.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.prost-derive-0.14.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__quanta-0.12.6\",\n sha256 = \"f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/quanta/0.12.6/download\"],\n strip_prefix = \"quanta-0.12.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.quanta-0.12.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__quick-xml-0.26.0\",\n sha256 = \"7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/quick-xml/0.26.0/download\"],\n strip_prefix = \"quick-xml-0.26.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.quick-xml-0.26.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__quick_cache-0.6.18\",\n sha256 = \"7ada44a88ef953a3294f6eb55d2007ba44646015e18613d2f213016379203ef3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/quick_cache/0.6.18/download\"],\n strip_prefix = \"quick_cache-0.6.18\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.quick_cache-0.6.18.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__quote-1.0.42\",\n sha256 = \"a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/quote/1.0.42/download\"],\n strip_prefix = \"quote-1.0.42\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.quote-1.0.42.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__r-efi-5.3.0\",\n sha256 = \"69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/r-efi/5.3.0/download\"],\n strip_prefix = \"r-efi-5.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.r-efi-5.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__radium-0.7.0\",\n sha256 = \"dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/radium/0.7.0/download\"],\n strip_prefix = \"radium-0.7.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.radium-0.7.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__radix_trie-0.2.1\",\n sha256 = \"c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/radix_trie/0.2.1/download\"],\n strip_prefix = \"radix_trie-0.2.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.radix_trie-0.2.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand-0.8.5\",\n sha256 = \"34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand/0.8.5/download\"],\n strip_prefix = \"rand-0.8.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand-0.8.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand-0.9.2\",\n sha256 = \"6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand/0.9.2/download\"],\n strip_prefix = \"rand-0.9.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand-0.9.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand_chacha-0.3.1\",\n sha256 = \"e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand_chacha/0.3.1/download\"],\n strip_prefix = \"rand_chacha-0.3.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand_chacha-0.3.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand_chacha-0.9.0\",\n sha256 = \"d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand_chacha/0.9.0/download\"],\n strip_prefix = \"rand_chacha-0.9.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand_chacha-0.9.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand_core-0.6.4\",\n sha256 = \"ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand_core/0.6.4/download\"],\n strip_prefix = \"rand_core-0.6.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand_core-0.6.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand_core-0.9.3\",\n sha256 = \"99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand_core/0.9.3/download\"],\n strip_prefix = \"rand_core-0.9.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand_core-0.9.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand_distr-0.5.1\",\n sha256 = \"6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand_distr/0.5.1/download\"],\n strip_prefix = \"rand_distr-0.5.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand_distr-0.5.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand_xorshift-0.4.0\",\n sha256 = \"513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand_xorshift/0.4.0/download\"],\n strip_prefix = \"rand_xorshift-0.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand_xorshift-0.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rand_xoshiro-0.7.0\",\n sha256 = \"f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rand_xoshiro/0.7.0/download\"],\n strip_prefix = \"rand_xoshiro-0.7.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rand_xoshiro-0.7.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__raw-cpuid-11.6.0\",\n sha256 = \"498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/raw-cpuid/11.6.0/download\"],\n strip_prefix = \"raw-cpuid-11.6.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.raw-cpuid-11.6.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rayon-1.11.0\",\n sha256 = \"368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rayon/1.11.0/download\"],\n strip_prefix = \"rayon-1.11.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rayon-1.11.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rayon-core-1.13.0\",\n sha256 = \"22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rayon-core/1.13.0/download\"],\n strip_prefix = \"rayon-core-1.13.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rayon-core-1.13.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__redox_syscall-0.5.18\",\n sha256 = \"ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/redox_syscall/0.5.18/download\"],\n strip_prefix = \"redox_syscall-0.5.18\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.redox_syscall-0.5.18.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__regex-1.12.2\",\n sha256 = \"843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/regex/1.12.2/download\"],\n strip_prefix = \"regex-1.12.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.regex-1.12.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__regex-automata-0.4.13\",\n sha256 = \"5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/regex-automata/0.4.13/download\"],\n strip_prefix = \"regex-automata-0.4.13\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.regex-automata-0.4.13.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__regex-syntax-0.8.8\",\n sha256 = \"7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/regex-syntax/0.8.8/download\"],\n strip_prefix = \"regex-syntax-0.8.8\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.regex-syntax-0.8.8.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__reqwest-0.12.24\",\n sha256 = \"9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/reqwest/0.12.24/download\"],\n strip_prefix = \"reqwest-0.12.24\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.reqwest-0.12.24.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rgb-0.8.52\",\n sha256 = \"0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rgb/0.8.52/download\"],\n strip_prefix = \"rgb-0.8.52\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rgb-0.8.52.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ring-0.17.14\",\n sha256 = \"a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ring/0.17.14/download\"],\n strip_prefix = \"ring-0.17.14\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ring-0.17.14.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rlp-0.6.1\",\n sha256 = \"fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rlp/0.6.1/download\"],\n strip_prefix = \"rlp-0.6.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rlp-0.6.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rtrb-0.3.2\",\n sha256 = \"ad8388ea1a9e0ea807e442e8263a699e7edcb320ecbcd21b4fa8ff859acce3ba\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rtrb/0.3.2/download\"],\n strip_prefix = \"rtrb-0.3.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rtrb-0.3.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustc-demangle-0.1.26\",\n sha256 = \"56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustc-demangle/0.1.26/download\"],\n strip_prefix = \"rustc-demangle-0.1.26\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustc-demangle-0.1.26.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustc-hash-2.1.1\",\n sha256 = \"357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustc-hash/2.1.1/download\"],\n strip_prefix = \"rustc-hash-2.1.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustc-hash-2.1.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustc-hex-2.1.0\",\n sha256 = \"3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustc-hex/2.1.0/download\"],\n strip_prefix = \"rustc-hex-2.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustc-hex-2.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustix-1.1.2\",\n sha256 = \"cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustix/1.1.2/download\"],\n strip_prefix = \"rustix-1.1.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustix-1.1.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustls-0.23.35\",\n sha256 = \"533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustls/0.23.35/download\"],\n strip_prefix = \"rustls-0.23.35\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustls-0.23.35.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustls-native-certs-0.8.2\",\n sha256 = \"9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustls-native-certs/0.8.2/download\"],\n strip_prefix = \"rustls-native-certs-0.8.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustls-native-certs-0.8.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustls-pki-types-1.13.0\",\n sha256 = \"94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustls-pki-types/1.13.0/download\"],\n strip_prefix = \"rustls-pki-types-1.13.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustls-pki-types-1.13.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustls-webpki-0.103.8\",\n sha256 = \"2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustls-webpki/0.103.8/download\"],\n strip_prefix = \"rustls-webpki-0.103.8\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustls-webpki-0.103.8.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__rustversion-1.0.22\",\n sha256 = \"b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/rustversion/1.0.22/download\"],\n strip_prefix = \"rustversion-1.0.22\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.rustversion-1.0.22.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__ryu-1.0.20\",\n sha256 = \"28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/ryu/1.0.20/download\"],\n strip_prefix = \"ryu-1.0.20\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.ryu-1.0.20.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__same-file-1.0.6\",\n sha256 = \"93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/same-file/1.0.6/download\"],\n strip_prefix = \"same-file-1.0.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.same-file-1.0.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__scc-2.4.0\",\n sha256 = \"46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/scc/2.4.0/download\"],\n strip_prefix = \"scc-2.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.scc-2.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__schannel-0.1.28\",\n sha256 = \"891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/schannel/0.1.28/download\"],\n strip_prefix = \"schannel-0.1.28\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.schannel-0.1.28.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__scopeguard-1.2.0\",\n sha256 = \"94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/scopeguard/1.2.0/download\"],\n strip_prefix = \"scopeguard-1.2.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.scopeguard-1.2.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__sdd-3.0.10\",\n sha256 = \"490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/sdd/3.0.10/download\"],\n strip_prefix = \"sdd-3.0.10\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.sdd-3.0.10.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__security-framework-3.5.1\",\n sha256 = \"b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/security-framework/3.5.1/download\"],\n strip_prefix = \"security-framework-3.5.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.security-framework-3.5.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__security-framework-sys-2.15.0\",\n sha256 = \"cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/security-framework-sys/2.15.0/download\"],\n strip_prefix = \"security-framework-sys-2.15.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.security-framework-sys-2.15.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__self_cell-1.2.1\",\n sha256 = \"16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/self_cell/1.2.1/download\"],\n strip_prefix = \"self_cell-1.2.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.self_cell-1.2.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__semver-1.0.27\",\n sha256 = \"d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/semver/1.0.27/download\"],\n strip_prefix = \"semver-1.0.27\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.semver-1.0.27.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__serde-1.0.228\",\n sha256 = \"9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/serde/1.0.228/download\"],\n strip_prefix = \"serde-1.0.228\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.serde-1.0.228.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__serde_core-1.0.228\",\n sha256 = \"41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/serde_core/1.0.228/download\"],\n strip_prefix = \"serde_core-1.0.228\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.serde_core-1.0.228.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__serde_derive-1.0.228\",\n sha256 = \"d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/serde_derive/1.0.228/download\"],\n strip_prefix = \"serde_derive-1.0.228\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.serde_derive-1.0.228.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__serde_json-1.0.145\",\n sha256 = \"402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/serde_json/1.0.145/download\"],\n strip_prefix = \"serde_json-1.0.145\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.serde_json-1.0.145.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__serde_spanned-1.0.3\",\n sha256 = \"e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/serde_spanned/1.0.3/download\"],\n strip_prefix = \"serde_spanned-1.0.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.serde_spanned-1.0.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__serde_urlencoded-0.7.1\",\n sha256 = \"d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/serde_urlencoded/0.7.1/download\"],\n strip_prefix = \"serde_urlencoded-0.7.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.serde_urlencoded-0.7.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__serial_test-3.2.0\",\n sha256 = \"1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/serial_test/3.2.0/download\"],\n strip_prefix = \"serial_test-3.2.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.serial_test-3.2.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__serial_test_derive-3.2.0\",\n sha256 = \"5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/serial_test_derive/3.2.0/download\"],\n strip_prefix = \"serial_test_derive-3.2.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.serial_test_derive-3.2.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__sha2-0.10.9\",\n sha256 = \"a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/sha2/0.10.9/download\"],\n strip_prefix = \"sha2-0.10.9\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.sha2-0.10.9.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__sha3-0.10.8\",\n sha256 = \"75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/sha3/0.10.8/download\"],\n strip_prefix = \"sha3-0.10.8\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.sha3-0.10.8.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__shlex-1.3.0\",\n sha256 = \"0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/shlex/1.3.0/download\"],\n strip_prefix = \"shlex-1.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.shlex-1.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__sketches-ddsketch-0.3.0\",\n sha256 = \"c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/sketches-ddsketch/0.3.0/download\"],\n strip_prefix = \"sketches-ddsketch-0.3.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.sketches-ddsketch-0.3.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__slab-0.4.11\",\n sha256 = \"7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/slab/0.4.11/download\"],\n strip_prefix = \"slab-0.4.11\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.slab-0.4.11.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__small_ctor-0.1.2\",\n sha256 = \"88414a5ca1f85d82cc34471e975f0f74f6aa54c40f062efa42c0080e7f763f81\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/small_ctor/0.1.2/download\"],\n strip_prefix = \"small_ctor-0.1.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.small_ctor-0.1.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__smallvec-1.15.1\",\n sha256 = \"67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/smallvec/1.15.1/download\"],\n strip_prefix = \"smallvec-1.15.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.smallvec-1.15.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__socket2-0.6.1\",\n sha256 = \"17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/socket2/0.6.1/download\"],\n strip_prefix = \"socket2-0.6.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.socket2-0.6.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__spin-0.10.0\",\n sha256 = \"d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/spin/0.10.0/download\"],\n strip_prefix = \"spin-0.10.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.spin-0.10.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__stable_deref_trait-1.2.1\",\n sha256 = \"6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/stable_deref_trait/1.2.1/download\"],\n strip_prefix = \"stable_deref_trait-1.2.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.stable_deref_trait-1.2.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__static_assertions-1.1.0\",\n sha256 = \"a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/static_assertions/1.1.0/download\"],\n strip_prefix = \"static_assertions-1.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.static_assertions-1.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__std-semaphore-0.1.0\",\n sha256 = \"33ae9eec00137a8eed469fb4148acd9fc6ac8c3f9b110f52cd34698c8b5bfa0e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/std-semaphore/0.1.0/download\"],\n strip_prefix = \"std-semaphore-0.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.std-semaphore-0.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__str_stack-0.1.0\",\n sha256 = \"9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/str_stack/0.1.0/download\"],\n strip_prefix = \"str_stack-0.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.str_stack-0.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__strsim-0.11.1\",\n sha256 = \"7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/strsim/0.11.1/download\"],\n strip_prefix = \"strsim-0.11.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.strsim-0.11.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__subtle-2.6.1\",\n sha256 = \"13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/subtle/2.6.1/download\"],\n strip_prefix = \"subtle-2.6.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.subtle-2.6.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__symbolic-common-12.17.0\",\n sha256 = \"b3d8046c5674ab857104bc4559d505f4809b8060d57806e45d49737c97afeb60\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/symbolic-common/12.17.0/download\"],\n strip_prefix = \"symbolic-common-12.17.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.symbolic-common-12.17.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__symbolic-demangle-12.17.0\",\n sha256 = \"1accb6e5c4b0f682de907623912e616b44be1c9e725775155546669dbff720ec\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/symbolic-demangle/12.17.0/download\"],\n strip_prefix = \"symbolic-demangle-12.17.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.symbolic-demangle-12.17.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__syn-2.0.110\",\n sha256 = \"a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/syn/2.0.110/download\"],\n strip_prefix = \"syn-2.0.110\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.syn-2.0.110.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__sync_wrapper-1.0.2\",\n sha256 = \"0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/sync_wrapper/1.0.2/download\"],\n strip_prefix = \"sync_wrapper-1.0.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.sync_wrapper-1.0.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__synstructure-0.13.2\",\n sha256 = \"728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/synstructure/0.13.2/download\"],\n strip_prefix = \"synstructure-0.13.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.synstructure-0.13.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tap-1.0.1\",\n sha256 = \"55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tap/1.0.1/download\"],\n strip_prefix = \"tap-1.0.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tap-1.0.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__target-triple-1.0.0\",\n sha256 = \"591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/target-triple/1.0.0/download\"],\n strip_prefix = \"target-triple-1.0.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.target-triple-1.0.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tempfile-3.23.0\",\n sha256 = \"2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tempfile/3.23.0/download\"],\n strip_prefix = \"tempfile-3.23.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tempfile-3.23.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__termcolor-1.4.1\",\n sha256 = \"06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/termcolor/1.4.1/download\"],\n strip_prefix = \"termcolor-1.4.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.termcolor-1.4.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__termtree-0.5.1\",\n sha256 = \"8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/termtree/0.5.1/download\"],\n strip_prefix = \"termtree-0.5.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.termtree-0.5.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__test-case-3.3.1\",\n sha256 = \"eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/test-case/3.3.1/download\"],\n strip_prefix = \"test-case-3.3.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.test-case-3.3.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__test-case-core-3.3.1\",\n sha256 = \"adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/test-case-core/3.3.1/download\"],\n strip_prefix = \"test-case-core-3.3.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.test-case-core-3.3.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__test-case-macros-3.3.1\",\n sha256 = \"5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/test-case-macros/3.3.1/download\"],\n strip_prefix = \"test-case-macros-3.3.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.test-case-macros-3.3.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__thiserror-2.0.17\",\n sha256 = \"f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/thiserror/2.0.17/download\"],\n strip_prefix = \"thiserror-2.0.17\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.thiserror-2.0.17.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__thiserror-impl-2.0.17\",\n sha256 = \"3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/thiserror-impl/2.0.17/download\"],\n strip_prefix = \"thiserror-impl-2.0.17\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.thiserror-impl-2.0.17.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tikv-jemalloc-sys-0.6.1-5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7\",\n sha256 = \"cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tikv-jemalloc-sys/0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7/download\"],\n strip_prefix = \"tikv-jemalloc-sys-0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tikv-jemalloc-sys-0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tikv-jemallocator-0.6.1\",\n sha256 = \"0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tikv-jemallocator/0.6.1/download\"],\n strip_prefix = \"tikv-jemallocator-0.6.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tikv-jemallocator-0.6.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tiny-keccak-2.0.2\",\n sha256 = \"2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tiny-keccak/2.0.2/download\"],\n strip_prefix = \"tiny-keccak-2.0.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tiny-keccak-2.0.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tinystr-0.8.2\",\n sha256 = \"42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tinystr/0.8.2/download\"],\n strip_prefix = \"tinystr-0.8.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tinystr-0.8.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tinytemplate-1.2.1\",\n sha256 = \"be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tinytemplate/1.2.1/download\"],\n strip_prefix = \"tinytemplate-1.2.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tinytemplate-1.2.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tokio-1.48.0\",\n sha256 = \"ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tokio/1.48.0/download\"],\n strip_prefix = \"tokio-1.48.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tokio-1.48.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tokio-rustls-0.26.4\",\n sha256 = \"1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tokio-rustls/0.26.4/download\"],\n strip_prefix = \"tokio-rustls-0.26.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tokio-rustls-0.26.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tokio-stream-0.1.17\",\n sha256 = \"eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tokio-stream/0.1.17/download\"],\n strip_prefix = \"tokio-stream-0.1.17\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tokio-stream-0.1.17.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tokio-util-0.7.17\",\n sha256 = \"2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tokio-util/0.7.17/download\"],\n strip_prefix = \"tokio-util-0.7.17\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tokio-util-0.7.17.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__toml-0.9.8\",\n sha256 = \"f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/toml/0.9.8/download\"],\n strip_prefix = \"toml-0.9.8\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.toml-0.9.8.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__toml_datetime-0.7.3\",\n sha256 = \"f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/toml_datetime/0.7.3/download\"],\n strip_prefix = \"toml_datetime-0.7.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.toml_datetime-0.7.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__toml_edit-0.23.7\",\n sha256 = \"6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/toml_edit/0.23.7/download\"],\n strip_prefix = \"toml_edit-0.23.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.toml_edit-0.23.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__toml_parser-1.0.4\",\n sha256 = \"c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/toml_parser/1.0.4/download\"],\n strip_prefix = \"toml_parser-1.0.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.toml_parser-1.0.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__toml_writer-1.0.4\",\n sha256 = \"df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/toml_writer/1.0.4/download\"],\n strip_prefix = \"toml_writer-1.0.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.toml_writer-1.0.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tonic-0.14.2\",\n sha256 = \"eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tonic/0.14.2/download\"],\n strip_prefix = \"tonic-0.14.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tonic-0.14.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tonic-prost-0.14.2\",\n sha256 = \"66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tonic-prost/0.14.2/download\"],\n strip_prefix = \"tonic-prost-0.14.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tonic-prost-0.14.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tower-0.5.2\",\n sha256 = \"d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tower/0.5.2/download\"],\n strip_prefix = \"tower-0.5.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tower-0.5.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tower-http-0.6.6\",\n sha256 = \"adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tower-http/0.6.6/download\"],\n strip_prefix = \"tower-http-0.6.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tower-http-0.6.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tower-layer-0.3.3\",\n sha256 = \"121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tower-layer/0.3.3/download\"],\n strip_prefix = \"tower-layer-0.3.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tower-layer-0.3.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tower-service-0.3.3\",\n sha256 = \"8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tower-service/0.3.3/download\"],\n strip_prefix = \"tower-service-0.3.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tower-service-0.3.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tracing-0.1.41\",\n sha256 = \"784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tracing/0.1.41/download\"],\n strip_prefix = \"tracing-0.1.41\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tracing-0.1.41.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tracing-attributes-0.1.30\",\n sha256 = \"81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tracing-attributes/0.1.30/download\"],\n strip_prefix = \"tracing-attributes-0.1.30\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tracing-attributes-0.1.30.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__tracing-core-0.1.34\",\n sha256 = \"b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/tracing-core/0.1.34/download\"],\n strip_prefix = \"tracing-core-0.1.34\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.tracing-core-0.1.34.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__trie-standardmap-0.16.0\",\n sha256 = \"684aafb332fae6f83d7fe10b3fbfdbe39a1b3234c4e2a618f030815838519516\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/trie-standardmap/0.16.0/download\"],\n strip_prefix = \"trie-standardmap-0.16.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.trie-standardmap-0.16.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__triomphe-0.1.15\",\n sha256 = \"dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/triomphe/0.1.15/download\"],\n strip_prefix = \"triomphe-0.1.15\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.triomphe-0.1.15.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__try-lock-0.2.5\",\n sha256 = \"e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/try-lock/0.2.5/download\"],\n strip_prefix = \"try-lock-0.2.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.try-lock-0.2.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__trybuild-1.0.114\",\n sha256 = \"3e17e807bff86d2a06b52bca4276746584a78375055b6e45843925ce2802b335\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/trybuild/1.0.114/download\"],\n strip_prefix = \"trybuild-1.0.114\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.trybuild-1.0.114.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__typed-builder-0.23.1\",\n sha256 = \"1cce8e9c8115897e896894868ad4ae6851eff0fb7fd33fa95610e0fa93211886\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/typed-builder/0.23.1/download\"],\n strip_prefix = \"typed-builder-0.23.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.typed-builder-0.23.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__typed-builder-macro-0.23.1\",\n sha256 = \"921d52b8b19b1a455f54fa76a925a1cf49c0d6a7c6b232fc58523400d1f91560\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/typed-builder-macro/0.23.1/download\"],\n strip_prefix = \"typed-builder-macro-0.23.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.typed-builder-macro-0.23.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__typenum-1.19.0\",\n sha256 = \"562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/typenum/1.19.0/download\"],\n strip_prefix = \"typenum-1.19.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.typenum-1.19.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__uint-0.10.0\",\n sha256 = \"909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/uint/0.10.0/download\"],\n strip_prefix = \"uint-0.10.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.uint-0.10.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__unarray-0.1.4\",\n sha256 = \"eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/unarray/0.1.4/download\"],\n strip_prefix = \"unarray-0.1.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.unarray-0.1.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__unicode-ident-1.0.22\",\n sha256 = \"9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/unicode-ident/1.0.22/download\"],\n strip_prefix = \"unicode-ident-1.0.22\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.unicode-ident-1.0.22.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__unicode-width-0.2.2\",\n sha256 = \"b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/unicode-width/0.2.2/download\"],\n strip_prefix = \"unicode-width-0.2.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.unicode-width-0.2.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__unicode-xid-0.2.6\",\n sha256 = \"ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/unicode-xid/0.2.6/download\"],\n strip_prefix = \"unicode-xid-0.2.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.unicode-xid-0.2.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__unit-prefix-0.5.2\",\n sha256 = \"81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/unit-prefix/0.5.2/download\"],\n strip_prefix = \"unit-prefix-0.5.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.unit-prefix-0.5.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__untrusted-0.9.0\",\n sha256 = \"8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/untrusted/0.9.0/download\"],\n strip_prefix = \"untrusted-0.9.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.untrusted-0.9.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__url-2.5.7\",\n sha256 = \"08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/url/2.5.7/download\"],\n strip_prefix = \"url-2.5.7\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.url-2.5.7.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__utf8_iter-1.0.4\",\n sha256 = \"b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/utf8_iter/1.0.4/download\"],\n strip_prefix = \"utf8_iter-1.0.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.utf8_iter-1.0.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__utf8parse-0.2.2\",\n sha256 = \"06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/utf8parse/0.2.2/download\"],\n strip_prefix = \"utf8parse-0.2.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.utf8parse-0.2.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__uuid-1.18.1\",\n sha256 = \"2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/uuid/1.18.1/download\"],\n strip_prefix = \"uuid-1.18.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.uuid-1.18.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__value-log-1.9.0\",\n sha256 = \"62fc7c4ce161f049607ecea654dca3f2d727da5371ae85e2e4f14ce2b98ed67c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/value-log/1.9.0/download\"],\n strip_prefix = \"value-log-1.9.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.value-log-1.9.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__varint-rs-2.2.0\",\n sha256 = \"8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/varint-rs/2.2.0/download\"],\n strip_prefix = \"varint-rs-2.2.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.varint-rs-2.2.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__version_check-0.9.5\",\n sha256 = \"0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/version_check/0.9.5/download\"],\n strip_prefix = \"version_check-0.9.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.version_check-0.9.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wait-timeout-0.2.1\",\n sha256 = \"09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wait-timeout/0.2.1/download\"],\n strip_prefix = \"wait-timeout-0.2.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wait-timeout-0.2.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__walkdir-2.5.0\",\n sha256 = \"29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/walkdir/2.5.0/download\"],\n strip_prefix = \"walkdir-2.5.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.walkdir-2.5.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__want-0.3.1\",\n sha256 = \"bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/want/0.3.1/download\"],\n strip_prefix = \"want-0.3.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.want-0.3.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wasi-0.11.1-wasi-snapshot-preview1\",\n sha256 = \"ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wasi/0.11.1+wasi-snapshot-preview1/download\"],\n strip_prefix = \"wasi-0.11.1+wasi-snapshot-preview1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wasi-0.11.1+wasi-snapshot-preview1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wasip2-1.0.1-wasi-0.2.4\",\n sha256 = \"0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wasip2/1.0.1+wasi-0.2.4/download\"],\n strip_prefix = \"wasip2-1.0.1+wasi-0.2.4\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wasip2-1.0.1+wasi-0.2.4.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wasix-0.12.21\",\n sha256 = \"c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wasix/0.12.21/download\"],\n strip_prefix = \"wasix-0.12.21\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wasix-0.12.21.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wasm-bindgen-0.2.105\",\n sha256 = \"da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wasm-bindgen/0.2.105/download\"],\n strip_prefix = \"wasm-bindgen-0.2.105\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wasm-bindgen-0.2.105.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wasm-bindgen-futures-0.4.55\",\n sha256 = \"551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wasm-bindgen-futures/0.4.55/download\"],\n strip_prefix = \"wasm-bindgen-futures-0.4.55\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wasm-bindgen-futures-0.4.55.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wasm-bindgen-macro-0.2.105\",\n sha256 = \"04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wasm-bindgen-macro/0.2.105/download\"],\n strip_prefix = \"wasm-bindgen-macro-0.2.105\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wasm-bindgen-macro-0.2.105.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wasm-bindgen-macro-support-0.2.105\",\n sha256 = \"420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wasm-bindgen-macro-support/0.2.105/download\"],\n strip_prefix = \"wasm-bindgen-macro-support-0.2.105\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wasm-bindgen-macro-support-0.2.105.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wasm-bindgen-shared-0.2.105\",\n sha256 = \"76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wasm-bindgen-shared/0.2.105/download\"],\n strip_prefix = \"wasm-bindgen-shared-0.2.105\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wasm-bindgen-shared-0.2.105.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__weak-table-0.3.2\",\n sha256 = \"323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/weak-table/0.3.2/download\"],\n strip_prefix = \"weak-table-0.3.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.weak-table-0.3.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__web-sys-0.3.82\",\n sha256 = \"3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/web-sys/0.3.82/download\"],\n strip_prefix = \"web-sys-0.3.82\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.web-sys-0.3.82.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__web-time-1.1.0\",\n sha256 = \"5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/web-time/1.1.0/download\"],\n strip_prefix = \"web-time-1.1.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.web-time-1.1.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__winapi-0.3.9\",\n sha256 = \"5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/winapi/0.3.9/download\"],\n strip_prefix = \"winapi-0.3.9\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.winapi-0.3.9.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__winapi-i686-pc-windows-gnu-0.4.0\",\n sha256 = \"ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/winapi-i686-pc-windows-gnu/0.4.0/download\"],\n strip_prefix = \"winapi-i686-pc-windows-gnu-0.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.winapi-i686-pc-windows-gnu-0.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__winapi-util-0.1.11\",\n sha256 = \"c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/winapi-util/0.1.11/download\"],\n strip_prefix = \"winapi-util-0.1.11\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.winapi-util-0.1.11.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__winapi-x86_64-pc-windows-gnu-0.4.0\",\n sha256 = \"712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/winapi-x86_64-pc-windows-gnu/0.4.0/download\"],\n strip_prefix = \"winapi-x86_64-pc-windows-gnu-0.4.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.winapi-x86_64-pc-windows-gnu-0.4.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-core-0.62.2\",\n sha256 = \"b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-core/0.62.2/download\"],\n strip_prefix = \"windows-core-0.62.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-core-0.62.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-implement-0.60.2\",\n sha256 = \"053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-implement/0.60.2/download\"],\n strip_prefix = \"windows-implement-0.60.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-implement-0.60.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-interface-0.59.3\",\n sha256 = \"3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-interface/0.59.3/download\"],\n strip_prefix = \"windows-interface-0.59.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-interface-0.59.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-link-0.2.1\",\n sha256 = \"f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-link/0.2.1/download\"],\n strip_prefix = \"windows-link-0.2.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-link-0.2.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-result-0.4.1\",\n sha256 = \"7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-result/0.4.1/download\"],\n strip_prefix = \"windows-result-0.4.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-result-0.4.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-strings-0.5.1\",\n sha256 = \"7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-strings/0.5.1/download\"],\n strip_prefix = \"windows-strings-0.5.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-strings-0.5.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-sys-0.52.0\",\n sha256 = \"282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-sys/0.52.0/download\"],\n strip_prefix = \"windows-sys-0.52.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-sys-0.52.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-sys-0.60.2\",\n sha256 = \"f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-sys/0.60.2/download\"],\n strip_prefix = \"windows-sys-0.60.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-sys-0.60.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-sys-0.61.2\",\n sha256 = \"ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-sys/0.61.2/download\"],\n strip_prefix = \"windows-sys-0.61.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-sys-0.61.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-targets-0.52.6\",\n sha256 = \"9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-targets/0.52.6/download\"],\n strip_prefix = \"windows-targets-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-targets-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows-targets-0.53.5\",\n sha256 = \"4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows-targets/0.53.5/download\"],\n strip_prefix = \"windows-targets-0.53.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows-targets-0.53.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_aarch64_gnullvm-0.52.6\",\n sha256 = \"32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_aarch64_gnullvm/0.52.6/download\"],\n strip_prefix = \"windows_aarch64_gnullvm-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_aarch64_gnullvm-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_aarch64_gnullvm-0.53.1\",\n sha256 = \"a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_aarch64_gnullvm/0.53.1/download\"],\n strip_prefix = \"windows_aarch64_gnullvm-0.53.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_aarch64_gnullvm-0.53.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_aarch64_msvc-0.52.6\",\n sha256 = \"09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_aarch64_msvc/0.52.6/download\"],\n strip_prefix = \"windows_aarch64_msvc-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_aarch64_msvc-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_aarch64_msvc-0.53.1\",\n sha256 = \"b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_aarch64_msvc/0.53.1/download\"],\n strip_prefix = \"windows_aarch64_msvc-0.53.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_aarch64_msvc-0.53.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_i686_gnu-0.52.6\",\n sha256 = \"8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_i686_gnu/0.52.6/download\"],\n strip_prefix = \"windows_i686_gnu-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_i686_gnu-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_i686_gnu-0.53.1\",\n sha256 = \"960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_i686_gnu/0.53.1/download\"],\n strip_prefix = \"windows_i686_gnu-0.53.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_i686_gnu-0.53.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_i686_gnullvm-0.52.6\",\n sha256 = \"0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_i686_gnullvm/0.52.6/download\"],\n strip_prefix = \"windows_i686_gnullvm-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_i686_gnullvm-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_i686_gnullvm-0.53.1\",\n sha256 = \"fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_i686_gnullvm/0.53.1/download\"],\n strip_prefix = \"windows_i686_gnullvm-0.53.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_i686_gnullvm-0.53.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_i686_msvc-0.52.6\",\n sha256 = \"240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_i686_msvc/0.52.6/download\"],\n strip_prefix = \"windows_i686_msvc-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_i686_msvc-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_i686_msvc-0.53.1\",\n sha256 = \"1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_i686_msvc/0.53.1/download\"],\n strip_prefix = \"windows_i686_msvc-0.53.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_i686_msvc-0.53.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_x86_64_gnu-0.52.6\",\n sha256 = \"147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_x86_64_gnu/0.52.6/download\"],\n strip_prefix = \"windows_x86_64_gnu-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_x86_64_gnu-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_x86_64_gnu-0.53.1\",\n sha256 = \"9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_x86_64_gnu/0.53.1/download\"],\n strip_prefix = \"windows_x86_64_gnu-0.53.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_x86_64_gnu-0.53.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_x86_64_gnullvm-0.52.6\",\n sha256 = \"24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_x86_64_gnullvm/0.52.6/download\"],\n strip_prefix = \"windows_x86_64_gnullvm-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_x86_64_gnullvm-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_x86_64_gnullvm-0.53.1\",\n sha256 = \"0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_x86_64_gnullvm/0.53.1/download\"],\n strip_prefix = \"windows_x86_64_gnullvm-0.53.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_x86_64_gnullvm-0.53.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_x86_64_msvc-0.52.6\",\n sha256 = \"589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_x86_64_msvc/0.52.6/download\"],\n strip_prefix = \"windows_x86_64_msvc-0.52.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_x86_64_msvc-0.52.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__windows_x86_64_msvc-0.53.1\",\n sha256 = \"d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/windows_x86_64_msvc/0.53.1/download\"],\n strip_prefix = \"windows_x86_64_msvc-0.53.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.windows_x86_64_msvc-0.53.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__winnow-0.7.13\",\n sha256 = \"21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/winnow/0.7.13/download\"],\n strip_prefix = \"winnow-0.7.13\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.winnow-0.7.13.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wit-bindgen-0.46.0\",\n sha256 = \"f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wit-bindgen/0.46.0/download\"],\n strip_prefix = \"wit-bindgen-0.46.0\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wit-bindgen-0.46.0.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__writeable-0.6.2\",\n sha256 = \"9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/writeable/0.6.2/download\"],\n strip_prefix = \"writeable-0.6.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.writeable-0.6.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__wyz-0.5.1\",\n sha256 = \"05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/wyz/0.5.1/download\"],\n strip_prefix = \"wyz-0.5.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.wyz-0.5.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__xxhash-rust-0.8.15\",\n sha256 = \"fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/xxhash-rust/0.8.15/download\"],\n strip_prefix = \"xxhash-rust-0.8.15\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.xxhash-rust-0.8.15.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__yoke-0.8.1\",\n sha256 = \"72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/yoke/0.8.1/download\"],\n strip_prefix = \"yoke-0.8.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.yoke-0.8.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__yoke-derive-0.8.1\",\n sha256 = \"b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/yoke-derive/0.8.1/download\"],\n strip_prefix = \"yoke-derive-0.8.1\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.yoke-derive-0.8.1.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__zerocopy-0.8.27\",\n sha256 = \"0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/zerocopy/0.8.27/download\"],\n strip_prefix = \"zerocopy-0.8.27\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.zerocopy-0.8.27.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__zerocopy-derive-0.8.27\",\n sha256 = \"88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/zerocopy-derive/0.8.27/download\"],\n strip_prefix = \"zerocopy-derive-0.8.27\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.zerocopy-derive-0.8.27.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__zerofrom-0.1.6\",\n sha256 = \"50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/zerofrom/0.1.6/download\"],\n strip_prefix = \"zerofrom-0.1.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.zerofrom-0.1.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__zerofrom-derive-0.1.6\",\n sha256 = \"d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/zerofrom-derive/0.1.6/download\"],\n strip_prefix = \"zerofrom-derive-0.1.6\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.zerofrom-derive-0.1.6.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__zeroize-1.8.2\",\n sha256 = \"b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/zeroize/1.8.2/download\"],\n strip_prefix = \"zeroize-1.8.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.zeroize-1.8.2.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__zerotrie-0.2.3\",\n sha256 = \"2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/zerotrie/0.2.3/download\"],\n strip_prefix = \"zerotrie-0.2.3\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.zerotrie-0.2.3.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__zerovec-0.11.5\",\n sha256 = \"6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/zerovec/0.11.5/download\"],\n strip_prefix = \"zerovec-0.11.5\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.zerovec-0.11.5.bazel\"),\n )\n\n maybe(\n http_archive,\n name = \"firewood_crates__zerovec-derive-0.11.2\",\n sha256 = \"eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3\",\n type = \"tar.gz\",\n urls = [\"https://static.crates.io/crates/zerovec-derive/0.11.2/download\"],\n strip_prefix = \"zerovec-derive-0.11.2\",\n build_file = Label(\"@firewood_crates//firewood_crates:BUILD.zerovec-derive-0.11.2.bazel\"),\n )\n\n return [\n struct(repo=\"firewood_crates__aquamarine-0.6.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__askama-0.14.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__bitfield-0.19.4\", is_dev_dep = False),\n struct(repo=\"firewood_crates__bitflags-2.10.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__bumpalo-3.19.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__bytemuck-1.24.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__bytemuck_derive-1.10.2\", is_dev_dep = False),\n struct(repo=\"firewood_crates__bytes-1.11.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__cbindgen-0.29.2\", is_dev_dep = False),\n struct(repo=\"firewood_crates__chrono-0.4.42\", is_dev_dep = False),\n struct(repo=\"firewood_crates__clap-4.5.52\", is_dev_dep = False),\n struct(repo=\"firewood_crates__coarsetime-0.1.36\", is_dev_dep = False),\n struct(repo=\"firewood_crates__csv-1.4.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__derive-where-1.6.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__enum-as-inner-0.6.1\", is_dev_dep = False),\n struct(repo=\"firewood_crates__env_logger-0.11.8\", is_dev_dep = False),\n struct(repo=\"firewood_crates__fastrace-0.7.14\", is_dev_dep = False),\n struct(repo=\"firewood_crates__fastrace-opentelemetry-0.14.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__fjall-2.11.2\", is_dev_dep = False),\n struct(repo=\"firewood_crates__hash-db-0.16.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__hex-0.4.3\", is_dev_dep = False),\n struct(repo=\"firewood_crates__indicatif-0.18.3\", is_dev_dep = False),\n struct(repo=\"firewood_crates__integer-encoding-4.1.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__io-uring-0.7.11\", is_dev_dep = False),\n struct(repo=\"firewood_crates__log-0.4.28\", is_dev_dep = False),\n struct(repo=\"firewood_crates__lru-0.16.2\", is_dev_dep = False),\n struct(repo=\"firewood_crates__metrics-0.24.2\", is_dev_dep = False),\n struct(repo=\"firewood_crates__metrics-exporter-prometheus-0.17.2\", is_dev_dep = False),\n struct(repo=\"firewood_crates__metrics-util-0.20.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__nonzero_ext-0.3.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__num-format-0.4.4\", is_dev_dep = False),\n struct(repo=\"firewood_crates__opentelemetry-0.31.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__opentelemetry-otlp-0.31.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__opentelemetry-proto-0.31.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__opentelemetry_sdk-0.31.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__oxhttp-0.3.1\", is_dev_dep = False),\n struct(repo=\"firewood_crates__parking_lot-0.12.5\", is_dev_dep = False),\n struct(repo=\"firewood_crates__pretty-duration-0.1.1\", is_dev_dep = False),\n struct(repo=\"firewood_crates__proc-macro2-1.0.103\", is_dev_dep = False),\n struct(repo=\"firewood_crates__quote-1.0.42\", is_dev_dep = False),\n struct(repo=\"firewood_crates__rand-0.9.2\", is_dev_dep = False),\n struct(repo=\"firewood_crates__rand_distr-0.5.1\", is_dev_dep = False),\n struct(repo=\"firewood_crates__rayon-1.11.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__rlp-0.6.1\", is_dev_dep = False),\n struct(repo=\"firewood_crates__semver-1.0.27\", is_dev_dep = False),\n struct(repo=\"firewood_crates__sha2-0.10.9\", is_dev_dep = False),\n struct(repo=\"firewood_crates__smallvec-1.15.1\", is_dev_dep = False),\n struct(repo=\"firewood_crates__syn-2.0.110\", is_dev_dep = False),\n struct(repo=\"firewood_crates__thiserror-2.0.17\", is_dev_dep = False),\n struct(repo=\"firewood_crates__tikv-jemallocator-0.6.1\", is_dev_dep = False),\n struct(repo=\"firewood_crates__tokio-1.48.0\", is_dev_dep = False),\n struct(repo=\"firewood_crates__triomphe-0.1.15\", is_dev_dep = False),\n struct(repo=\"firewood_crates__typed-builder-0.23.1\", is_dev_dep = False),\n struct(repo=\"firewood_crates__weak-table-0.3.2\", is_dev_dep = False),\n struct(repo = \"firewood_crates__anyhow-1.0.100\", is_dev_dep = True),\n struct(repo = \"firewood_crates__assert_cmd-2.1.1\", is_dev_dep = True),\n struct(repo = \"firewood_crates__criterion-0.7.0\", is_dev_dep = True),\n struct(repo = \"firewood_crates__ctor-0.6.1\", is_dev_dep = True),\n struct(repo = \"firewood_crates__ethereum-types-0.16.0\", is_dev_dep = True),\n struct(repo = \"firewood_crates__hex-literal-1.1.0\", is_dev_dep = True),\n struct(repo = \"firewood_crates__keccak-hasher-0.16.0\", is_dev_dep = True),\n struct(repo = \"firewood_crates__plain_hasher-0.2.3\", is_dev_dep = True),\n struct(repo = \"firewood_crates__pprof-0.15.0\", is_dev_dep = True),\n struct(repo = \"firewood_crates__predicates-3.1.3\", is_dev_dep = True),\n struct(repo = \"firewood_crates__serial_test-3.2.0\", is_dev_dep = True),\n struct(repo = \"firewood_crates__sha3-0.10.8\", is_dev_dep = True),\n struct(repo = \"firewood_crates__tempfile-3.23.0\", is_dev_dep = True),\n struct(repo = \"firewood_crates__test-case-3.3.1\", is_dev_dep = True),\n struct(repo = \"firewood_crates__tiny-keccak-2.0.2\", is_dev_dep = True),\n struct(repo = \"firewood_crates__trie-standardmap-0.16.0\", is_dev_dep = True),\n struct(repo = \"firewood_crates__trybuild-1.0.114\", is_dev_dep = True),\n ]\n" + } + } + }, + "firewood_crates__addr2line-0.25.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/addr2line/0.25.1/download" + ], + "strip_prefix": "addr2line-0.25.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"addr2line\",\n deps = [\n \"@firewood_crates__gimli-0.32.3//:gimli\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=addr2line\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.25.1\",\n)\n" + } + }, + "firewood_crates__adler2-2.0.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/adler2/2.0.1/download" + ], + "strip_prefix": "adler2-2.0.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"adler2\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=adler2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.0.1\",\n)\n" + } + }, + "firewood_crates__ahash-0.8.12": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ahash/0.8.12/download" + ], + "strip_prefix": "ahash-0.8.12", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ahash\",\n deps = [\n \"@firewood_crates__ahash-0.8.12//:build_script_build\",\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__getrandom-0.3.4//:getrandom\",\n \"@firewood_crates__zerocopy-0.8.27//:zerocopy\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\", # cfg(not(all(target_arch = \"arm\", target_os = \"none\")))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\", # cfg(not(all(target_arch = \"arm\", target_os = \"none\")))\n ],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\", # cfg(not(all(target_arch = \"arm\", target_os = \"none\")))\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\", # cfg(not(all(target_arch = \"arm\", target_os = \"none\")))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\", # cfg(not(all(target_arch = \"arm\", target_os = \"none\")))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\", # cfg(not(all(target_arch = \"arm\", target_os = \"none\")))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\", # cfg(not(all(target_arch = \"arm\", target_os = \"none\")))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"getrandom\",\n \"runtime-rng\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ahash\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.12\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"getrandom\",\n \"runtime-rng\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__version_check-0.9.5//:version_check\",\n ],\n edition = \"2018\",\n pkg_name = \"ahash\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ahash\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.8.12\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__aho-corasick-1.1.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/aho-corasick/1.1.4/download" + ], + "strip_prefix": "aho-corasick-1.1.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"aho_corasick\",\n deps = [\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"perf-literal\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=aho-corasick\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.4\",\n)\n" + } + }, + "firewood_crates__aligned-vec-0.6.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/aligned-vec/0.6.4/download" + ], + "strip_prefix": "aligned-vec-0.6.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"aligned_vec\",\n deps = [\n \"@firewood_crates__equator-0.4.2//:equator\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=aligned-vec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.4\",\n)\n" + } + }, + "firewood_crates__allocator-api2-0.2.21": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/allocator-api2/0.2.21/download" + ], + "strip_prefix": "allocator-api2-0.2.21", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"allocator_api2\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=allocator-api2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.21\",\n)\n" + } + }, + "firewood_crates__android_system_properties-0.1.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/android_system_properties/0.1.5/download" + ], + "strip_prefix": "android_system_properties-0.1.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"android_system_properties\",\n deps = [\n \"@firewood_crates__libc-0.2.177//:libc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=android_system_properties\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.5\",\n)\n" + } + }, + "firewood_crates__anes-0.1.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/anes/0.1.6/download" + ], + "strip_prefix": "anes-0.1.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"anes\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=anes\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.6\",\n)\n" + } + }, + "firewood_crates__anstream-0.6.21": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/anstream/0.6.21/download" + ], + "strip_prefix": "anstream-0.6.21", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"anstream\",\n deps = [\n \"@firewood_crates__anstyle-1.0.13//:anstyle\",\n \"@firewood_crates__anstyle-parse-0.2.7//:anstyle_parse\",\n \"@firewood_crates__anstyle-query-1.1.5//:anstyle_query\",\n \"@firewood_crates__colorchoice-1.0.4//:colorchoice\",\n \"@firewood_crates__is_terminal_polyfill-1.70.2//:is_terminal_polyfill\",\n \"@firewood_crates__utf8parse-0.2.2//:utf8parse\",\n ] + select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__anstyle-wincon-3.0.11//:anstyle_wincon\", # x86_64-pc-windows-msvc\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"auto\",\n \"default\",\n \"wincon\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=anstream\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.21\",\n)\n" + } + }, + "firewood_crates__anstyle-1.0.13": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/anstyle/1.0.13/download" + ], + "strip_prefix": "anstyle-1.0.13", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"anstyle\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=anstyle\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.13\",\n)\n" + } + }, + "firewood_crates__anstyle-parse-0.2.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/anstyle-parse/0.2.7/download" + ], + "strip_prefix": "anstyle-parse-0.2.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"anstyle_parse\",\n deps = [\n \"@firewood_crates__utf8parse-0.2.2//:utf8parse\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"utf8\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=anstyle-parse\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.7\",\n)\n" + } + }, + "firewood_crates__anstyle-query-1.1.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/anstyle-query/1.1.5/download" + ], + "strip_prefix": "anstyle-query-1.1.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"anstyle_query\",\n deps = select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=anstyle-query\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.5\",\n)\n" + } + }, + "firewood_crates__anstyle-wincon-3.0.11": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/anstyle-wincon/3.0.11/download" + ], + "strip_prefix": "anstyle-wincon-3.0.11", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"anstyle_wincon\",\n deps = [\n \"@firewood_crates__anstyle-1.0.13//:anstyle\",\n ] + select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__once_cell_polyfill-1.70.2//:once_cell_polyfill\", # cfg(windows)\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=anstyle-wincon\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.0.11\",\n)\n" + } + }, + "firewood_crates__anyhow-1.0.100": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/anyhow/1.0.100/download" + ], + "strip_prefix": "anyhow-1.0.100", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"anyhow\",\n deps = [\n \"@firewood_crates__anyhow-1.0.100//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=anyhow\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.100\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"anyhow\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=anyhow\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.0.100\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__aquamarine-0.6.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0f50776554130342de4836ba542aa85a4ddb361690d7e8df13774d7284c3d5c2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/aquamarine/0.6.0/download" + ], + "strip_prefix": "aquamarine-0.6.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"aquamarine\",\n deps = [\n \"@firewood_crates__include_dir-0.7.4//:include_dir\",\n \"@firewood_crates__itertools-0.10.5//:itertools\",\n \"@firewood_crates__proc-macro-error2-2.0.1//:proc_macro_error2\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=aquamarine\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.0\",\n)\n" + } + }, + "firewood_crates__arrayvec-0.7.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/arrayvec/0.7.6/download" + ], + "strip_prefix": "arrayvec-0.7.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"arrayvec\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=arrayvec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.6\",\n)\n" + } + }, + "firewood_crates__askama-0.14.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/askama/0.14.0/download" + ], + "strip_prefix": "askama-0.14.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"askama\",\n deps = [\n \"@firewood_crates__itoa-1.0.15//:itoa\",\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__askama_derive-0.14.0//:askama_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"config\",\n \"default\",\n \"derive\",\n \"std\",\n \"urlencode\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=askama\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.0\",\n)\n" + } + }, + "firewood_crates__askama_derive-0.14.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/askama_derive/0.14.0/download" + ], + "strip_prefix": "askama_derive-0.14.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"askama_derive\",\n deps = [\n \"@firewood_crates__askama_parser-0.14.0//:askama_parser\",\n \"@firewood_crates__basic-toml-0.1.10//:basic_toml\",\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__rustc-hash-2.1.1//:rustc_hash\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__serde_derive-1.0.228//:serde_derive\",\n ],\n aliases = {\n \"@firewood_crates__askama_parser-0.14.0//:askama_parser\": \"parser\",\n },\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"config\",\n \"default\",\n \"derive\",\n \"std\",\n \"urlencode\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=askama_derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.0\",\n)\n" + } + }, + "firewood_crates__askama_parser-0.14.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/askama_parser/0.14.0/download" + ], + "strip_prefix": "askama_parser-0.14.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"askama_parser\",\n deps = [\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__winnow-0.7.13//:winnow\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__serde_derive-1.0.228//:serde_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"config\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=askama_parser\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.0\",\n)\n" + } + }, + "firewood_crates__assert_cmd-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "bcbb6924530aa9e0432442af08bbcafdad182db80d2e560da42a6d442535bf85", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/assert_cmd/2.1.1/download" + ], + "strip_prefix": "assert_cmd-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"assert_cmd\",\n deps = [\n \"@firewood_crates__anstyle-1.0.13//:anstyle\",\n \"@firewood_crates__assert_cmd-2.1.1//:build_script_build\",\n \"@firewood_crates__bstr-1.12.1//:bstr\",\n \"@firewood_crates__predicates-3.1.3//:predicates\",\n \"@firewood_crates__predicates-core-1.0.9//:predicates_core\",\n \"@firewood_crates__predicates-tree-1.0.12//:predicates_tree\",\n \"@firewood_crates__wait-timeout-0.2.1//:wait_timeout\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=assert_cmd\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"assert_cmd\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=assert_cmd\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"2.1.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__async-trait-0.1.89": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/async-trait/0.1.89/download" + ], + "strip_prefix": "async-trait-0.1.89", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"async_trait\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=async-trait\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.89\",\n)\n" + } + }, + "firewood_crates__atomic-waker-1.1.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/atomic-waker/1.1.2/download" + ], + "strip_prefix": "atomic-waker-1.1.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"atomic_waker\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=atomic-waker\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.2\",\n)\n" + } + }, + "firewood_crates__autocfg-1.5.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/autocfg/1.5.0/download" + ], + "strip_prefix": "autocfg-1.5.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"autocfg\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=autocfg\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.5.0\",\n)\n" + } + }, + "firewood_crates__aws-lc-rs-1.15.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5932a7d9d28b0d2ea34c6b3779d35e3dd6f6345317c34e73438c4f1f29144151", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/aws-lc-rs/1.15.0/download" + ], + "strip_prefix": "aws-lc-rs-1.15.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"aws_lc_rs\",\n deps = [\n \"@firewood_crates__aws-lc-rs-1.15.0//:build_script_build\",\n \"@firewood_crates__aws-lc-sys-0.33.0//:aws_lc_sys\",\n \"@firewood_crates__zeroize-1.8.2//:zeroize\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"aws-lc-sys\",\n \"prebuilt-nasm\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=aws-lc-rs\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.15.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"aws-lc-sys\",\n \"prebuilt-nasm\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n link_deps = [\n \"@firewood_crates__aws-lc-sys-0.33.0//:aws_lc_sys\",\n ],\n edition = \"2021\",\n links = \"aws_lc_rs_1_15_0_sys\",\n pkg_name = \"aws-lc-rs\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=aws-lc-rs\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.15.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__aws-lc-sys-0.33.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1826f2e4cfc2cd19ee53c42fbf68e2f81ec21108e0b7ecf6a71cf062137360fc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/aws-lc-sys/0.33.0/download" + ], + "strip_prefix": "aws-lc-sys-0.33.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"aws_lc_sys\",\n deps = [\n \"@firewood_crates__aws-lc-sys-0.33.0//:build_script_main\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"prebuilt-nasm\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=aws-lc-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.33.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"prebuilt-nasm\",\n ],\n crate_name = \"build_script_main\",\n crate_root = \"builder/main.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__cc-1.2.46//:cc\",\n \"@firewood_crates__cmake-0.1.54//:cmake\",\n \"@firewood_crates__dunce-1.0.5//:dunce\",\n \"@firewood_crates__fs_extra-1.3.0//:fs_extra\",\n ] + select({\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__bindgen-0.72.1//:bindgen\", # cfg(not(any(all(any(target_arch = \"x86_64\", target_arch = \"aarch64\"), any(target_os = \"linux\", target_os = \"macos\", target_os = \"windows\"), any(target_env = \"gnu\", target_env = \"musl\", target_env = \"msvc\", target_env = \"\")), all(target_arch = \"x86\", target_os = \"windows\", target_env = \"msvc\"), all(target_arch = \"x86\", target_os = \"linux\", target_env = \"gnu\"))))\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__bindgen-0.72.1//:bindgen\", # cfg(not(any(all(any(target_arch = \"x86_64\", target_arch = \"aarch64\"), any(target_os = \"linux\", target_os = \"macos\", target_os = \"windows\"), any(target_env = \"gnu\", target_env = \"musl\", target_env = \"msvc\", target_env = \"\")), all(target_arch = \"x86\", target_os = \"windows\", target_env = \"msvc\"), all(target_arch = \"x86\", target_os = \"linux\", target_env = \"gnu\"))))\n ],\n \"//conditions:default\": [],\n }),\n edition = \"2021\",\n links = \"aws_lc_0_33_0\",\n pkg_name = \"aws-lc-sys\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=aws-lc-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.33.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_main\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__backtrace-0.3.76": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/backtrace/0.3.76/download" + ], + "strip_prefix": "backtrace-0.3.76", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"backtrace\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__rustc-demangle-0.1.26//:rustc_demangle\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__addr2line-0.25.1//:addr2line\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__miniz_oxide-0.8.9//:miniz_oxide\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__object-0.37.3//:object\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__addr2line-0.25.1//:addr2line\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__miniz_oxide-0.8.9//:miniz_oxide\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__object-0.37.3//:object\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n ],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__addr2line-0.25.1//:addr2line\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__miniz_oxide-0.8.9//:miniz_oxide\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__object-0.37.3//:object\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__addr2line-0.25.1//:addr2line\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__miniz_oxide-0.8.9//:miniz_oxide\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__object-0.37.3//:object\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-link-0.2.1//:windows_link\", # cfg(any(windows, target_os = \"cygwin\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__addr2line-0.25.1//:addr2line\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__miniz_oxide-0.8.9//:miniz_oxide\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__object-0.37.3//:object\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__addr2line-0.25.1//:addr2line\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__miniz_oxide-0.8.9//:miniz_oxide\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n \"@firewood_crates__object-0.37.3//:object\", # cfg(not(all(windows, target_env = \"msvc\", not(target_vendor = \"uwp\"))))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=backtrace\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.76\",\n)\n" + } + }, + "firewood_crates__base64-0.22.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/base64/0.22.1/download" + ], + "strip_prefix": "base64-0.22.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"base64\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=base64\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.22.1\",\n)\n" + } + }, + "firewood_crates__basic-toml-0.1.10": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/basic-toml/0.1.10/download" + ], + "strip_prefix": "basic-toml-0.1.10", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"basic_toml\",\n deps = [\n \"@firewood_crates__serde-1.0.228//:serde\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=basic-toml\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.10\",\n)\n" + } + }, + "firewood_crates__bindgen-0.72.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bindgen/0.72.1/download" + ], + "strip_prefix": "bindgen-0.72.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bindgen\",\n deps = [\n \"@firewood_crates__bindgen-0.72.1//:build_script_build\",\n \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n \"@firewood_crates__cexpr-0.6.0//:cexpr\",\n \"@firewood_crates__clang-sys-1.8.1//:clang_sys\",\n \"@firewood_crates__itertools-0.13.0//:itertools\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__regex-1.12.2//:regex\",\n \"@firewood_crates__rustc-hash-2.1.1//:rustc_hash\",\n \"@firewood_crates__shlex-1.3.0//:shlex\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bindgen\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.72.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n link_deps = [\n \"@firewood_crates__clang-sys-1.8.1//:clang_sys\",\n ],\n edition = \"2021\",\n pkg_name = \"bindgen\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bindgen\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.72.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__bitfield-0.19.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "21ba6517c6b0f2bf08be60e187ab64b038438f22dd755614d8fe4d4098c46419", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bitfield/0.19.4/download" + ], + "strip_prefix": "bitfield-0.19.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bitfield\",\n proc_macro_deps = [\n \"@firewood_crates__bitfield-macros-0.19.4//:bitfield_macros\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bitfield\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.19.4\",\n)\n" + } + }, + "firewood_crates__bitfield-macros-0.19.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bitfield-macros/0.19.4/download" + ], + "strip_prefix": "bitfield-macros-0.19.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"bitfield_macros\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bitfield-macros\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.19.4\",\n)\n" + } + }, + "firewood_crates__bitflags-1.3.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bitflags/1.3.2/download" + ], + "strip_prefix": "bitflags-1.3.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bitflags\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bitflags\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.3.2\",\n)\n" + } + }, + "firewood_crates__bitflags-2.10.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bitflags/2.10.0/download" + ], + "strip_prefix": "bitflags-2.10.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bitflags\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"std\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"std\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"std\", # wasm32-wasip1\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"std\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"std\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bitflags\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.10.0\",\n)\n" + } + }, + "firewood_crates__bitvec-1.0.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bitvec/1.0.1/download" + ], + "strip_prefix": "bitvec-1.0.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bitvec\",\n deps = [\n \"@firewood_crates__funty-2.0.0//:funty\",\n \"@firewood_crates__radium-0.7.0//:radium\",\n \"@firewood_crates__tap-1.0.1//:tap\",\n \"@firewood_crates__wyz-0.5.1//:wyz\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bitvec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.1\",\n)\n" + } + }, + "firewood_crates__block-buffer-0.10.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/block-buffer/0.10.4/download" + ], + "strip_prefix": "block-buffer-0.10.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"block_buffer\",\n deps = [\n \"@firewood_crates__generic-array-0.14.7//:generic_array\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=block-buffer\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.4\",\n)\n" + } + }, + "firewood_crates__bstr-1.12.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bstr/1.12.1/download" + ], + "strip_prefix": "bstr-1.12.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bstr\",\n deps = [\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__regex-automata-0.4.13//:regex_automata\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n \"unicode\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bstr\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.12.1\",\n)\n" + } + }, + "firewood_crates__bumpalo-3.19.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bumpalo/3.19.0/download" + ], + "strip_prefix": "bumpalo-3.19.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bumpalo\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"collections\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bumpalo\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.19.0\",\n)\n" + } + }, + "firewood_crates__byte-slice-cast-1.2.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/byte-slice-cast/1.2.3/download" + ], + "strip_prefix": "byte-slice-cast-1.2.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"byte_slice_cast\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=byte-slice-cast\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.2.3\",\n)\n" + } + }, + "firewood_crates__bytemuck-1.24.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bytemuck/1.24.0/download" + ], + "strip_prefix": "bytemuck-1.24.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bytemuck\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bytemuck\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.24.0\",\n)\n" + } + }, + "firewood_crates__bytemuck_derive-1.10.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bytemuck_derive/1.10.2/download" + ], + "strip_prefix": "bytemuck_derive-1.10.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"bytemuck_derive\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bytemuck_derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.10.2\",\n)\n" + } + }, + "firewood_crates__byteorder-1.5.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/byteorder/1.5.0/download" + ], + "strip_prefix": "byteorder-1.5.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"byteorder\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=byteorder\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.5.0\",\n)\n" + } + }, + "firewood_crates__bytes-1.11.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/bytes/1.11.0/download" + ], + "strip_prefix": "bytes-1.11.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"bytes\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=bytes\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.11.0\",\n)\n" + } + }, + "firewood_crates__byteview-0.6.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6236364b88b9b6d0bc181ba374cf1ab55ba3ef97a1cb6f8cddad48a273767fb5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/byteview/0.6.1/download" + ], + "strip_prefix": "byteview-0.6.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"byteview\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=byteview\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.1\",\n)\n" + } + }, + "firewood_crates__cast-0.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/cast/0.3.0/download" + ], + "strip_prefix": "cast-0.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"cast\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cast\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.0\",\n)\n" + } + }, + "firewood_crates__cbindgen-0.29.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "befbfd072a8e81c02f8c507aefce431fe5e7d051f83d48a23ffc9b9fe5a11799", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/cbindgen/0.29.2/download" + ], + "strip_prefix": "cbindgen-0.29.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"cbindgen\",\n deps = [\n \"@firewood_crates__cbindgen-0.29.2//:build_script_build\",\n \"@firewood_crates__clap-4.5.52//:clap\",\n \"@firewood_crates__heck-0.5.0//:heck\",\n \"@firewood_crates__indexmap-2.12.0//:indexmap\",\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__serde_json-1.0.145//:serde_json\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n \"@firewood_crates__tempfile-3.23.0//:tempfile\",\n \"@firewood_crates__toml-0.9.8//:toml\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"clap\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cbindgen\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.29.2\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"clap\",\n \"default\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"cbindgen\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cbindgen\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.29.2\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__cc-1.2.46": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/cc/1.2.46/download" + ], + "strip_prefix": "cc-1.2.46", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"cc\",\n deps = [\n \"@firewood_crates__find-msvc-tools-0.1.5//:find_msvc_tools\",\n \"@firewood_crates__jobserver-0.1.34//:jobserver\",\n \"@firewood_crates__shlex-1.3.0//:shlex\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"parallel\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.2.46\",\n)\n" + } + }, + "firewood_crates__cexpr-0.6.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/cexpr/0.6.0/download" + ], + "strip_prefix": "cexpr-0.6.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"cexpr\",\n deps = [\n \"@firewood_crates__nom-7.1.3//:nom\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cexpr\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.0\",\n)\n" + } + }, + "firewood_crates__cfg-if-1.0.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/cfg-if/1.0.4/download" + ], + "strip_prefix": "cfg-if-1.0.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"cfg_if\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cfg-if\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.4\",\n)\n" + } + }, + "firewood_crates__chrono-0.4.42": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/chrono/0.4.42/download" + ], + "strip_prefix": "chrono-0.4.42", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"chrono\",\n deps = [\n \"@firewood_crates__num-traits-0.2.19//:num_traits\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__iana-time-zone-0.1.64//:iana_time_zone\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__iana-time-zone-0.1.64//:iana_time_zone\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__js-sys-0.3.82//:js_sys\", # wasm32-unknown-unknown\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\", # wasm32-unknown-unknown\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-link-0.2.1//:windows_link\", # x86_64-pc-windows-msvc\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__iana-time-zone-0.1.64//:iana_time_zone\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__iana-time-zone-0.1.64//:iana_time_zone\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"clock\",\n \"default\",\n \"iana-time-zone\",\n \"js-sys\",\n \"now\",\n \"oldtime\",\n \"std\",\n \"wasm-bindgen\",\n \"wasmbind\",\n \"winapi\",\n \"windows-link\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=chrono\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.42\",\n)\n" + } + }, + "firewood_crates__ciborium-0.2.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ciborium/0.2.2/download" + ], + "strip_prefix": "ciborium-0.2.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ciborium\",\n deps = [\n \"@firewood_crates__ciborium-io-0.2.2//:ciborium_io\",\n \"@firewood_crates__ciborium-ll-0.2.2//:ciborium_ll\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ciborium\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.2\",\n)\n" + } + }, + "firewood_crates__ciborium-io-0.2.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ciborium-io/0.2.2/download" + ], + "strip_prefix": "ciborium-io-0.2.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ciborium_io\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ciborium-io\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.2\",\n)\n" + } + }, + "firewood_crates__ciborium-ll-0.2.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ciborium-ll/0.2.2/download" + ], + "strip_prefix": "ciborium-ll-0.2.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ciborium_ll\",\n deps = [\n \"@firewood_crates__ciborium-io-0.2.2//:ciborium_io\",\n \"@firewood_crates__half-2.7.1//:half\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ciborium-ll\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.2\",\n)\n" + } + }, + "firewood_crates__clang-sys-1.8.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/clang-sys/1.8.1/download" + ], + "strip_prefix": "clang-sys-1.8.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"clang_sys\",\n deps = [\n \"@firewood_crates__clang-sys-1.8.1//:build_script_build\",\n \"@firewood_crates__glob-0.3.3//:glob\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=clang-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.8.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__glob-0.3.3//:glob\",\n ],\n edition = \"2021\",\n links = \"clang\",\n pkg_name = \"clang-sys\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=clang-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.8.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__clap-4.5.52": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/clap/4.5.52/download" + ], + "strip_prefix": "clap-4.5.52", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"clap\",\n deps = [\n \"@firewood_crates__clap_builder-4.5.52//:clap_builder\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__clap_derive-4.5.49//:clap_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"cargo\",\n \"color\",\n \"default\",\n \"derive\",\n \"error-context\",\n \"help\",\n \"std\",\n \"string\",\n \"suggestions\",\n \"usage\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=clap\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"4.5.52\",\n)\n" + } + }, + "firewood_crates__clap_builder-4.5.52": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/clap_builder/4.5.52/download" + ], + "strip_prefix": "clap_builder-4.5.52", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"clap_builder\",\n deps = [\n \"@firewood_crates__anstream-0.6.21//:anstream\",\n \"@firewood_crates__anstyle-1.0.13//:anstyle\",\n \"@firewood_crates__clap_lex-0.7.6//:clap_lex\",\n \"@firewood_crates__strsim-0.11.1//:strsim\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"cargo\",\n \"color\",\n \"error-context\",\n \"help\",\n \"std\",\n \"string\",\n \"suggestions\",\n \"usage\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=clap_builder\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"4.5.52\",\n)\n" + } + }, + "firewood_crates__clap_derive-4.5.49": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/clap_derive/4.5.49/download" + ], + "strip_prefix": "clap_derive-4.5.49", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"clap_derive\",\n deps = [\n \"@firewood_crates__heck-0.5.0//:heck\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=clap_derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"4.5.49\",\n)\n" + } + }, + "firewood_crates__clap_lex-0.7.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/clap_lex/0.7.6/download" + ], + "strip_prefix": "clap_lex-0.7.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"clap_lex\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=clap_lex\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.6\",\n)\n" + } + }, + "firewood_crates__cmake-0.1.54": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/cmake/0.1.54/download" + ], + "strip_prefix": "cmake-0.1.54", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"cmake\",\n deps = [\n \"@firewood_crates__cc-1.2.46//:cc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cmake\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.54\",\n)\n" + } + }, + "firewood_crates__coarsetime-0.1.36": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "91849686042de1b41cd81490edc83afbcb0abe5a9b6f2c4114f23ce8cca1bcf4", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/coarsetime/0.1.36/download" + ], + "strip_prefix": "coarsetime-0.1.36", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"coarsetime\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"wasix\", target_os = \"wasi\")))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"wasix\", target_os = \"wasi\")))\n ],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"wasix\", target_os = \"wasi\")))\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\", # cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__wasix-0.12.21//:wasix\", # cfg(any(target_os = \"wasix\", target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"wasix\", target_os = \"wasi\")))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"wasix\", target_os = \"wasi\")))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"wasix\", target_os = \"wasi\")))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=coarsetime\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.36\",\n)\n" + } + }, + "firewood_crates__colorchoice-1.0.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/colorchoice/1.0.4/download" + ], + "strip_prefix": "colorchoice-1.0.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"colorchoice\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=colorchoice\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.4\",\n)\n" + } + }, + "firewood_crates__compare-0.0.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ea0095f6103c2a8b44acd6fd15960c801dafebf02e21940360833e0673f48ba7", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/compare/0.0.6/download" + ], + "strip_prefix": "compare-0.0.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"compare\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=compare\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.0.6\",\n)\n" + } + }, + "firewood_crates__console-0.16.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b430743a6eb14e9764d4260d4c0d8123087d504eeb9c48f2b2a5e810dd369df4", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/console/0.16.1/download" + ], + "strip_prefix": "console-0.16.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"console\",\n deps = [\n \"@firewood_crates__libc-0.2.177//:libc\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__unicode-width-0.2.2//:unicode_width\",\n ] + select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__encode_unicode-1.0.0//:encode_unicode\", # cfg(windows)\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"ansi-parsing\",\n \"std\",\n \"unicode-width\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=console\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.16.1\",\n)\n" + } + }, + "firewood_crates__const-hex-1.17.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/const-hex/1.17.0/download" + ], + "strip_prefix": "const-hex-1.17.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"const_hex\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n ] + select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(any(target_arch = \"x86\", target_arch = \"x86_64\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(any(target_arch = \"x86\", target_arch = \"x86_64\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(any(target_arch = \"x86\", target_arch = \"x86_64\"))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=const-hex\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.17.0\",\n)\n" + } + }, + "firewood_crates__const_format-0.2.35": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/const_format/0.2.35/download" + ], + "strip_prefix": "const_format-0.2.35", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"const_format\",\n proc_macro_deps = [\n \"@firewood_crates__const_format_proc_macros-0.2.34//:const_format_proc_macros\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=const_format\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.35\",\n)\n" + } + }, + "firewood_crates__const_format_proc_macros-0.2.34": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/const_format_proc_macros/0.2.34/download" + ], + "strip_prefix": "const_format_proc_macros-0.2.34", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"const_format_proc_macros\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__unicode-xid-0.2.6//:unicode_xid\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=const_format_proc_macros\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.34\",\n)\n" + } + }, + "firewood_crates__core-foundation-0.10.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/core-foundation/0.10.1/download" + ], + "strip_prefix": "core-foundation-0.10.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"core_foundation\",\n deps = [\n \"@firewood_crates__core-foundation-sys-0.8.7//:core_foundation_sys\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"link\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=core-foundation\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.1\",\n)\n" + } + }, + "firewood_crates__core-foundation-sys-0.8.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/core-foundation-sys/0.8.7/download" + ], + "strip_prefix": "core-foundation-sys-0.8.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"core_foundation_sys\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"link\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=core-foundation-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.7\",\n)\n" + } + }, + "firewood_crates__cpp_demangle-0.4.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/cpp_demangle/0.4.5/download" + ], + "strip_prefix": "cpp_demangle-0.4.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"cpp_demangle\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__cpp_demangle-0.4.5//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cpp_demangle\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.5\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"cpp_demangle\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cpp_demangle\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.4.5\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__cpufeatures-0.2.17": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/cpufeatures/0.2.17/download" + ], + "strip_prefix": "cpufeatures-0.2.17", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"cpufeatures\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(target_arch = \"aarch64\", target_vendor = \"apple\"))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(target_arch = \"aarch64\", target_os = \"linux\"))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=cpufeatures\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.17\",\n)\n" + } + }, + "firewood_crates__criterion-0.7.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/criterion/0.7.0/download" + ], + "strip_prefix": "criterion-0.7.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"criterion\",\n deps = [\n \"@firewood_crates__anes-0.1.6//:anes\",\n \"@firewood_crates__cast-0.3.0//:cast\",\n \"@firewood_crates__ciborium-0.2.2//:ciborium\",\n \"@firewood_crates__clap-4.5.52//:clap\",\n \"@firewood_crates__criterion-plot-0.6.0//:criterion_plot\",\n \"@firewood_crates__itertools-0.13.0//:itertools\",\n \"@firewood_crates__num-traits-0.2.19//:num_traits\",\n \"@firewood_crates__oorandom-11.1.5//:oorandom\",\n \"@firewood_crates__plotters-0.3.7//:plotters\",\n \"@firewood_crates__rayon-1.11.0//:rayon\",\n \"@firewood_crates__regex-1.12.2//:regex\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__serde_json-1.0.145//:serde_json\",\n \"@firewood_crates__tinytemplate-1.2.1//:tinytemplate\",\n \"@firewood_crates__walkdir-2.5.0//:walkdir\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"cargo_bench_support\",\n \"default\",\n \"html_reports\",\n \"plotters\",\n \"rayon\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=criterion\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.0\",\n)\n" + } + }, + "firewood_crates__criterion-plot-0.6.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/criterion-plot/0.6.0/download" + ], + "strip_prefix": "criterion-plot-0.6.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"criterion_plot\",\n deps = [\n \"@firewood_crates__cast-0.3.0//:cast\",\n \"@firewood_crates__itertools-0.13.0//:itertools\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=criterion-plot\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.0\",\n)\n" + } + }, + "firewood_crates__crossbeam-deque-0.8.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/crossbeam-deque/0.8.6/download" + ], + "strip_prefix": "crossbeam-deque-0.8.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"crossbeam_deque\",\n deps = [\n \"@firewood_crates__crossbeam-epoch-0.9.18//:crossbeam_epoch\",\n \"@firewood_crates__crossbeam-utils-0.8.21//:crossbeam_utils\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=crossbeam-deque\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.6\",\n)\n" + } + }, + "firewood_crates__crossbeam-epoch-0.9.18": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/crossbeam-epoch/0.9.18/download" + ], + "strip_prefix": "crossbeam-epoch-0.9.18", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"crossbeam_epoch\",\n deps = [\n \"@firewood_crates__crossbeam-utils-0.8.21//:crossbeam_utils\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=crossbeam-epoch\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.18\",\n)\n" + } + }, + "firewood_crates__crossbeam-skiplist-0.1.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "df29de440c58ca2cc6e587ec3d22347551a32435fbde9d2bff64e78a9ffa151b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/crossbeam-skiplist/0.1.3/download" + ], + "strip_prefix": "crossbeam-skiplist-0.1.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"crossbeam_skiplist\",\n deps = [\n \"@firewood_crates__crossbeam-epoch-0.9.18//:crossbeam_epoch\",\n \"@firewood_crates__crossbeam-utils-0.8.21//:crossbeam_utils\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=crossbeam-skiplist\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.3\",\n)\n" + } + }, + "firewood_crates__crossbeam-utils-0.8.21": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/crossbeam-utils/0.8.21/download" + ], + "strip_prefix": "crossbeam-utils-0.8.21", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"crossbeam_utils\",\n deps = [\n \"@firewood_crates__crossbeam-utils-0.8.21//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=crossbeam-utils\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.21\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"crossbeam-utils\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=crossbeam-utils\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.8.21\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__crunchy-0.2.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/crunchy/0.2.4/download" + ], + "strip_prefix": "crunchy-0.2.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"crunchy\",\n deps = [\n \"@firewood_crates__crunchy-0.2.4//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"limit_128\",\n \"limit_256\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=crunchy\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.4\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"limit_128\",\n \"limit_256\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"crunchy\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=crunchy\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.2.4\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__crypto-common-0.1.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/crypto-common/0.1.7/download" + ], + "strip_prefix": "crypto-common-0.1.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"crypto_common\",\n deps = [\n \"@firewood_crates__generic-array-0.14.7//:generic_array\",\n \"@firewood_crates__typenum-1.19.0//:typenum\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=crypto-common\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.7\",\n)\n" + } + }, + "firewood_crates__csv-1.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/csv/1.4.0/download" + ], + "strip_prefix": "csv-1.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"csv\",\n deps = [\n \"@firewood_crates__csv-core-0.1.13//:csv_core\",\n \"@firewood_crates__itoa-1.0.15//:itoa\",\n \"@firewood_crates__ryu-1.0.20//:ryu\",\n \"@firewood_crates__serde_core-1.0.228//:serde_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=csv\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.4.0\",\n)\n" + } + }, + "firewood_crates__csv-core-0.1.13": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/csv-core/0.1.13/download" + ], + "strip_prefix": "csv-core-0.1.13", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"csv_core\",\n deps = [\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=csv-core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.13\",\n)\n" + } + }, + "firewood_crates__ctor-0.6.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3ffc71fcdcdb40d6f087edddf7f8f1f8f79e6cf922f555a9ee8779752d4819bd", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ctor/0.6.1/download" + ], + "strip_prefix": "ctor-0.6.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ctor\",\n deps = [\n \"@firewood_crates__dtor-0.1.1//:dtor\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__ctor-proc-macro-0.0.7//:ctor_proc_macro\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"__no_warn_on_missing_unsafe\",\n \"default\",\n \"dtor\",\n \"proc_macro\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ctor\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.1\",\n)\n" + } + }, + "firewood_crates__ctor-proc-macro-0.0.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ctor-proc-macro/0.0.7/download" + ], + "strip_prefix": "ctor-proc-macro-0.0.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"ctor_proc_macro\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ctor-proc-macro\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.0.7\",\n)\n" + } + }, + "firewood_crates__dashmap-6.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/dashmap/6.1.0/download" + ], + "strip_prefix": "dashmap-6.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"dashmap\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__crossbeam-utils-0.8.21//:crossbeam_utils\",\n \"@firewood_crates__hashbrown-0.14.5//:hashbrown\",\n \"@firewood_crates__lock_api-0.4.14//:lock_api\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__parking_lot_core-0.9.12//:parking_lot_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=dashmap\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"6.1.0\",\n)\n" + } + }, + "firewood_crates__debugid-0.8.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/debugid/0.8.0/download" + ], + "strip_prefix": "debugid-0.8.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"debugid\",\n deps = [\n \"@firewood_crates__uuid-1.18.1//:uuid\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=debugid\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.0\",\n)\n" + } + }, + "firewood_crates__derive-where-1.6.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/derive-where/1.6.0/download" + ], + "strip_prefix": "derive-where-1.6.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"derive_where\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=derive-where\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.6.0\",\n)\n" + } + }, + "firewood_crates__difflib-0.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/difflib/0.4.0/download" + ], + "strip_prefix": "difflib-0.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"difflib\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=difflib\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.0\",\n)\n" + } + }, + "firewood_crates__digest-0.10.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/digest/0.10.7/download" + ], + "strip_prefix": "digest-0.10.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"digest\",\n deps = [\n \"@firewood_crates__block-buffer-0.10.4//:block_buffer\",\n \"@firewood_crates__crypto-common-0.1.7//:crypto_common\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"block-buffer\",\n \"core-api\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=digest\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.7\",\n)\n" + } + }, + "firewood_crates__displaydoc-0.2.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/displaydoc/0.2.5/download" + ], + "strip_prefix": "displaydoc-0.2.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"displaydoc\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=displaydoc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.5\",\n)\n" + } + }, + "firewood_crates__double-ended-peekable-0.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c0d05e1c0dbad51b52c38bda7adceef61b9efc2baf04acfe8726a8c4630a6f57", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/double-ended-peekable/0.1.0/download" + ], + "strip_prefix": "double-ended-peekable-0.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"double_ended_peekable\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=double-ended-peekable\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.0\",\n)\n" + } + }, + "firewood_crates__dtor-0.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/dtor/0.1.1/download" + ], + "strip_prefix": "dtor-0.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"dtor\",\n proc_macro_deps = [\n \"@firewood_crates__dtor-proc-macro-0.0.6//:dtor_proc_macro\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"__no_warn_on_missing_unsafe\",\n \"proc_macro\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=dtor\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.1\",\n)\n" + } + }, + "firewood_crates__dtor-proc-macro-0.0.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/dtor-proc-macro/0.0.6/download" + ], + "strip_prefix": "dtor-proc-macro-0.0.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"dtor_proc_macro\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=dtor-proc-macro\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.0.6\",\n)\n" + } + }, + "firewood_crates__dunce-1.0.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/dunce/1.0.5/download" + ], + "strip_prefix": "dunce-1.0.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"dunce\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=dunce\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.5\",\n)\n" + } + }, + "firewood_crates__either-1.15.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/either/1.15.0/download" + ], + "strip_prefix": "either-1.15.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"either\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n \"use_std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=either\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.15.0\",\n)\n" + } + }, + "firewood_crates__encode_unicode-1.0.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/encode_unicode/1.0.0/download" + ], + "strip_prefix": "encode_unicode-1.0.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"encode_unicode\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=encode_unicode\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.0\",\n)\n" + } + }, + "firewood_crates__endian-type-0.1.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/endian-type/0.1.2/download" + ], + "strip_prefix": "endian-type-0.1.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"endian_type\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=endian-type\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.2\",\n)\n" + } + }, + "firewood_crates__enum-as-inner-0.6.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/enum-as-inner/0.6.1/download" + ], + "strip_prefix": "enum-as-inner-0.6.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"enum_as_inner\",\n deps = [\n \"@firewood_crates__heck-0.5.0//:heck\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=enum-as-inner\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.1\",\n)\n" + } + }, + "firewood_crates__enum_dispatch-0.3.13": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/enum_dispatch/0.3.13/download" + ], + "strip_prefix": "enum_dispatch-0.3.13", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"enum_dispatch\",\n deps = [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=enum_dispatch\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.13\",\n)\n" + } + }, + "firewood_crates__env_filter-0.1.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/env_filter/0.1.4/download" + ], + "strip_prefix": "env_filter-0.1.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"env_filter\",\n deps = [\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__regex-1.12.2//:regex\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"regex\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=env_filter\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.4\",\n)\n" + } + }, + "firewood_crates__env_logger-0.11.8": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/env_logger/0.11.8/download" + ], + "strip_prefix": "env_logger-0.11.8", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"env_logger\",\n deps = [\n \"@firewood_crates__anstream-0.6.21//:anstream\",\n \"@firewood_crates__anstyle-1.0.13//:anstyle\",\n \"@firewood_crates__env_filter-0.1.4//:env_filter\",\n \"@firewood_crates__jiff-0.2.16//:jiff\",\n \"@firewood_crates__log-0.4.28//:log\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"auto-color\",\n \"color\",\n \"default\",\n \"humantime\",\n \"regex\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=env_logger\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.11.8\",\n)\n" + } + }, + "firewood_crates__equator-0.4.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/equator/0.4.2/download" + ], + "strip_prefix": "equator-0.4.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"equator\",\n proc_macro_deps = [\n \"@firewood_crates__equator-macro-0.4.2//:equator_macro\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=equator\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.2\",\n)\n" + } + }, + "firewood_crates__equator-macro-0.4.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/equator-macro/0.4.2/download" + ], + "strip_prefix": "equator-macro-0.4.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"equator_macro\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=equator-macro\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.2\",\n)\n" + } + }, + "firewood_crates__equivalent-1.0.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/equivalent/1.0.2/download" + ], + "strip_prefix": "equivalent-1.0.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"equivalent\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=equivalent\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.2\",\n)\n" + } + }, + "firewood_crates__errno-0.3.14": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/errno/0.3.14/download" + ], + "strip_prefix": "errno-0.3.14", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"errno\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(target_os = \"wasi\")\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=errno\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.14\",\n)\n" + } + }, + "firewood_crates__ethbloom-0.14.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "8c321610643004cf908ec0f5f2aa0d8f1f8e14b540562a2887a1111ff1ecbf7b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ethbloom/0.14.1/download" + ], + "strip_prefix": "ethbloom-0.14.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ethbloom\",\n deps = [\n \"@firewood_crates__crunchy-0.2.4//:crunchy\",\n \"@firewood_crates__fixed-hash-0.8.0//:fixed_hash\",\n \"@firewood_crates__impl-rlp-0.4.0//:impl_rlp\",\n \"@firewood_crates__impl-serde-0.5.0//:impl_serde\",\n \"@firewood_crates__tiny-keccak-2.0.2//:tiny_keccak\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"impl-rlp\",\n \"impl-serde\",\n \"rlp\",\n \"rustc-hex\",\n \"serialize\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ethbloom\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.1\",\n)\n" + } + }, + "firewood_crates__ethereum-types-0.16.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f7326303c6c18bb03c7a3c4c22d4032ae60dfe673ca9109602aa4d8154b2637e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ethereum-types/0.16.0/download" + ], + "strip_prefix": "ethereum-types-0.16.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ethereum_types\",\n deps = [\n \"@firewood_crates__ethbloom-0.14.1//:ethbloom\",\n \"@firewood_crates__fixed-hash-0.8.0//:fixed_hash\",\n \"@firewood_crates__impl-rlp-0.4.0//:impl_rlp\",\n \"@firewood_crates__impl-serde-0.5.0//:impl_serde\",\n \"@firewood_crates__primitive-types-0.14.0//:primitive_types\",\n \"@firewood_crates__uint-0.10.0//:uint\",\n ],\n aliases = {\n \"@firewood_crates__uint-0.10.0//:uint\": \"uint_crate\",\n },\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"ethbloom\",\n \"impl-rlp\",\n \"impl-serde\",\n \"rlp\",\n \"serialize\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ethereum-types\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.16.0\",\n)\n" + } + }, + "firewood_crates__fastant-0.1.10": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "62bf7fa928ce0c4a43bd6e7d1235318fc32ac3a3dea06a2208c44e729449471a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fastant/0.1.10/download" + ], + "strip_prefix": "fastant-0.1.10", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"fastant\",\n deps = [\n \"@firewood_crates__web-time-1.1.0//:web_time\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__small_ctor-0.1.2//:small_ctor\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fastant\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.10\",\n)\n" + } + }, + "firewood_crates__fastrace-0.7.14": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "318783b9fefe06130ab664ff1779215657586b004c0c7f3d6ece16d658936d06", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fastrace/0.7.14/download" + ], + "strip_prefix": "fastrace-0.7.14", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"fastrace\",\n deps = [\n \"@firewood_crates__fastant-0.1.10//:fastant\",\n \"@firewood_crates__parking_lot-0.12.5//:parking_lot\",\n \"@firewood_crates__pin-project-1.1.10//:pin_project\",\n \"@firewood_crates__rand-0.9.2//:rand\",\n \"@firewood_crates__rtrb-0.3.2//:rtrb\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__fastrace-macro-0.7.14//:fastrace_macro\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"enable\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fastrace\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.14\",\n)\n" + } + }, + "firewood_crates__fastrace-macro-0.7.14": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c7079009cf129d63c850dee732b58d7639d278a47ad99c607954ac94cfd57ef4", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fastrace-macro/0.7.14/download" + ], + "strip_prefix": "fastrace-macro-0.7.14", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"fastrace_macro\",\n deps = [\n \"@firewood_crates__proc-macro-error2-2.0.1//:proc_macro_error2\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"enable\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fastrace-macro\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.14\",\n)\n" + } + }, + "firewood_crates__fastrace-opentelemetry-0.14.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b7e8ec7cff0ea398352764b6ee15c0902ccabf23d823525254b52d7f878fcf60", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fastrace-opentelemetry/0.14.0/download" + ], + "strip_prefix": "fastrace-opentelemetry-0.14.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"fastrace_opentelemetry\",\n deps = [\n \"@firewood_crates__fastrace-0.7.14//:fastrace\",\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__opentelemetry-0.31.0//:opentelemetry\",\n \"@firewood_crates__opentelemetry_sdk-0.31.0//:opentelemetry_sdk\",\n \"@firewood_crates__pollster-0.4.0//:pollster\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fastrace-opentelemetry\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.0\",\n)\n" + } + }, + "firewood_crates__fastrand-2.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fastrand/2.3.0/download" + ], + "strip_prefix": "fastrand-2.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"fastrand\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fastrand\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.3.0\",\n)\n" + } + }, + "firewood_crates__find-msvc-tools-0.1.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/find-msvc-tools/0.1.5/download" + ], + "strip_prefix": "find-msvc-tools-0.1.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"find_msvc_tools\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=find-msvc-tools\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.5\",\n)\n" + } + }, + "firewood_crates__findshlibs-0.10.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/findshlibs/0.10.2/download" + ], + "strip_prefix": "findshlibs-0.10.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"findshlibs\",\n deps = [\n \"@firewood_crates__findshlibs-0.10.2//:build_script_build\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__lazy_static-1.5.0//:lazy_static\", # cfg(any(target_os = \"macos\", target_os = \"ios\"))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__winapi-0.3.9//:winapi\", # cfg(target_os = \"windows\")\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=findshlibs\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.2\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__cc-1.2.46//:cc\",\n ],\n edition = \"2018\",\n pkg_name = \"findshlibs\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=findshlibs\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.10.2\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__fixed-hash-0.8.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fixed-hash/0.8.0/download" + ], + "strip_prefix": "fixed-hash-0.8.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"fixed_hash\",\n deps = [\n \"@firewood_crates__byteorder-1.5.0//:byteorder\",\n \"@firewood_crates__rand-0.8.5//:rand\",\n \"@firewood_crates__rustc-hex-2.1.0//:rustc_hex\",\n \"@firewood_crates__static_assertions-1.1.0//:static_assertions\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"byteorder\",\n \"default\",\n \"rand\",\n \"rustc-hex\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fixed-hash\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.0\",\n)\n" + } + }, + "firewood_crates__fjall-2.11.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0b25ad44cd4360a0448a9b5a0a6f1c7a621101cca4578706d43c9a821418aebc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fjall/2.11.2/download" + ], + "strip_prefix": "fjall-2.11.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"fjall\",\n deps = [\n \"@firewood_crates__byteorder-1.5.0//:byteorder\",\n \"@firewood_crates__byteview-0.6.1//:byteview\",\n \"@firewood_crates__dashmap-6.1.0//:dashmap\",\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__lsm-tree-2.10.4//:lsm_tree\",\n \"@firewood_crates__path-absolutize-3.1.1//:path_absolutize\",\n \"@firewood_crates__std-semaphore-0.1.0//:std_semaphore\",\n \"@firewood_crates__tempfile-3.23.0//:tempfile\",\n \"@firewood_crates__xxhash-rust-0.8.15//:xxhash_rust\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"lz4\",\n \"single_writer_tx\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fjall\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.11.2\",\n)\n" + } + }, + "firewood_crates__float-cmp-0.10.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/float-cmp/0.10.0/download" + ], + "strip_prefix": "float-cmp-0.10.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"float_cmp\",\n deps = [\n \"@firewood_crates__num-traits-0.2.19//:num_traits\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"num-traits\",\n \"ratio\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=float-cmp\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.0\",\n)\n" + } + }, + "firewood_crates__fnv-1.0.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fnv/1.0.7/download" + ], + "strip_prefix": "fnv-1.0.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"fnv\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fnv\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.7\",\n)\n" + } + }, + "firewood_crates__foldhash-0.1.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/foldhash/0.1.5/download" + ], + "strip_prefix": "foldhash-0.1.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"foldhash\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=foldhash\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.5\",\n)\n" + } + }, + "firewood_crates__foldhash-0.2.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/foldhash/0.2.0/download" + ], + "strip_prefix": "foldhash-0.2.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"foldhash\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=foldhash\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.0\",\n)\n" + } + }, + "firewood_crates__form_urlencoded-1.2.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/form_urlencoded/1.2.2/download" + ], + "strip_prefix": "form_urlencoded-1.2.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"form_urlencoded\",\n deps = [\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=form_urlencoded\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.2.2\",\n)\n" + } + }, + "firewood_crates__fs_extra-1.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/fs_extra/1.3.0/download" + ], + "strip_prefix": "fs_extra-1.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"fs_extra\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=fs_extra\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.3.0\",\n)\n" + } + }, + "firewood_crates__funty-2.0.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/funty/2.0.0/download" + ], + "strip_prefix": "funty-2.0.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"funty\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=funty\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.0.0\",\n)\n" + } + }, + "firewood_crates__futures-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures/0.3.31/download" + ], + "strip_prefix": "futures-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"futures\",\n deps = [\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\",\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-executor-0.3.31//:futures_executor\",\n \"@firewood_crates__futures-io-0.3.31//:futures_io\",\n \"@firewood_crates__futures-sink-0.3.31//:futures_sink\",\n \"@firewood_crates__futures-task-0.3.31//:futures_task\",\n \"@firewood_crates__futures-util-0.3.31//:futures_util\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"executor\",\n \"futures-executor\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__futures-channel-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures-channel/0.3.31/download" + ], + "strip_prefix": "futures-channel-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"futures_channel\",\n deps = [\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-sink-0.3.31//:futures_sink\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"futures-sink\",\n \"sink\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures-channel\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__futures-core-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures-core/0.3.31/download" + ], + "strip_prefix": "futures-core-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"futures_core\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures-core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__futures-executor-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures-executor/0.3.31/download" + ], + "strip_prefix": "futures-executor-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"futures_executor\",\n deps = [\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-task-0.3.31//:futures_task\",\n \"@firewood_crates__futures-util-0.3.31//:futures_util\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures-executor\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__futures-io-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures-io/0.3.31/download" + ], + "strip_prefix": "futures-io-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"futures_io\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures-io\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__futures-macro-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures-macro/0.3.31/download" + ], + "strip_prefix": "futures-macro-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"futures_macro\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures-macro\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__futures-sink-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures-sink/0.3.31/download" + ], + "strip_prefix": "futures-sink-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"futures_sink\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures-sink\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__futures-task-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures-task/0.3.31/download" + ], + "strip_prefix": "futures-task-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"futures_task\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures-task\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__futures-util-0.3.31": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/futures-util/0.3.31/download" + ], + "strip_prefix": "futures-util-0.3.31", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"futures_util\",\n deps = [\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\",\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-io-0.3.31//:futures_io\",\n \"@firewood_crates__futures-sink-0.3.31//:futures_sink\",\n \"@firewood_crates__futures-task-0.3.31//:futures_task\",\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__pin-utils-0.1.0//:pin_utils\",\n \"@firewood_crates__slab-0.4.11//:slab\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__futures-macro-0.3.31//:futures_macro\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"async-await\",\n \"async-await-macro\",\n \"channel\",\n \"futures-channel\",\n \"futures-io\",\n \"futures-macro\",\n \"futures-sink\",\n \"io\",\n \"memchr\",\n \"sink\",\n \"slab\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=futures-util\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.31\",\n)\n" + } + }, + "firewood_crates__generic-array-0.14.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/generic-array/0.14.7/download" + ], + "strip_prefix": "generic-array-0.14.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"generic_array\",\n deps = [\n \"@firewood_crates__generic-array-0.14.7//:build_script_build\",\n \"@firewood_crates__typenum-1.19.0//:typenum\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"more_lengths\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=generic-array\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.7\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"more_lengths\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__version_check-0.9.5//:version_check\",\n ],\n edition = \"2015\",\n pkg_name = \"generic-array\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=generic-array\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.14.7\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__getrandom-0.2.16": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/getrandom/0.2.16/download" + ], + "strip_prefix": "getrandom-0.2.16", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"getrandom\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__wasi-0.11.1-wasi-snapshot-preview1//:wasi\", # cfg(target_os = \"wasi\")\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=getrandom\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.16\",\n)\n" + } + }, + "firewood_crates__getrandom-0.3.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/getrandom/0.3.4/download" + ], + "strip_prefix": "getrandom-0.3.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"getrandom\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__getrandom-0.3.4//:build_script_build\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(any(target_os = \"macos\", target_os = \"openbsd\", target_os = \"vita\", target_os = \"emscripten\"))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(any(target_os = \"linux\", target_os = \"android\"), not(any(all(target_os = \"linux\", target_env = \"\"), getrandom_backend = \"custom\", getrandom_backend = \"linux_raw\", getrandom_backend = \"rdrand\", getrandom_backend = \"rndr\"))))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(any(target_os = \"linux\", target_os = \"android\"), not(any(all(target_os = \"linux\", target_env = \"\"), getrandom_backend = \"custom\", getrandom_backend = \"linux_raw\", getrandom_backend = \"rdrand\", getrandom_backend = \"rndr\"))))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(any(target_os = \"linux\", target_os = \"android\"), not(any(all(target_os = \"linux\", target_env = \"\"), getrandom_backend = \"custom\", getrandom_backend = \"linux_raw\", getrandom_backend = \"rdrand\", getrandom_backend = \"rndr\"))))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=getrandom\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.4\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"getrandom\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=getrandom\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.3.4\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__gimli-0.32.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/gimli/0.32.3/download" + ], + "strip_prefix": "gimli-0.32.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"gimli\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"read\",\n \"read-core\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=gimli\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.32.3\",\n)\n" + } + }, + "firewood_crates__glob-0.3.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/glob/0.3.3/download" + ], + "strip_prefix": "glob-0.3.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"glob\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=glob\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.3\",\n)\n" + } + }, + "firewood_crates__guardian-1.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/guardian/1.3.0/download" + ], + "strip_prefix": "guardian-1.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"guardian\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=guardian\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.3.0\",\n)\n" + } + }, + "firewood_crates__h2-0.4.12": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/h2/0.4.12/download" + ], + "strip_prefix": "h2-0.4.12", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"h2\",\n deps = [\n \"@firewood_crates__atomic-waker-1.1.2//:atomic_waker\",\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__fnv-1.0.7//:fnv\",\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-sink-0.3.31//:futures_sink\",\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__indexmap-2.12.0//:indexmap\",\n \"@firewood_crates__slab-0.4.11//:slab\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__tokio-util-0.7.17//:tokio_util\",\n \"@firewood_crates__tracing-0.1.41//:tracing\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=h2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.12\",\n)\n" + } + }, + "firewood_crates__half-2.7.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/half/2.7.1/download" + ], + "strip_prefix": "half-2.7.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"half\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__zerocopy-0.8.27//:zerocopy\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=half\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.7.1\",\n)\n" + } + }, + "firewood_crates__hash-db-0.16.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hash-db/0.16.0/download" + ], + "strip_prefix": "hash-db-0.16.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hash_db\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hash-db\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.16.0\",\n)\n" + } + }, + "firewood_crates__hash256-std-hasher-0.15.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hash256-std-hasher/0.15.2/download" + ], + "strip_prefix": "hash256-std-hasher-0.15.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hash256_std_hasher\",\n deps = [\n \"@firewood_crates__crunchy-0.2.4//:crunchy\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hash256-std-hasher\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.15.2\",\n)\n" + } + }, + "firewood_crates__hashbrown-0.14.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hashbrown/0.14.5/download" + ], + "strip_prefix": "hashbrown-0.14.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hashbrown\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"raw\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hashbrown\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.5\",\n)\n" + } + }, + "firewood_crates__hashbrown-0.15.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hashbrown/0.15.5/download" + ], + "strip_prefix": "hashbrown-0.15.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hashbrown\",\n deps = [\n \"@firewood_crates__foldhash-0.1.5//:foldhash\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default-hasher\",\n \"raw-entry\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hashbrown\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.15.5\",\n)\n" + } + }, + "firewood_crates__hashbrown-0.16.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hashbrown/0.16.0/download" + ], + "strip_prefix": "hashbrown-0.16.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hashbrown\",\n deps = [\n \"@firewood_crates__allocator-api2-0.2.21//:allocator_api2\",\n \"@firewood_crates__equivalent-1.0.2//:equivalent\",\n \"@firewood_crates__foldhash-0.2.0//:foldhash\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"allocator-api2\",\n \"default\",\n \"default-hasher\",\n \"equivalent\",\n \"inline-more\",\n \"raw-entry\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hashbrown\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.16.0\",\n)\n" + } + }, + "firewood_crates__heck-0.5.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/heck/0.5.0/download" + ], + "strip_prefix": "heck-0.5.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"heck\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=heck\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.0\",\n)\n" + } + }, + "firewood_crates__hermit-abi-0.5.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hermit-abi/0.5.2/download" + ], + "strip_prefix": "hermit-abi-0.5.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hermit_abi\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hermit-abi\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.2\",\n)\n" + } + }, + "firewood_crates__hex-0.4.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hex/0.4.3/download" + ], + "strip_prefix": "hex-0.4.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hex\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hex\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.3\",\n)\n" + } + }, + "firewood_crates__hex-literal-1.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hex-literal/1.1.0/download" + ], + "strip_prefix": "hex-literal-1.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hex_literal\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2024\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hex-literal\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.0\",\n)\n" + } + }, + "firewood_crates__http-1.3.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/http/1.3.1/download" + ], + "strip_prefix": "http-1.3.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"http\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__fnv-1.0.7//:fnv\",\n \"@firewood_crates__itoa-1.0.15//:itoa\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=http\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.3.1\",\n)\n" + } + }, + "firewood_crates__http-body-1.0.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/http-body/1.0.1/download" + ], + "strip_prefix": "http-body-1.0.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"http_body\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__http-1.3.1//:http\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=http-body\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.1\",\n)\n" + } + }, + "firewood_crates__http-body-util-0.1.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/http-body-util/0.1.3/download" + ], + "strip_prefix": "http-body-util-0.1.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"http_body_util\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__http-body-1.0.1//:http_body\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=http-body-util\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.3\",\n)\n" + } + }, + "firewood_crates__httparse-1.10.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/httparse/1.10.1/download" + ], + "strip_prefix": "httparse-1.10.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"httparse\",\n deps = [\n \"@firewood_crates__httparse-1.10.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=httparse\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.10.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"httparse\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=httparse\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.10.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__httpdate-1.0.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/httpdate/1.0.3/download" + ], + "strip_prefix": "httpdate-1.0.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"httpdate\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=httpdate\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.3\",\n)\n" + } + }, + "firewood_crates__hyper-1.8.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hyper/1.8.1/download" + ], + "strip_prefix": "hyper-1.8.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hyper\",\n deps = [\n \"@firewood_crates__atomic-waker-1.1.2//:atomic_waker\",\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\",\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__h2-0.4.12//:h2\",\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__http-body-1.0.1//:http_body\",\n \"@firewood_crates__httparse-1.10.1//:httparse\",\n \"@firewood_crates__httpdate-1.0.3//:httpdate\",\n \"@firewood_crates__itoa-1.0.15//:itoa\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__pin-utils-0.1.0//:pin_utils\",\n \"@firewood_crates__smallvec-1.15.1//:smallvec\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__want-0.3.1//:want\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"client\",\n \"default\",\n \"http1\",\n \"http2\",\n \"server\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hyper\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.8.1\",\n)\n" + } + }, + "firewood_crates__hyper-rustls-0.27.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hyper-rustls/0.27.7/download" + ], + "strip_prefix": "hyper-rustls-0.27.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hyper_rustls\",\n deps = [\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__hyper-1.8.1//:hyper\",\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\",\n \"@firewood_crates__rustls-0.23.35//:rustls\",\n \"@firewood_crates__rustls-native-certs-0.8.2//:rustls_native_certs\",\n \"@firewood_crates__rustls-pki-types-1.13.0//:rustls_pki_types\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__tokio-rustls-0.26.4//:tokio_rustls\",\n \"@firewood_crates__tower-service-0.3.3//:tower_service\",\n ],\n aliases = {\n \"@firewood_crates__rustls-pki-types-1.13.0//:rustls_pki_types\": \"pki_types\",\n },\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"aws-lc-rs\",\n \"http1\",\n \"rustls-native-certs\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hyper-rustls\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.27.7\",\n)\n" + } + }, + "firewood_crates__hyper-timeout-0.5.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hyper-timeout/0.5.2/download" + ], + "strip_prefix": "hyper-timeout-0.5.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hyper_timeout\",\n deps = [\n \"@firewood_crates__hyper-1.8.1//:hyper\",\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__tower-service-0.3.3//:tower_service\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hyper-timeout\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.2\",\n)\n" + } + }, + "firewood_crates__hyper-util-0.1.18": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/hyper-util/0.1.18/download" + ], + "strip_prefix": "hyper-util-0.1.18", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"hyper_util\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\",\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-util-0.3.31//:futures_util\",\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__http-body-1.0.1//:http_body\",\n \"@firewood_crates__hyper-1.8.1//:hyper\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__socket2-0.6.1//:socket2\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__tower-service-0.3.3//:tower_service\",\n \"@firewood_crates__tracing-0.1.41//:tracing\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__base64-0.22.1//:base64\", # aarch64-apple-darwin\n \"@firewood_crates__ipnet-2.11.0//:ipnet\", # aarch64-apple-darwin\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__base64-0.22.1//:base64\", # aarch64-unknown-linux-gnu\n \"@firewood_crates__ipnet-2.11.0//:ipnet\", # aarch64-unknown-linux-gnu\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__base64-0.22.1//:base64\", # x86_64-pc-windows-msvc\n \"@firewood_crates__ipnet-2.11.0//:ipnet\", # x86_64-pc-windows-msvc\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # x86_64-pc-windows-msvc\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__base64-0.22.1//:base64\", # x86_64-unknown-linux-gnu\n \"@firewood_crates__ipnet-2.11.0//:ipnet\", # x86_64-unknown-linux-gnu\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__base64-0.22.1//:base64\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n \"@firewood_crates__ipnet-2.11.0//:ipnet\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"client\",\n \"client-legacy\",\n \"default\",\n \"http1\",\n \"http2\",\n \"server\",\n \"server-auto\",\n \"service\",\n \"tokio\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"client-proxy\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"client-proxy\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"client-proxy\", # x86_64-pc-windows-msvc\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"client-proxy\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"client-proxy\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=hyper-util\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.18\",\n)\n" + } + }, + "firewood_crates__iana-time-zone-0.1.64": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/iana-time-zone/0.1.64/download" + ], + "strip_prefix": "iana-time-zone-0.1.64", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"iana_time_zone\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__core-foundation-sys-0.8.7//:core_foundation_sys\", # cfg(target_vendor = \"apple\")\n ],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__js-sys-0.3.82//:js_sys\", # cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))\n \"@firewood_crates__log-0.4.28//:log\", # cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\", # cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-core-0.62.2//:windows_core\", # cfg(target_os = \"windows\")\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"fallback\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=iana-time-zone\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.64\",\n)\n" + } + }, + "firewood_crates__iana-time-zone-haiku-0.1.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/iana-time-zone-haiku/0.1.2/download" + ], + "strip_prefix": "iana-time-zone-haiku-0.1.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"iana_time_zone_haiku\",\n deps = [\n \"@firewood_crates__iana-time-zone-haiku-0.1.2//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=iana-time-zone-haiku\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.2\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__cc-1.2.46//:cc\",\n ],\n edition = \"2018\",\n pkg_name = \"iana-time-zone-haiku\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=iana-time-zone-haiku\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.1.2\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__icu_collections-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/icu_collections/2.1.1/download" + ], + "strip_prefix": "icu_collections-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"icu_collections\",\n deps = [\n \"@firewood_crates__potential_utf-0.1.4//:potential_utf\",\n \"@firewood_crates__yoke-0.8.1//:yoke\",\n \"@firewood_crates__zerofrom-0.1.6//:zerofrom\",\n \"@firewood_crates__zerovec-0.11.5//:zerovec\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__displaydoc-0.2.5//:displaydoc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_collections\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n" + } + }, + "firewood_crates__icu_locale_core-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/icu_locale_core/2.1.1/download" + ], + "strip_prefix": "icu_locale_core-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"icu_locale_core\",\n deps = [\n \"@firewood_crates__litemap-0.8.1//:litemap\",\n \"@firewood_crates__tinystr-0.8.2//:tinystr\",\n \"@firewood_crates__writeable-0.6.2//:writeable\",\n \"@firewood_crates__zerovec-0.11.5//:zerovec\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__displaydoc-0.2.5//:displaydoc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"zerovec\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_locale_core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n" + } + }, + "firewood_crates__icu_normalizer-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/icu_normalizer/2.1.1/download" + ], + "strip_prefix": "icu_normalizer-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"icu_normalizer\",\n deps = [\n \"@firewood_crates__icu_collections-2.1.1//:icu_collections\",\n \"@firewood_crates__icu_normalizer_data-2.1.1//:icu_normalizer_data\",\n \"@firewood_crates__icu_provider-2.1.1//:icu_provider\",\n \"@firewood_crates__smallvec-1.15.1//:smallvec\",\n \"@firewood_crates__zerovec-0.11.5//:zerovec\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"compiled_data\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_normalizer\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n" + } + }, + "firewood_crates__icu_normalizer_data-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/icu_normalizer_data/2.1.1/download" + ], + "strip_prefix": "icu_normalizer_data-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"icu_normalizer_data\",\n deps = [\n \"@firewood_crates__icu_normalizer_data-2.1.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_normalizer_data\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"icu_normalizer_data\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_normalizer_data\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"2.1.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__icu_properties-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/icu_properties/2.1.1/download" + ], + "strip_prefix": "icu_properties-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"icu_properties\",\n deps = [\n \"@firewood_crates__icu_collections-2.1.1//:icu_collections\",\n \"@firewood_crates__icu_locale_core-2.1.1//:icu_locale_core\",\n \"@firewood_crates__icu_properties_data-2.1.1//:icu_properties_data\",\n \"@firewood_crates__icu_provider-2.1.1//:icu_provider\",\n \"@firewood_crates__zerotrie-0.2.3//:zerotrie\",\n \"@firewood_crates__zerovec-0.11.5//:zerovec\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"compiled_data\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_properties\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n" + } + }, + "firewood_crates__icu_properties_data-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/icu_properties_data/2.1.1/download" + ], + "strip_prefix": "icu_properties_data-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"icu_properties_data\",\n deps = [\n \"@firewood_crates__icu_properties_data-2.1.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_properties_data\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"icu_properties_data\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_properties_data\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"2.1.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__icu_provider-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/icu_provider/2.1.1/download" + ], + "strip_prefix": "icu_provider-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"icu_provider\",\n deps = [\n \"@firewood_crates__icu_locale_core-2.1.1//:icu_locale_core\",\n \"@firewood_crates__writeable-0.6.2//:writeable\",\n \"@firewood_crates__yoke-0.8.1//:yoke\",\n \"@firewood_crates__zerofrom-0.1.6//:zerofrom\",\n \"@firewood_crates__zerotrie-0.2.3//:zerotrie\",\n \"@firewood_crates__zerovec-0.11.5//:zerovec\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__displaydoc-0.2.5//:displaydoc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"baked\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=icu_provider\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n" + } + }, + "firewood_crates__idna-1.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/idna/1.1.0/download" + ], + "strip_prefix": "idna-1.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"idna\",\n deps = [\n \"@firewood_crates__idna_adapter-1.2.1//:idna_adapter\",\n \"@firewood_crates__smallvec-1.15.1//:smallvec\",\n \"@firewood_crates__utf8_iter-1.0.4//:utf8_iter\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"compiled_data\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=idna\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.0\",\n)\n" + } + }, + "firewood_crates__idna_adapter-1.2.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/idna_adapter/1.2.1/download" + ], + "strip_prefix": "idna_adapter-1.2.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"idna_adapter\",\n deps = [\n \"@firewood_crates__icu_normalizer-2.1.1//:icu_normalizer\",\n \"@firewood_crates__icu_properties-2.1.1//:icu_properties\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"compiled_data\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=idna_adapter\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.2.1\",\n)\n" + } + }, + "firewood_crates__impl-codec-0.7.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2d40b9d5e17727407e55028eafc22b2dc68781786e6d7eb8a21103f5058e3a14", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/impl-codec/0.7.1/download" + ], + "strip_prefix": "impl-codec-0.7.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"impl_codec\",\n deps = [\n \"@firewood_crates__parity-scale-codec-3.7.5//:parity_scale_codec\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=impl-codec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.1\",\n)\n" + } + }, + "firewood_crates__impl-rlp-0.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "54ed8ad1f3877f7e775b8cbf30ed1bd3209a95401817f19a0eb4402d13f8cf90", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/impl-rlp/0.4.0/download" + ], + "strip_prefix": "impl-rlp-0.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"impl_rlp\",\n deps = [\n \"@firewood_crates__rlp-0.6.1//:rlp\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=impl-rlp\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.0\",\n)\n" + } + }, + "firewood_crates__impl-serde-0.5.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "4a143eada6a1ec4aefa5049037a26a6d597bfd64f8c026d07b77133e02b7dd0b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/impl-serde/0.5.0/download" + ], + "strip_prefix": "impl-serde-0.5.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"impl_serde\",\n deps = [\n \"@firewood_crates__serde-1.0.228//:serde\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=impl-serde\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.0\",\n)\n" + } + }, + "firewood_crates__impl-trait-for-tuples-0.2.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/impl-trait-for-tuples/0.2.3/download" + ], + "strip_prefix": "impl-trait-for-tuples-0.2.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"impl_trait_for_tuples\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=impl-trait-for-tuples\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.3\",\n)\n" + } + }, + "firewood_crates__include_dir-0.7.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/include_dir/0.7.4/download" + ], + "strip_prefix": "include_dir-0.7.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"include_dir\",\n proc_macro_deps = [\n \"@firewood_crates__include_dir_macros-0.7.4//:include_dir_macros\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=include_dir\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.4\",\n)\n" + } + }, + "firewood_crates__include_dir_macros-0.7.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/include_dir_macros/0.7.4/download" + ], + "strip_prefix": "include_dir_macros-0.7.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"include_dir_macros\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=include_dir_macros\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.4\",\n)\n" + } + }, + "firewood_crates__indexmap-2.12.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/indexmap/2.12.0/download" + ], + "strip_prefix": "indexmap-2.12.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"indexmap\",\n deps = [\n \"@firewood_crates__equivalent-1.0.2//:equivalent\",\n \"@firewood_crates__hashbrown-0.16.0//:hashbrown\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=indexmap\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.12.0\",\n)\n" + } + }, + "firewood_crates__indicatif-0.18.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/indicatif/0.18.3/download" + ], + "strip_prefix": "indicatif-0.18.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"indicatif\",\n deps = [\n \"@firewood_crates__console-0.16.1//:console\",\n \"@firewood_crates__portable-atomic-1.11.1//:portable_atomic\",\n \"@firewood_crates__unicode-width-0.2.2//:unicode_width\",\n \"@firewood_crates__unit-prefix-0.5.2//:unit_prefix\",\n ] + select({\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__web-time-1.1.0//:web_time\", # cfg(target_arch = \"wasm32\")\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__web-time-1.1.0//:web_time\", # cfg(target_arch = \"wasm32\")\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"unicode-width\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=indicatif\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.18.3\",\n)\n" + } + }, + "firewood_crates__inferno-0.11.21": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/inferno/0.11.21/download" + ], + "strip_prefix": "inferno-0.11.21", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"inferno\",\n deps = [\n \"@firewood_crates__ahash-0.8.12//:ahash\",\n \"@firewood_crates__indexmap-2.12.0//:indexmap\",\n \"@firewood_crates__is-terminal-0.4.17//:is_terminal\",\n \"@firewood_crates__itoa-1.0.15//:itoa\",\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__num-format-0.4.4//:num_format\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__quick-xml-0.26.0//:quick_xml\",\n \"@firewood_crates__rgb-0.8.52//:rgb\",\n \"@firewood_crates__str_stack-0.1.0//:str_stack\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"indexmap\",\n \"nameattr\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=inferno\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.11.21\",\n)\n" + } + }, + "firewood_crates__integer-encoding-4.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "14c00403deb17c3221a1fe4fb571b9ed0370b3dcd116553c77fa294a3d918699", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/integer-encoding/4.1.0/download" + ], + "strip_prefix": "integer-encoding-4.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"integer_encoding\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=integer-encoding\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"4.1.0\",\n)\n" + } + }, + "firewood_crates__interval-heap-0.0.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "11274e5e8e89b8607cfedc2910b6626e998779b48a019151c7604d0adcb86ac6", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/interval-heap/0.0.5/download" + ], + "strip_prefix": "interval-heap-0.0.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"interval_heap\",\n deps = [\n \"@firewood_crates__compare-0.0.6//:compare\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=interval-heap\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.0.5\",\n)\n" + } + }, + "firewood_crates__io-uring-0.7.11": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "fdd7bddefd0a8833b88a4b68f90dae22c7450d11b354198baee3874fd811b344", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/io-uring/0.7.11/download" + ], + "strip_prefix": "io-uring-0.7.11", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"io_uring\",\n deps = [\n \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__io-uring-0.7.11//:build_script_build\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=io-uring\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.11\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"io-uring\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=io-uring\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.7.11\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__ipnet-2.11.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ipnet/2.11.0/download" + ], + "strip_prefix": "ipnet-2.11.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ipnet\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"default\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"default\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"default\", # x86_64-pc-windows-msvc\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"default\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"default\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ipnet\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.11.0\",\n)\n" + } + }, + "firewood_crates__iri-string-0.7.9": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/iri-string/0.7.9/download" + ], + "strip_prefix": "iri-string-0.7.9", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"iri_string\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=iri-string\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.9\",\n)\n" + } + }, + "firewood_crates__is-terminal-0.4.17": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/is-terminal/0.4.17/download" + ], + "strip_prefix": "is-terminal-0.4.17", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"is_terminal\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=is-terminal\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.17\",\n)\n" + } + }, + "firewood_crates__is_terminal_polyfill-1.70.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/is_terminal_polyfill/1.70.2/download" + ], + "strip_prefix": "is_terminal_polyfill-1.70.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"is_terminal_polyfill\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=is_terminal_polyfill\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.70.2\",\n)\n" + } + }, + "firewood_crates__itertools-0.10.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/itertools/0.10.5/download" + ], + "strip_prefix": "itertools-0.10.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"itertools\",\n deps = [\n \"@firewood_crates__either-1.15.0//:either\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"use_alloc\",\n \"use_std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=itertools\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.5\",\n)\n" + } + }, + "firewood_crates__itertools-0.13.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/itertools/0.13.0/download" + ], + "strip_prefix": "itertools-0.13.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"itertools\",\n deps = [\n \"@firewood_crates__either-1.15.0//:either\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"use_alloc\",\n \"use_std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=itertools\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.13.0\",\n)\n" + } + }, + "firewood_crates__itertools-0.14.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/itertools/0.14.0/download" + ], + "strip_prefix": "itertools-0.14.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"itertools\",\n deps = [\n \"@firewood_crates__either-1.15.0//:either\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"use_alloc\",\n \"use_std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=itertools\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.0\",\n)\n" + } + }, + "firewood_crates__itoa-1.0.15": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/itoa/1.0.15/download" + ], + "strip_prefix": "itoa-1.0.15", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"itoa\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=itoa\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.15\",\n)\n" + } + }, + "firewood_crates__jiff-0.2.16": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/jiff/0.2.16/download" + ], + "strip_prefix": "jiff-0.2.16", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"jiff\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=jiff\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.16\",\n)\n" + } + }, + "firewood_crates__jiff-static-0.2.16": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/jiff-static/0.2.16/download" + ], + "strip_prefix": "jiff-static-0.2.16", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"jiff_static\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=jiff-static\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.16\",\n)\n" + } + }, + "firewood_crates__jobserver-0.1.34": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/jobserver/0.1.34/download" + ], + "strip_prefix": "jobserver-0.1.34", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"jobserver\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__getrandom-0.3.4//:getrandom\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=jobserver\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.34\",\n)\n" + } + }, + "firewood_crates__js-sys-0.3.82": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/js-sys/0.3.82/download" + ], + "strip_prefix": "js-sys-0.3.82", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"js_sys\",\n deps = [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=js-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.82\",\n)\n" + } + }, + "firewood_crates__keccak-0.1.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/keccak/0.1.5/download" + ], + "strip_prefix": "keccak-0.1.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"keccak\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(target_arch = \"aarch64\")\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(target_arch = \"aarch64\")\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=keccak\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.5\",\n)\n" + } + }, + "firewood_crates__keccak-hasher-0.16.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "19ea4653859ca2266a86419d3f592d3f22e7a854b482f99180d2498507902048", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/keccak-hasher/0.16.0/download" + ], + "strip_prefix": "keccak-hasher-0.16.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"keccak_hasher\",\n deps = [\n \"@firewood_crates__hash-db-0.16.0//:hash_db\",\n \"@firewood_crates__hash256-std-hasher-0.15.2//:hash256_std_hasher\",\n \"@firewood_crates__tiny-keccak-2.0.2//:tiny_keccak\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=keccak-hasher\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.16.0\",\n)\n" + } + }, + "firewood_crates__lazy_static-1.5.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/lazy_static/1.5.0/download" + ], + "strip_prefix": "lazy_static-1.5.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"lazy_static\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=lazy_static\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.5.0\",\n)\n" + } + }, + "firewood_crates__libc-0.2.177": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/libc/0.2.177/download" + ], + "strip_prefix": "libc-0.2.177", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"libc\",\n deps = [\n \"@firewood_crates__libc-0.2.177//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"extra_traits\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=libc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.177\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"extra_traits\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"libc\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=libc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.2.177\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__libloading-0.8.9": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/libloading/0.8.9/download" + ], + "strip_prefix": "libloading-0.8.9", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"libloading\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-link-0.2.1//:windows_link\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=libloading\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.9\",\n)\n" + } + }, + "firewood_crates__libm-0.2.15": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/libm/0.2.15/download" + ], + "strip_prefix": "libm-0.2.15", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"libm\",\n deps = [\n \"@firewood_crates__libm-0.2.15//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"arch\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=libm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.15\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"arch\",\n \"default\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"libm\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=libm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.2.15\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__linux-raw-sys-0.11.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/linux-raw-sys/0.11.0/download" + ], + "strip_prefix": "linux-raw-sys-0.11.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"linux_raw_sys\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"auxvec\",\n \"elf\",\n \"errno\",\n \"general\",\n \"ioctl\",\n \"no_std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=linux-raw-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.11.0\",\n)\n" + } + }, + "firewood_crates__litemap-0.8.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/litemap/0.8.1/download" + ], + "strip_prefix": "litemap-0.8.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"litemap\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=litemap\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.1\",\n)\n" + } + }, + "firewood_crates__lock_api-0.4.14": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/lock_api/0.4.14/download" + ], + "strip_prefix": "lock_api-0.4.14", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"lock_api\",\n deps = [\n \"@firewood_crates__scopeguard-1.2.0//:scopeguard\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"atomic_usize\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=lock_api\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.14\",\n)\n" + } + }, + "firewood_crates__log-0.4.28": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/log/0.4.28/download" + ], + "strip_prefix": "log-0.4.28", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"log\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=log\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.28\",\n)\n" + } + }, + "firewood_crates__lru-0.16.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/lru/0.16.2/download" + ], + "strip_prefix": "lru-0.16.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"lru\",\n deps = [\n \"@firewood_crates__hashbrown-0.16.0//:hashbrown\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"hashbrown\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=lru\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.16.2\",\n)\n" + } + }, + "firewood_crates__lsm-tree-2.10.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "799399117a2bfb37660e08be33f470958babb98386b04185288d829df362ea15", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/lsm-tree/2.10.4/download" + ], + "strip_prefix": "lsm-tree-2.10.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"lsm_tree\",\n deps = [\n \"@firewood_crates__byteorder-1.5.0//:byteorder\",\n \"@firewood_crates__crossbeam-skiplist-0.1.3//:crossbeam_skiplist\",\n \"@firewood_crates__double-ended-peekable-0.1.0//:double_ended_peekable\",\n \"@firewood_crates__guardian-1.3.0//:guardian\",\n \"@firewood_crates__interval-heap-0.0.5//:interval_heap\",\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__lz4_flex-0.11.5//:lz4_flex\",\n \"@firewood_crates__path-absolutize-3.1.1//:path_absolutize\",\n \"@firewood_crates__quick_cache-0.6.18//:quick_cache\",\n \"@firewood_crates__rustc-hash-2.1.1//:rustc_hash\",\n \"@firewood_crates__self_cell-1.2.1//:self_cell\",\n \"@firewood_crates__tempfile-3.23.0//:tempfile\",\n \"@firewood_crates__value-log-1.9.0//:value_log\",\n \"@firewood_crates__varint-rs-2.2.0//:varint_rs\",\n \"@firewood_crates__xxhash-rust-0.8.15//:xxhash_rust\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__enum_dispatch-0.3.13//:enum_dispatch\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"lz4\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=lsm-tree\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.10.4\",\n)\n" + } + }, + "firewood_crates__lz4_flex-0.11.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/lz4_flex/0.11.5/download" + ], + "strip_prefix": "lz4_flex-0.11.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"lz4_flex\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=lz4_flex\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.11.5\",\n)\n" + } + }, + "firewood_crates__memchr-2.7.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/memchr/2.7.6/download" + ], + "strip_prefix": "memchr-2.7.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"memchr\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=memchr\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.7.6\",\n)\n" + } + }, + "firewood_crates__memmap2-0.9.9": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/memmap2/0.9.9/download" + ], + "strip_prefix": "memmap2-0.9.9", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"memmap2\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=memmap2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.9\",\n)\n" + } + }, + "firewood_crates__metrics-0.24.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "25dea7ac8057892855ec285c440160265225438c3c45072613c25a4b26e98ef5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/metrics/0.24.2/download" + ], + "strip_prefix": "metrics-0.24.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"metrics\",\n deps = [\n \"@firewood_crates__ahash-0.8.12//:ahash\",\n ] + select({\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__portable-atomic-1.11.1//:portable_atomic\", # cfg(target_pointer_width = \"32\")\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__portable-atomic-1.11.1//:portable_atomic\", # cfg(target_pointer_width = \"32\")\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=metrics\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.24.2\",\n)\n" + } + }, + "firewood_crates__metrics-exporter-prometheus-0.17.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2b166dea96003ee2531cf14833efedced545751d800f03535801d833313f8c15", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/metrics-exporter-prometheus/0.17.2/download" + ], + "strip_prefix": "metrics-exporter-prometheus-0.17.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"metrics_exporter_prometheus\",\n deps = [\n \"@firewood_crates__base64-0.22.1//:base64\",\n \"@firewood_crates__http-body-util-0.1.3//:http_body_util\",\n \"@firewood_crates__hyper-1.8.1//:hyper\",\n \"@firewood_crates__hyper-rustls-0.27.7//:hyper_rustls\",\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\",\n \"@firewood_crates__indexmap-2.12.0//:indexmap\",\n \"@firewood_crates__ipnet-2.11.0//:ipnet\",\n \"@firewood_crates__metrics-0.24.2//:metrics\",\n \"@firewood_crates__metrics-util-0.20.0//:metrics_util\",\n \"@firewood_crates__quanta-0.12.6//:quanta\",\n \"@firewood_crates__thiserror-2.0.17//:thiserror\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__tracing-0.1.41//:tracing\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"_hyper-client\",\n \"_hyper-server\",\n \"async-runtime\",\n \"default\",\n \"http-body-util\",\n \"http-listener\",\n \"hyper\",\n \"hyper-rustls\",\n \"hyper-util\",\n \"ipnet\",\n \"push-gateway\",\n \"tokio\",\n \"tracing\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=metrics-exporter-prometheus\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.17.2\",\n)\n" + } + }, + "firewood_crates__metrics-util-0.20.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "fe8db7a05415d0f919ffb905afa37784f71901c9a773188876984b4f769ab986", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/metrics-util/0.20.0/download" + ], + "strip_prefix": "metrics-util-0.20.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"metrics_util\",\n deps = [\n \"@firewood_crates__aho-corasick-1.1.4//:aho_corasick\",\n \"@firewood_crates__crossbeam-epoch-0.9.18//:crossbeam_epoch\",\n \"@firewood_crates__crossbeam-utils-0.8.21//:crossbeam_utils\",\n \"@firewood_crates__hashbrown-0.15.5//:hashbrown\",\n \"@firewood_crates__indexmap-2.12.0//:indexmap\",\n \"@firewood_crates__metrics-0.24.2//:metrics\",\n \"@firewood_crates__ordered-float-4.6.0//:ordered_float\",\n \"@firewood_crates__quanta-0.12.6//:quanta\",\n \"@firewood_crates__radix_trie-0.2.1//:radix_trie\",\n \"@firewood_crates__rand-0.9.2//:rand\",\n \"@firewood_crates__rand_xoshiro-0.7.0//:rand_xoshiro\",\n \"@firewood_crates__sketches-ddsketch-0.3.0//:sketches_ddsketch\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"aho-corasick\",\n \"crossbeam-epoch\",\n \"crossbeam-utils\",\n \"debugging\",\n \"default\",\n \"hashbrown\",\n \"indexmap\",\n \"layer-filter\",\n \"layer-router\",\n \"layers\",\n \"ordered-float\",\n \"quanta\",\n \"radix_trie\",\n \"rand\",\n \"rand_xoshiro\",\n \"recency\",\n \"registry\",\n \"sketches-ddsketch\",\n \"storage\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=metrics-util\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.20.0\",\n)\n" + } + }, + "firewood_crates__minimal-lexical-0.2.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/minimal-lexical/0.2.1/download" + ], + "strip_prefix": "minimal-lexical-0.2.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"minimal_lexical\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=minimal-lexical\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.1\",\n)\n" + } + }, + "firewood_crates__miniz_oxide-0.8.9": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/miniz_oxide/0.8.9/download" + ], + "strip_prefix": "miniz_oxide-0.8.9", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"miniz_oxide\",\n deps = [\n \"@firewood_crates__adler2-2.0.1//:adler2\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=miniz_oxide\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.9\",\n)\n" + } + }, + "firewood_crates__mio-1.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/mio/1.1.0/download" + ], + "strip_prefix": "mio-1.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"mio\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(target_os = \"wasi\")\n \"@firewood_crates__wasi-0.11.1-wasi-snapshot-preview1//:wasi\", # cfg(target_os = \"wasi\")\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"net\",\n \"os-ext\",\n \"os-poll\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=mio\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.0\",\n)\n" + } + }, + "firewood_crates__nibble_vec-0.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/nibble_vec/0.1.0/download" + ], + "strip_prefix": "nibble_vec-0.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"nibble_vec\",\n deps = [\n \"@firewood_crates__smallvec-1.15.1//:smallvec\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=nibble_vec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.0\",\n)\n" + } + }, + "firewood_crates__nix-0.26.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/nix/0.26.4/download" + ], + "strip_prefix": "nix-0.26.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"nix\",\n deps = [\n \"@firewood_crates__bitflags-1.3.2//:bitflags\",\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"fs\",\n \"process\",\n \"signal\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=nix\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.26.4\",\n)\n" + } + }, + "firewood_crates__nom-7.1.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/nom/7.1.3/download" + ], + "strip_prefix": "nom-7.1.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"nom\",\n deps = [\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__minimal-lexical-0.2.1//:minimal_lexical\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=nom\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"7.1.3\",\n)\n" + } + }, + "firewood_crates__nonzero_ext-0.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/nonzero_ext/0.3.0/download" + ], + "strip_prefix": "nonzero_ext-0.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"nonzero_ext\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=nonzero_ext\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.0\",\n)\n" + } + }, + "firewood_crates__normalize-line-endings-0.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/normalize-line-endings/0.3.0/download" + ], + "strip_prefix": "normalize-line-endings-0.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"normalize_line_endings\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=normalize-line-endings\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.0\",\n)\n" + } + }, + "firewood_crates__num-format-0.4.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/num-format/0.4.4/download" + ], + "strip_prefix": "num-format-0.4.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"num_format\",\n deps = [\n \"@firewood_crates__arrayvec-0.7.6//:arrayvec\",\n \"@firewood_crates__itoa-1.0.15//:itoa\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=num-format\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.4\",\n)\n" + } + }, + "firewood_crates__num-traits-0.2.19": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/num-traits/0.2.19/download" + ], + "strip_prefix": "num-traits-0.2.19", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"num_traits\",\n deps = [\n \"@firewood_crates__libm-0.2.15//:libm\",\n \"@firewood_crates__num-traits-0.2.19//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"libm\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=num-traits\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.19\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"libm\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__autocfg-1.5.0//:autocfg\",\n ],\n edition = \"2021\",\n pkg_name = \"num-traits\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=num-traits\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.2.19\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__object-0.37.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/object/0.37.3/download" + ], + "strip_prefix": "object-0.37.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"object\",\n deps = [\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__object-0.37.3//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"archive\",\n \"coff\",\n \"elf\",\n \"macho\",\n \"pe\",\n \"read_core\",\n \"unaligned\",\n \"xcoff\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=object\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.37.3\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"archive\",\n \"coff\",\n \"elf\",\n \"macho\",\n \"pe\",\n \"read_core\",\n \"unaligned\",\n \"xcoff\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"object\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=object\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.37.3\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__once_cell-1.21.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/once_cell/1.21.3/download" + ], + "strip_prefix": "once_cell-1.21.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"once_cell\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"race\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=once_cell\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.21.3\",\n)\n" + } + }, + "firewood_crates__once_cell_polyfill-1.70.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/once_cell_polyfill/1.70.2/download" + ], + "strip_prefix": "once_cell_polyfill-1.70.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"once_cell_polyfill\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=once_cell_polyfill\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.70.2\",\n)\n" + } + }, + "firewood_crates__oorandom-11.1.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/oorandom/11.1.5/download" + ], + "strip_prefix": "oorandom-11.1.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"oorandom\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=oorandom\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"11.1.5\",\n)\n" + } + }, + "firewood_crates__openssl-probe-0.1.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/openssl-probe/0.1.6/download" + ], + "strip_prefix": "openssl-probe-0.1.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"openssl_probe\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=openssl-probe\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.6\",\n)\n" + } + }, + "firewood_crates__opentelemetry-0.31.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/opentelemetry/0.31.0/download" + ], + "strip_prefix": "opentelemetry-0.31.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"opentelemetry\",\n deps = [\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-sink-0.3.31//:futures_sink\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__thiserror-2.0.17//:thiserror\",\n \"@firewood_crates__tracing-0.1.41//:tracing\",\n ] + select({\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__js-sys-0.3.82//:js_sys\", # cfg(all(target_arch = \"wasm32\", not(target_os = \"wasi\")))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"futures\",\n \"futures-core\",\n \"futures-sink\",\n \"internal-logs\",\n \"logs\",\n \"metrics\",\n \"pin-project-lite\",\n \"thiserror\",\n \"trace\",\n \"tracing\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=opentelemetry\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.31.0\",\n)\n" + } + }, + "firewood_crates__opentelemetry-http-0.31.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/opentelemetry-http/0.31.0/download" + ], + "strip_prefix": "opentelemetry-http-0.31.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"opentelemetry_http\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__opentelemetry-0.31.0//:opentelemetry\",\n \"@firewood_crates__reqwest-0.12.24//:reqwest\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__async-trait-0.1.89//:async_trait\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"internal-logs\",\n \"reqwest\",\n \"reqwest-blocking\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=opentelemetry-http\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.31.0\",\n)\n" + } + }, + "firewood_crates__opentelemetry-otlp-0.31.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/opentelemetry-otlp/0.31.0/download" + ], + "strip_prefix": "opentelemetry-otlp-0.31.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"opentelemetry_otlp\",\n deps = [\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__opentelemetry-0.31.0//:opentelemetry\",\n \"@firewood_crates__opentelemetry-http-0.31.0//:opentelemetry_http\",\n \"@firewood_crates__opentelemetry-proto-0.31.0//:opentelemetry_proto\",\n \"@firewood_crates__opentelemetry_sdk-0.31.0//:opentelemetry_sdk\",\n \"@firewood_crates__prost-0.14.1//:prost\",\n \"@firewood_crates__reqwest-0.12.24//:reqwest\",\n \"@firewood_crates__thiserror-2.0.17//:thiserror\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__tonic-0.14.2//:tonic\",\n \"@firewood_crates__tracing-0.1.41//:tracing\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"grpc-tonic\",\n \"http\",\n \"http-proto\",\n \"internal-logs\",\n \"logs\",\n \"metrics\",\n \"opentelemetry-http\",\n \"prost\",\n \"reqwest\",\n \"reqwest-blocking-client\",\n \"tokio\",\n \"tonic\",\n \"trace\",\n \"tracing\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=opentelemetry-otlp\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.31.0\",\n)\n" + } + }, + "firewood_crates__opentelemetry-proto-0.31.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/opentelemetry-proto/0.31.0/download" + ], + "strip_prefix": "opentelemetry-proto-0.31.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"opentelemetry_proto\",\n deps = [\n \"@firewood_crates__base64-0.22.1//:base64\",\n \"@firewood_crates__const-hex-1.17.0//:const_hex\",\n \"@firewood_crates__opentelemetry-0.31.0//:opentelemetry\",\n \"@firewood_crates__opentelemetry_sdk-0.31.0//:opentelemetry_sdk\",\n \"@firewood_crates__prost-0.14.1//:prost\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__serde_json-1.0.145//:serde_json\",\n \"@firewood_crates__tonic-0.14.2//:tonic\",\n \"@firewood_crates__tonic-prost-0.14.2//:tonic_prost\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"base64\",\n \"const-hex\",\n \"default\",\n \"full\",\n \"gen-tonic\",\n \"gen-tonic-messages\",\n \"internal-logs\",\n \"logs\",\n \"metrics\",\n \"prost\",\n \"serde\",\n \"serde_json\",\n \"tonic\",\n \"tonic-prost\",\n \"trace\",\n \"with-serde\",\n \"zpages\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=opentelemetry-proto\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.31.0\",\n)\n" + } + }, + "firewood_crates__opentelemetry_sdk-0.31.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/opentelemetry_sdk/0.31.0/download" + ], + "strip_prefix": "opentelemetry_sdk-0.31.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"opentelemetry_sdk\",\n deps = [\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\",\n \"@firewood_crates__futures-executor-0.3.31//:futures_executor\",\n \"@firewood_crates__futures-util-0.3.31//:futures_util\",\n \"@firewood_crates__opentelemetry-0.31.0//:opentelemetry\",\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\",\n \"@firewood_crates__rand-0.9.2//:rand\",\n \"@firewood_crates__thiserror-2.0.17//:thiserror\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"internal-logs\",\n \"logs\",\n \"metrics\",\n \"percent-encoding\",\n \"rand\",\n \"trace\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=opentelemetry_sdk\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.31.0\",\n)\n" + } + }, + "firewood_crates__ordered-float-4.6.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ordered-float/4.6.0/download" + ], + "strip_prefix": "ordered-float-4.6.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ordered_float\",\n deps = [\n \"@firewood_crates__num-traits-0.2.19//:num_traits\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ordered-float\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"4.6.0\",\n)\n" + } + }, + "firewood_crates__oxhttp-0.3.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "971c03797806d47915950e62816a8f365e3ddc8800310e3200ec666934d0f7c9", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/oxhttp/0.3.1/download" + ], + "strip_prefix": "oxhttp-0.3.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"oxhttp\",\n deps = [\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__httparse-1.10.1//:httparse\",\n \"@firewood_crates__url-2.5.7//:url\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"client\",\n \"default\",\n \"server\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=oxhttp\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.1\",\n)\n" + } + }, + "firewood_crates__parity-scale-codec-3.7.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/parity-scale-codec/3.7.5/download" + ], + "strip_prefix": "parity-scale-codec-3.7.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"parity_scale_codec\",\n deps = [\n \"@firewood_crates__arrayvec-0.7.6//:arrayvec\",\n \"@firewood_crates__byte-slice-cast-1.2.3//:byte_slice_cast\",\n \"@firewood_crates__const_format-0.2.35//:const_format\",\n \"@firewood_crates__parity-scale-codec-3.7.5//:build_script_build\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__impl-trait-for-tuples-0.2.3//:impl_trait_for_tuples\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=parity-scale-codec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.7.5\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"parity-scale-codec\",\n proc_macro_deps = [\n \"@firewood_crates__rustversion-1.0.22//:rustversion\",\n ],\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=parity-scale-codec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"3.7.5\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__parity-scale-codec-derive-3.7.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/parity-scale-codec-derive/3.7.5/download" + ], + "strip_prefix": "parity-scale-codec-derive-3.7.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"parity_scale_codec_derive\",\n deps = [\n \"@firewood_crates__proc-macro-crate-3.4.0//:proc_macro_crate\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=parity-scale-codec-derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.7.5\",\n)\n" + } + }, + "firewood_crates__parking_lot-0.12.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/parking_lot/0.12.5/download" + ], + "strip_prefix": "parking_lot-0.12.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"parking_lot\",\n deps = [\n \"@firewood_crates__lock_api-0.4.14//:lock_api\",\n \"@firewood_crates__parking_lot_core-0.9.12//:parking_lot_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=parking_lot\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.12.5\",\n)\n" + } + }, + "firewood_crates__parking_lot_core-0.9.12": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/parking_lot_core/0.9.12/download" + ], + "strip_prefix": "parking_lot_core-0.9.12", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"parking_lot_core\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__parking_lot_core-0.9.12//:build_script_build\",\n \"@firewood_crates__smallvec-1.15.1//:smallvec\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-link-0.2.1//:windows_link\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=parking_lot_core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.12\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"parking_lot_core\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=parking_lot_core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.9.12\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__path-absolutize-3.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/path-absolutize/3.1.1/download" + ], + "strip_prefix": "path-absolutize-3.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"path_absolutize\",\n deps = [\n \"@firewood_crates__path-dedot-3.1.1//:path_dedot\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=path-absolutize\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.1.1\",\n)\n" + } + }, + "firewood_crates__path-dedot-3.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/path-dedot/3.1.1/download" + ], + "strip_prefix": "path-dedot-3.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"path_dedot\",\n deps = [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=path-dedot\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.1.1\",\n)\n" + } + }, + "firewood_crates__percent-encoding-2.3.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/percent-encoding/2.3.2/download" + ], + "strip_prefix": "percent-encoding-2.3.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"percent_encoding\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=percent-encoding\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.3.2\",\n)\n" + } + }, + "firewood_crates__pin-project-1.1.10": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/pin-project/1.1.10/download" + ], + "strip_prefix": "pin-project-1.1.10", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"pin_project\",\n proc_macro_deps = [\n \"@firewood_crates__pin-project-internal-1.1.10//:pin_project_internal\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=pin-project\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.10\",\n)\n" + } + }, + "firewood_crates__pin-project-internal-1.1.10": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/pin-project-internal/1.1.10/download" + ], + "strip_prefix": "pin-project-internal-1.1.10", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"pin_project_internal\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=pin-project-internal\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.10\",\n)\n" + } + }, + "firewood_crates__pin-project-lite-0.2.16": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/pin-project-lite/0.2.16/download" + ], + "strip_prefix": "pin-project-lite-0.2.16", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"pin_project_lite\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=pin-project-lite\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.16\",\n)\n" + } + }, + "firewood_crates__pin-utils-0.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/pin-utils/0.1.0/download" + ], + "strip_prefix": "pin-utils-0.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"pin_utils\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=pin-utils\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.0\",\n)\n" + } + }, + "firewood_crates__plain_hasher-0.2.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1e19e6491bdde87c2c43d70f4c194bc8a758f2eb732df00f61e43f7362e3b4cc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/plain_hasher/0.2.3/download" + ], + "strip_prefix": "plain_hasher-0.2.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"plain_hasher\",\n deps = [\n \"@firewood_crates__crunchy-0.2.4//:crunchy\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=plain_hasher\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.3\",\n)\n" + } + }, + "firewood_crates__plotters-0.3.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/plotters/0.3.7/download" + ], + "strip_prefix": "plotters-0.3.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"plotters\",\n deps = [\n \"@firewood_crates__num-traits-0.2.19//:num_traits\",\n \"@firewood_crates__plotters-backend-0.3.7//:plotters_backend\",\n \"@firewood_crates__plotters-svg-0.3.7//:plotters_svg\",\n ] + select({\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\", # cfg(all(target_arch = \"wasm32\", not(target_os = \"wasi\")))\n \"@firewood_crates__web-sys-0.3.82//:web_sys\", # cfg(all(target_arch = \"wasm32\", not(target_os = \"wasi\")))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"area_series\",\n \"line_series\",\n \"plotters-svg\",\n \"svg_backend\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=plotters\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.7\",\n)\n" + } + }, + "firewood_crates__plotters-backend-0.3.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/plotters-backend/0.3.7/download" + ], + "strip_prefix": "plotters-backend-0.3.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"plotters_backend\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=plotters-backend\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.7\",\n)\n" + } + }, + "firewood_crates__plotters-svg-0.3.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/plotters-svg/0.3.7/download" + ], + "strip_prefix": "plotters-svg-0.3.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"plotters_svg\",\n deps = [\n \"@firewood_crates__plotters-backend-0.3.7//:plotters_backend\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=plotters-svg\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.7\",\n)\n" + } + }, + "firewood_crates__pollster-0.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/pollster/0.4.0/download" + ], + "strip_prefix": "pollster-0.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"pollster\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=pollster\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.0\",\n)\n" + } + }, + "firewood_crates__portable-atomic-1.11.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/portable-atomic/1.11.1/download" + ], + "strip_prefix": "portable-atomic-1.11.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"portable_atomic\",\n deps = [\n \"@firewood_crates__portable-atomic-1.11.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"fallback\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=portable-atomic\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.11.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"fallback\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"portable-atomic\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=portable-atomic\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.11.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__portable-atomic-util-0.2.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/portable-atomic-util/0.2.4/download" + ], + "strip_prefix": "portable-atomic-util-0.2.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"portable_atomic_util\",\n deps = [\n \"@firewood_crates__portable-atomic-1.11.1//:portable_atomic\",\n \"@firewood_crates__portable-atomic-util-0.2.4//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=portable-atomic-util\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.4\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"portable-atomic-util\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=portable-atomic-util\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.2.4\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__potential_utf-0.1.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/potential_utf/0.1.4/download" + ], + "strip_prefix": "potential_utf-0.1.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"potential_utf\",\n deps = [\n \"@firewood_crates__zerovec-0.11.5//:zerovec\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"zerovec\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=potential_utf\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.4\",\n)\n" + } + }, + "firewood_crates__pprof-0.15.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "38a01da47675efa7673b032bf8efd8214f1917d89685e07e395ab125ea42b187", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/pprof/0.15.0/download" + ], + "strip_prefix": "pprof-0.15.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"pprof\",\n deps = [\n \"@firewood_crates__aligned-vec-0.6.4//:aligned_vec\",\n \"@firewood_crates__backtrace-0.3.76//:backtrace\",\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__findshlibs-0.10.2//:findshlibs\",\n \"@firewood_crates__inferno-0.11.21//:inferno\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__nix-0.26.4//:nix\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__pprof-0.15.0//:build_script_build\",\n \"@firewood_crates__smallvec-1.15.1//:smallvec\",\n \"@firewood_crates__spin-0.10.0//:spin\",\n \"@firewood_crates__symbolic-demangle-12.17.0//:symbolic_demangle\",\n \"@firewood_crates__tempfile-3.23.0//:tempfile\",\n \"@firewood_crates__thiserror-2.0.17//:thiserror\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"cpp\",\n \"default\",\n \"flamegraph\",\n \"inferno\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=pprof\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.15.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"cpp\",\n \"default\",\n \"flamegraph\",\n \"inferno\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"pprof\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=pprof\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.15.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__ppv-lite86-0.2.21": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ppv-lite86/0.2.21/download" + ], + "strip_prefix": "ppv-lite86-0.2.21", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ppv_lite86\",\n deps = [\n \"@firewood_crates__zerocopy-0.8.27//:zerocopy\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"simd\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ppv-lite86\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.21\",\n)\n" + } + }, + "firewood_crates__predicates-3.1.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/predicates/3.1.3/download" + ], + "strip_prefix": "predicates-3.1.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"predicates\",\n deps = [\n \"@firewood_crates__anstyle-1.0.13//:anstyle\",\n \"@firewood_crates__difflib-0.4.0//:difflib\",\n \"@firewood_crates__float-cmp-0.10.0//:float_cmp\",\n \"@firewood_crates__normalize-line-endings-0.3.0//:normalize_line_endings\",\n \"@firewood_crates__predicates-core-1.0.9//:predicates_core\",\n \"@firewood_crates__regex-1.12.2//:regex\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"color\",\n \"default\",\n \"diff\",\n \"float-cmp\",\n \"normalize-line-endings\",\n \"regex\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=predicates\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.1.3\",\n)\n" + } + }, + "firewood_crates__predicates-core-1.0.9": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/predicates-core/1.0.9/download" + ], + "strip_prefix": "predicates-core-1.0.9", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"predicates_core\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=predicates-core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.9\",\n)\n" + } + }, + "firewood_crates__predicates-tree-1.0.12": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/predicates-tree/1.0.12/download" + ], + "strip_prefix": "predicates-tree-1.0.12", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"predicates_tree\",\n deps = [\n \"@firewood_crates__predicates-core-1.0.9//:predicates_core\",\n \"@firewood_crates__termtree-0.5.1//:termtree\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=predicates-tree\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.12\",\n)\n" + } + }, + "firewood_crates__pretty-duration-0.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d8868e7264af614b3634ff0abbe37b178e61000611b8a75221aea40221924aba", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/pretty-duration/0.1.1/download" + ], + "strip_prefix": "pretty-duration-0.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"pretty_duration\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=pretty-duration\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.1\",\n)\n" + } + }, + "firewood_crates__prettyplease-0.2.37": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/prettyplease/0.2.37/download" + ], + "strip_prefix": "prettyplease-0.2.37", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"prettyplease\",\n deps = [\n \"@firewood_crates__prettyplease-0.2.37//:build_script_build\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=prettyplease\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.37\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n links = \"prettyplease02\",\n pkg_name = \"prettyplease\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=prettyplease\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.2.37\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__primitive-types-0.14.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "721a1da530b5a2633218dc9f75713394c983c352be88d2d7c9ee85e2c4c21794", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/primitive-types/0.14.0/download" + ], + "strip_prefix": "primitive-types-0.14.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"primitive_types\",\n deps = [\n \"@firewood_crates__fixed-hash-0.8.0//:fixed_hash\",\n \"@firewood_crates__impl-rlp-0.4.0//:impl_rlp\",\n \"@firewood_crates__impl-serde-0.5.0//:impl_serde\",\n \"@firewood_crates__uint-0.10.0//:uint\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"impl-rlp\",\n \"impl-serde\",\n \"rand\",\n \"rlp\",\n \"rustc-hex\",\n \"serde_no_std\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=primitive-types\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.0\",\n)\n" + } + }, + "firewood_crates__proc-macro-crate-3.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/proc-macro-crate/3.4.0/download" + ], + "strip_prefix": "proc-macro-crate-3.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"proc_macro_crate\",\n deps = [\n \"@firewood_crates__toml_edit-0.23.7//:toml_edit\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=proc-macro-crate\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.4.0\",\n)\n" + } + }, + "firewood_crates__proc-macro-error-attr2-2.0.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/proc-macro-error-attr2/2.0.0/download" + ], + "strip_prefix": "proc-macro-error-attr2-2.0.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"proc_macro_error_attr2\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=proc-macro-error-attr2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.0.0\",\n)\n" + } + }, + "firewood_crates__proc-macro-error2-2.0.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/proc-macro-error2/2.0.1/download" + ], + "strip_prefix": "proc-macro-error2-2.0.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"proc_macro_error2\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__proc-macro-error-attr2-2.0.0//:proc_macro_error_attr2\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"syn-error\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=proc-macro-error2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.0.1\",\n)\n" + } + }, + "firewood_crates__proc-macro2-1.0.103": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/proc-macro2/1.0.103/download" + ], + "strip_prefix": "proc-macro2-1.0.103", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"proc_macro2\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:build_script_build\",\n \"@firewood_crates__unicode-ident-1.0.22//:unicode_ident\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"proc-macro\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=proc-macro2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.103\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"proc-macro\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"proc-macro2\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=proc-macro2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.0.103\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__proptest-1.9.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/proptest/1.9.0/download" + ], + "strip_prefix": "proptest-1.9.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"proptest\",\n deps = [\n \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n \"@firewood_crates__num-traits-0.2.19//:num_traits\",\n \"@firewood_crates__rand-0.9.2//:rand\",\n \"@firewood_crates__rand_chacha-0.9.0//:rand_chacha\",\n \"@firewood_crates__rand_xorshift-0.4.0//:rand_xorshift\",\n \"@firewood_crates__unarray-0.1.4//:unarray\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=proptest\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.9.0\",\n)\n" + } + }, + "firewood_crates__prost-0.14.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/prost/0.14.1/download" + ], + "strip_prefix": "prost-0.14.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"prost\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__prost-derive-0.14.1//:prost_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"derive\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=prost\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.1\",\n)\n" + } + }, + "firewood_crates__prost-derive-0.14.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/prost-derive/0.14.1/download" + ], + "strip_prefix": "prost-derive-0.14.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"prost_derive\",\n deps = [\n \"@firewood_crates__anyhow-1.0.100//:anyhow\",\n \"@firewood_crates__itertools-0.14.0//:itertools\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=prost-derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.1\",\n)\n" + } + }, + "firewood_crates__quanta-0.12.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/quanta/0.12.6/download" + ], + "strip_prefix": "quanta-0.12.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"quanta\",\n deps = [\n \"@firewood_crates__crossbeam-utils-0.8.21//:crossbeam_utils\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"windows\", target_arch = \"wasm32\")))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"windows\", target_arch = \"wasm32\")))\n ],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__web-sys-0.3.82//:web_sys\", # cfg(all(target_arch = \"wasm32\", target_os = \"unknown\"))\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__wasi-0.11.1-wasi-snapshot-preview1//:wasi\", # cfg(all(target_arch = \"wasm32\", target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__raw-cpuid-11.6.0//:raw_cpuid\", # cfg(target_arch = \"x86_64\")\n \"@firewood_crates__winapi-0.3.9//:winapi\", # cfg(target_os = \"windows\")\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"windows\", target_arch = \"wasm32\")))\n \"@firewood_crates__raw-cpuid-11.6.0//:raw_cpuid\", # cfg(target_arch = \"x86_64\")\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(not(any(target_os = \"windows\", target_arch = \"wasm32\")))\n \"@firewood_crates__raw-cpuid-11.6.0//:raw_cpuid\", # cfg(target_arch = \"x86_64\")\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=quanta\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.12.6\",\n)\n" + } + }, + "firewood_crates__quick-xml-0.26.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/quick-xml/0.26.0/download" + ], + "strip_prefix": "quick-xml-0.26.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"quick_xml\",\n deps = [\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=quick-xml\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.26.0\",\n)\n" + } + }, + "firewood_crates__quick_cache-0.6.18": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7ada44a88ef953a3294f6eb55d2007ba44646015e18613d2f213016379203ef3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/quick_cache/0.6.18/download" + ], + "strip_prefix": "quick_cache-0.6.18", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"quick_cache\",\n deps = [\n \"@firewood_crates__equivalent-1.0.2//:equivalent\",\n \"@firewood_crates__hashbrown-0.16.0//:hashbrown\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=quick_cache\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.18\",\n)\n" + } + }, + "firewood_crates__quote-1.0.42": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/quote/1.0.42/download" + ], + "strip_prefix": "quote-1.0.42", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"quote\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"proc-macro\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=quote\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.42\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"proc-macro\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"quote\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=quote\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.0.42\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__r-efi-5.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/r-efi/5.3.0/download" + ], + "strip_prefix": "r-efi-5.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"r_efi\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=r-efi\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"5.3.0\",\n)\n" + } + }, + "firewood_crates__radium-0.7.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/radium/0.7.0/download" + ], + "strip_prefix": "radium-0.7.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"radium\",\n deps = [\n \"@firewood_crates__radium-0.7.0//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=radium\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"radium\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=radium\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.7.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__radix_trie-0.2.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/radix_trie/0.2.1/download" + ], + "strip_prefix": "radix_trie-0.2.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"radix_trie\",\n deps = [\n \"@firewood_crates__endian-type-0.1.2//:endian_type\",\n \"@firewood_crates__nibble_vec-0.1.0//:nibble_vec\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=radix_trie\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.1\",\n)\n" + } + }, + "firewood_crates__rand-0.8.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand/0.8.5/download" + ], + "strip_prefix": "rand-0.8.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand\",\n deps = [\n \"@firewood_crates__rand_chacha-0.3.1//:rand_chacha\",\n \"@firewood_crates__rand_core-0.6.4//:rand_core\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"getrandom\",\n \"libc\",\n \"rand_chacha\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.5\",\n)\n" + } + }, + "firewood_crates__rand-0.9.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand/0.9.2/download" + ], + "strip_prefix": "rand-0.9.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand\",\n deps = [\n \"@firewood_crates__rand_chacha-0.9.0//:rand_chacha\",\n \"@firewood_crates__rand_core-0.9.3//:rand_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"os_rng\",\n \"small_rng\",\n \"std\",\n \"std_rng\",\n \"thread_rng\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.2\",\n)\n" + } + }, + "firewood_crates__rand_chacha-0.3.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand_chacha/0.3.1/download" + ], + "strip_prefix": "rand_chacha-0.3.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand_chacha\",\n deps = [\n \"@firewood_crates__ppv-lite86-0.2.21//:ppv_lite86\",\n \"@firewood_crates__rand_core-0.6.4//:rand_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand_chacha\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.1\",\n)\n" + } + }, + "firewood_crates__rand_chacha-0.9.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand_chacha/0.9.0/download" + ], + "strip_prefix": "rand_chacha-0.9.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand_chacha\",\n deps = [\n \"@firewood_crates__ppv-lite86-0.2.21//:ppv_lite86\",\n \"@firewood_crates__rand_core-0.9.3//:rand_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand_chacha\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.0\",\n)\n" + } + }, + "firewood_crates__rand_core-0.6.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand_core/0.6.4/download" + ], + "strip_prefix": "rand_core-0.6.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand_core\",\n deps = [\n \"@firewood_crates__getrandom-0.2.16//:getrandom\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"getrandom\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand_core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.4\",\n)\n" + } + }, + "firewood_crates__rand_core-0.9.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand_core/0.9.3/download" + ], + "strip_prefix": "rand_core-0.9.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand_core\",\n deps = [\n \"@firewood_crates__getrandom-0.3.4//:getrandom\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"os_rng\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand_core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.3\",\n)\n" + } + }, + "firewood_crates__rand_distr-0.5.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand_distr/0.5.1/download" + ], + "strip_prefix": "rand_distr-0.5.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand_distr\",\n deps = [\n \"@firewood_crates__num-traits-0.2.19//:num_traits\",\n \"@firewood_crates__rand-0.9.2//:rand\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand_distr\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.1\",\n)\n" + } + }, + "firewood_crates__rand_xorshift-0.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand_xorshift/0.4.0/download" + ], + "strip_prefix": "rand_xorshift-0.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand_xorshift\",\n deps = [\n \"@firewood_crates__rand_core-0.9.3//:rand_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand_xorshift\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.0\",\n)\n" + } + }, + "firewood_crates__rand_xoshiro-0.7.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rand_xoshiro/0.7.0/download" + ], + "strip_prefix": "rand_xoshiro-0.7.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rand_xoshiro\",\n deps = [\n \"@firewood_crates__rand_core-0.9.3//:rand_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rand_xoshiro\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.0\",\n)\n" + } + }, + "firewood_crates__raw-cpuid-11.6.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/raw-cpuid/11.6.0/download" + ], + "strip_prefix": "raw-cpuid-11.6.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"raw_cpuid\",\n deps = [\n \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=raw-cpuid\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"11.6.0\",\n)\n" + } + }, + "firewood_crates__rayon-1.11.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rayon/1.11.0/download" + ], + "strip_prefix": "rayon-1.11.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rayon\",\n deps = [\n \"@firewood_crates__either-1.15.0//:either\",\n \"@firewood_crates__rayon-core-1.13.0//:rayon_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rayon\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.11.0\",\n)\n" + } + }, + "firewood_crates__rayon-core-1.13.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rayon-core/1.13.0/download" + ], + "strip_prefix": "rayon-core-1.13.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rayon_core\",\n deps = [\n \"@firewood_crates__crossbeam-deque-0.8.6//:crossbeam_deque\",\n \"@firewood_crates__crossbeam-utils-0.8.21//:crossbeam_utils\",\n \"@firewood_crates__rayon-core-1.13.0//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rayon-core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.13.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n links = \"rayon-core\",\n pkg_name = \"rayon-core\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rayon-core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.13.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__redox_syscall-0.5.18": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/redox_syscall/0.5.18/download" + ], + "strip_prefix": "redox_syscall-0.5.18", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"syscall\",\n deps = [\n \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=redox_syscall\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.18\",\n)\n" + } + }, + "firewood_crates__regex-1.12.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/regex/1.12.2/download" + ], + "strip_prefix": "regex-1.12.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"regex\",\n deps = [\n \"@firewood_crates__aho-corasick-1.1.4//:aho_corasick\",\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__regex-automata-0.4.13//:regex_automata\",\n \"@firewood_crates__regex-syntax-0.8.8//:regex_syntax\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"perf\",\n \"perf-backtrack\",\n \"perf-cache\",\n \"perf-dfa\",\n \"perf-inline\",\n \"perf-literal\",\n \"perf-onepass\",\n \"std\",\n \"unicode\",\n \"unicode-age\",\n \"unicode-bool\",\n \"unicode-case\",\n \"unicode-gencat\",\n \"unicode-perl\",\n \"unicode-script\",\n \"unicode-segment\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=regex\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.12.2\",\n)\n" + } + }, + "firewood_crates__regex-automata-0.4.13": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/regex-automata/0.4.13/download" + ], + "strip_prefix": "regex-automata-0.4.13", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"regex_automata\",\n deps = [\n \"@firewood_crates__aho-corasick-1.1.4//:aho_corasick\",\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__regex-syntax-0.8.8//:regex_syntax\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"dfa-onepass\",\n \"dfa-search\",\n \"hybrid\",\n \"meta\",\n \"nfa-backtrack\",\n \"nfa-pikevm\",\n \"nfa-thompson\",\n \"perf-inline\",\n \"perf-literal\",\n \"perf-literal-multisubstring\",\n \"perf-literal-substring\",\n \"std\",\n \"syntax\",\n \"unicode\",\n \"unicode-age\",\n \"unicode-bool\",\n \"unicode-case\",\n \"unicode-gencat\",\n \"unicode-perl\",\n \"unicode-script\",\n \"unicode-segment\",\n \"unicode-word-boundary\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=regex-automata\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.13\",\n)\n" + } + }, + "firewood_crates__regex-syntax-0.8.8": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/regex-syntax/0.8.8/download" + ], + "strip_prefix": "regex-syntax-0.8.8", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"regex_syntax\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n \"unicode\",\n \"unicode-age\",\n \"unicode-bool\",\n \"unicode-case\",\n \"unicode-gencat\",\n \"unicode-perl\",\n \"unicode-script\",\n \"unicode-segment\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=regex-syntax\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.8\",\n)\n" + } + }, + "firewood_crates__reqwest-0.12.24": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/reqwest/0.12.24/download" + ], + "strip_prefix": "reqwest-0.12.24", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"reqwest\",\n deps = [\n \"@firewood_crates__base64-0.22.1//:base64\",\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-util-0.3.31//:futures_util\",\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__serde_urlencoded-0.7.1//:serde_urlencoded\",\n \"@firewood_crates__sync_wrapper-1.0.2//:sync_wrapper\",\n \"@firewood_crates__url-2.5.7//:url\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\", # aarch64-apple-darwin\n \"@firewood_crates__http-body-1.0.1//:http_body\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__http-body-util-0.1.3//:http_body_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-1.8.1//:hyper\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__log-0.4.28//:log\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tokio-1.48.0//:tokio\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-0.5.2//:tower\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-http-0.6.6//:tower_http\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-service-0.3.3//:tower_service\", # cfg(not(target_arch = \"wasm32\"))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\", # aarch64-unknown-linux-gnu\n \"@firewood_crates__http-body-1.0.1//:http_body\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__http-body-util-0.1.3//:http_body_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-1.8.1//:hyper\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__log-0.4.28//:log\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tokio-1.48.0//:tokio\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-0.5.2//:tower\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-http-0.6.6//:tower_http\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-service-0.3.3//:tower_service\", # cfg(not(target_arch = \"wasm32\"))\n ],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__js-sys-0.3.82//:js_sys\", # cfg(target_arch = \"wasm32\")\n \"@firewood_crates__serde_json-1.0.145//:serde_json\", # cfg(target_arch = \"wasm32\")\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\", # cfg(target_arch = \"wasm32\")\n \"@firewood_crates__wasm-bindgen-futures-0.4.55//:wasm_bindgen_futures\", # cfg(target_arch = \"wasm32\")\n \"@firewood_crates__web-sys-0.3.82//:web_sys\", # cfg(target_arch = \"wasm32\")\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__js-sys-0.3.82//:js_sys\", # cfg(target_arch = \"wasm32\")\n \"@firewood_crates__serde_json-1.0.145//:serde_json\", # cfg(target_arch = \"wasm32\")\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\", # cfg(target_arch = \"wasm32\")\n \"@firewood_crates__wasm-bindgen-futures-0.4.55//:wasm_bindgen_futures\", # cfg(target_arch = \"wasm32\")\n \"@firewood_crates__web-sys-0.3.82//:web_sys\", # cfg(target_arch = \"wasm32\")\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\", # x86_64-pc-windows-msvc\n \"@firewood_crates__http-body-1.0.1//:http_body\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__http-body-util-0.1.3//:http_body_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-1.8.1//:hyper\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__log-0.4.28//:log\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tokio-1.48.0//:tokio\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-0.5.2//:tower\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-http-0.6.6//:tower_http\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-service-0.3.3//:tower_service\", # cfg(not(target_arch = \"wasm32\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\", # x86_64-unknown-linux-gnu\n \"@firewood_crates__http-body-1.0.1//:http_body\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__http-body-util-0.1.3//:http_body_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-1.8.1//:hyper\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__log-0.4.28//:log\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tokio-1.48.0//:tokio\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-0.5.2//:tower\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-http-0.6.6//:tower_http\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-service-0.3.3//:tower_service\", # cfg(not(target_arch = \"wasm32\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__futures-channel-0.3.31//:futures_channel\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n \"@firewood_crates__http-body-1.0.1//:http_body\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__http-body-util-0.1.3//:http_body_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-1.8.1//:hyper\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__log-0.4.28//:log\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tokio-1.48.0//:tokio\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-0.5.2//:tower\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-http-0.6.6//:tower_http\", # cfg(not(target_arch = \"wasm32\"))\n \"@firewood_crates__tower-service-0.3.3//:tower_service\", # cfg(not(target_arch = \"wasm32\"))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"blocking\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=reqwest\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.12.24\",\n)\n" + } + }, + "firewood_crates__rgb-0.8.52": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rgb/0.8.52/download" + ], + "strip_prefix": "rgb-0.8.52", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rgb\",\n deps = [\n \"@firewood_crates__bytemuck-1.24.0//:bytemuck\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"argb\",\n \"as-bytes\",\n \"bytemuck\",\n \"default\",\n \"grb\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rgb\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.52\",\n)\n" + } + }, + "firewood_crates__ring-0.17.14": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ring/0.17.14/download" + ], + "strip_prefix": "ring-0.17.14", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ring\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__getrandom-0.2.16//:getrandom\",\n \"@firewood_crates__ring-0.17.14//:build_script_build\",\n \"@firewood_crates__untrusted-0.9.0//:untrusted\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(all(target_arch = \"aarch64\", target_endian = \"little\"), target_vendor = \"apple\", any(target_os = \"ios\", target_os = \"macos\", target_os = \"tvos\", target_os = \"visionos\", target_os = \"watchos\")))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(any(all(target_arch = \"aarch64\", target_endian = \"little\"), all(target_arch = \"arm\", target_endian = \"little\")), any(target_os = \"android\", target_os = \"linux\")))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ring\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.17.14\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__cc-1.2.46//:cc\",\n ],\n edition = \"2021\",\n links = \"ring_core_0_17_14_\",\n pkg_name = \"ring\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ring\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.17.14\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__rlp-0.6.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rlp/0.6.1/download" + ], + "strip_prefix": "rlp-0.6.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rlp\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__rustc-hex-2.1.0//:rustc_hex\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rlp\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.1\",\n)\n" + } + }, + "firewood_crates__rtrb-0.3.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ad8388ea1a9e0ea807e442e8263a699e7edcb320ecbcd21b4fa8ff859acce3ba", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rtrb/0.3.2/download" + ], + "strip_prefix": "rtrb-0.3.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rtrb\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rtrb\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.2\",\n)\n" + } + }, + "firewood_crates__rustc-demangle-0.1.26": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustc-demangle/0.1.26/download" + ], + "strip_prefix": "rustc-demangle-0.1.26", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rustc_demangle\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustc-demangle\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.26\",\n)\n" + } + }, + "firewood_crates__rustc-hash-2.1.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustc-hash/2.1.1/download" + ], + "strip_prefix": "rustc-hash-2.1.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rustc_hash\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustc-hash\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.1\",\n)\n" + } + }, + "firewood_crates__rustc-hex-2.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustc-hex/2.1.0/download" + ], + "strip_prefix": "rustc-hex-2.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rustc_hex\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustc-hex\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.1.0\",\n)\n" + } + }, + "firewood_crates__rustix-1.1.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustix/1.1.2/download" + ], + "strip_prefix": "rustix-1.1.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rustix\",\n deps = [\n \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n \"@firewood_crates__rustix-1.1.2//:build_script_build\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__errno-0.3.14//:errno\", # aarch64-apple-darwin, cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\")))))))\n \"@firewood_crates__libc-0.2.177//:libc\", # aarch64-apple-darwin, cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\")))))))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__linux-raw-sys-0.11.0//:linux_raw_sys\", # cfg(all(not(rustix_use_libc), not(miri), target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"))))\n ],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__errno-0.3.14//:errno\", # cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\")))))))\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\")))))))\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__errno-0.3.14//:errno\", # cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"))))))), wasm32-wasip1\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"))))))), wasm32-wasip1\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__errno-0.3.14//:errno\", # cfg(windows)\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__linux-raw-sys-0.11.0//:linux_raw_sys\", # cfg(all(not(rustix_use_libc), not(miri), target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"))))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__linux-raw-sys-0.11.0//:linux_raw_sys\", # cfg(all(not(rustix_use_libc), not(miri), target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"))))\n ],\n \"//conditions:default\": [],\n }),\n aliases = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": {\n \"@firewood_crates__errno-0.3.14//:errno\": \"libc_errno\", # aarch64-apple-darwin, cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\")))))))\n },\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": {\n \"@firewood_crates__errno-0.3.14//:errno\": \"libc_errno\", # cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\")))))))\n },\n \"@rules_rust//rust/platform:wasm32-wasip1\": {\n \"@firewood_crates__errno-0.3.14//:errno\": \"libc_errno\", # cfg(all(not(windows), any(rustix_use_libc, miri, not(all(target_os = \"linux\", any(target_endian = \"little\", any(target_arch = \"s390x\", target_arch = \"powerpc\")), any(target_arch = \"arm\", all(target_arch = \"aarch64\", target_pointer_width = \"64\"), target_arch = \"riscv64\", all(rustix_use_experimental_asm, target_arch = \"powerpc\"), all(rustix_use_experimental_asm, target_arch = \"powerpc64\"), all(rustix_use_experimental_asm, target_arch = \"s390x\"), all(rustix_use_experimental_asm, target_arch = \"mips\"), all(rustix_use_experimental_asm, target_arch = \"mips32r6\"), all(rustix_use_experimental_asm, target_arch = \"mips64\"), all(rustix_use_experimental_asm, target_arch = \"mips64r6\"), target_arch = \"x86\", all(target_arch = \"x86_64\", target_pointer_width = \"64\"))))))), wasm32-wasip1\n },\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": {\n \"@firewood_crates__errno-0.3.14//:errno\": \"libc_errno\", # cfg(windows)\n },\n \"//conditions:default\": {},\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"fs\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustix\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.2\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"fs\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"rustix\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustix\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.1.2\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__rustls-0.23.35": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustls/0.23.35/download" + ], + "strip_prefix": "rustls-0.23.35", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rustls\",\n deps = [\n \"@firewood_crates__aws-lc-rs-1.15.0//:aws_lc_rs\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__rustls-0.23.35//:build_script_build\",\n \"@firewood_crates__rustls-pki-types-1.13.0//:rustls_pki_types\",\n \"@firewood_crates__rustls-webpki-0.103.8//:webpki\",\n \"@firewood_crates__subtle-2.6.1//:subtle\",\n \"@firewood_crates__zeroize-1.8.2//:zeroize\",\n ],\n aliases = {\n \"@firewood_crates__rustls-pki-types-1.13.0//:rustls_pki_types\": \"pki_types\",\n },\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"aws-lc-rs\",\n \"aws_lc_rs\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustls\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.23.35\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"aws-lc-rs\",\n \"aws_lc_rs\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n link_deps = [\n \"@firewood_crates__aws-lc-rs-1.15.0//:aws_lc_rs\",\n ],\n edition = \"2021\",\n pkg_name = \"rustls\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustls\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.23.35\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__rustls-native-certs-0.8.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustls-native-certs/0.8.2/download" + ], + "strip_prefix": "rustls-native-certs-0.8.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rustls_native_certs\",\n deps = [\n \"@firewood_crates__rustls-pki-types-1.13.0//:rustls_pki_types\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__security-framework-3.5.1//:security_framework\", # cfg(target_os = \"macos\")\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__openssl-probe-0.1.6//:openssl_probe\", # cfg(all(unix, not(target_os = \"macos\")))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__schannel-0.1.28//:schannel\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__openssl-probe-0.1.6//:openssl_probe\", # cfg(all(unix, not(target_os = \"macos\")))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__openssl-probe-0.1.6//:openssl_probe\", # cfg(all(unix, not(target_os = \"macos\")))\n ],\n \"//conditions:default\": [],\n }),\n aliases = {\n \"@firewood_crates__rustls-pki-types-1.13.0//:rustls_pki_types\": \"pki_types\",\n },\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustls-native-certs\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.2\",\n)\n" + } + }, + "firewood_crates__rustls-pki-types-1.13.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustls-pki-types/1.13.0/download" + ], + "strip_prefix": "rustls-pki-types-1.13.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"rustls_pki_types\",\n deps = [\n \"@firewood_crates__zeroize-1.8.2//:zeroize\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustls-pki-types\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.13.0\",\n)\n" + } + }, + "firewood_crates__rustls-webpki-0.103.8": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustls-webpki/0.103.8/download" + ], + "strip_prefix": "rustls-webpki-0.103.8", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"webpki\",\n deps = [\n \"@firewood_crates__aws-lc-rs-1.15.0//:aws_lc_rs\",\n \"@firewood_crates__rustls-pki-types-1.13.0//:rustls_pki_types\",\n \"@firewood_crates__untrusted-0.9.0//:untrusted\",\n ],\n aliases = {\n \"@firewood_crates__rustls-pki-types-1.13.0//:rustls_pki_types\": \"pki_types\",\n },\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"aws-lc-rs\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustls-webpki\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.103.8\",\n)\n" + } + }, + "firewood_crates__rustversion-1.0.22": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/rustversion/1.0.22/download" + ], + "strip_prefix": "rustversion-1.0.22", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"rustversion\",\n deps = [\n \"@firewood_crates__rustversion-1.0.22//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustversion\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.22\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build/build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"rustversion\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=rustversion\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.0.22\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__ryu-1.0.20": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/ryu/1.0.20/download" + ], + "strip_prefix": "ryu-1.0.20", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"ryu\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=ryu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.20\",\n)\n" + } + }, + "firewood_crates__same-file-1.0.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/same-file/1.0.6/download" + ], + "strip_prefix": "same-file-1.0.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"same_file\",\n deps = select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__winapi-util-0.1.11//:winapi_util\", # cfg(windows)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=same-file\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.6\",\n)\n" + } + }, + "firewood_crates__scc-2.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/scc/2.4.0/download" + ], + "strip_prefix": "scc-2.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"scc\",\n deps = [\n \"@firewood_crates__sdd-3.0.10//:sdd\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=scc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.4.0\",\n)\n" + } + }, + "firewood_crates__schannel-0.1.28": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/schannel/0.1.28/download" + ], + "strip_prefix": "schannel-0.1.28", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"schannel\",\n deps = [\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=schannel\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.28\",\n)\n" + } + }, + "firewood_crates__scopeguard-1.2.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/scopeguard/1.2.0/download" + ], + "strip_prefix": "scopeguard-1.2.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"scopeguard\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=scopeguard\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.2.0\",\n)\n" + } + }, + "firewood_crates__sdd-3.0.10": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/sdd/3.0.10/download" + ], + "strip_prefix": "sdd-3.0.10", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"sdd\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=sdd\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.0.10\",\n)\n" + } + }, + "firewood_crates__security-framework-3.5.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/security-framework/3.5.1/download" + ], + "strip_prefix": "security-framework-3.5.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"security_framework\",\n deps = [\n \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n \"@firewood_crates__core-foundation-0.10.1//:core_foundation\",\n \"@firewood_crates__core-foundation-sys-0.8.7//:core_foundation_sys\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n \"@firewood_crates__security-framework-sys-2.15.0//:security_framework_sys\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"OSX_10_12\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=security-framework\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.5.1\",\n)\n" + } + }, + "firewood_crates__security-framework-sys-2.15.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/security-framework-sys/2.15.0/download" + ], + "strip_prefix": "security-framework-sys-2.15.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"security_framework_sys\",\n deps = [\n \"@firewood_crates__core-foundation-sys-0.8.7//:core_foundation_sys\",\n \"@firewood_crates__libc-0.2.177//:libc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"OSX_10_10\",\n \"OSX_10_11\",\n \"OSX_10_12\",\n \"OSX_10_9\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=security-framework-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.15.0\",\n)\n" + } + }, + "firewood_crates__self_cell-1.2.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/self_cell/1.2.1/download" + ], + "strip_prefix": "self_cell-1.2.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"self_cell\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=self_cell\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.2.1\",\n)\n" + } + }, + "firewood_crates__semver-1.0.27": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/semver/1.0.27/download" + ], + "strip_prefix": "semver-1.0.27", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"semver\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=semver\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.27\",\n)\n" + } + }, + "firewood_crates__serde-1.0.228": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/serde/1.0.228/download" + ], + "strip_prefix": "serde-1.0.228", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"serde\",\n deps = [\n \"@firewood_crates__serde-1.0.228//:build_script_build\",\n \"@firewood_crates__serde_core-1.0.228//:serde_core\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__serde_derive-1.0.228//:serde_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"derive\",\n \"serde_derive\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.228\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"derive\",\n \"serde_derive\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"serde\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.0.228\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__serde_core-1.0.228": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/serde_core/1.0.228/download" + ], + "strip_prefix": "serde_core-1.0.228", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"serde_core\",\n deps = [\n \"@firewood_crates__serde_core-1.0.228//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"result\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde_core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.228\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"result\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"serde_core\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde_core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.0.228\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__serde_derive-1.0.228": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/serde_derive/1.0.228/download" + ], + "strip_prefix": "serde_derive-1.0.228", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"serde_derive\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde_derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.228\",\n)\n" + } + }, + "firewood_crates__serde_json-1.0.145": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/serde_json/1.0.145/download" + ], + "strip_prefix": "serde_json-1.0.145", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"serde_json\",\n deps = [\n \"@firewood_crates__itoa-1.0.15//:itoa\",\n \"@firewood_crates__memchr-2.7.6//:memchr\",\n \"@firewood_crates__ryu-1.0.20//:ryu\",\n \"@firewood_crates__serde_core-1.0.228//:serde_core\",\n \"@firewood_crates__serde_json-1.0.145//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde_json\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.145\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"serde_json\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde_json\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.0.145\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__serde_spanned-1.0.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/serde_spanned/1.0.3/download" + ], + "strip_prefix": "serde_spanned-1.0.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"serde_spanned\",\n deps = [\n \"@firewood_crates__serde_core-1.0.228//:serde_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"serde\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde_spanned\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.3\",\n)\n" + } + }, + "firewood_crates__serde_urlencoded-0.7.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/serde_urlencoded/0.7.1/download" + ], + "strip_prefix": "serde_urlencoded-0.7.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"serde_urlencoded\",\n deps = [\n \"@firewood_crates__form_urlencoded-1.2.2//:form_urlencoded\",\n \"@firewood_crates__itoa-1.0.15//:itoa\",\n \"@firewood_crates__ryu-1.0.20//:ryu\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serde_urlencoded\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.1\",\n)\n" + } + }, + "firewood_crates__serial_test-3.2.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/serial_test/3.2.0/download" + ], + "strip_prefix": "serial_test-3.2.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"serial_test\",\n deps = [\n \"@firewood_crates__futures-0.3.31//:futures\",\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__parking_lot-0.12.5//:parking_lot\",\n \"@firewood_crates__scc-2.4.0//:scc\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__serial_test_derive-3.2.0//:serial_test_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"async\",\n \"default\",\n \"logging\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serial_test\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.2.0\",\n)\n" + } + }, + "firewood_crates__serial_test_derive-3.2.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/serial_test_derive/3.2.0/download" + ], + "strip_prefix": "serial_test_derive-3.2.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"serial_test_derive\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"async\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=serial_test_derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.2.0\",\n)\n" + } + }, + "firewood_crates__sha2-0.10.9": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/sha2/0.10.9/download" + ], + "strip_prefix": "sha2-0.10.9", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"sha2\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__digest-0.10.7//:digest\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(any(target_arch = \"aarch64\", target_arch = \"x86_64\", target_arch = \"x86\"))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(any(target_arch = \"aarch64\", target_arch = \"x86_64\", target_arch = \"x86\"))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(any(target_arch = \"aarch64\", target_arch = \"x86_64\", target_arch = \"x86\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(any(target_arch = \"aarch64\", target_arch = \"x86_64\", target_arch = \"x86\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__cpufeatures-0.2.17//:cpufeatures\", # cfg(any(target_arch = \"aarch64\", target_arch = \"x86_64\", target_arch = \"x86\"))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=sha2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.9\",\n)\n" + } + }, + "firewood_crates__sha3-0.10.8": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/sha3/0.10.8/download" + ], + "strip_prefix": "sha3-0.10.8", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"sha3\",\n deps = [\n \"@firewood_crates__digest-0.10.7//:digest\",\n \"@firewood_crates__keccak-0.1.5//:keccak\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=sha3\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.8\",\n)\n" + } + }, + "firewood_crates__shlex-1.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/shlex/1.3.0/download" + ], + "strip_prefix": "shlex-1.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"shlex\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=shlex\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.3.0\",\n)\n" + } + }, + "firewood_crates__sketches-ddsketch-0.3.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/sketches-ddsketch/0.3.0/download" + ], + "strip_prefix": "sketches-ddsketch-0.3.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"sketches_ddsketch\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=sketches-ddsketch\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.0\",\n)\n" + } + }, + "firewood_crates__slab-0.4.11": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/slab/0.4.11/download" + ], + "strip_prefix": "slab-0.4.11", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"slab\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=slab\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.11\",\n)\n" + } + }, + "firewood_crates__small_ctor-0.1.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "88414a5ca1f85d82cc34471e975f0f74f6aa54c40f062efa42c0080e7f763f81", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/small_ctor/0.1.2/download" + ], + "strip_prefix": "small_ctor-0.1.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"small_ctor\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=small_ctor\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.2\",\n)\n" + } + }, + "firewood_crates__smallvec-1.15.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/smallvec/1.15.1/download" + ], + "strip_prefix": "smallvec-1.15.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"smallvec\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"const_generics\",\n \"const_new\",\n \"union\",\n \"write\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=smallvec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.15.1\",\n)\n" + } + }, + "firewood_crates__socket2-0.6.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/socket2/0.6.1/download" + ], + "strip_prefix": "socket2-0.6.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"socket2\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-sys-0.60.2//:windows_sys\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"all\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=socket2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.1\",\n)\n" + } + }, + "firewood_crates__spin-0.10.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/spin/0.10.0/download" + ], + "strip_prefix": "spin-0.10.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"spin\",\n deps = [\n \"@firewood_crates__lock_api-0.4.14//:lock_api\",\n ],\n aliases = {\n \"@firewood_crates__lock_api-0.4.14//:lock_api\": \"lock_api_crate\",\n },\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"barrier\",\n \"default\",\n \"lazy\",\n \"lock_api\",\n \"mutex\",\n \"once\",\n \"rwlock\",\n \"spin_mutex\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=spin\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.0\",\n)\n" + } + }, + "firewood_crates__stable_deref_trait-1.2.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/stable_deref_trait/1.2.1/download" + ], + "strip_prefix": "stable_deref_trait-1.2.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"stable_deref_trait\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=stable_deref_trait\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.2.1\",\n)\n" + } + }, + "firewood_crates__static_assertions-1.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/static_assertions/1.1.0/download" + ], + "strip_prefix": "static_assertions-1.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"static_assertions\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=static_assertions\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.0\",\n)\n" + } + }, + "firewood_crates__std-semaphore-0.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "33ae9eec00137a8eed469fb4148acd9fc6ac8c3f9b110f52cd34698c8b5bfa0e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/std-semaphore/0.1.0/download" + ], + "strip_prefix": "std-semaphore-0.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"std_semaphore\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=std-semaphore\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.0\",\n)\n" + } + }, + "firewood_crates__str_stack-0.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/str_stack/0.1.0/download" + ], + "strip_prefix": "str_stack-0.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"str_stack\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=str_stack\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.0\",\n)\n" + } + }, + "firewood_crates__strsim-0.11.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/strsim/0.11.1/download" + ], + "strip_prefix": "strsim-0.11.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"strsim\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=strsim\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.11.1\",\n)\n" + } + }, + "firewood_crates__subtle-2.6.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/subtle/2.6.1/download" + ], + "strip_prefix": "subtle-2.6.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"subtle\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=subtle\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.6.1\",\n)\n" + } + }, + "firewood_crates__symbolic-common-12.17.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b3d8046c5674ab857104bc4559d505f4809b8060d57806e45d49737c97afeb60", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/symbolic-common/12.17.0/download" + ], + "strip_prefix": "symbolic-common-12.17.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"symbolic_common\",\n deps = [\n \"@firewood_crates__debugid-0.8.0//:debugid\",\n \"@firewood_crates__memmap2-0.9.9//:memmap2\",\n \"@firewood_crates__stable_deref_trait-1.2.1//:stable_deref_trait\",\n \"@firewood_crates__uuid-1.18.1//:uuid\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=symbolic-common\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"12.17.0\",\n)\n" + } + }, + "firewood_crates__symbolic-demangle-12.17.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1accb6e5c4b0f682de907623912e616b44be1c9e725775155546669dbff720ec", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/symbolic-demangle/12.17.0/download" + ], + "strip_prefix": "symbolic-demangle-12.17.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"symbolic_demangle\",\n deps = [\n \"@firewood_crates__cpp_demangle-0.4.5//:cpp_demangle\",\n \"@firewood_crates__rustc-demangle-0.1.26//:rustc_demangle\",\n \"@firewood_crates__symbolic-common-12.17.0//:symbolic_common\",\n \"@firewood_crates__symbolic-demangle-12.17.0//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"cpp\",\n \"cpp_demangle\",\n \"rust\",\n \"rustc-demangle\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=symbolic-demangle\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"12.17.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"cpp\",\n \"cpp_demangle\",\n \"rust\",\n \"rustc-demangle\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"symbolic-demangle\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=symbolic-demangle\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"12.17.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__syn-2.0.110": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/syn/2.0.110/download" + ], + "strip_prefix": "syn-2.0.110", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"syn\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__unicode-ident-1.0.22//:unicode_ident\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"clone-impls\",\n \"default\",\n \"derive\",\n \"extra-traits\",\n \"fold\",\n \"full\",\n \"parsing\",\n \"printing\",\n \"proc-macro\",\n \"visit\",\n \"visit-mut\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=syn\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.0.110\",\n)\n" + } + }, + "firewood_crates__sync_wrapper-1.0.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/sync_wrapper/1.0.2/download" + ], + "strip_prefix": "sync_wrapper-1.0.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"sync_wrapper\",\n deps = [\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"futures\",\n \"futures-core\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=sync_wrapper\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.2\",\n)\n" + } + }, + "firewood_crates__synstructure-0.13.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/synstructure/0.13.2/download" + ], + "strip_prefix": "synstructure-0.13.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"synstructure\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"proc-macro\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=synstructure\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.13.2\",\n)\n" + } + }, + "firewood_crates__tap-1.0.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tap/1.0.1/download" + ], + "strip_prefix": "tap-1.0.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tap\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tap\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.1\",\n)\n" + } + }, + "firewood_crates__target-triple-1.0.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/target-triple/1.0.0/download" + ], + "strip_prefix": "target-triple-1.0.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"target_triple\",\n deps = [\n \"@firewood_crates__target-triple-1.0.0//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=target-triple\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"target-triple\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=target-triple\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.0.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__tempfile-3.23.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tempfile/3.23.0/download" + ], + "strip_prefix": "tempfile-3.23.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tempfile\",\n deps = [\n \"@firewood_crates__fastrand-2.3.0//:fastrand\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__getrandom-0.3.4//:getrandom\", # aarch64-apple-darwin\n \"@firewood_crates__rustix-1.1.2//:rustix\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__getrandom-0.3.4//:getrandom\", # aarch64-unknown-linux-gnu\n \"@firewood_crates__rustix-1.1.2//:rustix\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [\n \"@firewood_crates__getrandom-0.3.4//:getrandom\", # wasm32-wasip1\n \"@firewood_crates__rustix-1.1.2//:rustix\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__getrandom-0.3.4//:getrandom\", # x86_64-pc-windows-msvc\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__getrandom-0.3.4//:getrandom\", # x86_64-unknown-linux-gnu\n \"@firewood_crates__rustix-1.1.2//:rustix\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__getrandom-0.3.4//:getrandom\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n \"@firewood_crates__rustix-1.1.2//:rustix\", # cfg(any(unix, target_os = \"wasi\"))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"getrandom\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tempfile\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.23.0\",\n)\n" + } + }, + "firewood_crates__termcolor-1.4.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/termcolor/1.4.1/download" + ], + "strip_prefix": "termcolor-1.4.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"termcolor\",\n deps = select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__winapi-util-0.1.11//:winapi_util\", # cfg(windows)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=termcolor\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.4.1\",\n)\n" + } + }, + "firewood_crates__termtree-0.5.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/termtree/0.5.1/download" + ], + "strip_prefix": "termtree-0.5.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"termtree\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=termtree\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.1\",\n)\n" + } + }, + "firewood_crates__test-case-3.3.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/test-case/3.3.1/download" + ], + "strip_prefix": "test-case-3.3.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"test_case\",\n proc_macro_deps = [\n \"@firewood_crates__test-case-macros-3.3.1//:test_case_macros\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=test-case\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.3.1\",\n)\n" + } + }, + "firewood_crates__test-case-core-3.3.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/test-case-core/3.3.1/download" + ], + "strip_prefix": "test-case-core-3.3.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"test_case_core\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=test-case-core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.3.1\",\n)\n" + } + }, + "firewood_crates__test-case-macros-3.3.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/test-case-macros/3.3.1/download" + ], + "strip_prefix": "test-case-macros-3.3.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"test_case_macros\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n \"@firewood_crates__test-case-core-3.3.1//:test_case_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=test-case-macros\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"3.3.1\",\n)\n" + } + }, + "firewood_crates__thiserror-2.0.17": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/thiserror/2.0.17/download" + ], + "strip_prefix": "thiserror-2.0.17", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"thiserror\",\n deps = [\n \"@firewood_crates__thiserror-2.0.17//:build_script_build\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__thiserror-impl-2.0.17//:thiserror_impl\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=thiserror\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.0.17\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"thiserror\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=thiserror\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"2.0.17\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__thiserror-impl-2.0.17": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/thiserror-impl/2.0.17/download" + ], + "strip_prefix": "thiserror-impl-2.0.17", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"thiserror_impl\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=thiserror-impl\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.0.17\",\n)\n" + } + }, + "firewood_crates__tikv-jemalloc-sys-0.6.1-5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tikv-jemalloc-sys/0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7/download" + ], + "strip_prefix": "tikv-jemalloc-sys-0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tikv_jemalloc_sys\",\n deps = [\n \"@firewood_crates__libc-0.2.177//:libc\",\n \"@firewood_crates__tikv-jemalloc-sys-0.6.1-5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"background_threads_runtime_support\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tikv-jemalloc-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"background_threads_runtime_support\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n deps = [\n \"@firewood_crates__cc-1.2.46//:cc\",\n ],\n edition = \"2018\",\n links = \"jemalloc\",\n pkg_name = \"tikv-jemalloc-sys\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tikv-jemalloc-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__tikv-jemallocator-0.6.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tikv-jemallocator/0.6.1/download" + ], + "strip_prefix": "tikv-jemallocator-0.6.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tikv_jemallocator\",\n deps = [\n \"@firewood_crates__libc-0.2.177//:libc\",\n \"@firewood_crates__tikv-jemalloc-sys-0.6.1-5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7//:tikv_jemalloc_sys\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"background_threads_runtime_support\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tikv-jemallocator\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.1\",\n)\n" + } + }, + "firewood_crates__tiny-keccak-2.0.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tiny-keccak/2.0.2/download" + ], + "strip_prefix": "tiny-keccak-2.0.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tiny_keccak\",\n deps = [\n \"@firewood_crates__crunchy-0.2.4//:crunchy\",\n \"@firewood_crates__tiny-keccak-2.0.2//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"keccak\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tiny-keccak\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.0.2\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"keccak\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"tiny-keccak\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tiny-keccak\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"2.0.2\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__tinystr-0.8.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tinystr/0.8.2/download" + ], + "strip_prefix": "tinystr-0.8.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tinystr\",\n deps = [\n \"@firewood_crates__zerovec-0.11.5//:zerovec\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__displaydoc-0.2.5//:displaydoc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"zerovec\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tinystr\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.2\",\n)\n" + } + }, + "firewood_crates__tinytemplate-1.2.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tinytemplate/1.2.1/download" + ], + "strip_prefix": "tinytemplate-1.2.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tinytemplate\",\n deps = [\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__serde_json-1.0.145//:serde_json\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tinytemplate\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.2.1\",\n)\n" + } + }, + "firewood_crates__tokio-1.48.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tokio/1.48.0/download" + ], + "strip_prefix": "tokio-1.48.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tokio\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__mio-1.1.0//:mio\",\n \"@firewood_crates__parking_lot-0.12.5//:parking_lot\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # aarch64-apple-darwin\n \"@firewood_crates__socket2-0.6.1//:socket2\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # aarch64-unknown-linux-gnu\n \"@firewood_crates__socket2-0.6.1//:socket2\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__socket2-0.6.1//:socket2\", # x86_64-pc-windows-msvc\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # x86_64-pc-windows-msvc\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # x86_64-unknown-linux-gnu\n \"@firewood_crates__socket2-0.6.1//:socket2\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n \"@firewood_crates__socket2-0.6.1//:socket2\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"bytes\",\n \"default\",\n \"io-std\",\n \"io-util\",\n \"libc\",\n \"mio\",\n \"net\",\n \"parking_lot\",\n \"rt\",\n \"rt-multi-thread\",\n \"socket2\",\n \"sync\",\n \"time\",\n ] + select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"windows-sys\", # x86_64-pc-windows-msvc\n ],\n \"//conditions:default\": [],\n }),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tokio\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.48.0\",\n)\n" + } + }, + "firewood_crates__tokio-rustls-0.26.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tokio-rustls/0.26.4/download" + ], + "strip_prefix": "tokio-rustls-0.26.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tokio_rustls\",\n deps = [\n \"@firewood_crates__rustls-0.23.35//:rustls\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tokio-rustls\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.26.4\",\n)\n" + } + }, + "firewood_crates__tokio-stream-0.1.17": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tokio-stream/0.1.17/download" + ], + "strip_prefix": "tokio-stream-0.1.17", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tokio_stream\",\n deps = [\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tokio-stream\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.17\",\n)\n" + } + }, + "firewood_crates__tokio-util-0.7.17": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tokio-util/0.7.17/download" + ], + "strip_prefix": "tokio-util-0.7.17", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tokio_util\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-sink-0.3.31//:futures_sink\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"codec\",\n \"default\",\n \"io\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tokio-util\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.17\",\n)\n" + } + }, + "firewood_crates__toml-0.9.8": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/toml/0.9.8/download" + ], + "strip_prefix": "toml-0.9.8", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"toml\",\n deps = [\n \"@firewood_crates__serde_core-1.0.228//:serde_core\",\n \"@firewood_crates__serde_spanned-1.0.3//:serde_spanned\",\n \"@firewood_crates__toml_datetime-0.7.3//:toml_datetime\",\n \"@firewood_crates__toml_parser-1.0.4//:toml_parser\",\n \"@firewood_crates__toml_writer-1.0.4//:toml_writer\",\n \"@firewood_crates__winnow-0.7.13//:winnow\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"display\",\n \"parse\",\n \"serde\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=toml\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.8\",\n)\n" + } + }, + "firewood_crates__toml_datetime-0.7.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/toml_datetime/0.7.3/download" + ], + "strip_prefix": "toml_datetime-0.7.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"toml_datetime\",\n deps = [\n \"@firewood_crates__serde_core-1.0.228//:serde_core\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"serde\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=toml_datetime\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.3\",\n)\n" + } + }, + "firewood_crates__toml_edit-0.23.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/toml_edit/0.23.7/download" + ], + "strip_prefix": "toml_edit-0.23.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"toml_edit\",\n deps = [\n \"@firewood_crates__indexmap-2.12.0//:indexmap\",\n \"@firewood_crates__toml_datetime-0.7.3//:toml_datetime\",\n \"@firewood_crates__toml_parser-1.0.4//:toml_parser\",\n \"@firewood_crates__winnow-0.7.13//:winnow\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"parse\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=toml_edit\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.23.7\",\n)\n" + } + }, + "firewood_crates__toml_parser-1.0.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/toml_parser/1.0.4/download" + ], + "strip_prefix": "toml_parser-1.0.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"toml_parser\",\n deps = [\n \"@firewood_crates__winnow-0.7.13//:winnow\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=toml_parser\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.4\",\n)\n" + } + }, + "firewood_crates__toml_writer-1.0.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/toml_writer/1.0.4/download" + ], + "strip_prefix": "toml_writer-1.0.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"toml_writer\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=toml_writer\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.4\",\n)\n" + } + }, + "firewood_crates__tonic-0.14.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tonic/0.14.2/download" + ], + "strip_prefix": "tonic-0.14.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tonic\",\n deps = [\n \"@firewood_crates__base64-0.22.1//:base64\",\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__http-body-1.0.1//:http_body\",\n \"@firewood_crates__http-body-util-0.1.3//:http_body_util\",\n \"@firewood_crates__hyper-1.8.1//:hyper\",\n \"@firewood_crates__hyper-timeout-0.5.2//:hyper_timeout\",\n \"@firewood_crates__hyper-util-0.1.18//:hyper_util\",\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\",\n \"@firewood_crates__pin-project-1.1.10//:pin_project\",\n \"@firewood_crates__sync_wrapper-1.0.2//:sync_wrapper\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__tokio-stream-0.1.17//:tokio_stream\",\n \"@firewood_crates__tower-0.5.2//:tower\",\n \"@firewood_crates__tower-layer-0.3.3//:tower_layer\",\n \"@firewood_crates__tower-service-0.3.3//:tower_service\",\n \"@firewood_crates__tracing-0.1.41//:tracing\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__async-trait-0.1.89//:async_trait\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"channel\",\n \"codegen\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tonic\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.2\",\n)\n" + } + }, + "firewood_crates__tonic-prost-0.14.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tonic-prost/0.14.2/download" + ], + "strip_prefix": "tonic-prost-0.14.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tonic_prost\",\n deps = [\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__prost-0.14.1//:prost\",\n \"@firewood_crates__tonic-0.14.2//:tonic\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tonic-prost\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.14.2\",\n)\n" + } + }, + "firewood_crates__tower-0.5.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tower/0.5.2/download" + ], + "strip_prefix": "tower-0.5.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tower\",\n deps = [\n \"@firewood_crates__futures-core-0.3.31//:futures_core\",\n \"@firewood_crates__futures-util-0.3.31//:futures_util\",\n \"@firewood_crates__indexmap-2.12.0//:indexmap\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__slab-0.4.11//:slab\",\n \"@firewood_crates__sync_wrapper-1.0.2//:sync_wrapper\",\n \"@firewood_crates__tokio-1.48.0//:tokio\",\n \"@firewood_crates__tokio-util-0.7.17//:tokio_util\",\n \"@firewood_crates__tower-layer-0.3.3//:tower_layer\",\n \"@firewood_crates__tower-service-0.3.3//:tower_service\",\n \"@firewood_crates__tracing-0.1.41//:tracing\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"__common\",\n \"balance\",\n \"buffer\",\n \"discover\",\n \"futures-core\",\n \"futures-util\",\n \"indexmap\",\n \"limit\",\n \"load\",\n \"load-shed\",\n \"make\",\n \"pin-project-lite\",\n \"ready-cache\",\n \"slab\",\n \"sync_wrapper\",\n \"tokio\",\n \"tokio-util\",\n \"tracing\",\n \"util\",\n ] + select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"retry\", # aarch64-apple-darwin\n \"timeout\", # aarch64-apple-darwin\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"retry\", # aarch64-unknown-linux-gnu\n \"timeout\", # aarch64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"retry\", # x86_64-pc-windows-msvc\n \"timeout\", # x86_64-pc-windows-msvc\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"retry\", # x86_64-unknown-linux-gnu\n \"timeout\", # x86_64-unknown-linux-gnu\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"retry\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n \"timeout\", # x86_64-unknown-linux-gnu, x86_64-unknown-nixos-gnu\n ],\n \"//conditions:default\": [],\n }),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tower\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.2\",\n)\n" + } + }, + "firewood_crates__tower-http-0.6.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tower-http/0.6.6/download" + ], + "strip_prefix": "tower-http-0.6.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tower_http\",\n deps = [\n \"@firewood_crates__bitflags-2.10.0//:bitflags\",\n \"@firewood_crates__bytes-1.11.0//:bytes\",\n \"@firewood_crates__futures-util-0.3.31//:futures_util\",\n \"@firewood_crates__http-1.3.1//:http\",\n \"@firewood_crates__http-body-1.0.1//:http_body\",\n \"@firewood_crates__iri-string-0.7.9//:iri_string\",\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__tower-0.5.2//:tower\",\n \"@firewood_crates__tower-layer-0.3.3//:tower_layer\",\n \"@firewood_crates__tower-service-0.3.3//:tower_service\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"follow-redirect\",\n \"futures-util\",\n \"iri-string\",\n \"tower\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tower-http\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.6\",\n)\n" + } + }, + "firewood_crates__tower-layer-0.3.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tower-layer/0.3.3/download" + ], + "strip_prefix": "tower-layer-0.3.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tower_layer\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tower-layer\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.3\",\n)\n" + } + }, + "firewood_crates__tower-service-0.3.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tower-service/0.3.3/download" + ], + "strip_prefix": "tower-service-0.3.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tower_service\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tower-service\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.3\",\n)\n" + } + }, + "firewood_crates__tracing-0.1.41": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tracing/0.1.41/download" + ], + "strip_prefix": "tracing-0.1.41", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tracing\",\n deps = [\n \"@firewood_crates__pin-project-lite-0.2.16//:pin_project_lite\",\n \"@firewood_crates__tracing-core-0.1.34//:tracing_core\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__tracing-attributes-0.1.30//:tracing_attributes\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"attributes\",\n \"default\",\n \"std\",\n \"tracing-attributes\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tracing\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.41\",\n)\n" + } + }, + "firewood_crates__tracing-attributes-0.1.30": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tracing-attributes/0.1.30/download" + ], + "strip_prefix": "tracing-attributes-0.1.30", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"tracing_attributes\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tracing-attributes\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.30\",\n)\n" + } + }, + "firewood_crates__tracing-core-0.1.34": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/tracing-core/0.1.34/download" + ], + "strip_prefix": "tracing-core-0.1.34", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"tracing_core\",\n deps = [\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"once_cell\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=tracing-core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.34\",\n)\n" + } + }, + "firewood_crates__trie-standardmap-0.16.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "684aafb332fae6f83d7fe10b3fbfdbe39a1b3234c4e2a618f030815838519516", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/trie-standardmap/0.16.0/download" + ], + "strip_prefix": "trie-standardmap-0.16.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"trie_standardmap\",\n deps = [\n \"@firewood_crates__hash-db-0.16.0//:hash_db\",\n \"@firewood_crates__keccak-hasher-0.16.0//:keccak_hasher\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=trie-standardmap\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.16.0\",\n)\n" + } + }, + "firewood_crates__triomphe-0.1.15": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/triomphe/0.1.15/download" + ], + "strip_prefix": "triomphe-0.1.15", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"triomphe\",\n deps = [\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__stable_deref_trait-1.2.1//:stable_deref_trait\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"serde\",\n \"stable_deref_trait\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=triomphe\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.15\",\n)\n" + } + }, + "firewood_crates__try-lock-0.2.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/try-lock/0.2.5/download" + ], + "strip_prefix": "try-lock-0.2.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"try_lock\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=try-lock\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.5\",\n)\n" + } + }, + "firewood_crates__trybuild-1.0.114": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3e17e807bff86d2a06b52bca4276746584a78375055b6e45843925ce2802b335", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/trybuild/1.0.114/download" + ], + "strip_prefix": "trybuild-1.0.114", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"trybuild\",\n deps = [\n \"@firewood_crates__glob-0.3.3//:glob\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n \"@firewood_crates__serde_json-1.0.145//:serde_json\",\n \"@firewood_crates__target-triple-1.0.0//:target_triple\",\n \"@firewood_crates__termcolor-1.4.1//:termcolor\",\n \"@firewood_crates__toml-0.9.8//:toml\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__serde_derive-1.0.228//:serde_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=trybuild\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.114\",\n)\n" + } + }, + "firewood_crates__typed-builder-0.23.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1cce8e9c8115897e896894868ad4ae6851eff0fb7fd33fa95610e0fa93211886", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/typed-builder/0.23.1/download" + ], + "strip_prefix": "typed-builder-0.23.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"typed_builder\",\n proc_macro_deps = [\n \"@firewood_crates__typed-builder-macro-0.23.1//:typed_builder_macro\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2024\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=typed-builder\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.23.1\",\n)\n" + } + }, + "firewood_crates__typed-builder-macro-0.23.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "921d52b8b19b1a455f54fa76a925a1cf49c0d6a7c6b232fc58523400d1f91560", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/typed-builder-macro/0.23.1/download" + ], + "strip_prefix": "typed-builder-macro-0.23.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"typed_builder_macro\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2024\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=typed-builder-macro\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.23.1\",\n)\n" + } + }, + "firewood_crates__typenum-1.19.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/typenum/1.19.0/download" + ], + "strip_prefix": "typenum-1.19.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"typenum\",\n deps = [\n \"@firewood_crates__typenum-1.19.0//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=typenum\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.19.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2018\",\n pkg_name = \"typenum\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=typenum\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"1.19.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__uint-0.10.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/uint/0.10.0/download" + ], + "strip_prefix": "uint-0.10.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"uint\",\n deps = [\n \"@firewood_crates__byteorder-1.5.0//:byteorder\",\n \"@firewood_crates__crunchy-0.2.4//:crunchy\",\n \"@firewood_crates__hex-0.4.3//:hex\",\n \"@firewood_crates__static_assertions-1.1.0//:static_assertions\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=uint\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.10.0\",\n)\n" + } + }, + "firewood_crates__unarray-0.1.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/unarray/0.1.4/download" + ], + "strip_prefix": "unarray-0.1.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"unarray\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=unarray\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.4\",\n)\n" + } + }, + "firewood_crates__unicode-ident-1.0.22": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/unicode-ident/1.0.22/download" + ], + "strip_prefix": "unicode-ident-1.0.22", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"unicode_ident\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=unicode-ident\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.22\",\n)\n" + } + }, + "firewood_crates__unicode-width-0.2.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/unicode-width/0.2.2/download" + ], + "strip_prefix": "unicode-width-0.2.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"unicode_width\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"cjk\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=unicode-width\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.2\",\n)\n" + } + }, + "firewood_crates__unicode-xid-0.2.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/unicode-xid/0.2.6/download" + ], + "strip_prefix": "unicode-xid-0.2.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"unicode_xid\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=unicode-xid\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.6\",\n)\n" + } + }, + "firewood_crates__unit-prefix-0.5.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/unit-prefix/0.5.2/download" + ], + "strip_prefix": "unit-prefix-0.5.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"unit_prefix\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=unit-prefix\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.2\",\n)\n" + } + }, + "firewood_crates__untrusted-0.9.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/untrusted/0.9.0/download" + ], + "strip_prefix": "untrusted-0.9.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"untrusted\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=untrusted\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.0\",\n)\n" + } + }, + "firewood_crates__url-2.5.7": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/url/2.5.7/download" + ], + "strip_prefix": "url-2.5.7", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"url\",\n deps = [\n \"@firewood_crates__form_urlencoded-1.2.2//:form_urlencoded\",\n \"@firewood_crates__idna-1.1.0//:idna\",\n \"@firewood_crates__percent-encoding-2.3.2//:percent_encoding\",\n \"@firewood_crates__serde-1.0.228//:serde\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"serde\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=url\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.5.7\",\n)\n" + } + }, + "firewood_crates__utf8_iter-1.0.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/utf8_iter/1.0.4/download" + ], + "strip_prefix": "utf8_iter-1.0.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"utf8_iter\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=utf8_iter\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.4\",\n)\n" + } + }, + "firewood_crates__utf8parse-0.2.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/utf8parse/0.2.2/download" + ], + "strip_prefix": "utf8parse-0.2.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"utf8parse\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=utf8parse\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.2\",\n)\n" + } + }, + "firewood_crates__uuid-1.18.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/uuid/1.18.1/download" + ], + "strip_prefix": "uuid-1.18.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"uuid\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=uuid\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.18.1\",\n)\n" + } + }, + "firewood_crates__value-log-1.9.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "62fc7c4ce161f049607ecea654dca3f2d727da5371ae85e2e4f14ce2b98ed67c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/value-log/1.9.0/download" + ], + "strip_prefix": "value-log-1.9.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"value_log\",\n deps = [\n \"@firewood_crates__byteorder-1.5.0//:byteorder\",\n \"@firewood_crates__byteview-0.6.1//:byteview\",\n \"@firewood_crates__interval-heap-0.0.5//:interval_heap\",\n \"@firewood_crates__log-0.4.28//:log\",\n \"@firewood_crates__path-absolutize-3.1.1//:path_absolutize\",\n \"@firewood_crates__rustc-hash-2.1.1//:rustc_hash\",\n \"@firewood_crates__tempfile-3.23.0//:tempfile\",\n \"@firewood_crates__varint-rs-2.2.0//:varint_rs\",\n \"@firewood_crates__xxhash-rust-0.8.15//:xxhash_rust\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=value-log\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.9.0\",\n)\n" + } + }, + "firewood_crates__varint-rs-2.2.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/varint-rs/2.2.0/download" + ], + "strip_prefix": "varint-rs-2.2.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"varint_rs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"signed\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=varint-rs\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.2.0\",\n)\n" + } + }, + "firewood_crates__version_check-0.9.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/version_check/0.9.5/download" + ], + "strip_prefix": "version_check-0.9.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"version_check\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=version_check\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.9.5\",\n)\n" + } + }, + "firewood_crates__wait-timeout-0.2.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wait-timeout/0.2.1/download" + ], + "strip_prefix": "wait-timeout-0.2.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wait_timeout\",\n deps = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__libc-0.2.177//:libc\", # cfg(unix)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wait-timeout\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.1\",\n)\n" + } + }, + "firewood_crates__walkdir-2.5.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/walkdir/2.5.0/download" + ], + "strip_prefix": "walkdir-2.5.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"walkdir\",\n deps = [\n \"@firewood_crates__same-file-1.0.6//:same_file\",\n ] + select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__winapi-util-0.1.11//:winapi_util\", # cfg(windows)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=walkdir\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"2.5.0\",\n)\n" + } + }, + "firewood_crates__want-0.3.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/want/0.3.1/download" + ], + "strip_prefix": "want-0.3.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"want\",\n deps = [\n \"@firewood_crates__try-lock-0.2.5//:try_lock\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=want\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.1\",\n)\n" + } + }, + "firewood_crates__wasi-0.11.1-wasi-snapshot-preview1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wasi/0.11.1+wasi-snapshot-preview1/download" + ], + "strip_prefix": "wasi-0.11.1+wasi-snapshot-preview1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wasi\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasi\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.11.1+wasi-snapshot-preview1\",\n)\n" + } + }, + "firewood_crates__wasip2-1.0.1-wasi-0.2.4": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wasip2/1.0.1+wasi-0.2.4/download" + ], + "strip_prefix": "wasip2-1.0.1+wasi-0.2.4", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wasip2\",\n deps = [\n \"@firewood_crates__wit-bindgen-0.46.0//:wit_bindgen\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasip2\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.0.1+wasi-0.2.4\",\n)\n" + } + }, + "firewood_crates__wasix-0.12.21": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wasix/0.12.21/download" + ], + "strip_prefix": "wasix-0.12.21", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wasix\",\n deps = [\n \"@firewood_crates__wasi-0.11.1-wasi-snapshot-preview1//:wasi\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasix\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.12.21\",\n)\n" + } + }, + "firewood_crates__wasm-bindgen-0.2.105": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wasm-bindgen/0.2.105/download" + ], + "strip_prefix": "wasm-bindgen-0.2.105", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wasm_bindgen\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__wasm-bindgen-0.2.105//:build_script_build\",\n \"@firewood_crates__wasm-bindgen-shared-0.2.105//:wasm_bindgen_shared\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__wasm-bindgen-macro-0.2.105//:wasm_bindgen_macro\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasm-bindgen\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.105\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n aliases = {\n \"@firewood_crates__rustversion-1.0.22//:rustversion\": \"rustversion_compat\",\n },\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n link_deps = [\n \"@firewood_crates__wasm-bindgen-shared-0.2.105//:wasm_bindgen_shared\",\n ],\n edition = \"2021\",\n pkg_name = \"wasm-bindgen\",\n proc_macro_deps = [\n \"@firewood_crates__rustversion-1.0.22//:rustversion\",\n ],\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasm-bindgen\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.2.105\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__wasm-bindgen-futures-0.4.55": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wasm-bindgen-futures/0.4.55/download" + ], + "strip_prefix": "wasm-bindgen-futures-0.4.55", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wasm_bindgen_futures\",\n deps = [\n \"@firewood_crates__cfg-if-1.0.4//:cfg_if\",\n \"@firewood_crates__js-sys-0.3.82//:js_sys\",\n \"@firewood_crates__once_cell-1.21.3//:once_cell\",\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasm-bindgen-futures\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.55\",\n)\n" + } + }, + "firewood_crates__wasm-bindgen-macro-0.2.105": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wasm-bindgen-macro/0.2.105/download" + ], + "strip_prefix": "wasm-bindgen-macro-0.2.105", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"wasm_bindgen_macro\",\n deps = [\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__wasm-bindgen-macro-support-0.2.105//:wasm_bindgen_macro_support\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasm-bindgen-macro\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.105\",\n)\n" + } + }, + "firewood_crates__wasm-bindgen-macro-support-0.2.105": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wasm-bindgen-macro-support/0.2.105/download" + ], + "strip_prefix": "wasm-bindgen-macro-support-0.2.105", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wasm_bindgen_macro_support\",\n deps = [\n \"@firewood_crates__bumpalo-3.19.0//:bumpalo\",\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n \"@firewood_crates__wasm-bindgen-shared-0.2.105//:wasm_bindgen_shared\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasm-bindgen-macro-support\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.105\",\n)\n" + } + }, + "firewood_crates__wasm-bindgen-shared-0.2.105": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wasm-bindgen-shared/0.2.105/download" + ], + "strip_prefix": "wasm-bindgen-shared-0.2.105", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wasm_bindgen_shared\",\n deps = [\n \"@firewood_crates__unicode-ident-1.0.22//:unicode_ident\",\n \"@firewood_crates__wasm-bindgen-shared-0.2.105//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasm-bindgen-shared\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.105\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n links = \"wasm_bindgen\",\n pkg_name = \"wasm-bindgen-shared\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wasm-bindgen-shared\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.2.105\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__weak-table-0.3.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/weak-table/0.3.2/download" + ], + "strip_prefix": "weak-table-0.3.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"weak_table\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=weak-table\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.2\",\n)\n" + } + }, + "firewood_crates__web-sys-0.3.82": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/web-sys/0.3.82/download" + ], + "strip_prefix": "web-sys-0.3.82", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"web_sys\",\n deps = [\n \"@firewood_crates__js-sys-0.3.82//:js_sys\",\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"AbortController\",\n \"AbortSignal\",\n \"Blob\",\n \"BlobPropertyBag\",\n \"EventTarget\",\n \"File\",\n \"FormData\",\n \"Headers\",\n \"ReadableStream\",\n \"Request\",\n \"RequestCache\",\n \"RequestCredentials\",\n \"RequestInit\",\n \"RequestMode\",\n \"Response\",\n \"ServiceWorkerGlobalScope\",\n \"Window\",\n \"WorkerGlobalScope\",\n \"default\",\n \"std\",\n ] + select({\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"CanvasRenderingContext2d\", # wasm32-unknown-unknown\n \"Document\", # wasm32-unknown-unknown\n \"DomRect\", # wasm32-unknown-unknown\n \"DomRectReadOnly\", # wasm32-unknown-unknown\n \"Element\", # wasm32-unknown-unknown\n \"HtmlCanvasElement\", # wasm32-unknown-unknown\n \"HtmlElement\", # wasm32-unknown-unknown\n \"Node\", # wasm32-unknown-unknown\n \"Performance\", # wasm32-unknown-unknown\n ],\n \"//conditions:default\": [],\n }),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=web-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.82\",\n)\n" + } + }, + "firewood_crates__web-time-1.1.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/web-time/1.1.0/download" + ], + "strip_prefix": "web-time-1.1.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"web_time\",\n deps = select({\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [\n \"@firewood_crates__js-sys-0.3.82//:js_sys\", # cfg(all(target_family = \"wasm\", target_os = \"unknown\"))\n \"@firewood_crates__wasm-bindgen-0.2.105//:wasm_bindgen\", # cfg(all(target_family = \"wasm\", target_os = \"unknown\"))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=web-time\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.1.0\",\n)\n" + } + }, + "firewood_crates__winapi-0.3.9": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/winapi/0.3.9/download" + ], + "strip_prefix": "winapi-0.3.9", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"winapi\",\n deps = [\n \"@firewood_crates__winapi-0.3.9//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"libloaderapi\",\n \"memoryapi\",\n \"processthreadsapi\",\n \"profileapi\",\n \"psapi\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=winapi\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.3.9\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"libloaderapi\",\n \"memoryapi\",\n \"processthreadsapi\",\n \"profileapi\",\n \"psapi\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2015\",\n pkg_name = \"winapi\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=winapi\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.3.9\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__winapi-i686-pc-windows-gnu-0.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/winapi-i686-pc-windows-gnu/0.4.0/download" + ], + "strip_prefix": "winapi-i686-pc-windows-gnu-0.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"winapi_i686_pc_windows_gnu\",\n deps = [\n \"@firewood_crates__winapi-i686-pc-windows-gnu-0.4.0//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=winapi-i686-pc-windows-gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2015\",\n pkg_name = \"winapi-i686-pc-windows-gnu\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=winapi-i686-pc-windows-gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.4.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__winapi-util-0.1.11": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/winapi-util/0.1.11/download" + ], + "strip_prefix": "winapi-util-0.1.11", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"winapi_util\",\n deps = select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows-sys-0.61.2//:windows_sys\", # cfg(windows)\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=winapi-util\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.11\",\n)\n" + } + }, + "firewood_crates__winapi-x86_64-pc-windows-gnu-0.4.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/winapi-x86_64-pc-windows-gnu/0.4.0/download" + ], + "strip_prefix": "winapi-x86_64-pc-windows-gnu-0.4.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"winapi_x86_64_pc_windows_gnu\",\n deps = [\n \"@firewood_crates__winapi-x86_64-pc-windows-gnu-0.4.0//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2015\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=winapi-x86_64-pc-windows-gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2015\",\n pkg_name = \"winapi-x86_64-pc-windows-gnu\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=winapi-x86_64-pc-windows-gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.4.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows-core-0.62.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-core/0.62.2/download" + ], + "strip_prefix": "windows-core-0.62.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_core\",\n deps = [\n \"@firewood_crates__windows-link-0.2.1//:windows_link\",\n \"@firewood_crates__windows-result-0.4.1//:windows_result\",\n \"@firewood_crates__windows-strings-0.5.1//:windows_strings\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__windows-implement-0.60.2//:windows_implement\",\n \"@firewood_crates__windows-interface-0.59.3//:windows_interface\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-core\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.62.2\",\n)\n" + } + }, + "firewood_crates__windows-implement-0.60.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-implement/0.60.2/download" + ], + "strip_prefix": "windows-implement-0.60.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"windows_implement\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-implement\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.60.2\",\n)\n" + } + }, + "firewood_crates__windows-interface-0.59.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-interface/0.59.3/download" + ], + "strip_prefix": "windows-interface-0.59.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"windows_interface\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-interface\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.59.3\",\n)\n" + } + }, + "firewood_crates__windows-link-0.2.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-link/0.2.1/download" + ], + "strip_prefix": "windows-link-0.2.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_link\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-link\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.1\",\n)\n" + } + }, + "firewood_crates__windows-result-0.4.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-result/0.4.1/download" + ], + "strip_prefix": "windows-result-0.4.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_result\",\n deps = [\n \"@firewood_crates__windows-link-0.2.1//:windows_link\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-result\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.4.1\",\n)\n" + } + }, + "firewood_crates__windows-strings-0.5.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-strings/0.5.1/download" + ], + "strip_prefix": "windows-strings-0.5.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_strings\",\n deps = [\n \"@firewood_crates__windows-link-0.2.1//:windows_link\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-strings\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.1\",\n)\n" + } + }, + "firewood_crates__windows-sys-0.52.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-sys/0.52.0/download" + ], + "strip_prefix": "windows-sys-0.52.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_sys\",\n deps = [\n \"@firewood_crates__windows-targets-0.52.6//:windows_targets\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.0\",\n)\n" + } + }, + "firewood_crates__windows-sys-0.60.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-sys/0.60.2/download" + ], + "strip_prefix": "windows-sys-0.60.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_sys\",\n deps = [\n \"@firewood_crates__windows-targets-0.53.5//:windows_targets\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"Win32\",\n \"Win32_Foundation\",\n \"Win32_Networking\",\n \"Win32_Networking_WinSock\",\n \"Win32_System\",\n \"Win32_System_IO\",\n \"Win32_System_Threading\",\n \"Win32_System_WindowsProgramming\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.60.2\",\n)\n" + } + }, + "firewood_crates__windows-sys-0.61.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-sys/0.61.2/download" + ], + "strip_prefix": "windows-sys-0.61.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_sys\",\n deps = [\n \"@firewood_crates__windows-link-0.2.1//:windows_link\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"Wdk\",\n \"Wdk_Foundation\",\n \"Wdk_Storage\",\n \"Wdk_Storage_FileSystem\",\n \"Wdk_System\",\n \"Wdk_System_IO\",\n \"Win32\",\n \"Win32_Foundation\",\n \"Win32_Networking\",\n \"Win32_Networking_WinSock\",\n \"Win32_Security\",\n \"Win32_Security_Authentication\",\n \"Win32_Security_Authentication_Identity\",\n \"Win32_Security_Credentials\",\n \"Win32_Security_Cryptography\",\n \"Win32_Storage\",\n \"Win32_Storage_FileSystem\",\n \"Win32_System\",\n \"Win32_System_Console\",\n \"Win32_System_IO\",\n \"Win32_System_LibraryLoader\",\n \"Win32_System_Memory\",\n \"Win32_System_Pipes\",\n \"Win32_System_SystemInformation\",\n \"Win32_System_SystemServices\",\n \"Win32_System_WindowsProgramming\",\n \"Win32_UI\",\n \"Win32_UI_Input\",\n \"Win32_UI_Input_KeyboardAndMouse\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-sys\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.61.2\",\n)\n" + } + }, + "firewood_crates__windows-targets-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-targets/0.52.6/download" + ], + "strip_prefix": "windows-targets-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_targets\",\n deps = select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows_x86_64_msvc-0.52.6//:windows_x86_64_msvc\", # cfg(all(any(target_arch = \"x86_64\", target_arch = \"arm64ec\"), target_env = \"msvc\", not(windows_raw_dylib)))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__windows_x86_64_gnu-0.52.6//:windows_x86_64_gnu\", # cfg(all(target_arch = \"x86_64\", target_env = \"gnu\", not(target_abi = \"llvm\"), not(windows_raw_dylib)))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__windows_x86_64_gnu-0.52.6//:windows_x86_64_gnu\", # cfg(all(target_arch = \"x86_64\", target_env = \"gnu\", not(target_abi = \"llvm\"), not(windows_raw_dylib)))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-targets\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n" + } + }, + "firewood_crates__windows-targets-0.53.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows-targets/0.53.5/download" + ], + "strip_prefix": "windows-targets-0.53.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_targets\",\n deps = select({\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [\n \"@firewood_crates__windows_x86_64_msvc-0.53.1//:windows_x86_64_msvc\", # cfg(all(any(target_arch = \"x86_64\", target_arch = \"arm64ec\"), target_env = \"msvc\", not(windows_raw_dylib)))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [\n \"@firewood_crates__windows_x86_64_gnu-0.53.1//:windows_x86_64_gnu\", # cfg(all(target_arch = \"x86_64\", target_env = \"gnu\", not(target_abi = \"llvm\"), not(windows_raw_dylib)))\n ],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [\n \"@firewood_crates__windows_x86_64_gnu-0.53.1//:windows_x86_64_gnu\", # cfg(all(target_arch = \"x86_64\", target_env = \"gnu\", not(target_abi = \"llvm\"), not(windows_raw_dylib)))\n ],\n \"//conditions:default\": [],\n }),\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows-targets\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.5\",\n)\n" + } + }, + "firewood_crates__windows_aarch64_gnullvm-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_aarch64_gnullvm/0.52.6/download" + ], + "strip_prefix": "windows_aarch64_gnullvm-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_aarch64_gnullvm\",\n deps = [\n \"@firewood_crates__windows_aarch64_gnullvm-0.52.6//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_aarch64_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_aarch64_gnullvm\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_aarch64_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.52.6\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_aarch64_gnullvm-0.53.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_aarch64_gnullvm/0.53.1/download" + ], + "strip_prefix": "windows_aarch64_gnullvm-0.53.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_aarch64_gnullvm\",\n deps = [\n \"@firewood_crates__windows_aarch64_gnullvm-0.53.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_aarch64_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_aarch64_gnullvm\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_aarch64_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.53.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_aarch64_msvc-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_aarch64_msvc/0.52.6/download" + ], + "strip_prefix": "windows_aarch64_msvc-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_aarch64_msvc\",\n deps = [\n \"@firewood_crates__windows_aarch64_msvc-0.52.6//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_aarch64_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_aarch64_msvc\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_aarch64_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.52.6\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_aarch64_msvc-0.53.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_aarch64_msvc/0.53.1/download" + ], + "strip_prefix": "windows_aarch64_msvc-0.53.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_aarch64_msvc\",\n deps = [\n \"@firewood_crates__windows_aarch64_msvc-0.53.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_aarch64_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_aarch64_msvc\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_aarch64_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.53.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_i686_gnu-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_i686_gnu/0.52.6/download" + ], + "strip_prefix": "windows_i686_gnu-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_i686_gnu\",\n deps = [\n \"@firewood_crates__windows_i686_gnu-0.52.6//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_i686_gnu\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.52.6\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_i686_gnu-0.53.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_i686_gnu/0.53.1/download" + ], + "strip_prefix": "windows_i686_gnu-0.53.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_i686_gnu\",\n deps = [\n \"@firewood_crates__windows_i686_gnu-0.53.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_i686_gnu\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.53.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_i686_gnullvm-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_i686_gnullvm/0.52.6/download" + ], + "strip_prefix": "windows_i686_gnullvm-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_i686_gnullvm\",\n deps = [\n \"@firewood_crates__windows_i686_gnullvm-0.52.6//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_i686_gnullvm\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.52.6\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_i686_gnullvm-0.53.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_i686_gnullvm/0.53.1/download" + ], + "strip_prefix": "windows_i686_gnullvm-0.53.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_i686_gnullvm\",\n deps = [\n \"@firewood_crates__windows_i686_gnullvm-0.53.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_i686_gnullvm\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.53.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_i686_msvc-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_i686_msvc/0.52.6/download" + ], + "strip_prefix": "windows_i686_msvc-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_i686_msvc\",\n deps = [\n \"@firewood_crates__windows_i686_msvc-0.52.6//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_i686_msvc\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.52.6\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_i686_msvc-0.53.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_i686_msvc/0.53.1/download" + ], + "strip_prefix": "windows_i686_msvc-0.53.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_i686_msvc\",\n deps = [\n \"@firewood_crates__windows_i686_msvc-0.53.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_i686_msvc\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_i686_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.53.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_x86_64_gnu-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_x86_64_gnu/0.52.6/download" + ], + "strip_prefix": "windows_x86_64_gnu-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_x86_64_gnu\",\n deps = [\n \"@firewood_crates__windows_x86_64_gnu-0.52.6//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_x86_64_gnu\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.52.6\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_x86_64_gnu-0.53.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_x86_64_gnu/0.53.1/download" + ], + "strip_prefix": "windows_x86_64_gnu-0.53.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_x86_64_gnu\",\n deps = [\n \"@firewood_crates__windows_x86_64_gnu-0.53.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_x86_64_gnu\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_gnu\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.53.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_x86_64_gnullvm-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_x86_64_gnullvm/0.52.6/download" + ], + "strip_prefix": "windows_x86_64_gnullvm-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_x86_64_gnullvm\",\n deps = [\n \"@firewood_crates__windows_x86_64_gnullvm-0.52.6//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_x86_64_gnullvm\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.52.6\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_x86_64_gnullvm-0.53.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_x86_64_gnullvm/0.53.1/download" + ], + "strip_prefix": "windows_x86_64_gnullvm-0.53.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_x86_64_gnullvm\",\n deps = [\n \"@firewood_crates__windows_x86_64_gnullvm-0.53.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_x86_64_gnullvm\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_gnullvm\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.53.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_x86_64_msvc-0.52.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_x86_64_msvc/0.52.6/download" + ], + "strip_prefix": "windows_x86_64_msvc-0.52.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_x86_64_msvc\",\n deps = [\n \"@firewood_crates__windows_x86_64_msvc-0.52.6//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.52.6\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_x86_64_msvc\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.52.6\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__windows_x86_64_msvc-0.53.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/windows_x86_64_msvc/0.53.1/download" + ], + "strip_prefix": "windows_x86_64_msvc-0.53.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"windows_x86_64_msvc\",\n deps = [\n \"@firewood_crates__windows_x86_64_msvc-0.53.1//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.53.1\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"windows_x86_64_msvc\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=windows_x86_64_msvc\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.53.1\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__winnow-0.7.13": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/winnow/0.7.13/download" + ], + "strip_prefix": "winnow-0.7.13", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"winnow\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n \"std\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=winnow\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.7.13\",\n)\n" + } + }, + "firewood_crates__wit-bindgen-0.46.0": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wit-bindgen/0.46.0/download" + ], + "strip_prefix": "wit-bindgen-0.46.0", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wit_bindgen\",\n deps = [\n \"@firewood_crates__wit-bindgen-0.46.0//:build_script_build\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wit-bindgen\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.46.0\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"wit-bindgen\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wit-bindgen\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.46.0\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__writeable-0.6.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/writeable/0.6.2/download" + ], + "strip_prefix": "writeable-0.6.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"writeable\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=writeable\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.6.2\",\n)\n" + } + }, + "firewood_crates__wyz-0.5.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/wyz/0.5.1/download" + ], + "strip_prefix": "wyz-0.5.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"wyz\",\n deps = [\n \"@firewood_crates__tap-1.0.1//:tap\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=wyz\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.5.1\",\n)\n" + } + }, + "firewood_crates__xxhash-rust-0.8.15": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/xxhash-rust/0.8.15/download" + ], + "strip_prefix": "xxhash-rust-0.8.15", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"xxhash_rust\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"xxh3\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2018\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=xxhash-rust\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.15\",\n)\n" + } + }, + "firewood_crates__yoke-0.8.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/yoke/0.8.1/download" + ], + "strip_prefix": "yoke-0.8.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"yoke\",\n deps = [\n \"@firewood_crates__stable_deref_trait-1.2.1//:stable_deref_trait\",\n \"@firewood_crates__zerofrom-0.1.6//:zerofrom\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__yoke-derive-0.8.1//:yoke_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"derive\",\n \"zerofrom\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=yoke\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.1\",\n)\n" + } + }, + "firewood_crates__yoke-derive-0.8.1": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/yoke-derive/0.8.1/download" + ], + "strip_prefix": "yoke-derive-0.8.1", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"yoke_derive\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n \"@firewood_crates__synstructure-0.13.2//:synstructure\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=yoke-derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.1\",\n)\n" + } + }, + "firewood_crates__zerocopy-0.8.27": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/zerocopy/0.8.27/download" + ], + "strip_prefix": "zerocopy-0.8.27", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\n \"@rules_rust//cargo:defs.bzl\",\n \"cargo_build_script\",\n \"cargo_toml_env_vars\",\n)\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"zerocopy\",\n deps = [\n \"@firewood_crates__zerocopy-0.8.27//:build_script_build\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__zerocopy-derive-0.8.27//:zerocopy_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"derive\",\n \"simd\",\n \"zerocopy-derive\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zerocopy\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.27\",\n)\n\ncargo_build_script(\n name = \"_bs\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \"**/*.rs\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"derive\",\n \"simd\",\n \"zerocopy-derive\",\n ],\n crate_name = \"build_script_build\",\n crate_root = \"build.rs\",\n data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n edition = \"2021\",\n pkg_name = \"zerocopy\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zerocopy\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n version = \"0.8.27\",\n visibility = [\"//visibility:private\"],\n)\n\nalias(\n name = \"build_script_build\",\n actual = \":_bs\",\n tags = [\"manual\"],\n)\n" + } + }, + "firewood_crates__zerocopy-derive-0.8.27": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/zerocopy-derive/0.8.27/download" + ], + "strip_prefix": "zerocopy-derive-0.8.27", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"zerocopy_derive\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zerocopy-derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.8.27\",\n)\n" + } + }, + "firewood_crates__zerofrom-0.1.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/zerofrom/0.1.6/download" + ], + "strip_prefix": "zerofrom-0.1.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"zerofrom\",\n proc_macro_deps = [\n \"@firewood_crates__zerofrom-derive-0.1.6//:zerofrom_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"derive\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zerofrom\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.6\",\n)\n" + } + }, + "firewood_crates__zerofrom-derive-0.1.6": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/zerofrom-derive/0.1.6/download" + ], + "strip_prefix": "zerofrom-derive-0.1.6", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"zerofrom_derive\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n \"@firewood_crates__synstructure-0.13.2//:synstructure\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zerofrom-derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.1.6\",\n)\n" + } + }, + "firewood_crates__zeroize-1.8.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/zeroize/1.8.2/download" + ], + "strip_prefix": "zeroize-1.8.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"zeroize\",\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"alloc\",\n \"default\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zeroize\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"1.8.2\",\n)\n" + } + }, + "firewood_crates__zerotrie-0.2.3": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/zerotrie/0.2.3/download" + ], + "strip_prefix": "zerotrie-0.2.3", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"zerotrie\",\n deps = [\n \"@firewood_crates__yoke-0.8.1//:yoke\",\n \"@firewood_crates__zerofrom-0.1.6//:zerofrom\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__displaydoc-0.2.5//:displaydoc\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"yoke\",\n \"zerofrom\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zerotrie\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.2.3\",\n)\n" + } + }, + "firewood_crates__zerovec-0.11.5": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/zerovec/0.11.5/download" + ], + "strip_prefix": "zerovec-0.11.5", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_library\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_library(\n name = \"zerovec\",\n deps = [\n \"@firewood_crates__yoke-0.8.1//:yoke\",\n \"@firewood_crates__zerofrom-0.1.6//:zerofrom\",\n ],\n proc_macro_deps = [\n \"@firewood_crates__zerovec-derive-0.11.2//:zerovec_derive\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_features = [\n \"derive\",\n \"yoke\",\n ],\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zerovec\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.11.5\",\n)\n" + } + }, + "firewood_crates__zerovec-derive-0.11.2": { + "bzlFile": "@@bazel_tools//tools/build_defs/repo:http.bzl", + "ruleClassName": "http_archive", + "attributes": { + "patch_args": [ + "-p0" + ], + "patch_tool": "", + "patches": [], + "remote_patch_strip": 1, + "sha256": "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3", + "type": "tar.gz", + "urls": [ + "https://static.crates.io/crates/zerovec-derive/0.11.2/download" + ], + "strip_prefix": "zerovec-derive-0.11.2", + "build_file_content": "###############################################################################\n# @generated\n# DO NOT MODIFY: This file is auto-generated by a crate_universe tool. To \n# regenerate this file, run the following:\n#\n# bazel mod show_repo 'avalanchego'\n###############################################################################\n\nload(\"@rules_rust//cargo:defs.bzl\", \"cargo_toml_env_vars\")\n\nload(\"@rules_rust//rust:defs.bzl\", \"rust_proc_macro\")\n\n# buildifier: disable=bzl-visibility\nload(\"@rules_rust//crate_universe/private:selects.bzl\", \"selects\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\ncargo_toml_env_vars(\n name = \"cargo_toml_env_vars\",\n src = \"Cargo.toml\",\n)\n\nrust_proc_macro(\n name = \"zerovec_derive\",\n deps = [\n \"@firewood_crates__proc-macro2-1.0.103//:proc_macro2\",\n \"@firewood_crates__quote-1.0.42//:quote\",\n \"@firewood_crates__syn-2.0.110//:syn\",\n ],\n compile_data = glob(\n allow_empty = True,\n include = [\"**\"],\n exclude = [\n \"**/* *\",\n \".tmp_git_root/**/*\",\n \"BUILD\",\n \"BUILD.bazel\",\n \"WORKSPACE\",\n \"WORKSPACE.bazel\",\n ],\n ),\n crate_root = \"src/lib.rs\",\n edition = \"2021\",\n rustc_env_files = [\n \":cargo_toml_env_vars\",\n ],\n rustc_flags = [\n \"--cap-lints=allow\",\n ],\n srcs = glob(\n allow_empty = True,\n include = [\"**/*.rs\"],\n ),\n tags = [\n \"cargo-bazel\",\n \"crate-name=zerovec-derive\",\n \"manual\",\n \"noclippy\",\n \"norustfmt\",\n ],\n target_compatible_with = select({\n \"@rules_rust//rust/platform:aarch64-apple-darwin\": [],\n \"@rules_rust//rust/platform:aarch64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:wasm32-unknown-unknown\": [],\n \"@rules_rust//rust/platform:wasm32-wasip1\": [],\n \"@rules_rust//rust/platform:x86_64-pc-windows-msvc\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-linux-gnu\": [],\n \"@rules_rust//rust/platform:x86_64-unknown-nixos-gnu\": [],\n \"//conditions:default\": [\"@platforms//:incompatible\"],\n }),\n version = \"0.11.2\",\n)\n" + } + } + }, + "moduleExtensionMetadata": { + "useAllRepos": "NO", + "reproducible": false + }, + "recordedRepoMappingEntries": [ + [ + "bazel_features~", + "bazel_features_globals", + "bazel_features~~version_extension~bazel_features_globals" + ], + [ + "bazel_features~", + "bazel_features_version", + "bazel_features~~version_extension~bazel_features_version" + ], + [ + "rules_cc~", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_cc~", + "rules_cc", + "rules_cc~" + ], + [ + "rules_rust~", + "bazel_features", + "bazel_features~" + ], + [ + "rules_rust~", + "bazel_skylib", + "bazel_skylib~" + ], + [ + "rules_rust~", + "bazel_tools", + "bazel_tools" + ], + [ + "rules_rust~", + "rules_cc", + "rules_cc~" + ], + [ + "rules_rust~", + "rules_rust", + "rules_rust~" + ] + ] + } + } + } +} diff --git a/Taskfile.yml b/Taskfile.yml index a4b4e782be70..0c4db9f716fd 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -461,3 +461,47 @@ tasks: cmds: - task: build - cmd: bash -x ./scripts/tests.upgrade.sh {{.CLI_ARGS}} + + # ============================================================================ + # Bazel build tasks + # ============================================================================ + + bazel-build: + desc: Build avalanchego with Bazel + cmds: + - bazel build //main:avalanchego + + bazel-build-opt: + desc: Build avalanchego with Bazel (optimized) + cmds: + - bazel build --compilation_mode=opt //main:avalanchego + + bazel-test: + desc: Run all tests with Bazel + cmds: + - bazel test //... + + bazel-clean: + desc: Clean Bazel build outputs + cmds: + - bazel clean + + bazel-clean-all: + desc: Clean all Bazel caches (full clean) + cmds: + - bazel clean --expunge + + bazel-gazelle: + desc: Run gazelle to update BUILD files + cmds: + - bazel run //:gazelle + + bazel-fmt: + desc: Format BUILD files with buildifier + cmds: + - buildifier -r . + + bazel-mod-tidy: + desc: Tidy MODULE.bazel use_repo calls + cmds: + - bazel mod tidy diff --git a/api/BUILD.bazel b/api/BUILD.bazel new file mode 100644 index 000000000000..7b27d5dca165 --- /dev/null +++ b/api/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "api", + srcs = [ + "common_args_responses.go", + "traced_handler.go", + ], + importpath = "github.com/ava-labs/avalanchego/api", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//trace", + "//utils/formatting", + "//utils/json", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + ], +) diff --git a/api/admin/BUILD.bazel b/api/admin/BUILD.bazel new file mode 100644 index 000000000000..46e9cb79bbb9 --- /dev/null +++ b/api/admin/BUILD.bazel @@ -0,0 +1,55 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "admin", + srcs = [ + "client.go", + "key_value_reader.go", + "service.go", + ], + importpath = "github.com/ava-labs/avalanchego/api/admin", + visibility = ["//visibility:public"], + deps = [ + "//api", + "//api/server", + "//chains", + "//database", + "//database/rpcdb", + "//ids", + "//proto/pb/rpcdb", + "//utils", + "//utils/constants", + "//utils/formatting", + "//utils/json", + "//utils/logging", + "//utils/perms", + "//utils/profiler", + "//utils/rpc", + "//vms", + "//vms/registry", + "@com_github_gorilla_rpc//v2:rpc", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "admin_test", + srcs = [ + "client_test.go", + "service_test.go", + ], + embed = [":admin"], + deps = [ + "//api", + "//database/memdb", + "//ids", + "//proto/pb/rpcdb", + "//utils/formatting", + "//utils/logging", + "//utils/rpc", + "//vms/registry/registrymock", + "//vms/vmsmock", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/api/connectclient/BUILD.bazel b/api/connectclient/BUILD.bazel new file mode 100644 index 000000000000..b9d3777614a0 --- /dev/null +++ b/api/connectclient/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "connectclient", + srcs = ["client.go"], + importpath = "github.com/ava-labs/avalanchego/api/connectclient", + visibility = ["//visibility:public"], + deps = [ + "//api/server", + "@com_connectrpc_connect//:connect", + "@org_golang_x_net//http2", + ], +) diff --git a/api/health/BUILD.bazel b/api/health/BUILD.bazel new file mode 100644 index 000000000000..5cbea4dc69fd --- /dev/null +++ b/api/health/BUILD.bazel @@ -0,0 +1,44 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "health", + srcs = [ + "checker.go", + "client.go", + "handler.go", + "health.go", + "result.go", + "service.go", + "worker.go", + ], + importpath = "github.com/ava-labs/avalanchego/api/health", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/json", + "//utils/logging", + "//utils/rpc", + "//utils/set", + "@com_github_gorilla_rpc//v2:rpc", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "health_test", + srcs = [ + "client_test.go", + "health_test.go", + "service_test.go", + ], + embed = [":health"], + deps = [ + "//ids", + "//utils", + "//utils/logging", + "//utils/rpc", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/api/info/BUILD.bazel b/api/info/BUILD.bazel new file mode 100644 index 000000000000..b7d2a0ba7c04 --- /dev/null +++ b/api/info/BUILD.bazel @@ -0,0 +1,52 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "info", + srcs = [ + "client.go", + "service.go", + ], + importpath = "github.com/ava-labs/avalanchego/api/info", + visibility = ["//visibility:public"], + deps = [ + "//chains", + "//ids", + "//network", + "//network/peer", + "//snow/networking/benchlist", + "//snow/validators", + "//upgrade", + "//utils", + "//utils/constants", + "//utils/json", + "//utils/logging", + "//utils/rpc", + "//utils/set", + "//utils/units", + "//version", + "//vms", + "//vms/nftfx", + "//vms/platformvm/signer", + "//vms/propertyfx", + "//vms/secp256k1fx", + "@com_github_gorilla_rpc//v2:rpc", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "info_test", + srcs = [ + "client_test.go", + "service_test.go", + ], + embed = [":info"], + deps = [ + "//ids", + "//utils/logging", + "//utils/rpc", + "//vms/vmsmock", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/api/metrics/BUILD.bazel b/api/metrics/BUILD.bazel new file mode 100644 index 000000000000..a7762e66d5e2 --- /dev/null +++ b/api/metrics/BUILD.bazel @@ -0,0 +1,38 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "metrics", + srcs = [ + "client.go", + "label_gatherer.go", + "multi_gatherer.go", + "prefix_gatherer.go", + ], + importpath = "github.com/ava-labs/avalanchego/api/metrics", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/metric", + "//utils/rpc", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_model//go", + "@com_github_prometheus_common//expfmt", + "@org_golang_google_protobuf//proto", + ], +) + +go_test( + name = "metrics_test", + srcs = [ + "gatherer_test.go", + "label_gatherer_test.go", + "prefix_gatherer_test.go", + ], + embed = [":metrics"], + deps = [ + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/testutil", + "@com_github_prometheus_client_model//go", + "@com_github_stretchr_testify//require", + ], +) diff --git a/api/server/BUILD.bazel b/api/server/BUILD.bazel new file mode 100644 index 000000000000..d3126beaeb46 --- /dev/null +++ b/api/server/BUILD.bazel @@ -0,0 +1,44 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "server", + srcs = [ + "allowed_hosts.go", + "metrics.go", + "router.go", + "server.go", + ], + importpath = "github.com/ava-labs/avalanchego/api/server", + visibility = ["//visibility:public"], + deps = [ + "//api", + "//ids", + "//snow", + "//snow/engine/common", + "//trace", + "//utils/constants", + "//utils/logging", + "//utils/set", + "@com_github_gorilla_mux//:mux", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_rs_cors//:cors", + "@org_golang_x_net//http2", + "@org_golang_x_net//http2/h2c", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "server_test", + srcs = [ + "allowed_hosts_test.go", + "router_test.go", + "server_test.go", + ], + embed = [":server"], + deps = [ + "//snow", + "//snow/snowtest", + "@com_github_stretchr_testify//require", + ], +) diff --git a/app/BUILD.bazel b/app/BUILD.bazel new file mode 100644 index 000000000000..7e974c078828 --- /dev/null +++ b/app/BUILD.bazel @@ -0,0 +1,17 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "app", + srcs = ["app.go"], + importpath = "github.com/ava-labs/avalanchego/app", + visibility = ["//visibility:public"], + deps = [ + "//config/node", + "//node", + "//utils", + "//utils/logging", + "//utils/perms", + "//utils/ulimit", + "@org_uber_go_zap//:zap", + ], +) diff --git a/cache/BUILD.bazel b/cache/BUILD.bazel new file mode 100644 index 000000000000..c317de38a015 --- /dev/null +++ b/cache/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "cache", + srcs = [ + "cache.go", + "empty.go", + ], + importpath = "github.com/ava-labs/avalanchego/cache", + visibility = ["//visibility:public"], + deps = ["//utils"], +) diff --git a/cache/cachetest/BUILD.bazel b/cache/cachetest/BUILD.bazel new file mode 100644 index 000000000000..5bd4162ad7a6 --- /dev/null +++ b/cache/cachetest/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "cachetest", + srcs = ["cacher.go"], + importpath = "github.com/ava-labs/avalanchego/cache/cachetest", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/cache/lru/BUILD.bazel b/cache/lru/BUILD.bazel new file mode 100644 index 000000000000..60129c60322e --- /dev/null +++ b/cache/lru/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "lru", + srcs = [ + "cache.go", + "deduplicator.go", + "sized_cache.go", + ], + importpath = "github.com/ava-labs/avalanchego/cache/lru", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//utils", + "//utils/linked", + ], +) + +go_test( + name = "lru_test", + srcs = [ + "cache_test.go", + "deduplicator_test.go", + "sized_cache_test.go", + ], + embed = [":lru"], + deps = [ + "//cache/cachetest", + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/cache/metercacher/BUILD.bazel b/cache/metercacher/BUILD.bazel new file mode 100644 index 000000000000..1769ad615126 --- /dev/null +++ b/cache/metercacher/BUILD.bazel @@ -0,0 +1,29 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "metercacher", + srcs = [ + "cache.go", + "metrics.go", + ], + importpath = "github.com/ava-labs/avalanchego/cache/metercacher", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "metercacher_test", + srcs = ["cache_test.go"], + embed = [":metercacher"], + deps = [ + "//cache", + "//cache/cachetest", + "//cache/lru", + "//ids", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/chains/BUILD.bazel b/chains/BUILD.bazel new file mode 100644 index 000000000000..ea97ac3352c6 --- /dev/null +++ b/chains/BUILD.bazel @@ -0,0 +1,84 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "chains", + srcs = [ + "linearizable_vm.go", + "manager.go", + "registrant.go", + "subnets.go", + "test_manager.go", + ], + importpath = "github.com/ava-labs/avalanchego/chains", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//api/metrics", + "//api/server", + "//chains/atomic", + "//database", + "//database/meterdb", + "//database/prefixdb", + "//ids", + "//message", + "//network", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/consensus/snowball", + "//snow/consensus/snowman", + "//snow/engine/avalanche", + "//snow/engine/avalanche/bootstrap", + "//snow/engine/avalanche/bootstrap/queue", + "//snow/engine/avalanche/getter", + "//snow/engine/avalanche/state", + "//snow/engine/avalanche/vertex", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/snowman", + "//snow/engine/snowman/block", + "//snow/engine/snowman/bootstrap", + "//snow/engine/snowman/getter", + "//snow/engine/snowman/syncer", + "//snow/networking/handler", + "//snow/networking/router", + "//snow/networking/sender", + "//snow/networking/timeout", + "//snow/networking/tracker", + "//snow/validators", + "//staking", + "//subnets", + "//trace", + "//upgrade", + "//utils/buffer", + "//utils/constants", + "//utils/crypto/bls", + "//utils/logging", + "//utils/metric", + "//utils/perms", + "//utils/set", + "//vms", + "//vms/fx", + "//vms/metervm", + "//vms/nftfx", + "//vms/platformvm/warp", + "//vms/propertyfx", + "//vms/proposervm", + "//vms/secp256k1fx", + "//vms/tracedvm", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "chains_test", + srcs = ["subnets_test.go"], + embed = [":chains"], + deps = [ + "//ids", + "//subnets", + "//utils/constants", + "@com_github_stretchr_testify//require", + ], +) diff --git a/chains/atomic/BUILD.bazel b/chains/atomic/BUILD.bazel new file mode 100644 index 000000000000..629d76e3aa40 --- /dev/null +++ b/chains/atomic/BUILD.bazel @@ -0,0 +1,44 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "atomic", + srcs = [ + "codec.go", + "memory.go", + "prefixes.go", + "shared_memory.go", + "state.go", + "writer.go", + ], + importpath = "github.com/ava-labs/avalanchego/chains/atomic", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//database", + "//database/linkeddb", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//utils", + "//utils/hashing", + "//utils/set", + ], +) + +go_test( + name = "atomic_test", + srcs = [ + "memory_test.go", + "mocks_generate_test.go", + "shared_memory_test.go", + ], + embed = [":atomic"], + deps = [ + "//chains/atomic/atomictest", + "//database/memdb", + "//database/prefixdb", + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/chains/atomic/atomicmock/BUILD.bazel b/chains/atomic/atomicmock/BUILD.bazel new file mode 100644 index 000000000000..7723a898ffde --- /dev/null +++ b/chains/atomic/atomicmock/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "atomicmock", + srcs = ["shared_memory.go"], + importpath = "github.com/ava-labs/avalanchego/chains/atomic/atomicmock", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//database", + "//ids", + "@org_uber_go_mock//gomock", + ], +) diff --git a/chains/atomic/atomictest/BUILD.bazel b/chains/atomic/atomictest/BUILD.bazel new file mode 100644 index 000000000000..17a4f7704175 --- /dev/null +++ b/chains/atomic/atomictest/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "atomictest", + srcs = ["shared_memory.go"], + importpath = "github.com/ava-labs/avalanchego/chains/atomic/atomictest", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//database", + "//ids", + "//utils/units", + "@com_github_stretchr_testify//require", + ], +) diff --git a/chains/atomic/gsharedmemory/BUILD.bazel b/chains/atomic/gsharedmemory/BUILD.bazel new file mode 100644 index 000000000000..de5c2b14109b --- /dev/null +++ b/chains/atomic/gsharedmemory/BUILD.bazel @@ -0,0 +1,36 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "gsharedmemory", + srcs = [ + "filtered_batch.go", + "shared_memory_client.go", + "shared_memory_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/chains/atomic/gsharedmemory", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//database", + "//ids", + "//proto/pb/sharedmemory", + "//utils/set", + ], +) + +go_test( + name = "gsharedmemory_test", + srcs = ["shared_memory_test.go"], + embed = [":gsharedmemory"], + deps = [ + "//chains/atomic", + "//chains/atomic/atomictest", + "//database", + "//database/memdb", + "//database/prefixdb", + "//ids", + "//proto/pb/sharedmemory", + "//vms/rpcchainvm/grpcutils", + "@com_github_stretchr_testify//require", + ], +) diff --git a/codec/BUILD.bazel b/codec/BUILD.bazel new file mode 100644 index 000000000000..1b3f434a5782 --- /dev/null +++ b/codec/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "codec", + srcs = [ + "codec.go", + "general_codec.go", + "manager.go", + "registry.go", + ], + importpath = "github.com/ava-labs/avalanchego/codec", + visibility = ["//visibility:public"], + deps = [ + "//utils/units", + "//utils/wrappers", + ], +) + +go_test( + name = "codec_test", + srcs = ["mocks_generate_test.go"], + embed = [":codec"], +) diff --git a/codec/codecmock/BUILD.bazel b/codec/codecmock/BUILD.bazel new file mode 100644 index 000000000000..506ab501345a --- /dev/null +++ b/codec/codecmock/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "codecmock", + srcs = ["manager.go"], + importpath = "github.com/ava-labs/avalanchego/codec/codecmock", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "@org_uber_go_mock//gomock", + ], +) diff --git a/codec/codectest/BUILD.bazel b/codec/codectest/BUILD.bazel new file mode 100644 index 000000000000..cc9a57037513 --- /dev/null +++ b/codec/codectest/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "codectest", + srcs = ["codectest.go"], + importpath = "github.com/ava-labs/avalanchego/codec/codectest", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//utils/wrappers", + "@com_github_stretchr_testify//require", + ], +) diff --git a/codec/hierarchycodec/BUILD.bazel b/codec/hierarchycodec/BUILD.bazel new file mode 100644 index 000000000000..46b10cf6f928 --- /dev/null +++ b/codec/hierarchycodec/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "hierarchycodec", + srcs = ["codec.go"], + importpath = "github.com/ava-labs/avalanchego/codec/hierarchycodec", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/reflectcodec", + "//utils/bimap", + "//utils/wrappers", + ], +) + +go_test( + name = "hierarchycodec_test", + srcs = ["codec_test.go"], + embed = [":hierarchycodec"], + deps = [ + "//codec", + "//codec/codectest", + ], +) diff --git a/codec/linearcodec/BUILD.bazel b/codec/linearcodec/BUILD.bazel new file mode 100644 index 000000000000..fb0824419a32 --- /dev/null +++ b/codec/linearcodec/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "linearcodec", + srcs = ["codec.go"], + importpath = "github.com/ava-labs/avalanchego/codec/linearcodec", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/reflectcodec", + "//utils/bimap", + "//utils/wrappers", + ], +) + +go_test( + name = "linearcodec_test", + srcs = ["codec_test.go"], + embed = [":linearcodec"], + deps = [ + "//codec", + "//codec/codectest", + ], +) diff --git a/codec/reflectcodec/BUILD.bazel b/codec/reflectcodec/BUILD.bazel new file mode 100644 index 000000000000..3b306f85a9d9 --- /dev/null +++ b/codec/reflectcodec/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "reflectcodec", + srcs = [ + "struct_fielder.go", + "type_codec.go", + ], + importpath = "github.com/ava-labs/avalanchego/codec/reflectcodec", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//utils/set", + "//utils/wrappers", + ], +) diff --git a/combined.patch b/combined.patch new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/config/BUILD.bazel b/config/BUILD.bazel new file mode 100644 index 000000000000..f5d27a1c7a73 --- /dev/null +++ b/config/BUILD.bazel @@ -0,0 +1,71 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "config", + srcs = [ + "config.go", + "flags.go", + "keys.go", + "viper.go", + ], + importpath = "github.com/ava-labs/avalanchego/config", + visibility = ["//visibility:public"], + deps = [ + "//api/server", + "//chains", + "//config/node", + "//database/leveldb", + "//database/memdb", + "//database/pebbledb", + "//genesis", + "//ids", + "//network", + "//network/dialer", + "//network/throttling", + "//snow/consensus/snowball", + "//snow/networking/benchlist", + "//snow/networking/router", + "//snow/networking/tracker", + "//staking", + "//subnets", + "//trace", + "//upgrade", + "//utils/bag", + "//utils/compression", + "//utils/constants", + "//utils/dynamicip", + "//utils/ips", + "//utils/logging", + "//utils/perms", + "//utils/profiler", + "//utils/set", + "//utils/storage", + "//utils/timer", + "//utils/ulimit", + "//utils/units", + "//version", + "//vms/components/gas", + "//vms/platformvm/reward", + "//vms/platformvm/validators/fee", + "//vms/proposervm", + "@com_github_spf13_pflag//:pflag", + "@com_github_spf13_viper//:viper", + ], +) + +go_test( + name = "config_test", + srcs = ["config_test.go"], + embed = [":config"], + deps = [ + "//chains", + "//config/node", + "//ids", + "//snow/consensus/snowball", + "//subnets", + "//utils/constants", + "@com_github_spf13_pflag//:pflag", + "@com_github_spf13_viper//:viper", + "@com_github_stretchr_testify//require", + ], +) diff --git a/config/node/BUILD.bazel b/config/node/BUILD.bazel new file mode 100644 index 000000000000..c55dea2c6f1e --- /dev/null +++ b/config/node/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "node", + srcs = [ + "config.go", + "process_context.go", + ], + importpath = "github.com/ava-labs/avalanchego/config/node", + visibility = ["//visibility:public"], + deps = [ + "//api/server", + "//chains", + "//genesis", + "//ids", + "//network", + "//snow/networking/benchlist", + "//snow/networking/router", + "//snow/networking/tracker", + "//subnets", + "//trace", + "//upgrade", + "//utils/logging", + "//utils/profiler", + "//utils/set", + "//utils/timer", + ], +) + +go_test( + name = "node_test", + srcs = ["process_context_test.go"], + embed = [":node"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/connectproto/pb/proposervm/BUILD.bazel b/connectproto/pb/proposervm/BUILD.bazel new file mode 100644 index 000000000000..3f23dee42e0f --- /dev/null +++ b/connectproto/pb/proposervm/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "proposervm", + srcs = ["service.pb.go"], + importpath = "github.com/ava-labs/avalanchego/connectproto/pb/proposervm", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/connectproto/pb/proposervm/proposervmconnect/BUILD.bazel b/connectproto/pb/proposervm/proposervmconnect/BUILD.bazel new file mode 100644 index 000000000000..112d01214ca0 --- /dev/null +++ b/connectproto/pb/proposervm/proposervmconnect/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "proposervmconnect", + srcs = ["service.connect.go"], + importpath = "github.com/ava-labs/avalanchego/connectproto/pb/proposervm/proposervmconnect", + visibility = ["//visibility:public"], + deps = [ + "//connectproto/pb/proposervm", + "@com_connectrpc_connect//:connect", + ], +) diff --git a/connectproto/pb/xsvm/BUILD.bazel b/connectproto/pb/xsvm/BUILD.bazel new file mode 100644 index 000000000000..b2ad1276cd78 --- /dev/null +++ b/connectproto/pb/xsvm/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "xsvm", + srcs = ["service.pb.go"], + importpath = "github.com/ava-labs/avalanchego/connectproto/pb/xsvm", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/connectproto/pb/xsvm/xsvmconnect/BUILD.bazel b/connectproto/pb/xsvm/xsvmconnect/BUILD.bazel new file mode 100644 index 000000000000..bc9a7709b1c4 --- /dev/null +++ b/connectproto/pb/xsvm/xsvmconnect/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "xsvmconnect", + srcs = ["service.connect.go"], + importpath = "github.com/ava-labs/avalanchego/connectproto/pb/xsvm/xsvmconnect", + visibility = ["//visibility:public"], + deps = [ + "//connectproto/pb/xsvm", + "@com_connectrpc_connect//:connect", + ], +) diff --git a/connectproto/proposervm/BUILD.bazel b/connectproto/proposervm/BUILD.bazel new file mode 100644 index 000000000000..6271dc0e065d --- /dev/null +++ b/connectproto/proposervm/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "proposervm_proto", + srcs = ["service.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "proposervm_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/connectproto/pb/proposervm", + proto = ":proposervm_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "proposervm", + embed = [":proposervm_go_proto"], + importpath = "github.com/ava-labs/avalanchego/connectproto/pb/proposervm", + visibility = ["//visibility:public"], +) diff --git a/connectproto/xsvm/BUILD.bazel b/connectproto/xsvm/BUILD.bazel new file mode 100644 index 000000000000..16187ebb78cb --- /dev/null +++ b/connectproto/xsvm/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "xsvm_proto", + srcs = ["service.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "xsvm_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/connectproto/pb/xsvm", + proto = ":xsvm_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "xsvm", + embed = [":xsvm_go_proto"], + importpath = "github.com/ava-labs/avalanchego/connectproto/pb/xsvm", + visibility = ["//visibility:public"], +) diff --git a/database/BUILD.bazel b/database/BUILD.bazel new file mode 100644 index 000000000000..ac42bbf3c6de --- /dev/null +++ b/database/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "database", + srcs = [ + "batch.go", + "common.go", + "database.go", + "errors.go", + "helpers.go", + "iterator.go", + ], + importpath = "github.com/ava-labs/avalanchego/database", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//ids", + ], +) + +go_test( + name = "database_test", + srcs = [ + "helpers_test.go", + "mocks_generate_test.go", + ], + embed = [":database"], + deps = [ + "//database/memdb", + "//utils", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/corruptabledb/BUILD.bazel b/database/corruptabledb/BUILD.bazel new file mode 100644 index 000000000000..a26acf7ac6a3 --- /dev/null +++ b/database/corruptabledb/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "corruptabledb", + srcs = ["db.go"], + importpath = "github.com/ava-labs/avalanchego/database/corruptabledb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//utils/logging", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "corruptabledb_test", + srcs = ["db_test.go"], + embed = [":corruptabledb"], + deps = [ + "//database", + "//database/databasemock", + "//database/dbtest", + "//database/memdb", + "//utils/logging", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/database/databasemock/BUILD.bazel b/database/databasemock/BUILD.bazel new file mode 100644 index 000000000000..3ffa4953c6a1 --- /dev/null +++ b/database/databasemock/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "databasemock", + srcs = [ + "batch.go", + "iterator.go", + ], + importpath = "github.com/ava-labs/avalanchego/database/databasemock", + visibility = ["//visibility:public"], + deps = [ + "//database", + "@org_uber_go_mock//gomock", + ], +) diff --git a/database/dbtest/BUILD.bazel b/database/dbtest/BUILD.bazel new file mode 100644 index 000000000000..d0cfe496084d --- /dev/null +++ b/database/dbtest/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "dbtest", + srcs = [ + "benchmark.go", + "dbtest.go", + ], + importpath = "github.com/ava-labs/avalanchego/database/dbtest", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//database/databasemock", + "//utils", + "//utils/units", + "@com_github_stretchr_testify//require", + "@org_golang_x_exp//maps", + "@org_golang_x_sync//errgroup", + "@org_uber_go_mock//gomock", + ], +) diff --git a/database/factory/BUILD.bazel b/database/factory/BUILD.bazel new file mode 100644 index 000000000000..c8ace318ee42 --- /dev/null +++ b/database/factory/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "factory", + srcs = ["factory.go"], + importpath = "github.com/ava-labs/avalanchego/database/factory", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//database/corruptabledb", + "//database/leveldb", + "//database/memdb", + "//database/pebbledb", + "//database/versiondb", + "//utils/logging", + "@com_github_prometheus_client_golang//prometheus", + ], +) diff --git a/database/heightindexdb/dbtest/BUILD.bazel b/database/heightindexdb/dbtest/BUILD.bazel new file mode 100644 index 000000000000..09d88a4f69af --- /dev/null +++ b/database/heightindexdb/dbtest/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "dbtest", + srcs = ["dbtest.go"], + importpath = "github.com/ava-labs/avalanchego/database/heightindexdb/dbtest", + visibility = ["//visibility:public"], + deps = [ + "//database", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/heightindexdb/memdb/BUILD.bazel b/database/heightindexdb/memdb/BUILD.bazel new file mode 100644 index 000000000000..1677eb4f32b8 --- /dev/null +++ b/database/heightindexdb/memdb/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "memdb", + srcs = ["database.go"], + importpath = "github.com/ava-labs/avalanchego/database/heightindexdb/memdb", + visibility = ["//visibility:public"], + deps = ["//database"], +) + +go_test( + name = "memdb_test", + srcs = ["database_test.go"], + embed = [":memdb"], + deps = [ + "//database", + "//database/heightindexdb/dbtest", + ], +) diff --git a/database/heightindexdb/meterdb/BUILD.bazel b/database/heightindexdb/meterdb/BUILD.bazel new file mode 100644 index 000000000000..9a4b2367a407 --- /dev/null +++ b/database/heightindexdb/meterdb/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "meterdb", + srcs = ["db.go"], + importpath = "github.com/ava-labs/avalanchego/database/heightindexdb/meterdb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "meterdb_test", + srcs = ["db_test.go"], + embed = [":meterdb"], + deps = [ + "//database", + "//database/heightindexdb/memdb", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_model//go", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/leveldb/BUILD.bazel b/database/leveldb/BUILD.bazel new file mode 100644 index 000000000000..7932120bd8b8 --- /dev/null +++ b/database/leveldb/BUILD.bazel @@ -0,0 +1,37 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "leveldb", + srcs = [ + "db.go", + "metrics.go", + ], + importpath = "github.com/ava-labs/avalanchego/database/leveldb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//utils", + "//utils/logging", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_syndtr_goleveldb//leveldb", + "@com_github_syndtr_goleveldb//leveldb/errors", + "@com_github_syndtr_goleveldb//leveldb/filter", + "@com_github_syndtr_goleveldb//leveldb/iterator", + "@com_github_syndtr_goleveldb//leveldb/opt", + "@com_github_syndtr_goleveldb//leveldb/util", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "leveldb_test", + srcs = ["db_test.go"], + embed = [":leveldb"], + deps = [ + "//database", + "//database/dbtest", + "//utils/logging", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/linkeddb/BUILD.bazel b/database/linkeddb/BUILD.bazel new file mode 100644 index 000000000000..daf86e60cebd --- /dev/null +++ b/database/linkeddb/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "linkeddb", + srcs = [ + "codec.go", + "linkeddb.go", + ], + importpath = "github.com/ava-labs/avalanchego/database/linkeddb", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//codec", + "//codec/linearcodec", + "//database", + ], +) + +go_test( + name = "linkeddb_test", + srcs = [ + "db_test.go", + "linkeddb_test.go", + ], + embed = [":linkeddb"], + deps = [ + "//database", + "//database/dbtest", + "//database/memdb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/memdb/BUILD.bazel b/database/memdb/BUILD.bazel new file mode 100644 index 000000000000..1ebf77af7e74 --- /dev/null +++ b/database/memdb/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "memdb", + srcs = ["db.go"], + importpath = "github.com/ava-labs/avalanchego/database/memdb", + visibility = ["//visibility:public"], + deps = ["//database"], +) + +go_test( + name = "memdb_test", + srcs = ["db_test.go"], + embed = [":memdb"], + deps = ["//database/dbtest"], +) diff --git a/database/meterdb/BUILD.bazel b/database/meterdb/BUILD.bazel new file mode 100644 index 000000000000..83ae4cff922f --- /dev/null +++ b/database/meterdb/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "meterdb", + srcs = ["db.go"], + importpath = "github.com/ava-labs/avalanchego/database/meterdb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "meterdb_test", + srcs = ["db_test.go"], + embed = [":meterdb"], + deps = [ + "//database", + "//database/dbtest", + "//database/memdb", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/pebbledb/BUILD.bazel b/database/pebbledb/BUILD.bazel new file mode 100644 index 000000000000..198af7b77f9f --- /dev/null +++ b/database/pebbledb/BUILD.bazel @@ -0,0 +1,36 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "pebbledb", + srcs = [ + "batch.go", + "db.go", + "iterator.go", + ], + importpath = "github.com/ava-labs/avalanchego/database/pebbledb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//utils/logging", + "//utils/set", + "//utils/units", + "@com_github_cockroachdb_pebble//:pebble", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "pebbledb_test", + srcs = [ + "batch_test.go", + "db_test.go", + ], + embed = [":pebbledb"], + deps = [ + "//database/dbtest", + "//utils/logging", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/prefixdb/BUILD.bazel b/database/prefixdb/BUILD.bazel new file mode 100644 index 000000000000..8cdee5ee3f43 --- /dev/null +++ b/database/prefixdb/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "prefixdb", + srcs = ["db.go"], + importpath = "github.com/ava-labs/avalanchego/database/prefixdb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//utils", + "//utils/hashing", + ], +) + +go_test( + name = "prefixdb_test", + srcs = ["db_test.go"], + embed = [":prefixdb"], + deps = [ + "//database/dbtest", + "//database/memdb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/rpcdb/BUILD.bazel b/database/rpcdb/BUILD.bazel new file mode 100644 index 000000000000..8c781eaa7996 --- /dev/null +++ b/database/rpcdb/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "rpcdb", + srcs = [ + "db_client.go", + "db_server.go", + "errors.go", + ], + importpath = "github.com/ava-labs/avalanchego/database/rpcdb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//proto/pb/rpcdb", + "//utils", + "//utils/set", + "//utils/units", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) + +go_test( + name = "rpcdb_test", + srcs = ["db_test.go"], + embed = [":rpcdb"], + deps = [ + "//database/corruptabledb", + "//database/dbtest", + "//database/memdb", + "//proto/pb/rpcdb", + "//utils/logging", + "//vms/rpcchainvm/grpcutils", + "@com_github_stretchr_testify//require", + ], +) diff --git a/database/versiondb/BUILD.bazel b/database/versiondb/BUILD.bazel new file mode 100644 index 000000000000..1a0a7d952785 --- /dev/null +++ b/database/versiondb/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "versiondb", + srcs = ["db.go"], + importpath = "github.com/ava-labs/avalanchego/database/versiondb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//database/memdb", + ], +) + +go_test( + name = "versiondb_test", + srcs = ["db_test.go"], + embed = [":versiondb"], + deps = [ + "//database", + "//database/dbtest", + "//database/memdb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/firewood/.cargo/config.toml b/firewood/.cargo/config.toml new file mode 100644 index 000000000000..cc8300c56f92 --- /dev/null +++ b/firewood/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +build-static-ffi = "build --frozen --profile maxperf --package firewood-ffi --features ethhash,logger" diff --git a/firewood/.gitattributes b/firewood/.gitattributes new file mode 100644 index 000000000000..e43ce2d10eaa --- /dev/null +++ b/firewood/.gitattributes @@ -0,0 +1,2 @@ +# Hint that ffi/firewood.h is a generated file for GitHub Linguist +ffi/firewood.h linguist-generated=true diff --git a/firewood/.github/.gitignore b/firewood/.github/.gitignore new file mode 100644 index 000000000000..2815f8fa3fdf --- /dev/null +++ b/firewood/.github/.gitignore @@ -0,0 +1,3 @@ +.golangci.yaml +.golangci.yaml.orig +.golangci.yaml.rej diff --git a/firewood/.github/.golangci.yaml.patch b/firewood/.github/.golangci.yaml.patch new file mode 100644 index 000000000000..f90b1b764702 --- /dev/null +++ b/firewood/.github/.golangci.yaml.patch @@ -0,0 +1,68 @@ +--- .github/.golangci.yaml 2025-11-26 17:52:36.814736814 +0000 ++++ ffi/.golangci.yaml 2025-11-26 17:52:31.624079933 +0000 +@@ -40,7 +40,7 @@ + - standard + - default + - blank +- - prefix(github.com/ava-labs/avalanchego) ++ - prefix(github.com/ava-labs/firewood/ffi) + - alias + - dot + custom-order: true +@@ -93,8 +93,6 @@ + rules: + packages: + deny: +- - pkg: container/list +- desc: github.com/ava-labs/avalanchego/utils/linked should be used instead. + - pkg: github.com/golang/mock/gomock + desc: go.uber.org/mock/gomock should be used instead. + - pkg: github.com/stretchr/testify/assert +@@ -109,29 +107,10 @@ + forbidigo: + # Forbid the following identifiers (list of regexp). + forbid: +- - pattern: require\.Error$(# ErrorIs should be used instead)? +- - pattern: require\.ErrorContains$(# ErrorIs should be used instead)? +- - pattern: require\.EqualValues$(# Equal should be used instead)? +- - pattern: require\.NotEqualValues$(# NotEqual should be used instead)? + - pattern: ^(t|b|tb|f)\.(Fatal|Fatalf|Error|Errorf)$(# the require library should be used instead)? + - pattern: ^sort\.(Slice|Strings)$(# the slices package should be used instead)? + # Exclude godoc examples from forbidigo checks. + exclude-godoc-examples: false +- gosec: +- excludes: +- - G107 # Url provided to HTTP request as taint input https://securego.io/docs/rules/g107 +- - G115 # TODO(marun) Enable this ruleset in a follow-up PR +- importas: +- # Do not allow unaliased imports of aliased packages. +- no-unaliased: false +- # Do not allow non-required aliases. +- no-extra-aliases: false +- # List of aliases +- alias: +- - pkg: github.com/ava-labs/avalanchego/utils/math +- alias: safemath +- - pkg: github.com/ava-labs/avalanchego/utils/json +- alias: avajson + revive: + rules: + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bool-literal-in-expr +@@ -195,17 +174,6 @@ + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break + - name: useless-break + disabled: false +- spancheck: +- # https://github.com/jjti/go-spancheck#checks +- checks: +- - end +- staticcheck: +- # https://staticcheck.io/docs/options#checks +- checks: +- - all +- - -SA6002A # Storing non-pointer values in sync.Pool allocates memory +- - -SA1019 # Using a deprecated function, variable, constant or field +- - -QF1008 # Unnecessary embedded expressions + tagalign: + align: true + sort: true diff --git a/firewood/.github/check-license-headers.yaml b/firewood/.github/check-license-headers.yaml new file mode 100644 index 000000000000..3452bdf4c4f8 --- /dev/null +++ b/firewood/.github/check-license-headers.yaml @@ -0,0 +1,64 @@ +[ + { + "include": [ + "**/**/*.rs", + "**/**/*.go", + "**/**/*.h", + ], + "exclude": [ + "target/**", + "*/LICENSE*", + "LICENSE.md", + "RELEASE.md", + "grpc-testtool/**", + "README*", + "**/README*", + "METRICS.md", + "Cargo.toml", + "Cargo.lock", + "*/Cargo.toml", + "docs/**", + "CODEOWNERS", + "CONTRIBUTING.md", + "benchmark/**", + "triehash/**", + "CHANGELOG.md", + "cliff.toml", + "clippy.toml", + "**/tests/compile_*/**", + "**/go.mod", + "**/go.mod", + "**/cbindgen.toml", + ], + "license": "./.github/license-header.txt" + }, + { + "include": [ + "target/**", + "*/LICENSE*", + "LICENSE.md", + "RELEASE.md", + "grpc-testtool/**", + "README*", + "**/README*", + "METRICS.md", + "Cargo.toml", + "Cargo.lock", + "*/Cargo.toml", + "docs/**", + "benchmark/**", + "ffi/**", + "CODEOWNERS", + "CONTRIBUTING.md", + "triehash/**", + "CHANGELOG.md", + "AGENTS.md", + "CLAUDE.md", + "cliff.toml", + "clippy.toml", + "**/tests/compile_*/**", + "justfile", + "scripts/run-just.sh", + ], + } +] diff --git a/firewood/.github/dependabot.yml b/firewood/.github/dependabot.yml new file mode 100644 index 000000000000..0f613b81fe35 --- /dev/null +++ b/firewood/.github/dependabot.yml @@ -0,0 +1,19 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" + time: "05:00" + timezone: "America/Los_Angeles" + open-pull-requests-limit: 0 # Disable non-security version updates + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 0 # Disable non-security version updates diff --git a/firewood/.github/license-header.txt b/firewood/.github/license-header.txt new file mode 100644 index 000000000000..bb72d440a583 --- /dev/null +++ b/firewood/.github/license-header.txt @@ -0,0 +1,2 @@ +// Copyright (C) %year%, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. diff --git a/firewood/.github/scripts/verify_golangci_yaml_changes.sh b/firewood/.github/scripts/verify_golangci_yaml_changes.sh new file mode 100755 index 000000000000..9773f61039b1 --- /dev/null +++ b/firewood/.github/scripts/verify_golangci_yaml_changes.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# ==== Generating Expected Diff ==== +# 1. Review the changes from AvalancheGo and apply them if necessary to our local file. +# https://github.com/ava-labs/avalanchego/commits/master/.golangci.yml +# 2. Update the diff file by running: +# .github/scripts/verify_golangci_yaml_changes.sh update + +declare -r golangci_yaml="ffi/.golangci.yaml" +declare -r upstream_yaml=".github/.golangci.yaml" +declare -r expected_patch=".github/.golangci.yaml.patch" +declare -r upstream_url="https://raw.githubusercontent.com/ava-labs/avalanchego/refs/heads/master/.golangci.yml" +declare -r history_url="https://github.com/ava-labs/avalanchego/commits/master/.golangci.yml" + +function @die() { + local -r code="$1" + local -r message="$2" + + echo "Error: $message" >&2 + exit "$code" +} + +function @usage() { + cat <"$dest" 2>/dev/null; then + @die 3 "'$golangci_yaml' has no differences '$upstream_yaml'; this is unexpected! At least package name must be different." + fi +} + +function @apply-patch-to-upstream() { + if ! patch -t "$upstream_yaml" "$expected_patch"; then + @die 4 "Failed to apply the patch from $expected_patch. Please review the changes manually." + fi +} + +function @apply() { + local backup + backup=$(mktemp) + trap 'rm -f "$backup"' EXIT + + # make a copy of the upstream yaml before applying the patch so we can refresh the patch file later + cp -f "$upstream_yaml" "$backup" + @apply-patch-to-upstream + + # We cleanly applied the patch, so we can now replace the local file with the patched version + cp -f "$upstream_yaml" "$golangci_yaml" + cp -f "$backup" "$upstream_yaml" + echo "Successfully applied the patch from $expected_patch to $golangci_yaml" + + # refresh the patch so `check` apply later can use it + @update +} + +function @check() { + @apply-patch-to-upstream + + local patch + patch=$(mktemp) + trap 'rm -f "$patch"' EXIT + + if diff -Nau "$upstream_yaml" "$golangci_yaml" >"$patch" 2>&1; then + echo "'$golangci_yaml' is up to date with AvalancheGo's .golangci.yaml." + exit 0 + fi + + { + echo "'$golangci_yaml' has unexpected changes from AvalancheGo." + echo "View the upstream changes at: $history_url and apply them if necessary." + echo "" + echo "Current changes:" + cat "$patch" + } >&2 + + exit 5 +} + +function @update() { + @generate-patch "$expected_patch" + echo "Updated expected changes in $expected_patch" + exit 0 +} + +case "${1:-check}" in +apply | check | update) + # make sure we are in the root of the repository + cd "$(git rev-parse --show-toplevel)" + + @download-upstream + + case "${1:-check}" in + apply) @apply ;; + check) @check ;; + update) @update ;; + esac + + ;; +*) @usage ;; +esac diff --git a/firewood/.github/workflows/attach-static-libs.yaml b/firewood/.github/workflows/attach-static-libs.yaml new file mode 100644 index 000000000000..d216daadcc73 --- /dev/null +++ b/firewood/.github/workflows/attach-static-libs.yaml @@ -0,0 +1,226 @@ +name: attach-static-libs + +on: + workflow_dispatch: + inputs: + create_branch_name: + description: "Name of the new branch to create and attach static libs" + required: true + push: + tags: + - "*" + branches: + - "main" + pull_request: + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: full + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +# Build, upload, and collect static libraries for each target architecture, +# so that golang projects can import the FFI package without needing to +# recompile Firewood locally. +# Supported architectures are: +# - x86_64-unknown-linux-gnu +# - aarch64-unknown-linux-gnu +# - x86_64-apple-darwin +# - aarch64-apple-darwin +jobs: + # Build the static libraries for each target architecture and upload + # them as artifacts to collect and attach in the next job. + build-firewood-ffi-libs: + runs-on: ${{ matrix.os }} + strategy: + matrix: + include: + - os: ubuntu-latest + target: x86_64-unknown-linux-gnu + - os: ubuntu-22.04-arm + target: aarch64-unknown-linux-gnu + - os: macos-latest + target: aarch64-apple-darwin + pre-build-cmd: echo "MACOSX_DEPLOYMENT_TARGET=15.0" >> "$GITHUB_ENV" + - os: macos-latest + target: x86_64-apple-darwin + pre-build-cmd: echo "MACOSX_DEPLOYMENT_TARGET=15.0" >> "$GITHUB_ENV" + outputs: + has_secrets: ${{ steps.check_secrets.outputs.has_secrets }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + shared-key: ${{ matrix.target }} + + - name: Add target for cross-compilation + run: rustup target add ${{ matrix.target }} + + - name: Run pre-build command + if: matrix.pre-build-cmd != '' + run: ${{ matrix.pre-build-cmd }} + + # Require Cargo.lock to be up to date and ensure the registry cache is populated + - name: Cargo Fetch (run `cargo generate-lockfile` if this fails) + run: cargo fetch --locked --verbose + + - name: Build for ${{ matrix.target }} + run: cargo build-static-ffi --target ${{ matrix.target }} + + - name: Upload binary + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.target }} + path: target/${{ matrix.target }}/maxperf/libfirewood_ffi.a + if-no-files-found: error + + - name: Check if FIREWOOD_GO_GITHUB_TOKEN is set + id: check_secrets + run: | + if [ -z "${{ secrets.FIREWOOD_GO_GITHUB_TOKEN }}" ]; then + echo "FIREWOOD_GO_GITHUB_TOKEN is not set" + echo "has_secrets=false" >> "$GITHUB_OUTPUT" + else + echo "FIREWOOD_GO_GITHUB_TOKEN is set" + echo "has_secrets=true" >> "$GITHUB_OUTPUT" + fi + + # Collect all the static libraries built on the previous matrix of jobs + # and add them into ffi/libs directory. + # We commit and push this as a new branch with "--force" to overwrite + # the previous static libs that will not be on our branch. + push-firewood-ffi-libs: + needs: build-firewood-ffi-libs + if: needs.build-firewood-ffi-libs.outputs.has_secrets == 'true' + runs-on: ubuntu-latest + outputs: + target_branch: ${{ steps.determine_branch.outputs.target_branch }} + steps: + - name: Determine branch name + id: determine_branch + run: | + if [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ github.event.inputs.create_branch_name }}" ]]; then + export target_branch="${{ github.event.inputs.create_branch_name }}" + echo "Using workflow input as target branch: $target_branch" + echo "target_branch=$target_branch" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_type }}" == "tag" ]]; then + export target_branch="${GITHUB_REF#refs/tags/}" + echo "Using tag name as target_branch: $target_branch" + echo "target_branch=$target_branch" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == "main" ]]; then + export target_branch="main-ci" # Avoid pushing to main branch of firewood-go-ethhash repo + echo "Using main-ci as target branch for push to main: $target_branch" + echo "target_branch=$target_branch" >> "$GITHUB_OUTPUT" + elif [[ "${{ github.event_name }}" == "pull_request" ]]; then + export target_branch="${{ github.event.pull_request.head.ref }}" + echo "Using PR head name as target branch: $target_branch" + echo "target_branch=$target_branch" >> "$GITHUB_OUTPUT" + else + echo "No valid input or tag found." + exit 1 + fi + + - uses: actions/checkout@v4 + with: + path: firewood + + - uses: actions/checkout@v4 + with: + repository: ava-labs/firewood-go-ethhash + token: ${{ secrets.FIREWOOD_GO_GITHUB_TOKEN }} + path: firewood-go-ethhash + + - name: Copy FFI Source Code + run: cp -r firewood/ffi firewood-go-ethhash + + - name: Switch to Static Libs CGO Mode + working-directory: firewood-go-ethhash/ffi + run: FIREWOOD_LD_MODE=STATIC_LIBS go generate + + - name: Download binaries into libs directory + uses: actions/download-artifact@v4 + with: + path: firewood-go-ethhash/ffi/libs + + - name: List downloaded target directory + run: find firewood-go-ethhash -type f | sort + + - name: Push static libs to branch + working-directory: firewood-go-ethhash + # GITHUB_TOKEN is configured in the last actions/checkout step + # to have read/write permissions to the firewood-go-ethhash repo. + run: | + git config --global user.name "FirewoodCI" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git checkout -b ${{ steps.determine_branch.outputs.target_branch }} + echo "Updating ffi module path before pushing to alternative remote" + pushd ffi + go mod edit -module github.com/ava-labs/firewood-go-ethhash/ffi + popd + git add . + git commit -m "firewood ci ${{ github.sha }}: attach firewood static libs" + git push -u origin ${{ steps.determine_branch.outputs.target_branch }} --force + + if [[ "${{ github.ref_type }}" == "tag" ]]; then + # If the tag is a semantic version, prefix it with "ffi/" to ensure go get correctly + # fetches the submodule. Otherwise, use the tag name as is. + # Note: we explicitly ignore semantic versions with suffixes ie. v1.1.1-beta because + # go get treats them as non-semantic version tags. + # Ref: https://github.com/ava-labs/firewood/pull/991 + if [[ "${{ github.ref_name }}" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + tag_name="ffi/${GITHUB_REF#refs/tags/}" + else + tag_name="${GITHUB_REF#refs/tags/}" + fi + git tag -a "$tag_name" -m "firewood ci ${{ github.sha }}: attach firewood static libs" + git push origin "refs/tags/$tag_name" + fi + + # Check out the branch created in the previous job on a matrix of + # our target architectures and test the FFI package on a fresh + # machine without re-compiling Firewood locally. + # This tests that the Firewood FFI package passes tests on the target + # architecture when it is forced to depend on the attached static libs. + test-firewood-ffi-libs: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, ubuntu-22.04-arm, macos-latest] + needs: push-firewood-ffi-libs + continue-on-error: true + steps: + - uses: actions/checkout@v4 + with: + repository: ava-labs/firewood-go-ethhash + token: ${{ secrets.FIREWOOD_GO_GITHUB_TOKEN }} + ref: ${{ needs.push-firewood-ffi-libs.outputs.target_branch }} + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: "ffi/go.mod" + cache-dependency-path: "ffi/go.sum" + - name: Test Go FFI bindings + working-directory: ffi + # cgocheck2 is expensive but provides complete pointer checks + run: GOEXPERIMENT=cgocheck2 TEST_FIREWOOD_HASH_MODE=ethhash go test ./... + + remove-if-pr-only: + runs-on: ubuntu-latest + needs: [push-firewood-ffi-libs, test-firewood-ffi-libs] + if: needs.push-firewood-ffi-libs.result == 'success' && github.event_name == 'pull_request' + permissions: + # Give the GITHUB_TOKEN write permission to delete the + # branch created by the previous job if it is a pull request. + contents: write + steps: + - uses: actions/checkout@v4 + with: + repository: ava-labs/firewood-go-ethhash + token: ${{ secrets.FIREWOOD_GO_GITHUB_TOKEN }} + ref: ${{ needs.push-firewood-ffi-libs.outputs.target_branch }} + - name: Delete branch + run: | + git push origin --delete ${{ needs.push-firewood-ffi-libs.outputs.target_branch }} diff --git a/firewood/.github/workflows/cache-cleanup.yaml b/firewood/.github/workflows/cache-cleanup.yaml new file mode 100644 index 000000000000..43461d14dfdc --- /dev/null +++ b/firewood/.github/workflows/cache-cleanup.yaml @@ -0,0 +1,34 @@ +name: cleanup caches by a branch +on: + pull_request: + types: + - closed + +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Cleanup + run: | + gh extension install actions/gh-actions-cache + + REPO=${{ github.repository }} + BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge" + + echo "Fetching list of cache key" + cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 ) + + ## Setting this to not fail the workflow while deleting cache keys. + set +e + echo "Deleting caches..." + for cacheKey in $cacheKeysForPR + do + gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm + done + echo "Done" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/firewood/.github/workflows/ci.yaml b/firewood/.github/workflows/ci.yaml new file mode 100644 index 000000000000..3274a7a81f49 --- /dev/null +++ b/firewood/.github/workflows/ci.yaml @@ -0,0 +1,334 @@ +name: ci + +on: + pull_request: + push: + branches: [main] + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: full + +jobs: + build: + # To optimize cargo performance and caching throughout the CI pipeline, we use Swatinem/rust-cache + # and set up an initial build job that writes the cache for a matrix of joint build profiles and + # feature sets. + # Future jobs specify the job they "need" (block to ensure the cache has been populated), the shared-key + # to read the cache and can set save-if: "false" to skip an expensive and unnecessary cache write. + # + # GitHub Actions does not provide easy support to define and re-use a matrix across multiple jobs + # and later jobs may also want to execute with only a subset of this matrix. Therefore, we define + # the matrix here and later jobs must re-specify the full matrix, a subset, or declare a single + # shared-key to read the cache. + strategy: + # do not cancel concurrent jobs if one fails for exhaustive failure reasons + fail-fast: false + matrix: + include: + - profile-key: debug-no-default-features + profile-args: "--no-default-features" + - profile-key: debug-no-features + profile-args: "" + - profile-key: debug-no-features + profile-args: "" + os: macos-latest + - profile-key: debug-ethhash-logger + profile-args: "--features ethhash,logger" + - profile-key: maxperf-ethhash-logger + profile-args: "--profile maxperf --features ethhash,logger" + runs-on: ${{ matrix.os || 'ubuntu-latest' }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + with: + shared-key: ${{ matrix.profile-key }} + cache-all-crates: true + cache-workspace-crates: true + # Require Cargo.lock to be up to date and ensure the registry cache is populated + - name: Cargo Fetch (run `cargo generate-lockfile` if this fails) + run: cargo fetch --locked --verbose + - name: Check + run: cargo check --frozen ${{ matrix.profile-args }} --workspace --all-targets + - name: Build + run: cargo build --frozen ${{ matrix.profile-args }} --workspace --all-targets + + no-rust-cache-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: rustfmt + - name: Check license headers + uses: viperproject/check-license-header@v2 + with: + path: . + config: .github/check-license-headers.yaml + strict: true + - name: Format + run: cargo fmt -- --check + + rust-lint-pr-comments: + # caveat emptor: actions-rs/clippy-check can only write comments on pull requests + # not originating from a fork. + if: github.event_name == 'pull_request' && github.repository == github.event.pull_request.head.repo.full_name + needs: build + strategy: + matrix: + include: + - profile-key: debug-no-default-features + profile-args: "--no-default-features" + - profile-key: debug-no-features + profile-args: "" + - profile-key: debug-no-features + profile-args: "" + os: macos-latest + - profile-key: debug-ethhash-logger + profile-args: "--features ethhash,logger" + runs-on: ${{ matrix.os || 'ubuntu-latest' }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: ${{ matrix.profile-key }} + - uses: actions-rs/clippy-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + name: ${{ matrix.profile-key }} + args: --locked ${{ matrix.profile-args }} --workspace --all-targets + + rust-lint: + needs: build + strategy: + # do not cancel concurrent jobs if one fails for exhaustive failure reasons + fail-fast: false + matrix: + include: + - profile-key: debug-no-default-features + profile-args: "--no-default-features" + - profile-key: debug-no-features + profile-args: "" + - profile-key: debug-no-features + profile-args: "" + os: macos-latest + - profile-key: debug-ethhash-logger + profile-args: "--features ethhash,logger" + runs-on: ${{ matrix.os || 'ubuntu-latest' }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: ${{ matrix.profile-key }} + - name: Clippy + run: cargo clippy --locked ${{ matrix.profile-args }} --workspace --all-targets -- -D warnings + + test: + needs: build + strategy: + # do not cancel concurrent jobs if one fails for exhaustive failure reasons + fail-fast: false + matrix: + include: + - profile-key: debug-no-default-features + profile-args: "--no-default-features" + - profile-key: debug-no-features + profile-args: "" + - profile-key: debug-no-features + profile-args: "" + os: macos-latest + - profile-key: debug-ethhash-logger + profile-args: "--features ethhash,logger" + - profile-key: maxperf-ethhash-logger + profile-args: "--profile maxperf --features ethhash,logger" + runs-on: ${{ matrix.os || 'ubuntu-latest' }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: ${{ matrix.profile-key }} + - name: Run tests with features enabled + run: cargo test --locked --verbose ${{ matrix.profile-args }} + + examples: + needs: build + strategy: + matrix: + include: + - profile-key: debug-no-default-features + profile-args: "--no-default-features" + - profile-key: debug-no-features + profile-args: "" + - profile-key: debug-no-features + profile-args: "" + os: macos-latest + - profile-key: debug-ethhash-logger + profile-args: "--features ethhash,logger" + - profile-key: maxperf-ethhash-logger + profile-args: "--profile maxperf --features ethhash,logger" + runs-on: ${{ matrix.os || 'ubuntu-latest' }} + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: ${{ matrix.profile-key }} + - name: Run benchmark example + run: cargo run --locked ${{ matrix.profile-args }} --bin benchmark -- --number-of-batches 100 --batch-size 1000 create + - name: Run insert example + run: cargo run --locked ${{ matrix.profile-args }} --example insert + + docs: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: "debug-no-features" + - name: md check + uses: DavidAnson/markdownlint-cli2-action@v20 + with: + globs: | + *.md + **/*.md + !CHANGELOG.md + !target/** + - name: doc generation + run: RUSTDOCFLAGS="-D warnings" cargo doc --locked --document-private-items --no-deps + + ffi: + needs: build + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: "debug-no-features" + - name: Build Firewood FFI + working-directory: ffi + run: cargo build --locked --release + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: "ffi/go.mod" + cache-dependency-path: "ffi/go.sum" + - name: Run golangci-lint + uses: golangci/golangci-lint-action@v7.0.1 + with: + version: latest + working-directory: ffi + - name: Test Go FFI bindings + working-directory: ffi + # cgocheck2 is expensive but provides complete pointer checks + run: GOEXPERIMENT=cgocheck2 TEST_FIREWOOD_HASH_MODE=firewood go test -race ./... + + firewood-ethhash-differential-fuzz: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: "debug-ethhash-logger" + - name: Build Firewood FFI (with ethhash) + run: cargo build --features ethhash,logger + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: "ffi/tests/eth/go.mod" + cache-dependency-path: "ffi/tests/eth/go.sum" + - name: Test Go FFI bindings + working-directory: ffi + # cgocheck2 is expensive but provides complete pointer checks + run: GOEXPERIMENT=cgocheck2 TEST_FIREWOOD_HASH_MODE=ethhash go test -race ./... + - name: Test Firewood <> Ethereum Differential Fuzz + working-directory: ffi/tests/eth + run: | + # Set memlock to unlimited for the shell invoking the fuzz tests + ulimit -Sa + ulimit -Ha + sudo prlimit --pid $$ --memlock=-1:-1 || echo "prlimit not available, locking kernel memory may fail when setting up io-uring" + ulimit -Sa + ulimit -Ha + go test -fuzz=. -fuzztime=1m + - name: Upload Fuzz testdata + if: failure() + uses: actions/upload-artifact@v4 + with: + name: ethhash-differential-fuzz-testdata + path: ffi/tests/eth/testdata + retention-days: 30 + + firewood-merkle-differential-fuzz: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: "debug-no-features" + - name: Build Firewood FFI + run: cargo build -p firewood-ffi + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: "ffi/tests/firewood/go.mod" + cache-dependency-path: "ffi/tests/firewood/go.sum" + - name: Test Firewood <> MerkleDB Differential fuzz + working-directory: ffi/tests/firewood + run: | + # Set memlock to unlimited for the shell invoking the fuzz tests + ulimit -Sa + ulimit -Ha + sudo prlimit --pid $$ --memlock=-1:-1 || echo "prlimit not available, locking kernel memory may fail when setting up io-uring" + ulimit -Sa + ulimit -Ha + go test -fuzz=. -fuzztime=1m + - name: Upload Fuzz testdata + if: failure() + uses: actions/upload-artifact@v4 + with: + name: firewood-merkle-differential-fuzz-testdata + path: ffi/tests/firewood/testdata + retention-days: 30 + + stale-deps: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: "debug-no-features" + - name: Install cargo-machete + run: cargo install cargo-machete + - name: Check for stale dependencies + run: cargo machete --with-metadata diff --git a/firewood/.github/workflows/default-branch-cache.yaml b/firewood/.github/workflows/default-branch-cache.yaml new file mode 100644 index 000000000000..c41b43dc3d7a --- /dev/null +++ b/firewood/.github/workflows/default-branch-cache.yaml @@ -0,0 +1,29 @@ +# because apparently caches are isolated across branches +name: default-branch-cache + +on: + workflow_dispatch: + push: + branches: + - main + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy,rustfmt + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + shared-key: "debug-no-features" + - name: Check + run: cargo check --workspace --all-targets + - name: Build + run: cargo build --workspace --all-targets diff --git a/firewood/.github/workflows/expected-golangci-yaml-diff.yaml b/firewood/.github/workflows/expected-golangci-yaml-diff.yaml new file mode 100644 index 000000000000..3eab5f9f436a --- /dev/null +++ b/firewood/.github/workflows/expected-golangci-yaml-diff.yaml @@ -0,0 +1,26 @@ +name: expected golangci.yaml diff + +on: + pull_request: + paths: + - .github/scripts/verify_golangci_yaml_changes.sh + - .github/workflows/expected-golangci-yaml-diff.yaml + - .github/.golangci.yaml.patch + - ffi/.golangci.yaml + # if updating the general CI workflow, go ahead and update the golangci.yaml + - .github/workflows/ci.yaml + # for good measure, if someone is editing the go.mod or go.sum files then + # they should make sure the golangci.yaml is up to date + - ffi/go.mod + - ffi/go.sum + push: + branches: + - "main" + +jobs: + expected-golangci-yaml-diff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Validate expected golangci-lint changes + run: .github/scripts/verify_golangci_yaml_changes.sh diff --git a/firewood/.github/workflows/ffi-nix.yaml b/firewood/.github/workflows/ffi-nix.yaml new file mode 100644 index 000000000000..c0962eacd614 --- /dev/null +++ b/firewood/.github/workflows/ffi-nix.yaml @@ -0,0 +1,18 @@ +name: ffi-nix + +on: + push: + branches: [main] + +jobs: + ffi-nix: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: DeterminateSystems/nix-installer-action@786fff0690178f1234e4e1fe9b536e94f5433196 #v20 + - uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 #v13 + - name: Check that FFI flake is up-to-date + run: ./scripts/run-just.sh check-ffi-flake + - name: Test nix build of Golang FFI bindings + run: ./scripts/run-just.sh test-ffi-nix + diff --git a/firewood/.github/workflows/gh-pages.yaml b/firewood/.github/workflows/gh-pages.yaml new file mode 100644 index 000000000000..b767da48d177 --- /dev/null +++ b/firewood/.github/workflows/gh-pages.yaml @@ -0,0 +1,63 @@ +name: gh-pages + +on: + push: + branches: + - "main" + - "rkuris/gh-pages" + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + # caution: this is the same restore as in ci.yaml + - uses: Swatinem/rust-cache@v2 + with: + save-if: "false" + - name: Build + run: cargo doc --document-private-items --no-deps + - name: Set up _site redirect to firewood + run: | + rm -fr _site + mkdir _site + echo "" > _site/index.html + - name: Copy doc files to _site + run: | + cp -rv target/doc/* ./_site + cp -rv docs/assets ./_site + - uses: actions/upload-artifact@v4 + with: + name: pages + path: _site + if-no-files-found: error + overwrite: true + include-hidden-files: true + deploy: + needs: build + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Download pages artifact + uses: actions/download-artifact@v4 + with: + name: pages + path: . + - name: Setup Pages + uses: actions/configure-pages@v3 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: . + - name: Deploy to GitHub pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/firewood/.github/workflows/label-pull-requests.yaml b/firewood/.github/workflows/label-pull-requests.yaml new file mode 100644 index 000000000000..900fa9f280e9 --- /dev/null +++ b/firewood/.github/workflows/label-pull-requests.yaml @@ -0,0 +1,52 @@ +name: Label pull requests + +on: pull_request_target + +jobs: + add_label: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: Check if pull request is from a fork + id: check_is_form + run: | + if [[ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]]; then + echo "is_fork=true" >> "$GITHUB_OUTPUT" + else + echo "is_fork=false" >> "$GITHUB_OUTPUT" + fi + + - name: Add label to third-party pull request + uses: actions/github-script@v7 + with: + script: | + const label = '3rd party contributor'; + const isFork = ${{ steps.check_is_form.outputs.is_fork }}; + const { data: issue } = await github.rest.issues.get({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + const isLabeled = issue.labels.some(l => l.name === label); + // add the label if a fork (and not already labeled), + // remove if not a fork and is labeled + if (isFork && !isLabeled) { + console.log(`Adding label: ${label}`); + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + labels: [label], + }); + } else if (!isFork && isLabeled) { + console.log(`Removing label: ${label}`); + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + name: label, + }); + } + console.log(`Label ${isFork ? 'added' : 'removed'}: ${label}`); diff --git a/firewood/.github/workflows/metrics-check.yaml b/firewood/.github/workflows/metrics-check.yaml new file mode 100644 index 000000000000..9f997bc0ff6a --- /dev/null +++ b/firewood/.github/workflows/metrics-check.yaml @@ -0,0 +1,86 @@ +name: Metrics Change Check + +on: + pull_request: + types: [opened, synchronize, reopened] + +concurrency: + group: metrics-check-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + check-metrics-changes: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Fetch full history to compare changes + + - name: Check for metric-related changes + id: check-metrics + run: | + # Get the base commit for comparison + if [ "${{ github.event_name }}" = "pull_request" ]; then + BASE_COMMIT="${{ github.event.pull_request.base.sha }}" + else + BASE_COMMIT="${{ github.event.before }}" + fi + + # Check if Grafana dashboard was modified - exit early if so + if git diff --name-only $BASE_COMMIT..HEAD | grep -q "benchmark/Grafana-dashboard.json"; then + echo "benchmark/Grafana-dashboard.json was modified - skipping metrics check" + exit 0 + fi + + # Regex pattern to match metric-related code changes + METRIC_REGEX_PATTERN="(counter!|gauge!|histogram!|#\\[metrics\\])" # ci trigger + + # Check for metric-related changes + METRIC_CHANGES=$(git diff $BASE_COMMIT..HEAD --unified=0 | grep -E "$METRIC_REGEX_PATTERN" || true) + + if [ -n "$METRIC_CHANGES" ]; then + echo "⚠️ WARNING: Found metric-related changes, but no dashboard modification:" + echo "$METRIC_CHANGES" + else + echo "✅ No metric-related changes found" + fi + + # Set output variables for the comment step + echo "metric_changes_found=$([ -n "$METRIC_CHANGES" ] && echo "true" || echo "false")" >> $GITHUB_OUTPUT + echo "metric_changes<> $GITHUB_OUTPUT + echo "$METRIC_CHANGES" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Look for previous comment + if: github.repository == github.event.pull_request.head.repo.full_name && steps.check-metrics.outputs.metric_changes_found == 'true' + id: find-comment + uses: peter-evans/find-comment@v3 + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: github-actions[bot] + body-includes: "## Metrics Change Detection ⚠️" + + - name: Comment on PR (if applicable) + if: github.repository == github.event.pull_request.head.repo.full_name && steps.check-metrics.outputs.metric_changes_found == 'true' + uses: peter-evans/create-or-update-comment@v4 + with: + issue-number: ${{ github.event.pull_request.number }} + body: | + ## Metrics Change Detection ⚠️ + + This PR contains changes related to metrics: + + ``` + ${{ steps.check-metrics.outputs.metric_changes }} + ``` + + However, the dashboard was not modified. + + You may need to update `benchmark/Grafana-dashboard.json` accordingly. + + --- + + *This check is automated to help maintain the dashboard.* + edit-mode: replace + comment-id: ${{ steps.find-comment.outputs.comment-id }} diff --git a/firewood/.github/workflows/pr-title.yaml b/firewood/.github/workflows/pr-title.yaml new file mode 100644 index 000000000000..9191a61fce2b --- /dev/null +++ b/firewood/.github/workflows/pr-title.yaml @@ -0,0 +1,46 @@ +# Check that the PR title matches the conventional commit format +name: pr-title + +permissions: + pull-requests: write + +on: + pull_request: + types: + - edited + - opened + - reopened + +jobs: + check-pr-title: + runs-on: ubuntu-latest + permissions: + pull-requests: read + steps: + - name: Check PR title follows conventional commits + uses: amannn/action-semantic-pull-request@v5 + with: + types: | + build + chore + ci + docs + feat + fix + perf + refactor + style + test + # scope is not required ("feat: whatever" is okay) + requireScope: false + # if the PR only has one commit, we can validate the commit message + # instead of the PR title + validateSingleCommit: true + subjectPattern: ^.{1,}$ + subjectPatternError: | + The subject "{subject}" found in the pull request title "{title}" + didn't match the configured pattern. Please ensure that the subject + matches the conventional commit format. + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + diff --git a/firewood/.github/workflows/publish.yaml b/firewood/.github/workflows/publish.yaml new file mode 100644 index 000000000000..08be902a3182 --- /dev/null +++ b/firewood/.github/workflows/publish.yaml @@ -0,0 +1,52 @@ +name: publish + +on: + workflow_dispatch: + release: + types: [published] + +jobs: + publish-firewood-crate: + name: firewood-lib + runs-on: ubuntu-latest + if: startsWith(github.event.release.tag_name, 'v') + steps: + - uses: actions/checkout@v1 + - uses: dtolnay/rust-toolchain@stable + ## NOTE: keep these packages sorted in reverse topological order! + ## cargo tree --workspace -e all | grep firewood + - name: publish firewood-macros crate + continue-on-error: false + run: | + cargo login ${{ secrets.CARGO_TOKEN }} + cargo publish -p firewood-macros + - name: publish firewood-triehash crate + continue-on-error: false + run: | + cargo login ${{ secrets.CARGO_TOKEN }} + cargo publish -p firewood-triehash + - name: publish firewood-storage crate + continue-on-error: false + run: | + cargo login ${{ secrets.CARGO_TOKEN }} + cargo publish -p firewood-storage + - name: publish firewood crate + continue-on-error: false + run: | + cargo login ${{ secrets.CARGO_TOKEN }} + cargo publish -p firewood + - name: publish firewood-ffi crate + continue-on-error: false + run: | + cargo login ${{ secrets.CARGO_TOKEN }} + cargo publish -p firewood-ffi + - name: publish firewood-fwdctl crate + continue-on-error: false + run: | + cargo login ${{ secrets.CARGO_TOKEN }} + cargo publish -p firewood-fwdctl + - name: publish firewood-benchmark crate + continue-on-error: false + run: | + cargo login ${{ secrets.CARGO_TOKEN }} + cargo publish -p firewood-benchmark diff --git a/firewood/.github/workflows/release.yaml b/firewood/.github/workflows/release.yaml new file mode 100644 index 000000000000..547bd1a582c5 --- /dev/null +++ b/firewood/.github/workflows/release.yaml @@ -0,0 +1,18 @@ +name: release + +on: + push: + tags: + - "v*.*.*" + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Release + uses: softprops/action-gh-release@v1 + with: + draft: true + generate_release_notes: true diff --git a/firewood/.gitignore b/firewood/.gitignore new file mode 100644 index 000000000000..bc93dbf81862 --- /dev/null +++ b/firewood/.gitignore @@ -0,0 +1,104 @@ +# Ignore VSCode directory +.vscode +.idea + +compose-dev.yaml + +# ignore test databases +*_db + +#### Below sections are auto-generated #### + +# Created by https://www.toptal.com/developers/gitignore/api/rust,visualstudiocode,vim,macos +# Edit at https://www.toptal.com/developers/gitignore?templates=rust,visualstudiocode,vim,macos + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Rust ### +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +### Golang ### +go.work +go.work.sum + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/rust,visualstudiocode,vim,macos diff --git a/firewood/.markdownlint.json b/firewood/.markdownlint.json new file mode 100644 index 000000000000..92a0928f72c2 --- /dev/null +++ b/firewood/.markdownlint.json @@ -0,0 +1,3 @@ +{ + "line-length": false, +} diff --git a/firewood/.vscode/extensions.json b/firewood/.vscode/extensions.json new file mode 100644 index 000000000000..4f731bf664e5 --- /dev/null +++ b/firewood/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "davidanson.vscode-markdownlint", + "rust-lang.rust-analyzer", + "vadimcn.vscode-lldb" + ] +} diff --git a/firewood/AGENTS.md b/firewood/AGENTS.md new file mode 100644 index 000000000000..7751e53ad8dc --- /dev/null +++ b/firewood/AGENTS.md @@ -0,0 +1,188 @@ +# Firewood - AI Assistant Guide + +This document provides context and guidance for AI assistants working with the Firewood codebase. + +## Project Overview + +Firewood is an embedded key-value store optimized for storing recent Merkleized +blockchain state with minimal overhead. It's designed for the Avalanche C-Chain +and EVM-compatible blockchains that store state in Merkle tries. + +**Key Characteristics:** + +- Written in Rust (edition 2024, MSRV 1.91.0) +- Beta-level software with evolving API +- Compaction-less database that directly stores trie nodes on-disk +- Not built on generic KV stores (LevelDB/RocksDB) +- Uses trie structure directly as the index on-disk +- Maintains configurable number of recent revisions in memory and on disk + +## Architecture Principles + +1. **Direct Trie Storage**: Unlike most state management approaches, Firewood directly uses the trie structure as the index on-disk rather than emulating it on top of a generic database. + +2. **Revision Management**: Creates new roots for each revision, tracks deleted nodes in a future-delete log (FDL), and returns space to free lists when revisions expire. + +3. **Disk Addressing**: Root address of a node is simply the disk offset within the database file, not based on hashes. + +4. **Recoverability**: Guarantees recoverability by not referencing new nodes before they're flushed to disk and carefully managing free lists. + +## Workspace Structure + +This is a Cargo workspace with the following members: + +```text +firewood/ # Core library and main database implementation +├── src/ # Core source code +│ ├── db.rs # Main database API +│ └── manager.rs # RevisionManager for managing historical revisions +├── examples/ # Example usage (e.g., insert example) +└── benches/ # Benchmarks + +firewood-macros/ # Procedural macros for the project +storage/ # Storage layer implementation +triehash/ # Trie hashing functionality +ffi/ # Foreign Function Interface (FFI) binding for Golang +├── src/ # Rust FFI bindings (C-compatible API) +├── firewood.go # Go wrapper around the Firewood `Db` type +├── proposal.go # Go wrapper around the Firewood `Proposal` type +└── revision.go # Go wrapper around the Firewood `DbView` type +fwdctl/ # CLI tool for interacting with Firewood databases +benchmark/ # Performance benchmarking suite +├── bootstrap/ # Script for running C-Chain reexecution benchmark on an EC2 instance. +└── setup-scripts/ # Scripts for setting up benchmark environments +``` + +## Important Terminology + +- **Revision**: Historical point-in-time state of the trie +- **View**: Interface to read from a Revision or Proposal +- **Node**: Portion of a trie that can point to other nodes and/or contain Key/Value pairs +- **Hash/Root Hash**: Merkle hash for a node/root node +- **Proposal**: Consists of base Root Hash and Batch, not yet committed +- **Commit**: Operation of applying Proposals to the most recent Revision +- **Batch**: Ordered set of Put/Delete operations + +## Feature Flags + +### `ethhash` + +By default, Firewood uses SHA-256 hashing compatible with merkledb. Enable this feature for Ethereum compatibility: + +- Changes hashing from SHA-256 to Keccak-256 +- Understands "account" nodes at specific depths with RLP-encoded values +- Computes account trie hash as actual root +- See `firewood/storage/src/hashers/ethhash.rs` for implementation details + +### `logging` + +Enable for runtime logging. Set `RUST_LOG` environment variable accordingly (uses `env_logger`). + +## Common Development Tasks + +### FFI + +Building and using the FFI library is a multi-step process. To generate the +Firewood Rust FFI bindings: + +```bash +cd ffi/src # Go to Rust binding directory +cargo clean # Remove any existing bindings +cargo build --profile maxperf --features ethhash,logger # Generate bindings +``` + +To then have Golang utilize these new bindings: + +```bash +cd .. # Go to ffi directory +go tool cgo firewood.go # Generate cgo wrappers +``` + +### Using the CLI + +The `fwdctl` tool provides command-line operations on databases. See `fwdctl/README.md`. + +## Coding Conventions and Constraints + +For more information on coding conventions and constraints, please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) + +## PR Strategy + +Before submitting/updating a PR, run the following + +```bash +cargo fmt # Format code +cargo test --workspace --features ethhash,logger --all-targets # Run tests +cargo clippy --workspace --features ethhash,logger --all-targets # Linter +cargo doc --no-deps # Ensure docs build +``` + +All tests must pass, and there should be no clippy warnings. + +### Markdown Linter + +If your PR touches any Markdown file, run the following: + +```bash +markdownlint-cli2 . +``` + +If the linter fails, run the following to fix any lint errors: + +```bash +markdownlint-cli2 . --fix +``` + +If you don't have `markdownlint-cli2` available on your system, run the +following to install the linter: + +```bash +brew install markdownlint-cli2 +``` + +## Performance Profiles + +- **release**: Standard release with debug symbols +- **maxperf**: Panic abort, single codegen unit, fat LTO, no debug symbols + +## Dependencies Management + +Key dependencies are centrally managed in workspace `Cargo.toml`: + +- `firewood`, `firewood-macros`, `firewood-storage`, `firewood-ffi`, `firewood-triehash` (workspace members) +- Common deps: `clap`, `thiserror`, `smallvec`, `sha2`, `log`, etc. +- Test deps: `criterion`, `tempfile`, `rand`, etc. + +## Key Files to Know + +- `README.md` - Main documentation +- `CONTRIBUTING.md` - Contribution guidelines +- `RELEASE.md` - Release process +- `README.docker.md` - Docker setup +- `CHANGELOG.md` - Version history +- `clippy.toml` - Linting configuration +- `justfile` - Just command runner recipes +- `cliff.toml` - Changelog generation config + +## Notes for AI Assistants + +1. **Safety First**: This codebase denies unsafe code. Never suggest unsafe + blocks without documentation and strong justification. Unsafe code could be + utilized in the `ffi` crate. + +2. **Testing**: Any changes should include appropriate tests. Run `cargo test --release` to verify. + +3. **Performance Context**: This is a database designed for blockchain state. Performance matters. Consider allocation patterns and hot paths. + +4. **Beta Status**: The API may change. Don't assume stability guarantees. + +5. **Feature Flags**: Be aware of `ethhash` feature flag when discussing Ethereum compatibility vs. default merkledb compatibility. + +6. **Documentation**: Public APIs should be well-documented. Run `cargo doc --no-deps` to check. + +7. **Workspace Awareness**: This is a multi-crate workspace. Changes may affect multiple crates. Check `Cargo.toml` for workspace structure. + +## Additional Resources + +- [Auto-generated docs](https://ava-labs.github.io/firewood/firewood/) +- [Issue tracker](https://github.com/ava-labs/firewood/issues) diff --git a/firewood/BUILD.bazel b/firewood/BUILD.bazel new file mode 100644 index 000000000000..969e08488f94 --- /dev/null +++ b/firewood/BUILD.bazel @@ -0,0 +1,4 @@ +exports_files([ + "Cargo.toml", + "Cargo.lock", +]) diff --git a/firewood/CHANGELOG.md b/firewood/CHANGELOG.md new file mode 100644 index 000000000000..5eb0f1baf4b1 --- /dev/null +++ b/firewood/CHANGELOG.md @@ -0,0 +1,732 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [0.0.15] - 2025-11-18 + +### 🚀 Features + +- Merge key-value range into trie ([#1427](https://github.com/ava-labs/firewood/pull/1427)) +- *(storage)* Replace `ArcSwap` with `Mutex` for better performance ([#1447](https://github.com/ava-labs/firewood/pull/1447)) +- *(ffi)* [**breaking**] Remove unused kvBackend interface ([#1448](https://github.com/ava-labs/firewood/pull/1448)) +- *(ffi)* Add keepalive struct to own waitgroup logic ([#1437](https://github.com/ava-labs/firewood/pull/1437)) +- Remove the last bits of arc-swap ([#1464](https://github.com/ava-labs/firewood/pull/1464)) +- *(ffi)* Fill in ffi methods for range proofs ([#1429](https://github.com/ava-labs/firewood/pull/1429)) +- *(firewood/ffi)* Add `FjallStore` ([#1395](https://github.com/ava-labs/firewood/pull/1395)) + +### 🚜 Refactor + +- *(rootstore)* Replace RootStoreError with boxed error ([#1446](https://github.com/ava-labs/firewood/pull/1446)) +- Remove default 1-minute timeout on `Database.Close()` and set 1-sec in tests ([#1458](https://github.com/ava-labs/firewood/pull/1458)) + +### 📚 Documentation + +- Add agent instructions ([#1445](https://github.com/ava-labs/firewood/pull/1445)) +- *(firewood)* Clean up commit steps ([#1453](https://github.com/ava-labs/firewood/pull/1453)) +- Merge code review process into CONTRIBUTING.md ([#1397](https://github.com/ava-labs/firewood/pull/1397)) +- Add comprehensive metrics documentation in METRICS.md ([#1402](https://github.com/ava-labs/firewood/pull/1402)) + +### ⚡ Performance + +- *(ffi)* [**breaking**] Use fixed size Hash ([#1449](https://github.com/ava-labs/firewood/pull/1449)) + +### 🧪 Testing + +- Fix `giant_node` test ([#1465](https://github.com/ava-labs/firewood/pull/1465)) + +### ⚙️ Miscellaneous Tasks + +- *(ci)* Re-enable ffi-nix job ([#1450](https://github.com/ava-labs/firewood/pull/1450)) +- Relegate build equivalent check to post-merge job ([#1469](https://github.com/ava-labs/firewood/pull/1469)) + +## [0.0.14] - 2025-11-07 + +### 🚀 Features + +- *(monitoring)* Grafana automatic dashboard and auth provisioning ([#1307](https://github.com/ava-labs/firewood/pull/1307)) +- *(ffi)* Implement revision handles and expose to FFI layer ([#1326](https://github.com/ava-labs/firewood/pull/1326)) +- *(ffi-iterator)* Implementation of Iterator in Rust (1/4) ([#1255](https://github.com/ava-labs/firewood/pull/1255)) +- *(ffi-iterator)* Implementation of Iterator in Go (2/4) ([#1256](https://github.com/ava-labs/firewood/pull/1256)) +- *(1/7)* Add U4 type to be used as a path component ([#1336](https://github.com/ava-labs/firewood/pull/1336)) +- *(2/7)* Add newtype for PathComponent ([#1337](https://github.com/ava-labs/firewood/pull/1337)) +- *(3/7)* Add TriePath trait and path abstraction ([#1338](https://github.com/ava-labs/firewood/pull/1338)) +- *(4/7)* Add SplitPath trait ([#1339](https://github.com/ava-labs/firewood/pull/1339)) +- *(ffi-iterator)* Batching support for Iterator (3/4) ([#1257](https://github.com/ava-labs/firewood/pull/1257)) +- *(5/7)* Add PackedPathRef type ([#1341](https://github.com/ava-labs/firewood/pull/1341)) +- *(6/7)* Children newtype ([#1344](https://github.com/ava-labs/firewood/pull/1344)) +- Use PathComponent in proofs ([#1359](https://github.com/ava-labs/firewood/pull/1359)) +- Replace NodeAndPrefix with HashableShunt ([#1362](https://github.com/ava-labs/firewood/pull/1362)) +- Parallel updates to Merkle trie (v2) ([#1258](https://github.com/ava-labs/firewood/pull/1258)) +- Parallel hashing of Merkle trie ([#1303](https://github.com/ava-labs/firewood/pull/1303)) +- Add nix flake for ffi ([#1319](https://github.com/ava-labs/firewood/pull/1319)) +- Add more info for IO error message ([#1378](https://github.com/ava-labs/firewood/pull/1378)) +- Add TrieNode trait and related functionality ([#1363](https://github.com/ava-labs/firewood/pull/1363)) +- Add hashed key-value trie implementation ([#1365](https://github.com/ava-labs/firewood/pull/1365)) +- Define explicit associated types on Hashable ([#1366](https://github.com/ava-labs/firewood/pull/1366)) +- *(ffi)* `Database.Close()` guarantees proposals committed or freed ([#1349](https://github.com/ava-labs/firewood/pull/1349)) +- *(ffi)* [**breaking**] Support empty values in Update operations ([#1420](https://github.com/ava-labs/firewood/pull/1420)) +- Add just task runner to ensure reproducibility of CI ([#1345](https://github.com/ava-labs/firewood/pull/1345)) +- *(ffi)* [**breaking**] Add finalization logic for Revisions ([#1435](https://github.com/ava-labs/firewood/pull/1435)) +- *(benchmark/bootstrap)* Add config param ([#1438](https://github.com/ava-labs/firewood/pull/1438)) + +### 🐛 Bug Fixes + +- Explicitly release advisory lock on drop ([#1352](https://github.com/ava-labs/firewood/pull/1352)) +- EINTR during iouring calls ([#1354](https://github.com/ava-labs/firewood/pull/1354)) +- Revert "feat: Parallel updates to Merkle trie (v2)" ([#1372](https://github.com/ava-labs/firewood/pull/1372)) +- Revert "fix: Revert "feat: Parallel updates to Merkle trie (v2)"" ([#1374](https://github.com/ava-labs/firewood/pull/1374)) +- *(storage)* Flush freelist early to prevent corruption ([#1389](https://github.com/ava-labs/firewood/pull/1389)) +- *(benchmark/bootstrap)* Consistent go deps ([#1436](https://github.com/ava-labs/firewood/pull/1436)) + +### 🚜 Refactor + +- Unify root storage using Child enum ([#1330](https://github.com/ava-labs/firewood/pull/1330)) +- *(db)* `TestDb` constructor ([#1351](https://github.com/ava-labs/firewood/pull/1351)) + +### 📚 Documentation + +- *(benchmark/bootstrap)* Expand README.md ([#1421](https://github.com/ava-labs/firewood/pull/1421)) + +### 🧪 Testing + +- Show symbol diff when ffi-nix build equivalency test fails ([#1423](https://github.com/ava-labs/firewood/pull/1423)) + +### ⚙️ Miscellaneous Tasks + +- Include dependency lockfile ([#1321](https://github.com/ava-labs/firewood/pull/1321)) +- Add race detection in Go ([#1323](https://github.com/ava-labs/firewood/pull/1323)) +- *(nodestore)* Remove empty committed err ([#1353](https://github.com/ava-labs/firewood/pull/1353)) +- Upgrade dependencies ([#1360](https://github.com/ava-labs/firewood/pull/1360)) +- *(nodestore)* Access persisted nodestores ([#1355](https://github.com/ava-labs/firewood/pull/1355)) +- Update Go to 1.24.8 ([#1361](https://github.com/ava-labs/firewood/pull/1361)) +- Print ulimits and set memlock to unlimited before fuzz tests ([#1375](https://github.com/ava-labs/firewood/pull/1375)) +- *(db/manager)* Add `MockStore` ([#1346](https://github.com/ava-labs/firewood/pull/1346)) +- Update Go to 1.24.9 ([#1380](https://github.com/ava-labs/firewood/pull/1380)) +- *(ffi/firewood)* Remove `RootStore` generics ([#1388](https://github.com/ava-labs/firewood/pull/1388)) +- Update .golangci.yaml ([#1394](https://github.com/ava-labs/firewood/pull/1394)) +- Update ffi build check to configure cargo with same MAKEFLAGS as nix ([#1392](https://github.com/ava-labs/firewood/pull/1392)) +- Fix new lint warning from 1.91 update ([#1417](https://github.com/ava-labs/firewood/pull/1417)) +- Update .golangci.yaml ([#1419](https://github.com/ava-labs/firewood/pull/1419)) +- [**breaking**] Drop binary support for macos 13/14 ([#1425](https://github.com/ava-labs/firewood/pull/1425)) +- *(ci)* Disable ffi-nix job pending reliable build equivalency ([#1426](https://github.com/ava-labs/firewood/pull/1426)) +- Added helper to reduce code duplication between Db.propose and Proposal.create_proposal ([#1343](https://github.com/ava-labs/firewood/pull/1343)) +- Add guidance on Go workspaces ([#1434](https://github.com/ava-labs/firewood/pull/1434)) + +## [0.0.13] - 2025-09-26 + +### 🚀 Features + +- *(async-removal)* Phase 3 - make `Db` trait sync ([#1213](https://github.com/ava-labs/firewood/pull/1213)) +- *(checker)* Fix error with free area that is not head of a free list ([#1231](https://github.com/ava-labs/firewood/pull/1231)) +- *(async-removal)* Phase 4 - Make `DbView` synchronous ([#1219](https://github.com/ava-labs/firewood/pull/1219)) +- *(ffi-refactor)* Refactor cached view (1/8) ([#1222](https://github.com/ava-labs/firewood/pull/1222)) +- *(ffi-refactor)* Add OwnedSlice and OwnedBytes (2/8) ([#1223](https://github.com/ava-labs/firewood/pull/1223)) +- *(ffi-refactor)* Introduce VoidResult and panic handlers (3/8) ([#1224](https://github.com/ava-labs/firewood/pull/1224)) +- *(ffi-refactor)* Refactor Db opening to use new Result structure (4/8) ([#1225](https://github.com/ava-labs/firewood/pull/1225)) +- *(ffi-refactor)* Refactor how hash values are returned (5/8) ([#1226](https://github.com/ava-labs/firewood/pull/1226)) +- *(ffi-refactor)* Refactor revision to use database handle (6/8) ([#1227](https://github.com/ava-labs/firewood/pull/1227)) +- *(ffi-refactor)* Add `ValueResult` type (7/8) ([#1228](https://github.com/ava-labs/firewood/pull/1228)) +- *(checker)* Print report using template for better readability ([#1237](https://github.com/ava-labs/firewood/pull/1237)) +- *(checker)* Fix free lists when the erroneous area is the head ([#1240](https://github.com/ava-labs/firewood/pull/1240)) +- *(ffi-proofs)* Stub interfaces for FFI to interact with proofs. ([#1253](https://github.com/ava-labs/firewood/pull/1253)) +- Explicit impl of PartialEq/Eq on HashOrRlp ([#1260](https://github.com/ava-labs/firewood/pull/1260)) +- *(proofs)* [**breaking**] Disable `ValueDigest::Hash` for ethhash ([#1269](https://github.com/ava-labs/firewood/pull/1269)) +- [**breaking**] Rename `Hashable::key` ([#1270](https://github.com/ava-labs/firewood/pull/1270)) +- *(range-proofs)* KeyValuePairIter (1/2) ([#1282](https://github.com/ava-labs/firewood/pull/1282)) +- *(proofs)* [**breaking**] Add v0 serialization for RangeProofs ([#1271](https://github.com/ava-labs/firewood/pull/1271)) +- *(ffi-refactor)* Replace sequence id with pointer to proposals (8/8) ([#1221](https://github.com/ava-labs/firewood/pull/1221)) + +### 🐛 Bug Fixes + +- Add an advisory lock ([#1244](https://github.com/ava-labs/firewood/pull/1244)) +- Path iterator returned wrong node ([#1259](https://github.com/ava-labs/firewood/pull/1259)) +- Use `count` instead of `size_hint` ([#1268](https://github.com/ava-labs/firewood/pull/1268)) +- Correct typo in README.md ([#1276](https://github.com/ava-labs/firewood/pull/1276)) +- Resolve build failures by pinning opentelemetry to 0.30 ([#1281](https://github.com/ava-labs/firewood/pull/1281)) +- *(range-proofs)* Serialize range proof key consistently ([#1278](https://github.com/ava-labs/firewood/pull/1278)) +- *(range-proofs)* Fix verify of exclusion proofs ([#1279](https://github.com/ava-labs/firewood/pull/1279)) +- *(ffi)* GetFromRoot typo ([#1298](https://github.com/ava-labs/firewood/pull/1298)) +- Incorrect gauge metrics ([#1300](https://github.com/ava-labs/firewood/pull/1300)) +- M6id is a amd64 machine ([#1305](https://github.com/ava-labs/firewood/pull/1305)) +- Revert #1116 ([#1313](https://github.com/ava-labs/firewood/pull/1313)) + +### 💼 Other + +- *(deps)* Update typed-builder requirement from 0.21.0 to 0.22.0 ([#1275](https://github.com/ava-labs/firewood/pull/1275)) + +### 📚 Documentation + +- README implies commit == persist ([#1283](https://github.com/ava-labs/firewood/pull/1283)) + +### 🧪 Testing + +- Mark new_empty_proposal as test only ([#1249](https://github.com/ava-labs/firewood/pull/1249)) +- *(firewood)* Use ctor section to init logger for all tests ([#1277](https://github.com/ava-labs/firewood/pull/1277)) +- *(bootstrap)* Bootstrap testing scripts ([#1287](https://github.com/ava-labs/firewood/pull/1287)) + +### ⚙️ Miscellaneous Tasks + +- Only allocate the area needed ([#1217](https://github.com/ava-labs/firewood/pull/1217)) +- Synchronize .golangci.yaml ([#1234](https://github.com/ava-labs/firewood/pull/1234)) +- *(metrics-check)* Re-use previous comment instead of spamming new ones ([#1232](https://github.com/ava-labs/firewood/pull/1232)) +- Nuke grpc-testtool ([#1220](https://github.com/ava-labs/firewood/pull/1220)) +- Rename FuzzTree ([#1239](https://github.com/ava-labs/firewood/pull/1239)) +- Upgrade to rust 1.89 ([#1242](https://github.com/ava-labs/firewood/pull/1242)) +- Rename mut_root to root_mut ([#1248](https://github.com/ava-labs/firewood/pull/1248)) +- Add missing debug traits ([#1254](https://github.com/ava-labs/firewood/pull/1254)) +- These tests actually work now ([#1262](https://github.com/ava-labs/firewood/pull/1262)) +- Cargo +nightly clippy --fix ([#1265](https://github.com/ava-labs/firewood/pull/1265)) +- Update .golangci.yaml ([#1274](https://github.com/ava-labs/firewood/pull/1274)) +- Various script improvements ([#1288](https://github.com/ava-labs/firewood/pull/1288)) +- *(bootstrap)* Add keys for brandon ([#1289](https://github.com/ava-labs/firewood/pull/1289)) +- *(bootstrap)* Add keys for Bernard and Amin ([#1291](https://github.com/ava-labs/firewood/pull/1291)) +- [**breaking**] Decorate enums and structs with `#[non_exhaustive]` ([#1292](https://github.com/ava-labs/firewood/pull/1292)) +- Add spot instance support ([#1294](https://github.com/ava-labs/firewood/pull/1294)) +- Upgrade go ([#1296](https://github.com/ava-labs/firewood/pull/1296)) +- Ask for clippy and rustfmt ([#1306](https://github.com/ava-labs/firewood/pull/1306)) +- Add support for enormous disk ([#1308](https://github.com/ava-labs/firewood/pull/1308)) +- Disable non-security dependabot version bumps ([#1315](https://github.com/ava-labs/firewood/pull/1315)) +- Upgrade dependencies ([#1314](https://github.com/ava-labs/firewood/pull/1314)) +- *(benchmark)* Add ssh key ([#1316](https://github.com/ava-labs/firewood/pull/1316)) + +## [0.0.11] - 2025-08-20 + +### 🚀 Features + +- *(checker)* Checker returns all errors found in the report ([#1176](https://github.com/ava-labs/firewood/pull/1176)) +- Remove Default impl on HashType ([#1169](https://github.com/ava-labs/firewood/pull/1169)) +- Update revision manager error ([#1170](https://github.com/ava-labs/firewood/pull/1170)) +- *(checker)* Return the leaked areas in the checker report ([#1179](https://github.com/ava-labs/firewood/pull/1179)) +- *(checker)* Update unaligned page count ([#1181](https://github.com/ava-labs/firewood/pull/1181)) +- *(checker)* Add error when node data is bigger than area size ([#1183](https://github.com/ava-labs/firewood/pull/1183)) +- Remove `Batch` type alias ([#1171](https://github.com/ava-labs/firewood/pull/1171)) +- *(checker)* Annotate IO error with parent pointer in checker errors ([#1188](https://github.com/ava-labs/firewood/pull/1188)) +- *(checker)* Do not return physical size to accomodate raw disks ([#1200](https://github.com/ava-labs/firewood/pull/1200)) +- *(ffi)* Add BorrowedBytes type ([#1174](https://github.com/ava-labs/firewood/pull/1174)) +- *(checker)* More clear print formats for checker report ([#1201](https://github.com/ava-labs/firewood/pull/1201)) +- *(async-removal)* Phase 1 - lint on `clippy::unused_async` ([#1211](https://github.com/ava-labs/firewood/pull/1211)) +- *(checker)* Collect statistics for branches and leaves separately ([#1206](https://github.com/ava-labs/firewood/pull/1206)) +- *(async-removal)* Phase 2 - make `Proposal` trait sync ([#1212](https://github.com/ava-labs/firewood/pull/1212)) +- *(checker)* Add checker fix template ([#1199](https://github.com/ava-labs/firewood/pull/1199)) + +### 🐛 Bug Fixes + +- *(checker)* Skip freelist after first encountering an invalid free area ([#1178](https://github.com/ava-labs/firewood/pull/1178)) +- Fix race around reading nodes during commit ([#1180](https://github.com/ava-labs/firewood/pull/1180)) +- *(fwdctl)* [**breaking**] Db path consistency + no auto-create ([#1189](https://github.com/ava-labs/firewood/pull/1189)) + +### ⚡ Performance + +- Remove unnecessary Box on `OffsetReader` ([#1185](https://github.com/ava-labs/firewood/pull/1185)) + +### 🧪 Testing + +- Add read-during-commit test ([#1186](https://github.com/ava-labs/firewood/pull/1186)) +- Fix merkle compatibility test ([#1173](https://github.com/ava-labs/firewood/pull/1173)) +- Ban `rand::rng()` and provide an env seeded alternative ([#1192](https://github.com/ava-labs/firewood/pull/1192)) +- Reenable eth merkle compatibility test ([#1214](https://github.com/ava-labs/firewood/pull/1214)) + +### ⚙️ Miscellaneous Tasks + +- Metric change detection comments only on 1st-party PRs ([#1167](https://github.com/ava-labs/firewood/pull/1167)) +- Run CI on macOS ([#1168](https://github.com/ava-labs/firewood/pull/1168)) +- Update .golangci.yaml ([#1166](https://github.com/ava-labs/firewood/pull/1166)) +- Allow FreeListIterator to skip to next free list ([#1177](https://github.com/ava-labs/firewood/pull/1177)) +- Address lints triggered with rust 1.89 ([#1182](https://github.com/ava-labs/firewood/pull/1182)) +- Deny `undocumented-unsafe-blocks` ([#1172](https://github.com/ava-labs/firewood/pull/1172)) +- Fwdctl cleanups ([#1190](https://github.com/ava-labs/firewood/pull/1190)) +- AreaIndex newtype ([#1193](https://github.com/ava-labs/firewood/pull/1193)) +- Remove setup-protoc ([#1203](https://github.com/ava-labs/firewood/pull/1203)) +- Automatically label PRs from external contributors ([#1195](https://github.com/ava-labs/firewood/pull/1195)) +- Don't fail fast on certain jobs ([#1198](https://github.com/ava-labs/firewood/pull/1198)) +- Add PathGuard type when computing hashes ([#1202](https://github.com/ava-labs/firewood/pull/1202)) +- *(checker)* Add function to compute area counts and bytes ([#1218](https://github.com/ava-labs/firewood/pull/1218)) + +## [0.0.10] - 2025-08-01 + +### 🚀 Features + +- *(async-iterator)* Implement ([#1096](https://github.com/ava-labs/firewood/pull/1096)) +- Export logs ([#1070](https://github.com/ava-labs/firewood/pull/1070)) +- Render the commit sha in fwdctl ([#1109](https://github.com/ava-labs/firewood/pull/1109)) +- Update proof types to be generic over mutable or immutable collections ([#1121](https://github.com/ava-labs/firewood/pull/1121)) +- Refactor value types to use the type alias ([#1122](https://github.com/ava-labs/firewood/pull/1122)) +- *(dumper)* Child links in hex (easy) ([#1124](https://github.com/ava-labs/firewood/pull/1124)) +- *(deferred-allocate)* Part 3: Defer allocate ([#1061](https://github.com/ava-labs/firewood/pull/1061)) +- *(checker)* Disable buggy ethhash checker ([#1127](https://github.com/ava-labs/firewood/pull/1127)) +- Add `Children` type alias ([#1123](https://github.com/ava-labs/firewood/pull/1123)) +- Make NodeStore more generic ([#1134](https://github.com/ava-labs/firewood/pull/1134)) +- *(checker)* Add progress bar ([#1105](https://github.com/ava-labs/firewood/pull/1105)) +- *(checker)* Checker errors include reference to parent ([#1085](https://github.com/ava-labs/firewood/pull/1085)) +- Update RangeProof structure ([#1136](https://github.com/ava-labs/firewood/pull/1136)) +- Update range_proof signature ([#1151](https://github.com/ava-labs/firewood/pull/1151)) +- *(checker)* Add InvalidKey error +- *(deferred-persist)* Part 1: unpersisted gauge ([#1116](https://github.com/ava-labs/firewood/pull/1116)) +- *(checker)* Collect basic statistics while checking the db image ([#1149](https://github.com/ava-labs/firewood/pull/1149)) +- *(fwdctl)* Add support for dump formats ([#1161](https://github.com/ava-labs/firewood/pull/1161)) +- *(ffi)* Remove the Arc wrapper around Proposal ([#1160](https://github.com/ava-labs/firewood/pull/1160)) + +### 🐛 Bug Fixes + +- *(fwdctl)* Fix fwdctl with ethhash ([#1091](https://github.com/ava-labs/firewood/pull/1091)) +- *(checker)* Fix checker with ethhash ([#1130](https://github.com/ava-labs/firewood/pull/1130)) +- Fix broken deserialization of old FreeArea format ([#1147](https://github.com/ava-labs/firewood/pull/1147)) +- Create metrics registration macros ([#980](https://github.com/ava-labs/firewood/pull/980)) + +### 💼 Other + +- Cargo.toml upgrades and fixes ([#1099](https://github.com/ava-labs/firewood/pull/1099)) +- *(deps)* Update criterion requirement from 0.6.0 to 0.7.0 ([#1140](https://github.com/ava-labs/firewood/pull/1140)) + +### 📚 Documentation + +- Update ffi/README.md to include configs, metrics, and logs ([#1111](https://github.com/ava-labs/firewood/pull/1111)) + +### 🎨 Styling + +- Remove unnecessary string in error ([#1104](https://github.com/ava-labs/firewood/pull/1104)) + +### 🧪 Testing + +- Add fuzz testing for checker, with fixes ([#1118](https://github.com/ava-labs/firewood/pull/1118)) +- Port TestDeepPropose from go->rust ([#1115](https://github.com/ava-labs/firewood/pull/1115)) + +### ⚙️ Miscellaneous Tasks + +- Add propose-on-propose test ([#1097](https://github.com/ava-labs/firewood/pull/1097)) +- Implement newtype for LInearAddress ([#1086](https://github.com/ava-labs/firewood/pull/1086)) +- Refactor verifying value digests ([#1119](https://github.com/ava-labs/firewood/pull/1119)) +- Checker test cleanups ([#1131](https://github.com/ava-labs/firewood/pull/1131)) +- Minor cleanups and nits ([#1133](https://github.com/ava-labs/firewood/pull/1133)) +- Add a golang install script ([#1141](https://github.com/ava-labs/firewood/pull/1141)) +- Move all merkle tests into a subdirectory ([#1150](https://github.com/ava-labs/firewood/pull/1150)) +- Require license header for ffi code ([#1159](https://github.com/ava-labs/firewood/pull/1159)) +- Bump version to v0.0.10 ([#1165](https://github.com/ava-labs/firewood/pull/1165)) + +## [0.0.9] - 2025-07-17 + +### 🚀 Features + +- *(ffi)* Add gauges to metrics reporter ([#1035](https://github.com/ava-labs/firewood/pull/1035)) +- *(delayed-persist)* Part 1: Roots may be in mem ([#1041](https://github.com/ava-labs/firewood/pull/1041)) +- *(delayed-persist)* 2.1: Unpersisted deletions ([#1045](https://github.com/ava-labs/firewood/pull/1045)) +- *(delayed-persist)* Part 2.2: Branch Children ([#1047](https://github.com/ava-labs/firewood/pull/1047)) +- [**breaking**] Export firewood metrics ([#1044](https://github.com/ava-labs/firewood/pull/1044)) +- *(checker)* Add error to report finding leaked areas ([#1052](https://github.com/ava-labs/firewood/pull/1052)) +- *(delayed-persist)* Dump unpersisted nodestore ([#1055](https://github.com/ava-labs/firewood/pull/1055)) +- *(checker)* Split leaked ranges into valid areas ([#1059](https://github.com/ava-labs/firewood/pull/1059)) +- *(checker)* Check for misaligned stored areas ([#1046](https://github.com/ava-labs/firewood/pull/1046)) +- [**breaking**] Auto open or create with truncate ([#1064](https://github.com/ava-labs/firewood/pull/1064)) +- *(deferred-allocate)* UnpersistedIterator ([#1060](https://github.com/ava-labs/firewood/pull/1060)) +- *(checker)* Add hash checks ([#1063](https://github.com/ava-labs/firewood/pull/1063)) + +### 🐛 Bug Fixes + +- Avoid reference to LinearAddress ([#1042](https://github.com/ava-labs/firewood/pull/1042)) +- Remove dependency on serde ([#1066](https://github.com/ava-labs/firewood/pull/1066)) +- Encoding partial paths for leaf nodes ([#1067](https://github.com/ava-labs/firewood/pull/1067)) +- Root_hash_reversed_deletions duplicate keys ([#1076](https://github.com/ava-labs/firewood/pull/1076)) +- *(checker)* Avoid checking physical file size for compatibility ([#1079](https://github.com/ava-labs/firewood/pull/1079)) + +### 🎨 Styling + +- Remove unnecessary error descriptor ([#1049](https://github.com/ava-labs/firewood/pull/1049)) + +### ⚙️ Miscellaneous Tasks + +- *(build)* Remove unused dependencies ([#1037](https://github.com/ava-labs/firewood/pull/1037)) +- Update firewood in grpc-testtool ([#1040](https://github.com/ava-labs/firewood/pull/1040)) +- Aaron is requested only for .github ([#1043](https://github.com/ava-labs/firewood/pull/1043)) +- Remove `#[allow]`s no longer needed ([#1022](https://github.com/ava-labs/firewood/pull/1022)) +- Split nodestore into functional areas ([#1048](https://github.com/ava-labs/firewood/pull/1048)) +- Update `golangci-lint` ([#1053](https://github.com/ava-labs/firewood/pull/1053)) +- Update CODEOWNERS ([#1080](https://github.com/ava-labs/firewood/pull/1080)) +- Run CI with --no-default-features ([#1081](https://github.com/ava-labs/firewood/pull/1081)) +- Release 0.0.9 ([#1084](https://github.com/ava-labs/firewood/pull/1084)) + +## [0.0.8] - 2025-07-07 + +### 🚀 Features + +- *(checker)* Firewood checker framework ([#936](https://github.com/ava-labs/firewood/pull/936)) +- Enable a configurable free list cache in the FFI ([#1017](https://github.com/ava-labs/firewood/pull/1017)) +- *(nodestore)* Add functionalities to iterate the free list ([#1015](https://github.com/ava-labs/firewood/pull/1015)) +- *(checker)* Traverse free lists ([#1026](https://github.com/ava-labs/firewood/pull/1026)) + +### 🐛 Bug Fixes + +- Unnecessary quotes in publish action ([#996](https://github.com/ava-labs/firewood/pull/996)) +- Report IO errors ([#1005](https://github.com/ava-labs/firewood/pull/1005)) +- Publish firewood-macros ([#1019](https://github.com/ava-labs/firewood/pull/1019)) +- Logger macros causing linting warnings ([#1021](https://github.com/ava-labs/firewood/pull/1021)) + +### 💼 Other + +- *(deps)* Update lru requirement from 0.14.0 to 0.15.0 ([#1001](https://github.com/ava-labs/firewood/pull/1001)) +- *(deps)* Update lru requirement from 0.15.0 to 0.16.0 ([#1023](https://github.com/ava-labs/firewood/pull/1023)) +- *(deps)* Upgrade sha2, tokio, clap, fastrace, serde... ([#1025](https://github.com/ava-labs/firewood/pull/1025)) + +### 🚜 Refactor + +- *(deps)* Move duplicates to workspace ([#1002](https://github.com/ava-labs/firewood/pull/1002)) +- *(ffi)* [**breaking**] Split starting metrics exporter from db startup ([#1016](https://github.com/ava-labs/firewood/pull/1016)) + +### 📚 Documentation + +- README cleanup ([#1024](https://github.com/ava-labs/firewood/pull/1024)) + +### ⚡ Performance + +- Cache the latest view ([#1004](https://github.com/ava-labs/firewood/pull/1004)) +- Allow cloned proposals ([#1010](https://github.com/ava-labs/firewood/pull/1010)) +- Break up the RevisionManager lock ([#1027](https://github.com/ava-labs/firewood/pull/1027)) + +### ⚙️ Miscellaneous Tasks + +- Suppress clippy::cast_possible_truncation across the workspace ([#1012](https://github.com/ava-labs/firewood/pull/1012)) +- Clippy pushdown ([#1011](https://github.com/ava-labs/firewood/pull/1011)) +- Allow some extra pedantic warnings ([#1014](https://github.com/ava-labs/firewood/pull/1014)) +- Check for metrics changes ([#1013](https://github.com/ava-labs/firewood/pull/1013)) +- Share workspace metadata and packages ([#1020](https://github.com/ava-labs/firewood/pull/1020)) +- Add concurrency group to attach static libs workflow ([#1038](https://github.com/ava-labs/firewood/pull/1038)) +- Bump version to v0.0.8 ([#1018](https://github.com/ava-labs/firewood/pull/1018)) + +## [0.0.7] - 2025-06-26 + +### 🚀 Features + +- Add methods to fetch views from any hash ([#993](https://github.com/ava-labs/firewood/pull/993)) + +### 🐛 Bug Fixes + +- *(ci)* Include submodule name in ffi tag ([#991](https://github.com/ava-labs/firewood/pull/991)) + +### ⚡ Performance + +- *(metrics)* Add some metrics around propose and commit times ([#989](https://github.com/ava-labs/firewood/pull/989)) + +### 🎨 Styling + +- Use cbindgen to convert to pointers ([#969](https://github.com/ava-labs/firewood/pull/969)) + +### 🧪 Testing + +- Check support for empty proposals ([#988](https://github.com/ava-labs/firewood/pull/988)) + +### ⚙️ Miscellaneous Tasks + +- Simplify + cleanup generate_cgo script ([#979](https://github.com/ava-labs/firewood/pull/979)) +- Update Cargo.toml add repository field ([#987](https://github.com/ava-labs/firewood/pull/987)) +- *(fuzz)* Add step to upload fuzz testdata on failure ([#990](https://github.com/ava-labs/firewood/pull/990)) +- Add special case for non semver tags to attach static libs ([#992](https://github.com/ava-labs/firewood/pull/992)) +- Remove requirement for conventional commits ([#994](https://github.com/ava-labs/firewood/pull/994)) +- Release v0.0.7 ([#997](https://github.com/ava-labs/firewood/pull/997)) + +## [0.0.6] - 2025-06-21 + +### 🚀 Features + +- Improve error handling and add sync iterator ([#941](https://github.com/ava-labs/firewood/pull/941)) +- *(metrics)* Add read_node counters ([#947](https://github.com/ava-labs/firewood/pull/947)) +- Return database creation errors through FFI ([#945](https://github.com/ava-labs/firewood/pull/945)) +- *(ffi)* Add go generate switch between enabled cgo blocks ([#978](https://github.com/ava-labs/firewood/pull/978)) + +### 🐛 Bug Fixes + +- Use saturating subtraction for metrics counter ([#937](https://github.com/ava-labs/firewood/pull/937)) +- *(attach-static-libs)* Push commit/branch to remote on tag events ([#944](https://github.com/ava-labs/firewood/pull/944)) +- Add add_arithmetic_side_effects clippy ([#949](https://github.com/ava-labs/firewood/pull/949)) +- Improve ethhash warning message ([#961](https://github.com/ava-labs/firewood/pull/961)) +- *(storage)* Parse and validate database versions ([#964](https://github.com/ava-labs/firewood/pull/964)) + +### 💼 Other + +- *(deps)* Update fastrace-opentelemetry requirement from 0.11.0 to 0.12.0 ([#943](https://github.com/ava-labs/firewood/pull/943)) +- Move lints to the workspace ([#957](https://github.com/ava-labs/firewood/pull/957)) + +### ⚡ Performance + +- Remove some unecessary allocs during serialization ([#965](https://github.com/ava-labs/firewood/pull/965)) + +### 🎨 Styling + +- *(attach-static-libs)* Use go mod edit instead of sed to update mod path ([#946](https://github.com/ava-labs/firewood/pull/946)) + +### 🧪 Testing + +- *(ethhash)* Convert ethhash test to fuzz test for ethhash compatibility ([#956](https://github.com/ava-labs/firewood/pull/956)) + +### ⚙️ Miscellaneous Tasks + +- Upgrade actions/checkout ([#939](https://github.com/ava-labs/firewood/pull/939)) +- Add push to main to attach static libs triggers ([#952](https://github.com/ava-labs/firewood/pull/952)) +- Check the PR title for conventional commits ([#953](https://github.com/ava-labs/firewood/pull/953)) +- Add Brandon to CODEOWNERS ([#954](https://github.com/ava-labs/firewood/pull/954)) +- Set up for publishing to crates.io ([#962](https://github.com/ava-labs/firewood/pull/962)) +- Remove remnants of no-std ([#968](https://github.com/ava-labs/firewood/pull/968)) +- *(ffi)* Rename ffi package to match dir ([#971](https://github.com/ava-labs/firewood/pull/971)) +- *(attach-static-libs)* Add pre build command to set MACOSX_DEPLOYMENT_TARGET for static libs build ([#973](https://github.com/ava-labs/firewood/pull/973)) +- Use new firewood-go-* FFI repo naming ([#975](https://github.com/ava-labs/firewood/pull/975)) +- Upgrade metrics packages ([#982](https://github.com/ava-labs/firewood/pull/982)) +- Release v0.0.6 ([#985](https://github.com/ava-labs/firewood/pull/985)) + +## [0.0.5] - 2025-06-05 + +### 🚀 Features + +- *(ffi)* Ffi error messages ([#860](https://github.com/ava-labs/firewood/pull/860)) +- *(ffi)* Proposal creation isolated from committing ([#867](https://github.com/ava-labs/firewood/pull/867)) +- *(ffi)* Get values from proposals ([#877](https://github.com/ava-labs/firewood/pull/877)) +- *(ffi)* Full proposal support ([#878](https://github.com/ava-labs/firewood/pull/878)) +- *(ffi)* Support `Get` for historical revisions ([#881](https://github.com/ava-labs/firewood/pull/881)) +- *(ffi)* Add proposal root retrieval ([#910](https://github.com/ava-labs/firewood/pull/910)) + +### 🐛 Bug Fixes + +- *(ffi)* Prevent memory leak and tips for finding leaks ([#862](https://github.com/ava-labs/firewood/pull/862)) +- *(src)* Drop unused revisions ([#866](https://github.com/ava-labs/firewood/pull/866)) +- *(ffi)* Clarify roles of `Value` extractors ([#875](https://github.com/ava-labs/firewood/pull/875)) +- *(ffi)* Check revision is available ([#890](https://github.com/ava-labs/firewood/pull/890)) +- *(ffi)* Prevent undefined behavior on empty slices ([#894](https://github.com/ava-labs/firewood/pull/894)) +- Fix empty hash values ([#925](https://github.com/ava-labs/firewood/pull/925)) + +### 💼 Other + +- *(deps)* Update pprof requirement from 0.12.1 to 0.13.0 ([#283](https://github.com/ava-labs/firewood/pull/283)) +- *(deps)* Update lru requirement from 0.11.0 to 0.12.0 ([#306](https://github.com/ava-labs/firewood/pull/306)) +- *(deps)* Update typed-builder requirement from 0.16.0 to 0.17.0 ([#320](https://github.com/ava-labs/firewood/pull/320)) +- *(deps)* Update typed-builder requirement from 0.17.0 to 0.18.0 ([#324](https://github.com/ava-labs/firewood/pull/324)) +- Remove dead code ([#333](https://github.com/ava-labs/firewood/pull/333)) +- Kv_dump should be done with the iterator ([#347](https://github.com/ava-labs/firewood/pull/347)) +- Add remaining lint checks ([#397](https://github.com/ava-labs/firewood/pull/397)) +- Finish error handler mapper ([#421](https://github.com/ava-labs/firewood/pull/421)) +- Switch from EmptyDB to Db ([#422](https://github.com/ava-labs/firewood/pull/422)) +- *(deps)* Update aquamarine requirement from 0.3.1 to 0.4.0 ([#434](https://github.com/ava-labs/firewood/pull/434)) +- *(deps)* Update serial_test requirement from 2.0.0 to 3.0.0 ([#477](https://github.com/ava-labs/firewood/pull/477)) +- *(deps)* Update aquamarine requirement from 0.4.0 to 0.5.0 ([#496](https://github.com/ava-labs/firewood/pull/496)) +- *(deps)* Update env_logger requirement from 0.10.1 to 0.11.0 ([#502](https://github.com/ava-labs/firewood/pull/502)) +- *(deps)* Update tonic-build requirement from 0.10.2 to 0.11.0 ([#522](https://github.com/ava-labs/firewood/pull/522)) +- *(deps)* Update tonic requirement from 0.10.2 to 0.11.0 ([#523](https://github.com/ava-labs/firewood/pull/523)) +- *(deps)* Update nix requirement from 0.27.1 to 0.28.0 ([#563](https://github.com/ava-labs/firewood/pull/563)) +- Move clippy pragma closer to usage ([#578](https://github.com/ava-labs/firewood/pull/578)) +- *(deps)* Update typed-builder requirement from 0.18.1 to 0.19.1 ([#684](https://github.com/ava-labs/firewood/pull/684)) +- *(deps)* Update lru requirement from 0.8.0 to 0.12.4 ([#708](https://github.com/ava-labs/firewood/pull/708)) +- *(deps)* Update typed-builder requirement from 0.19.1 to 0.20.0 ([#711](https://github.com/ava-labs/firewood/pull/711)) +- *(deps)* Bump actions/download-artifact from 3 to 4.1.7 in /.github/workflows ([#715](https://github.com/ava-labs/firewood/pull/715)) +- Insert truncated trie +- Allow for trace and no logging +- Add read_for_update +- Revision history should never grow +- Use a more random hash +- Use smallvec to optimize for 16 byte values +- *(deps)* Update aquamarine requirement from 0.5.0 to 0.6.0 ([#727](https://github.com/ava-labs/firewood/pull/727)) +- *(deps)* Update thiserror requirement from 1.0.57 to 2.0.3 ([#751](https://github.com/ava-labs/firewood/pull/751)) +- *(deps)* Update pprof requirement from 0.13.0 to 0.14.0 ([#750](https://github.com/ava-labs/firewood/pull/750)) +- *(deps)* Update metrics-util requirement from 0.18.0 to 0.19.0 ([#765](https://github.com/ava-labs/firewood/pull/765)) +- *(deps)* Update cbindgen requirement from 0.27.0 to 0.28.0 ([#767](https://github.com/ava-labs/firewood/pull/767)) +- *(deps)* Update bitfield requirement from 0.17.0 to 0.18.1 ([#772](https://github.com/ava-labs/firewood/pull/772)) +- *(deps)* Update lru requirement from 0.12.4 to 0.13.0 ([#771](https://github.com/ava-labs/firewood/pull/771)) +- *(deps)* Update bitfield requirement from 0.18.1 to 0.19.0 ([#801](https://github.com/ava-labs/firewood/pull/801)) +- *(deps)* Update typed-builder requirement from 0.20.0 to 0.21.0 ([#815](https://github.com/ava-labs/firewood/pull/815)) +- *(deps)* Update tonic requirement from 0.12.1 to 0.13.0 ([#826](https://github.com/ava-labs/firewood/pull/826)) +- *(deps)* Update opentelemetry requirement from 0.28.0 to 0.29.0 ([#816](https://github.com/ava-labs/firewood/pull/816)) +- *(deps)* Update lru requirement from 0.13.0 to 0.14.0 ([#840](https://github.com/ava-labs/firewood/pull/840)) +- *(deps)* Update metrics-exporter-prometheus requirement from 0.16.1 to 0.17.0 ([#853](https://github.com/ava-labs/firewood/pull/853)) +- *(deps)* Update rand requirement from 0.8.5 to 0.9.1 ([#850](https://github.com/ava-labs/firewood/pull/850)) +- *(deps)* Update pprof requirement from 0.14.0 to 0.15.0 ([#906](https://github.com/ava-labs/firewood/pull/906)) +- *(deps)* Update cbindgen requirement from 0.28.0 to 0.29.0 ([#899](https://github.com/ava-labs/firewood/pull/899)) +- *(deps)* Update criterion requirement from 0.5.1 to 0.6.0 ([#898](https://github.com/ava-labs/firewood/pull/898)) +- *(deps)* Bump golang.org/x/crypto from 0.17.0 to 0.35.0 in /ffi/tests ([#907](https://github.com/ava-labs/firewood/pull/907)) +- *(deps)* Bump google.golang.org/protobuf from 1.27.1 to 1.33.0 /ffi/tests ([#923](https://github.com/ava-labs/firewood/pull/923)) +- *(deps)* Bump google.golang.org/protobuf from 1.30.0 to 1.33.0 ([#924](https://github.com/ava-labs/firewood/pull/924)) + +### 🚜 Refactor + +- *(ffi)* Cleanup unused and duplicate code ([#926](https://github.com/ava-labs/firewood/pull/926)) + +### 📚 Documentation + +- *(ffi)* Remove private declarations from public docs ([#874](https://github.com/ava-labs/firewood/pull/874)) + +### 🧪 Testing + +- *(ffi/tests)* Basic eth compatibility ([#825](https://github.com/ava-labs/firewood/pull/825)) +- *(ethhash)* Use libevm ([#900](https://github.com/ava-labs/firewood/pull/900)) + +### ⚙️ Miscellaneous Tasks + +- Use `decode` in single key proof verification ([#295](https://github.com/ava-labs/firewood/pull/295)) +- Use `decode` in range proof verification ([#303](https://github.com/ava-labs/firewood/pull/303)) +- Naming the elements of `ExtNode` ([#305](https://github.com/ava-labs/firewood/pull/305)) +- Remove the getter pattern over `ExtNode` ([#310](https://github.com/ava-labs/firewood/pull/310)) +- Proof cleanup ([#316](https://github.com/ava-labs/firewood/pull/316)) +- *(ffi/tests)* Update go-ethereum v1.15.7 ([#838](https://github.com/ava-labs/firewood/pull/838)) +- *(ffi)* Fix typo fwd_close_db comment ([#843](https://github.com/ava-labs/firewood/pull/843)) +- *(ffi)* Add linter ([#893](https://github.com/ava-labs/firewood/pull/893)) +- Require conventional commit format ([#933](https://github.com/ava-labs/firewood/pull/933)) +- Bump to v0.5.0 ([#934](https://github.com/ava-labs/firewood/pull/934)) + +## [0.0.4] - 2023-09-27 + +### 🚀 Features + +- Identify a revision with root hash ([#126](https://github.com/ava-labs/firewood/pull/126)) +- Supports chains of `StoreRevMut` ([#175](https://github.com/ava-labs/firewood/pull/175)) +- Add proposal ([#181](https://github.com/ava-labs/firewood/pull/181)) + +### 🐛 Bug Fixes + +- Update release to cargo-workspace-version ([#75](https://github.com/ava-labs/firewood/pull/75)) + +### 💼 Other + +- *(deps)* Update criterion requirement from 0.4.0 to 0.5.1 ([#96](https://github.com/ava-labs/firewood/pull/96)) +- *(deps)* Update enum-as-inner requirement from 0.5.1 to 0.6.0 ([#107](https://github.com/ava-labs/firewood/pull/107)) +- :position FTW? ([#140](https://github.com/ava-labs/firewood/pull/140)) +- *(deps)* Update indexmap requirement from 1.9.1 to 2.0.0 ([#147](https://github.com/ava-labs/firewood/pull/147)) +- *(deps)* Update pprof requirement from 0.11.1 to 0.12.0 ([#152](https://github.com/ava-labs/firewood/pull/152)) +- *(deps)* Update typed-builder requirement from 0.14.0 to 0.15.0 ([#153](https://github.com/ava-labs/firewood/pull/153)) +- *(deps)* Update lru requirement from 0.10.0 to 0.11.0 ([#155](https://github.com/ava-labs/firewood/pull/155)) +- Update hash fn to root_hash ([#170](https://github.com/ava-labs/firewood/pull/170)) +- Remove generics on Db ([#196](https://github.com/ava-labs/firewood/pull/196)) +- Remove generics for Proposal ([#197](https://github.com/ava-labs/firewood/pull/197)) +- Use quotes around all ([#200](https://github.com/ava-labs/firewood/pull/200)) +- :get: use Nibbles ([#210](https://github.com/ava-labs/firewood/pull/210)) +- Variable renames ([#211](https://github.com/ava-labs/firewood/pull/211)) +- Use thiserror ([#221](https://github.com/ava-labs/firewood/pull/221)) +- *(deps)* Update typed-builder requirement from 0.15.0 to 0.16.0 ([#222](https://github.com/ava-labs/firewood/pull/222)) +- *(deps)* Update tonic-build requirement from 0.9.2 to 0.10.0 ([#247](https://github.com/ava-labs/firewood/pull/247)) +- *(deps)* Update prost requirement from 0.11.9 to 0.12.0 ([#246](https://github.com/ava-labs/firewood/pull/246)) + +### ⚙️ Miscellaneous Tasks + +- Refactor `rev.rs` ([#74](https://github.com/ava-labs/firewood/pull/74)) +- Disable `test_buffer_with_redo` ([#128](https://github.com/ava-labs/firewood/pull/128)) +- Verify concurrent committing write batches ([#172](https://github.com/ava-labs/firewood/pull/172)) +- Remove redundant code ([#174](https://github.com/ava-labs/firewood/pull/174)) +- Remove unused clone for `StoreRevMutDelta` ([#178](https://github.com/ava-labs/firewood/pull/178)) +- Abstract out mutable store creation ([#176](https://github.com/ava-labs/firewood/pull/176)) +- Proposal test cleanup ([#184](https://github.com/ava-labs/firewood/pull/184)) +- Add comments for `Proposal` ([#186](https://github.com/ava-labs/firewood/pull/186)) +- Deprecate `WriteBatch` and use `Proposal` instead ([#188](https://github.com/ava-labs/firewood/pull/188)) +- Inline doc clean up ([#240](https://github.com/ava-labs/firewood/pull/240)) +- Remove unused blob in db ([#245](https://github.com/ava-labs/firewood/pull/245)) +- Add license header to firewood files ([#262](https://github.com/ava-labs/firewood/pull/262)) +- Revert back `test_proof` changes accidentally changed ([#279](https://github.com/ava-labs/firewood/pull/279)) + +## [0.0.3] - 2023-04-28 + +### 💼 Other + +- Move benching to criterion ([#61](https://github.com/ava-labs/firewood/pull/61)) +- Refactor file operations to use a Path ([#26](https://github.com/ava-labs/firewood/pull/26)) +- Fix panic get_item on a dirty write ([#66](https://github.com/ava-labs/firewood/pull/66)) +- Improve error handling ([#70](https://github.com/ava-labs/firewood/pull/70)) + +### 🧪 Testing + +- Speed up slow unit tests ([#58](https://github.com/ava-labs/firewood/pull/58)) + +### ⚙️ Miscellaneous Tasks + +- Add backtrace to e2e tests ([#59](https://github.com/ava-labs/firewood/pull/59)) + +## [0.0.2] - 2023-04-21 + +### 💼 Other + +- Fix test flake ([#44](https://github.com/ava-labs/firewood/pull/44)) + +### 📚 Documentation + +- Add release notes ([#27](https://github.com/ava-labs/firewood/pull/27)) +- Update CODEOWNERS ([#28](https://github.com/ava-labs/firewood/pull/28)) +- Add badges to README ([#33](https://github.com/ava-labs/firewood/pull/33)) + +## [0.0.1] - 2023-04-14 + +### 🐛 Bug Fixes + +- Clippy linting +- Specificy --lib in rustdoc linters +- Unset the pre calculated RLP values of interval nodes +- Run cargo clippy --fix +- Handle empty key value proof arguments as an error +- Tweak repo organization ([#130](https://github.com/ava-labs/firewood/pull/130)) +- Run clippy --fix across all workspaces ([#149](https://github.com/ava-labs/firewood/pull/149)) +- Update StoreError to use thiserror ([#156](https://github.com/ava-labs/firewood/pull/156)) +- Update db::new() to accept a Path ([#187](https://github.com/ava-labs/firewood/pull/187)) +- Use bytemuck instead of unsafe in growth-ring ([#185](https://github.com/ava-labs/firewood/pull/185)) +- Update firewood sub-projects ([#16](https://github.com/ava-labs/firewood/pull/16)) + +### 💼 Other + +- Fix additional clippy warnings +- Additional clippy fixes +- Fix additional clippy warnings +- Fix outstanding lint issues +- *(deps)* Update nix requirement from 0.25.0 to 0.26.1 +- Update version to 0.0.1 +- Add usage examples +- Add fwdctl create command +- Add fwdctl README and test +- Fix flag arguments; add fwdctl documentation +- Add logger +- Use log-level flag for setting logging level +- *(deps)* Update lru requirement from 0.8.0 to 0.9.0 +- Add generic key value insertion command +- Add get command +- Add delete command +- Move cli tests under tests/ +- Only use kv_ functions in fwdctl +- Fix implementation and add tests +- Add exit codes and stderr error logging +- Add tests +- Add serial library for testing purposes +- Add root command +- Add dump command +- Fixup root tests to be serial +- *(deps)* Update typed-builder requirement from 0.11.0 to 0.12.0 +- Add VSCode +- Update merkle_utils to return Results +- Fixup command UX to be positional +- Update firewood to match needed functionality +- Update DB and Merkle errors to implement the Error trait +- Update proof errors +- Add StdError trait to ProofError +- *(deps)* Update nix requirement from 0.25.0 to 0.26.2 +- *(deps)* Update lru requirement from 0.8.0 to 0.10.0 +- *(deps)* Update typed-builder requirement from 0.12.0 to 0.13.0 +- *(deps)* Update typed-builder requirement from 0.13.0 to 0.14.0 ([#144](https://github.com/ava-labs/firewood/pull/144)) +- Update create_file to return a Result ([#150](https://github.com/ava-labs/firewood/pull/150)) +- *(deps)* Update predicates requirement from 2.1.1 to 3.0.1 ([#154](https://github.com/ava-labs/firewood/pull/154)) +- Add new library crate ([#158](https://github.com/ava-labs/firewood/pull/158)) +- *(deps)* Update serial_test requirement from 1.0.0 to 2.0.0 ([#173](https://github.com/ava-labs/firewood/pull/173)) +- Refactor kv_remove to be more ergonomic ([#168](https://github.com/ava-labs/firewood/pull/168)) +- Add e2e test ([#167](https://github.com/ava-labs/firewood/pull/167)) +- Use eth and proof feature gates across all API surfaces. ([#181](https://github.com/ava-labs/firewood/pull/181)) +- Add license header to firewood source code ([#189](https://github.com/ava-labs/firewood/pull/189)) + +### 📚 Documentation + +- Add link to fwdctl README in main README +- Update fwdctl README with storage information +- Update fwdctl README with more examples +- Document get_revisions function with additional information. ([#177](https://github.com/ava-labs/firewood/pull/177)) +- Add alpha warning to firewood README ([#191](https://github.com/ava-labs/firewood/pull/191)) + +### 🧪 Testing + +- Add more range proof tests +- Update tests to use Results +- Re-enable integration tests after introduce cargo workspaces + +### ⚙️ Miscellaneous Tasks + +- Add release and publish GH Actions +- Update batch sizes in ci e2e job +- Add docs linter to strengthen firewood documentation +- Clippy should fail in case of warnings ([#151](https://github.com/ava-labs/firewood/pull/151)) +- Fail in case of error publishing firewood crate ([#21](https://github.com/ava-labs/firewood/pull/21)) + + diff --git a/firewood/CLAUDE.md b/firewood/CLAUDE.md new file mode 120000 index 000000000000..47dc3e3d863c --- /dev/null +++ b/firewood/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/firewood/CODEOWNERS b/firewood/CODEOWNERS new file mode 100644 index 000000000000..4aa1bc7b5e12 --- /dev/null +++ b/firewood/CODEOWNERS @@ -0,0 +1,5 @@ +# CODEOWNERS +# Note: more specific rules overrule wildcard +* @rkuris @demosdemon +/ffi @rkuris @demosdemon @alarso16 +/.github @rkuris @demosdemon @aaronbuchwald diff --git a/firewood/CONTRIBUTING.md b/firewood/CONTRIBUTING.md new file mode 100644 index 000000000000..0ee1df69d288 --- /dev/null +++ b/firewood/CONTRIBUTING.md @@ -0,0 +1,124 @@ +# Welcome contributors + +We are eager for contributions and happy you found yourself here. +Please read through this document to familiarize yourself with our +guidelines for contributing to firewood. + +## Table of Contents + +* [Quick Links](#Quick Links) +* [Testing](#testing) +* [How to submit changes](#How to submit changes) +* [Code Review Process](#Code Review Process) +* [Where can I ask for help?](#Where can I ask for help) + +## [Quick Links] + +* [Setting up docker](README.docker.md) +* [Auto-generated documentation](https://ava-labs.github.io/firewood/firewood/) +* [Issue tracker](https://github.com/ava-labs/firewood/issues) + +## [Testing] + +After submitting a PR, we'll run all the tests and verify your code meets our submission guidelines. To ensure it's more likely to pass these checks, you should run the following commands locally: + + cargo fmt + cargo test + cargo clippy + cargo doc --no-deps + +Resolve any warnings or errors before making your PR. + +## [How to submit changes] + +To create a PR, fork firewood, and use GitHub to create the PR. We typically prioritize reviews in the middle of the next work day, +so you should expect a response during the week within 24 hours. + +## [Code Review Process] + +Code review is a critical part of our development process. It ensures that our codebase remains maintainable, performant, and secure. This document outlines how we approach code reviews at Ava Labs, with responsibilities and expectations for both reviewers and authors. + +### For Reviewers + +Reviews should be completed or commented within one business day. We have a daily reminder for reviews that have not been reviewed that is posted in slack's #firewood channel. + +When reviewing code, your goal is to help the author improve the quality of the change and confirm that it meets our architectural and operational standards. GitHub provides three primary review options: + +#### ✅ Accept (Approve) + +Use this when the code is an improvement over the current state of the codebase. + +* It's okay to request minor changes in comments and still approve the pull request. +* Perfection is not the goal — progress is. If the submitted code is better than what's in production, it's acceptable to approve even if small improvements remain. Consider adding a new issue or request adding a code TODO for larger changes. + +#### 💬 Comment (Comment Only) + +Use this when your review is incomplete, or you're not ready to approve or reject yet. You should use this if the code is too large to review in a limited amount of time (typically 30-60 minutes). You can also suggest how to break up this diff into a smaller diff. + +* This can be helpful for asking clarifying questions, suggesting optional improvements, or flagging issues you're unsure about. +* This state signals that your review is in progress or advisory, not final. + +#### ❌ Reject (Request Changes) + +Use this when there are significant concerns with the code's correctness, architecture, design, or maintainability. + +* A "Reject" signals that the pull request must not be merged until the raised issues are addressed. +* The author is expected to make substantial revisions and return the code for a second round of review by the same reviewer. + +#### Best Practices + +* Be respectful and constructive. Your comments should guide and empower the author, not discourage them. +* Justify your feedback with principles, not preferences. +* If you're unsure, ask questions rather than assume intent. +* If you're going to nitpick, preface the comment with "nit:". This means the author can choose to ignore the comment. + +### For Authors + +As the author of a pull request, your responsibility is to ensure the review process is smooth, transparent, and productive. + +#### Before Requesting a Review + +* Review your own code. Catch obvious issues and clean up unnecessary changes. +* Some code changes are too large to be reviewed quickly. This can happen when the number of lines of new code is more than a few hundred. Consider breaking up your code in this case. +* Write a clear PR description. Include context, reasoning, and anything reviewers should know up front. +* Add tests and verify they pass locally and in CI. + +#### During Review + +* Respond to each comment, even if just to acknowledge it. +* Use GitHub's "Resolve" feature when you've addressed feedback. In some cases, to get to the "Resolve" button requires you select "Hide" first, with a reason of "Resolved". +* Don't be afraid to explain your design decisions—but stay open to change. +* If you disagree with a reviewer's suggestion, provide reasoning. If you're sure your response fully resolves the reviewer's suggestion, mark it as resolved. + +#### After Review + +* When you've made requested changes, clearly indicate it in your comment or commit, and re-request the review. +* If the PR was rejected, wait for explicit re-approval before merging. +* Thank your reviewers—they're helping you ship better code. + +## [How to report a bug] + +Please use the [issue tracker](https://github.com/ava-labs/firewood/issues) for reporting issues. + +## [First time fixes for contributors] + +The [issue tracker](https://github.com/ava-labs/firewood/issues) typically has some issues tagged for first-time contributors. If not, +please reach out. We hope you work on an easy task before tackling a harder one. + +## [How to request an enhancement] + +Just like bugs, please use the [issue tracker](https://github.com/ava-labs/firewood/issues) for requesting enhancements. Please tag the issue with the "enhancement" tag. + +## [Style Guide / Coding Conventions] + +We generally follow the same rules that `cargo fmt` and `cargo clippy` will report as warnings, with a few notable exceptions as documented in the associated Cargo.toml file. + +By default, we prohibit bare `unwrap` calls and index dereferencing, as there are usually better ways to write this code. In the case where you can't, please use `expect` with a message explaining why it would be a bug, which we currently allow. For more information on our motivation, please read this great article on unwrap: [Using unwrap() in Rust is Okay](https://blog.burntsushi.net/unwrap) by [Andrew Gallant](https://blog.burntsushi.net). + +## [Where can I ask for help]? + +If you have questions or need help, please post them as issues in the [issue tracker](https://github.com/ava-labs/firewood/issues). This allows the community to benefit from the discussion and helps us maintain a searchable knowledge base. + +## Thank you + +We'd like to extend a pre-emptive "thank you" for reading through this and submitting your first contribution! diff --git a/firewood/Cargo.lock b/firewood/Cargo.lock new file mode 100644 index 000000000000..9f3d87310afb --- /dev/null +++ b/firewood/Cargo.lock @@ -0,0 +1,4550 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" + +[[package]] +name = "anstream" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "aquamarine" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f50776554130342de4836ba542aa85a4ddb361690d7e8df13774d7284c3d5c2" +dependencies = [ + "include_dir", + "itertools 0.10.5", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "askama" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" +dependencies = [ + "askama_parser", + "basic-toml", + "memchr", + "proc-macro2", + "quote", + "rustc-hash", + "serde", + "serde_derive", + "syn", +] + +[[package]] +name = "askama_parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" +dependencies = [ + "memchr", + "serde", + "serde_derive", + "winnow", +] + +[[package]] +name = "assert_cmd" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcbb6924530aa9e0432442af08bbcafdad182db80d2e560da42a6d442535bf85" +dependencies = [ + "anstyle", + "bstr", + "libc", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "aws-lc-rs" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5932a7d9d28b0d2ea34c6b3779d35e3dd6f6345317c34e73438c4f1f29144151" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1826f2e4cfc2cd19ee53c42fbf68e2f81ec21108e0b7ecf6a71cf062137360fc" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-link", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + +[[package]] +name = "bindgen" +version = "0.72.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" +dependencies = [ + "bitflags 2.10.0", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", +] + +[[package]] +name = "bitfield" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21ba6517c6b0f2bf08be60e187ab64b038438f22dd755614d8fe4d4098c46419" +dependencies = [ + "bitfield-macros", +] + +[[package]] +name = "bitfield-macros" +version = "0.19.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f48d6ace212fdf1b45fd6b566bb40808415344642b76c3224c07c8df9da81e97" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bstr" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + +[[package]] +name = "bytemuck" +version = "1.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" + +[[package]] +name = "byteview" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6236364b88b9b6d0bc181ba374cf1ab55ba3ef97a1cb6f8cddad48a273767fb5" + +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + +[[package]] +name = "cbindgen" +version = "0.29.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "befbfd072a8e81c02f8c507aefce431fe5e7d051f83d48a23ffc9b9fe5a11799" +dependencies = [ + "clap", + "heck", + "indexmap", + "log", + "proc-macro2", + "quote", + "serde", + "serde_json", + "syn", + "tempfile", + "toml", +] + +[[package]] +name = "cc" +version = "1.2.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa8120877db0e5c011242f96806ce3c94e0737ab8108532a76a3300a01db2ab8" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02576b399397b659c26064fbc92a75fede9d18ffd5f80ca1cd74ddab167016e1" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" + +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + +[[package]] +name = "coarsetime" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91849686042de1b41cd81490edc83afbcb0abe5a9b6f2c4114f23ce8cca1bcf4" +dependencies = [ + "libc", + "wasix", + "wasm-bindgen", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "compare" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea0095f6103c2a8b44acd6fd15960c801dafebf02e21940360833e0673f48ba7" + +[[package]] +name = "console" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b430743a6eb14e9764d4260d4c0d8123087d504eeb9c48f2b2a5e810dd369df4" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.61.2", +] + +[[package]] +name = "const-hex" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" +dependencies = [ + "cfg-if", + "cpufeatures", + "proptest", + "serde_core", +] + +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpp_demangle" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2bb79cb74d735044c972aae58ed0aaa9a837e85b01106a54c39e42e97f62253" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "criterion" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928" +dependencies = [ + "anes", + "cast", + "ciborium", + "clap", + "criterion-plot", + "itertools 0.13.0", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_json", + "tinytemplate", + "walkdir", +] + +[[package]] +name = "criterion-plot" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338" +dependencies = [ + "cast", + "itertools 0.13.0", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-skiplist" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df29de440c58ca2cc6e587ec3d22347551a32435fbde9d2bff64e78a9ffa151b" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + +[[package]] +name = "ctor" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ffc71fcdcdb40d6f087edddf7f8f1f8f79e6cf922f555a9ee8779752d4819bd" +dependencies = [ + "ctor-proc-macro", + "dtor", +] + +[[package]] +name = "ctor-proc-macro" +version = "0.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + +[[package]] +name = "derive-where" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "direct-cargo-bazel-deps" +version = "0.0.1" +dependencies = [ + "bytes", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "double-ended-peekable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0d05e1c0dbad51b52c38bda7adceef61b9efc2baf04acfe8726a8c4630a6f57" + +[[package]] +name = "dtor" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "404d02eeb088a82cfd873006cb713fe411306c7d182c344905e101fb1167d301" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "endian-type" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "enum_dispatch" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa18ce2bc66555b3218614519ac839ddb759a7d6720732f979ef8d13be147ecd" +dependencies = [ + "once_cell", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "ethbloom" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c321610643004cf908ec0f5f2aa0d8f1f8e14b540562a2887a1111ff1ecbf7b" +dependencies = [ + "crunchy", + "fixed-hash", + "impl-rlp", + "impl-serde", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7326303c6c18bb03c7a3c4c22d4032ae60dfe673ca9109602aa4d8154b2637e" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-rlp", + "impl-serde", + "primitive-types", + "uint", +] + +[[package]] +name = "fastant" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bf7fa928ce0c4a43bd6e7d1235318fc32ac3a3dea06a2208c44e729449471a" +dependencies = [ + "small_ctor", + "web-time", +] + +[[package]] +name = "fastrace" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "318783b9fefe06130ab664ff1779215657586b004c0c7f3d6ece16d658936d06" +dependencies = [ + "fastant", + "fastrace-macro", + "parking_lot", + "pin-project", + "rand 0.9.2", + "rtrb", + "serde", +] + +[[package]] +name = "fastrace-macro" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7079009cf129d63c850dee732b58d7639d278a47ad99c607954ac94cfd57ef4" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "fastrace-opentelemetry" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e8ec7cff0ea398352764b6ee15c0902ccabf23d823525254b52d7f878fcf60" +dependencies = [ + "fastrace", + "log", + "opentelemetry", + "opentelemetry_sdk", + "pollster", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + +[[package]] +name = "findshlibs" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" +dependencies = [ + "cc", + "lazy_static", + "libc", + "winapi", +] + +[[package]] +name = "firewood" +version = "0.0.15" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "clap", + "coarsetime", + "criterion", + "ctor", + "derive-where", + "env_logger", + "ethereum-types", + "fastrace", + "firewood-macros", + "firewood-storage", + "firewood-triehash", + "fjall", + "hash-db", + "hex", + "hex-literal", + "integer-encoding", + "metrics", + "parking_lot", + "plain_hasher", + "pprof", + "rand 0.9.2", + "rayon", + "rlp", + "sha3", + "tempfile", + "test-case", + "thiserror", + "typed-builder", + "weak-table", +] + +[[package]] +name = "firewood-benchmark" +version = "0.0.15" +dependencies = [ + "clap", + "env_logger", + "fastrace", + "fastrace-opentelemetry", + "firewood", + "firewood-storage", + "hex", + "log", + "metrics", + "metrics-exporter-prometheus", + "metrics-util", + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry-proto", + "opentelemetry_sdk", + "pretty-duration", + "rand 0.9.2", + "rand_distr", + "sha2", + "tikv-jemallocator", + "tokio", +] + +[[package]] +name = "firewood-ffi" +version = "0.0.15" +dependencies = [ + "cbindgen", + "chrono", + "coarsetime", + "derive-where", + "env_logger", + "firewood", + "firewood-storage", + "metrics", + "metrics-util", + "oxhttp", + "parking_lot", + "test-case", + "tikv-jemallocator", +] + +[[package]] +name = "firewood-fwdctl" +version = "0.0.15" +dependencies = [ + "anyhow", + "askama", + "assert_cmd", + "clap", + "csv", + "env_logger", + "firewood", + "firewood-storage", + "hex", + "indicatif", + "log", + "nonzero_ext", + "num-format", + "predicates", + "rand 0.9.2", + "serial_test", +] + +[[package]] +name = "firewood-macros" +version = "0.0.15" +dependencies = [ + "coarsetime", + "metrics", + "proc-macro2", + "quote", + "syn", + "trybuild", +] + +[[package]] +name = "firewood-storage" +version = "0.0.15" +dependencies = [ + "aquamarine", + "bitfield", + "bitflags 2.10.0", + "bumpalo", + "bytemuck", + "bytemuck_derive", + "bytes", + "coarsetime", + "criterion", + "derive-where", + "enum-as-inner", + "fastrace", + "hex", + "indicatif", + "integer-encoding", + "io-uring", + "log", + "lru", + "metrics", + "nonzero_ext", + "parking_lot", + "pprof", + "rand 0.9.2", + "rlp", + "semver", + "sha2", + "sha3", + "smallvec", + "tempfile", + "test-case", + "thiserror", + "triomphe", +] + +[[package]] +name = "firewood-triehash" +version = "0.0.15" +dependencies = [ + "criterion", + "ethereum-types", + "hash-db", + "hex-literal", + "keccak-hasher", + "rlp", + "tiny-keccak", + "trie-standardmap", +] + +[[package]] +name = "fixed-hash" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +dependencies = [ + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", +] + +[[package]] +name = "fjall" +version = "2.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25ad44cd4360a0448a9b5a0a6f1c7a621101cca4578706d43c9a821418aebc" +dependencies = [ + "byteorder", + "byteview", + "dashmap", + "log", + "lsm-tree", + "path-absolutize", + "std-semaphore", + "tempfile", + "xxhash-rust", +] + +[[package]] +name = "float-cmp" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09cf3155332e944990140d967ff5eceb70df778b34f77d8075db46e4704e6d8" +dependencies = [ + "num-traits", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "guardian" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17e2ac29387b1aa07a1e448f7bb4f35b500787971e965b02842b900afa5c8f6f" + +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hash-db" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7d7786361d7425ae2fe4f9e407eb0efaa0840f5212d109cc018c40c35c6ab4" + +[[package]] +name = "hash256-std-hasher" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92c171d55b98633f4ed3860808f004099b36c1cc29c42cfc53aa8591b21efcf2" +dependencies = [ + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-literal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-codec" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d40b9d5e17727407e55028eafc22b2dc68781786e6d7eb8a21103f5058e3a14" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54ed8ad1f3877f7e775b8cbf30ed1bd3209a95401817f19a0eb4402d13f8cf90" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a143eada6a1ec4aefa5049037a26a6d597bfd64f8c026d07b77133e02b7dd0b" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "include_dir" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923d117408f1e49d914f1a379a309cffe4f18c05cf4e3d12e613a15fc81bd0dd" +dependencies = [ + "include_dir_macros", +] + +[[package]] +name = "include_dir_macros" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cab85a7ed0bd5f0e76d93846e0147172bed2e2d3f859bcc33a8d9699cad1a75" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", +] + +[[package]] +name = "indicatif" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88" +dependencies = [ + "console", + "portable-atomic", + "unicode-width", + "unit-prefix", + "web-time", +] + +[[package]] +name = "inferno" +version = "0.11.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "232929e1d75fe899576a3d5c7416ad0d88dbfbb3c3d6aa00873a7408a50ddb88" +dependencies = [ + "ahash", + "indexmap", + "is-terminal", + "itoa", + "log", + "num-format", + "once_cell", + "quick-xml", + "rgb", + "str_stack", +] + +[[package]] +name = "integer-encoding" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c00403deb17c3221a1fe4fb571b9ed0370b3dcd116553c77fa294a3d918699" + +[[package]] +name = "interval-heap" +version = "0.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11274e5e8e89b8607cfedc2910b6626e998779b48a019151c7604d0adcb86ac6" +dependencies = [ + "compare", +] + +[[package]] +name = "io-uring" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd7bddefd0a8833b88a4b68f90dae22c7450d11b354198baee3874fd811b344" +dependencies = [ + "bitflags 2.10.0", + "cfg-if", + "libc", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is-terminal" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keccak-hasher" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ea4653859ca2266a86419d3f592d3f22e7a854b482f99180d2498507902048" +dependencies = [ + "hash-db", + "hash256-std-hasher", + "tiny-keccak", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "lru" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96051b46fc183dc9cd4a223960ef37b9af631b55191852a8274bfef064cda20f" +dependencies = [ + "hashbrown 0.16.0", +] + +[[package]] +name = "lsm-tree" +version = "2.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799399117a2bfb37660e08be33f470958babb98386b04185288d829df362ea15" +dependencies = [ + "byteorder", + "crossbeam-skiplist", + "double-ended-peekable", + "enum_dispatch", + "guardian", + "interval-heap", + "log", + "lz4_flex", + "path-absolutize", + "quick_cache", + "rustc-hash", + "self_cell", + "tempfile", + "value-log", + "varint-rs", + "xxhash-rust", +] + +[[package]] +name = "lz4_flex" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "memmap2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +dependencies = [ + "libc", +] + +[[package]] +name = "metrics" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dea7ac8057892855ec285c440160265225438c3c45072613c25a4b26e98ef5" +dependencies = [ + "ahash", + "portable-atomic", +] + +[[package]] +name = "metrics-exporter-prometheus" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b166dea96003ee2531cf14833efedced545751d800f03535801d833313f8c15" +dependencies = [ + "base64", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "indexmap", + "ipnet", + "metrics", + "metrics-util", + "quanta", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "metrics-util" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe8db7a05415d0f919ffb905afa37784f71901c9a773188876984b4f769ab986" +dependencies = [ + "aho-corasick", + "crossbeam-epoch", + "crossbeam-utils", + "hashbrown 0.15.5", + "indexmap", + "metrics", + "ordered-float", + "quanta", + "radix_trie", + "rand 0.9.2", + "rand_xoshiro", + "sketches-ddsketch", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + +[[package]] +name = "normalize-line-endings" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be" + +[[package]] +name = "num-format" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" +dependencies = [ + "arrayvec", + "itoa", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "oorandom" +version = "11.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "opentelemetry" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84bcd6ae87133e903af7ef497404dda70c60d0ea14895fc8a5e6722754fc2a0" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "pin-project-lite", + "thiserror", + "tracing", +] + +[[package]] +name = "opentelemetry-http" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a6d09a73194e6b66df7c8f1b680f156d916a1a942abf2de06823dd02b7855d" +dependencies = [ + "async-trait", + "bytes", + "http", + "opentelemetry", + "reqwest", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2366db2dca4d2ad033cad11e6ee42844fd727007af5ad04a1730f4cb8163bf" +dependencies = [ + "http", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry_sdk", + "prost", + "reqwest", + "thiserror", + "tokio", + "tonic", + "tracing", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7175df06de5eaee9909d4805a3d07e28bb752c34cab57fa9cff549da596b30f" +dependencies = [ + "base64", + "const-hex", + "opentelemetry", + "opentelemetry_sdk", + "prost", + "serde", + "serde_json", + "tonic", + "tonic-prost", +] + +[[package]] +name = "opentelemetry_sdk" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ae4f5991976fd48df6d843de219ca6d31b01daaab2dad5af2badeded372bd" +dependencies = [ + "futures-channel", + "futures-executor", + "futures-util", + "opentelemetry", + "percent-encoding", + "rand 0.9.2", + "thiserror", +] + +[[package]] +name = "ordered-float" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" +dependencies = [ + "num-traits", +] + +[[package]] +name = "oxhttp" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "971c03797806d47915950e62816a8f365e3ddc8800310e3200ec666934d0f7c9" +dependencies = [ + "http", + "httparse", + "url", +] + +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "path-absolutize" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5" +dependencies = [ + "path-dedot", +] + +[[package]] +name = "path-dedot" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397" +dependencies = [ + "once_cell", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "plain_hasher" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e19e6491bdde87c2c43d70f4c194bc8a758f2eb732df00f61e43f7362e3b4cc" +dependencies = [ + "crunchy", +] + +[[package]] +name = "plotters" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" +dependencies = [ + "num-traits", + "plotters-backend", + "plotters-svg", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "plotters-backend" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" + +[[package]] +name = "plotters-svg" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" +dependencies = [ + "plotters-backend", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "pprof" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38a01da47675efa7673b032bf8efd8214f1917d89685e07e395ab125ea42b187" +dependencies = [ + "aligned-vec", + "backtrace", + "cfg-if", + "findshlibs", + "inferno", + "libc", + "log", + "nix", + "once_cell", + "smallvec", + "spin", + "symbolic-demangle", + "tempfile", + "thiserror", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "predicates" +version = "3.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +dependencies = [ + "anstyle", + "difflib", + "float-cmp", + "normalize-line-endings", + "predicates-core", + "regex", +] + +[[package]] +name = "predicates-core" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" + +[[package]] +name = "predicates-tree" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "pretty-duration" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8868e7264af614b3634ff0abbe37b178e61000611b8a75221aea40221924aba" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "primitive-types" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721a1da530b5a2633218dc9f75713394c983c352be88d2d7c9ee85e2c4c21794" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +dependencies = [ + "bitflags 2.10.0", + "num-traits", + "rand 0.9.2", + "rand_chacha 0.9.0", + "rand_xorshift", + "regex-syntax", + "unarray", +] + +[[package]] +name = "prost" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "quanta" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + +[[package]] +name = "quick-xml" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" +dependencies = [ + "memchr", +] + +[[package]] +name = "quick_cache" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ada44a88ef953a3294f6eb55d2007ba44646015e18613d2f213016379203ef3" +dependencies = [ + "equivalent", + "hashbrown 0.16.0", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "radix_trie" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +dependencies = [ + "endian-type", + "nibble_vec", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_distr" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" +dependencies = [ + "num-traits", + "rand 0.9.2", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "rayon" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.10.0", +] + +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "reqwest" +version = "0.12.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "rgb" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rlp" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24e92bb2a83198bb76d661a71df9f7076b8c420b8696e4d3d97d50d94479e3" +dependencies = [ + "bytes", + "rustc-hex", +] + +[[package]] +name = "rtrb" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8388ea1a9e0ea807e442e8263a699e7edcb320ecbcd21b4fa8ff859acce3ba" + +[[package]] +name = "rustc-demangle" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags 2.10.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "aws-lc-rs", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scc" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" +dependencies = [ + "sdd", +] + +[[package]] +name = "schannel" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + +[[package]] +name = "security-framework" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +dependencies = [ + "bitflags 2.10.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "self_cell" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33" + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serial_test" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +dependencies = [ + "futures", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sketches-ddsketch" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" + +[[package]] +name = "slab" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" + +[[package]] +name = "small_ctor" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88414a5ca1f85d82cc34471e975f0f74f6aa54c40f062efa42c0080e7f763f81" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "std-semaphore" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ae9eec00137a8eed469fb4148acd9fc6ac8c3f9b110f52cd34698c8b5bfa0e" + +[[package]] +name = "str_stack" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "symbolic-common" +version = "12.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d8046c5674ab857104bc4559d505f4809b8060d57806e45d49737c97afeb60" +dependencies = [ + "debugid", + "memmap2", + "stable_deref_trait", + "uuid", +] + +[[package]] +name = "symbolic-demangle" +version = "12.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1accb6e5c4b0f682de907623912e616b44be1c9e725775155546669dbff720ec" +dependencies = [ + "cpp_demangle", + "rustc-demangle", + "symbolic-common", +] + +[[package]] +name = "syn" +version = "2.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "target-triple" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "591ef38edfb78ca4771ee32cf494cb8771944bee237a9b91fc9c1424ac4b777b" + +[[package]] +name = "tempfile" +version = "3.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +dependencies = [ + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "termtree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683" + +[[package]] +name = "test-case" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8" +dependencies = [ + "test-case-macros", +] + +[[package]] +name = "test-case-core" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "test-case-macros" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "test-case-core", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tikv-jemalloc-sys" +version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "tikv-jemallocator" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a" +dependencies = [ + "libc", + "tikv-jemalloc-sys", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinytemplate" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "socket2", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6485ef6d0d9b5d0ec17244ff7eb05310113c3f316f2d14200d4de56b3cb98f8d" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" + +[[package]] +name = "tonic" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203" +dependencies = [ + "async-trait", + "base64", + "bytes", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67" +dependencies = [ + "bytes", + "prost", + "tonic", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project-lite", + "slab", + "sync_wrapper", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.10.0", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", +] + +[[package]] +name = "trie-standardmap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684aafb332fae6f83d7fe10b3fbfdbe39a1b3234c4e2a618f030815838519516" +dependencies = [ + "hash-db", + "keccak-hasher", +] + +[[package]] +name = "triomphe" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39" +dependencies = [ + "serde", + "stable_deref_trait", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "trybuild" +version = "1.0.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e17e807bff86d2a06b52bca4276746584a78375055b6e45843925ce2802b335" +dependencies = [ + "glob", + "serde", + "serde_derive", + "serde_json", + "target-triple", + "termcolor", + "toml", +] + +[[package]] +name = "typed-builder" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cce8e9c8115897e896894868ad4ae6851eff0fb7fd33fa95610e0fa93211886" +dependencies = [ + "typed-builder-macro", +] + +[[package]] +name = "typed-builder-macro" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921d52b8b19b1a455f54fa76a925a1cf49c0d6a7c6b232fc58523400d1f91560" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "uint" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909988d098b2f738727b161a106cfc7cab00c539c2687a8836f8e565976fb53e" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "value-log" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62fc7c4ce161f049607ecea654dca3f2d727da5371ae85e2e4f14ce2b98ed67c" +dependencies = [ + "byteorder", + "byteview", + "interval-heap", + "log", + "path-absolutize", + "rustc-hash", + "tempfile", + "varint-rs", + "xxhash-rust", +] + +[[package]] +name = "varint-rs" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wait-timeout" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" +dependencies = [ + "libc", +] + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasix" +version = "0.12.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fbb4ef9bbca0c1170e0b00dd28abc9e3b68669821600cad1caaed606583c6d" +dependencies = [ + "wasi", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "weak-table" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "323f4da9523e9a669e1eaf9c6e763892769b1d38c623913647bfdc1532fe4549" + +[[package]] +name = "web-sys" +version = "0.3.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/firewood/Cargo.toml b/firewood/Cargo.toml new file mode 100644 index 000000000000..cfdff00314a3 --- /dev/null +++ b/firewood/Cargo.toml @@ -0,0 +1,92 @@ +[workspace] +members = [ + "benchmark", + "ffi", + "firewood-macros", + "firewood", + "fwdctl", + "storage", + "triehash", +] +resolver = "2" + +[workspace.package] +# NOTE: when bumping to 0.1.0, this will be removed and each crate will have its +# version set independently. +version = "0.0.15" +edition = "2024" +license-file = "LICENSE.md" +homepage = "https://avalabs.org" +repository = "https://github.com/ava-labs/firewood" +readme = "README.md" +rust-version = "1.91.0" + +[profile.release] +debug = true + +[profile.maxperf] +panic = "abort" +codegen-units = 1 +lto = "fat" +debug = false +inherits = "release" + +[workspace.lints.rust] +unsafe_code = "deny" +missing_debug_implementations = "warn" + +[workspace.lints.clippy] +unwrap_used = "warn" +indexing_slicing = "warn" +explicit_deref_methods = "warn" +missing_const_for_fn = "warn" +arithmetic_side_effects = "warn" +undocumented_unsafe_blocks = "deny" +# lower the priority of pedantic to allow overriding the lints it includes +pedantic = { level = "warn", priority = -1 } +# These lints are from pedantic but allowed. They are a bit too pedantic and +# encourage making backwards incompatible changes. +needless_pass_by_value = "allow" +unnecessary_wraps = "allow" +unused_self = "allow" +# Ignore interger casts. This is to avoid unnecessary `try_into` calls for usize +# to u64 and vice versa and should be re-enabled if/when clippy has a separate +# lint for usize vs non-usize truncation. +cast_possible_truncation = "allow" + +[workspace.dependencies] +# workspace local packages +firewood = { path = "firewood", version = "0.0.15" } +firewood-macros = { path = "firewood-macros", version = "0.0.15" } +firewood-storage = { path = "storage", version = "0.0.15" } +firewood-ffi = { path = "ffi", version = "0.0.15" } +firewood-triehash = { path = "triehash", version = "0.0.15" } + +# common dependencies +aquamarine = "0.6.0" +bytemuck = "1.24.0" +bytemuck_derive = "1.10.2" +clap = { version = "4.5.52", features = ["derive"] } +coarsetime = "0.1.36" +env_logger = "0.11.8" +fastrace = "0.7.14" +hex = "0.4.3" +integer-encoding = "4.1.0" +log = "0.4.28" +metrics = "0.24.2" +metrics-util = "0.20.0" +nonzero_ext = "0.3.0" +rand_distr = "0.5.1" +sha2 = "0.10.9" +smallvec = { version = "1.15.1", features = ["write", "union", "const_new"] } +test-case = "3.3.1" +thiserror = "2.0.17" +parking_lot = "0.12.3" + +# common dev dependencies +criterion = "0.7.0" +ethereum-types = "0.16.0" +hex-literal = "1.1.0" +pprof = "0.15.0" +rand = "0.9.2" +tempfile = "3.23.0" diff --git a/firewood/LICENSE.md b/firewood/LICENSE.md new file mode 100644 index 000000000000..e7fe69c61eb0 --- /dev/null +++ b/firewood/LICENSE.md @@ -0,0 +1,65 @@ +# Ecosystem License + +Version: 1.1 + +Subject to the terms herein, Ava Labs, Inc. (**“Ava Labs”**) hereby grants you +a limited, royalty-free, worldwide, non-sublicensable, non-transferable, +non-exclusive license to use, copy, modify, create derivative works based on, +and redistribute the Software, in source code, binary, or any other form, +including any modifications or derivative works of the Software (collectively, +**“Licensed Software”**), in each case subject to this Ecosystem License +(**“License”**). + +This License applies to all copies, modifications, derivative works, and any +other form or usage of the Licensed Software. You will include and display +this License, without modification, with all uses of the Licensed Software, +regardless of form. + +You will use the Licensed Software solely (i) in connection with the Avalanche +Public Blockchain platform, having a NetworkID of 1 (Mainnet) or 5 (Fuji), and +associated blockchains, comprised exclusively of the Avalanche X-Chain, +C-Chain, P-Chain and any subnets linked to the P-Chain (“Avalanche Authorized +Platform”) or (ii) for non-production, testing or research purposes within the +Avalanche ecosystem, in each case, without any commercial application +(“Non-Commercial Use”); provided that this License does not permit use of the +Licensed Software in connection with (a) any forks of the Avalanche Authorized +Platform or (b) in any manner not operationally connected to the Avalanche +Authorized Platform other than, for the avoidance of doubt, the limited +exception for Non-Commercial Use. Ava Labs may publicly announce changes or +additions to the Avalanche Authorized Platform, which may expand or modify +usage of the Licensed Software. Upon such announcement, the Avalanche +Authorized Platform will be deemed to be the then-current iteration of such +platform. + +You hereby acknowledge and agree to the terms set forth at +. + +If you use the Licensed Software in violation of this License, this License +will automatically terminate and Ava Labs reserves all rights to seek any +remedy for such violation. + +Except for uses explicitly permitted in this License, Ava Labs retains all +rights in the Licensed Software, including without limitation the ability to +modify it. + +Except as required or explicitly permitted by this License, you will not use +any Ava Labs names, logos, or trademarks without Ava Labs’ prior written +consent. + +You may use this License for software other than the “Licensed Software” +specified above, as long as the only change to this License is the definition +of the term “Licensed Software.” + +The Licensed Software may reference third party components. You acknowledge +and agree that these third party components may be governed by a separate +license or terms and that you will comply with them. + +**TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE LICENSED SOFTWARE IS PROVIDED +ON AN “AS IS” BASIS, AND AVA LABS EXPRESSLY DISCLAIMS AND EXCLUDES ALL +REPRESENTATIONS, WARRANTIES AND OTHER TERMS AND CONDITIONS, WHETHER EXPRESS OR +IMPLIED, INCLUDING WITHOUT LIMITATION BY OPERATION OF LAW OR BY CUSTOM, +STATUTE OR OTHERWISE, AND INCLUDING, BUT NOT LIMITED TO, ANY IMPLIED WARRANTY, +TERM, OR CONDITION OF NON-INFRINGEMENT, MERCHANTABILITY, TITLE, OR FITNESS FOR +PARTICULAR PURPOSE. YOU USE THE LICENSED SOFTWARE AT YOUR OWN RISK. AVA LABS +EXPRESSLY DISCLAIMS ALL LIABILITY (INCLUDING FOR ALL DIRECT, CONSEQUENTIAL OR +OTHER DAMAGES OR LOSSES) RELATED TO ANY USE OF THE LICENSED SOFTWARE.** diff --git a/firewood/METRICS.md b/firewood/METRICS.md new file mode 100644 index 000000000000..fcac0c31a123 --- /dev/null +++ b/firewood/METRICS.md @@ -0,0 +1,286 @@ +# Firewood Metrics + +Firewood provides comprehensive metrics for monitoring database performance, resource utilization, and operational characteristics. These metrics are built using the [Prometheus](https://prometheus.io/) format and can be exposed for collection by monitoring systems. + +**Note**: Metric names in this documentation use dots (e.g., `firewood.proposal.commit`), but when exported to Prometheus, dots are automatically converted to underscores (e.g., `firewood_proposal_commit`) following Prometheus naming conventions. + +## Enabling Metrics + +Metrics are available when Firewood is built with the `metrics` feature. By default, metrics collection is enabled in the library but needs to be explicitly started in applications. + +**Important**: Only one metrics instance can be created per process. Attempting to initialize metrics multiple times will result in an error. + +### For Rust Applications + +Metrics are automatically registered when the instrumented code paths are executed. To expose metrics via HTTP: + +```rust +use metrics_exporter_prometheus::PrometheusBuilder; + +// Set up Prometheus exporter on port 9000 +PrometheusBuilder::new() + .install() + .expect("failed to install Prometheus recorder"); +``` + +### For FFI/Go Applications + +In the Go FFI layer, metrics must be explicitly enabled: + +```go +import "github.com/ava-labs/firewood-go-ethhash/ffi" + +// Option 1: Start metrics with HTTP exporter on a specific port +ffi.StartMetricsWithExporter(9000) + +// Option 2: Start metrics without exporter (use Gatherer to access) +ffi.StartMetrics() + +// Retrieve metrics programmatically +gatherer := ffi.Gatherer{} +metrics, err := gatherer.Gather() +``` + +See the [FFI README](ffi/README.md) for more details on FFI metrics configuration. + +## Available Metrics + +### Database Operations + +#### Proposal Metrics + +- **`firewood.proposals`** (counter) + - Description: Total number of proposals created + - Use: Track proposal creation rate and throughput + +- **`firewood.proposal.create`** (counter with `success` label) + - Description: Count of proposal creation operations + - Labels: `success=true|false` + - Use: Monitor proposal creation success rate + +- **`firewood.proposal.create_ms`** (counter with `success` label) + - Description: Time spent creating proposals in milliseconds + - Labels: `success=true|false` + - Use: Track proposal creation latency + +- **`firewood.proposal.commit`** (counter with `success` label) + - Description: Count of proposal commit operations + - Labels: `success=true|false` + - Use: Monitor commit success rate + +- **`firewood.proposal.commit_ms`** (counter with `success` label) + - Description: Time spent committing proposals in milliseconds + - Labels: `success=true|false` + - Use: Track commit latency and identify slow commits + +#### Revision Management + +- **`firewood.active_revisions`** (gauge) + - Description: Current number of active revisions in memory + - Use: Monitor memory usage and revision retention + +- **`firewood.max_revisions`** (gauge) + - Description: Maximum number of revisions configured + - Use: Track configuration setting + +### Merkle Trie Operations + +#### Insert Operations + +- **`firewood.insert`** (counter with `merkle` label) + - Description: Count of insert operations by type + - Labels: `merkle=update|above|below|split` + - `update`: Value updated at existing key + - `above`: New node inserted above existing node + - `below`: New node inserted below existing node + - `split`: Node split during insertion + - Use: Understand insert patterns and trie structure evolution + +#### Remove Operations + +- **`firewood.remove`** (counter with `prefix` and `result` labels) + - Description: Count of remove operations + - Labels: + - `prefix=true|false`: Whether operation is prefix-based removal + - `result=success|nonexistent`: Whether key(s) were found + - Use: Track deletion patterns and key existence + +### Storage and I/O Metrics + +#### Node Reading + +- **`firewood.read_node`** (counter with `from` label) + - Description: Count of node reads by source + - Labels: `from=file|memory` + - Use: Monitor read patterns and storage layer usage + +#### Cache Performance + +- **`firewood.cache.node`** (counter with `mode` and `type` labels) + - Description: Node cache hit/miss statistics + - Labels: + - `mode`: Read operation mode + - `type=hit|miss`: Cache hit or miss + - Use: Evaluate cache effectiveness for nodes + +- **`firewood.cache.freelist`** (counter with `type` label) + - Description: Free list cache hit/miss statistics + - Labels: `type=hit|miss` + - Use: Monitor free list cache efficiency + +#### I/O Operations + +- **`firewood.io.read`** (counter) + - Description: Total number of I/O read operations + - Use: Track I/O operation count + +- **`firewood.io.read_ms`** (counter) + - Description: Total time spent in I/O reads in milliseconds + - Use: Identify I/O bottlenecks and disk performance issues + +#### Node Persistence + +- **`firewood.flush_nodes`** (counter) + - Description: Cumulative time spent flushing nodes to disk in milliseconds (counter incremented by flush duration) + - Use: Monitor flush performance and identify slow disk writes; calculate average flush time using rate() + +### Memory Management + +#### Space Allocation + +- **`firewood.space.reused`** (counter with `index` label) + - Description: Bytes reused from free list + - Labels: `index`: Size index of allocated area + - Use: Track memory reuse efficiency + +- **`firewood.space.from_end`** (counter with `index` label) + - Description: Bytes allocated from end of nodestore when free list was insufficient + - Labels: `index`: Size index of allocated area + - Use: Track database growth and free list effectiveness + +- **`firewood.space.freed`** (counter with `index` label) + - Description: Bytes freed back to free list + - Labels: `index`: Size index of freed area + - Use: Monitor memory reclamation + +#### Node Management + +- **`firewood.delete_node`** (counter with `index` label) + - Description: Count of nodes deleted + - Labels: `index`: Size index of deleted node + - Use: Track node deletion patterns + +#### Ring Buffer + +- **`ring.full`** (counter) + - Description: Count of times the ring buffer became full during node flushing + - Use: Identify backpressure in node persistence pipeline + +### FFI Layer Metrics + +These metrics are specific to the Foreign Function Interface (Go) layer: + +#### Batch Operations + +- **`firewood.ffi.batch`** (counter) + - Description: Count of batch operations completed + - Use: Track FFI batch throughput + +- **`firewood.ffi.batch_ms`** (counter) + - Description: Time spent processing batches in milliseconds + - Use: Monitor FFI batch latency + +#### Proposal Operations + +- **`firewood.ffi.propose`** (counter) + - Description: Count of proposal operations via FFI + - Use: Track FFI proposal throughput + +- **`firewood.ffi.propose_ms`** (counter) + - Description: Time spent creating proposals via FFI in milliseconds + - Use: Monitor FFI proposal latency + +#### Commit Operations + +- **`firewood.ffi.commit`** (counter) + - Description: Count of commit operations via FFI + - Use: Track FFI commit throughput + +- **`firewood.ffi.commit_ms`** (counter) + - Description: Time spent committing via FFI in milliseconds + - Use: Monitor FFI commit latency + +#### View Caching + +- **`firewood.ffi.cached_view.hit`** (counter) + - Description: Count of cached view hits + - Use: Monitor view cache effectiveness + +- **`firewood.ffi.cached_view.miss`** (counter) + - Description: Count of cached view misses + - Use: Monitor view cache effectiveness + +## Interpreting Metrics + +### Performance Monitoring + +1. **Latency Tracking**: The `*_ms` metrics track operation durations. Monitor these for: + - Sudden increases indicating performance degradation + - Baseline establishment for SLA monitoring + - Correlation with system load + +2. **Throughput Monitoring**: Counter metrics without `_ms` suffix track operation counts: + - Rate of change indicates throughput + - Compare with expected load patterns + - Identify anomalies in operation rates + +### Resource Utilization + +1. **Cache Efficiency**: + - Calculate hit rate: `cache.hit / (cache.hit + cache.miss)` + - Target: >90% for node cache, >80% for free list cache + - Low hit rates may indicate insufficient cache size + +2. **Memory Management**: + - Monitor `space.reused` vs `space.from_end` ratio + - High `space.from_end` indicates database growth + - High `space.wasted` suggests fragmentation issues + +3. **Active Revisions**: + - `active_revisions` approaching `max_revisions` triggers cleanup + - Sustained high values may indicate memory pressure + +### Debugging + +1. **Failed Operations**: + - Check metrics with `success=false` label + - Correlate with error logs for root cause analysis + +2. **Ring Buffer Backpressure**: + - `ring.full` counter increasing indicates persistence bottleneck + - May require tuning of flush parameters or disk subsystem + +3. **Insert/Remove Patterns**: + - `firewood.insert` labels show trie structure evolution + - High `split` counts indicate complex key distributions + - Remove `nonexistent` suggests application-level issues + +## Example Monitoring Queries + +For Prometheus-based monitoring (note: metric names use underscores in queries): + +```promql +# Average commit latency over 5 minutes +rate(firewood_proposal_commit_ms[5m]) / rate(firewood_proposal_commit[5m]) + +# Cache hit rate +sum(rate(firewood_cache_node{type="hit"}[5m])) / +sum(rate(firewood_cache_node[5m])) + +# Database growth rate (bytes/sec) +rate(firewood_space_from_end[5m]) + +# Failed commit ratio +rate(firewood_proposal_commit{success="false"}[5m]) / +rate(firewood_proposal_commit[5m]) +``` diff --git a/firewood/README.docker.md b/firewood/README.docker.md new file mode 100644 index 000000000000..4097d9f7395f --- /dev/null +++ b/firewood/README.docker.md @@ -0,0 +1,82 @@ +# Docker on Mac Compatibility + +Note: +Docker compatiblitiy is a work in progress. Please PR any changes here if you find a better way to do this. + +## Steps + +### Step 1 + +Install docker-desktop ([guide](https://docs.docker.com/desktop/install/mac-install/)) + +### Step 2 + +Setup a dev-environment ([guide](https://docs.docker.com/desktop/dev-environments/set-up/#set-up-a-dev-environment)) + +Here, you want to specifically pick a local-directory (the repo's directory) + +![image](https://github.com/ava-labs/firewood/assets/3286504/83d6b66d-19e3-4b59-bc73-f67cf68d7329) + +This is best because you can still do all your `git` stuff from the host. + +### Step 3 + +You will need the `Dev Containers` VSCODE extension, authored by Microsoft for this next step. + +Open your dev-environment with VSCODE. Until you do this, the volume might not be properly mounted. If you (dear reader) know of a better way to do this, please open a PR. VSCODE is very useful for its step-by-step debugger, but other than that, you can run whatever IDE you would like in the host environment and just open a shell in the container to run the tests. + +![image](https://github.com/ava-labs/firewood/assets/3286504/88c981cb-42b9-4b99-acec-fbca31cca652) + +### Step 4 + +Open a terminal in vscode OR exec into the container directly as follows + +```sh +# you don't need to do this if you open the terminal from vscode +# the container name here is "firewood-app-1", you should be able to see this in docker-desktop +docker exec -it --privileged -u root firewood-app-1 zsh +``` + +Once you're in the terminal you'll want to install the Rust toolset. You can [find instructions here](https://rustup.rs/) + +**!!! IMPORTANT !!!** + +Make sure you read the output of any commands that you run. `rustup` will likely ask you to `source` a file to add some tools to your `PATH`. + +You'll also need to install all the regular linux dependencies (if there is anything from this list that's missing, please add to this README) + +```sh +apt update +apt install vim +apt install build-essential +apt install protobuf-compiler +``` + +### Step 5 + +**!!! IMPORTANT !!!** + +You need to create a separate `CARGO_TARGET_DIR` that isn't volume mounted onto the host. `VirtioFS` (the default file-system) has some concurrency issues when dealing with sequential writes and reads to a volume that is mounted to the host. You can put a directory here for example: `/root/target`. + +For step-by-step debugging and development directly in the container, you will also **need to make sure that `rust-analyzer` is configured to point to the new target-directory instead of just default**. + +There are a couple of places where this can be setup. If you're a `zsh` user, you should add `export CARGO_TARGET_DIR=/root/target` to either `/root/.zshrc` or `/root/.bashrc`. +After adding the line, don't forget to `source` the file to make sure your current session is updated. + +### Step 6 + +Navigate to `/com.docker.devenvironments.code` and run `cargo test`. If it worked, you are most of the way there! If it did not work, there are a couple of common issues. If the code will not compile, it's possible that your target directory isn't set up properly. Check inside `/root/target` to see if there are any build artifacts. If not, you might need to call `source ~/.zshrc` again (sub in whatever your preferred shell is). + +Now for vscode, you need to configure your `rust-analyzer` in the "remote-environment" (the Docker container). There are a couple of places to do this. First, you want to open `/root/.vscode-server/Machine/settings.json` and make sure that you have the following entry: + +```json +{ + "rust-analyzer.cargo.extraEnv": { + "CARGO_TARGET_DIR": "/root/target" + } +} +``` + +Then, you want to make sure that the terminal that's being used by the vscode instance (for the host system) is the same as your preferred terminal in the container to make sure that things work as expected. [Here are the docs](https://code.visualstudio.com/docs/terminal/profiles) to help you with setting up the proper profile. + +And that should be enough to get your started! Feel free to open an issue if you need any help debugging. diff --git a/firewood/README.md b/firewood/README.md new file mode 100644 index 000000000000..e06489714e34 --- /dev/null +++ b/firewood/README.md @@ -0,0 +1,150 @@ +# Firewood: Compaction-Less Database Optimized for Efficiently Storing Recent Merkleized Blockchain State + +![Github Actions](https://github.com/ava-labs/firewood/actions/workflows/ci.yaml/badge.svg?branch=main) +[![Ecosystem license](https://img.shields.io/badge/License-Ecosystem-blue.svg)](./LICENSE.md) + +> :warning: Firewood is beta-level software. +> The Firewood API may change with little to no warning. + +Firewood is an embedded key-value store, optimized to store recent Merkleized blockchain +state with minimal overhead. Most blockchains, including Avalanche's C-Chain and Ethereum, store their state in Merkle tries to support efficient generation and verification of state proofs. +Firewood is implemented from the ground up to directly store trie nodes on-disk. +Unlike most state management approaches in the field, +it is not built on top of a generic KV store such as LevelDB/RocksDB. +Firewood, like a B+-tree based database, directly uses the trie structure as the index on-disk. +There is no additional “emulation” of the logical trie to flatten out the data structure +to feed into the underlying database that is unaware of the data being stored. +The convenient byproduct of this approach is that iteration is still fast (for serving state sync queries) +but compaction is not required to maintain the index. +Firewood was first conceived to provide a very fast storage layer for the EVM, +but could be used on any blockchain that requires an authenticated state. + +Firewood only attempts to store recent revisions on-disk and will actively clean up unused data when revisions expire. +Firewood keeps some configurable number of previous states in memory and on disk to power state sync and APIs +which may occur at a few roots behind the current state. +To do this, a new root is always created for each revision that can reference either new nodes from this revision or nodes from a prior revision. +When creating a revision, +a list of nodes that are no longer needed are computed and saved to disk in a future-delete log (FDL) as well as kept in memory. +When a revision expires, the nodes that were deleted when it was created are returned to the free space. + +Hashes are not used to determine where a node is stored on disk in the database file. +Instead space for nodes may be allocated from the end of the file, +or from space freed from expired revision. Free space management algorithmically resembles that of traditional heap memory management, with free lists used to track different-size spaces that can be reused. +The root address of a node is simply the disk offset within the database file, +and each branch node points to the disk offset of that other node. + +Firewood guarantees recoverability by not referencing the new nodes in a new revision before they are flushed to disk, +as well as carefully managing the free list during the creation and expiration of revisions. + +## Architecture Diagram + +![architecture diagram](./docs/assets/architecture.svg) + +## Terminology + +- `Revision` - A historical point-in-time state/version of the trie. This + represents the entire trie, including all `Key`/`Value`s at that point + in time, and all `Node`s. +- `View` - This is the interface to read from a `Revision` or a `Proposal`. +- `Node` - A node is a portion of a trie. A trie consists of nodes that are linked + together. Nodes can point to other nodes and/or contain `Key`/`Value` pairs. +- `Hash` - In this context, this refers to the merkle hash for a specific node. +- `Root Hash` - The hash of the root node for a specific revision. +- `Key` - Represents an individual byte array used to index into a trie. A `Key` + usually has a specific `Value`. +- `Value` - Represents a byte array for the value of a specific `Key`. Values can + contain 0-N bytes. In particular, a zero-length `Value` is valid. +- `Key Proof` - A proof that a `Key` exists within a specific revision of a trie. + This includes the hash for the node containing the `Key` as well as all parents. +- `Range Proof` - A proof that consists of two `Key Proof`s, one for the start of + the range, and one for the end of the range, as well as a list of all `Key`/`Value` + pairs in between the two. A `Range Proof` can be validated independently of an + actual database by constructing a trie from the `Key`/`Value`s provided. +- `Change Proof` - A proof that consists of a set of all changes between two + revisions. +- `Put` - An operation for a `Key`/`Value` pair. A put means "create if it doesn't + exist, or update it if it does. A put operation is how you add a `Value` for a + specific `Key`. +- `Delete` - An operation indicating that a `Key` should be removed from the trie. +- `Batch Operation` - An operation of either `Put` or `Delete`. +- `Batch` - An ordered set of `Batch Operation`s. +- `Proposal` - A proposal consists of a base `Root Hash` and a `Batch`, but is not + yet committed to the trie. In Firewood's most recent API, a `Proposal` is required + to `Commit`. +- `Commit` - The operation of applying one or more `Proposal`s to the most recent + `Revision`. + +## Metrics + +Firewood provides comprehensive metrics for monitoring database performance, resource utilization, and operational characteristics. For detailed information about all available metrics, how to enable them, and how to interpret them, see [METRICS.md](METRICS.md). + +## Build + +In order to build firewood, the following dependencies must be installed: + +- `protoc` See [installation instructions](https://grpc.io/docs/protoc-installation/). +- `cargo` See [installation instructions](https://doc.rust-lang.org/cargo/getting-started/installation.html). +- `make` See [download instructions](https://www.gnu.org/software/make/#download) or run `sudo apt install build-essential` on Linux. + +More detailed build instructions, including some scripts, +can be found in the [benchmark setup scripts](benchmark/setup-scripts). + +If you want to build and test the ffi layer for another platform, +you can find those instructions in the [ffi README](ffi/README.md). + +## Ethereum compatibility + +By default, Firewood builds with hashes compatible with [merkledb](https://github.com/ava-labs/avalanchego/tree/master/x/merkledb), +and does not support accounts. +To enable this feature (at the cost of some performance) enable the ethhash [feature flag](https://doc.rust-lang.org/cargo/reference/features.html#command-line-feature-options). + +Enabling this feature +changes the hashing algorithm from [sha256](https://docs.rs/sha2/latest/sha2/type.Sha256.html) +to [keccak256](https://docs.rs/sha3/latest/sha3/type.Keccak256.html), +understands that an "account" is actually just a node in the storage tree at a specific depth with a specific RLP-encoded value, +and computes the hash of the account trie as if it were an actual root. + +It is worth noting that the hash stored as a value inside the account root RLP is not used. +During hash calculations, we know the hash of the children, +and use that directly to modify the value in-place +when hashing the node. +See [replace\_hash](firewood/storage/src/hashers/ethhash.rs) for more details. + +## Run + +Example(s) are in the [examples](firewood/examples) directory, that simulate real world +use-cases. Try running the insert example via the command-line, via `cargo run --release +--example insert`. + +There is a [fwdctl cli](fwdctl) for command-line operations on a database. + +There is also a [benchmark](benchmark) that shows some other example uses. + +For maximum runtime performance at the cost of compile time, +use `cargo run --maxperf` instead, +which enables maximum link time compiler optimizations. + +## Logging + +If you want logging, enable the `logging` feature flag, and then set RUST\_LOG accordingly. +See the documentation for [env\_logger](https://docs.rs/env_logger/latest/env_logger/) for specifics. +We currently have very few logging statements, but this is useful for print-style debugging. + +## Release + +See the [release documentation](./RELEASE.md) for detailed information on how to release Firewood. + +## CLI + +Firewood comes with a CLI tool called `fwdctl` that enables one to create and interact with a local instance of a Firewood database. For more information, see the [fwdctl README](fwdctl/README.md). + +## Test + +```sh +cargo test --release +``` + +## License + +Firewood is licensed by the Ecosystem License. For more information, see the +[LICENSE file](./LICENSE.md). diff --git a/firewood/RELEASE.md b/firewood/RELEASE.md new file mode 100644 index 000000000000..c037539d8a91 --- /dev/null +++ b/firewood/RELEASE.md @@ -0,0 +1,177 @@ +# Releasing firewood + +Releasing firewood is straightforward and can mostly be done in CI. Updating the +Cargo.toml file is currently manual. + +Firewood is made up of several sub-projects in a workspace. Each project is in +its own crate and has an independent version. + +## Workspace Dependencies + +Ensure the following tools are installed before beginning: + +```shell +cargo install --locked git-cliff cargo-edit +``` + +## Git Branch + +Before making changes, create a new branch (if not already on one): + +```console +$ git fetch +$ git switch -c release/v0.0.16 origin/main +branch 'release/v0.0.16' set up to track 'origin/main'. +Switched to a new branch 'release/v0.0.16' +``` + +If already on a new branch, ensure `HEAD` is the same as the remote's `main`. +As the upstream repo changes, rebase the branch onto `main` so that the changes +from `git cliff` follow the repository history in the correct linear order. + +## Dependency upgrades + +### Rust MSRV + +Optionally, the minimum supported rust version can be bumped. See + for the latest version. Best +effort 2 releases behind the current latest stable [^1]. However, Rust evolves +fairly quickly and we occasionally want to take advantage of a new improvement +before the stable release matures. + +Updating the Rust MSRV requires edits in two places: + +- [clippy.toml] + - Update the root `msrv` setting to indicate the set MSRV. This configures + clippy to include newer lints that would otherwise be incorrect with a lower + MSRV; such as recommending newly stablized features that were unstable in + the older release. +- [Cargo.toml] + - Update `workspace.package.rust-version` which will propagate through the + other cargo packages that have `package.rust-version.workspace = true` set. + +[^1]: e.g., with 1.91 stable, 1.89 is the best effort MSRV + +### Cargo Dependencies + +```shell +cargo upgrade # installed through cargo-edit above +cargo upgrade --incompatible # may require fixes; if too many fixes are needed, split into a separate PR +cargo update --verbose # ensure lockfile is up-to-date with all changes +cargo test --workspace --all-targets +cargo test --workspace --all-targets -F ethhash +``` + +### Go Dependencies + +Go dependencies are updated on an as-needed basis, usually for security. + +## Package Version + +Next, update the workspace version and ensure all crates within the firewood +project are using the version of the new release. The root [Cargo.toml](Cargo.toml) +file uses the [`[workspace.package]`](https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table) +table to define the version for all subpackages. + +```toml +[workspace.package] +version = "0.0.16" +``` + +Each package inherits this version by setting `package.version.workspace = true`. + +```toml +[package] +name = "firewood" +version.workspace = true +``` + +Therefore, updating only the version defined in the root config is needed. + +## Dependency Version + +`cargo publish` for each package requires that each dependency specify _a_ version; +therefore, the next step is to bump the dependency declarations to the new version. +Packages within the workspace that are used as libraries are also defined within +the [`[workspace.dependencies]`](https://doc.rust-lang.org/cargo/reference/workspaces.html#the-dependencies-table) +table. E.g.,: + +```toml +[workspace.dependencies] +# workspace local packages +firewood = { path = "firewood", version = "0.0.16" } +``` + +This allows packages within the workspace to inherit the dependency, +including path, version, and workspace-level features by adding `workspace = true` +to the dependency table (note: using `cargo add -p firewood-fwdctl firewood-metrics` +would automatically add the dependency with `workspace = true`). + +```toml +[dependencies] +firewood-macros.workspace = true + +# more complex example +[target.'cfg(target_os = "linux")'.dependencies] +firewood-storage = { workspace = true, features = ["io-uring"] } + +[target.'cfg(not(target_os = "linux"))'.dependencies] +firewood-storage.workspace = true +``` + +Thefefore, after updating the `workspace.package.version` value, we must update +the dependency versions to match. + +Run `cargo update` after editing the `Cargo.toml` files to ensure the lockfile +is correct and reflects the new package versions. + +## Changelog + +To build the changelog, see git-cliff.org. Short version: + +```sh +git cliff --tag v0.0.16 -o CHANGELOG.md +``` + +## Commit + +Commit the version bump and change log updates. Using the summary prefix: + +> chore(release): prepare for + +will cause `git-cliff` to omit the commit from the changelog. This is why +substantive changes when upgrading dependencies should be in their own commit. +If you do not use the prefix, there will be an egg-and-chicken problem as the +commit message generated by GitHub includes the pull request as a suffix. +Manually resolve this in the CHANGELOG if needed; otherwise, the CHANGELOG will +have irrelevant changes on future releases. + +## Review + +> ❗ Be sure to update the versions of all sub-projects before creating a new +> release. Open a PR with the updated versions and merge it before continuing to +> the next step. + +## Publish + +To trigger a release, push a tag to the main branch matching the new version, + +```sh +# be sure to switch back to the main branch before tagging +git checkout main +git pull --prune +git tag -s -a v0.0.16 -m 'Release v0.0.16' +git push origin v0.0.16 +``` + +for `v0.0.16` for the merged version change. The CI will automatically publish a +draft release which consists of release notes and changes (see +[.github/workflows/release.yaml](.github/workflows/release.yaml)). + +## Milestone + +> NOTE: this should be automated as well. + +Close the GitHub milestone for the version that was released. Be sure to create +a new milestone for the next version if one does not already exist. Carry over +any incomplete tasks to the next milestone. diff --git a/firewood/benchmark/Cargo.toml b/firewood/benchmark/Cargo.toml new file mode 100644 index 000000000000..962868bc5605 --- /dev/null +++ b/firewood/benchmark/Cargo.toml @@ -0,0 +1,64 @@ +[package] +name = "firewood-benchmark" +version.workspace = true +edition.workspace = true +authors = [ + "Aaron Buchwald ", + "Ron Kuris ", +] +description = "Benchmarking tool for Firewood, an embedded key-value store optimized for blockchain state." +license-file.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true + +[package.metadata.cargo-machete] +ignored = ["opentelemetry-proto"] + +[[bin]] +name = "benchmark" +path = "src/main.rs" + +[dependencies] +# Workspace dependencies +clap = { workspace = true, features = ['string'] } +env_logger.workspace = true +fastrace = { workspace = true, features = ["enable"] } +firewood.workspace = true +firewood-storage = { workspace = true, features = ["test_utils"] } +hex.workspace = true +log.workspace = true +metrics.workspace = true +metrics-util = { workspace = true, optional = true } +rand.workspace = true +rand_distr.workspace = true +sha2.workspace = true +# Regular dependencies +fastrace-opentelemetry = { version = "=0.14.0" } +metrics-exporter-prometheus = { version = "0.17.2", optional = true } +opentelemetry = "=0.31.0" +opentelemetry-otlp = { version = "=0.31.0", features = ["grpc-tonic"] } +opentelemetry-proto = "=0.31.0" +opentelemetry_sdk = "=0.31.0" +pretty-duration = "0.1.1" + +[dependencies.tokio] +optional = true +version = "1.48.0" +features = ["mio", "net", "parking_lot", "rt", "time"] + +[target.'cfg(unix)'.dependencies] +tikv-jemallocator = "0.6.1" + +[features] +default = ["prometheus"] +logger = ["firewood/logger"] +prometheus = [ + "dep:metrics-exporter-prometheus", + "dep:metrics-util", + "dep:tokio", +] + +[lints] +workspace = true diff --git a/firewood/benchmark/Grafana-dashboard.json b/firewood/benchmark/Grafana-dashboard.json new file mode 100644 index 000000000000..e29741a71941 --- /dev/null +++ b/firewood/benchmark/Grafana-dashboard.json @@ -0,0 +1,851 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 10, + "panels": [], + "title": "Cache", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 1 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "rate(firewood_cache_node{type=\"miss\", mode!=\"open\"}[$__rate_interval])", + "fullMetaSearch": false, + "includeNullMetadata": false, + "instant": false, + "legendFormat": "{{mode}}", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Node cache misses (read+deserialize)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "max": 100, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 1 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "100 * sum(increase(firewood_cache_node{type=\"hit\"}[$__rate_interval])) by (name) / sum(increase(firewood_cache_node[$__rate_interval])) by (name)", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "node", + "range": true, + "refId": "A", + "useBackend": false + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "100 * sum(increase(firewood_cache_freelist{type=\"hit\"}[$__rate_interval])) by (name) / sum(increase(firewood_cache_freelist[$__rate_interval])) by (name)", + "hide": false, + "instant": false, + "legendFormat": "freelist", + "range": true, + "refId": "B" + } + ], + "title": "Cache hit rate", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 9 + }, + "id": 9, + "panels": [], + "title": "Throughput", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 11, + "x": 0, + "y": 10 + }, + "id": 8, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.1", + "targets": [ + { + "editorMode": "code", + "expr": "firewood_proposals", + "legendFormat": "__auto", + "range": true, + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + } + } + ], + "title": "Proposals Submitted (Blocks Processed)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 25, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 13, + "x": 11, + "y": 10 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "min", + "max", + "mean", + "last" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "irate(firewood_remove[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Remove {prefix=\"{{prefix}}\"}", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "sum(irate(firewood_insert{merkle!=\"update\"}[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "Insert", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "irate(firewood_insert{merkle=\"update\"}[$__rate_interval])", + "hide": false, + "instant": false, + "legendFormat": "Update", + "range": true, + "refId": "A" + } + ], + "title": "Operation Rate", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 11, + "panels": [], + "title": "Internals", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "disableTextWrap": false, + "editorMode": "code", + "expr": "sum(firewood_cache_node) / sum(firewood_insert)", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Reads per insert", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 11, + "x": 12, + "y": 23 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.1", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "editorMode": "code", + "expr": "node_memory_Dirty_bytes", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Dirty bytes (OS pending write to disk)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 31 + }, + "id": 12, + "options": { + "legend": { + "calcs": [ + "min", + "mean", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.5.1", + "targets": [ + { + "editorMode": "code", + "expr": "irate(firewood_insert[$__rate_interval])", + "legendFormat": "merkle=\"{{merkle}}\"", + "range": true, + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${datasource}" + } + } + ], + "title": "Insert Merkle Ops by Type", + "type": "timeseries" + } + ], + "refresh": "10s", + "schemaVersion": 40, + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Prometheus", + "value": "prometheus" + }, + "includeAll": false, + "label": "Data Source", + "name": "datasource", + "options": [], + "query": "prometheus", + "refresh": 1, + "regex": "", + "type": "datasource" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Firewood Dashboard", + "uid": "adxfhfmwx5ypsc", + "version": 12, + "weekStart": "" +} \ No newline at end of file diff --git a/firewood/benchmark/README.md b/firewood/benchmark/README.md new file mode 100644 index 000000000000..453775c2530c --- /dev/null +++ b/firewood/benchmark/README.md @@ -0,0 +1,172 @@ +# Firewood Benchmark + +Welcome to the Firewood Benchmark! This repository contains the benchmarking +code and resources for the Firewood project. + +## Table of Contents + +- [Introduction](#introduction) +- [Benchmark Description](#benchmark-description) +- [Installation](#installation) +- [Usage](#usage) + +## Introduction + +The Firewood Benchmark is a performance testing suite designed to evaluate the performance of the Firewood project. It includes a set of benchmarks that measure various aspects of the project's performance, such as execution time, memory usage, and scalability. + +## Benchmark Description + +There are currently three different benchmarks, as follows: + +1. `tenkrandom` which does transactions of size 10k, 5k updates, 2.5k inserts, and 2.5k deletes +2. `zipf` which uses a zipf distribution across the database to perform updates +3. `single` which only updates a single row (row 1) repeatedly in a tiny transaction + +There is also a `create` benchmark which creates the database to begin with. The defaults will create +a 10M row database. If you want a larger one, increase the number of batches. + +## Benchmark Specification + +This describes each benchmark in detail, and forms a standard for how to test merkle databases. The pseudo-code for each +benchmark is provided. + +Note that the `commit` operation is expected to persist the database and compute the root hash for each merkle. + +### create + +Inserts are done starting from an empty database, 10,000 rows at a time, starting with row id 0 and increasing by 1 for each row. +The key and data consist of the SHA-256 of the row id, in native endian format. + +```rust + for key in (0..N) { + let key_and_data = sha256(key.to_ne_bytes()); + testdb.insert(key_and_data, key_and_data); + if key % 10000 == 9999 { + testdb.commit(); + } + } +``` + +Exception: when creating the 1B row database, 100,000 rows at a time are added. + +### tenkrandom + +This test uses two variables, low and high, which initially start off at 0 and N, where N is the number of rows in the database. +A batch consists of deleting 2,500 rows from low to low+2499, 2,500 new insertions from high to high+2499, and 5,000 updates from (low+high)/2 to (low+high)/2+4999. The key is computed based on the sha256 as when the database is created, but the data is set to the sha256 of the value of 'low', to ensure that the data is updated. Once a batch is completed, low and high are increased by 2,500. + +```rust + let low = 0; + let high = N; + loop { + let hashed_low = sha256(low.to_ne_bytes()); + for key in (low..low+2499) { + testdb.delete(hashed_key); + let hashed_key = sha256(key.to_ne_bytes()); + } + for key in (high..high+2499) { + let hashed_key = sha256(key.to_ne_bytes()); + testdb.insert(hashed_key, hashed_low); + } + for key in ((low+high)/2, (low+high)/2+4999) { + let hashed_key = sha256(key.to_ne_bytes()); + testdb.upsert(hashed_key, hashed_low); + } + testdb.commit(); + } +``` + +### zipf + +A zipf distribution with an exponent of 1.2 on the total number of inserted rows is used to compute which rows to update with a batch of 10,000 rows. Note that this results in duplicates -- the duplicates are passed to the database for resolution. + +```rust + for id in (0..N) { + let key = zipf(1.2, N); + let hashed_key = sha256(key.to_ne_bytes()); + let hashed_data = sha256(id.to_ne_bytes()); + testdb.upsert(hashed_key, hashed_data); + if id % 10000 == 9999 { + testdb.commit(); + } + } + +``` + +### single + +This test repeatedly updates the first row. + +```rust + let hashed_key = sha256(0.to_ne_bytes()); + for id in (0..) { + let hashed_data = sha256(id.to_ne_bytes()); + testdb.upsert(hashed_key, hashed_data); + testdb.commit(); + } +``` + +## Installation + +To install the Firewood Benchmark, follow these steps: + +1. Install the build prerequisites: `sudo bash setup-scripts/build-environment.sh` +2. \[Optional\] Install grafana: `sudo bash setup-scripts/install-grafana.sh` +3. Build firewood: `bash setup-scripts/build-firewood.sh` +4. Create the benchmark database: `nohup time cargo run --profile maxperf --bin benchmark -- create`. For a larger database, add `--number-of-batches=10000` before the subcommand 'create' for a 100M row database (each batch by default is 10K rows). Additional options are documented in setup-scripts/run-benchmarks.sh + +If you want to install grafana and prometheus on an AWS host (using Ubuntu as a base), do the following: + +1. Log in to the AWS EC2 console +2. Launch a new instance: + 1. Name: Firewood Benchmark + 2. Click on 'Ubuntu' in the quick start section + 3. Set the instance type to m5d.2xlarge + 4. Set your key pair + 5. Open SSH, HTTP, and port 3000 so prometheus can be probed remotely (we use a 'firewood-bench' security group) + 6. Configure storage to 20GiB disk + 7. \[optional] Save money by selecting 'spot instance' in advanced + 8. Launch the instance +3. ssh ubuntu@AWS-IP +4. Run the scripts as described above, including the grafana installation. +5. Log in to Grafana at + a. Username: `admin`, password: `firewood_is_fast` +6. A Prometheus data source, the Firewood dashboard, and a [system statistics dashboard](https://grafana.com/grafana/dashboards/1860-node-exporter-full/) are preconfigured and ready to use. + +### Updating the dashboard + +If you want to update the dashboard and commit it, do not enable "Export for sharing externally" when exporting. These dashboards are provisioned and reference the default Prometheus data source, with the option to pick from available data sources. + +## Usage + +Since the benchmark is in two phases, you may want to create the database first and then +examine the steady-state performance second. This can easily be accomplished with a few +command line options. + +To create test databases, use the following command: + +```sh + nohup time cargo run --profile maxperf --bin benchmark -- -n 10000 create +``` + +Then, you can look at nohup.out and see how long the database took to initialize. Then, to run +the second phase, use: + +```sh + nohup time cargo run --profile maxperf --bin benchmark -- -n 10000 zipf +``` + +If you're looking for detailed logging, there are some command line options to enable it. For example, to enable debug logging for the single benchmark, you can use the following: + +```sh + cargo run --profile release --bin benchmark -- -l debug -n 10000 single +``` + +## Using opentelemetry + +To use the opentelemetry server and record timings, just run a docker image that collects the data using: + +```sh +docker run -p 127.0.0.1:4318:4318 -p 127.0.0.1:55679:55679 otel/opentelemetry-collector-contrib:0.97.0 2>&1 +``` + +Then, pass the `-e` option to the benchmark. diff --git a/firewood/benchmark/bootstrap/README.md b/firewood/benchmark/bootstrap/README.md new file mode 100644 index 000000000000..ac35a7c08fb1 --- /dev/null +++ b/firewood/benchmark/bootstrap/README.md @@ -0,0 +1,81 @@ +# Bootstrap Testing Script + +This directory contains tools for automated Firewood blockchain database benchmarking on AWS. The `aws-launch.sh` script creates EC2 instances, sets up the complete testing environment, and executes C-chain (Avalanche) block bootstrapping tests. + +## Prerequisites + +Before running the script, you'll need: + +- AWS CLI installed and configured on your machine +- Authenticated AWS session: `aws sso login` + - Your session should be configured to use the `Experimental` account. + +## What It Does + +The `aws-launch.sh` script automatically: + +1. Launches an EC2 instance with the specified instance type and configuration +2. Sets up the environment with all necessary dependencies (Git, Rust, Go, build tools, Grafana) +3. Creates user accounts with SSH access for the team +4. Clones and builds: + - Firewood (from specified branch or default) + - AvalancheGo (from specified branch or default) + - Coreth (from specified branch or default) + - LibEVM (from specified branch or default) +5. Downloads pre-existing blockchain data from S3 (1M, 10M, or 50M blocks) +6. Executes the bootstrapping benchmark to test Firewood's performance + +## Usage + +```bash +./aws-launch.sh [OPTIONS] +``` + +For a complete list of options, run: + +```bash +./aws-launch.sh --help +``` + +## Examples + +### Run a large benchmark with spot pricing + +```bash +./aws-launch.sh --instance-type i4i.xlarge --nblocks 10m --spot +``` + +### Test multiple component branches together + +```bash +./aws-launch.sh --firewood-branch my-firewood-branch --avalanchego-branch develop --coreth-branch foo --libevm-branch bar +``` + +### Preview a configuration without launching + +```bash +./aws-launch.sh --dry-run --firewood-branch my-branch --nblocks 1m +``` + +## Monitoring Results + +After launching, the script outputs an instance ID. You can: + +1. **SSH to the instance** - Only authorized team members (rkuris, austin, aaron, brandon, amin, bernard, rodrigo) can SSH using their configured GPG hardware keys. Note: Your GPG agent must be properly configured for SSH support on your local machine. + + ```bash + ssh @ + ``` + +2. **Monitor benchmark progress**: + + ```bash + tail -f /var/log/bootstrap.log + ``` + +3. **Check build logs**: + + ```bash + tail -f /mnt/nvme/ubuntu/firewood/build.log + tail -f /mnt/nvme/ubuntu/avalanchego/build.log + ``` diff --git a/firewood/benchmark/bootstrap/aws-launch.sh b/firewood/benchmark/bootstrap/aws-launch.sh new file mode 100755 index 000000000000..b4645ac2561a --- /dev/null +++ b/firewood/benchmark/bootstrap/aws-launch.sh @@ -0,0 +1,492 @@ +#!/usr/bin/env bash +set +e + +# Default values +INSTANCE_TYPE=i4g.large +FIREWOOD_BRANCH="" +AVALANCHEGO_BRANCH="" +CORETH_BRANCH="" +LIBEVM_COMMIT="" +NBLOCKS="1m" +CONFIG="firewood" +REGION="us-west-2" +DRY_RUN=false +SPOT_INSTANCE=false + +# Valid instance types and their architectures +declare -A VALID_INSTANCES=( + ["i4g.large"]="arm64" + ["i4g.xlarge"]="arm64" + ["i4i.large"]="amd64" + ["i4i.xlarge"]="amd64" + ["m6id.xlarge"]="amd64" + ["c6gd.2xlarge"]="arm64" + ["x2gd.xlarge"]="arm64" + ["m5ad.2xlarge"]="arm64" + ["r6gd.2xlarge"]="arm64" + ["r6id.2xlarge"]="amd64" + ["x2gd.2xlarge"]="arm64" + ["z1d.2xlarge"]="amd64" + ["i8ge.12xlarge"]="arm64" +) + +# Maximum spot prices for each instance type (from the pricing table) +declare -A MAX_SPOT_PRICES=( + ["i4g.large"]="0.1544" + ["i4g.xlarge"]="0.3088" + ["i4i.large"]="0.1720" + ["i4i.xlarge"]="0.3440" + ["m6id.xlarge"]="0.2373" + ["c6gd.2xlarge"]="0.3072" + ["x2gd.xlarge"]="0.3340" + ["m5ad.2xlarge"]="0.4120" + ["r6gd.2xlarge"]="0.4608" + ["r6id.2xlarge"]="0.6048" + ["x2gd.2xlarge"]="0.6680" + ["z1d.2xlarge"]="0.7440" + ["i8ge.12xlarge"]="5.6952" +) + +# Valid nblocks values +VALID_NBLOCKS=("1m" "10m" "50m") + +# Function to show usage +show_usage() { + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --instance-type TYPE EC2 instance type (default: i4g.large)" + echo " --firewood-branch BRANCH Firewood git branch to checkout" + echo " --avalanchego-branch BRANCH AvalancheGo git branch to checkout" + echo " --coreth-branch BRANCH Coreth git branch to checkout" + echo " --libevm-commit COMMIT LibEVM git commit to checkout" + echo " --nblocks BLOCKS Number of blocks to download (default: 1m)" + echo " --config CONFIG The VM reexecution config to use (default: firewood)" + echo " --region REGION AWS region (default: us-west-2)" + echo " --spot Use spot instance pricing (default depends on instance type)" + echo " --dry-run Show the aws command that would be run without executing it" + echo " --help Show this help message" + echo "" + echo "Valid instance types:" + echo " # name Type disk vcpu memory $/hr notes" + echo " i4g.large arm64 468 2 16 GiB \$0.1544 Graviton2-powered" + echo " i4i.large amd64 468 2 16 GiB \$0.1720 Intel Xeon Scalable" + echo " m6id.xlarge arm64 237 4 16 GiB \$0.2373 Intel Xeon Scalable" + echo " c6gd.2xlarge arm64 474 8 16 GiB \$0.3072 Graviton2 compute-optimized" + echo " i4g.xlarge arm64 937 4 32 GiB \$0.3088 Graviton2-powered" + echo " i4i.xlarge amd64 937 4 32 GiB \$0.3440 Intel Xeon Scalable" + echo " x2gd.xlarge arm64 237 4 64 GiB \$0.3340 Graviton2 memory-optimized" + echo " m5ad.2xlarge arm64 300 8 32 GiB \$0.4120 AMD EPYC processors" + echo " r6gd.2xlarge arm64 474 8 64 GiB \$0.4608 Graviton2 memory-optimized" + echo " r6id.2xlarge amd64 474 8 64 GiB \$0.6048 Intel Xeon Scalable" + echo " x2gd.2xlarge arm64 475 8 128 GiB \$0.6680 Graviton2 memory-optimized" + echo " z1d.2xlarge amd64 300 8 64 GiB \$0.7440 High-frequency Intel Xeon CPUs" + echo " i8ge.12xlarge arm64 11250 48 384 GiB \$5.5952 Careful, very expensive" + echo "" + echo "Valid nblocks values: ${VALID_NBLOCKS[*]}" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --instance-type) + INSTANCE_TYPE="$2" + if [[ ! ${VALID_INSTANCES[$INSTANCE_TYPE]+_} ]]; then + echo "Error: Invalid instance type '$INSTANCE_TYPE'" + echo "Valid types: ${!VALID_INSTANCES[*]}" + exit 1 + fi + shift 2 + ;; + --firewood-branch) + FIREWOOD_BRANCH="$2" + shift 2 + ;; + --avalanchego-branch) + AVALANCHEGO_BRANCH="$2" + shift 2 + ;; + --coreth-branch) + CORETH_BRANCH="$2" + shift 2 + ;; + --libevm-commit) + LIBEVM_COMMIT="$2" + shift 2 + ;; + --nblocks) + NBLOCKS="$2" + # Validate nblocks value + if [[ ! " ${VALID_NBLOCKS[*]} " =~ [[:space:]]${NBLOCKS}[[:space:]] ]]; then + echo "Error: Invalid nblocks value '$NBLOCKS'" + echo "Valid values: ${VALID_NBLOCKS[*]}" + exit 1 + fi + shift 2 + ;; + --config) + CONFIG="$2" + shift 2 + ;; + --region) + REGION="$2" + shift 2 + ;; + --spot) + SPOT_INSTANCE=true + shift + ;; + --dry-run) + DRY_RUN=true + shift + ;; + --help) + show_usage + exit 0 + ;; + *) + echo "Error: Unknown option $1" + show_usage + exit 1 + ;; + esac +done + +# Set architecture type based on instance type +TYPE=${VALID_INSTANCES[$INSTANCE_TYPE]} + +echo "Configuration:" +echo " Instance Type: $INSTANCE_TYPE ($TYPE)" +echo " Firewood Branch: ${FIREWOOD_BRANCH:-default}" +echo " AvalancheGo Branch: ${AVALANCHEGO_BRANCH:-default}" +echo " Coreth Branch: ${CORETH_BRANCH:-default}" +echo " LibEVM Commit: ${LIBEVM_COMMIT:-default}" +echo " Number of Blocks: $NBLOCKS" +echo " Config: $CONFIG" +echo " Region: $REGION" +if [ "$SPOT_INSTANCE" = true ]; then + echo " Spot Instance: Yes (max price: \$${MAX_SPOT_PRICES[$INSTANCE_TYPE]})" +else + echo " Spot Instance: No" +fi +if [ "$DRY_RUN" = true ]; then + echo " Mode: DRY RUN (will not launch instance)" +fi +echo "" + +if [ "$DRY_RUN" = true ]; then + # For dry run, use placeholder values + AMI_ID="ami-placeholder" + USERDATA="base64-encoded-userdata-placeholder" +else + # find the latest ubuntu-noble base image ID (only works for intel processors) + AMI_ID=$(aws ec2 describe-images \ + --region "$REGION" \ + --owners 099720109477 \ + --filters "Name=name,Values=ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-$TYPE-server-*" \ + "Name=state,Values=available" \ + --query "Images | sort_by(@, &CreationDate)[-1].ImageId" \ + --output text) + export AMI_ID +fi + +if [ "$DRY_RUN" = false ]; then + # Prepare branch arguments for cloud-init +FIREWOOD_BRANCH_ARG="" +AVALANCHEGO_BRANCH_ARG="" +CORETH_BRANCH_ARG="" + +if [ -n "$FIREWOOD_BRANCH" ]; then + FIREWOOD_BRANCH_ARG="--branch $FIREWOOD_BRANCH" +fi +if [ -n "$AVALANCHEGO_BRANCH" ]; then + AVALANCHEGO_BRANCH_ARG="--branch $AVALANCHEGO_BRANCH" +fi +if [ -n "$CORETH_BRANCH" ]; then + CORETH_BRANCH_ARG="--branch $CORETH_BRANCH" +fi + +# For libevm, default to main branch if no commit specified +LIBEVM_COMMIT_CHECKOUT="${LIBEVM_COMMIT:-main}" + +# set up this script to run at startup, installing a few packages, creating user accounts, +# and downloading the blocks for the C-chain +USERDATA_TEMPLATE=$(cat <<'END_HEREDOC' +#cloud-config +package_update: true +package_upgrade: true +packages: + - git + - build-essential + - curl + - protobuf-compiler + - make + - apt-transport-https + - net-tools + - unzip +users: + - default + - name: rkuris + lock_passwd: true + groups: users, adm, sudo + shell: /usr/bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL2RVmfpoKYi0tJd2DhQEp8tB3m2PSuaYxIfnLwqt03u cardno:23_537_110 ron + - name: austin + lock_passwd: true + groups: users, adm, sudo + shell: /usr/bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICoGgX8nCin3FPc1V3YYN1M9g039wMbzZSAXZJCqzBt3 cardno:31_786_961 austin + - name: aaron + lock_passwd: true + groups: users, adm, sudo + shell: /usr/bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMj2j6ySwsFx7Y6FW2UXlkjCZfFDQKHWh0GTBjkK9ruV cardno:19_236_959 aaron + - name: brandon + lock_passwd: true + groups: users, adm, sudo + shell: /usr/bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFuwpEMnsBLdfr7V9SFRTm9XWHEFX3yQQP7nmsFHetBo cardno:26_763_547 brandon + - name: amin + lock_passwd: true + groups: users, adm, sudo + shell: /usr/bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE8iR1X8/ELrzjczZvCkrTGCEoN6/dtlP01QFGuUpYxV cardno:33_317_839 amin + - name: bernard + lock_passwd: true + groups: users, adm, sudo + shell: /usr/bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE/1C8JVL0g6qqMw1p0TwJMqJqERxYTX+7PnP+gXP4km cardno:19_155_748 bernard + - name: rodrigo + lock_passwd: true + groups: users, adm, sudo + shell: /usr/bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDT0/IE2kLNpvaELug1zppQGY03z3fe2zOTjyS655Sgq cardno:28_650_437 rodrigo + +swap: + filename: /swapfile + size: 16G + maxsize: 16G + +# anyone can use the -D option +write_files: +- content: | + Defaults runcwd=* + path: "/etc/sudoers.d/91-cloud-init-enable-D-option" + permissions: '0440' +- content: | + export PATH="$PATH:/usr/local/go/bin" + permissions: "0644" + path: "/etc/profile.d/go_path.sh" +- content: | + export RUSTUP_HOME=/usr/local/rust + export PATH="$PATH:/usr/local/rust/bin" + permissions: "0644" + path: "/etc/profile.d/rust_path.sh" + +runcmd: + # install rust + - echo 'PATH=/usr/local/go/bin:$HOME/.cargo/bin:$PATH' >> ~ubuntu/.profile + - > + curl https://sh.rustup.rs -sSf + | RUSTUP_HOME=/usr/local/rust CARGO_HOME=/usr/local/rust + sh -s -- -y --no-modify-path + - sudo -u ubuntu --login rustup default stable + # install firewood + - git clone --depth 1 __FIREWOOD_BRANCH_ARG__ https://github.com/ava-labs/firewood.git /tmp/firewood + - bash /tmp/firewood/benchmark/setup-scripts/build-environment.sh + - bash -c 'mkdir ~ubuntu/firewood; mv /tmp/firewood/{.[!.],}* ~ubuntu/firewood/' + # fix up the directories so that anyone is group 'users' has r/w access + - chown -R ubuntu:users /mnt/nvme/ubuntu + - chmod -R g=u /mnt/nvme/ubuntu + - find /mnt/nvme/ubuntu -type d -print0 | xargs -0 chmod g+s + # helpful symbolic links from home directories + - sudo -u ubuntu ln -s /mnt/nvme/ubuntu/data /home/ubuntu/data + - sudo -u ubuntu ln -s /mnt/nvme/ubuntu/avalanchego /home/ubuntu/avalanchego + # install go and grafana + - bash /mnt/nvme/ubuntu/firewood/benchmark/setup-scripts/install-golang.sh + - bash /mnt/nvme/ubuntu/firewood/benchmark/setup-scripts/install-grafana.sh + # install task, avalanchego, coreth + - snap install task --classic + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu + git clone --depth 100 __AVALANCHEGO_BRANCH_ARG__ https://github.com/ava-labs/avalanchego.git + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu + git clone --depth 100 __CORETH_BRANCH_ARG__ https://github.com/ava-labs/coreth.git + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu + git clone https://github.com/ava-labs/libevm.git + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu/libevm + git checkout __LIBEVM_COMMIT__ + # force coreth to use the checked-out versions of libevm and firewood + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu/coreth + /usr/local/go/bin/go mod edit -replace + github.com/ava-labs/firewood-go-ethhash/ffi=../firewood/ffi + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu/coreth + /usr/local/go/bin/go mod edit -replace + github.com/ava-labs/libevm=../libevm + # force avalanchego to use the checked-out versions of coreth, libevm, and firewood + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu/avalanchego + /usr/local/go/bin/go mod edit -replace + github.com/ava-labs/firewood-go-ethhash/ffi=../firewood/ffi + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu/avalanchego + /usr/local/go/bin/go mod edit -replace + github.com/ava-labs/coreth=../coreth + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu/avalanchego + /usr/local/go/bin/go mod edit -replace + github.com/ava-labs/libevm=../libevm + # build firewood in maxperf mode + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu/firewood/ffi --login time cargo build + --profile maxperf + --features ethhash,logger + > /mnt/nvme/ubuntu/firewood/build.log 2>&1 + # run go mod tidy for coreth and avalanchego + - sudo -u ubuntu --login -D /mnt/nvme/ubuntu/coreth go mod tidy + - sudo -u ubuntu --login -D /mnt/nvme/ubuntu/avalanchego go mod tidy + # build avalanchego + - > + sudo -u ubuntu --login -D /mnt/nvme/ubuntu/avalanchego time scripts/build.sh + > /mnt/nvme/ubuntu/avalanchego/build.log 2>&1 & + # install s5cmd + - curl -L -o /tmp/s5cmd.deb $(curl -s https://api.github.com/repos/peak/s5cmd/releases/latest | grep "browser_download_url" | grep "linux_$(dpkg --print-architecture).deb" | cut -d '"' -f 4) && dpkg -i /tmp/s5cmd.deb + # download and extract mainnet blocks + - echo 'downloading mainnet blocks' + - sudo -u ubuntu mkdir -p /mnt/nvme/ubuntu/exec-data/blocks + - s5cmd cp s3://avalanchego-bootstrap-testing/cchain-mainnet-blocks-__NBLOCKS__-ldb/\* /mnt/nvme/ubuntu/exec-data/blocks/ >/dev/null + - chown -R ubuntu /mnt/nvme/ubuntu/exec-data + - chmod -R g=u /mnt/nvme/ubuntu/exec-data + # execute bootstrapping + - > + sudo -u ubuntu -D /mnt/nvme/ubuntu/avalanchego --login + time task reexecute-cchain-range CURRENT_STATE_DIR=/mnt/nvme/ubuntu/exec-data/current-state BLOCK_DIR=/mnt/nvme/ubuntu/exec-data/blocks START_BLOCK=1 END_BLOCK=__END_BLOCK__ CONFIG=__CONFIG__ METRICS_ENABLED=false + > /var/log/bootstrap.log 2>&1 +END_HEREDOC +) + +# Convert nblocks to actual end block number +case $NBLOCKS in + "1m") END_BLOCK="1000000" ;; + "10m") END_BLOCK="10000000" ;; + "50m") END_BLOCK="50000000" ;; + *) END_BLOCK="1000000" ;; # Default fallback +esac + +# Substitute branch arguments and block values in the userdata template +USERDATA=$(echo "$USERDATA_TEMPLATE" | \ + sed "s|__FIREWOOD_BRANCH_ARG__|$FIREWOOD_BRANCH_ARG|g" | \ + sed "s|__AVALANCHEGO_BRANCH_ARG__|$AVALANCHEGO_BRANCH_ARG|g" | \ + sed "s|__CORETH_BRANCH_ARG__|$CORETH_BRANCH_ARG|g" | \ + sed "s|__LIBEVM_COMMIT__|$LIBEVM_COMMIT_CHECKOUT|g" | \ + sed "s|__NBLOCKS__|$NBLOCKS|g" | \ + sed "s|__END_BLOCK__|$END_BLOCK|g" | \ + sed "s|__CONFIG__|$CONFIG|g" | \ + base64) +export USERDATA + +fi # End of DRY_RUN=false conditional + + +SUFFIX=$(hexdump -vn4 -e'4/4 "%08X" 1 "\n"' /dev/urandom) + +# Build instance name with branch info +INSTANCE_NAME="$USER-fw-$SUFFIX" +if [ -n "$FIREWOOD_BRANCH" ]; then + INSTANCE_NAME="$INSTANCE_NAME-fw-$FIREWOOD_BRANCH" +fi +if [ -n "$AVALANCHEGO_BRANCH" ]; then + INSTANCE_NAME="$INSTANCE_NAME-ag-$AVALANCHEGO_BRANCH" +fi +if [ -n "$CORETH_BRANCH" ]; then + INSTANCE_NAME="$INSTANCE_NAME-ce-$CORETH_BRANCH" +fi +if [ -n "$LIBEVM_COMMIT" ]; then + INSTANCE_NAME="$INSTANCE_NAME-le-$LIBEVM_COMMIT" +fi + +# Build spot instance market options if requested +SPOT_OPTIONS="" +if [ "$SPOT_INSTANCE" = true ]; then + MAX_PRICE=${MAX_SPOT_PRICES[$INSTANCE_TYPE]} + SPOT_OPTIONS="--instance-market-options '{\"MarketType\":\"spot\", \"SpotOptions\": {\"MaxPrice\":\"$MAX_PRICE\"}}'" +fi + +if [ "$DRY_RUN" = true ]; then + echo "DRY RUN - Would execute the following command:" + echo "" + echo "aws ec2 run-instances \\" + echo " --region \"$REGION\" \\" + echo " --image-id \"$AMI_ID\" \\" + echo " --count 1 \\" + echo " --instance-type $INSTANCE_TYPE \\" + echo " --key-name rkuris \\" + echo " --security-groups rkuris-starlink-only \\" + echo " --iam-instance-profile \"Name=s3-readonly\" \\" + if [ "$SPOT_INSTANCE" = true ]; then + echo " $SPOT_OPTIONS \\" + fi + echo " --user-data \"$USERDATA\" \\" + echo " --tag-specifications \"ResourceType=instance,Tags=[{Key=Name,Value=$INSTANCE_NAME}]\" \\" + echo " --block-device-mappings \"DeviceName=/dev/sda1,Ebs={VolumeSize=50,VolumeType=gp3}\" \\" + echo " --query 'Instances[0].InstanceId' \\" + echo " --output text" + echo "" + echo "Instance would be named: $INSTANCE_NAME" +else + set -e + # Build the AWS command with conditional spot options + AWS_CMD="aws ec2 run-instances \ + --region \"$REGION\" \ + --image-id \"$AMI_ID\" \ + --count 1 \ + --instance-type \"$INSTANCE_TYPE\" \ + --key-name rkuris \ + --security-groups rkuris-starlink-only \ + --iam-instance-profile \"Name=s3-readonly\"" + + if [ "$SPOT_INSTANCE" = true ]; then + AWS_CMD="$AWS_CMD $SPOT_OPTIONS" + fi + + AWS_CMD="$AWS_CMD \ + --user-data \"$USERDATA\" \ + --tag-specifications \"ResourceType=instance,Tags=[{Key=Name,Value=$INSTANCE_NAME}]\" \ + --block-device-mappings \"DeviceName=/dev/sda1,Ebs={VolumeSize=50,VolumeType=gp3}\" \ + --query 'Instances[0].InstanceId' \ + --output text" + + INSTANCE_ID=$(eval "$AWS_CMD") + echo "instance id $INSTANCE_ID started" + echo -e "\033[33mREMINDER: Please manually shut down your EC2 instance after running the benchmark to avoid unexpected costs!\033[0m" +fi + +if [ "$DRY_RUN" = false ]; then + # IP=$(aws ec2 describe-instances --instance-ids "$INSTANCE_ID" --query 'Reservations[].Instances[].PublicIpAddress' --output text) + set +e + + #IP=$(echo "$JSON" | jq -r '.PublicIpAddress') + #echo $IP + #while nc -zv $IP 22; do + #sleep 1 + #done +fi diff --git a/firewood/benchmark/setup-scripts/README.md b/firewood/benchmark/setup-scripts/README.md new file mode 100644 index 000000000000..31b92807dcb0 --- /dev/null +++ b/firewood/benchmark/setup-scripts/README.md @@ -0,0 +1,33 @@ +# Setup Scripts + +This directory contains the scripts needed to set up the firewood benchmarks, as follows: + +```bash +sudo bash build-environment.sh +``` + +This script sets up the build environment, including installing the firewood build dependencies. + +By default, it sets the bytes-per-inode to 2097152 (2MB) when creating the ext4 filesystem. This default works well for workloads that create many small files (such as LevelDB with AvalancheGo). + +If you're not using LevelDB (for example, just using Firewood without AvalancheGo), you don't need as many inodes, which gives you more room for the database itself. In this case, you can and should use a larger value with the `--bytes-per-inode` option: + +```bash +sudo bash build-environment.sh --bytes-per-inode 6291456 +``` + +```bash +sudo bash install-grafana.sh +``` + +This script sets up grafana to listen on port 3000 for firewood. It also sets up listening +for coreth as well, on port 6060, with the special metrics path coreth expects. + +```bash +bash build-firewood.sh +``` + +This script checks out and builds firewood. It assumes you have already set up the build environment earlier. + +The final script, `run-benchmarks.sh`, is a set of commands that can be copied/pasted to run individual +benchmarks of different sizes. diff --git a/firewood/benchmark/setup-scripts/build-environment.sh b/firewood/benchmark/setup-scripts/build-environment.sh new file mode 100644 index 000000000000..82a1a42efaac --- /dev/null +++ b/firewood/benchmark/setup-scripts/build-environment.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# This script sets up the build environment, including installing the firewood build dependencies. +set -o errexit + +if [ "$EUID" -ne 0 ]; then + echo "This script must be run as root" >&2 + exit 1 +fi + +# Default bytes-per-inode for ext4 filesystem (2MB) +BYTES_PER_INODE=2097152 + +# Parse command line arguments +show_usage() { + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --bytes-per-inode BYTES Set bytes-per-inode for ext4 filesystem (default: 2097152)" + echo " --help Show this help message" +} + +while [[ $# -gt 0 ]]; do + case $1 in + --bytes-per-inode) + BYTES_PER_INODE="$2" + shift 2 + ;; + --help) + show_usage + exit 0 + ;; + *) + echo "Error: Unknown option $1" >&2 + show_usage + exit 1 + ;; + esac +done + +apt upgrade -y + +# install the build dependency packages +pkgs=(git protobuf-compiler build-essential apt-transport-https net-tools zfsutils-linux mdadm) +install_pkgs=() +for pkg in "${pkgs[@]}"; do + if ! dpkg -s "$pkg" > /dev/null 2>&1; then + install_pkgs+=("$pkg") + fi +done +if [ "${#install_pkgs[@]}" -gt 0 ]; then + apt-get install -y "${install_pkgs[@]}" +fi + +# If there are NVMe devices, set up RAID if multiple, or use single device +mapfile -t NVME_DEVS < <(realpath /dev/disk/by-id/nvme-Amazon_EC2_NVMe_Instance_Storage_* 2>/dev/null | sort | uniq) +if [ "${#NVME_DEVS[@]}" -gt 0 ]; then + DEVICE_TO_USE="" + + if [ "${#NVME_DEVS[@]}" -eq 1 ]; then + # Single device, use it directly + DEVICE_TO_USE="${NVME_DEVS[0]}" + echo "Using single NVMe device: $DEVICE_TO_USE" + elif [ "${#NVME_DEVS[@]}" -eq 2 ]; then + # Two devices, create RAID1 + echo "Creating RAID1 array with 2 devices: ${NVME_DEVS[*]}" + mdadm --create /dev/md0 --level=1 --raid-devices=2 "${NVME_DEVS[@]}" + DEVICE_TO_USE="/dev/md0" + elif [ "${#NVME_DEVS[@]}" -eq 3 ]; then + # Three devices, create RAID5 + echo "Creating RAID5 array with 3 devices: ${NVME_DEVS[*]}" + mdadm --create /dev/md0 --level=5 --raid-devices=3 "${NVME_DEVS[@]}" + DEVICE_TO_USE="/dev/md0" + elif [ "${#NVME_DEVS[@]}" -eq 4 ]; then + # Four devices, create RAID10 + echo "Creating RAID10 array with 4 devices: ${NVME_DEVS[*]}" + mdadm --create /dev/md0 --level=10 --raid-devices=4 "${NVME_DEVS[@]}" + DEVICE_TO_USE="/dev/md0" + else + echo "Unsupported number of NVMe devices: ${#NVME_DEVS[@]}. Using first device only." + DEVICE_TO_USE="${NVME_DEVS[0]}" + fi + + # Wait for RAID array to be ready (if created) + if [[ "$DEVICE_TO_USE" == "/dev/md0" ]]; then + echo "Waiting for RAID array to be ready..." + while [ ! -e "$DEVICE_TO_USE" ]; do + sleep 1 + done + # Save RAID configuration + mdadm --detail --scan >> /etc/mdadm/mdadm.conf + update-initramfs -u + fi + + # Format and mount the device + mkfs.ext4 -E nodiscard -i "$BYTES_PER_INODE" "$DEVICE_TO_USE" + NVME_MOUNT=/mnt/nvme + mkdir -p "$NVME_MOUNT" + mount -o noatime "$DEVICE_TO_USE" "$NVME_MOUNT" + echo "$DEVICE_TO_USE $NVME_MOUNT ext4 noatime 0 0" >> /etc/fstab + mkdir -p "$NVME_MOUNT/ubuntu/firewood" + chown ubuntu:ubuntu "$NVME_MOUNT/ubuntu" "$NVME_MOUNT/ubuntu/firewood" + ln -s "$NVME_MOUNT/ubuntu/firewood" /home/ubuntu/firewood +fi diff --git a/firewood/benchmark/setup-scripts/build-firewood.sh b/firewood/benchmark/setup-scripts/build-firewood.sh new file mode 100644 index 000000000000..06ae19c202a1 --- /dev/null +++ b/firewood/benchmark/setup-scripts/build-firewood.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -o errexit + +if [ "$EUID" -eq 0 ]; then + echo "This script should be run as a non-root user" + exit 1 +fi + +# install rust +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +. "$HOME/.cargo/env" + +# clone the firewood repository +if [ ! -d "$HOME/firewood" ]; then + mkdir -p "$HOME/firewood" +fi +pushd "$HOME/firewood" + +git clone https://github.com/ava-labs/firewood.git . + +# build the firewood binary +cargo build --profile maxperf +popd + diff --git a/firewood/benchmark/setup-scripts/install-golang.sh b/firewood/benchmark/setup-scripts/install-golang.sh new file mode 100644 index 000000000000..e00575d07546 --- /dev/null +++ b/firewood/benchmark/setup-scripts/install-golang.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +set -euo pipefail + +INSTALL_DIR="/usr/local/go" + +# Check write permission +if [ -d "$INSTALL_DIR" ]; then + if [ ! -w "$INSTALL_DIR" ]; then + echo "Error: $INSTALL_DIR exists but is not writable." >&2 + exit 1 + fi +else + if [ ! -w "$(dirname "$INSTALL_DIR")" ]; then + echo "Error: Cannot create $INSTALL_DIR. $(dirname "$INSTALL_DIR") is not writable." >&2 + exit 1 + fi +fi + +# Detect latest Go version +LATEST_VERSION=$(curl -s https://go.dev/dl/?mode=json | \ + grep -oE '"version": ?"go[0-9]+\.[0-9]+(\.[0-9]+)?"' | \ + head -n1 | cut -d\" -f4) + +if [ -z "$LATEST_VERSION" ]; then + echo "Error: Could not detect latest Go version." >&2 + exit 1 +fi + +# Detect platform +UNAME_OS="$(uname -s | tr '[:upper:]' '[:lower:]')" +UNAME_ARCH="$(uname -m)" + +# Map to Go arch +case "$UNAME_ARCH" in + x86_64) ARCH="amd64" ;; + aarch64 | arm64) ARCH="arm64" ;; + armv6l | armv7l) ARCH="arm" ;; + *) echo "Unsupported architecture: $UNAME_ARCH" >&2; exit 1 ;; +esac + +# Map to Go OS +case "$UNAME_OS" in + linux | darwin) OS="$UNAME_OS" ;; + *) echo "Unsupported OS: $UNAME_OS" >&2; exit 1 ;; +esac + +# Build tarball name and URL +TARBALL="${LATEST_VERSION}.${OS}-${ARCH}.tar.gz" +URL="https://go.dev/dl/${TARBALL}" + +# Validate URL +echo "Checking URL: $URL" +if ! curl --head --fail --silent "$URL" >/dev/null; then + echo "Error: Go tarball not found at $URL" >&2 + exit 1 +fi + +# Download and install +TMP_DIR=$(mktemp -d) +cd "$TMP_DIR" +echo "Downloading $TARBALL..." +curl -fLO "$URL" + +# Validate archive format +if ! file "$TARBALL" | grep -q 'gzip compressed data'; then + echo "Error: Downloaded file is not a valid tar.gz archive." >&2 + exit 1 +fi + +echo "Removing any existing Go installation in $INSTALL_DIR..." +rm -rf "$INSTALL_DIR" + +echo "Extracting Go to $INSTALL_DIR..." +tar -C "$(dirname "$INSTALL_DIR")" -xzf "$TARBALL" + +rm -rf "$TMP_DIR" + +echo "✅ Go $LATEST_VERSION installed to $INSTALL_DIR" +echo "➕ Add to PATH if needed:" +echo " export PATH=\$PATH:/usr/local/go/bin" + diff --git a/firewood/benchmark/setup-scripts/install-grafana.sh b/firewood/benchmark/setup-scripts/install-grafana.sh new file mode 100644 index 000000000000..f3c5157aad4d --- /dev/null +++ b/firewood/benchmark/setup-scripts/install-grafana.sh @@ -0,0 +1,115 @@ +#!/bin/bash +set -o errexit + +# install the keyrings needed to validate the grafana apt repository +if ! [ -d /etc/apt/keyrings ]; then + mkdir -p /etc/apt/keyrings/ +fi +if ! [ -f /etc/apt/keyrings/grafana.gpg ]; then + wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor > /etc/apt/keyrings/grafana.gpg + echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" >> /etc/apt/sources.list.d/grafana.list +fi +apt-get update + +# set up the systemd configuration to allow grafana to bind to port 80 +if ! [ -d /etc/systemd/system/grafana-server.service.d ]; then + mkdir -p /etc/systemd/system/grafana-server.service.d +fi + +if ! [ -f /etc/systemd/system/grafana-server.service.d/override.conf ]; then + cat > /etc/systemd/system/grafana-server.service.d/override.conf < /dev/null 2>&1; then + install_pkgs+=("$pkg") + fi +done +if [ "${#install_pkgs[@]}" -gt 0 ]; then + apt-get install -y "${install_pkgs[@]}" +fi + +# configure grafana to listen on port 80 +if ! grep -q '^http_port = 80$' /etc/grafana/grafana.ini; then + perl -pi -e 's/^;?http_port = .*/http_port = 80/' /etc/grafana/grafana.ini +fi + +# configure username and password +# TODO(amin): auto-generate some password for more security +# TODO(amin): another possible option here is enabling google oauth, and this could give access +# to anyone within our org emails +sed -i -E "s|^;?\s*admin_user\s*=.*|admin_user = admin|" /etc/grafana/grafana.ini +sed -i -E "s|^;?\s*admin_password\s*=.*|admin_password = firewood_is_fast|" /etc/grafana/grafana.ini + +# provision data source and dashboards +cat > /etc/grafana/provisioning/datasources/prometheus.yml < /etc/grafana/provisioning/dashboards/dashboards.yaml <> /etc/prometheus/prometheus.yml <> /etc/default/prometheus-node-exporter < Result<(), Box> { + let keys = args.global_opts.batch_size; + let start = Instant::now(); + + for key in 0..args.global_opts.number_of_batches { + let root = Span::root(func_path!(), SpanContext::random()); + let _guard = root.set_local_parent(); + + let batch = Self::generate_inserts(key * keys, args.global_opts.batch_size); + + let proposal = db.propose(batch).expect("proposal should succeed"); + proposal.commit()?; + } + let duration = start.elapsed(); + info!( + "Generated and inserted {} batches of size {keys} in {}", + args.global_opts.number_of_batches, + pretty_duration(&duration, None) + ); + + Ok(()) + } +} diff --git a/firewood/benchmark/src/main.rs b/firewood/benchmark/src/main.rs new file mode 100644 index 000000000000..9af45df8e28f --- /dev/null +++ b/firewood/benchmark/src/main.rs @@ -0,0 +1,309 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. +// + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 2 occurrences after enabling the lint." +)] +#![expect( + clippy::match_same_arms, + reason = "Found 1 occurrences after enabling the lint." +)] +#![doc = include_str!("../README.md")] + +use clap::{Parser, Subcommand, ValueEnum}; +use fastrace_opentelemetry::OpenTelemetryReporter; +use firewood::logger::trace; +use log::LevelFilter; +use sha2::{Digest, Sha256}; +use std::borrow::Cow; +use std::error::Error; +use std::fmt::Display; +use std::num::NonZeroUsize; +use std::path::PathBuf; + +use firewood::db::{BatchOp, Db, DbConfig}; +use firewood::manager::{CacheReadStrategy, RevisionManagerConfig}; + +use fastrace::collector::Config; + +use opentelemetry::InstrumentationScope; +use opentelemetry_otlp::{SpanExporter, WithExportConfig}; +use opentelemetry_sdk::Resource; + +#[derive(Parser, Debug)] +struct Args { + #[clap(flatten)] + global_opts: GlobalOpts, + + #[clap(subcommand)] + test_name: TestName, +} + +#[derive(clap::Args, Debug)] +struct GlobalOpts { + #[arg( + short = 'e', + long, + default_value_t = false, + help = "Enable telemetry server reporting" + )] + telemetry_server: bool, + #[arg(short, long, default_value_t = 10000)] + batch_size: u64, + #[arg(short, long, default_value_t = 1000)] + number_of_batches: u64, + #[arg(short, long, default_value_t = NonZeroUsize::new(1500000).expect("is non-zero"))] + cache_size: NonZeroUsize, + #[arg(short, long, default_value_t = 128)] + revisions: usize, + #[cfg(feature = "prometheus")] + #[arg( + short = 'p', + long, + default_value_t = 3000, + help = "Port to listen for prometheus" + )] + prometheus_port: u16, + #[cfg(feature = "prometheus")] + #[arg( + short = 's', + long, + default_value_t = false, + help = "Dump prometheus stats on exit" + )] + stats_dump: bool, + + #[arg( + long, + short = 'l', + required = false, + help = "Log level. Respects RUST_LOG.", + value_name = "LOG_LEVEL", + num_args = 1, + value_parser = ["trace", "debug", "info", "warn", "none"], + default_value_t = String::from("info"), + )] + log_level: String, + #[arg( + long, + short = 'd', + required = false, + help = "Use this database name instead of the default", + default_value = PathBuf::from("benchmark_db").into_os_string(), + )] + dbname: PathBuf, + #[arg( + long, + short = 't', + required = false, + help = "Terminate the test after this many minutes", + default_value_t = 65 + )] + duration_minutes: u64, + #[arg( + long, + short = 'C', + required = false, + help = "Read cache strategy", + default_value_t = ArgCacheReadStrategy::WritesOnly + )] + cache_read_strategy: ArgCacheReadStrategy, +} +#[derive(Debug, PartialEq, ValueEnum, Clone)] +pub enum ArgCacheReadStrategy { + WritesOnly, + BranchReads, + All, +} +impl Display for ArgCacheReadStrategy { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ArgCacheReadStrategy::WritesOnly => write!(f, "writes-only"), + ArgCacheReadStrategy::BranchReads => write!(f, "branch-reads"), + ArgCacheReadStrategy::All => write!(f, "all"), + } + } +} +impl From for CacheReadStrategy { + fn from(arg: ArgCacheReadStrategy) -> Self { + match arg { + ArgCacheReadStrategy::WritesOnly => CacheReadStrategy::WritesOnly, + ArgCacheReadStrategy::BranchReads => CacheReadStrategy::BranchReads, + ArgCacheReadStrategy::All => CacheReadStrategy::All, + } + } +} + +mod create; +mod single; +mod tenkrandom; +mod zipf; + +#[derive(Debug, Subcommand, PartialEq)] +enum TestName { + /// Create a database + Create, + + /// Insert batches of random keys + TenKRandom, + + /// Insert batches of keys following a Zipf distribution + Zipf(zipf::Args), + + /// Repeatedly update a single row + Single, +} + +trait TestRunner { + fn run(&self, db: &Db, args: &Args) -> Result<(), Box>; + + fn generate_inserts( + start: u64, + count: u64, + ) -> impl Iterator, Box<[u8]>>> { + (start..start + count) + .map(|inner_key| { + let digest: Box<[u8]> = Sha256::digest(inner_key.to_ne_bytes())[..].into(); + trace!( + "inserting {:?} with digest {}", + inner_key, + hex::encode(&digest), + ); + (digest.clone(), digest) + }) + .map(|(key, value)| BatchOp::Put { key, value }) + .collect::>() + .into_iter() + } +} + +#[global_allocator] +#[cfg(unix)] +static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; + +fn main() -> Result<(), Box> { + let args = Args::parse(); + + if args.global_opts.telemetry_server { + let reporter = OpenTelemetryReporter::new( + SpanExporter::builder() + .with_tonic() + .with_endpoint("http://127.0.0.1:4317".to_string()) + .with_protocol(opentelemetry_otlp::Protocol::Grpc) + .with_timeout(opentelemetry_otlp::OTEL_EXPORTER_OTLP_TIMEOUT_DEFAULT) + .build() + .expect("initialize oltp exporter"), + Cow::Owned( + Resource::builder() + .with_service_name("avalabs.firewood.benchmark") + .build(), + ), + InstrumentationScope::builder("firewood") + .with_version(env!("CARGO_PKG_VERSION")) + .build(), + ); + fastrace::set_reporter(reporter, Config::default()); + } + + assert!( + !(args.test_name == TestName::Single && args.global_opts.batch_size > 1000), + "Single test is not designed to handle batch sizes > 1000" + ); + + env_logger::Builder::new() + .filter_level(match args.global_opts.log_level.as_str() { + "debug" => LevelFilter::Debug, + "info" => LevelFilter::Info, + "trace" => LevelFilter::Trace, + "none" => LevelFilter::Off, + _ => LevelFilter::Info, + }) + .init(); + + // Manually set up prometheus + #[cfg(feature = "prometheus")] + let prometheus_handle = spawn_prometheus_listener(args.global_opts.prometheus_port) + .expect("failed to spawn prometheus listener"); + + let mgrcfg = RevisionManagerConfig::builder() + .node_cache_size(args.global_opts.cache_size) + .free_list_cache_size( + NonZeroUsize::new(4 * args.global_opts.batch_size as usize).expect("batch size > 0"), + ) + .cache_read_strategy(args.global_opts.cache_read_strategy.clone().into()) + .max_revisions(args.global_opts.revisions) + .build(); + let cfg = DbConfig::builder() + .truncate(matches!(args.test_name, TestName::Create)) + .manager(mgrcfg) + .build(); + + let db = Db::new(args.global_opts.dbname.clone(), cfg).expect("db initiation should succeed"); + + match args.test_name { + TestName::Create => { + let runner = create::Create; + runner.run(&db, &args)?; + } + TestName::TenKRandom => { + let runner = tenkrandom::TenKRandom; + runner.run(&db, &args)?; + } + TestName::Zipf(_) => { + let runner = zipf::Zipf; + runner.run(&db, &args)?; + } + TestName::Single => { + let runner = single::Single; + runner.run(&db, &args)?; + } + } + + #[cfg(feature = "prometheus")] + if args.global_opts.stats_dump { + println!("{}", prometheus_handle.render()); + } + + fastrace::flush(); + + Ok(()) +} + +#[cfg(feature = "prometheus")] +fn spawn_prometheus_listener( + port: u16, +) -> Result> { + use metrics_exporter_prometheus::PrometheusBuilder; + use metrics_util::MetricKindMask; + use std::net::{Ipv6Addr, SocketAddr}; + use std::time::Duration; + + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build()?; + + let (recorder, exporter) = { + // PrometheusBuilder::build requires that we be within the tokio runtime context + // but we don't need to actually invoke the runtime until we spawn the thread + let _guard = rt.enter(); + PrometheusBuilder::new() + .with_http_listener(SocketAddr::new(Ipv6Addr::UNSPECIFIED.into(), port)) + .idle_timeout( + MetricKindMask::COUNTER | MetricKindMask::HISTOGRAM, + Some(Duration::from_secs(10)), + ) + .build()? + }; + + std::thread::Builder::new() + .name("metrics-exporter-prometheus".to_owned()) + .spawn(move || rt.block_on(exporter))?; + + let handle = recorder.handle(); + + metrics::set_global_recorder(recorder)?; + + Ok(handle) +} diff --git a/firewood/benchmark/src/single.rs b/firewood/benchmark/src/single.rs new file mode 100644 index 000000000000..04642d24a2dd --- /dev/null +++ b/firewood/benchmark/src/single.rs @@ -0,0 +1,52 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 2 occurrences after enabling the lint." +)] +#![expect( + clippy::cast_sign_loss, + reason = "Found 1 occurrences after enabling the lint." +)] + +use crate::TestRunner; +use firewood::db::{BatchOp, Db}; +use firewood::v2::api::{Db as _, Proposal as _}; +use log::debug; +use pretty_duration::pretty_duration; +use sha2::{Digest, Sha256}; +use std::error::Error; +use std::time::Instant; + +#[derive(Clone)] +pub struct Single; + +impl TestRunner for Single { + fn run(&self, db: &Db, args: &crate::Args) -> Result<(), Box> { + let start = Instant::now(); + let inner_keys: Vec<_> = (0..args.global_opts.batch_size) + .map(|i| Sha256::digest(i.to_ne_bytes())) + .collect(); + let mut batch_id = 0; + + while start.elapsed().as_secs() / 60 < args.global_opts.duration_minutes { + let batch = inner_keys.iter().map(|key| BatchOp::Put { + key, + value: vec![batch_id as u8], + }); + let proposal = db.propose(batch).expect("proposal should succeed"); + proposal.commit()?; + + if log::log_enabled!(log::Level::Debug) && batch_id % 1000 == 999 { + debug!( + "completed {} batches in {}", + 1 + batch_id, + pretty_duration(&start.elapsed(), None) + ); + } + batch_id += 1; + } + Ok(()) + } +} diff --git a/firewood/benchmark/src/tenkrandom.rs b/firewood/benchmark/src/tenkrandom.rs new file mode 100644 index 000000000000..ec47b8b8379b --- /dev/null +++ b/firewood/benchmark/src/tenkrandom.rs @@ -0,0 +1,74 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 7 occurrences after enabling the lint." +)] + +use std::error::Error; +use std::time::Instant; + +use firewood::db::{BatchOp, Db}; +use firewood::logger::debug; +use firewood::v2::api::{Db as _, Proposal as _}; + +use crate::{Args, TestRunner}; +use sha2::{Digest, Sha256}; + +#[derive(Clone, Default)] +pub struct TenKRandom; + +impl TestRunner for TenKRandom { + fn run(&self, db: &Db, args: &Args) -> Result<(), Box> { + let mut low = 0; + let mut high = args.global_opts.number_of_batches * args.global_opts.batch_size; + let twenty_five_pct = args.global_opts.batch_size / 4; + + let start = Instant::now(); + + while start.elapsed().as_secs() / 60 < args.global_opts.duration_minutes { + let batch: Vec> = Self::generate_inserts(high, twenty_five_pct) + .chain(generate_deletes(low, twenty_five_pct)) + .chain(generate_updates(low + high / 2, twenty_five_pct * 2, low)) + .collect(); + let proposal = db.propose(batch).expect("proposal should succeed"); + proposal.commit()?; + low += twenty_five_pct; + high += twenty_five_pct; + } + Ok(()) + } +} +fn generate_updates( + start: u64, + count: u64, + low: u64, +) -> impl Iterator, Box<[u8]>>> { + let hash_of_low: Box<[u8]> = Sha256::digest(low.to_ne_bytes())[..].into(); + (start..start + count) + .map(|inner_key| { + let digest = Sha256::digest(inner_key.to_ne_bytes())[..].into(); + debug!( + "updating {:?} with digest {} to {}", + inner_key, + hex::encode(&digest), + hex::encode(&hash_of_low) + ); + (digest, hash_of_low.clone()) + }) + .map(|(key, value)| BatchOp::Put { key, value }) + .collect::>() + .into_iter() +} +fn generate_deletes(start: u64, count: u64) -> impl Iterator, Box<[u8]>>> { + (start..start + count) + .map(|key| { + let digest = Sha256::digest(key.to_ne_bytes())[..].into(); + debug!("deleting {:?} with digest {}", key, hex::encode(&digest)); + digest + }) + .map(|key| BatchOp::Delete { key }) + .collect::>() + .into_iter() +} diff --git a/firewood/benchmark/src/zipf.rs b/firewood/benchmark/src/zipf.rs new file mode 100644 index 000000000000..d1b76bbc7187 --- /dev/null +++ b/firewood/benchmark/src/zipf.rs @@ -0,0 +1,111 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 2 occurrences after enabling the lint." +)] +#![expect( + clippy::cast_precision_loss, + reason = "Found 1 occurrences after enabling the lint." +)] +#![expect( + clippy::cast_sign_loss, + reason = "Found 1 occurrences after enabling the lint." +)] +#![expect( + clippy::unwrap_used, + reason = "Found 1 occurrences after enabling the lint." +)] + +use crate::TestRunner; +use firewood::db::{BatchOp, Db}; +use firewood::v2::api::{Db as _, Proposal as _}; +use log::{debug, trace}; +use pretty_duration::pretty_duration; +use rand::prelude::*; +use sha2::{Digest, Sha256}; +use std::collections::HashSet; +use std::error::Error; +use std::time::Instant; + +#[derive(clap::Args, Debug, PartialEq)] +pub struct Args { + #[arg(short, long, help = "zipf exponent", default_value_t = 1.2)] + exponent: f64, +} + +#[derive(Clone)] +pub struct Zipf; + +impl TestRunner for Zipf { + fn run(&self, db: &Db, args: &crate::Args) -> Result<(), Box> { + let exponent = if let crate::TestName::Zipf(args) = &args.test_name { + args.exponent + } else { + unreachable!() + }; + let rows = (args.global_opts.number_of_batches * args.global_opts.batch_size) as f64; + let zipf = rand_distr::Zipf::new(rows, exponent).unwrap(); + let start = Instant::now(); + let mut batch_id = 0; + + let rng = firewood_storage::SeededRng::from_env_or_random(); + while start.elapsed().as_secs() / 60 < args.global_opts.duration_minutes { + let batch: Vec> = + generate_updates(&rng, batch_id, args.global_opts.batch_size as usize, zipf) + .collect(); + if log::log_enabled!(log::Level::Debug) { + let mut distinct = HashSet::new(); + for op in &batch { + match op { + BatchOp::Put { key, value: _ } => { + distinct.insert(key); + } + _ => unreachable!(), + } + } + debug!( + "inserting batch {} with {} distinct data values", + batch_id, + distinct.len() + ); + } + let proposal = db.propose(batch).expect("proposal should succeed"); + proposal.commit()?; + + if log::log_enabled!(log::Level::Debug) { + debug!( + "completed batch {} in {}", + batch_id, + pretty_duration(&start.elapsed(), None) + ); + } + batch_id += 1; + } + Ok(()) + } +} +fn generate_updates( + rng: &firewood_storage::SeededRng, + batch_id: u32, + batch_size: usize, + zipf: rand_distr::Zipf, +) -> impl Iterator, Vec>> { + let hash_of_batch_id = Sha256::digest(batch_id.to_ne_bytes()).to_vec(); + zipf.sample_iter(rng) + .take(batch_size) + .map(|inner_key| { + let digest = Sha256::digest((inner_key as u64).to_ne_bytes()).to_vec(); + trace!( + "updating {:?} with digest {} to {}", + inner_key, + hex::encode(&digest), + hex::encode(&hash_of_batch_id) + ); + (digest, hash_of_batch_id.clone()) + }) + .map(|(key, value)| BatchOp::Put { key, value }) + .collect::>() + .into_iter() +} diff --git a/firewood/cliff.toml b/firewood/cliff.toml new file mode 100644 index 000000000000..c7f5d34743bb --- /dev/null +++ b/firewood/cliff.toml @@ -0,0 +1,107 @@ +# git-cliff ~ configuration file +# https://git-cliff.org/docs/configuration + + +[changelog] +# A Tera template to be rendered as the changelog's footer. +# See https://keats.github.io/tera/docs/#introduction +header = """ +# Changelog\n +All notable changes to this project will be documented in this file.\n +""" +# A Tera template to be rendered for each release in the changelog. +# See https://keats.github.io/tera/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | striptags | trim | upper_first }} + {% for commit in commits %} + - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ + {% if commit.breaking %}[**breaking**] {% endif %}\ + {{ commit.message | upper_first }}\ + {% endfor %} +{% endfor %}\n +""" +# A Tera template to be rendered as the changelog's footer. +# See https://keats.github.io/tera/docs/#introduction +footer = """ + +""" +# Remove leading and trailing whitespaces from the changelog's body. +trim = true +# Render body even when there are no releases to process. +render_always = true +# An array of regex based postprocessors to modify the changelog. +postprocessors = [ + # Replace the placeholder with a URL. + { pattern = '', replace = "https://github.com/ava-labs/firewood" }, +] +# render body even when there are no releases to process +# render_always = true +# output file path +# output = "test.md" + +[git] +# Parse commits according to the conventional commits specification. +# See https://www.conventionalcommits.org +conventional_commits = true +# Exclude commits that do not match the conventional commits specification. +filter_unconventional = true +# Require all commits to be conventional. +# Takes precedence over filter_unconventional. +require_conventional = false +# Split commits on newlines, treating each line as an individual commit. +split_commits = false +# An array of regex based parsers to modify commit messages prior to further processing. +commit_preprocessors = [ + # Replace issue numbers with link templates to be updated in `changelog.postprocessors`. + #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](/issues/${2}))"}, + # Check spelling of the commit message using https://github.com/crate-ci/typos. + # If the spelling is incorrect, it will be fixed automatically. + #{ pattern = '.*', replace_command = 'typos --write-changes -' }, + # Squash merges end with the pull request number (e.g., `(#12345)`). Replace those with a link to the pull request. + { pattern = '\(#([0-9]+)\)', replace = '([#${1}](/pull/${1}))' }, +] +# Prevent commits that are breaking from being excluded by commit parsers. +protect_breaking_commits = false +# An array of regex based parsers for extracting data from the commit message. +# Assigns commits to groups. +# Optionally sets the commit's scope and can decide to exclude commits from further processing. +commit_parsers = [ + { message = "^feat", group = "🚀 Features" }, + { message = "^fix", group = "🐛 Bug Fixes" }, + { message = "^doc", group = "📚 Documentation" }, + { message = "^perf", group = "⚡ Performance" }, + { message = "^refactor", group = "🚜 Refactor" }, + { message = "^style", group = "🎨 Styling" }, + { message = "^test", group = "🧪 Testing" }, + { message = "^chore\\(release\\): prepare for", skip = true }, + { message = "^chore\\(deps.*\\)", skip = true }, + { message = "^chore\\(pr\\)", skip = true }, + { message = "^chore\\(pull\\)", skip = true }, + { message = "^chore|^ci", group = "⚙️ Miscellaneous Tasks" }, + { body = ".*security", group = "🛡️ Security" }, + { message = "^revert", group = "◀️ Revert" }, + { message = ".*", group = "💼 Other" }, +] +# Exclude commits that are not matched by any commit parser. +filter_commits = false +# An array of link parsers for extracting external references, and turning them into URLs, using regex. +link_parsers = [] +# Include only the tags that belong to the current branch. +use_branch_tags = true +# Order releases topologically instead of chronologically. +topo_order = false +# Order releases topologically instead of chronologically. +topo_order_commits = true +# Order of commits in each group/release within the changelog. +# Allowed values: newest, oldest +sort_commits = "oldest" +# Process submodules commits +recurse_submodules = false +# Only process tags in this pattern +tag_pattern = "v[0-9].*" diff --git a/firewood/clippy.toml b/firewood/clippy.toml new file mode 100644 index 000000000000..f46b95050f76 --- /dev/null +++ b/firewood/clippy.toml @@ -0,0 +1,24 @@ +# See https://doc.rust-lang.org/clippy/lint_configuration.html +# for full configuration options. + +msrv = "1.91" + +doc-valid-idents = [ + "MerkleDB", + # this list must end with ".." so that it does not truncate the default list + "..", +] + +disallowed-methods = [ + { path = "rand::rng", replacement = "firewood_storage::SeededRng::from_env_or_random", reason = "use a prng with a user-defined seed instead", allow-invalid = true }, +] + +disallowed-types = [ + { path = "rand::SeedableRng", replacement = "firewood_storage::SeededRng", reason = "use a prng with a user-defined seed instead", allow-invalid = true }, + { path = "rand::rngs::StdRng", replacement = "firewood_storage::SeededRng", reason = "use a prng with a user-defined seed instead", allow-invalid = true }, + { path = "std::sync::Mutex", replacement = "parking_lot::Mutex", reason = "prefer parking_lot locking primitives for consistency and performance", allow-invalid = true }, + { path = "std::sync::MutexGuard", replacement = "parking_lot::MutexGuard", reason = "prefer parking_lot locking primitives for consistency and performance", allow-invalid = true }, + { path = "std::sync::RwLock", replacement = "parking_lot::RwLock", reason = "prefer parking_lot locking primitives for consistency and performance", allow-invalid = true }, + { path = "std::sync::RwLockReadGuard", replacement = "parking_lot::RwLockReadGuard", reason = "prefer parking_lot locking primitives for consistency and performance", allow-invalid = true }, + { path = "std::sync::RwLockWriteGuard", replacement = "parking_lot::RwLockWriteGuard", reason = "prefer parking_lot locking primitives for consistency and performance", allow-invalid = true }, +] diff --git a/firewood/docs/assets/architecture.svg b/firewood/docs/assets/architecture.svg new file mode 100644 index 000000000000..a88885f0d78e --- /dev/null +++ b/firewood/docs/assets/architecture.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/firewood/ffi/.gitignore b/firewood/ffi/.gitignore new file mode 100644 index 000000000000..ecc17f0fc9a1 --- /dev/null +++ b/firewood/ffi/.gitignore @@ -0,0 +1,5 @@ +dbtest +_obj + +# Nix output +result diff --git a/firewood/ffi/.golangci.yaml b/firewood/ffi/.golangci.yaml new file mode 100644 index 000000000000..a833506d90df --- /dev/null +++ b/firewood/ffi/.golangci.yaml @@ -0,0 +1,228 @@ +# https://golangci-lint.run/usage/configuration/ +version: "2" +run: + # If set we pass it to "go list -mod={option}". From "go help modules": + # If invoked with -mod=readonly, the go command is disallowed from the implicit + # automatic updating of go.mod described above. Instead, it fails when any changes + # to go.mod are needed. This setting is most useful to check that go.mod does + # not need updates, such as in a continuous integration and testing system. + # If invoked with -mod=vendor, the go command assumes that the vendor + # directory holds the correct copies of dependencies and ignores + # the dependency descriptions in go.mod. + # + # Allowed values: readonly|vendor|mod + # By default, it isn't set. + modules-download-mode: readonly + + # Include non-test files tagged as test-only. + # Context: https://github.com/ava-labs/avalanchego/pull/3173 + build-tags: + - test + +issues: + # Make issues output unique by line. + uniq-by-line: false + + # Maximum issues count per one linter. + max-issues-per-linter: 0 + + # Maximum count of issues with the same text. + max-same-issues: 0 + +formatters: + enable: + - gci + - gofmt + - gofumpt + settings: + gci: + sections: + - standard + - default + - blank + - prefix(github.com/ava-labs/firewood/ffi) + - alias + - dot + custom-order: true + exclusions: + generated: lax + +linters: + default: none + enable: + - asciicheck + - bidichk + - bodyclose + - copyloopvar + - depguard + - durationcheck + - errcheck + - errorlint + - forbidigo + - goconst + - gocheckcompilerdirectives + - gocritic + - goprintffuncname + - gosec + - govet + - importas + - ineffassign + - mirror + - misspell + - nakedret + - nilerr + - noctx + - nolintlint + - perfsprint + - prealloc + - predeclared + - reassign + - revive + - spancheck + - staticcheck + - tagalign + - testifylint + - unconvert + - usetesting + - unparam + - unused + - usestdlibvars + - whitespace + settings: + depguard: + rules: + packages: + deny: + - pkg: github.com/golang/mock/gomock + desc: go.uber.org/mock/gomock should be used instead. + - pkg: github.com/stretchr/testify/assert + desc: github.com/stretchr/testify/require should be used instead. + - pkg: io/ioutil + desc: io/ioutil is deprecated. Use package io or os instead. + errorlint: + # Check for plain type assertions and type switches. + asserts: false + # Check for plain error comparisons. + comparison: false + forbidigo: + # Forbid the following identifiers (list of regexp). + forbid: + - pattern: ^(t|b|tb|f)\.(Fatal|Fatalf|Error|Errorf)$(# the require library should be used instead)? + - pattern: ^sort\.(Slice|Strings)$(# the slices package should be used instead)? + # Exclude godoc examples from forbidigo checks. + exclude-godoc-examples: false + revive: + rules: + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bool-literal-in-expr + - name: bool-literal-in-expr + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#early-return + - name: early-return + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-lines + - name: empty-lines + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-import-alias + - name: redundant-import-alias + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-format + - name: string-format + disabled: false + arguments: + - - b.Logf[0] + - /.*%.*/ + - no format directive, use b.Log instead + - - fmt.Errorf[0] + - /.*%.*/ + - no format directive, use errors.New instead + - - fmt.Fprintf[1] + - /.*%.*/ + - no format directive, use fmt.Fprint instead + - - fmt.Printf[0] + - /.*%.*/ + - no format directive, use fmt.Print instead + - - fmt.Sprintf[0] + - /.*%.*/ + - no format directive, use fmt.Sprint instead + - - log.Fatalf[0] + - /.*%.*/ + - no format directive, use log.Fatal instead + - - log.Printf[0] + - /.*%.*/ + - no format directive, use log.Print instead + - - t.Logf[0] + - /.*%.*/ + - no format directive, use t.Log instead + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#struct-tag + - name: struct-tag + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-naming + - name: unexported-naming + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unhandled-error + - name: unhandled-error + # prefer the errcheck linter since it can be disabled directly with nolint directive + # but revive's disable directive (e.g. //revive:disable:unhandled-error) is not + # supported when run under golangci_lint + disabled: true + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter + - name: unused-parameter + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-receiver + - name: unused-receiver + disabled: false + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break + - name: useless-break + disabled: false + tagalign: + align: true + sort: true + order: + - serialize + strict: true + testifylint: + # Enable all checkers (https://github.com/Antonboom/testifylint#checkers). + # Default: false + enable-all: true + # Disable checkers by name + # (in addition to default + # suite-thelper + # ). + disable: + - go-require + - float-compare + usetesting: + os-create-temp: true # Disallow `os.CreateTemp("", ...)` + os-mkdir-temp: true # Disallow `os.MkdirTemp()` + os-setenv: true # Disallow `os.Setenv()` + os-temp-dir: true # Disallow `os.TempDir()` + os-chdir: true # Disallow `os.Chdir()` + context-background: true # Disallow `context.Background()` + context-todo: true # Disallow `context.TODO()` + unused: + # Mark all struct fields that have been written to as used. + # Default: true + field-writes-are-uses: false + # Treat IncDec statement (e.g. `i++` or `i--`) as both read and write operation instead of just write. + # Default: false + post-statements-are-reads: true + # Mark all local variables as used. + # default: true + local-variables-are-used: false + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + # Exclude some linters from running on test files. + # 1. Exclude the top level tests/ directory. + # 2. Exclude any file prefixed with test_ in any directory. + # 3. Exclude any directory suffixed with test. + # 4. Exclude any file suffixed with _test.go. + - path: "(^tests/)|(^(.*/)*test_[^/]*\\.go$)|(.*test/.*)|(.*_test\\.go$)" + linters: + - gosec + - prealloc diff --git a/firewood/ffi/BUILD.bazel b/firewood/ffi/BUILD.bazel new file mode 100644 index 000000000000..a76626f137fa --- /dev/null +++ b/firewood/ffi/BUILD.bazel @@ -0,0 +1,94 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") +load("@rules_rust//rust:defs.bzl", "rust_static_library") + +# Rust static library for firewood FFI +# Note: We use the committed firewood.h header rather than running cbindgen +# at build time. The header should be kept in sync via cargo build locally. +rust_static_library( + name = "firewood_ffi_rust", + srcs = glob(["src/**/*.rs"]), + compile_data = ["README.md"], + crate_features = [ + "ethhash", + "logger", + ], + crate_root = "src/lib.rs", + edition = "2024", + proc_macro_deps = [ + "@firewood_crates//:derive-where", + ], + visibility = ["//visibility:public"], + deps = [ + "//firewood/firewood", + "//firewood/storage:firewood-storage", + "@firewood_crates//:chrono", + "@firewood_crates//:coarsetime", + "@firewood_crates//:env_logger", + "@firewood_crates//:metrics", + "@firewood_crates//:metrics-util", + "@firewood_crates//:oxhttp", + "@firewood_crates//:parking_lot", + ] + select({ + "@platforms//os:linux": ["@firewood_crates//:tikv-jemallocator"], + "@platforms//os:macos": ["@firewood_crates//:tikv-jemallocator"], + "//conditions:default": [], + }), +) + +# C library wrapper for CGO +cc_library( + name = "firewood_ffi", + hdrs = ["firewood.h"], + linkopts = select({ + "@platforms//os:linux": [ + "-lm", + "-ldl", + "-lpthread", + ], + "@platforms//os:macos": ["-lm"], + "//conditions:default": ["-lm"], + }), + visibility = ["//visibility:public"], + deps = [":firewood_ffi_rust"], +) + +# Go library with CGO bindings +# gazelle:ignore +go_library( + name = "ffi", + srcs = [ + "firewood.go", + "firewood.h", + "iterator.go", + "keepalive.go", + "maybe.go", + "memory.go", + "metrics.go", + "proofs.go", + "proposal.go", + "revision.go", + ], + cdeps = [":firewood_ffi"], + cgo = True, + importpath = "github.com/ava-labs/firewood-go-ethhash/ffi", + visibility = ["//visibility:public"], + deps = [ + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_model//go", + "@com_github_prometheus_common//expfmt", + ], +) + +go_test( + name = "ffi_test", + srcs = [ + "firewood_test.go", + "metrics_test.go", + "proofs_test.go", + ], + embed = [":ffi"], + deps = [ + "@com_github_prometheus_client_model//go", + "@com_github_stretchr_testify//require", + ], +) diff --git a/firewood/ffi/Cargo.toml b/firewood/ffi/Cargo.toml new file mode 100644 index 000000000000..9ba1b4953498 --- /dev/null +++ b/firewood/ffi/Cargo.toml @@ -0,0 +1,55 @@ +[package] +name = "firewood-ffi" +version.workspace = true +edition.workspace = true +authors = [ + "Aaron Buchwald ", + "Arran Schlosberg <519948+ARR4N@users.noreply.github.com>", + "Austin Larson <78000745+alarso16@users.noreply.github.com>", + "Darioush Jalali ", + "Ron Kuris ", +] +description = "C FFI bindings for Firewood, an embedded key-value store optimized for blockchain state." +license-file.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true + +[lib] +crate-type = ["staticlib"] + +[dependencies] +# Workspace dependencies +coarsetime.workspace = true +firewood.workspace = true +firewood-storage.workspace = true +metrics.workspace = true +metrics-util.workspace = true +parking_lot.workspace = true +# Regular dependencies +chrono = "0.4.42" +oxhttp = "0.3.1" +# Optional dependencies +env_logger = { workspace = true, optional = true } +derive-where = "1.6.0" + +[target.'cfg(unix)'.dependencies] +tikv-jemallocator = "0.6.1" + +[dev-dependencies] +# Workspace dependencies +test-case.workspace = true + +[features] +logger = ["dep:env_logger", "firewood/logger"] +ethhash = ["firewood/ethhash"] + +[build-dependencies] +cbindgen = "0.29.2" + +[lints] +workspace = true + +[package.metadata.cargo-machete] +ignored = ["cbindgen"] diff --git a/firewood/ffi/README.md b/firewood/ffi/README.md new file mode 100644 index 000000000000..7c6507e7fbf0 --- /dev/null +++ b/firewood/ffi/README.md @@ -0,0 +1,86 @@ +# Firewood Golang FFI + +The FFI package provides a golang FFI layer for Firewood. + +## Building Firewood Golang FFI + +The Golang FFI layer uses a CGO directive to locate a C-API compatible binary built from Firewood. Firewood supports both seamless local development and a single-step compilation process for Go projects that depend or transitively depend on Firewood. + +To do this, [firewood.go](./firewood.go) includes CGO directives to include multiple search paths for the Firewood binary in the local `target/` build directory and `ffi/libs`. For the latter, [attach-static-libs](../.github/workflows/attach-static-libs.yaml) GitHub Action pushes an FFI package for `ethhash` with static libraries attached for the following supported architectures: + +- x86_64-unknown-linux-gnu +- aarch64-unknown-linux-gnu +- aarch64-apple-darwin +- x86_64-apple-darwin + +to a separate repo [firewood-go-ethhash](https://github.com/ava-labs/firewood-go-ethhash) (to avoid including binaries in the Firewood repo). + +### Local Development + +[firewood.go](./firewood.go) includes CGO directives to include builds in the `target/` directory. + +Firewood prioritizes builds in the following order: + +1. maxperf +2. release +3. debug + +To use and test the Firewood FFI locally, you can run: + +```bash +cargo build --profile maxperf +cd ffi +go test +``` + +To use a local build of Firewood for a project that depends on Firewood, you must redirect the `go.mod` to use the local version of Firewood FFI, for example: + +```bash +go mod edit -replace github.com/ava-labs/firewood-go-ethhash/ffi=/path/to/firewood/ffi +go mod tidy +``` + +### Production Development Flow + +Firewood pushes the FFI source code and attached static libraries to [firewood-go-ethhash](https://github.com/ava-labs/firewood-go-ethhash) via [attach-static-libs](../.github/workflows/attach-static-libs.yaml). + +This enables consumers to utilize it directly without forcing them to compile Firewood locally. Go programs running on supported architectures can utilize `firewood-go-ethhash/ffi` just like any other dependency. + +To trigger this build, [attach-static-libs](../.github/workflows/attach-static-libs.yaml) supports triggers for both manual GitHub Actions and tags, so you can create a mirror branch/tag on [firewood-go-ethhash](https://github.com/ava-labs/firewood-go-ethhash) by either trigger a manual GitHub Action and selecting your branch or pushing a tag to Firewood. + +### Hash Mode + +Firewood implemented its own optimized merkle trie structure. To support Ethereum Merkle Trie hash compatibility, it also provides a feature flag `ethhash`. + +This is an optional feature (disabled by default). To enable it for a local build, compile with: + +```sh +cargo build -p firewood-ffi --features ethhash +``` + +To support development in [Coreth](https://github.com/ava-labs/coreth), Firewood pushes static libraries for Ethereum-compatible hashing to [firewood-go-ethhash](https://github.com/ava-labs/firewood-go-ethhash) with `ethhash` enabled by default. To use Firewood's native hashing structure, you must still build the static library separately. + +## Development + +Iterative building is unintuitive for the ffi and some common sources of confusion are listed below. + +### CGO Regeneration + +As you edit any Rust code and save the file in VS Code, the `firewood.h` file is automatically updated with edited function and struct definitions. However, the Go linter will not recognize these changes until you manually regenerate the cgo wrappers. To do this, you can run `go tool cgo firewood.go`. Alternatively, in VS Code, right above the `import "C"` definition, you can click on the small letters saying "regenerate CGO definitions". This will allow the linter to use the altered definitions. + +Because the C header file is autogenerated from the Rust code, the naming matches exactly (due to the `no_mangle` macro). However, the C definitions imported in Go do not match exactly, and are prefixed with `struct_`. Function naming is the same as the header file. These names are generated by the `go tool cgo` command above. + +It is possible that your editor does not properly recognize the C bindings, due to the nature of multi-module workspaces. If the Go code still compiles, this is likely the issue. To fix this, you can just `./scripts/run_just.sh setup-go-workspace` from the repository root and refresh your editor. Changes to the go workspace should not be checked in. + +### Testing + +Although the VS Code testing feature does work, there are some quirks in ensuring proper building. The Rust code must be compiled separated, and sometimes the `go test` command continues to use a cached result. Whenever testing after making changes to the Rust/C builds, the cache should be cleared if results don't seem correct. The Go testing suite can determine dynamically whether ethhash is enabled or not, so it can be run with either configuration. For each individual testing module, ensure the hashing method you compiled with matches the test. + +To ensure there are no memory leaks, the easiest way is to use your preferred CLI tool (e.g. `valgrind` for Linux, `leaks` for macOS) and compile the tests into a binary. You must not compile a release binary to ensure all memory can be managed. An example flow is given below. + +```sh +cd ffi +cargo build # use debug +go test -a -c -o binary_file # ignore cache +leaks --nostacks --atExit -- ./binary_file +``` diff --git a/firewood/ffi/build.rs b/firewood/ffi/build.rs new file mode 100644 index 000000000000..4a37d783294a --- /dev/null +++ b/firewood/ffi/build.rs @@ -0,0 +1,27 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::env; + +extern crate cbindgen; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR is not set"); + + let config = cbindgen::Config::from_file("cbindgen.toml").expect("cbindgen.toml is present"); + + cbindgen::Builder::new() + .with_crate(crate_dir) + // Add any additional configuration options here + .with_config(config) + .generate() + .map_or_else( + |error| match error { + cbindgen::Error::ParseSyntaxError { .. } => {} + e => panic!("{e:?}"), + }, + |bindings| { + bindings.write_to_file("firewood.h"); + }, + ); +} diff --git a/firewood/ffi/cbindgen.toml b/firewood/ffi/cbindgen.toml new file mode 100644 index 000000000000..0369f02b1c21 --- /dev/null +++ b/firewood/ffi/cbindgen.toml @@ -0,0 +1,135 @@ +# This is a template cbindgen.toml file with all of the default values. +# Some values are commented out because their absence is the real default. +# +# See https://github.com/mozilla/cbindgen/blob/master/docs.md#cbindgentoml +# for detailed documentation of every option here. + + +language = "C" + + +############## Options for Wrapping the Contents of the Header ################# + +# header = "/* Text to put at the beginning of the generated file. Probably a license. */" +header = """// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// This file was @generated by cbindgen. Do not edit this file manually. +// Run `cargo build --target firewood-ffi` to regenerate this file.""" + +# trailer = "/* Text to put at the end of the generated file */" +# include_guard = "my_bindings_h" +# pragma_once = true +# autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" +include_version = false +# namespace = "my_namespace" +namespaces = [] +using_namespaces = [] +sys_includes = [] +includes = [] +no_includes = false +# cpp_compat = true +after_includes = "" + + +############################ Code Style Options ################################ + +braces = "SameLine" +line_length = 100 +tab_width = 2 +documentation = true +documentation_style = "auto" +documentation_length = "full" +line_endings = "LF" # also "CR", "CRLF", "Native" + + +############################# Codegen Options ################################## + +style = "both" +sort_by = "Name" # default for `fn.sort_by` and `const.sort_by` +usize_is_size_t = true + +[defines] +# "target_os = freebsd" = "DEFINE_FREEBSD" +# "feature = serde" = "DEFINE_SERDE" + +[export] +include = [] +exclude = [] +# prefix = "CAPI_" +item_types = [] +renaming_overrides_prefixing = false + +[export.rename] +"Db" = "void" + +[export.body] + +[export.mangle] + +[fn] +rename_args = "None" +# must_use = "MUST_USE_FUNC" +# deprecated = "DEPRECATED_FUNC" +# deprecated_with_note = "DEPRECATED_FUNC_WITH_NOTE" +# no_return = "NO_RETURN" +# prefix = "START_FUNC" +# postfix = "END_FUNC" +args = "auto" +sort_by = "Name" + +[struct] +rename_fields = "None" +# must_use = "MUST_USE_STRUCT" +# deprecated = "DEPRECATED_STRUCT" +# deprecated_with_note = "DEPRECATED_STRUCT_WITH_NOTE" +derive_constructor = false +derive_eq = false +derive_neq = false +derive_lt = false +derive_lte = false +derive_gt = false +derive_gte = false + +[enum] +rename_variants = "None" +# must_use = "MUST_USE_ENUM" +# deprecated = "DEPRECATED_ENUM" +# deprecated_with_note = "DEPRECATED_ENUM_WITH_NOTE" +add_sentinel = false +prefix_with_name = true +derive_helper_methods = false +derive_const_casts = false +derive_mut_casts = false +# cast_assert_name = "ASSERT" +derive_tagged_enum_destructor = false +derive_tagged_enum_copy_constructor = false +enum_class = true +private_default_tagged_enum_constructor = false + + +[const] +allow_static_const = true +allow_constexpr = false +sort_by = "Name" + + +[macro_expansion] +bitflags = false + + +############## Options for How Your Rust library Should Be Parsed ############## + +[parse] +parse_deps = false +# include = [] +exclude = [] +clean = false +extra_bindings = [] + + +[parse.expand] +crates = [] +all_features = false +default_features = true +features = [] diff --git a/firewood/ffi/firewood.go b/firewood/ffi/firewood.go new file mode 100644 index 000000000000..c6d4c17f4e47 --- /dev/null +++ b/firewood/ffi/firewood.go @@ -0,0 +1,357 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// Package ffi provides a Go wrapper around the [Firewood] database. +// +// [Firewood]: https://github.com/ava-labs/firewood +package ffi + +//go:generate go run generate_cgo.go + +// // Note that -lm is required on Linux but not on Mac. +// // FIREWOOD_CGO_BEGIN_STATIC_LIBS +// // #cgo linux,amd64 LDFLAGS: -L${SRCDIR}/libs/x86_64-unknown-linux-gnu +// // #cgo linux,arm64 LDFLAGS: -L${SRCDIR}/libs/aarch64-unknown-linux-gnu +// // #cgo darwin,amd64 LDFLAGS: -L${SRCDIR}/libs/x86_64-apple-darwin +// // #cgo darwin,arm64 LDFLAGS: -L${SRCDIR}/libs/aarch64-apple-darwin +// // FIREWOOD_CGO_END_STATIC_LIBS +// // FIREWOOD_CGO_BEGIN_LOCAL_LIBS +// #cgo LDFLAGS: -L${SRCDIR}/../target/debug +// #cgo LDFLAGS: -L${SRCDIR}/../target/release +// #cgo LDFLAGS: -L${SRCDIR}/../target/maxperf +// // FIREWOOD_CGO_END_LOCAL_LIBS +// #cgo LDFLAGS: -lfirewood_ffi -lm +// #include +// #include "firewood.h" +import "C" + +import ( + "context" + "errors" + "fmt" + "runtime" + "sync" +) + +// RootLength is the hash length for all Firewood hashes. +const RootLength = C.sizeof_HashKey + +// Hash is the type used for all firewood hashes. +type Hash [RootLength]byte + +var ( + // EmptyRoot is the zero value for [Hash] + EmptyRoot Hash + // ErrActiveKeepAliveHandles is returned when attempting to close a database with unfreed memory. + ErrActiveKeepAliveHandles = errors.New("cannot close database with active keep-alive handles") + + errDBClosed = errors.New("firewood database already closed") +) + +// Database is an FFI wrapper for the Rust Firewood database. +// All functions rely on CGO to call into the underlying Rust implementation. +// Instances are created via [New] and must be closed with [Database.Close] +// when no longer needed. +// +// A Database can have outstanding [Revision] and [Proposal], which +// access the database's memory. These must be released before closing the +// database. See [Database.Close] for more details. +// +// Database supports two hashing modes: Firewood hashing and Ethereum-compatible +// hashing. Ethereum-compatible hashing is distributed, but you can use the more efficient +// Firewood hashing by compiling from source. See the Firewood repository for more details. +// +// For concurrent use cases, see each type and method's documentation for thread-safety. +type Database struct { + // handle is returned and accepted by cgo functions. It MUST be treated as + // an opaque value without special meaning. + // https://en.wikipedia.org/wiki/Blinkenlights + handle *C.DatabaseHandle + outstandingHandles sync.WaitGroup +} + +// Config defines the configuration parameters used when opening a [Database]. +type Config struct { + // Truncate indicates whether to clear the database file if it already exists. + Truncate bool + // NodeCacheEntries is the number of entries in the cache. + // Must be non-zero. + NodeCacheEntries uint + // FreeListCacheEntries is the number of entries in the freelist cache. + // Must be non-zero. + FreeListCacheEntries uint + // Revisions is the maximum number of historical revisions to keep in memory. + // If RootStoreDir is set, then any revisions removed from memory will still be kept on disk. + // Otherwise, any revisions removed from memory will no longer be kept on disk. + // Must be >= 2. + Revisions uint + // ReadCacheStrategy is the caching strategy used for the node cache. + ReadCacheStrategy CacheStrategy + // RootStoreDir defines a path to store all historical roots on disk. + RootStoreDir string +} + +// DefaultConfig returns a [*Config] with sensible defaults: +// - NodeCacheEntries: 1_000_000 +// - FreeListCacheEntries: 40_000 +// - Revisions: 100 +// - ReadCacheStrategy: OnlyCacheWrites +func DefaultConfig() *Config { + return &Config{ + NodeCacheEntries: 1_000_000, + FreeListCacheEntries: 40_000, + Revisions: 100, + ReadCacheStrategy: OnlyCacheWrites, + } +} + +// A CacheStrategy represents the caching strategy used by a [Database]. +type CacheStrategy uint8 + +const ( + // OnlyCacheWrites caches only writes. + OnlyCacheWrites CacheStrategy = iota + // CacheBranchReads caches intermediate reads and writes. + CacheBranchReads + // CacheAllReads caches all reads and writes. + CacheAllReads + + // invalidCacheStrategy MUST be the final value in the iota block to make it + // the smallest value greater than all valid values. + invalidCacheStrategy +) + +// New opens or creates a new Firewood database with the given configuration. If +// a nil config is provided, [DefaultConfig] will be used instead. +// The database file will be created at the provided file path if it does not +// already exist. +// +// It is the caller's responsibility to call [Database.Close] when the database +// is no longer needed. No other [Database] in this process should be opened with +// the same file path until the database is closed. +func New(filePath string, conf *Config) (*Database, error) { + if conf == nil { + conf = DefaultConfig() + } + if conf.ReadCacheStrategy >= invalidCacheStrategy { + return nil, fmt.Errorf("invalid %T (%[1]d)", conf.ReadCacheStrategy) + } + if conf.Revisions < 2 { + return nil, fmt.Errorf("%T.Revisions must be >= 2", conf) + } + if conf.NodeCacheEntries < 1 { + return nil, fmt.Errorf("%T.NodeCacheEntries must be >= 1", conf) + } + if conf.FreeListCacheEntries < 1 { + return nil, fmt.Errorf("%T.FreeListCacheEntries must be >= 1", conf) + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.struct_DatabaseHandleArgs{ + path: newBorrowedBytes([]byte(filePath), &pinner), + cache_size: C.size_t(conf.NodeCacheEntries), + free_list_cache_size: C.size_t(conf.FreeListCacheEntries), + revisions: C.size_t(conf.Revisions), + strategy: C.uint8_t(conf.ReadCacheStrategy), + truncate: C.bool(conf.Truncate), + root_store_path: newBorrowedBytes([]byte(conf.RootStoreDir), &pinner), + } + + return getDatabaseFromHandleResult(C.fwd_open_db(args)) +} + +// Update applies a batch of updates to the database, returning the hash of the +// root node after the batch is applied. This is equilalent to creating a proposal +// with [Database.Propose], then committing it with [Proposal.Commit]. +// +// Value Semantics: +// - nil value (vals[i] == nil): Performs a DeleteRange operation using the key as a prefix +// - empty slice (vals[i] != nil && len(vals[i]) == 0): Inserts/updates the key with an empty value +// - non-empty value: Inserts/updates the key with the provided value +// +// WARNING: Calling Update with an empty key and nil value will delete the entire database +// due to prefix deletion semantics. +// +// This function is not thread-safe with respect to other calls that reference the latest +// state of the database, nor any calls that mutate the state of the database. +func (db *Database) Update(keys, vals [][]byte) (Hash, error) { + if db.handle == nil { + return EmptyRoot, errDBClosed + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + kvp, err := newKeyValuePairs(keys, vals, &pinner) + if err != nil { + return EmptyRoot, err + } + + return getHashKeyFromHashResult(C.fwd_batch(db.handle, kvp)) +} + +// Propose creates a new proposal with the given keys and values. The proposal +// is not committed until [Proposal.Commit] is called. See [Database.Close] regarding +// freeing proposals. All proposals should be freed before closing the database. +// +// Value Semantics: +// - nil value (vals[i] == nil): Performs a DeleteRange operation using the key as a prefix +// - empty slice (vals[i] != nil && len(vals[i]) == 0): Inserts/updates the key with an empty value +// - non-empty value: Inserts/updates the key with the provided value +// +// This function is not thread-safe with respect to other calls that reference the latest +// state of the database, nor any calls that mutate the latest state of the database. +func (db *Database) Propose(keys, vals [][]byte) (*Proposal, error) { + if db.handle == nil { + return nil, errDBClosed + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + kvp, err := newKeyValuePairs(keys, vals, &pinner) + if err != nil { + return nil, err + } + return getProposalFromProposalResult(C.fwd_propose_on_db(db.handle, kvp), &db.outstandingHandles) +} + +// Get retrieves the value for the given key from the most recent revision. +// If the key is not found, the return value will be nil. +// +// This function is thread-safe with all other read operations, but is not thread-safe +// with respect to other calls that mutate the latest state of the database. +func (db *Database) Get(key []byte) ([]byte, error) { + if db.handle == nil { + return nil, errDBClosed + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + val, err := getValueFromValueResult(C.fwd_get_latest(db.handle, newBorrowedBytes(key, &pinner))) + // The revision won't be found if the database is empty. + // This is valid, but should be treated as a non-existent key + if errors.Is(err, errRevisionNotFound) { + return nil, nil + } + + return val, err +} + +// GetFromRoot retrieves the value for the given key from a specific root hash. +// If the root is not found, it returns an error. +// If key is not found, it returns nil. +// +// GetFromRoot caches a handle to the revision associated with the provided root hash, allowing +// subsequent calls with the same root to be more efficient. +// +// This function is thread-safe with all other operations. +func (db *Database) GetFromRoot(root Hash, key []byte) ([]byte, error) { + if db.handle == nil { + return nil, errDBClosed + } + + // If the root is empty, the database is empty. + if root == EmptyRoot { + return nil, nil + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + return getValueFromValueResult(C.fwd_get_from_root( + db.handle, + newCHashKey(root), + newBorrowedBytes(key, &pinner), + )) +} + +// Root returns the current root hash of the trie. +// With Firewood hashing, the empty trie must return [EmptyRoot]. +// +// This function is thread-safe with all other operations, except those that mutate +// the latest state of the database. +func (db *Database) Root() (Hash, error) { + if db.handle == nil { + return EmptyRoot, errDBClosed + } + + return getHashKeyFromHashResult(C.fwd_root_hash(db.handle)) +} + +// LatestRevision returns a [Revision] representing the latest state of the database. +// If the latest revision has root [EmptyRoot], it returns an error. The [Revision] must +// be dropped prior to closing the database. +// +// This function is thread-safe with all other operations, except those that mutate +// the latest state of the database. +func (db *Database) LatestRevision() (*Revision, error) { + root, err := db.Root() + if err != nil { + return nil, err + } + if root == EmptyRoot { + return nil, errRevisionNotFound + } + return db.Revision(root) +} + +// Revision returns a historical revision of the database. +// If the provided root does not exist (or is the [EmptyRoot]), it returns an error. +// The [Revision] must be dropped prior to closing the database. +// +// This function is thread-safe with all other operations. +func (db *Database) Revision(root Hash) (*Revision, error) { + rev, err := getRevisionFromResult(C.fwd_get_revision( + db.handle, + newCHashKey(root), + ), &db.outstandingHandles) + if err != nil { + return nil, err + } + + return rev, nil +} + +// Close releases the memory associated with the Database. +// +// This blocks until all outstanding keep-alive handles are disowned or the +// [context.Context] is cancelled. That is, until all Revisions and Proposals +// created from this Database are either unreachable or one of +// [Proposal.Commit], [Proposal.Drop], or [Revision.Drop] has been called on +// them. Unreachable objects will be automatically dropped before Close returns, +// unless an alternate GC finalizer is set on them. +// +// This is safe to call multiple times; subsequent calls after the first will do +// nothing. However, it is not safe to call this method concurrently from multiple +// goroutines. +func (db *Database) Close(ctx context.Context) error { + if db.handle == nil { + return nil + } + + go runtime.GC() + + done := make(chan struct{}) + go func() { + db.outstandingHandles.Wait() + close(done) + }() + + select { + case <-done: + case <-ctx.Done(): + return fmt.Errorf("%w: %w", ctx.Err(), ErrActiveKeepAliveHandles) + } + + if err := getErrorFromVoidResult(C.fwd_close_db(db.handle)); err != nil { + return fmt.Errorf("unexpected error when closing database: %w", err) + } + + db.handle = nil // Prevent double free + + return nil +} diff --git a/firewood/ffi/firewood.h b/firewood/ffi/firewood.h new file mode 100644 index 000000000000..1955ac86d8b7 --- /dev/null +++ b/firewood/ffi/firewood.h @@ -0,0 +1,2008 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// This file was @generated by cbindgen. Do not edit this file manually. +// Run `cargo build --target firewood-ffi` to regenerate this file. + +#include +#include +#include +#include +#include + + +/** + * FFI context for a parsed or generated change proof. + */ +typedef struct ChangeProofContext ChangeProofContext; + +/** + * A handle to the database, returned by `fwd_open_db`. + * + * These handles are passed to the other FFI functions. + * + */ +typedef struct DatabaseHandle DatabaseHandle; + +/** + * An opaque wrapper around a [`BoxKeyValueIter`]. + */ +typedef struct IteratorHandle IteratorHandle; + +/** + * An opaque wrapper around a Proposal that also retains a reference to the + * database handle it was created from. + */ +typedef struct ProposalHandle ProposalHandle; + +/** + * FFI context for for a parsed or generated range proof. + */ +typedef struct RangeProofContext RangeProofContext; + +typedef struct RevisionHandle RevisionHandle; + +/** + * A database hash key, used in FFI functions that require hashes. + * This type requires no allocation and can be copied freely and + * dropped without any additional overhead. + * + * This is useful because it is the same size as 4 words which is equivalent + * to 2 heap-allocated slices (pointer + length each), or 1.5 vectors (which + * uses an extra word for allocation capacity) and it can be passed around + * without needing to allocate or deallocate memory. + */ +typedef struct HashKey { + uint8_t _0[32]; +} HashKey; + +/** + * A Rust-owned vector of bytes that can be passed to C code. + * + * C callers must free this memory using the respective FFI function for the + * concrete type (but not using the `free` function from the C standard library). + */ +typedef struct OwnedSlice_u8 { + uint8_t *ptr; + size_t len; +} OwnedSlice_u8; + +/** + * A type alias for a rust-owned byte slice. + */ +typedef struct OwnedSlice_u8 OwnedBytes; + +/** + * A result type returned from FFI functions return the database root hash. This + * may or may not be after a mutation. + */ +typedef enum HashResult_Tag { + /** + * The caller provided a null pointer to a database handle. + */ + HashResult_NullHandlePointer, + /** + * The proposal resulted in an empty database or the database currently has + * no root hash. + */ + HashResult_None, + /** + * The mutation was successful and the root hash is returned, if this result + * was from a mutation. Otherwise, this is the current root hash of the + * database. + */ + HashResult_Some, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. If + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + HashResult_Err, +} HashResult_Tag; + +typedef struct HashResult { + HashResult_Tag tag; + union { + struct { + struct HashKey some; + }; + struct { + OwnedBytes err; + }; + }; +} HashResult; + +/** + * A borrowed byte slice. Used to represent data that was passed in from C + * callers and will not be freed or retained by Rust code. + */ +typedef struct BorrowedSlice_u8 { + /** + * A pointer to the slice of bytes. This can be null if the slice is empty. + * + * If the pointer is not null, it must point to a valid slice of `len` + * elements sized and aligned for `T`. + * + * As a note, [`NonNull`] is not appropriate here because [`NonNull`] pointer + * provenance requires mutable access to the pointer, which is not an invariant + * we want to enforce here. We want (and require) the pointer to be immutable. + * + * [`NonNull`]: std::ptr::NonNull + */ + const uint8_t *ptr; + /** + * The length of the slice. It is ignored if the pointer is null; however, + * if the pointer is not null, it must be equal to the number of elements + * pointed to by `ptr`. + */ + size_t len; +} BorrowedSlice_u8; + +/** + * A type alias for a borrowed byte slice. + * + * C callers can use this to pass in a byte slice that will not be freed by Rust + * code. + * + * C callers must ensure that the pointer, if not null, points to a valid slice + * of bytes of length `len`. C callers must also ensure that the slice is valid + * for the duration of the C function call that was passed this slice. + */ +typedef struct BorrowedSlice_u8 BorrowedBytes; + +/** + * A `KeyValue` represents a key-value pair, passed to the FFI. + */ +typedef struct KeyValuePair { + BorrowedBytes key; + BorrowedBytes value; +} KeyValuePair; + +/** + * A borrowed byte slice. Used to represent data that was passed in from C + * callers and will not be freed or retained by Rust code. + */ +typedef struct BorrowedSlice_KeyValuePair { + /** + * A pointer to the slice of bytes. This can be null if the slice is empty. + * + * If the pointer is not null, it must point to a valid slice of `len` + * elements sized and aligned for `T`. + * + * As a note, [`NonNull`] is not appropriate here because [`NonNull`] pointer + * provenance requires mutable access to the pointer, which is not an invariant + * we want to enforce here. We want (and require) the pointer to be immutable. + * + * [`NonNull`]: std::ptr::NonNull + */ + const struct KeyValuePair *ptr; + /** + * The length of the slice. It is ignored if the pointer is null; however, + * if the pointer is not null, it must be equal to the number of elements + * pointed to by `ptr`. + */ + size_t len; +} BorrowedSlice_KeyValuePair; + +/** + * A type alias for a borrowed slice of [`KeyValuePair`]s. + * + * C callers can use this to pass in a slice of key-value pairs that will not + * be freed by Rust code. + * + * C callers must ensure that the pointer, if not null, points to a valid slice + * of key-value pairs of length `len`. C callers must also ensure that the slice + * is valid for the duration of the C function call that was passed this slice. + */ +typedef struct BorrowedSlice_KeyValuePair BorrowedKeyValuePairs; + +/** + * Maybe is a C-compatible optional type using a tagged union pattern. + * + * FFI methods and types can use this to represent optional values where `Optional` + * does not work due to it not having a C-compatible layout. + */ +typedef enum Maybe_OwnedBytes_Tag { + /** + * No value present. + */ + Maybe_OwnedBytes_None_OwnedBytes, + /** + * A value is present. + */ + Maybe_OwnedBytes_Some_OwnedBytes, +} Maybe_OwnedBytes_Tag; + +typedef struct Maybe_OwnedBytes { + Maybe_OwnedBytes_Tag tag; + union { + struct { + OwnedBytes some; + }; + }; +} Maybe_OwnedBytes; + +/** + * A key range that should be fetched to continue iterating through a range + * or change proof that was truncated. Represents a half-open range + * `[start_key, end_key)`. If `end_key` is `None`, the range is unbounded + * and continues to the end of the keyspace. + */ +typedef struct NextKeyRange { + /** + * The start key of the next range to fetch. + */ + OwnedBytes start_key; + /** + * If set, a non-inclusive upper bound for the next range to fetch. If not + * set, the range is unbounded (this is the final range). + */ + struct Maybe_OwnedBytes end_key; +} NextKeyRange; + +typedef enum NextKeyRangeResult_Tag { + /** + * The caller provided a null pointer to the input handle. + */ + NextKeyRangeResult_NullHandlePointer, + /** + * The proof has not prepared into a proposal nor committed to the database. + */ + NextKeyRangeResult_NotPrepared, + /** + * There are no more keys to fetch. + */ + NextKeyRangeResult_None, + /** + * The next key range to fetch is returned. + */ + NextKeyRangeResult_Some, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. If + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + NextKeyRangeResult_Err, +} NextKeyRangeResult_Tag; + +typedef struct NextKeyRangeResult { + NextKeyRangeResult_Tag tag; + union { + struct { + struct NextKeyRange some; + }; + struct { + OwnedBytes err; + }; + }; +} NextKeyRangeResult; + +/** + * A result type returned from FFI functions that create or parse change proofs. + * + * The caller must ensure that [`fwd_free_change_proof`] is called to + * free the memory associated with the returned context when it is no longer + * needed. + * + * [`fwd_free_change_proof`]: crate::fwd_free_change_proof + */ +typedef enum ChangeProofResult_Tag { + /** + * The caller provided a null pointer to the input handle. + */ + ChangeProofResult_NullHandlePointer, + /** + * The provided root was not found in the database. + */ + ChangeProofResult_RevisionNotFound, + /** + * The proof was successfully created or parsed. + * + * If the value was parsed from a serialized proof, this does not imply that + * the proof is valid, only that it is well-formed. The verify method must + * be called to ensure the proof is cryptographically valid. + */ + ChangeProofResult_Ok, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. If + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + ChangeProofResult_Err, +} ChangeProofResult_Tag; + +typedef struct ChangeProofResult { + ChangeProofResult_Tag tag; + union { + struct { + struct HashKey revision_not_found; + }; + struct { + struct ChangeProofContext *ok; + }; + struct { + OwnedBytes err; + }; + }; +} ChangeProofResult; + +/** + * A result type returned from FFI functions that retrieve a single value. + */ +typedef enum ValueResult_Tag { + /** + * The caller provided a null pointer to a database handle. + */ + ValueResult_NullHandlePointer, + /** + * The provided root was not found in the database. + */ + ValueResult_RevisionNotFound, + /** + * The provided key was not found in the database or proposal. + */ + ValueResult_None, + /** + * A value was found and is returned. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this value. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + ValueResult_Some, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. If + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + ValueResult_Err, +} ValueResult_Tag; + +typedef struct ValueResult { + ValueResult_Tag tag; + union { + struct { + struct HashKey revision_not_found; + }; + struct { + OwnedBytes some; + }; + struct { + OwnedBytes err; + }; + }; +} ValueResult; + +/** + * The result type returned from an FFI function that returns no value but may + * return an error. + */ +typedef enum VoidResult_Tag { + /** + * The caller provided a null pointer to the input handle. + */ + VoidResult_NullHandlePointer, + /** + * The operation was successful and no error occurred. + */ + VoidResult_Ok, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. Its + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + VoidResult_Err, +} VoidResult_Tag; + +typedef struct VoidResult { + VoidResult_Tag tag; + union { + struct { + OwnedBytes err; + }; + }; +} VoidResult; + +/** + * Maybe is a C-compatible optional type using a tagged union pattern. + * + * FFI methods and types can use this to represent optional values where `Optional` + * does not work due to it not having a C-compatible layout. + */ +typedef enum Maybe_BorrowedBytes_Tag { + /** + * No value present. + */ + Maybe_BorrowedBytes_None_BorrowedBytes, + /** + * A value is present. + */ + Maybe_BorrowedBytes_Some_BorrowedBytes, +} Maybe_BorrowedBytes_Tag; + +typedef struct Maybe_BorrowedBytes { + Maybe_BorrowedBytes_Tag tag; + union { + struct { + BorrowedBytes some; + }; + }; +} Maybe_BorrowedBytes; + +/** + * Arguments for creating a change proof. + */ +typedef struct CreateChangeProofArgs { + /** + * The root hash of the starting revision. This must be provided. + * If the root is not found in the database, the function will return + * [`ChangeProofResult::RevisionNotFound`]. + */ + struct HashKey start_root; + /** + * The root hash of the ending revision. This must be provided. + * If the root is not found in the database, the function will return + * [`ChangeProofResult::RevisionNotFound`]. + */ + struct HashKey end_root; + /** + * The start key of the range to create the proof for. If `None`, the range + * starts from the beginning of the keyspace. + */ + struct Maybe_BorrowedBytes start_key; + /** + * The end key of the range to create the proof for. If `None`, the range + * ends at the end of the keyspace or until `max_length` items have been + * included in the proof. + */ + struct Maybe_BorrowedBytes end_key; + /** + * The maximum number of key/value pairs to include in the proof. If the + * range contains more items than this, the proof will be truncated. If + * `0`, there is no limit. + */ + uint32_t max_length; +} CreateChangeProofArgs; + +/** + * A result type returned from FFI functions that create or parse range proofs. + * + * The caller must ensure that [`fwd_free_range_proof`] is called to + * free the memory associated with the returned context when it is no longer + * needed. + * + * [`fwd_free_range_proof`]: crate::fwd_free_range_proof + */ +typedef enum RangeProofResult_Tag { + /** + * The caller provided a null pointer to the input handle. + */ + RangeProofResult_NullHandlePointer, + /** + * The provided root was not found in the database. + */ + RangeProofResult_RevisionNotFound, + /** + * A range proof was requested on an empty trie. + */ + RangeProofResult_EmptyTrie, + /** + * The proof was successfully created or parsed. + * + * If the value was parsed from a serialized proof, this does not imply that + * the proof is valid, only that it is well-formed. The verify method must + * be called to ensure the proof is cryptographically valid. + */ + RangeProofResult_Ok, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. If + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + RangeProofResult_Err, +} RangeProofResult_Tag; + +typedef struct RangeProofResult { + RangeProofResult_Tag tag; + union { + struct { + struct HashKey revision_not_found; + }; + struct { + struct RangeProofContext *ok; + }; + struct { + OwnedBytes err; + }; + }; +} RangeProofResult; + +/** + * Arguments for creating a range proof. + */ +typedef struct CreateRangeProofArgs { + /** + * The root hash of the revision to prove. + */ + struct HashKey root; + /** + * The start key of the range to prove. If `None`, the range starts from the + * beginning of the keyspace. + * + * The start key must be less than the end key if both are provided. + */ + struct Maybe_BorrowedBytes start_key; + /** + * The end key of the range to prove. If `None`, the range ends at the end + * of the keyspace or until `max_length` items have been been included in + * the proof. + * + * If provided, end key is inclusive if not truncated. Otherwise, the end + * key will be the final key in the returned key-value pairs. + */ + struct Maybe_BorrowedBytes end_key; + /** + * The maximum number of key/value pairs to include in the proof. If the + * range contains more items than this, the proof will be truncated. If + * `0`, there is no limit. + */ + uint32_t max_length; +} CreateRangeProofArgs; + +/** + * Arguments for verifying a change proof. + */ +typedef struct VerifyChangeProofArgs { + /** + * The change proof to verify. If null, the function will return + * [`VoidResult::NullHandlePointer`]. We need a mutable reference to + * update the validation context. + */ + struct ChangeProofContext *proof; + /** + * The root hash of the starting revision. This must match the starting + * root of the proof. + */ + struct HashKey start_root; + /** + * The root hash of the ending revision. This must match the ending root of + * the proof. + */ + struct HashKey end_root; + /** + * The lower bound of the key range that the proof is expected to cover. If + * `None`, the proof is expected to cover from the start of the keyspace. + */ + struct Maybe_BorrowedBytes start_key; + /** + * The upper bound of the key range that the proof is expected to cover. If + * `None`, the proof is expected to cover to the end of the keyspace. + */ + struct Maybe_BorrowedBytes end_key; + /** + * The maximum number of key/value pairs that the proof is expected to cover. + * If the proof contains more items than this, it is considered invalid. If + * `0`, there is no limit. + */ + uint32_t max_length; +} VerifyChangeProofArgs; + +/** + * Arguments for verifying a range proof. + */ +typedef struct VerifyRangeProofArgs { + /** + * The range proof to verify. If null, the function will return + * [`VoidResult::NullHandlePointer`]. We need a mutable reference to + * update the validation context. + */ + struct RangeProofContext *proof; + /** + * The root hash to verify the proof against. This must match the calculated + * hash of the root of the proof. + */ + struct HashKey root; + /** + * The lower bound of the key range that the proof is expected to cover. If + * `None`, the proof is expected to cover from the start of the keyspace. + * + * Must be present if the range proof contains a lower bound proof and must + * be absent if the range proof does not contain a lower bound proof. + */ + struct Maybe_BorrowedBytes start_key; + /** + * The upper bound of the key range that the proof is expected to cover. If + * `None`, the proof is expected to cover to the end of the keyspace. + * + * This is ignored if the proof is truncated and does not cover the full, + * in which case the upper bound key is the final key in the key-value pairs. + */ + struct Maybe_BorrowedBytes end_key; + /** + * The maximum number of key/value pairs that the proof is expected to cover. + * If the proof contains more items than this, it is considered invalid. If + * `0`, there is no limit. + */ + uint32_t max_length; +} VerifyRangeProofArgs; + +/** + * Owned version of `KeyValuePair`, returned to ffi callers. + * + * C callers must free this using [`crate::fwd_free_owned_kv_pair`], + * not the C standard library's `free` function. + */ +typedef struct OwnedKeyValuePair { + OwnedBytes key; + OwnedBytes value; +} OwnedKeyValuePair; + +/** + * A Rust-owned vector of bytes that can be passed to C code. + * + * C callers must free this memory using the respective FFI function for the + * concrete type (but not using the `free` function from the C standard library). + */ +typedef struct OwnedSlice_OwnedKeyValuePair { + struct OwnedKeyValuePair *ptr; + size_t len; +} OwnedSlice_OwnedKeyValuePair; + +/** + * A type alias for a rust-owned byte slice. + */ +typedef struct OwnedSlice_OwnedKeyValuePair OwnedKeyValueBatch; + +/** + * A result type returned from FFI functions that get a revision + */ +typedef enum RevisionResult_Tag { + /** + * The caller provided a null pointer to a database handle. + */ + RevisionResult_NullHandlePointer, + /** + * The provided root was not found in the database. + */ + RevisionResult_RevisionNotFound, + /** + * Getting the revision was successful and the revision handle and root + * hash are returned. + */ + RevisionResult_Ok, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. The + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + RevisionResult_Err, +} RevisionResult_Tag; + +typedef struct RevisionResult_Ok_Body { + /** + * An opaque pointer to the [`RevisionHandle`]. + * The value should be freed with [`fwd_free_revision`] + * + * [`fwd_free_revision`]: crate::fwd_free_revision + */ + struct RevisionHandle *handle; + /** + * The root hash of the revision. + */ + struct HashKey root_hash; +} RevisionResult_Ok_Body; + +typedef struct RevisionResult { + RevisionResult_Tag tag; + union { + struct { + struct HashKey revision_not_found; + }; + RevisionResult_Ok_Body ok; + struct { + OwnedBytes err; + }; + }; +} RevisionResult; + +/** + * A result type returned from iterator FFI functions + */ +typedef enum KeyValueResult_Tag { + /** + * The caller provided a null pointer to an iterator handle. + */ + KeyValueResult_NullHandlePointer, + /** + * The iterator is exhausted + */ + KeyValueResult_None, + /** + * The next item is returned. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with the key and the value of this pair. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + KeyValueResult_Some, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. The + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + KeyValueResult_Err, +} KeyValueResult_Tag; + +typedef struct KeyValueResult { + KeyValueResult_Tag tag; + union { + struct { + struct OwnedKeyValuePair some; + }; + struct { + OwnedBytes err; + }; + }; +} KeyValueResult; + +/** + * A result type returned from iterator FFI functions + */ +typedef enum KeyValueBatchResult_Tag { + /** + * The caller provided a null pointer to an iterator handle. + */ + KeyValueBatchResult_NullHandlePointer, + /** + * The next batch of items on iterator are returned. + */ + KeyValueBatchResult_Some, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. If + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + KeyValueBatchResult_Err, +} KeyValueBatchResult_Tag; + +typedef struct KeyValueBatchResult { + KeyValueBatchResult_Tag tag; + union { + struct { + OwnedKeyValueBatch some; + }; + struct { + OwnedBytes err; + }; + }; +} KeyValueBatchResult; + +/** + * A result type returned from FFI functions that create an iterator + */ +typedef enum IteratorResult_Tag { + /** + * The caller provided a null pointer to a revision/proposal handle. + */ + IteratorResult_NullHandlePointer, + /** + * Building the iterator was successful and the iterator handle is returned + */ + IteratorResult_Ok, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + IteratorResult_Err, +} IteratorResult_Tag; + +typedef struct IteratorResult_Ok_Body { + /** + * An opaque pointer to the [`IteratorHandle`]. + * The value should be freed with [`fwd_free_iterator`] + * + * [`fwd_free_iterator`]: crate::fwd_free_iterator + */ + struct IteratorHandle *handle; +} IteratorResult_Ok_Body; + +typedef struct IteratorResult { + IteratorResult_Tag tag; + union { + IteratorResult_Ok_Body ok; + struct { + OwnedBytes err; + }; + }; +} IteratorResult; + +/** + * The result type returned from the open or create database functions. + */ +typedef enum HandleResult_Tag { + /** + * The database was opened or created successfully and the handle is + * returned as an opaque pointer. + * + * The caller must ensure that [`fwd_close_db`] is called to free resources + * associated with this handle when it is no longer needed. + * + * [`fwd_close_db`]: crate::fwd_close_db + */ + HandleResult_Ok, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. If + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + HandleResult_Err, +} HandleResult_Tag; + +typedef struct HandleResult { + HandleResult_Tag tag; + union { + struct { + struct DatabaseHandle *ok; + }; + struct { + OwnedBytes err; + }; + }; +} HandleResult; + +/** + * Arguments for creating or opening a database. These are passed to [`fwd_open_db`] + * + * [`fwd_open_db`]: crate::fwd_open_db + */ +typedef struct DatabaseHandleArgs { + /** + * The path to the database file. + * + * This must be a valid UTF-8 string, even on Windows. + * + * If this is empty, an error will be returned. + */ + BorrowedBytes path; + /** + * The path to the `RootStore` directory. + * + * This must be a valid UTF-8 string, even on Windows. + * + * If this is empty, then the archival feature is disabled. + * + * Note: Setting this directory will only track new revisions going forward + * and will not contain revisions from a prior database instance that didn't + * set a `root_store_path`. + */ + BorrowedBytes root_store_path; + /** + * The size of the node cache. + * + * Opening returns an error if this is zero. + */ + size_t cache_size; + /** + * The size of the free list cache. + * + * Opening returns an error if this is zero. + */ + size_t free_list_cache_size; + /** + * The maximum number of revisions to keep. + */ + size_t revisions; + /** + * The cache read strategy to use. + * + * This must be one of the following: + * + * - `0`: No cache. + * - `1`: Cache only branch reads. + * - `2`: Cache all reads. + * + * Opening returns an error if this is not one of the above values. + */ + uint8_t strategy; + /** + * Whether to truncate the database file if it exists. + */ + bool truncate; +} DatabaseHandleArgs; + +/** + * A result type returned from FFI functions that create a proposal but do not + * commit it to the database. + */ +typedef enum ProposalResult_Tag { + /** + * The caller provided a null pointer to a database handle. + */ + ProposalResult_NullHandlePointer, + /** + * Buulding the proposal was successful and the proposal ID and root hash + * are returned. + */ + ProposalResult_Ok, + /** + * An error occurred and the message is returned as an [`OwnedBytes`]. If + * value is guaranteed to contain only valid UTF-8. + * + * The caller must call [`fwd_free_owned_bytes`] to free the memory + * associated with this error. + * + * [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + */ + ProposalResult_Err, +} ProposalResult_Tag; + +typedef struct ProposalResult_Ok_Body { + /** + * An opaque pointer to the [`ProposalHandle`] that can be use to create + * an additional proposal or later commit. The caller must ensure that this + * pointer is freed with [`fwd_free_proposal`] if it is not committed. + * + * [`fwd_free_proposal`]: crate::fwd_free_proposal + */ + struct ProposalHandle *handle; + /** + * The root hash of the proposal. Zeroed if the proposal resulted in an + * empty database. + */ + struct HashKey root_hash; +} ProposalResult_Ok_Body; + +typedef struct ProposalResult { + ProposalResult_Tag tag; + union { + ProposalResult_Ok_Body ok; + struct { + OwnedBytes err; + }; + }; +} ProposalResult; + +/** + * Arguments for initializing logging for the Firewood FFI. + */ +typedef struct LogArgs { + /** + * The file path where logs for this process are stored. + * + * If empty, this is set to `${TMPDIR}/firewood-log.txt`. + * + * This is required to be a valid UTF-8 string. + */ + BorrowedBytes path; + /** + * The filter level for logs. + * + * If empty, this is set to `info`. + * + * This is required to be a valid UTF-8 string. + */ + BorrowedBytes filter_level; +} LogArgs; + +/** + * Puts the given key-value pairs into the database. + * + * # Arguments + * + * * `db` - The database handle returned by [`fwd_open_db`] + * * `values` - A [`BorrowedKeyValuePairs`] containing the key-value pairs to put. + * + * # Returns + * + * - [`HashResult::NullHandlePointer`] if the provided database handle is null. + * - [`HashResult::None`] if the commit resulted in an empty database. + * - [`HashResult::Some`] if the commit was successful, containing the new root hash. + * - [`HashResult::Err`] if an error occurred while committing the batch. + * + * # Safety + * + * The caller must: + * * ensure that `db` is a valid pointer to a [`DatabaseHandle`] + * * ensure that `values` is valid for [`BorrowedKeyValuePairs`] + * * call [`fwd_free_owned_bytes`] to free the memory associated with the + * returned error ([`HashKey`] does not need to be freed as it is returned by + * value). + */ +struct HashResult fwd_batch(const struct DatabaseHandle *db, BorrowedKeyValuePairs values); + +/** + * Returns the next key range that should be fetched after processing the + * current set of operations in a change proof that was truncated. + * + * Can be called multiple times to get subsequent disjoint key ranges until + * it returns [`NextKeyRangeResult::None`], indicating there are no more keys to + * fetch and the proof is complete. + * + * # Arguments + * + * - `proof` - A [`ChangeProofContext`] previously returned from the create + * methods and has been prepared into a proposal or already committed. + * + * # Returns + * + * - [`NextKeyRangeResult::NullHandlePointer`] if the caller provided a null pointer. + * - [`NextKeyRangeResult::NotPrepared`] if the proof has not been prepared into + * a proposal nor committed to the database. + * - [`NextKeyRangeResult::None`] if there are no more keys to fetch. + * - [`NextKeyRangeResult::Some`] containing the next key range to fetch. + * - [`NextKeyRangeResult::Err`] containing an error message if the next key range + * could not be determined. + * + * # Thread Safety + * + * It is not safe to call this function concurrently with the same proof context + * nor is it safe to call any other function that accesses the same proof context + * concurrently. The caller must ensure exclusive access to the proof context + * for the duration of the call. + */ +struct NextKeyRangeResult fwd_change_proof_find_next_key(struct ChangeProofContext *_proof); + +/** + * Deserialize a `ChangeProof` from bytes. + * + * # Arguments + * + * * `bytes` - The bytes to deserialize the proof from. + * + * # Returns + * + * - [`ChangeProofResult::NullHandlePointer`] if the caller provided a null or zero-length slice. + * - [`ChangeProofResult::Ok`] containing a pointer to the `ChangeProofContext` if the proof + * was successfully parsed. This does not imply that the proof is valid, only that it is + * well-formed. The verify method must be called to ensure the proof is cryptographically valid. + * - [`ChangeProofResult::Err`] containing an error message if the proof could not be parsed. + */ +struct ChangeProofResult fwd_change_proof_from_bytes(BorrowedBytes _bytes); + +/** + * Serialize a `ChangeProof` to bytes. + * + * # Arguments + * + * - `proof` - A [`ChangeProofContext`] previously returned from the create + * method. If from a parsed proof, the proof will not be verified before + * serialization. + * + * # Returns + * + * - [`ValueResult::NullHandlePointer`] if the caller provided a null pointer. + * - [`ValueResult::Some`] containing the serialized bytes if successful. + * - [`ValueResult::Err`] if the caller provided a null pointer. + * + * The other [`ValueResult`] variants are not used. + */ +struct ValueResult fwd_change_proof_to_bytes(const struct ChangeProofContext *_proof); + +/** + * Close and free the memory for a database handle + * + * # Arguments + * + * * `db` - The database handle to close, previously returned from a call to [`fwd_open_db`]. + * + * # Returns + * + * - [`VoidResult::NullHandlePointer`] if the provided database handle is null. + * - [`VoidResult::Ok`] if the database handle was successfully closed and freed. + * - [`VoidResult::Err`] if the process panics while closing the database handle. + * + * # Safety + * + * Callers must ensure that: + * + * - `db` is a valid pointer to a [`DatabaseHandle`] returned by [`fwd_open_db`]. + * - There are no handles to any open proposals. If so, they must be freed first + * using [`fwd_free_proposal`]. + * - Freeing the database handle does not free outstanding [`RevisionHandle`]s + * returned by [`fwd_get_revision`]. To prevent leaks, free them separately + * with [`fwd_free_revision`]. + * - The database handle is not used after this function is called. + */ +struct VoidResult fwd_close_db(struct DatabaseHandle *db); + +/** + * Commits a proposal to the database. + * + * This function will consume the proposal regardless of whether the commit + * is successful. + * + * # Arguments + * + * * `handle` - The proposal handle returned by [`fwd_propose_on_db`] or + * [`fwd_propose_on_proposal`]. + * + * # Returns + * + * # Returns + * + * - [`HashResult::NullHandlePointer`] if the provided database handle is null. + * - [`HashResult::None`] if the commit resulted in an empty database. + * - [`HashResult::Some`] if the commit was successful, containing the new root hash. + * - [`HashResult::Err`] if an error occurred while committing the batch. + * + * # Safety + * + * The caller must: + * * ensure that `handle` is a valid pointer to a [`ProposalHandle`] + * * ensure that `handle` is not used again after this function is called. + * * call [`fwd_free_owned_bytes`] to free the memory associated with the + * returned error ([`HashKey`] does not need to be freed as it is returned + * by value). + */ +struct HashResult fwd_commit_proposal(struct ProposalHandle *proposal); + +/** + * Create a change proof for the given range of keys between two roots. + * + * # Arguments + * + * - `db` - The database to create the proof from. + * - `args` - The arguments for creating the change proof. + * + * # Returns + * + * - [`ChangeProofResult::NullHandlePointer`] if the caller provided a null pointer. + * - [`ChangeProofResult::RevisionNotFound`] if the caller provided a start or end root + * that was not found in the database. The missing root hash is included in the result. + * The start root is checked first, and if both are missing, only the start root is + * reported. + * - [`ChangeProofResult::Ok`] containing a pointer to the `ChangeProofContext` if the proof + * was successfully created. + * - [`ChangeProofResult::Err`] containing an error message if the proof could not be created. + */ +struct ChangeProofResult fwd_db_change_proof(const struct DatabaseHandle *_db, + struct CreateChangeProofArgs _args); + +/** + * Generate a range proof for the given range of keys for the latest revision. + * + * # Arguments + * + * - `db` - The database to create the proof from. + * - `args` - The arguments for creating the range proof. + * + * # Returns + * + * - [`RangeProofResult::NullHandlePointer`] if the caller provided a null pointer. + * - [`RangeProofResult::RevisionNotFound`] if the caller provided a root that was + * not found in the database. The missing root hash is included in the result. + * - [`RangeProofResult::Ok`] containing a pointer to the `RangeProofContext` if the proof + * was successfully created. + * - [`RangeProofResult::Err`] containing an error message if the proof could not be created. + */ +struct RangeProofResult fwd_db_range_proof(const struct DatabaseHandle *db, + struct CreateRangeProofArgs args); + +/** + * Verify and commit a change proof to the database. + * + * If the proof has already been verified, the previously prepared proposal will be + * committed instead of re-verifying. If the proof has not been verified, it will be + * verified now. If the prepared proposal is no longer valid (e.g., the database has + * changed since it was prepared), a new proposal will be created and committed. + * + * The proof context will be updated with additional information about the committed + * proof to allow for optimized introspection of the committed changes. + * + * # Arguments + * + * - `db` - The database to commit the changes to. + * - `args` - The arguments for verifying the change proof. + * + * # Returns + * + * - [`HashResult::NullHandlePointer`] if the caller provided a null pointer to either + * the database or the proof. + * - [`HashResult::None`] if the proof resulted in an empty database (i.e., all keys were deleted). + * - [`HashResult::Some`] containing the new root hash if the proof was successfully verified + * - [`HashResult::Err`] containing an error message if the proof could not be verified or committed. + * + * # Thread Safety + * + * It is not safe to call this function concurrently with the same proof context + * nor is it safe to call any other function that accesses the same proof context + * concurrently. The caller must ensure exclusive access to the proof context + * for the duration of the call. + */ +struct HashResult fwd_db_verify_and_commit_change_proof(const struct DatabaseHandle *_db, + struct VerifyChangeProofArgs _args); + +/** + * Verify and commit a range proof to the database. + * + * If a proposal was previously prepared by a call to [`fwd_db_verify_range_proof`], + * it will be committed instead of re-verifying the proof. If the proof has not yet + * been verified, it will be verified now. If the prepared proposal is no longer + * valid (e.g., the database has changed since it was prepared), a new proposal + * will be created and committed. + * + * The proof context will be updated with additional information about the committed + * proof to allow for optimized introspection of the committed changes. + * + * # Arguments + * + * - `db` - The database to commit the changes to. + * - `args` - The arguments for verifying the range proof. + * + * # Returns + * + * - [`HashResult::NullHandlePointer`] if the caller provided a null pointer to either + * the database or the proof. + * - [`HashResult::None`] if the proof resulted in an empty database (i.e., all keys were deleted). + * - [`HashResult::Some`] containing the new root hash if the proof was successfully verified + * - [`HashResult::Err`] containing an error message if the proof could not be verified or committed. + * + * # Thread Safety + * + * It is not safe to call this function concurrently with the same proof context + * nor is it safe to call any other function that accesses the same proof context + * concurrently. The caller must ensure exclusive access to the proof context + * for the duration of the call. + */ +struct HashResult fwd_db_verify_and_commit_range_proof(const struct DatabaseHandle *db, + struct VerifyRangeProofArgs args); + +/** + * Verify a change proof and prepare a proposal to later commit or drop. + * + * # Arguments + * + * - `db` - The database to verify the proof against. + * - `args` - The arguments for verifying the change proof. + * + * # Returns + * + * - [`VoidResult::NullHandlePointer`] if the caller provided a null pointer to either + * the database or the proof. + * - [`VoidResult::Ok`] if the proof was successfully verified. + * - [`VoidResult::Err`] containing an error message if the proof could not be verified + * + * # Thread Safety + * + * It is not safe to call this function concurrently with the same proof context + * nor is it safe to call any other function that accesses the same proof context + * concurrently. The caller must ensure exclusive access to the proof context + * for the duration of the call. + */ +struct VoidResult fwd_db_verify_change_proof(const struct DatabaseHandle *_db, + struct VerifyChangeProofArgs _args); + +/** + * Verify a range proof and prepare a proposal to later commit or drop. If the + * proof has already been verified, the cached validation context will be used + * to avoid re-verifying the proof. + * + * # Arguments + * + * - `db` - The database to verify the proof against. + * - `args` - The arguments for verifying the range proof. + * + * # Returns + * + * - [`VoidResult::NullHandlePointer`] if the caller provided a null pointer to either + * the database or the proof. + * - [`VoidResult::Ok`] if the proof was successfully verified. + * - [`VoidResult::Err`] containing an error message if the proof could not be verified + * + * # Thread Safety + * + * It is not safe to call this function concurrently with the same proof context + * nor is it safe to call any other function that accesses the same proof context + * concurrently. The caller must ensure exclusive access to the proof context + * for the duration of the call. + */ +struct VoidResult fwd_db_verify_range_proof(const struct DatabaseHandle *db, + struct VerifyRangeProofArgs args); + +/** + * Frees the memory associated with a `ChangeProofContext`. + * + * # Arguments + * + * * `proof` - The `ChangeProofContext` to free, previously returned from any Rust function. + * + * # Returns + * + * - [`VoidResult::Ok`] if the memory was successfully freed. + * - [`VoidResult::Err`] if the process panics while freeing the memory. + */ +struct VoidResult fwd_free_change_proof(struct ChangeProofContext *proof); + +/** + * Consumes the [`IteratorHandle`], destroys the iterator, and frees the memory. + * + * # Arguments + * + * * `iterator` - A pointer to a [`IteratorHandle`] previously returned from a + * function from this library. + * + * # Returns + * + * - [`VoidResult::NullHandlePointer`] if the provided iterator handle is null. + * - [`VoidResult::Ok`] if the iterator was successfully freed. + * - [`VoidResult::Err`] if the process panics while freeing the memory. + * + * # Safety + * + * The caller must ensure that the `iterator` is not null and that it points to + * a valid [`IteratorHandle`] previously returned by a function from this library. + * + */ +struct VoidResult fwd_free_iterator(struct IteratorHandle *iterator); + +/** + * Consumes the [`OwnedBytes`] and frees the memory associated with it. + * + * # Arguments + * + * * `bytes` - The [`OwnedBytes`] struct to free, previously returned from any + * function from this library. + * + * # Returns + * + * - [`VoidResult::Ok`] if the memory was successfully freed. + * - [`VoidResult::Err`] if the process panics while freeing the memory. + * + * # Safety + * + * The caller must ensure that the `bytes` struct is valid and that the memory + * it points to is uniquely owned by this object. However, if `bytes.ptr` is null, + * this function does nothing. + */ +struct VoidResult fwd_free_owned_bytes(OwnedBytes bytes); + +/** + * Consumes the [`OwnedKeyValueBatch`] and frees the memory associated with it. + * + * # Arguments + * + * * `batch` - The [`OwnedKeyValueBatch`] struct to free, previously returned from any + * function from this library. + * + * # Returns + * + * - [`VoidResult::Ok`] if the memory was successfully freed. + * - [`VoidResult::Err`] if the process panics while freeing the memory. + * + * # Safety + * + * The caller must ensure that the `batch` struct is valid and that the memory + * it points to is uniquely owned by this object. However, if `batch.ptr` is null, + * this function does nothing. + */ +struct VoidResult fwd_free_owned_key_value_batch(OwnedKeyValueBatch batch); + +/** + * Consumes the [`OwnedKeyValuePair`] and frees the memory associated with it. + * + * # Arguments + * + * * `kv` - The [`OwnedKeyValuePair`] struct to free, previously returned from any + * function from this library. + * + * # Returns + * + * - [`VoidResult::Ok`] if the memory was successfully freed. + * - [`VoidResult::Err`] if the process panics while freeing the memory. + * + * # Safety + * + * The caller must ensure that the `kv` struct is valid. + */ +struct VoidResult fwd_free_owned_kv_pair(struct OwnedKeyValuePair kv); + +/** + * Consumes the [`ProposalHandle`], cancels the proposal, and frees the memory. + * + * # Arguments + * + * * `proposal` - A pointer to a [`ProposalHandle`] previously returned from a + * function from this library. + * + * # Returns + * + * - [`VoidResult::NullHandlePointer`] if the provided proposal handle is null. + * - [`VoidResult::Ok`] if the proposal was successfully cancelled and freed. + * - [`VoidResult::Err`] if the process panics while freeing the memory. + * + * # Safety + * + * The caller must ensure that the `proposal` is not null and that it points to + * a valid [`ProposalHandle`] previously returned by a function from this library. + * + * The caller must ensure that the proposal was not committed. [`fwd_commit_proposal`] + * will consume the proposal automatically. + */ +struct VoidResult fwd_free_proposal(struct ProposalHandle *proposal); + +/** + * Frees the memory associated with a `RangeProofContext`. + * + * # Arguments + * + * * `proof` - The `RangeProofContext` to free, previously returned from any Rust function. + * + * # Returns + * + * - [`VoidResult::Ok`] if the memory was successfully freed. + * - [`VoidResult::Err`] if the process panics while freeing the memory. + */ +struct VoidResult fwd_free_range_proof(struct RangeProofContext *proof); + +/** + * Consumes the [`RevisionHandle`] and frees the memory associated with it. + * + * # Arguments + * + * * `revision` - A pointer to a [`RevisionHandle`] previously returned by + * [`fwd_get_revision`]. + * + * # Returns + * + * - [`VoidResult::NullHandlePointer`] if the provided revision handle is null. + * - [`VoidResult::Ok`] if the revision handle was successfully freed. + * - [`VoidResult::Err`] if the process panics while freeing the memory. + * + * # Safety + * + * The caller must ensure that the revision handle is valid and is not used again after + * this function is called. + */ +struct VoidResult fwd_free_revision(struct RevisionHandle *revision); + +/** + * Gather latest metrics for this process. + * + * # Returns + * + * - [`ValueResult::None`] if the gathered metrics resulted in an empty string. + * - [`ValueResult::Some`] the gathered metrics as an [`OwnedBytes`] (with + * guaranteed to be utf-8 data, not null terminated). + * - [`ValueResult::Err`] if an error occurred while retrieving the value. + * + * # Safety + * + * The caller must: + * * call [`fwd_free_owned_bytes`] to free the memory associated with the + * returned error or value. + */ +struct ValueResult fwd_gather(void); + +/** + * Gets the value associated with the given key from the proposal provided. + * + * # Arguments + * + * * `handle` - The proposal handle returned by [`fwd_propose_on_db`] or + * [`fwd_propose_on_proposal`]. + * * `key` - The key to look up, as a [`BorrowedBytes`]. + * + * # Returns + * + * - [`ValueResult::NullHandlePointer`] if the provided database handle is null. + * - [`ValueResult::None`] if the key was not found. + * - [`ValueResult::Some`] if the key was found with the associated value. + * - [`ValueResult::Err`] if an error occurred while retrieving the value. + * + * # Safety + * + * The caller must: + * * ensure that `handle` is a valid pointer to a [`ProposalHandle`] + * * ensure that `key` is valid for [`BorrowedBytes`] + * * call [`fwd_free_owned_bytes`] to free the memory associated [`OwnedBytes`] + * returned in the result. + */ +struct ValueResult fwd_get_from_proposal(const struct ProposalHandle *handle, BorrowedBytes key); + +/** + * Gets the value associated with the given key from the provided revision handle. + * + * # Arguments + * + * * `revision` - The revision handle returned by [`fwd_get_revision`]. + * * `key` - The key to look up as a [`BorrowedBytes`]. + * + * # Returns + * + * - [`ValueResult::NullHandlePointer`] if the provided revision handle is null. + * - [`ValueResult::None`] if the key was not found in the revision. + * - [`ValueResult::Some`] if the key was found with the associated value. + * - [`ValueResult::Err`] if an error occurred while retrieving the value. + * + * # Safety + * + * The caller must: + * * ensure that `revision` is a valid pointer to a [`RevisionHandle`]. + * * ensure that `key` is valid for [`BorrowedBytes`]. + * * call [`fwd_free_owned_bytes`] to free the memory associated with the [`OwnedBytes`] + * returned in the result. + */ +struct ValueResult fwd_get_from_revision(const struct RevisionHandle *revision, BorrowedBytes key); + +/** + * Gets a value assoicated with the given root hash and key. + * + * The hash may refer to a historical revision or an existing proposal. + * + * # Arguments + * + * * `db` - The database handle returned by [`fwd_open_db`] + * * `root` - The root hash to look up as a [`BorrowedBytes`] + * * `key` - The key to look up as a [`BorrowedBytes`] + * + * # Returns + * + * - [`ValueResult::NullHandlePointer`] if the provided database handle is null. + * - [`ValueResult::RevisionNotFound`] if no revision was found for the specified root. + * - [`ValueResult::None`] if the key was not found. + * - [`ValueResult::Some`] if the key was found with the associated value. + * - [`ValueResult::Err`] if an error occurred while retrieving the value. + * + * # Safety + * + * The caller must: + * * ensure that `db` is a valid pointer to a [`DatabaseHandle`] + * * ensure that `root` is a valid for [`BorrowedBytes`] + * * ensure that `key` is a valid for [`BorrowedBytes`] + * * call [`fwd_free_owned_bytes`] to free the memory associated [`OwnedBytes`] + * returned in the result. + */ +struct ValueResult fwd_get_from_root(const struct DatabaseHandle *db, + struct HashKey root, + BorrowedBytes key); + +/** + * Gets the value associated with the given key from the database for the + * latest revision. + * + * # Arguments + * + * * `db` - The database handle returned by [`fwd_open_db`] + * * `key` - The key to look up as a [`BorrowedBytes`] + * + * # Returns + * + * - [`ValueResult::NullHandlePointer`] if the provided database handle is null. + * - [`ValueResult::RevisionNotFound`] if no revision was found for the root + * (i.e., there is no current root). + * - [`ValueResult::None`] if the key was not found. + * - [`ValueResult::Some`] if the key was found with the associated value. + * - [`ValueResult::Err`] if an error occurred while retrieving the value. + * + * # Safety + * + * The caller must: + * * ensure that `db` is a valid pointer to a [`DatabaseHandle`]. + * * ensure that `key` is valid for [`BorrowedBytes`] + * * call [`fwd_free_owned_bytes`] to free the memory associated with the + * returned error or value. + * + * [`BorrowedBytes`]: crate::value::BorrowedBytes + */ +struct ValueResult fwd_get_latest(const struct DatabaseHandle *db, BorrowedBytes key); + +/** + * Gets a handle to the revision identified by the provided root hash. + * + * # Arguments + * + * * `db` - The database handle returned by [`fwd_open_db`]. + * * `root` - The hash of the revision as a [`BorrowedBytes`]. + * + * # Returns + * + * - [`RevisionResult::NullHandlePointer`] if the provided database handle is null. + * - [`RevisionResult::Ok`] containing a [`RevisionHandle`] and root hash if the revision exists. + * - [`RevisionResult::Err`] if the revision cannot be fetched or the root hash is invalid. + * + * # Safety + * + * The caller must: + * * ensure that `db` is a valid pointer to a [`DatabaseHandle`]. + * * ensure that `root` is valid for [`BorrowedBytes`]. + * * call [`fwd_free_revision`] to free the returned handle when it is no longer needed. + * + * [`BorrowedBytes`]: crate::value::BorrowedBytes + * [`RevisionHandle`]: crate::revision::RevisionHandle + */ +struct RevisionResult fwd_get_revision(const struct DatabaseHandle *db, struct HashKey root); + +/** + * Retrieves the next item from the iterator. + * + * # Arguments + * + * * `handle` - The iterator handle returned by [`fwd_iter_on_revision`] or + * [`fwd_iter_on_proposal`]. + * + * # Returns + * + * - [`KeyValueResult::NullHandlePointer`] if the provided iterator handle is null. + * - [`KeyValueResult::None`] if the iterator is exhausted (no remaining values). Once returned, + * subsequent calls will continue returning [`KeyValueResult::None`]. You may still call this + * safely, but freeing the iterator with [`fwd_free_iterator`] is recommended. + * - [`KeyValueResult::Some`] if the next item on iterator was retrieved, with the associated + * key value pair. + * - [`KeyValueResult::Err`] if an I/O error occurred while retrieving the next item. Most + * iterator errors are non-reentrant. Once returned, the iterator should be considered + * invalid and must be freed with [`fwd_free_iterator`]. + * + * # Safety + * + * The caller must: + * * ensure that `handle` is a valid pointer to a [`IteratorHandle`]. + * * call [`fwd_free_owned_kv_pair`] on returned [`OwnedKeyValuePair`] + * to free the memory associated with the returned value. + * + */ +struct KeyValueResult fwd_iter_next(struct IteratorHandle *handle); + +/** + * Retrieves the next batch of items from the iterator. + * + * # Arguments + * + * * `handle` - The iterator handle returned by [`fwd_iter_on_revision`] or + * [`fwd_iter_on_proposal`]. + * + * # Returns + * + * - [`KeyValueBatchResult::NullHandlePointer`] if the provided iterator handle is null. + * - [`KeyValueBatchResult::Some`] with up to `n` key/value pairs. If the iterator is + * exhausted, this may be fewer than `n`, including zero items. + * - [`KeyValueBatchResult::Err`] if an I/O error occurred while retrieving items. Most + * iterator errors are non-reentrant. Once returned, the iterator should be considered + * invalid and must be freed with [`fwd_free_iterator`]. + * + * Once an empty batch or items fewer than `n` is returned (iterator exhausted), subsequent calls + * will continue returning empty batches. You may still call this safely, but freeing the + * iterator with [`fwd_free_iterator`] is recommended. + * + * # Safety + * + * The caller must: + * * ensure that `handle` is a valid pointer to a [`IteratorHandle`]. + * * call [`fwd_free_owned_key_value_batch`] on the returned batch to free any allocated memory. + * + */ +struct KeyValueBatchResult fwd_iter_next_n(struct IteratorHandle *handle, size_t n); + +/** + * Returns an iterator on the provided proposal optionally starting from a key + * + * # Arguments + * + * * `handle` - The proposal handle returned by [`fwd_propose_on_db`] or + * [`fwd_propose_on_proposal`]. + * * `key` - The key to look up as a [`BorrowedBytes`] + * + * # Returns + * + * - [`IteratorResult::NullHandlePointer`] if the provided proposal handle is null. + * - [`IteratorResult::Ok`] if the iterator was created, with the iterator handle. + * - [`IteratorResult::Err`] if an error occurred while creating the iterator. + * + * # Safety + * + * The caller must: + * * ensure that `handle` is a valid pointer to a [`ProposalHandle`] + * * ensure that `key` is a valid for [`BorrowedBytes`] + * * call [`fwd_free_iterator`] to free the memory associated with the iterator. + * + */ +struct IteratorResult fwd_iter_on_proposal(const struct ProposalHandle *handle, BorrowedBytes key); + +/** + * Returns an iterator optionally starting from a key in the provided revision. + * + * # Arguments + * + * * `revision` - The revision handle returned by [`fwd_get_revision`]. + * * `key` - The key to look up as a [`BorrowedBytes`] + * + * # Returns + * + * - [`IteratorResult::NullHandlePointer`] if the provided revision handle is null. + * - [`IteratorResult::Ok`] if the iterator was created, with the iterator handle. + * - [`IteratorResult::Err`] if an error occurred while creating the iterator. + * + * # Safety + * + * The caller must: + * * ensure that `revision` is a valid pointer to a [`RevisionHandle`] + * * ensure that `key` is a valid [`BorrowedBytes`] + * * call [`fwd_free_iterator`] to free the memory associated with the iterator. + * + */ +struct IteratorResult fwd_iter_on_revision(const struct RevisionHandle *revision, + BorrowedBytes key); + +/** + * Open a database with the given arguments. + * + * # Arguments + * + * See [`DatabaseHandleArgs`]. + * + * # Returns + * + * - [`HandleResult::Ok`] with the database handle if successful. + * - [`HandleResult::Err`] if an error occurs while opening the database. + * + * # Safety + * + * The caller must: + * - ensure that the database is freed with [`fwd_close_db`] when no longer needed. + * - ensure that the database handle is freed only after freeing or committing + * all proposals created on it. + */ +struct HandleResult fwd_open_db(struct DatabaseHandleArgs args); + +/** + * Proposes a batch of operations to the database. + * + * # Arguments + * + * * `db` - The database handle returned by [`fwd_open_db`] + * * `values` - A [`BorrowedKeyValuePairs`] containing the key-value pairs to put. + * + * # Returns + * + * - [`ProposalResult::NullHandlePointer`] if the provided database handle is null. + * - [`ProposalResult::Ok`] if the proposal was created, with the proposal handle + * and calculated root hash. + * - [`ProposalResult::Err`] if an error occurred while creating the proposal. + * + * # Safety + * + * The caller must: + * * ensure that `db` is a valid pointer to a [`DatabaseHandle`] + * * ensure that `values` is valid for [`BorrowedKeyValuePairs`] + * * call [`fwd_commit_proposal`] or [`fwd_free_proposal`] to free the memory + * associated with the proposal. And, the caller must ensure this is done + * before calling [`fwd_close_db`] to avoid memory leaks or undefined behavior. + */ +struct ProposalResult fwd_propose_on_db(const struct DatabaseHandle *db, + BorrowedKeyValuePairs values); + +/** + * Proposes a batch of operations to the database on top of an existing proposal. + * + * # Arguments + * + * * `handle` - The proposal handle returned by [`fwd_propose_on_db`] or + * [`fwd_propose_on_proposal`]. + * * `values` - A [`BorrowedKeyValuePairs`] containing the key-value pairs to put. + * + * # Returns + * + * - [`ProposalResult::NullHandlePointer`] if the provided database handle is null. + * - [`ProposalResult::Ok`] if the proposal was created, with the proposal handle + * and calculated root hash. + * - [`ProposalResult::Err`] if an error occurred while creating the proposal. + * + * # Safety + * + * The caller must: + * * ensure that `handle` is a valid pointer to a [`ProposalHandle`] + * * ensure that `values` is valid for [`BorrowedKeyValuePairs`] + * * call [`fwd_commit_proposal`] or [`fwd_free_proposal`] to free the memory + * associated with the proposal. And, the caller must ensure this is done + * before calling [`fwd_close_db`] to avoid memory leaks or undefined behavior. + */ +struct ProposalResult fwd_propose_on_proposal(const struct ProposalHandle *handle, + BorrowedKeyValuePairs values); + +/** + * Returns the next key range that should be fetched after processing the + * current set of key-value pairs in a range proof that was truncated. + * + * Can be called multiple times to get subsequent disjoint key ranges until + * it returns [`NextKeyRangeResult::None`], indicating there are no more keys to + * fetch and the proof is complete. + * + * # Arguments + * + * - `proof` - A [`RangeProofContext`] previously returned from the create + * methods and has been prepared into a proposal or already committed. + * + * # Returns + * + * - [`NextKeyRangeResult::NullHandlePointer`] if the caller provided a null pointer. + * - [`NextKeyRangeResult::NotPrepared`] if the proof has not been prepared into + * a proposal nor committed to the database. + * - [`NextKeyRangeResult::None`] if there are no more keys to fetch. + * - [`NextKeyRangeResult::Some`] containing the next key range to fetch. + * - [`NextKeyRangeResult::Err`] containing an error message if the next key range + * could not be determined. + * + * # Thread Safety + * + * It is not safe to call this function concurrently with the same proof context + * nor is it safe to call any other function that accesses the same proof context + * concurrently. The caller must ensure exclusive access to the proof context + * for the duration of the call. + */ +struct NextKeyRangeResult fwd_range_proof_find_next_key(struct RangeProofContext *proof); + +/** + * Deserialize a `RangeProof` from bytes. + * + * # Arguments + * + * - `bytes` - The bytes to deserialize the proof from. + * + * # Returns + * + * - [`RangeProofResult::NullHandlePointer`] if the caller provided a null or zero-length slice. + * - [`RangeProofResult::Ok`] containing a pointer to the `RangeProofContext` if the proof + * was successfully parsed. This does not imply that the proof is valid, only that it is + * well-formed. The verify method must be called to ensure the proof is cryptographically valid. + * - [`RangeProofResult::Err`] containing an error message if the proof could not be parsed. + */ +struct RangeProofResult fwd_range_proof_from_bytes(BorrowedBytes bytes); + +/** + * Serialize a `RangeProof` to bytes. + * + * # Arguments + * + * - `proof` - A [`RangeProofContext`] previously returned from the create + * method. If from a parsed proof, the proof will not be verified before + * serialization. + * + * # Returns + * + * - [`ValueResult::NullHandlePointer`] if the caller provided a null pointer. + * - [`ValueResult::Some`] containing the serialized bytes if successful. + * - [`ValueResult::Err`] if the caller provided a null pointer. + */ +struct ValueResult fwd_range_proof_to_bytes(const struct RangeProofContext *proof); + +/** + * Verify a range proof against the given start and end keys and root hash. The + * proof will be updated with the validation context if the proof is valid to + * avoid re-verifying it during commit. + * + * # Arguments + * + * - `args` - The arguments for verifying the range proof. + * + * # Returns + * + * - [`VoidResult::NullHandlePointer`] if the caller provided a null pointer to the proof. + * - [`VoidResult::Ok`] if the proof was successfully verified. + * - [`VoidResult::Err`] containing an error message if the proof could not be verified. + * + * # Thread Safety + * + * It is not safe to call this function concurrently with the same proof context + * nor is it safe to call any other function that accesses the same proof context + * concurrently. The caller must ensure exclusive access to the proof context + * for the duration of the call. + */ +struct VoidResult fwd_range_proof_verify(struct VerifyRangeProofArgs args); + +/** + * Get the root hash of the latest version of the database + * + * # Argument + * + * * `db` - The database handle returned by [`fwd_open_db`] + * + * # Returns + * + * - [`HashResult::NullHandlePointer`] if the provided database handle is null. + * - [`HashResult::None`] if the database is empty. + * - [`HashResult::Some`] with the root hash of the database. + * - [`HashResult::Err`] if an error occurred while looking up the root hash. + * + * # Safety + * + * * ensure that `db` is a valid pointer to a [`DatabaseHandle`] + * * call [`fwd_free_owned_bytes`] to free the memory associated with the + * returned error ([`HashKey`] does not need to be freed as it is returned + * by value). + */ +struct HashResult fwd_root_hash(const struct DatabaseHandle *db); + +/** + * Start logs for this process. + * + * # Arguments + * + * See [`LogArgs`]. + * + * # Returns + * + * - [`VoidResult::Ok`] if the recorder was initialized. + * - [`VoidResult::Err`] if an error occurs during initialization. + * + * # Safety + * + * The caller must: + * * call [`fwd_free_owned_bytes`] to free the memory associated with the + * returned error (if any). + */ +struct VoidResult fwd_start_logs(struct LogArgs args); + +/** + * Start metrics recorder for this process. + * + * # Returns + * + * - [`VoidResult::Ok`] if the recorder was initialized. + * - [`VoidResult::Err`] if an error occurs during initialization. + */ +struct VoidResult fwd_start_metrics(void); + +/** + * Start metrics recorder and exporter for this process. + * + * # Arguments + * + * * `metrics_port` - the port where metrics will be exposed at + * + * # Returns + * + * - [`VoidResult::Ok`] if the recorder was initialized. + * - [`VoidResult::Err`] if an error occurs during initialization. + * + * # Safety + * + * The caller must: + * * call [`fwd_free_owned_bytes`] to free the memory associated with the + * returned error (if any). + */ +struct VoidResult fwd_start_metrics_with_exporter(uint16_t metrics_port); diff --git a/firewood/ffi/firewood_test.go b/firewood/ffi/firewood_test.go new file mode 100644 index 000000000000..97ed3e9e4421 --- /dev/null +++ b/firewood/ffi/firewood_test.go @@ -0,0 +1,1750 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +import ( + "bytes" + "context" + "encoding/hex" + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "slices" + "strconv" + "strings" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +const ( + ethhashKey = "ethhash" + firewoodKey = "firewood" + emptyKey = "empty" + insert100Key = "100" + emptyEthhashRoot = "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + emptyFirewoodRoot = "0000000000000000000000000000000000000000000000000000000000000000" + errWrongParent = "The proposal cannot be committed since it is not a direct child of the most recent commit. " +) + +// expectedRoots contains the expected root hashes for different use cases across both default +// firewood hashing and ethhash. +// By default, TestMain infers which mode Firewood is operating in and selects the expected roots +// accordingly (this does turn test empty database into an effective no-op). +// +// To test a specific hashing mode explicitly, set the environment variable: +// TEST_FIREWOOD_HASH_MODE=ethhash or TEST_FIREWOOD_HASH_MODE=firewood +// This will skip the inference step and enforce we use the expected roots for the specified mode. +var ( + // expectedRoots contains a mapping of expected root hashes for different test + // vectors. + expectedRootModes = map[string]map[string]string{ + ethhashKey: { + emptyKey: emptyEthhashRoot, + insert100Key: "c25a0076e0337d7c982c3c9dfa445c8088242a0a607f9d9def3762765bcb0fde", + }, + firewoodKey: { + emptyKey: emptyFirewoodRoot, + insert100Key: "f858b51ada79c4abeb6566ef1204a453030dba1cca3526d174e2cb3ce2aadc57", + }, + } + expectedEmptyRootToMode = map[string]string{ + emptyEthhashRoot: ethhashKey, + emptyFirewoodRoot: firewoodKey, + } + expectedRoots map[string]string +) + +func stringToHash(t *testing.T, s string) Hash { + t.Helper() + b, err := hex.DecodeString(s) + require.NoError(t, err) + require.Len(t, b, RootLength) + return Hash(b) +} + +func inferHashingMode(ctx context.Context) (string, error) { + dbFile := filepath.Join(os.TempDir(), "test.db") + db, err := newDatabase(dbFile) + if err != nil { + return "", err + } + defer func() { + ctx, cancel := context.WithTimeout(ctx, time.Second) + defer cancel() + _ = db.Close(ctx) + _ = os.Remove(dbFile) + }() + + actualEmptyRoot, err := db.Root() + if err != nil { + return "", fmt.Errorf("failed to get root of empty database: %w", err) + } + actualEmptyRootHex := hex.EncodeToString(actualEmptyRoot[:]) + + actualFwMode, ok := expectedEmptyRootToMode[actualEmptyRootHex] + if !ok { + return "", fmt.Errorf("unknown empty root %q, cannot infer mode", actualEmptyRootHex) + } + + return actualFwMode, nil +} + +func TestMain(m *testing.M) { + // The cgocheck debugging flag checks that all pointers are pinned. + // TODO(arr4n) why doesn't `//go:debug cgocheck=1` work? https://go.dev/doc/godebug + debug := strings.Split(os.Getenv("GODEBUG"), ",") + var hasCgoCheck bool + for _, kv := range debug { + switch strings.TrimSpace(kv) { + case "cgocheck=1": + hasCgoCheck = true + case "cgocheck=0": + fmt.Fprint(os.Stderr, "GODEBUG=cgocheck=0; MUST be 1 for Firewood cgo tests") + os.Exit(1) + } + } + + if !hasCgoCheck { + debug = append(debug, "cgocheck=1") + if err := os.Setenv("GODEBUG", strings.Join(debug, ",")); err != nil { + fmt.Fprintf(os.Stderr, `os.Setenv("GODEBUG", ...) error %v`, err) + os.Exit(1) + } + } + + // If TEST_FIREWOOD_HASH_MODE is set, use it to select the expected roots. + // Otherwise, infer the hash mode from an empty database. + hashMode := os.Getenv("TEST_FIREWOOD_HASH_MODE") + if hashMode == "" { + inferredHashMode, err := inferHashingMode(context.Background()) + if err != nil { + fmt.Fprintf(os.Stderr, "failed to infer hash mode %v\n", err) + os.Exit(1) + } + hashMode = inferredHashMode + } + selectedExpectedRoots, ok := expectedRootModes[hashMode] + if !ok { + fmt.Fprintf(os.Stderr, "unknown hash mode %q\n", hashMode) + os.Exit(1) + } + expectedRoots = selectedExpectedRoots + + os.Exit(m.Run()) +} + +// oneSecCtx returns `tb.Context()` with a 1-second timeout added. Any existing +// cancellation on `tb.Context()` is removed, which allows this function to be +// used inside a `tb.Cleanup()` +func oneSecCtx(tb testing.TB) context.Context { + ctx := context.WithoutCancel(tb.Context()) + ctx, cancel := context.WithTimeout(ctx, time.Second) + tb.Cleanup(cancel) + return ctx +} + +func newTestDatabase(t *testing.T, configureFns ...func(*Config)) *Database { + t.Helper() + r := require.New(t) + + dbFile := filepath.Join(t.TempDir(), "test.db") + db, err := newDatabase(dbFile, configureFns...) + r.NoError(err) + t.Cleanup(func() { + r.NoError(db.Close(oneSecCtx(t))) + }) + return db +} + +func newDatabase(dbFile string, configureFns ...func(*Config)) (*Database, error) { + conf := DefaultConfig() + conf.Truncate = true // in tests, we use filepath.Join, which creates an empty file + for _, fn := range configureFns { + fn(conf) + } + + f, err := New(dbFile, conf) + if err != nil { + return nil, fmt.Errorf("failed to create new database at filepath %q: %w", dbFile, err) + } + return f, nil +} + +func TestUpdateSingleKV(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(1) + _, err := db.Update(keys, vals) + r.NoError(err) + + got, err := db.Get(keys[0]) + r.NoError(err) + r.Equal(vals[0], got) +} + +func TestUpdateMultiKV(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(10) + _, err := db.Update(keys, vals) + r.NoError(err) + + for i, key := range keys { + got, err := db.Get(key) + r.NoError(err) + r.Equal(vals[i], got) + } +} + +func TestTruncateDatabase(t *testing.T) { + r := require.New(t) + dbFile := filepath.Join(t.TempDir(), "test.db") + // Create a new database with truncate enabled. + config := DefaultConfig() + config.Truncate = true + db, err := New(dbFile, config) + r.NoError(err) + + // Insert some data. + keys, vals := kvForTest(10) + _, err = db.Update(keys, vals) + r.NoError(err) + + // Close the database. + r.NoError(db.Close(oneSecCtx(t))) + + // Reopen the database with truncate enabled. + db, err = New(dbFile, config) + r.NoError(err) + + // Check that the database is empty after truncation. + hash, err := db.Root() + r.NoError(err) + expectedHash := stringToHash(t, expectedRoots[emptyKey]) + r.Equal(expectedHash, hash, "Root hash mismatch after truncation") + + r.NoError(db.Close(oneSecCtx(t))) +} + +func TestClosedDatabase(t *testing.T) { + r := require.New(t) + dbFile := filepath.Join(t.TempDir(), "test.db") + db, err := newDatabase(dbFile) + r.NoError(err) + + r.NoError(db.Close(oneSecCtx(t))) + + _, err = db.Root() + r.ErrorIs(err, errDBClosed) + + root, err := db.Update( + [][]byte{[]byte("key")}, + [][]byte{[]byte("value")}, + ) + r.Empty(root) + r.ErrorIs(err, errDBClosed) + + r.NoError(db.Close(oneSecCtx(t))) +} + +func keyForTest(i int) []byte { + return []byte("key" + strconv.Itoa(i)) +} + +func valForTest(i int) []byte { + return []byte("value" + strconv.Itoa(i)) +} + +func kvForTest(num int) ([][]byte, [][]byte) { + keys := make([][]byte, num) + vals := make([][]byte, num) + for i := range keys { + keys[i] = keyForTest(i) + vals[i] = valForTest(i) + } + _ = sortKV(keys, vals) + return keys, vals +} + +// sortKV sorts keys lexicographically and keeps vals paired. +func sortKV(keys, vals [][]byte) error { + if len(keys) != len(vals) { + return errors.New("keys/vals length mismatch") + } + n := len(keys) + if n <= 1 { + return nil + } + ord := make([]int, n) + for i := range ord { + ord[i] = i + } + slices.SortFunc(ord, func(i, j int) int { + return bytes.Compare(keys[i], keys[j]) + }) + perm := make([]int, n) + for dest, orig := range ord { + perm[orig] = dest + } + for i := 0; i < n; i++ { + for perm[i] != i { + j := perm[i] + keys[i], keys[j] = keys[j], keys[i] + vals[i], vals[j] = vals[j], vals[i] + perm[i], perm[j] = perm[j], j + } + } + return nil +} + +// Tests that 100 key-value pairs can be inserted and retrieved. +// This happens in three ways: +// 1. By calling [Database.Propose] and then [Proposal.Commit]. +// 2. By calling [Database.Update] directly - no proposal storage is needed. +// 3. By calling [Database.Propose] and not committing, which returns a proposal. +func TestInsert100(t *testing.T) { + type dbView interface { + Get(key []byte) ([]byte, error) + Propose(keys, vals [][]byte) (*Proposal, error) + Root() (Hash, error) + } + + tests := []struct { + name string + insert func(dbView, [][]byte, [][]byte) (dbView, error) + }{ + { + name: "Propose and Commit", + insert: func(db dbView, keys, vals [][]byte) (dbView, error) { + proposal, err := db.Propose(keys, vals) + if err != nil { + return nil, err + } + err = proposal.Commit() + if err != nil { + return nil, err + } + return db, nil + }, + }, + { + name: "Update", + insert: func(db dbView, keys, vals [][]byte) (dbView, error) { + actualDB, ok := db.(*Database) + if !ok { + return nil, fmt.Errorf("expected *Database, got %T", db) + } + _, err := actualDB.Update(keys, vals) + return db, err + }, + }, + { + name: "Propose", + insert: func(db dbView, keys, vals [][]byte) (dbView, error) { + proposal, err := db.Propose(keys, vals) + if err != nil { + return nil, err + } + return proposal, nil + }, + }, + } + + for _, tt := range tests { + keys, vals := kvForTest(100) + t.Run(tt.name, func(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + newDB, err := tt.insert(db, keys, vals) + r.NoError(err) + + for i := range keys { + got, err := newDB.Get(keys[i]) + r.NoError(err) + // Cast as strings to improve debug messages. + want := string(vals[i]) + r.Equal(want, string(got)) + } + + hash, err := newDB.Root() + r.NoError(err) + + // Assert the hash is exactly as expected. Test failure indicates a + // non-hash compatible change has been made since the string was set. + // If that's expected, update the string at the top of the file to + // fix this test. + expectedHash := stringToHash(t, expectedRoots[insert100Key]) + r.Equal(expectedHash, hash, "Root hash mismatch.\nExpected (hex): %x\nActual (hex): %x", expectedHash, hash) + }) + } +} + +// Tests that a range of keys can be deleted. +func TestRangeDelete(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(100) + _, err := db.Update(keys, vals) + r.NoError(err) + + const deletePrefix = 1 + _, err = db.Update([][]byte{keyForTest(deletePrefix)}, [][]byte{{}}) + r.NoError(err) + + for i := range keys { + got, err := db.Get(keys[i]) + r.NoError(err) + + if deleted := bytes.HasPrefix(keys[i], keyForTest(deletePrefix)); deleted { + r.NoError(err) + } else { + r.Equal(vals[i], got) + } + } +} + +// Tests that the database is empty after creation and doesn't panic. +func TestInvariants(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + hash, err := db.Root() + r.NoError(err) + + expectedHash := stringToHash(t, expectedRoots[emptyKey]) + r.Equalf(expectedHash, hash, "expected %x, got %x", expectedHash, hash) + + got, err := db.Get([]byte("non-existent")) + r.NoError(err) + r.Empty(got) +} + +func TestConflictingProposals(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Create 10 proposals, each with 10 keys. + const numProposals = 10 + const numKeys = 10 + proposals := make([]*Proposal, numProposals) + for i := range proposals { + keys := make([][]byte, numKeys) + vals := make([][]byte, numKeys) + for j := 0; j < numKeys; j++ { + keys[j] = keyForTest(i*numKeys + j) + vals[j] = valForTest(i*numKeys + j) + } + proposal, err := db.Propose(keys, vals) + r.NoError(err) + proposals[i] = proposal + } + + // Check that each value is present in each proposal. + for i, p := range proposals { + for j := 0; j < numKeys; j++ { + got, err := p.Get(keyForTest(i*numKeys + j)) + r.NoError(err) + r.Equal(valForTest(i*numKeys+j), got, "Get(%d)", i*numKeys+j) + } + } + + // Commit only the first proposal. + err := proposals[0].Commit() + r.NoError(err) + // Check that the first proposal's keys are present. + for j := 0; j < numKeys; j++ { + got, err := db.Get(keyForTest(j)) + r.NoError(err) + r.Equal(valForTest(j), got, "Get(%d)", j) + } + // Check that the other proposals' keys are not present. + for i := 1; i < numProposals; i++ { + for j := 0; j < numKeys; j++ { + got, err := db.Get(keyForTest(i*numKeys + j)) + r.Empty(got, "Get(%d)", i*numKeys+j) + r.NoError(err, "Get(%d)", i*numKeys+j) + } + } + + // Ensure we can still get values from the other proposals. + for i := 1; i < numProposals; i++ { + for j := 0; j < numKeys; j++ { + got, err := proposals[i].Get(keyForTest(i*numKeys + j)) + r.NoError(err, "Get(%d)", i*numKeys+j) + r.Equal(valForTest(i*numKeys+j), got, "Get(%d)", i*numKeys+j) + } + } + + // Now we ensure we cannot commit the other proposals. + for i := 1; i < numProposals; i++ { + err := proposals[i].Commit() + r.Contains(err.Error(), errWrongParent, "Commit(%d)", i) + } + + // After attempting to commit the other proposals, they should be completely invalid. + for i := 1; i < numProposals; i++ { + err := proposals[i].Commit() + r.ErrorIs(err, errDroppedProposal, "Commit(%d)", i) + } + + // Because they're invalid, we should not be able to get values from them. + for i := 1; i < numProposals; i++ { + for j := 0; j < numKeys; j++ { + got, err := proposals[i].Get(keyForTest(i*numKeys + j)) + r.ErrorIs(err, errDroppedProposal, "Get(%d)", i*numKeys+j) + r.Empty(got, "Get(%d)", i*numKeys+j) + } + } +} + +// Tests that a proposal that deletes all keys can be committed. +func TestDeleteAll(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + keys, vals := kvForTest(10) + // Insert 10 key-value pairs. + _, err := db.Update(keys, vals) + r.NoError(err) + + // Create a proposal that deletes all keys. + proposal, err := db.Propose([][]byte{[]byte("key")}, [][]byte{nil}) + r.NoError(err) + + // Check that the proposal doesn't have the keys we just inserted. + for i := range keys { + got, err := proposal.Get(keys[i]) + r.NoError(err, "Get(%d)", i) + r.Empty(got, "Get(%d)", i) + } + + expectedHash := stringToHash(t, expectedRoots[emptyKey]) + hash, err := proposal.Root() + r.NoError(err, "%T.Root() after commit", proposal) + r.Equalf(expectedHash, hash, "%T.Root() of empty trie", db) + + // Commit the proposal. + err = proposal.Commit() + r.NoError(err, "Commit") + + // Check that the database is empty. + hash, err = db.Root() + r.NoError(err, "%T.Root()", db) + r.Equalf(expectedHash, hash, "%T.Root() of empty trie", db) +} + +func TestDropProposal(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Create a proposal with 10 keys. + keys, vals := kvForTest(10) + proposal, err := db.Propose(keys, vals) + r.NoError(err, "Propose") + + // Drop the proposal. + err = proposal.Drop() + r.NoError(err) + + // Check all operations on the dropped proposal. + err = proposal.Commit() + r.ErrorIs(err, errDroppedProposal) + _, err = proposal.Get([]byte("non-existent")) + r.ErrorIs(err, errDroppedProposal) + _, err = proposal.Root() + r.NoError(err, "Root of dropped proposal should still be accessible") + + // Check that the keys are not in the database. + for i := range keys { + got, err := db.Get(keys[i]) + r.NoError(err, "Get(%d)", i) + r.Empty(got, "Get(%d)", i) + } +} + +// Create a proposal with 10 key-value pairs. +// Tests that a proposal can be created from another proposal, and both can be +// committed sequentially. +func TestProposeFromProposal(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Create two sets of keys and values. + keys1 := make([][]byte, 10) + vals1 := make([][]byte, 10) + keys2 := make([][]byte, 10) + vals2 := make([][]byte, 10) + for i := range keys1 { + keys1[i] = keyForTest(i) + vals1[i] = valForTest(i) + } + for i := range keys2 { + keys2[i] = keyForTest(i + 10) + vals2[i] = valForTest(i + 10) + } + + // Create the first proposal. + proposal1, err := db.Propose(keys1, vals1) + r.NoError(err) + // Create the second proposal from the first. + proposal2, err := proposal1.Propose(keys2, vals2) + r.NoError(err) + + // Assert that the first proposal doesn't have keys from the second. + for i := range keys2 { + got, err := proposal1.Get(keys2[i]) + r.NoError(err, "Get(%d)", i) + r.Empty(got, "Get(%d)", i) + } + // Assert that the second proposal has keys from the first. + for i := range keys1 { + got, err := proposal2.Get(keys1[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals1[i], got, "Get(%d)", i) + } + + // Commit the first proposal. + err = proposal1.Commit() + r.NoError(err, "Commit") + + // Assert that the second proposal has keys from the first and second. + for i := range keys1 { + got, err := db.Get(keys1[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals1[i], got, "Get(%d)", i) + } + for i := range keys2 { + got, err := proposal2.Get(keys2[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals2[i], got, "Get(%d)", i) + } + + // Commit the second proposal. + err = proposal2.Commit() + r.NoError(err) + + // Assert that the database has keys from both proposals. + for i := range keys1 { + got, err := db.Get(keys1[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals1[i], got, "Get(%d)", i) + } + for i := range keys2 { + got, err := db.Get(keys2[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals2[i], got, "Get(%d)", i) + } +} + +func TestDeepPropose(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Create a chain of two proposals, each with 10 keys. + const numKeys = 10 + const numProposals = 10 + proposals := make([]*Proposal, numProposals) + keys, vals := kvForTest(numKeys * numProposals) + + for i := range proposals { + var ( + p *Proposal + err error + ) + if i == 0 { + p, err = db.Propose(keys[i:(i+1)*numKeys], vals[i:(i+1)*numKeys]) + r.NoError(err, "Propose(%d)", i) + } else { + p, err = proposals[i-1].Propose(keys[i:(i+1)*numKeys], vals[i:(i+1)*numKeys]) + r.NoError(err, "Propose(%d)", i) + } + proposals[i] = p + } + + // Check that each value is present in the final proposal. + for i := range keys { + got, err := proposals[numProposals-1].Get(keys[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals[i], got, "Get(%d)", i) + } + + // Commit each proposal sequentially, and ensure that the values are + // present in the database after each commit. + for i := range proposals { + err := proposals[i].Commit() + r.NoError(err, "Commit(%d)", i) + + for j := i * numKeys; j < (i+1)*numKeys; j++ { + got, err := db.Get(keys[j]) + r.NoError(err, "Get(%d)", j) + r.Equal(vals[j], got, "Get(%d)", j) + } + } +} + +// Tests that dropping a proposal and committing another one still allows +// access to the data of children proposals +func TestDropProposalAndCommit(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Create a chain of three proposals, each with 10 keys. + const numKeys = 10 + const numProposals = 3 + proposals := make([]*Proposal, numProposals) + keys := make([][]byte, numKeys*numProposals) + vals := make([][]byte, numKeys*numProposals) + for i := range keys { + keys[i] = keyForTest(i) + vals[i] = valForTest(i) + } + for i := range proposals { + var ( + p *Proposal + err error + ) + if i == 0 { + p, err = db.Propose(keys[i:(i+1)*numKeys], vals[i:(i+1)*numKeys]) + r.NoError(err, "Propose(%d)", i) + } else { + p, err = proposals[i-1].Propose(keys[i:(i+1)*numKeys], vals[i:(i+1)*numKeys]) + r.NoError(err, "Propose(%d)", i) + } + proposals[i] = p + } + + // drop the second proposal + err := proposals[1].Drop() + r.NoError(err) + // Commit the first proposal + err = proposals[0].Commit() + r.NoError(err) + + // Check that the second proposal is dropped + _, err = proposals[1].Get(keys[0]) + r.ErrorIs(err, errDroppedProposal, "Get(%d)", 0) + + // Check that all keys can be accessed from the final proposal + for i := range keys { + got, err := proposals[numProposals-1].Get(keys[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals[i], got, "Get(%d)", i) + } +} + +// Create two proposals with the same root, and ensure that these proposals +// are identified as unique in the backend. +/* + /- P1 -\ /- P4 +R1 P2 + \- P2 -/ \- P5 +*/ +func TestProposeSameRoot(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Create two chains of proposals, resulting in the same root. + keys, vals := kvForTest(10) + + // Create the first proposal chain. + proposal1, err := db.Propose(keys[0:5], vals[0:5]) + r.NoError(err) + proposal3Top, err := proposal1.Propose(keys[5:10], vals[5:10]) + r.NoError(err) + // Create the second proposal chain. + proposal2, err := db.Propose(keys[5:10], vals[5:10]) + r.NoError(err) + proposal3Bottom, err := proposal2.Propose(keys[0:5], vals[0:5]) + r.NoError(err) + // Because the proposals are identical, they should have the same root. + + // Create a unique proposal from each of the two chains. + topKeys := make([][]byte, 5) + topVals := make([][]byte, 5) + for i := range topKeys { + topKeys[i] = keyForTest(i + 10) + topVals[i] = valForTest(i + 10) + } + bottomKeys := make([][]byte, 5) + bottomVals := make([][]byte, 5) + for i := range bottomKeys { + bottomKeys[i] = keyForTest(i + 20) + bottomVals[i] = valForTest(i + 20) + } + proposal4, err := proposal3Top.Propose(topKeys, topVals) + r.NoError(err) + proposal5, err := proposal3Bottom.Propose(bottomKeys, bottomVals) + r.NoError(err) + + // Now we will commit the top chain, and check that the bottom chain is still valid. + err = proposal1.Commit() + r.NoError(err) + err = proposal3Top.Commit() + r.NoError(err) + + // Check that both final proposals are valid. + for i := range keys { + got, err := proposal4.Get(keys[i]) + r.NoError(err, "P4 Get(%d)", i) + r.Equal(vals[i], got, "P4 Get(%d)", i) + got, err = proposal5.Get(keys[i]) + r.NoError(err, "P5 Get(%d)", i) + r.Equal(vals[i], got, "P5 Get(%d)", i) + } + + // Attempt to commit P5. Since this isn't in the canonical chain, it should + // fail. + err = proposal5.Commit() + r.Contains(err.Error(), errWrongParent) // this error is internal to firewood + + // We should be able to commit P4, since it is in the canonical chain. + err = proposal4.Commit() + r.NoError(err) +} + +// Tests that an empty revision can be retrieved. +func TestRevision(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + keys, vals := kvForTest(10) + + // Create a proposal with 10 key-value pairs. + proposal, err := db.Propose(keys, vals) + r.NoError(err) + + // Commit the proposal. + r.NoError(proposal.Commit()) + + root, err := db.Root() + r.NoError(err) + + // Create a revision from this root. + revision, err := db.Revision(root) + r.NoError(err) + t.Cleanup(func() { + r.NoError(revision.Drop()) + }) + + // Check that all keys can be retrieved from the revision. + for i := range keys { + got, err := revision.Get(keys[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(valForTest(i), got, "Get(%d)", i) + } + + // Create a second proposal with 10 key-value pairs. + keys2 := make([][]byte, 10) + vals2 := make([][]byte, 10) + for i := range keys2 { + keys2[i] = keyForTest(i + 10) + vals2[i] = valForTest(i + 10) + } + proposal2, err := db.Propose(keys2, vals2) + r.NoError(err) + // Commit the proposal. + err = proposal2.Commit() + r.NoError(err) + + // Create a "new" revision from the first old root. + revision, err = db.Revision(root) + r.NoError(err) + r.Equal(revision.Root(), root) + t.Cleanup(func() { + r.NoError(revision.Drop()) + }) + // Check that all keys can be retrieved from the revision. + for i := range keys { + got, err := revision.Get(keys[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(valForTest(i), got, "Get(%d)", i) + } +} + +// Tests that even if a proposal is committed, the corresponding revision will not go away +// as we're holding on to it +func TestRevisionOutlivesProposal(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + keys, vals := kvForTest(20) + _, err := db.Update(keys[:10], vals[:10]) + r.NoError(err) + + // Create a proposal with 10 key-value pairs. + nKeys, nVals := keys[10:], vals[10:] + proposal, err := db.Propose(nKeys, nVals) + r.NoError(err) + root, err := proposal.Root() + r.NoError(err) + + rev, err := db.Revision(root) + r.NoError(err) + + // we drop the proposal + r.NoError(proposal.Drop()) + + // revision should outlive the proposal, as we're still referencing its node store + for i, key := range nKeys { + val, err := rev.Get(key) + r.NoError(err) + r.Equal(val, nVals[i]) + } + + r.NoError(rev.Drop()) +} + +// Tests that holding a reference to revision will prevent from it being reaped +func TestRevisionOutlivesReaping(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t, func(config *Config) { + config.Revisions = 2 + }) + + keys, vals := kvForTest(40) + firstRoot, err := db.Update(keys[:10], vals[:10]) + r.NoError(err) + // let's get a revision at root + rev, err := db.Revision(firstRoot) + r.NoError(err) + + // commit two times, this would normally reap the first revision + secondRoot, err := db.Update(keys[10:20], vals[10:20]) + r.NoError(err) + _, err = db.Update(keys[20:30], vals[20:30]) + r.NoError(err) + + // revision should be still accessible, as we're hanging on to it, prevent reaping + nKeys, nVals := keys[:10], vals[:10] + for i, key := range nKeys { + val, err := rev.Get(key) + r.NoError(err) + r.Equal(val, nVals[i]) + } + r.NoError(rev.Drop()) + + // since we dropped the revision, if we commit, reaping will happen (cleaning first two revisions) + _, err = db.Update(keys[30:], vals[30:]) + r.NoError(err) + + _, err = db.Revision(firstRoot) + r.Error(err) + + _, err = db.Revision(secondRoot) + r.Error(err) +} + +func TestInvalidRevision(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Create a fake revision with an valid root. + validRoot := Hash([]byte("counting 32 bytes to make a hash")) + _, err := db.Revision(validRoot) + r.ErrorIs(err, errRevisionNotFound, "Revision(valid root)") +} + +// Tests that edge case `Get` calls are handled correctly. +func TestGetNilCases(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Commit 10 key-value pairs. + keys, vals := kvForTest(20) + root, err := db.Update(keys[:10], vals[:10]) + r.NoError(err) + + // Create the other views + proposal, err := db.Propose(keys[10:], vals[10:]) + r.NoError(err) + revision, err := db.Revision(root) + r.NoError(err) + t.Cleanup(func() { + r.NoError(revision.Drop()) + }) + + // Create edge case keys. + specialKeys := [][]byte{ + nil, + {}, // empty slice + } + for _, k := range specialKeys { + got, err := db.Get(k) + r.NoError(err, "db.Get(%q)", k) + r.Empty(got, "db.Get(%q)", k) + + got, err = revision.Get(k) + r.NoError(err, "Revision.Get(%q)", k) + r.Empty(got, "Revision.Get(%q)", k) + + got, err = proposal.Get(k) + r.NoError(err, "Proposal.Get(%q)", k) + r.Empty(got, "Proposal.Get(%q)", k) + } +} + +func TestEmptyProposals(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + numProposals := 10 + emptyProposals := make([]*Proposal, numProposals) + + // Create several empty proposals + for i := range numProposals { + // Create a proposal with no keys. + var err error + if i == 0 { + emptyProposals[i], err = db.Propose(nil, nil) + } else { + emptyProposals[i], err = emptyProposals[i-1].Propose(nil, nil) + } + r.NoError(err, "Propose(%d)", i) + + // Check that the proposal has no keys. + got, err := emptyProposals[i].Get([]byte("non-existent")) + r.NoError(err, "Get(%d)", i) + r.Empty(got, "Get(%d)", i) + } + + // Create one non-empty proposal. + keys, vals := kvForTest(10) + nonEmptyProposal, err := db.Propose(keys, vals) + r.NoError(err, "Propose non-empty proposal") + + // Check that the proposal has the keys we just inserted. + for i := range keys { + got, err := nonEmptyProposal.Get(keys[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals[i], got, "Get(%d)", i) + } + + // Commit all empty proposals. + for _, p := range emptyProposals { + r.NoError(p.Commit(), "Commit empty proposal") + } + + // Commit the empty proposal. + err = nonEmptyProposal.Commit() + r.NoError(err) + + // Check that the database has the keys from the non-empty proposal. + for i := range keys { + got, err := db.Get(keys[i]) + r.NoError(err, "Get(%d)", i) + r.Equal(vals[i], got, "Get(%d)", i) + } +} + +// Tests the GetFromRoot function for retrieving values from specific root hashes. +func TestGetFromRoot(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Check empty database + emptyRoot, err := db.Root() + r.NoError(err, "Root of empty database") + got, err := db.GetFromRoot(emptyRoot, []byte("non-existent")) + r.NoError(err, "GetFromRoot empty root") + r.Empty(got, "GetFromRoot empty root should return empty value") + + // Insert some initial data + keys, vals := kvForTest(10) + committedRoot, err := db.Update(keys[:5], vals[:5]) + r.NoError(err) + + // Test getting values from first state + for i := range 5 { + got, err := db.GetFromRoot(committedRoot, keys[i]) + r.NoError(err, "GetFromRoot committed key %d", i) + r.Equal(vals[i], got, "GetFromRoot committed key %d", i) + } + + // Replace the first 5 keys with new values + p, err := db.Propose(keys[:5], vals[5:]) + r.NoError(err, "Propose to update first 5 keys") + r.NotNil(p) + + proposedRoot, err := p.Root() + t.Logf("%x", proposedRoot) + r.NoError(err, "Root of proposal") + + // Test that we can still get old values from the first root + for i := range 5 { + got, err := db.GetFromRoot(committedRoot, keys[i]) + r.NoError(err, "GetFromRoot root1 after update, key %d", i) + r.Equal(vals[i], got, "GetFromRoot root1 after update, key %d", i) + + got, err = db.GetFromRoot(proposedRoot, keys[i]) + r.NoError(err, "GetFromRoot root1 newer key %d", i) + r.Equal(vals[i+5], got, "GetFromRoot root1 newer key %d", i) + } + + // Test with valid-length but non-existent root + var nonExistentRoot Hash + for i := range nonExistentRoot { + nonExistentRoot[i] = 0xFF // All 1's, very unlikely to exist + } + _, err = db.GetFromRoot(nonExistentRoot, []byte("key")) + r.Error(err, "GetFromRoot with non-existent root should return error") +} + +func TestGetFromRootParallel(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + key, val := []byte("key"), []byte("value") + allKeys, allVals := kvForTest(10000) // large number to encourage contention + allKeys = append(allKeys, key) + allVals = append(allVals, val) + + // Create a proposal + p, err := db.Propose(allKeys, allVals) + r.NoError(err, "Propose key-value pairs") + + root, err := p.Root() + r.NoError(err, "Root of proposal") + + // Use multiple goroutines to stress test concurrent access + const numReaders = 10 + results := make(chan error, numReaders) + finish := make(chan struct{}) + wg := sync.WaitGroup{} + + readLots := func(readerID int) error { + for j := 0; ; j++ { + got, err := db.GetFromRoot(root, key) + if err != nil { + return fmt.Errorf("reader %d, iteration %d: GetFromRoot error: %w", readerID, j, err) + } + if !bytes.Equal(got, val) { + return fmt.Errorf("reader %d, iteration %d: expected %q, got %q", readerID, j, val, got) + } + + // Add small delays and yield to increase race chances + if j%100 == 0 { + runtime.Gosched() + } + select { + case <-finish: + return nil // Exit if finish signal received + default: + } + } + } + + // Start multiple reader goroutines + for i := 0; i < numReaders; i++ { + wg.Add(1) + go func(readerID int) { + results <- readLots(readerID) + wg.Done() + }(i) + } + + // Add small delay to let readers start + time.Sleep(time.Microsecond * 500) + t.Log("Committing proposal to allow readers to access data") + require.NoError(t, p.Commit(), "Commit proposal") + t.Log("Proposal committed, readers should now access data") + close(finish) // Signal readers to finish + + // Wait for all readers to finish + wg.Wait() + + // Collect all results + for i := 0; i < numReaders; i++ { + err := <-results + r.NoError(err, "Parallel operation failed") + } +} + +func TestHandlesFreeImplicitly(t *testing.T) { + t.Parallel() + + db, err := newDatabase(filepath.Join(t.TempDir(), "test_GC_drops_implicitly.db")) + require.NoError(t, err) + + // make the db non-empty + _, err = db.Update([][]byte{keyForTest(1)}, [][]byte{valForTest(1)}) + require.NoError(t, err) + + var ( + explicitlyDropped []any + implicitlyDropped []any + ) + + // Grab one revision initially. All proposals can also be revisions, so + // this is the only case in which we don't add both a proposal and a revision. + historicExplicit, err := db.LatestRevision() + require.NoErrorf(t, err, "%T.LatestRevision()", db) + require.NoError(t, historicExplicit.Drop()) + explicitlyDropped = append(explicitlyDropped, historicExplicit) + historicImplicit, err := db.LatestRevision() + require.NoErrorf(t, err, "%T.LatestRevision()", db) + implicitlyDropped = append(implicitlyDropped, historicImplicit) + + // These MUST NOT be committed nor dropped as they demonstrate that the GC + // finalizer does it for us. + p0, err := db.Propose(kvForTest(1)) + require.NoErrorf(t, err, "%T.Propose(...)", db) + root0, err := p0.Root() + require.NoErrorf(t, err, "%T.Root()", p0) + rev0, err := db.Revision(root0) + require.NoErrorf(t, err, "%T.Revision(...)", db) + implicitlyDropped = append(implicitlyDropped, p0, rev0) + p1, err := p0.Propose(kvForTest(1)) + require.NoErrorf(t, err, "%T.Propose(...)", p0) + root1, err := p1.Root() + require.NoErrorf(t, err, "%T.Root()", p1) + rev1, err := db.Revision(root1) + require.NoErrorf(t, err, "%T.Revision(...)", db) + implicitlyDropped = append(implicitlyDropped, p1, rev1) + + // Demonstrates that explicit [Proposal.Commit] and [Proposal.Drop] calls + // are sufficient to unblock [Database.Close]. + // Each proposal has a corresponding revision to drop as well. + for name, free := range map[string](func(*Proposal) error){ + "Commit": (*Proposal).Commit, + "Drop": (*Proposal).Drop, + } { + p, err := db.Propose(kvForTest(1)) + require.NoErrorf(t, err, "%T.Propose(...)", db) + root, err := p.Root() + require.NoErrorf(t, err, "%T.Root()", p) + rev, err := db.Revision(root) + require.NoErrorf(t, err, "%T.Revision(...)", db) + require.NoErrorf(t, free(p), "%T.%s()", p, name) + require.NoErrorf(t, rev.Drop(), "%T.Drop()", rev) + explicitlyDropped = append(explicitlyDropped, p, rev) + } + + done := make(chan struct{}) + go func() { + require.NoErrorf(t, db.Close(oneSecCtx(t)), "%T.Close()", db) + close(done) + }() + + select { + case <-done: + require.Failf(t, "Unexpected return", "%T.Close() returned with undropped %T", db, p0) + case <-time.After(300 * time.Millisecond): + // TODO(arr4n) use `synctest` package when at Go 1.25 + } + + // This is the last time we must guarantee that these handles are reachable. + // After this, they must be unreachable so that the GC can collect them. + for _, h := range implicitlyDropped { + runtime.KeepAlive(h) + } + + // In practice there's no need to call [runtime.GC] if [Database.Close] is + // called after all proposals are unreachable, as it does it itself. + runtime.GC() + // Note that [Database.Close] waits for outstanding handles, so this would + // block permanently if the unreachability of implicitly dropped handles didn't + // result in their Drop methods being called. + <-done + + for _, p := range explicitlyDropped { + runtime.KeepAlive(p) + } +} + +func TestFjallStore(t *testing.T) { + r := require.New(t) + + var ( + tmpdir = t.TempDir() + dbFile = filepath.Join(tmpdir, "test.db") + rootStoreDir = filepath.Join(tmpdir, "root_store_dir") + ) + + // Create a new database with RootStore enabled + config := DefaultConfig() + config.RootStoreDir = rootStoreDir + // Setting the number of in-memory revisions to 5 tests that revision nodes + // are not reaped prior to closing the database. + config.Revisions = 5 + + db, err := New(dbFile, config) + r.NoError(err) + + // Create and commit 10 proposals + numRevisions := 10 + key := []byte("root_store") + _, vals := kvForTest(numRevisions) + revisionRoots := make([]Hash, numRevisions) + for i := range numRevisions { + proposal, err := db.Propose([][]byte{key}, [][]byte{vals[i]}) + r.NoError(err) + r.NoError(proposal.Commit()) + + revisionRoots[i], err = proposal.Root() + r.NoError(err) + } + + // Close and reopen the database + r.NoError(db.Close(t.Context())) + + db, err = New(dbFile, config) + r.NoError(err) + + // Verify that we can access all revisions + for i := range numRevisions { + revision, err := db.Revision(revisionRoots[i]) + r.NoError(err) + + defer func() { + r.NoError(revision.Drop()) + }() + + v, err := revision.Get(key) + r.NoError(err) + + r.Equal(vals[i], v) + r.NoError(revision.Drop()) + } +} + +type kvIter interface { + SetBatchSize(int) + Next() bool + Key() []byte + Value() []byte + Err() error + Drop() error +} +type borrowIter struct{ it *Iterator } + +func (b *borrowIter) SetBatchSize(batchSize int) { b.it.SetBatchSize(batchSize) } +func (b *borrowIter) Next() bool { return b.it.NextBorrowed() } +func (b *borrowIter) Key() []byte { return b.it.Key() } +func (b *borrowIter) Value() []byte { return b.it.Value() } +func (b *borrowIter) Err() error { return b.it.Err() } +func (b *borrowIter) Drop() error { return b.it.Drop() } + +func assertIteratorYields(r *require.Assertions, it kvIter, keys [][]byte, vals [][]byte) { + i := 0 + for ; it.Next(); i += 1 { + r.Equal(keys[i], it.Key()) + r.Equal(vals[i], it.Value()) + } + r.NoError(it.Err()) + r.Equal(len(keys), i) +} + +type iteratorConfigFn = func(it kvIter) kvIter + +var iterConfigs = map[string]iteratorConfigFn{ + "Owned": func(it kvIter) kvIter { return it }, + "Borrowed": func(it kvIter) kvIter { return &borrowIter{it: it.(*Iterator)} }, + "Single": func(it kvIter) kvIter { + it.SetBatchSize(1) + return it + }, + "Batched": func(it kvIter) kvIter { + it.SetBatchSize(100) + return it + }, +} + +func runIteratorTestForModes(t *testing.T, fn func(*testing.T, iteratorConfigFn), modes ...string) { + testName := strings.Join(modes, "/") + t.Run(testName, func(t *testing.T) { + r := require.New(t) + fn(t, func(it kvIter) kvIter { + for _, m := range modes { + config, ok := iterConfigs[m] + r.Truef(ok, "specified config mode %s does not exist", m) + it = config(it) + } + return it + }) + }) +} + +func runIteratorTestForAllModes(parentT *testing.T, fn func(*testing.T, iteratorConfigFn)) { + for _, dataMode := range []string{"Owned", "Borrowed"} { + for _, batchMode := range []string{"Single", "Batched"} { + runIteratorTestForModes(parentT, fn, batchMode, dataMode) + } + } +} + +// Tests that basic iterator functionality works +func TestIter(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(100) + _, err := db.Update(keys, vals) + r.NoError(err) + + runIteratorTestForAllModes(t, func(t *testing.T, cfn iteratorConfigFn) { + r := require.New(t) + rev, err := db.LatestRevision() + r.NoError(err) + it, err := rev.Iter(nil) + r.NoError(err) + t.Cleanup(func() { + r.NoError(it.Drop()) + r.NoError(rev.Drop()) + }) + + assertIteratorYields(r, cfn(it), keys, vals) + }) +} + +func TestIterOnRoot(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(240) + firstRoot, err := db.Update(keys[:80], vals[:80]) + r.NoError(err) + secondRoot, err := db.Update(keys[80:160], vals[80:160]) + r.NoError(err) + thirdRoot, err := db.Update(keys[160:], vals[160:]) + r.NoError(err) + + runIteratorTestForAllModes(t, func(t *testing.T, cfn iteratorConfigFn) { + r := require.New(t) + r1, err := db.Revision(firstRoot) + r.NoError(err) + h1, err := r1.Iter(nil) + r.NoError(err) + t.Cleanup(func() { + r.NoError(h1.Drop()) + r.NoError(r1.Drop()) + }) + + r2, err := db.Revision(secondRoot) + r.NoError(err) + h2, err := r2.Iter(nil) + r.NoError(err) + t.Cleanup(func() { + r.NoError(h2.Drop()) + r.NoError(r2.Drop()) + }) + + r3, err := db.Revision(thirdRoot) + r.NoError(err) + h3, err := r3.Iter(nil) + r.NoError(err) + t.Cleanup(func() { + r.NoError(h3.Drop()) + r.NoError(r3.Drop()) + }) + + assertIteratorYields(r, cfn(h1), keys[:80], vals[:80]) + assertIteratorYields(r, cfn(h2), keys[:160], vals[:160]) + assertIteratorYields(r, cfn(h3), keys, vals) + }) +} + +func TestIterOnProposal(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(240) + _, err := db.Update(keys, vals) + r.NoError(err) + + runIteratorTestForAllModes(t, func(t *testing.T, cfn iteratorConfigFn) { + r := require.New(t) + updatedValues := make([][]byte, len(vals)) + copy(updatedValues, vals) + + changedKeys := make([][]byte, 0) + changedVals := make([][]byte, 0) + for i := 0; i < len(vals); i += 4 { + changedKeys = append(changedKeys, keys[i]) + newVal := []byte{byte(i)} + changedVals = append(changedVals, newVal) + updatedValues[i] = newVal + } + p, err := db.Propose(changedKeys, changedVals) + r.NoError(err) + it, err := p.Iter(nil) + r.NoError(err) + t.Cleanup(func() { + r.NoError(it.Drop()) + }) + + assertIteratorYields(r, cfn(it), keys, updatedValues) + }) +} + +// Tests that the iterator still works after proposal is committed +func TestIterAfterProposalCommit(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + keys, vals := kvForTest(10) + p, err := db.Propose(keys, vals) + r.NoError(err) + + it, err := p.Iter(nil) + r.NoError(err) + t.Cleanup(func() { + r.NoError(it.Drop()) + }) + + err = p.Commit() + r.NoError(err) + + // iterate after commit + // because iterator hangs on the nodestore reference of proposal + // the nodestore won't be dropped until we drop the iterator + assertIteratorYields(r, it, keys, vals) +} + +// Tests that the iterator on latest revision works properly after a proposal commit +func TestIterUpdate(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + keys, vals := kvForTest(10) + _, err := db.Update(keys, vals) + r.NoError(err) + + // get an iterator on latest revision + rev, err := db.LatestRevision() + r.NoError(err) + it, err := rev.Iter(nil) + r.NoError(err) + t.Cleanup(func() { + r.NoError(it.Drop()) + r.NoError(rev.Drop()) + }) + + // update the database + keys2, vals2 := kvForTest(10) + _, err = db.Update(keys2, vals2) + r.NoError(err) + + // iterate after commit + // because iterator is fixed on the revision hash, it should return the initial values + assertIteratorYields(r, it, keys, vals) +} + +// Tests the iterator's behavior after exhaustion, should safely return empty item/batch, indicating done +func TestIterDone(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + keys, vals := kvForTest(18) + _, err := db.Update(keys, vals) + r.NoError(err) + + // get an iterator on latest revision + rev, err := db.LatestRevision() + r.NoError(err) + it, err := rev.Iter(nil) + r.NoError(err) + t.Cleanup(func() { + r.NoError(it.Drop()) + r.NoError(rev.Drop()) + }) + // consume the iterator + assertIteratorYields(r, it, keys, vals) + // calling next again should be safe and return false + r.False(it.Next()) + r.NoError(it.Err()) + + // get a new iterator + it2, err := rev.Iter(nil) + r.NoError(err) + // set batch size to 5 + it2.SetBatchSize(5) + // consume the iterator + assertIteratorYields(r, it2, keys, vals) + // calling next again should be safe and return false + r.False(it.Next()) + r.NoError(it.Err()) +} + +// TestNilVsEmptyValue tests that nil values cause delete operations while +// empty []byte{} values result in inserts with empty values. +func TestNilVsEmptyValue(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Insert a key with a non-empty value + key1 := []byte("key1") + value1 := []byte("value1") + _, err := db.Update([][]byte{key1}, [][]byte{value1}) + r.NoError(err, "Insert key1 with value1") + + // Verify the key exists + got, err := db.Get(key1) + r.NoError(err, "Get key1") + r.Equal(value1, got, "key1 should have value1") + + // Insert another key with an empty value (not nil) + key2 := []byte("key2") + emptyValue := []byte{} // empty slice, not nil + _, err = db.Update([][]byte{key2}, [][]byte{emptyValue}) + r.NoError(err, "Insert key2 with empty value") + + // Verify key2 exists with empty value + got, err = db.Get(key2) + r.NoError(err, "Get key2") + r.NotNil(got, "key2 should exist (not be nil)") + r.Empty(got, "key2 should have empty value") + + // Now use nil value to delete key1 (DeleteRange operation) + var nilValue []byte = nil + _, err = db.Update([][]byte{key1}, [][]byte{nilValue}) + r.NoError(err, "Delete key1 with nil value") + + // Verify key1 is deleted + got, err = db.Get(key1) + r.NoError(err, "Get key1 after delete") + r.Nil(got, "key1 should be deleted") + + // Verify key2 still exists with empty value + got, err = db.Get(key2) + r.NoError(err, "Get key2 after key1 delete") + r.NotNil(got, "key2 should still exist") + r.Empty(got, "key2 should still have empty value") + + // Test with batch operations + key3 := []byte("key3") + value3 := []byte("value3") + key4 := []byte("key4") + emptyValue4 := []byte{} + + _, err = db.Update( + [][]byte{key3, key4}, + [][]byte{value3, emptyValue4}, + ) + r.NoError(err, "Batch insert key3 and key4") + + // Verify both keys exist + got, err = db.Get(key3) + r.NoError(err, "Get key3") + r.Equal(value3, got, "key3 should have value3") + + got, err = db.Get(key4) + r.NoError(err, "Get key4") + r.NotNil(got, "key4 should exist") + r.Empty(got, "key4 should have empty value") +} + +// TestCloseWithCancelledContext verifies that Database.Close returns +// ErrActiveKeepAliveHandles when the context is cancelled before handles are dropped. +func TestCloseWithCancelledContext(t *testing.T) { + r := require.New(t) + dbFile := filepath.Join(t.TempDir(), "test.db") + db, err := newDatabase(dbFile) + r.NoError(err) + + // Create a proposal to keep a handle active + keys, vals := kvForTest(1) + proposal, err := db.Propose(keys, vals) + r.NoError(err) + + ctx, cancel := context.WithCancel(t.Context()) + + var wg sync.WaitGroup + wg.Add(1) + go func() { + defer wg.Done() + + err = db.Close(ctx) + }() + + cancel() + wg.Wait() + + r.ErrorIs(err, ErrActiveKeepAliveHandles, "Close should return ErrActiveKeepAliveHandles when context is cancelled") + r.ErrorIs(err, context.Canceled, "Close error should wrap context.Canceled") + + // Drop the proposal + r.NoError(proposal.Drop()) + + // Now Close should succeed + r.NoError(db.Close(oneSecCtx(t))) +} + +// TestCloseWithMultipleActiveHandles verifies that Database.Close returns +// ErrActiveKeepAliveHandles when multiple handles are active and context is cancelled. +func TestCloseWithMultipleActiveHandles(t *testing.T) { + r := require.New(t) + dbFile := filepath.Join(t.TempDir(), "test.db") + db, err := newDatabase(dbFile) + r.NoError(err) + + // Create multiple proposals + keys1, vals1 := kvForTest(3) + proposal1, err := db.Propose(keys1[:1], vals1[:1]) + r.NoError(err) + proposal2, err := db.Propose(keys1[1:2], vals1[1:2]) + r.NoError(err) + proposal3, err := db.Propose(keys1[2:3], vals1[2:3]) + r.NoError(err) + + // Create multiple revisions + root1, err := db.Update([][]byte{keyForTest(10)}, [][]byte{valForTest(10)}) + r.NoError(err) + root2, err := db.Update([][]byte{keyForTest(20)}, [][]byte{valForTest(20)}) + r.NoError(err) + + revision1, err := db.Revision(root1) + r.NoError(err) + revision2, err := db.Revision(root2) + r.NoError(err) + + // Create a cancelled context + ctx, cancel := context.WithCancel(t.Context()) + cancel() + + // Close should return ErrActiveKeepAliveHandles + err = db.Close(ctx) + r.ErrorIs(err, ErrActiveKeepAliveHandles, "Close should return ErrActiveKeepAliveHandles with multiple active handles") + r.ErrorIs(err, context.Canceled, "Close error should wrap context.Canceled") + + // Drop all handles + r.NoError(proposal1.Drop()) + r.NoError(proposal2.Drop()) + r.NoError(proposal3.Drop()) + r.NoError(revision1.Drop()) + r.NoError(revision2.Drop()) + + // Now Close should succeed + r.NoError(db.Close(oneSecCtx(t))) +} + +// TestCloseSucceedsWhenHandlesDroppedInTime verifies that Database.Close succeeds +// when all handles are dropped before the context timeout. +func TestCloseSucceedsWhenHandlesDroppedInTime(t *testing.T) { + r := require.New(t) + dbFile := filepath.Join(t.TempDir(), "test.db") + db, err := newDatabase(dbFile) + r.NoError(err) + + // Create two active proposals + keys, vals := kvForTest(2) + proposal1, err := db.Propose(keys[:1], vals[:1]) + r.NoError(err) + proposal2, err := db.Propose(keys[1:2], vals[1:2]) + r.NoError(err) + + // Channel to receive Close result + closeDone := make(chan error, 1) + + // Start Close in a goroutine + go func() { + closeDone <- db.Close(oneSecCtx(t)) + }() + + // Drop handles after a short delay (before timeout) + time.Sleep(100 * time.Millisecond) + r.NoError(proposal1.Drop()) + r.NoError(proposal2.Drop()) + r.NoError(<-closeDone, "Close should succeed when handles are dropped before timeout") +} diff --git a/firewood/ffi/flake.lock b/firewood/ffi/flake.lock new file mode 100644 index 000000000000..1910fe44ebe1 --- /dev/null +++ b/firewood/ffi/flake.lock @@ -0,0 +1,146 @@ +{ + "nodes": { + "crane": { + "locked": { + "lastModified": 1762538466, + "narHash": "sha256-8zrIPl6J+wLm9MH5ksHcW7BUHo7jSNOu0/hA0ohOOaM=", + "owner": "ipetkov", + "repo": "crane", + "rev": "0cea393fffb39575c46b7a0318386467272182fe", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "golang": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "dir": "nix/go", + "lastModified": 1760973838, + "narHash": "sha256-UnngvRB45lUeWwot7cvB0MaedaQEQmcw+q8Y6WbeGtE=", + "owner": "ava-labs", + "repo": "avalanchego", + "rev": "f10757d594eedf0f016bc1400739788c542f005f", + "type": "github" + }, + "original": { + "dir": "nix/go", + "owner": "ava-labs", + "ref": "f10757d594eedf0f016bc1400739788c542f005f", + "repo": "avalanchego", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1759735786, + "narHash": "sha256-a0+h02lyP2KwSNrZz4wLJTu9ikujNsTWIC874Bv7IJ0=", + "rev": "20c4598c84a671783f741e02bf05cbfaf4907cff", + "revCount": 810859, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2505.810859%2Brev-20c4598c84a671783f741e02bf05cbfaf4907cff/0199bc43-02e2-7036-8e2c-e43f6d6b4ede/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.2505.%2A.tar.gz" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1762498405, + "narHash": "sha256-Zg/SCgCaAioc0/SVZQJxuECGPJy+OAeBcGeA5okdYDc=", + "rev": "6faeb062ee4cf4f105989d490831713cc5a43ee1", + "revCount": 812554, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2505.812554%2Brev-6faeb062ee4cf4f105989d490831713cc5a43ee1/019a5f75-0159-79b8-b171-f9b6d2148da2/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.2505.%2A.tar.gz" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1744536153, + "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18dd725c29603f582cf1900e0d25f9f1063dbf11", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "crane": "crane", + "flake-utils": "flake-utils", + "golang": "golang", + "nixpkgs": "nixpkgs_2", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1762742448, + "narHash": "sha256-XMxV0h13gg63s0sV6beihCIqdpcJhtbse6DHI743nvo=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "7f3556887e3375dc26ff1601b57c93ee286f2c5e", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/firewood/ffi/flake.nix b/firewood/ffi/flake.nix new file mode 100644 index 000000000000..dab896af88b6 --- /dev/null +++ b/firewood/ffi/flake.nix @@ -0,0 +1,147 @@ +{ + # To test with arbitrary firewood versions (alternative to firewood-go-ethhash): + # - Install nix: https://github.com/DeterminateSystems/nix-installer?tab=readme-ov-file#install-nix + # - Clone firewood locally at desired version/commit + # - Build: `cd ffi && nix build` + # - In your Go project: `go mod edit -replace github.com/ava-labs/firewood-go-ethhash/ffi=/path/to/firewood/ffi/result/ffi` + + description = "Firewood FFI library and development environment"; + + inputs = { + nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2505.*.tar.gz"; + rust-overlay.url = "github:oxalica/rust-overlay"; + crane.url = "github:ipetkov/crane"; + flake-utils.url = "github:numtide/flake-utils"; + golang.url = "github:ava-labs/avalanchego?dir=nix/go&ref=f10757d594eedf0f016bc1400739788c542f005f"; + }; + + outputs = { self, nixpkgs, rust-overlay, crane, flake-utils, golang }: + flake-utils.lib.eachDefaultSystem (system: + let + overlays = [ (import rust-overlay) ]; + pkgs = import nixpkgs { inherit system overlays; }; + inherit (pkgs) lib; + + go = golang.packages.${system}.default; + + rustToolchain = pkgs.rust-bin.stable.latest.default.override { + extensions = [ "rust-src" "rustfmt" "clippy" ]; + }; + + craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain; + + # Extract crate info from Cargo.toml files + ffiCargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); + workspaceCargoToml = builtins.fromTOML (builtins.readFile ../Cargo.toml); + + src = lib.cleanSourceWith { + src = craneLib.path ./..; + filter = path: type: + (lib.hasSuffix "\.md" path) || + (lib.hasSuffix "\.go" path) || + (lib.hasSuffix "go.mod" path) || + (lib.hasSuffix "go.sum" path) || + (lib.hasSuffix "firewood.h" path) || + (craneLib.filterCargoSources path type); + }; + + commonArgs = { + inherit src; + strictDeps = true; + dontStrip = true; + + # Build only the firewood-ffi crate + pname = ffiCargoToml.package.name; + version = workspaceCargoToml.workspace.package.version; + + nativeBuildInputs = with pkgs; [ + pkg-config + ]; + + } // lib.optionalAttrs pkgs.stdenv.isDarwin { + # Set macOS deployment target for Darwin builds + MACOSX_DEPLOYMENT_TARGET = "15.0"; + }; + + cargoArtifacts = craneLib.buildDepsOnly (commonArgs // { + # Use cargo alias defined in .cargo/config.toml + cargoBuildCommand = "cargo build-static-ffi"; + }); + + firewood-ffi = craneLib.buildPackage (commonArgs // { + inherit cargoArtifacts; + # Use cargo alias defined in .cargo/config.toml + cargoBuildCommand = "cargo build-static-ffi"; + + # Disable tests - we only need to build the static library + doCheck = false; + + # Install the static library and header + postInstall = '' + # Create a package structure compatible with FIREWOOD_LD_MODE=STATIC_LIBS + mkdir -p $out/ffi + cp -R ./ffi/* $out/ffi/ + mkdir -p $out/ffi/libs/${pkgs.stdenv.hostPlatform.config} + cp target/maxperf/libfirewood_ffi.a $out/ffi/libs/${pkgs.stdenv.hostPlatform.config}/ + + # Run go generate to switch CGO directives to STATIC_LIBS mode + cd $out/ffi + HOME=$TMPDIR GOTOOLCHAIN=local FIREWOOD_LD_MODE=STATIC_LIBS ${go}/bin/go generate + ''; + + meta = with lib; { + description = "C FFI bindings for Firewood, an embedded key-value store"; + homepage = "https://github.com/ava-labs/firewood"; + license = { + fullName = "Ava Labs Ecosystem License 1.1"; + url = "https://github.com/ava-labs/firewood/blob/main/LICENSE.md"; + }; + platforms = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + }; + }); + in + { + packages = { + inherit firewood-ffi; + default = firewood-ffi; + }; + + apps.go = { + type = "app"; + program = "${go}/bin/go"; + }; + + apps.jq = { + type = "app"; + program = "${pkgs.jq}/bin/jq"; + }; + + apps.just = { + type = "app"; + program = "${pkgs.just}/bin/just"; + }; + + devShells.default = craneLib.devShell { + inputsFrom = [ firewood-ffi ]; + + packages = with pkgs; [ + firewood-ffi + go + jq + just + rustToolchain + ]; + + shellHook = '' + # Ensure golang bin is in the path + GOBIN="$(go env GOPATH)/bin" + if [[ ":$PATH:" != *":$GOBIN:"* ]]; then + export PATH="$GOBIN:$PATH" + fi + + # Force sequential build of vendored jemalloc for reproducibility + export MAKEFLAGS="-j1" + ''; + }; + }); +} diff --git a/firewood/ffi/generate_cgo.go b/firewood/ffi/generate_cgo.go new file mode 100644 index 000000000000..a314724f22b2 --- /dev/null +++ b/firewood/ffi/generate_cgo.go @@ -0,0 +1,149 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//go:build ignore + +// go generate script +// +// This script fixes up a go file to enable/disable the correct cgo directives, +// tailored for use in firewood.go to eliminate linker warnings for production builds. +// +// It scans for blocks of cgo directives, using marker lines like this: +// FIREWOOD_CGO_BEGIN_ +// cgo line 1 +// ... +// cgo line n +// FIREWOOD_CGO_END_ +// +// FIREWOOD_LD_MODE is an environment variable that decides which blocks are activated. +// The default value for FIREWOOD_LD_MODE is "LOCAL_LIBS" for local development. +// When building production static libraries, FIREWOOD_LD_MODE is set to "STATIC_LIBS" +// in the github actions workflow. +// +// The script enables CGO directives for the target mode and comments out CGO directives +// that do not match. +// +// CGO directives are already comments and CGO does not allow interleaving regular +// comments with CGO directives. To disable, we must double escape the CGO directives +// with: +// +// // #cgo ... +// +// The go file may contain multiple such blocks, but nesting is not allowed. + +package main + +import ( + "errors" + "fmt" + "log" + "os" + "strings" +) + +const ( + defaultMode = "LOCAL_LIBS" +) + +var errGoFileNotSet = errors.New("GOFILE is not set") + +func main() { + mode := getFirewoodLdMode() + + targetFile, err := getTargetFile() + if err != nil { + log.Fatalf("Error switching CGO mode to %s:\n%v", mode, err) + } + + if err := changeCgoDirectivesForFile(mode, targetFile); err != nil { + log.Fatalf("Error switching CGO mode to %s:\n%v", mode, err) + } + + fmt.Printf("Successfully switched CGO directives to %s mode\n", mode) +} + +// getFirewoodLdMode returns the FIREWOOD_LD_MODE environment variable. +// Defaults to "LOCAL_LIBS". +func getFirewoodLdMode() string { + mode, ok := os.LookupEnv("FIREWOOD_LD_MODE") + if !ok { + mode = "LOCAL_LIBS" + } + return mode +} + +func getTargetFile() (string, error) { + targetFile, ok := os.LookupEnv("GOFILE") + if !ok { + return "", errGoFileNotSet + } + return targetFile, nil +} + +func changeCgoDirectivesForFile(targetMode string, targetFile string) error { + originalFileContent, err := os.ReadFile(targetFile) + if err != nil { + return fmt.Errorf("failed to read %s: %w", targetFile, err) + } + + fileLines := strings.Split(string(originalFileContent), "\n") + + // Initial state is "None" which does not process any lines + currentBlockName := "None" + for i, line := range fileLines { + // process state transitions + // if the line starts with "// FIREWOOD_CGO_BEGIN_", set the state to the text after the prefix + if newBlockName, ok := strings.CutPrefix(line, "// // FIREWOOD_CGO_BEGIN_"); ok { + if currentBlockName != "None" { + return fmt.Errorf("[ERROR] %s:%d: nested CGO blocks not allowed (found %s after %s)", targetFile, i+1, newBlockName, currentBlockName) + } + currentBlockName = newBlockName + continue + } else if line == fmt.Sprintf("// // FIREWOOD_CGO_END_%s", currentBlockName) { + currentBlockName = "None" + continue + } + + // If we are in a block, process the line + if currentBlockName != "None" { + if !isCGODirective(line) { + return fmt.Errorf("[ERROR] %s:%d: invalid CGO directive in %s section:\n===\n%s\n===\n", targetFile, i+1, currentBlockName, line) + } + if currentBlockName == targetMode { + fileLines[i] = activateCGOLine(fileLines[i]) + } else { + fileLines[i] = deactivateCGOLine(fileLines[i]) + } + } + } + + if currentBlockName != "None" { + return fmt.Errorf("[ERROR] %s: unterminated CGO block ended in %s", targetFile, currentBlockName) + } + + // If the contents changed, write it back to the file + newContents := strings.Join(fileLines, "\n") + if newContents == string(originalFileContent) { + fmt.Printf("[INFO] No changes needed to %s\n", targetFile) + return nil + } + return os.WriteFile(targetFile, []byte(newContents), 0644) +} + +func isCGODirective(line string) bool { + trimmed := strings.TrimSpace(line) + return strings.HasPrefix(trimmed, "// #cgo") || strings.HasPrefix(trimmed, "// // #cgo") +} + +func activateCGOLine(line string) string { + // Convert "// // #cgo" to "// #cgo" + return strings.Replace(line, "// // #cgo", "// #cgo", 1) +} +func deactivateCGOLine(line string) string { + // Convert "// #cgo" to "// // #cgo" (but not "// // #cgo" to "// // // #cgo") + if strings.Contains(line, "// #cgo") && !strings.Contains(line, "// // #cgo") { + return strings.Replace(line, "// #cgo", "// // #cgo", 1) + } + // Already deactivated + return line +} diff --git a/firewood/ffi/go.mod b/firewood/ffi/go.mod new file mode 100644 index 000000000000..30ef658c3cd8 --- /dev/null +++ b/firewood/ffi/go.mod @@ -0,0 +1,31 @@ +module github.com/ava-labs/firewood/ffi + +go 1.24 + +// Changes to the toolchain version should be replicated in: +// - ffi/go.mod (here) +// - ffi/flake.nix (update golang.url to a version of avalanchego's nix/go/flake.nix that uses the desired version and run `just update-ffi-flake`) +// - ffi/tests/eth/go.mod +// - ffi/tests/firewood/go.mod +// `just check-golang-version` validates that these versions are in sync and will run in CI as part of the ffi-nix job. +toolchain go1.24.9 + +require ( + github.com/prometheus/client_golang v1.22.0 + github.com/prometheus/client_model v0.6.1 + github.com/prometheus/common v0.62.0 + github.com/stretchr/testify v1.10.0 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + golang.org/x/sys v0.30.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/firewood/ffi/go.sum b/firewood/ffi/go.sum new file mode 100644 index 000000000000..546cb55f6fa1 --- /dev/null +++ b/firewood/ffi/go.sum @@ -0,0 +1,38 @@ +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/firewood/ffi/iterator.go b/firewood/ffi/iterator.go new file mode 100644 index 000000000000..08a7cf7796d2 --- /dev/null +++ b/firewood/ffi/iterator.go @@ -0,0 +1,177 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +// #include +// #include "firewood.h" +import "C" + +import ( + "errors" + "fmt" + "unsafe" +) + +type Iterator struct { + // handle is an opaque pointer to the iterator within Firewood. It should be + // passed to the C FFI functions that operate on iterators + // + // It is not safe to call these methods with a nil handle. + handle *C.IteratorHandle + + // batchSize is the number of items that are loaded at once + // to reduce ffi call overheads + batchSize int + + // loadedPairs is the latest loaded key value pairs retrieved + // from the iterator, not yet consumed by user + loadedPairs []*ownedKeyValue + + // current* fields correspond to the current cursor state + // nil/empty if not started or exhausted; refreshed on each Next(). + currentPair *ownedKeyValue + currentKey []byte + currentValue []byte + // FFI resource for current pair or batch to free on advance or drop + currentResource interface{ free() error } + + // err is the error from the iterator, if any + err error +} + +func (it *Iterator) freeCurrentAllocation() error { + if it.currentResource == nil { + return nil + } + e := it.currentResource.free() + it.currentResource = nil + return e +} + +func (it *Iterator) nextInternal() error { + if len(it.loadedPairs) > 0 { + it.currentPair, it.loadedPairs = it.loadedPairs[0], it.loadedPairs[1:] + return nil + } + + // current resources should **only** be freed, on the next call to the FFI + // this is to make sure we don't invalidate a batch in between iteration + if e := it.freeCurrentAllocation(); e != nil { + return e + } + if it.batchSize <= 1 { + kv, e := getKeyValueFromResult(C.fwd_iter_next(it.handle)) + if e != nil { + return e + } + it.currentPair = kv + it.currentResource = kv + } else { + batch, e := getKeyValueBatchFromResult(C.fwd_iter_next_n(it.handle, C.size_t(it.batchSize))) + if e != nil { + return e + } + pairs := batch.copy() + if len(pairs) > 0 { + it.currentPair, it.loadedPairs = pairs[0], pairs[1:] + } else { + it.currentPair = nil + } + it.currentResource = batch + } + + return nil +} + +// SetBatchSize sets the max number of pairs to be retrieved in one ffi call. +func (it *Iterator) SetBatchSize(batchSize int) { + it.batchSize = batchSize +} + +// Next proceeds to the next item on the iterator, and returns true +// if succeeded and there is a pair available. +// The new pair could be retrieved with Key and Value methods. +func (it *Iterator) Next() bool { + it.err = it.nextInternal() + if it.currentPair == nil || it.err != nil { + return false + } + k, v := it.currentPair.copy() + it.currentKey = k + it.currentValue = v + return true +} + +// NextBorrowed is like Next, but Key and Value **borrow** rust-owned buffers. +// +// Lifetime: the returned slices are valid **only until** the next call to +// Next, NextBorrowed, Close, or any operation that advances/invalidates the iterator. +// They alias FFI-owned memory that will be **freed or reused** on the next advance. +// +// Do **not** retain, store, or modify these slices. +// **Copy** or use Next if you need to keep them. +// Misuse can read freed memory and cause undefined behavior. +func (it *Iterator) NextBorrowed() bool { + it.err = it.nextInternal() + if it.currentPair == nil || it.err != nil { + return false + } + it.currentKey = it.currentPair.key.BorrowedBytes() + it.currentValue = it.currentPair.value.BorrowedBytes() + it.err = nil + return true +} + +// Key returns the key of the current pair +func (it *Iterator) Key() []byte { + if it.currentPair == nil || it.err != nil { + return nil + } + return it.currentKey +} + +// Value returns the value of the current pair +func (it *Iterator) Value() []byte { + if it.currentPair == nil || it.err != nil { + return nil + } + return it.currentValue +} + +// Err returns the error if Next failed +func (it *Iterator) Err() error { + return it.err +} + +// Drop drops the iterator and releases the resources +func (it *Iterator) Drop() error { + err := it.freeCurrentAllocation() + if it.handle != nil { + // Always free the iterator even if releasing the current KV/batch failed. + // The iterator holds a NodeStore ref that must be dropped. + return errors.Join( + err, + getErrorFromVoidResult(C.fwd_free_iterator(it.handle))) + } + return err +} + +// getIteratorFromIteratorResult converts a C.IteratorResult to an Iterator or error. +func getIteratorFromIteratorResult(result C.IteratorResult) (*Iterator, error) { + switch result.tag { + case C.IteratorResult_NullHandlePointer: + return nil, errDBClosed + case C.IteratorResult_Ok: + body := (*C.IteratorResult_Ok_Body)(unsafe.Pointer(&result.anon0)) + proposal := &Iterator{ + handle: body.handle, + } + return proposal, nil + case C.IteratorResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.IteratorResult tag: %d", result.tag) + } +} diff --git a/firewood/ffi/keepalive.go b/firewood/ffi/keepalive.go new file mode 100644 index 000000000000..458b88b6fc60 --- /dev/null +++ b/firewood/ffi/keepalive.go @@ -0,0 +1,61 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +import "sync" + +// databaseKeepAliveHandle is added to types that hold a lease on the database +// to ensure it is not closed while those types are still in use. +// +// This is necessary to prevent use-after-free bugs where a type holding a +// reference to the database outlives the database itself. Even attempting to +// free those objects after the database has been closed will lead to undefined +// behavior, as a part of the underling Rust object will have already been freed. +type databaseKeepAliveHandle struct { + mu sync.Mutex + // [Database.Close] blocks on this WaitGroup, which is set and incremented + // by [newKeepAliveHandle], and decremented by + // [databaseKeepAliveHandle.disown]. + outstandingHandles *sync.WaitGroup +} + +// init initializes the keep-alive handle to track a new outstanding handle. +func (h *databaseKeepAliveHandle) init(wg *sync.WaitGroup) { + // lock not necessary today, but will be necessary in the future for types + // that initialize the handle at some point after construction (#1429). + h.mu.Lock() + defer h.mu.Unlock() + + if h.outstandingHandles != nil { + // setting the finalizer twice will also panic, so we're panicking + // early to provide better context + panic("keep-alive handle already initialized") + } + + h.outstandingHandles = wg + h.outstandingHandles.Add(1) +} + +// disown indicates that the object owning this handle is no longer keeping the +// database alive. If [attemptDisown] returns an error, disowning will only occur +// if [disownEvenOnErr] is true. +// +// This method is safe to call multiple times; subsequent calls after the first +// will continue to invoke [attemptDisown] but will not decrement the wait group +// unless [databaseKeepAliveHandle.init] was called again in the meantime. +func (h *databaseKeepAliveHandle) disown(disownEvenOnErr bool, attemptDisown func() error) error { + h.mu.Lock() + defer h.mu.Unlock() + + err := attemptDisown() + + if (err == nil || disownEvenOnErr) && h.outstandingHandles != nil { + h.outstandingHandles.Done() + // prevent calling `Done` multiple times if disown is called again, which + // may happen when the finalizer runs after an explicit call to Drop or Commit. + h.outstandingHandles = nil + } + + return err +} diff --git a/firewood/ffi/maybe.go b/firewood/ffi/maybe.go new file mode 100644 index 000000000000..baa2a7eca7fe --- /dev/null +++ b/firewood/ffi/maybe.go @@ -0,0 +1,54 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +// #include +// #include "firewood.h" +import "C" + +import ( + "unsafe" +) + +// Maybe is an interface that represents an optional value of type T. +// +// Maybe is a drop-in replacement for the Maybe type defined in avalanchego/utils/maybe. +// This interface is used to avoid importing avalanchego packages into the ffi +// package, which would create a circular dependency. +// +// +// +// The avalanchego implementation of Maybe implements this interface. +type Maybe[T any] interface { + // HasValue returns true if the Maybe contains a value. + HasValue() bool + // Value returns the value contained in the Maybe. + // + // Implementations may panic if the Maybe contains no value but can also + // return the zero value of T. + Value() T +} + +func newMaybeBorrowedBytes(maybe Maybe[[]byte], pinner Pinner) C.Maybe_BorrowedBytes { + var cMaybe C.Maybe_BorrowedBytes + + if maybe != nil && maybe.HasValue() { + cMaybeBorrowedBytesPtr := (*C.BorrowedBytes)(unsafe.Pointer(&cMaybe.anon0)) + *cMaybeBorrowedBytesPtr = newBorrowedBytes(maybe.Value(), pinner) + + cMaybe.tag = C.Maybe_BorrowedBytes_Some_BorrowedBytes + } else { + cMaybe.tag = C.Maybe_BorrowedBytes_None_BorrowedBytes + } + + return cMaybe +} + +func (b *ownedBytes) HasValue() bool { + return b != nil +} + +func (b *ownedBytes) Value() *ownedBytes { + return b +} diff --git a/firewood/ffi/memory.go b/firewood/ffi/memory.go new file mode 100644 index 000000000000..bfc6d2493002 --- /dev/null +++ b/firewood/ffi/memory.go @@ -0,0 +1,464 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +// // Note that -lm is required on Linux but not on Mac. +// #include +// #include "firewood.h" +import "C" + +import ( + "errors" + "fmt" + "unsafe" +) + +var ( + errKeysAndValues = errors.New("keys and values must have the same length") + errFreeingValue = errors.New("unexpected error while freeing value") +) + +type Pinner interface { + Pin(ptr any) + Unpin() +} + +// Borrower is an interface for types that can borrow or copy bytes returned +// from FFI methods. +type Borrower interface { + // BorrowedBytes returns a slice of bytes that borrows the data from the + // Borrower's internal memory. + // + // The returned slice is valid only as long as the Borrower is valid. + // If the Borrower is freed, the slice will become invalid. + BorrowedBytes() []byte + + // CopiedBytes returns a slice of bytes that is a copy of the Borrower's + // internal memory. + // + // This is fully independent of the borrowed data and is valid even after + // the Borrower is freed. + CopiedBytes() []byte + + // Free releases the memory associated with the Borrower's data. + // + // It is safe to call this method multiple times. Subsequent calls will + // do nothing if the data has already been freed (or was never set). + // + // However, it is not safe to call this method concurrently from multiple + // goroutines. It is also not safe to call this method while there are + // outstanding references to the slice returned by BorrowedBytes. Any + // existing slices will become invalid and may cause undefined behavior + // if used after the Free call. + Free() error +} + +var _ Borrower = (*ownedBytes)(nil) + +// newBorrowedBytes creates a new BorrowedBytes from a Go byte slice. +// +// Provide a Pinner to ensure the memory is pinned while the BorrowedBytes is in use. +func newBorrowedBytes(slice []byte, pinner Pinner) C.BorrowedBytes { + // Get the pointer first to distinguish between nil slice and empty slice + ptr := unsafe.SliceData(slice) + sliceLen := len(slice) + + // If ptr is nil (which means the slice itself is nil), return nil pointer + if ptr == nil { + return C.BorrowedBytes{ptr: nil, len: 0} + } + + // For non-nil slices (including empty slices like []byte{}), + // pin the pointer if the slice has data + if sliceLen > 0 { + pinner.Pin(ptr) + } + + return C.BorrowedBytes{ + ptr: (*C.uint8_t)(ptr), + len: C.size_t(sliceLen), + } +} + +// newKeyValuePair creates a new KeyValuePair from Go byte slices for key and value. +// +// Provide a Pinner to ensure the memory is pinned while the KeyValuePair is in use. +func newKeyValuePair(key, value []byte, pinner Pinner) C.KeyValuePair { + return C.KeyValuePair{ + key: newBorrowedBytes(key, pinner), + value: newBorrowedBytes(value, pinner), + } +} + +// newBorrowedKeyValuePairs creates a new BorrowedKeyValuePairs from a slice of KeyValuePair. +// +// Provide a Pinner to ensure the memory is pinned while the BorrowedKeyValuePairs is +// in use. +func newBorrowedKeyValuePairs(pairs []C.KeyValuePair, pinner Pinner) C.BorrowedKeyValuePairs { + sliceLen := len(pairs) + if sliceLen == 0 { + return C.BorrowedKeyValuePairs{ptr: nil, len: 0} + } + + ptr := unsafe.SliceData(pairs) + if ptr == nil { + return C.BorrowedKeyValuePairs{ptr: nil, len: 0} + } + + pinner.Pin(ptr) + + return C.BorrowedKeyValuePairs{ + ptr: ptr, + len: C.size_t(sliceLen), + } +} + +// newKeyValuePairs creates a new BorrowedKeyValuePairs from slices of keys and values. +// +// The keys and values must have the same length. +// +// Provide a Pinner to ensure the memory is pinned while the BorrowedKeyValuePairs is +// in use. +func newKeyValuePairs(keys, vals [][]byte, pinner Pinner) (C.BorrowedKeyValuePairs, error) { + if len(keys) != len(vals) { + return C.BorrowedKeyValuePairs{}, fmt.Errorf("%w: %d != %d", errKeysAndValues, len(keys), len(vals)) + } + + pairs := make([]C.KeyValuePair, len(keys)) + for i := range keys { + pairs[i] = newKeyValuePair(keys[i], vals[i], pinner) + } + + return newBorrowedKeyValuePairs(pairs, pinner), nil +} + +// ownedBytes is a wrapper around C.OwnedBytes that provides a Go interface +// for Rust-owned byte slices. +// +// ownedBytes implements the [Borrower] interface allowing it to be shared +// outside of the FFI package without exposing the C types directly or any FFI +// implementation details. +type ownedBytes struct { + owned C.OwnedBytes +} + +// Free releases the memory associated with the Borrower's data. +// +// It is safe to call this method multiple times. Subsequent calls will +// do nothing if the data has already been freed (or was never set). +// +// However, it is not safe to call this method concurrently from multiple +// goroutines. It is also not safe to call this method while there are +// outstanding references to the slice returned by BorrowedBytes. Any +// existing slices will become invalid and may cause undefined behavior +// if used after the Free call. +func (b *ownedBytes) Free() error { + if b.owned.ptr == nil { + // Already freed (or never set), nothing to do. + return nil + } + + if err := getErrorFromVoidResult(C.fwd_free_owned_bytes(b.owned)); err != nil { + return fmt.Errorf("%w: %w", errFreeingValue, err) + } + + b.owned = C.OwnedBytes{} + + return nil +} + +// BorrowedBytes returns the underlying byte slice. It may return nil if the +// data has already been freed was never set. +// +// The returned slice is valid only as long as the ownedBytes is valid. +// +// It does not copy the data; however, the slice is valid only as long as the +// ownedBytes is valid. If the ownedBytes is freed, the slice will +// become invalid. +// +// It is safe to cast the returned slice as a string so long as the ownedBytes +// is not freed while the string is in use. +// +// BorrowedBytes is part of the [Borrower] interface. +func (b *ownedBytes) BorrowedBytes() []byte { + if b.owned.ptr == nil { + return nil + } + + return unsafe.Slice((*byte)(b.owned.ptr), b.owned.len) +} + +// CopiedBytes returns a copy of the underlying byte slice. It may return nil if the +// data has already been freed or was never set. +// +// The returned slice is a copy of the data and is valid independently of the +// ownedBytes. It is safe to use after the ownedBytes is freed and will +// be freed by the Go garbage collector. +// +// CopiedBytes is part of the [Borrower] interface. +func (b *ownedBytes) CopiedBytes() []byte { + if b.owned.ptr == nil { + return nil + } + + return C.GoBytes(unsafe.Pointer(b.owned.ptr), C.int(b.owned.len)) +} + +// intoError converts the ownedBytes into an error. This is used for methods +// that return a ownedBytes as an error type. +// +// If the ownedBytes is nil or has already been freed, it returns nil. +// Otherwise, the bytes will be copied into Go memory and converted into an +// error. +// +// The original ownedBytes will be freed after this operation and is no longer +// valid. +func (b *ownedBytes) intoError() error { + if b.owned.ptr == nil { + return nil + } + + err := errors.New(string(b.CopiedBytes())) + + if err2 := b.Free(); err2 != nil { + return fmt.Errorf("%w: %w (original error: %w)", errFreeingValue, err, err2) + } + + return err +} + +// newOwnedBytes creates a ownedBytes from a C.OwnedBytes. +// +// The caller is responsible for calling Free() on the returned ownedBytes +// when it is no longer needed otherwise memory will leak. +// +// It is not an error to provide an OwnedBytes with a nil pointer or zero length +// in which case the returned ownedBytes will be empty. +func newOwnedBytes(owned C.OwnedBytes) *ownedBytes { + return &ownedBytes{owned: owned} +} + +// getHashKeyFromHashResult creates a byte slice or error from a C.HashResult. +// +// It returns nil, nil if the result is None. +// It returns nil, err if the result is an error. +// It returns a byte slice, nil if the result is Some. +func getHashKeyFromHashResult(result C.HashResult) (Hash, error) { + switch result.tag { + case C.HashResult_NullHandlePointer: + return EmptyRoot, errDBClosed + case C.HashResult_None: + return EmptyRoot, nil + case C.HashResult_Some: + cHashKey := (*C.HashKey)(unsafe.Pointer(&result.anon0)) + hashKey := *(*Hash)(unsafe.Pointer(&cHashKey._0)) + return hashKey, nil + case C.HashResult_Err: + ownedBytes := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))) + return EmptyRoot, ownedBytes.intoError() + default: + return EmptyRoot, fmt.Errorf("unknown C.HashResult tag: %d", result.tag) + } +} + +// getErrorgetErrorFromVoidResult converts a C.VoidResult to an error. +// +// It will return nil if the result is Ok, otherwise it returns an error. +func getErrorFromVoidResult(result C.VoidResult) error { + switch result.tag { + case C.VoidResult_NullHandlePointer: + return errDBClosed + case C.VoidResult_Ok: + return nil + case C.VoidResult_Err: + return newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + default: + return fmt.Errorf("unknown C.VoidResult tag: %d", result.tag) + } +} + +// getValueFromValueResult converts a C.ValueResult to a byte slice or error. +// +// It returns nil, nil if the result is None. +// It returns nil, errRevisionNotFound if the result is RevisionNotFound. +// It returns a byte slice, nil if the result is Some. +// It returns an error if the result is an error. +func getValueFromValueResult(result C.ValueResult) ([]byte, error) { + switch result.tag { + case C.ValueResult_NullHandlePointer: + return nil, errDBClosed + case C.ValueResult_RevisionNotFound: + // NOTE: the result value contains the provided root hash, we could use + // it in the error message if needed. + return nil, errRevisionNotFound + case C.ValueResult_None: + return nil, nil + case C.ValueResult_Some: + ownedBytes := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))) + bytes := ownedBytes.CopiedBytes() + if err := ownedBytes.Free(); err != nil { + return nil, fmt.Errorf("%w: %w", errFreeingValue, err) + } + return bytes, nil + case C.ValueResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.ValueResult tag: %d", result.tag) + } +} + +type ownedKeyValueBatch struct { + owned C.OwnedKeyValueBatch +} + +func (b *ownedKeyValueBatch) copy() []*ownedKeyValue { + if b.owned.ptr == nil { + return nil + } + borrowed := b.borrow() + copied := make([]*ownedKeyValue, len(borrowed)) + for i, borrow := range borrowed { + copied[i] = newOwnedKeyValue(borrow) + } + return copied +} + +func (b *ownedKeyValueBatch) borrow() []C.OwnedKeyValuePair { + if b.owned.ptr == nil { + return nil + } + + return unsafe.Slice((*C.OwnedKeyValuePair)(unsafe.Pointer(b.owned.ptr)), b.owned.len) +} + +func (b *ownedKeyValueBatch) free() error { + if b == nil || b.owned.ptr == nil { + // we want ownedKeyValueBatch to be typed-nil safe + return nil + } + + if err := getErrorFromVoidResult(C.fwd_free_owned_key_value_batch(b.owned)); err != nil { + return fmt.Errorf("%w: %w", errFreeingValue, err) + } + + b.owned = C.OwnedKeyValueBatch{} + + return nil +} + +// newOwnedKeyValueBatch creates a ownedKeyValueBatch from a C.OwnedKeyValueBatch. +// +// The caller is responsible for calling Free() on the returned ownedKeyValue +// when it is no longer needed otherwise memory will leak. +func newOwnedKeyValueBatch(owned C.OwnedKeyValueBatch) *ownedKeyValueBatch { + return &ownedKeyValueBatch{ + owned: owned, + } +} + +type ownedKeyValue struct { + // owned holds the original C-provided pair so we can free it + // with fwd_free_owned_kv_pair instead of freeing key/value separately. + owned C.OwnedKeyValuePair + // key and value wrappers provide Borrowed/Copied accessors + key *ownedBytes + value *ownedBytes +} + +func (kv *ownedKeyValue) copy() ([]byte, []byte) { + key := kv.key.CopiedBytes() + value := kv.value.CopiedBytes() + return key, value +} + +func (kv *ownedKeyValue) free() error { + if kv == nil { + // we want ownedKeyValue to be typed-nil safe + return nil + } + if err := getErrorFromVoidResult(C.fwd_free_owned_kv_pair(kv.owned)); err != nil { + return fmt.Errorf("%w: %w", errFreeingValue, err) + } + // zero out fields to avoid accidental reuse/double free + kv.owned = C.OwnedKeyValuePair{} + kv.key = nil + kv.value = nil + return nil +} + +// newOwnedKeyValue creates a ownedKeyValue from a C.OwnedKeyValuePair. +// +// The caller is responsible for calling Free() on the returned ownedKeyValue +// when it is no longer needed otherwise memory will leak. +func newOwnedKeyValue(owned C.OwnedKeyValuePair) *ownedKeyValue { + return &ownedKeyValue{ + owned: owned, + key: newOwnedBytes(owned.key), + value: newOwnedBytes(owned.value), + } +} + +// getKeyValueFromResult converts a C.KeyValueResult to a key value pair or error. +// +// It returns nil, nil if the result is None. +// It returns a *ownedKeyValue, nil if the result is Some. +// It returns an error if the result is an error. +func getKeyValueFromResult(result C.KeyValueResult) (*ownedKeyValue, error) { + switch result.tag { + case C.KeyValueResult_NullHandlePointer: + return nil, errDBClosed + case C.KeyValueResult_None: + return nil, nil + case C.KeyValueResult_Some: + ownedKvp := newOwnedKeyValue(*(*C.OwnedKeyValuePair)(unsafe.Pointer(&result.anon0))) + return ownedKvp, nil + case C.KeyValueResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.KeyValueResult tag: %d", result.tag) + } +} + +// getKeyValueBatchFromResult converts a C.KeyValueBatchResult to a key value batch or error. +// +// It returns nil, nil if the result is None. +// It returns a *ownedKeyValueBatch, nil if the result is Some. +// It returns an error if the result is an error. +func getKeyValueBatchFromResult(result C.KeyValueBatchResult) (*ownedKeyValueBatch, error) { + switch result.tag { + case C.KeyValueBatchResult_NullHandlePointer: + return nil, errDBClosed + case C.KeyValueBatchResult_Some: + ownedBatch := newOwnedKeyValueBatch(*(*C.OwnedKeyValueBatch)(unsafe.Pointer(&result.anon0))) + return ownedBatch, nil + case C.KeyValueBatchResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.KeyValueBatchResult tag: %d", result.tag) + } +} + +// getDatabaseFromHandleResult converts a C.HandleResult to a Database or error. +// +// If the C.HandleResult is an error, it returns an error instead of a Database. +func getDatabaseFromHandleResult(result C.HandleResult) (*Database, error) { + switch result.tag { + case C.HandleResult_Ok: + ptr := *(**C.DatabaseHandle)(unsafe.Pointer(&result.anon0)) + db := &Database{handle: ptr} + return db, nil + case C.HandleResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.HandleResult tag: %d", result.tag) + } +} + +func newCHashKey(hash Hash) C.HashKey { + return *(*C.HashKey)(unsafe.Pointer(&hash)) +} diff --git a/firewood/ffi/metrics.go b/firewood/ffi/metrics.go new file mode 100644 index 000000000000..e50ae69b5833 --- /dev/null +++ b/firewood/ffi/metrics.go @@ -0,0 +1,96 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +//go:generate go run generate_cgo.go + +// #include +// #include "firewood.h" +import "C" + +import ( + "runtime" + "strings" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/common/expfmt" + + dto "github.com/prometheus/client_model/go" +) + +var _ prometheus.Gatherer = (*Gatherer)(nil) + +type Gatherer struct{} + +func (Gatherer) Gather() ([]*dto.MetricFamily, error) { + metrics, err := GatherMetrics() + if err != nil { + return nil, err + } + + reader := strings.NewReader(metrics) + + var parser expfmt.TextParser + parsedMetrics, err := parser.TextToMetricFamilies(reader) + if err != nil { + return nil, err + } + + lst := make([]*dto.MetricFamily, 0, len(parsedMetrics)) + for _, v := range parsedMetrics { + lst = append(lst, v) + } + + return lst, nil +} + +// Starts global recorder for metrics. +// This function only needs to be called once. +// An error is returned if this method is called a second time, or if it is +// called after StartMetricsWithExporter. +// This is best used in conjunction with the [Gatherer] type to collect metrics. +func StartMetrics() error { + return getErrorFromVoidResult(C.fwd_start_metrics()) +} + +// Start global recorder for metrics along with an HTTP exporter. +// This function only needs to be called once. +// An error is returned if this method is called a second time, if it is +// called after StartMetrics, or if the exporter failed to start. +func StartMetricsWithExporter(metricsPort uint16) error { + return getErrorFromVoidResult(C.fwd_start_metrics_with_exporter(C.uint16_t(metricsPort))) +} + +// Collect metrics from global recorder +// Returns an error if the global recorder is not initialized. +// This method must be called after StartMetrics or StartMetricsWithExporter +func GatherMetrics() (string, error) { + bytes, err := getValueFromValueResult(C.fwd_gather()) + if err != nil { + return "", err + } + + return string(bytes), nil +} + +// LogConfig configures logs for this process. +type LogConfig struct { + Path string + FilterLevel string +} + +// Starts global logs. +// This function only needs to be called once. +// An error is returned if this method is called a second time. +func StartLogs(config *LogConfig) error { + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.struct_LogArgs{ + path: newBorrowedBytes([]byte(config.Path), &pinner), + filter_level: newBorrowedBytes([]byte(config.FilterLevel), &pinner), + } + + return getErrorFromVoidResult(C.fwd_start_logs(args)) +} diff --git a/firewood/ffi/metrics_test.go b/firewood/ffi/metrics_test.go new file mode 100644 index 000000000000..b588ee2d4adc --- /dev/null +++ b/firewood/ffi/metrics_test.go @@ -0,0 +1,103 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +import ( + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "testing" + "time" + + "github.com/stretchr/testify/require" + + dto "github.com/prometheus/client_model/go" +) + +// Test calling metrics exporter along with gathering metrics +// This lives under one test as we can only instantiate the global recorder once +func TestMetrics(t *testing.T) { + r := require.New(t) + ctx := t.Context() + + // test params + var ( + logPath = filepath.Join(t.TempDir(), "firewood.log") + metricsPort = uint16(3000) + ) + + db := newTestDatabase(t) + r.NoError(StartMetricsWithExporter(metricsPort)) + + logConfig := &LogConfig{ + Path: logPath, + FilterLevel: "trace", + } + + var logsDisabled bool + if err := StartLogs(logConfig); err != nil { + r.Contains(err.Error(), "Logging is not available") + logsDisabled = true + } + + // Populate DB + keys, vals := kvForTest(10) + _, err := db.Update(keys, vals) + r.NoError(err) + + req, err := http.NewRequestWithContext( + ctx, + http.MethodGet, + fmt.Sprintf("http://localhost:%d", metricsPort), + nil, + ) + r.NoError(err) + + client := &http.Client{Timeout: 10 * time.Second} + resp, err := client.Do(req) + r.NoError(err) + + body, err := io.ReadAll(resp.Body) + r.NoError(err) + r.NoError(resp.Body.Close()) + + // Check that batch op was recorded + r.Contains(string(body), "firewood_ffi_batch 1") + + g := Gatherer{} + metricsFamily, err := g.Gather() + r.NoError(err) + + expectedMetrics := map[string]dto.MetricType{ + "firewood_ffi_batch": dto.MetricType_COUNTER, + "firewood_proposal_commit": dto.MetricType_COUNTER, + "firewood_proposal_commit_ms": dto.MetricType_COUNTER, + "firewood_ffi_propose_ms": dto.MetricType_COUNTER, + "firewood_ffi_commit_ms": dto.MetricType_COUNTER, + "firewood_ffi_batch_ms": dto.MetricType_COUNTER, + "firewood_flush_nodes": dto.MetricType_COUNTER, + "firewood_insert": dto.MetricType_COUNTER, + "firewood_space_from_end": dto.MetricType_COUNTER, + } + + for k, v := range expectedMetrics { + var d *dto.MetricFamily + for _, m := range metricsFamily { + if *m.Name == k { + d = m + } + } + r.NotNil(d) + r.Equal(v, *d.Type) + } + + if !logsDisabled { + // logs should be non-empty if logging with trace filter level + f, err := os.ReadFile(logPath) + r.NoError(err) + r.NotEmpty(f) + } +} diff --git a/firewood/ffi/proofs.go b/firewood/ffi/proofs.go new file mode 100644 index 000000000000..56883928b17b --- /dev/null +++ b/firewood/ffi/proofs.go @@ -0,0 +1,489 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +// #include +// #include "firewood.h" +import "C" + +import ( + "encoding" + "errors" + "fmt" + "runtime" + "unsafe" +) + +var ( + errNotPrepared = errors.New("proof not prepared into a proposal or committed") + errEmptyTrie = errors.New("a range proof was requested on an empty trie") +) + +var ( + _ encoding.BinaryMarshaler = (*RangeProof)(nil) + _ encoding.BinaryUnmarshaler = (*RangeProof)(nil) +) + +// RangeProof represents a proof that a range of keys and their values are +// included in a trie with a given root hash. +// +// RangeProofs can be created via [Database.RangeProof] and are marshallable via +// [encoding.BinaryMarshaler] and [encoding.BinaryUnmarshaler]. They can be +// verified independent of a database via [RangeProof.Verify] or with a database +// via [Database.VerifyRangeProof]. Verified range proofs can be committed to a +// database via [Database.VerifyAndCommitRangeProof] (where verification will +// be skipped if it was already verified). Verifying a range proof with a +// database will optimistically prepare a proposal that can be committed later. +type RangeProof struct { + // handle is an opaque pointer to the range proof within Firewood. It should be + // passed to the C FFI functions that operate on range proofs + // + // It is not safe to call these methods with a nil handle. + // + // Calls to `C.fwd_free_range_proof` will invalidate this handle, so it + // should not be used after those calls. + // + // Calls to `C.fwd_db_verify_range_proof` will cause the range proof to + // build and retain ownership of an embedded proposal, which also retains + // a reference to the database. Therefore, while the range proof owns an + // embedded proposal, the database must be kept alive. The proposal and + // reference to the database are released after calling + // `C.fwd_db_verify_and_commit_range_proof` or `C.fwd_free_range_proof`. + handle *C.RangeProofContext + + // keepAliveHandle keeps the database alive while this range proof + // owns an embedded proposal. It is initialized when the range proof is + // verified with a database handle ([Database.VerifyRangeProof]) and not by + // unmarshalling or when [RangeProof.Verify] is used. It is disowned after + // [Database.VerifyAndCommitRangeProof] or [RangeProof.Free]. + keepAliveHandle databaseKeepAliveHandle +} + +// ChangeProof represents a proof of changes between two roots for a range of keys. +type ChangeProof struct { + handle *C.ChangeProofContext +} + +// NextKeyRange represents a range of keys to fetch from the database. The start +// key is inclusive while the end key is exclusive. If the end key is Nothing, +// the range is unbounded in that direction. +type NextKeyRange struct { + startKey *ownedBytes + endKey Maybe[*ownedBytes] +} + +// RangeProof returns a proof that the values in the range [startKey, endKey] are +// included in the tree with the current root. The proof may be truncated to at +// most [maxLength] entries, if non-zero. If either [startKey] or [endKey] is +// Nothing, the range is unbounded in that direction. If [rootHash] is Nothing, the +// current root of the database is used. +func (db *Database) RangeProof( + rootHash Hash, + startKey, endKey Maybe[[]byte], + maxLength uint32, +) (*RangeProof, error) { + if db.handle == nil { + return nil, errDBClosed + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.CreateRangeProofArgs{ + root: newCHashKey(rootHash), + start_key: newMaybeBorrowedBytes(startKey, &pinner), + end_key: newMaybeBorrowedBytes(endKey, &pinner), + max_length: C.uint32_t(maxLength), + } + + return getRangeProofFromRangeProofResult(C.fwd_db_range_proof(db.handle, args)) +} + +// Verify verifies the provided range [proof] proves the values in the range +// [startKey, endKey] are included in the tree with the given [rootHash]. If the +// proof is valid, nil is returned; otherwise an error describing why the proof is +// invalid is returned. +func (p *RangeProof) Verify( + rootHash Hash, + startKey, endKey Maybe[[]byte], + maxLength uint32, +) error { + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.VerifyRangeProofArgs{ + proof: p.handle, + root: newCHashKey(rootHash), + start_key: newMaybeBorrowedBytes(startKey, &pinner), + end_key: newMaybeBorrowedBytes(endKey, &pinner), + max_length: C.uint32_t(maxLength), + } + + return getErrorFromVoidResult(C.fwd_range_proof_verify(args)) +} + +// VerifyChangeProof verifies the provided change [proof] proves the changes +// between [startRoot] and [endRoot] for keys in the range [startKey, endKey]. If +// the proof is valid, a proposal containing the changes is prepared. The +// call to [*Database.VerifyAndCommitRangeProof] will skip verification and commit the +// prepared proposal. +// +// Because this method prepares a proposal, the database must be kept alive +// until the proof is committed or freed. +func (db *Database) VerifyRangeProof( + proof *RangeProof, + startKey, endKey Maybe[[]byte], + rootHash Hash, + maxLength uint32, +) error { + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.VerifyRangeProofArgs{ + proof: proof.handle, + root: newCHashKey(rootHash), + start_key: newMaybeBorrowedBytes(startKey, &pinner), + end_key: newMaybeBorrowedBytes(endKey, &pinner), + max_length: C.uint32_t(maxLength), + } + + if err := getErrorFromVoidResult(C.fwd_db_verify_range_proof(db.handle, args)); err != nil { + return err + } + + // keep the database alive while the proof owns the embedded proposal + proof.keepAliveHandle.init(&db.outstandingHandles) + runtime.SetFinalizer(proof, (*RangeProof).Free) + return nil +} + +// VerifyAndCommitRangeProof verifies the provided range [proof] proves the values +// in the range [startKey, endKey] are included in the tree with the given +// [rootHash]. If the proof is valid, it is committed to the database and the +// new root hash is returned. The resulting root hash may not equal the +// provided root hash if the proof was truncated due to [maxLength]. +func (db *Database) VerifyAndCommitRangeProof( + proof *RangeProof, + startKey, endKey Maybe[[]byte], + rootHash Hash, + maxLength uint32, +) (Hash, error) { + if db.handle == nil { + return EmptyRoot, errDBClosed + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.VerifyRangeProofArgs{ + proof: proof.handle, + root: newCHashKey(rootHash), + start_key: newMaybeBorrowedBytes(startKey, &pinner), + end_key: newMaybeBorrowedBytes(endKey, &pinner), + max_length: C.uint32_t(maxLength), + } + + var hash Hash + err := proof.keepAliveHandle.disown(true /* evenOnError */, func() error { + var err error + hash, err = getHashKeyFromHashResult(C.fwd_db_verify_and_commit_range_proof(db.handle, args)) + return err + }) + return hash, err +} + +// FindNextKey returns the next key range to fetch for this proof, if any. If the +// proof has been fully processed, nil is returned. If an error occurs while +// determining the next key range, that error is returned. +// +// FindNextKey can only be called after a successful call to [*Database.VerifyRangeProof] or +// [*Database.VerifyAndCommitRangeProof]. +func (p *RangeProof) FindNextKey() (*NextKeyRange, error) { + return getNextKeyRangeFromNextKeyRangeResult(C.fwd_range_proof_find_next_key(p.handle)) +} + +// MarshalBinary returns a serialized representation of this RangeProof. +// +// The format is unspecified and opaque to firewood. +func (p *RangeProof) MarshalBinary() ([]byte, error) { + return getValueFromValueResult(C.fwd_range_proof_to_bytes(p.handle)) +} + +// UnmarshalBinary sets the contents of this RangeProof to be the deserialized +// form of [data] overwriting any existing contents. +func (p *RangeProof) UnmarshalBinary(data []byte) error { + if err := p.Free(); err != nil { + return err + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + handle, err := getRangeProofFromRangeProofResult( + C.fwd_range_proof_from_bytes(newBorrowedBytes(data, &pinner))) + + if err == nil { + p.handle = handle.handle + handle.handle = nil + } + + return err +} + +// Free releases the resources associated with this RangeProof. +// +// It is safe to call Free more than once; subsequent calls after the first +// will be no-ops. +func (p *RangeProof) Free() error { + return p.keepAliveHandle.disown(false /* evenOnError */, func() error { + if p.handle == nil { + return nil + } + + if err := getErrorFromVoidResult(C.fwd_free_range_proof(p.handle)); err != nil { + return err + } + + p.handle = nil + return nil + }) +} + +// ChangeProof returns a proof that the changes between [startRoot] and +// [endRoot] for keys in the range [startKey, endKey]. The proof may be +// truncated to at most [maxLength] entries, if non-zero. If either [startKey] or +// [endKey] is Nothing, the range is unbounded in that direction. +func (db *Database) ChangeProof( + startRoot, endRoot Hash, + startKey, endKey Maybe[[]byte], + maxLength uint32, +) (*ChangeProof, error) { + if db.handle == nil { + return nil, errDBClosed + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.CreateChangeProofArgs{ + start_root: newCHashKey(startRoot), + end_root: newCHashKey(endRoot), + start_key: newMaybeBorrowedBytes(startKey, &pinner), + end_key: newMaybeBorrowedBytes(endKey, &pinner), + max_length: C.uint32_t(maxLength), + } + + return getChangeProofFromChangeProofResult(C.fwd_db_change_proof(db.handle, args)) +} + +// VerifyChangeProof verifies the provided change [proof] proves the changes +// between [startRoot] and [endRoot] for keys in the range [startKey, endKey]. If +// the proof is valid, a proposal containing the changes is prepared. The call +// to [*Database.VerifyAndCommitChangeProof] will skip verification and commit the +// prepared proposal. +func (db *Database) VerifyChangeProof( + proof *ChangeProof, + startRoot, endRoot Hash, + startKey, endKey Maybe[[]byte], + maxLength uint32, +) error { + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.VerifyChangeProofArgs{ + proof: proof.handle, + start_root: newCHashKey(startRoot), + end_root: newCHashKey(endRoot), + start_key: newMaybeBorrowedBytes(startKey, &pinner), + end_key: newMaybeBorrowedBytes(endKey, &pinner), + max_length: C.uint32_t(maxLength), + } + + return getErrorFromVoidResult(C.fwd_db_verify_change_proof(db.handle, args)) +} + +// VerifyAndCommitChangeProof verifies the provided change [proof] proves the changes +// between [startRoot] and [endRoot] for keys in the range [startKey, endKey]. If +// the proof is valid, it is committed to the database and the new root hash is +// returned. The resulting root hash may not equal the end root if the proof was +// truncated due to [maxLength]. +func (db *Database) VerifyAndCommitChangeProof( + proof *ChangeProof, + startRoot, endRoot Hash, + startKey, endKey Maybe[[]byte], + maxLength uint32, +) (Hash, error) { + if db.handle == nil { + return EmptyRoot, errDBClosed + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + args := C.VerifyChangeProofArgs{ + proof: proof.handle, + start_root: newCHashKey(startRoot), + end_root: newCHashKey(endRoot), + start_key: newMaybeBorrowedBytes(startKey, &pinner), + end_key: newMaybeBorrowedBytes(endKey, &pinner), + max_length: C.uint32_t(maxLength), + } + + return getHashKeyFromHashResult(C.fwd_db_verify_and_commit_change_proof(db.handle, args)) +} + +// FindNextKey returns the next key range to fetch for this proof, if any. If the +// proof has been fully processed, nil is returned. If an error occurs while +// determining the next key range, that error is returned. +// +// FindNextKey can only be called after a successful call to [*Database.VerifyChangeProof] or +// [*Database.VerifyAndCommitChangeProof]. +func (p *ChangeProof) FindNextKey() (*NextKeyRange, error) { + return getNextKeyRangeFromNextKeyRangeResult(C.fwd_change_proof_find_next_key(p.handle)) +} + +// MarshalBinary returns a serialized representation of this ChangeProof. +// +// The format is unspecified and opaque to firewood. +func (p *ChangeProof) MarshalBinary() ([]byte, error) { + return getValueFromValueResult(C.fwd_change_proof_to_bytes(p.handle)) +} + +// UnmarshalBinary sets the contents of this ChangeProof to be the deserialized +// form of [data] overwriting any existing contents. +func (p *ChangeProof) UnmarshalBinary(data []byte) error { + if err := p.Free(); err != nil { + return err + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + handle, err := getChangeProofFromChangeProofResult( + C.fwd_change_proof_from_bytes(newBorrowedBytes(data, &pinner))) + + if err == nil { + p.handle = handle.handle + handle.handle = nil + } + + return err +} + +// Free releases the resources associated with this ChangeProof. +// +// It is safe to call Free more than once; subsequent calls after the first +// will be no-ops. +func (p *ChangeProof) Free() error { + if p.handle == nil { + return nil + } + + if err := getErrorFromVoidResult(C.fwd_free_change_proof(p.handle)); err != nil { + return err + } + + p.handle = nil + + return nil +} + +// StartKey returns the inclusive start key of this key range. +func (r *NextKeyRange) StartKey() []byte { + return r.startKey.BorrowedBytes() +} + +// HasEndKey returns true if this key range has an exclusive end key. +func (r *NextKeyRange) HasEndKey() bool { + return r.endKey.HasValue() +} + +// EndKey returns the exclusive end key of this key range if it exists or nil if +// it does not. +func (r *NextKeyRange) EndKey() []byte { + if r.endKey.HasValue() { + return r.endKey.Value().BorrowedBytes() + } + return nil +} + +// Free releases the resources associated with this NextKeyRange. +// +// It is safe to call Free more than once; subsequent calls after the first +// will be no-ops. +func (r *NextKeyRange) Free() error { + var err1, err2 error + + err1 = r.startKey.Free() + if r.endKey != nil && r.endKey.HasValue() { + err2 = r.endKey.Value().Free() + } + + return errors.Join(err1, err2) +} + +func newNextKeyRange(cRange C.NextKeyRange) *NextKeyRange { + var nextKeyRange NextKeyRange + + nextKeyRange.startKey = newOwnedBytes(cRange.start_key) + + if cRange.end_key.tag == C.Maybe_OwnedBytes_Some_OwnedBytes { + nextKeyRange.endKey = newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&cRange.end_key.anon0))) + } + + return &nextKeyRange +} + +func getNextKeyRangeFromNextKeyRangeResult(result C.NextKeyRangeResult) (*NextKeyRange, error) { + switch result.tag { + case C.NextKeyRangeResult_NullHandlePointer: + return nil, errDBClosed + case C.NextKeyRangeResult_NotPrepared: + return nil, errNotPrepared + case C.NextKeyRangeResult_None: + return nil, nil + case C.NextKeyRangeResult_Some: + return newNextKeyRange(*(*C.NextKeyRange)(unsafe.Pointer(&result.anon0))), nil + case C.NextKeyRangeResult_Err: + return nil, newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + default: + return nil, fmt.Errorf("unknown C.NextKeyRangeResult tag: %d", result.tag) + } +} + +func getRangeProofFromRangeProofResult(result C.RangeProofResult) (*RangeProof, error) { + switch result.tag { + case C.RangeProofResult_NullHandlePointer: + return nil, errDBClosed + case C.RangeProofResult_RevisionNotFound: + // NOTE: the result value contains the provided root hash, we could use + // it in the error message if needed. + return nil, errRevisionNotFound + case C.RangeProofResult_EmptyTrie: + return nil, errEmptyTrie + case C.RangeProofResult_Ok: + ptr := *(**C.RangeProofContext)(unsafe.Pointer(&result.anon0)) + return &RangeProof{handle: ptr}, nil + case C.RangeProofResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.RangeProofResult tag: %d", result.tag) + } +} + +func getChangeProofFromChangeProofResult(result C.ChangeProofResult) (*ChangeProof, error) { + switch result.tag { + case C.ChangeProofResult_NullHandlePointer: + return nil, errDBClosed + case C.ChangeProofResult_Ok: + ptr := *(**C.ChangeProofContext)(unsafe.Pointer(&result.anon0)) + return &ChangeProof{handle: ptr}, nil + case C.ChangeProofResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.ChangeProofResult tag: %d", result.tag) + } +} diff --git a/firewood/ffi/proofs_test.go b/firewood/ffi/proofs_test.go new file mode 100644 index 000000000000..a0cb9d36d7da --- /dev/null +++ b/firewood/ffi/proofs_test.go @@ -0,0 +1,353 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +import ( + "runtime" + "testing" + + "github.com/stretchr/testify/require" +) + +const ( + rangeProofLenUnbounded = 0 + rangeProofLenTruncated = 10 +) + +type maybe struct { + value []byte + hasValue bool +} + +func (m maybe) HasValue() bool { + return m.hasValue +} + +func (m maybe) Value() []byte { + return m.value +} + +func something(b []byte) maybe { + return maybe{ + hasValue: true, + value: b, + } +} + +func nothing() maybe { + return maybe{ + hasValue: false, + } +} + +// assertProofNotNil verifies that the given proof and its inner handle are not nil. +func assertProofNotNil(t *testing.T, proof *RangeProof) { + t.Helper() + r := require.New(t) + r.NotNil(proof) + r.NotNil(proof.handle) +} + +// newVerifiedRangeProof generates a range proof for the given parameters and +// verifies using [RangeProof.Verify] which does not prepare a proposal. A +// cleanup is registered to free the proof when the test ends. +func newVerifiedRangeProof( + t *testing.T, + db *Database, + root Hash, + startKey, endKey maybe, + proofLen uint32, +) *RangeProof { + r := require.New(t) + + proof, err := db.RangeProof(root, startKey, endKey, proofLen) + r.NoError(err) + assertProofNotNil(t, proof) + t.Cleanup(func() { r.NoError(proof.Free()) }) + + r.NoError(proof.Verify(root, startKey, endKey, proofLen)) + + return proof +} + +// newSerializedRangeProof generates a range proof for the given parameters and +// returns its serialized bytes. +func newSerializedRangeProof( + t *testing.T, + db *Database, + root Hash, + startKey, endKey maybe, + proofLen uint32, +) []byte { + r := require.New(t) + + proof := newVerifiedRangeProof(t, db, root, startKey, endKey, proofLen) + + proofBytes, err := proof.MarshalBinary() + r.NoError(err) + + return proofBytes +} + +func TestRangeProofEmptyDB(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + proof, err := db.RangeProof(EmptyRoot, nothing(), nothing(), rangeProofLenUnbounded) + r.ErrorIs(err, errRevisionNotFound) + r.Nil(proof) +} + +func TestRangeProofNonExistentRoot(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // insert some data + keys, vals := kvForTest(100) + root, err := db.Update(keys, vals) + r.NoError(err) + + // create a bogus root + root[0] ^= 0xFF + + proof, err := db.RangeProof(root, nothing(), nothing(), rangeProofLenUnbounded) + r.ErrorIs(err, errRevisionNotFound) + r.Nil(proof) +} + +func TestRangeProofPartialRange(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Insert a lot of data. + keys, vals := kvForTest(10000) + root, err := db.Update(keys, vals) + r.NoError(err) + + // get a proof over some partial range + proof1 := newSerializedRangeProof(t, db, root, nothing(), nothing(), rangeProofLenTruncated) + + // get a proof over a different range + proof2 := newSerializedRangeProof(t, db, root, something([]byte("key2")), something([]byte("key3")), rangeProofLenTruncated) + + // ensure the proofs are different + r.NotEqual(proof1, proof2) +} + +func TestRangeProofDiffersAfterUpdate(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Insert some data. + keys, vals := kvForTest(100) + root1, err := db.Update(keys[:50], vals[:50]) + r.NoError(err) + + // get a proof + proof := newSerializedRangeProof(t, db, root1, nothing(), nothing(), rangeProofLenTruncated) + + // insert more data + root2, err := db.Update(keys[50:], vals[50:]) + r.NoError(err) + r.NotEqual(root1, root2) + + // get a proof again + proof2 := newSerializedRangeProof(t, db, root2, nothing(), nothing(), rangeProofLenTruncated) + + // ensure the proofs are different + r.NotEqual(proof, proof2) +} + +func TestRoundTripSerialization(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + // Insert some data. + keys, vals := kvForTest(10) + root, err := db.Update(keys, vals) + r.NoError(err) + + // get a proof + proofBytes := newSerializedRangeProof(t, db, root, nothing(), nothing(), rangeProofLenUnbounded) + + // Deserialize the proof. + proof := new(RangeProof) + err = proof.UnmarshalBinary(proofBytes) + r.NoError(err) + t.Cleanup(func() { r.NoError(proof.Free()) }) + + // serialize the proof again + serialized, err := proof.MarshalBinary() + r.NoError(err) + r.Equal(proofBytes, serialized) +} + +func TestRangeProofVerify(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + keys, vals := kvForTest(100) + root, err := db.Update(keys, vals) + r.NoError(err) + + proof := newVerifiedRangeProof(t, db, root, nothing(), nothing(), rangeProofLenTruncated) + + // Database should be immediately closeable (no keep-alive) + r.NoError(db.Close(oneSecCtx(t))) + + // Verify with wrong root should fail + root[0] ^= 0xFF + err = proof.Verify(root, nothing(), nothing(), rangeProofLenTruncated) + + // TODO(#738): re-enable after verification is implemented + // r.Error(err, "Verification with wrong root should fail") + r.NoError(err) +} + +func TestVerifyAndCommitRangeProof(t *testing.T) { + r := require.New(t) + + // Create source and target databases + dbSource := newTestDatabase(t) + dbTarget := newTestDatabase(t) + + // Populate source + keys, vals := kvForTest(50) + sourceRoot, err := dbSource.Update(keys, vals) + r.NoError(err) + + proof := newVerifiedRangeProof(t, dbSource, sourceRoot, nothing(), nothing(), rangeProofLenUnbounded) + + // Verify and commit to target without previously calling db.VerifyRangeProof + committedRoot, err := dbTarget.VerifyAndCommitRangeProof(proof, nothing(), nothing(), sourceRoot, rangeProofLenUnbounded) + r.NoError(err) + r.Equal(sourceRoot, committedRoot) + + // Verify all keys are now in target database + for i, key := range keys { + got, err := dbTarget.Get(key) + r.NoError(err, "Get key %d", i) + r.Equal(vals[i], got, "Value mismatch for key %d", i) + } +} + +func TestRangeProofFindNextKey(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + + keys, vals := kvForTest(100) + root, err := db.Update(keys, vals) + r.NoError(err) + + proof := newVerifiedRangeProof(t, db, root, nothing(), nothing(), rangeProofLenTruncated) + + // FindNextKey should fail before preparing a proposal or committing + _, err = proof.FindNextKey() + r.ErrorIs(err, errNotPrepared, "FindNextKey should fail on unverified proof") + + // Verify the proof + r.NoError(db.VerifyRangeProof(proof, nothing(), nothing(), root, rangeProofLenTruncated)) + + // Now FindNextKey should work + nextRange, err := proof.FindNextKey() + r.NoError(err) + r.NotNil(nextRange) + startKey := nextRange.StartKey() + r.NotEmpty(startKey) + startKey = append([]byte{}, startKey...) // copy to new slice to avoid use-after-free + r.NoError(nextRange.Free()) + + _, err = db.VerifyAndCommitRangeProof(proof, nothing(), nothing(), root, rangeProofLenTruncated) + r.NoError(err) + + // FindNextKey should still work after commit + nextRange, err = proof.FindNextKey() + r.NoError(err) + r.NotNil(nextRange) + r.Equal(nextRange.StartKey(), startKey) + r.NoError(nextRange.Free()) +} + +func TestRangeProofFreeReleasesKeepAlive(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(50) + root, err := db.Update(keys, vals) + r.NoError(err) + + proof := newVerifiedRangeProof(t, db, root, nothing(), nothing(), rangeProofLenTruncated) + r.NoError(err) + + // prepare proposal (acquires keep-alive) + r.NoError(db.VerifyRangeProof(proof, nothing(), nothing(), root, rangeProofLenTruncated)) + + // Database should not be closeable while proof has keep-alive + r.ErrorIs(db.Close(oneSecCtx(t)), ErrActiveKeepAliveHandles) + + // Free the proof (releases keep-alive) + r.NoError(proof.Free()) + + // Database should now be closeable + r.NoError(db.Close(oneSecCtx(t))) +} + +func TestRangeProofCommitReleasesKeepAlive(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(50) + root, err := db.Update(keys, vals) + r.NoError(err) + + proof := newVerifiedRangeProof(t, db, root, nothing(), nothing(), rangeProofLenTruncated) + marshalledBeforeCommit, err := proof.MarshalBinary() + r.NoError(err) + + // prepare proposal (acquires keep-alive) + r.NoError(db.VerifyRangeProof(proof, nothing(), nothing(), root, rangeProofLenTruncated)) + + // Database should not be closeable while proof has keep-alive + r.ErrorIs(db.Close(oneSecCtx(t)), ErrActiveKeepAliveHandles) + + // Commit the proof (releases keep-alive) + _, err = db.VerifyAndCommitRangeProof(proof, nothing(), nothing(), root, rangeProofLenTruncated) + r.NoError(err) + + // Database should now be closeable + r.NoError(db.Close(oneSecCtx(t))) + + marshalledAfterCommit, err := proof.MarshalBinary() + r.NoError(err) + + // methods like MarshalBinary should still work after commit and closing the database + r.Equal(marshalledBeforeCommit, marshalledAfterCommit) +} + +// TestRangeProofFinalizerCleanup verifies that the finalizer properly releases +// the keep-alive handle when the proof goes out of scope. +func TestRangeProofFinalizerCleanup(t *testing.T) { + r := require.New(t) + db := newTestDatabase(t) + keys, vals := kvForTest(50) + root, err := db.Update(keys, vals) + r.NoError(err) + + // note: this does not use newVerifiedRangeProof because it sets a cleanup + // which retains a handle to the proof blocking our ability to wait for the + // finalizer to run + proof, err := db.RangeProof(root, nothing(), nothing(), rangeProofLenTruncated) + r.NoError(err) + assertProofNotNil(t, proof) + + // prepare proposal (acquires keep-alive) + r.NoError(db.VerifyRangeProof(proof, nothing(), nothing(), root, rangeProofLenTruncated)) + + // Database should not be closeable while proof has keep-alive + r.ErrorIs(db.Close(oneSecCtx(t)), ErrActiveKeepAliveHandles) + + runtime.KeepAlive(proof) + proof = nil //nolint:ineffassign // necessary to drop the reference for GC + runtime.GC() + + r.NoError(db.Close(t.Context()), "Database should be closeable after proof is garbage collected") +} diff --git a/firewood/ffi/proposal.go b/firewood/ffi/proposal.go new file mode 100644 index 000000000000..4d59f4e35791 --- /dev/null +++ b/firewood/ffi/proposal.go @@ -0,0 +1,171 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +// #include +// #include "firewood.h" +import "C" + +import ( + "errors" + "fmt" + "runtime" + "sync" + "unsafe" +) + +var errDroppedProposal = errors.New("proposal already dropped") + +// Proposal represents a set of proposed changes to be committed to the database. +// Proposals are created via [Database.Propose] or [Proposal.Propose], and must be +// either committed with [Proposal.Commit] or released with [Proposal.Drop]. +// +// Proposals must be committed or dropped before the associated database is +// closed. A finalizer is set on each Proposal to ensure that Drop is called +// when the Proposal is garbage collected, but relying on finalizers is not +// recommended. Failing to commit or drop a proposal before the database is +// closed will cause it to block or fail. +// +// All operations on a Proposal are thread-safe with respect to each other, +// except for [Proposal.Commit] and [Proposal.Drop], which are not safe to +// call concurrently with any other operations. +type Proposal struct { + // handle is an opaque pointer to the proposal within Firewood. It should be + // passed to the C FFI functions that operate on proposals + // + // It is not safe to call these methods with a nil handle. + // + // Calls to `C.fwd_commit_proposal` and `C.fwd_free_proposal` will invalidate + // this handle, so it should not be used after those calls. + handle *C.ProposalHandle + + // root is the root hash of the proposal and the expected root hash after commit. + root Hash + + // keepAliveHandle is used to keep the database alive while this proposal is + // in use. It is initialized when the proposal is created and disowned after + // [Proposal.Commit] or [Proposal.Drop] is called. + keepAliveHandle databaseKeepAliveHandle +} + +// Root retrieves the root hash of the proposal. +func (p *Proposal) Root() (Hash, error) { + return p.root, nil +} + +// Get retrieves the value for the given key. +// If the key does not exist, it returns nil. +func (p *Proposal) Get(key []byte) ([]byte, error) { + if p.handle == nil { + return nil, errDroppedProposal + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + return getValueFromValueResult(C.fwd_get_from_proposal(p.handle, newBorrowedBytes(key, &pinner))) +} + +// Iter creates and iterator starting from the provided key on proposal. +// pass empty slice to start from beginning. +func (p *Proposal) Iter(key []byte) (*Iterator, error) { + if p.handle == nil { + return nil, errDBClosed + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + itResult := C.fwd_iter_on_proposal(p.handle, newBorrowedBytes(key, &pinner)) + + return getIteratorFromIteratorResult(itResult) +} + +// Propose is equivalent to [Database.Propose] except that the new proposal is +// based on `p`. +// The returned proposal cannot be committed until the parent proposal `p` has been +// committed. Additionally, it must be committed or dropped before the [Database] is closed. +// +// Value Semantics: +// - nil value (vals[i] == nil): Performs a DeleteRange operation using the key as a prefix +// - empty slice (vals[i] != nil && len(vals[i]) == 0): Inserts/updates the key with an empty value +// - non-empty value: Inserts/updates the key with the provided value +func (p *Proposal) Propose(keys, vals [][]byte) (*Proposal, error) { + if p.handle == nil { + return nil, errDroppedProposal + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + kvp, err := newKeyValuePairs(keys, vals, &pinner) + if err != nil { + return nil, err + } + return getProposalFromProposalResult(C.fwd_propose_on_proposal(p.handle, kvp), p.keepAliveHandle.outstandingHandles) +} + +// Commit commits the proposal and returns any errors. +// +// The underlying data is no longer available after this call, but the root +// hash can still be retrieved using [Proposal.Root]. +func (p *Proposal) Commit() error { + return p.keepAliveHandle.disown(true /* evenOnError */, func() error { + if p.handle == nil { + return errDroppedProposal + } + + _, err := getHashKeyFromHashResult(C.fwd_commit_proposal(p.handle)) + + // Prevent double free + p.handle = nil + + return err + }) +} + +// Drop releases the memory associated with the Proposal. All child proposals +// created from this proposal can no longer be committed. +// +// This is safe to call if the memory has already been released, in which case +// it does nothing. +func (p *Proposal) Drop() error { + return p.keepAliveHandle.disown(false /* evenOnError */, func() error { + if p.handle == nil { + return nil + } + + if err := getErrorFromVoidResult(C.fwd_free_proposal(p.handle)); err != nil { + return fmt.Errorf("%w: %w", errFreeingValue, err) + } + + // Prevent double free + p.handle = nil + + return nil + }) +} + +// getProposalFromProposalResult converts a C.ProposalResult to a Proposal or error. +func getProposalFromProposalResult(result C.ProposalResult, wg *sync.WaitGroup) (*Proposal, error) { + switch result.tag { + case C.ProposalResult_NullHandlePointer: + return nil, errDBClosed + case C.ProposalResult_Ok: + body := (*C.ProposalResult_Ok_Body)(unsafe.Pointer(&result.anon0)) + hashKey := *(*Hash)(unsafe.Pointer(&body.root_hash._0)) + proposal := &Proposal{ + handle: body.handle, + root: hashKey, + } + proposal.keepAliveHandle.init(wg) + runtime.SetFinalizer(proposal, (*Proposal).Drop) + return proposal, nil + case C.ProposalResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.ProposalResult tag: %d", result.tag) + } +} diff --git a/firewood/ffi/revision.go b/firewood/ffi/revision.go new file mode 100644 index 000000000000..743a9b5d7d51 --- /dev/null +++ b/firewood/ffi/revision.go @@ -0,0 +1,137 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package ffi + +// #include +// #include "firewood.h" +import "C" + +import ( + "errors" + "fmt" + "runtime" + "sync" + "unsafe" +) + +var ( + ErrDroppedRevision = errors.New("revision already dropped") + errRevisionNotFound = errors.New("revision not found") +) + +// Revision is an immutable view over the state at a specific root hash. +// Instances are created via [Database.Revision], provide read-only access to +// the revision, and must be released with [Revision.Drop] when no longer needed. +// +// Revisions must be dropped before the associated database is closed. A finalizer +// is set on each Revision to ensure that Drop is called when the Revision is +// garbage collected, but relying on finalizers is not recommended. Failing to +// drop a revision before the database is closed will cause it to block or fail. +// +// Additionally, Revisions should be dropped when no longer needed to allow the +// database to free any associated resources. Firewood ensures that the state +// associated with a Revision is retained until all Revisions based on that state +// have been dropped. +// +// All operations on a Revision are thread-safe with respect to each other. +type Revision struct { + // handle is an opaque pointer to the revision within Firewood. It should be + // passed to the C FFI functions that operate on revisions + // + // It is not safe to call these methods with a nil handle. + // + // Calls to `C.fwd_free_revision` will invalidate this handle, so it should + // not be used after that call. + handle *C.RevisionHandle + + // root is the root hash of the revision. + root Hash + + // keepAliveHandle is used to keep the database alive while this revision is + // in use. It is initialized when the revision is created and disowned after + // [Revision.Drop] is called. + keepAliveHandle databaseKeepAliveHandle +} + +// Get reads the value stored at the provided key within the revision. +// If the key does not exist, it returns nil. +// +// It returns ErrDroppedRevision if Drop has already been called. +func (r *Revision) Get(key []byte) ([]byte, error) { + if r.handle == nil { + return nil, ErrDroppedRevision + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + return getValueFromValueResult(C.fwd_get_from_revision( + r.handle, + newBorrowedBytes(key, &pinner), + )) +} + +// Iter creates an iterator starting from the provided key on revision. +// pass empty slice to start from beginning +// It returns ErrDroppedRevision if Drop has already been called. +func (r *Revision) Iter(key []byte) (*Iterator, error) { + if r.handle == nil { + return nil, ErrDroppedRevision + } + + var pinner runtime.Pinner + defer pinner.Unpin() + + itResult := C.fwd_iter_on_revision(r.handle, newBorrowedBytes(key, &pinner)) + + return getIteratorFromIteratorResult(itResult) +} + +// Drop releases the resources backed by the revision handle. +// +// It is safe to call Drop multiple times; subsequent calls after the first are no-ops. +func (r *Revision) Drop() error { + return r.keepAliveHandle.disown(false /* evenOnError */, func() error { + if r.handle == nil { + return nil + } + + if err := getErrorFromVoidResult(C.fwd_free_revision(r.handle)); err != nil { + return fmt.Errorf("%w: %w", errFreeingValue, err) + } + + r.handle = nil + return nil + }) +} + +// Root returns the root hash of the revision. +func (r *Revision) Root() Hash { + return r.root +} + +// getRevisionFromResult converts a C.RevisionResult to a Revision or error. +func getRevisionFromResult(result C.RevisionResult, wg *sync.WaitGroup) (*Revision, error) { + switch result.tag { + case C.RevisionResult_NullHandlePointer: + return nil, errDBClosed + case C.RevisionResult_RevisionNotFound: + return nil, errRevisionNotFound + case C.RevisionResult_Ok: + body := (*C.RevisionResult_Ok_Body)(unsafe.Pointer(&result.anon0)) + hashKey := *(*Hash)(unsafe.Pointer(&body.root_hash._0)) + rev := &Revision{ + handle: body.handle, + root: hashKey, + } + rev.keepAliveHandle.init(wg) + runtime.SetFinalizer(rev, (*Revision).Drop) + return rev, nil + case C.RevisionResult_Err: + err := newOwnedBytes(*(*C.OwnedBytes)(unsafe.Pointer(&result.anon0))).intoError() + return nil, err + default: + return nil, fmt.Errorf("unknown C.RevisionResult tag: %d", result.tag) + } +} diff --git a/firewood/ffi/src/arc_cache.rs b/firewood/ffi/src/arc_cache.rs new file mode 100644 index 000000000000..2d727bbce8a0 --- /dev/null +++ b/firewood/ffi/src/arc_cache.rs @@ -0,0 +1,91 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! A simple single-item cache for database views. +//! +//! This module provides [`ArcCache`], a thread-safe cache that holds at most one +//! key-value pair. It's specifically designed to cache database views in the FFI +//! layer to improve performance by avoiding repeated view creation for the same +//! root hash during database operations. + +use parking_lot::{Mutex, MutexGuard}; +use std::sync::Arc; + +/// A thread-safe single-item cache that stores key-value pairs as `Arc`. +/// +/// This cache is optimized for scenarios where you frequently access the same +/// item and want to avoid expensive recomputation. It holds at most one cached +/// entry and replaces it when a different key is requested. +/// +/// The cache is thread-safe and uses a mutex to protect concurrent access. +/// Values are stored as `Arc` to allow cheap cloning and sharing across +/// threads. +#[derive(Debug)] +pub struct ArcCache { + cache: Mutex)>>, +} + +impl ArcCache { + pub const fn new() -> Self { + ArcCache { + cache: Mutex::new(None), + } + } + + /// Gets the cached value for the given key, or creates and caches a new value. + /// + /// If the cache contains an entry with a key equal to the provided key, + /// returns a clone of the cached `Arc`. Otherwise, calls the factory + /// function to create a new value, caches it, and returns it. + /// + /// # Cache Behavior + /// + /// - Cache hit: Returns the cached value immediately + /// - Cache miss: Clears any existing cache entry, calls factory, caches the result + /// - Factory error: Cache is cleared and the error is propagated + /// + /// # Arguments + /// + /// * `key` - The key to look up or cache + /// * `factory` - A function that creates the value if not cached. It receives + /// a reference to the key as an argument. + /// + /// # Errors + /// + /// Returns any error produced by the factory function. + pub fn get_or_try_insert_with( + &self, + key: K, + factory: impl FnOnce(&K) -> Result, E>, + ) -> Result, E> { + let mut cache = self.lock(); + if let Some((cached_key, value)) = cache.as_ref() + && *cached_key == key + { + return Ok(Arc::clone(value)); + } + + // clear the cache before running the factory in case it fails + *cache = None; + + let value = factory(&key)?; + *cache = Some((key, Arc::clone(&value))); + + Ok(value) + } + + /// Clears the cache, removing any stored key-value pair. + pub fn clear(&self) { + self.lock().take(); + } + + fn lock(&self) -> MutexGuard<'_, Option<(K, Arc)>> { + self.cache.lock() + } +} + +impl Default for ArcCache { + fn default() -> Self { + Self::new() + } +} diff --git a/firewood/ffi/src/handle.rs b/firewood/ffi/src/handle.rs new file mode 100644 index 000000000000..994e04cd198f --- /dev/null +++ b/firewood/ffi/src/handle.rs @@ -0,0 +1,275 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::path::PathBuf; + +use firewood::{ + db::{Db, DbConfig}, + manager::RevisionManagerConfig, + v2::api::{self, ArcDynDbView, Db as _, DbView, HashKey, HashKeyExt, IntoBatchIter, KeyType}, +}; + +use crate::{BorrowedBytes, CView, CreateProposalResult, KeyValuePair, arc_cache::ArcCache}; + +use crate::revision::{GetRevisionResult, RevisionHandle}; +use metrics::counter; + +/// Arguments for creating or opening a database. These are passed to [`fwd_open_db`] +/// +/// [`fwd_open_db`]: crate::fwd_open_db +#[repr(C)] +#[derive(Debug)] +pub struct DatabaseHandleArgs<'a> { + /// The path to the database file. + /// + /// This must be a valid UTF-8 string, even on Windows. + /// + /// If this is empty, an error will be returned. + pub path: BorrowedBytes<'a>, + + /// The path to the `RootStore` directory. + /// + /// This must be a valid UTF-8 string, even on Windows. + /// + /// If this is empty, then the archival feature is disabled. + /// + /// Note: Setting this directory will only track new revisions going forward + /// and will not contain revisions from a prior database instance that didn't + /// set a `root_store_path`. + pub root_store_path: BorrowedBytes<'a>, + + /// The size of the node cache. + /// + /// Opening returns an error if this is zero. + pub cache_size: usize, + + /// The size of the free list cache. + /// + /// Opening returns an error if this is zero. + pub free_list_cache_size: usize, + + /// The maximum number of revisions to keep. + pub revisions: usize, + + /// The cache read strategy to use. + /// + /// This must be one of the following: + /// + /// - `0`: No cache. + /// - `1`: Cache only branch reads. + /// - `2`: Cache all reads. + /// + /// Opening returns an error if this is not one of the above values. + pub strategy: u8, + + /// Whether to truncate the database file if it exists. + pub truncate: bool, +} + +impl DatabaseHandleArgs<'_> { + fn as_rev_manager_config(&self) -> Result { + let cache_read_strategy = match self.strategy { + 0 => firewood::manager::CacheReadStrategy::WritesOnly, + 1 => firewood::manager::CacheReadStrategy::BranchReads, + 2 => firewood::manager::CacheReadStrategy::All, + _ => return Err(invalid_data("invalid cache strategy")), + }; + let config = RevisionManagerConfig::builder() + .node_cache_size( + self.cache_size + .try_into() + .map_err(|_| invalid_data("cache size should be non-zero"))?, + ) + .max_revisions(self.revisions) + .cache_read_strategy(cache_read_strategy) + .free_list_cache_size( + self.free_list_cache_size + .try_into() + .map_err(|_| invalid_data("free list cache size should be non-zero"))?, + ) + .build(); + Ok(config) + } +} + +/// A handle to the database, returned by `fwd_open_db`. +/// +/// These handles are passed to the other FFI functions. +/// +#[derive(Debug)] +#[repr(C)] +pub struct DatabaseHandle { + /// A single cached view to improve performance of reads while committing + cached_view: ArcCache, + + /// The database + db: Db, +} + +impl DatabaseHandle { + /// Creates a new database handle from the given arguments. + /// + /// # Errors + /// + /// If the path is empty, or if the configuration is invalid, this will return an error. + pub fn new(args: DatabaseHandleArgs<'_>) -> Result { + let root_store_path = args + .root_store_path + .as_str() + .map_err(|e| invalid_data(format!("root store path contains invalid utf-8: {e}")))?; + + let root_store_dir = Some(root_store_path) + .filter(|s| !s.is_empty()) + .map(PathBuf::from); + + let cfg = DbConfig::builder() + .truncate(args.truncate) + .manager(args.as_rev_manager_config()?) + .root_store_dir(root_store_dir) + .build(); + + let path = args + .path + .as_str() + .map_err(|err| invalid_data(format!("database path contains invalid utf-8: {err}")))?; + + if path.is_empty() { + return Err(invalid_data("database path cannot be empty")); + } + + Db::new(path, cfg).map(Self::from) + } + + /// Returns the current root hash of the database. + /// + /// # Errors + /// + /// An error is returned if there was an i/o error while reading the root hash. + pub fn current_root_hash(&self) -> Result, api::Error> { + self.db.root_hash() + } + + /// Returns a value from the database for the given key from the latest root hash. + /// + /// # Errors + /// + /// An error is returned if there was an i/o error while reading the value. + pub fn get_latest(&self, key: impl KeyType) -> Result>, api::Error> { + let Some(root) = self.current_root_hash()? else { + return Err(api::Error::RevisionNotFound { + provided: HashKey::default_root_hash(), + }); + }; + + self.db.revision(root)?.val(key) + } + + /// Returns a value from the database for the given key from the specified root hash. + /// + /// # Errors + /// + /// An error is returned if the root hash is invalid or if there was an i/o error + /// while reading the value. + pub fn get_from_root( + &self, + root: HashKey, + key: impl KeyType, + ) -> Result>, api::Error> { + self.get_root(root)?.val(key.as_ref()) + } + + /// Creates a proposal with the given values and returns the proposal and the start time. + /// + /// # Errors + /// + /// An error is returned if the proposal could not be created. + pub fn create_batch<'kvp>( + &self, + values: impl AsRef<[KeyValuePair<'kvp>]> + 'kvp, + ) -> Result, api::Error> { + let CreateProposalResult { handle, start_time } = + self.create_proposal_handle(values.as_ref())?; + + let root_hash = handle.commit_proposal(|commit_time| { + counter!("firewood.ffi.commit_ms").increment(commit_time.as_millis()); + })?; + + counter!("firewood.ffi.batch_ms").increment(start_time.elapsed().as_millis()); + counter!("firewood.ffi.batch").increment(1); + + Ok(root_hash) + } + + /// Returns an owned handle to the revision corresponding to the provided root hash. + /// + /// # Errors + /// + /// Returns an error if could not get the view from underlying database for the specified + /// root hash, for example when the revision does not exist or an I/O error occurs while + /// accessing the database. + pub fn get_revision(&self, root: HashKey) -> Result { + let view = self.db.view(root.clone())?; + Ok(GetRevisionResult { + handle: RevisionHandle::new(view), + root_hash: root, + }) + } + + pub(crate) fn get_root(&self, root: HashKey) -> Result { + let mut cache_miss = false; + let view = self.cached_view.get_or_try_insert_with(root, |key| { + cache_miss = true; + self.db.view(HashKey::clone(key)) + })?; + + if cache_miss { + counter!("firewood.ffi.cached_view.miss").increment(1); + } else { + counter!("firewood.ffi.cached_view.hit").increment(1); + } + + Ok(view) + } + + pub(crate) fn clear_cached_view(&self) { + self.cached_view.clear(); + } + + pub(crate) fn merge_key_value_range( + &self, + first_key: Option, + last_key: Option, + key_values: impl IntoIterator, + ) -> Result, api::Error> { + CreateProposalResult::new(self, || { + self.db + .merge_key_value_range(first_key, last_key, key_values) + }) + } +} + +impl From for DatabaseHandle { + fn from(db: Db) -> Self { + Self { + db, + cached_view: ArcCache::new(), + } + } +} + +impl<'db> CView<'db> for &'db crate::DatabaseHandle { + fn handle(&self) -> &'db crate::DatabaseHandle { + self + } + + fn create_proposal( + self, + values: impl IntoBatchIter, + ) -> Result, api::Error> { + self.db.propose(values) + } +} + +fn invalid_data(error: impl Into>) -> api::Error { + api::Error::IO(std::io::Error::new(std::io::ErrorKind::InvalidData, error)) +} diff --git a/firewood/ffi/src/iterator.rs b/firewood/ffi/src/iterator.rs new file mode 100644 index 000000000000..420749a50e9b --- /dev/null +++ b/firewood/ffi/src/iterator.rs @@ -0,0 +1,46 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use derive_where::derive_where; +use firewood::merkle; +use firewood::v2::api::{self, BoxKeyValueIter}; +use std::iter::FusedIterator; + +type KeyValueItem = (merkle::Key, merkle::Value); + +/// An opaque wrapper around a [`BoxKeyValueIter`]. +#[derive(Default)] +#[derive_where(Debug)] +#[derive_where(skip_inner)] +pub struct IteratorHandle<'view>(Option>); + +impl<'view> From> for IteratorHandle<'view> { + fn from(value: BoxKeyValueIter<'view>) -> Self { + IteratorHandle(Some(value)) + } +} + +impl Iterator for IteratorHandle<'_> { + type Item = Result; + + fn next(&mut self) -> Option { + let out = self.0.as_mut()?.next(); + if out.is_none() { + // iterator exhausted; drop it so the NodeStore can be released + self.0 = None; + } + out.map(|res| res.map_err(api::Error::from)) + } +} + +impl FusedIterator for IteratorHandle<'_> {} + +#[expect(clippy::missing_errors_doc)] +impl IteratorHandle<'_> { + pub fn iter_next_n(&mut self, n: usize) -> Result, api::Error> { + self.by_ref().take(n).collect() + } +} + +#[derive(Debug, Default)] +pub struct CreateIteratorResult<'db>(pub IteratorHandle<'db>); diff --git a/firewood/ffi/src/lib.rs b/firewood/ffi/src/lib.rs new file mode 100644 index 000000000000..ffa05ba4152f --- /dev/null +++ b/firewood/ffi/src/lib.rs @@ -0,0 +1,772 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// HINT WHEN REFERENCING TYPES OUTSIDE THIS LIBRARY: +// - Anything that is outside the crate must be included as a `type` alias (not just +// a `use`) in order for cbindgen to generate an opaque forward declaration. The type +// alias can have a doc comment which will be included in the generated header file. +// - The value must be boxed, or otherwise used via a pointer. This is because only +// a forward declaration is generated and callers will be unable to instantiate the +// type without a complete definition. + +#![doc = include_str!("../README.md")] +#![expect( + unsafe_code, + reason = "This is an FFI library, so unsafe code is expected." +)] +#![cfg_attr( + not(target_pointer_width = "64"), + forbid( + clippy::cast_possible_truncation, + reason = "non-64 bit target likely to cause issues during u64 to usize conversions" + ) +)] + +mod arc_cache; +mod handle; +mod iterator; +mod logging; +mod metrics_setup; +mod proofs; +mod proposal; +mod revision; +mod value; + +use firewood::v2::api::DbView; + +pub use crate::handle::*; +pub use crate::iterator::*; +pub use crate::logging::*; +pub use crate::proofs::*; +pub use crate::proposal::*; +pub use crate::revision::*; +pub use crate::value::*; + +#[cfg(unix)] +#[global_allocator] +#[doc(hidden)] +static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; + +/// Invokes a closure and returns the result as a [`CResult`]. +/// +/// If the closure panics, it will return [`CResult::from_panic`] with the panic +/// information. +#[inline] +fn invoke>(once: impl FnOnce() -> V) -> T { + match std::panic::catch_unwind(std::panic::AssertUnwindSafe(once)) { + Ok(result) => result.into(), + Err(panic) => T::from_panic(panic), + } +} + +/// Invokes a closure that requires a handle and returns the result as a [`NullHandleResult`]. +/// +/// If the provided handle is [`None`], the function will return early with the +/// [`NullHandleResult::null_handle_pointer_error`] result. +/// +/// Otherwise, the closure is invoked with the handle. If the closure panics, +/// it will be caught and returned as a [`CResult::from_panic`]. +#[inline] +fn invoke_with_handle>( + handle: Option, + once: impl FnOnce(H) -> V, +) -> T { + match handle { + Some(handle) => invoke(move || once(handle)), + None => T::null_handle_pointer_error(), + } +} + +/// Gets the value associated with the given key from the database for the +/// latest revision. +/// +/// # Arguments +/// +/// * `db` - The database handle returned by [`fwd_open_db`] +/// * `key` - The key to look up as a [`BorrowedBytes`] +/// +/// # Returns +/// +/// - [`ValueResult::NullHandlePointer`] if the provided database handle is null. +/// - [`ValueResult::RevisionNotFound`] if no revision was found for the root +/// (i.e., there is no current root). +/// - [`ValueResult::None`] if the key was not found. +/// - [`ValueResult::Some`] if the key was found with the associated value. +/// - [`ValueResult::Err`] if an error occurred while retrieving the value. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `db` is a valid pointer to a [`DatabaseHandle`]. +/// * ensure that `key` is valid for [`BorrowedBytes`] +/// * call [`fwd_free_owned_bytes`] to free the memory associated with the +/// returned error or value. +/// +/// [`BorrowedBytes`]: crate::value::BorrowedBytes +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_get_latest( + db: Option<&DatabaseHandle>, + key: BorrowedBytes, +) -> ValueResult { + invoke_with_handle(db, move |db| db.get_latest(key)) +} + +/// Returns an iterator optionally starting from a key in the provided revision. +/// +/// # Arguments +/// +/// * `revision` - The revision handle returned by [`fwd_get_revision`]. +/// * `key` - The key to look up as a [`BorrowedBytes`] +/// +/// # Returns +/// +/// - [`IteratorResult::NullHandlePointer`] if the provided revision handle is null. +/// - [`IteratorResult::Ok`] if the iterator was created, with the iterator handle. +/// - [`IteratorResult::Err`] if an error occurred while creating the iterator. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `revision` is a valid pointer to a [`RevisionHandle`] +/// * ensure that `key` is a valid [`BorrowedBytes`] +/// * call [`fwd_free_iterator`] to free the memory associated with the iterator. +/// +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_iter_on_revision<'view>( + revision: Option<&'view RevisionHandle>, + key: BorrowedBytes, +) -> IteratorResult<'view> { + invoke_with_handle(revision, move |rev| rev.iter_from(Some(key.as_slice()))) +} + +/// Returns an iterator on the provided proposal optionally starting from a key +/// +/// # Arguments +/// +/// * `handle` - The proposal handle returned by [`fwd_propose_on_db`] or +/// [`fwd_propose_on_proposal`]. +/// * `key` - The key to look up as a [`BorrowedBytes`] +/// +/// # Returns +/// +/// - [`IteratorResult::NullHandlePointer`] if the provided proposal handle is null. +/// - [`IteratorResult::Ok`] if the iterator was created, with the iterator handle. +/// - [`IteratorResult::Err`] if an error occurred while creating the iterator. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `handle` is a valid pointer to a [`ProposalHandle`] +/// * ensure that `key` is a valid for [`BorrowedBytes`] +/// * call [`fwd_free_iterator`] to free the memory associated with the iterator. +/// +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_iter_on_proposal<'p>( + handle: Option<&'p ProposalHandle<'_>>, + key: BorrowedBytes, +) -> IteratorResult<'p> { + invoke_with_handle(handle, move |p| p.iter_from(Some(key.as_slice()))) +} + +/// Retrieves the next item from the iterator. +/// +/// # Arguments +/// +/// * `handle` - The iterator handle returned by [`fwd_iter_on_revision`] or +/// [`fwd_iter_on_proposal`]. +/// +/// # Returns +/// +/// - [`KeyValueResult::NullHandlePointer`] if the provided iterator handle is null. +/// - [`KeyValueResult::None`] if the iterator is exhausted (no remaining values). Once returned, +/// subsequent calls will continue returning [`KeyValueResult::None`]. You may still call this +/// safely, but freeing the iterator with [`fwd_free_iterator`] is recommended. +/// - [`KeyValueResult::Some`] if the next item on iterator was retrieved, with the associated +/// key value pair. +/// - [`KeyValueResult::Err`] if an I/O error occurred while retrieving the next item. Most +/// iterator errors are non-reentrant. Once returned, the iterator should be considered +/// invalid and must be freed with [`fwd_free_iterator`]. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `handle` is a valid pointer to a [`IteratorHandle`]. +/// * call [`fwd_free_owned_kv_pair`] on returned [`OwnedKeyValuePair`] +/// to free the memory associated with the returned value. +/// +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_iter_next(handle: Option<&mut IteratorHandle<'_>>) -> KeyValueResult { + invoke_with_handle(handle, Iterator::next) +} + +/// Retrieves the next batch of items from the iterator. +/// +/// # Arguments +/// +/// * `handle` - The iterator handle returned by [`fwd_iter_on_revision`] or +/// [`fwd_iter_on_proposal`]. +/// +/// # Returns +/// +/// - [`KeyValueBatchResult::NullHandlePointer`] if the provided iterator handle is null. +/// - [`KeyValueBatchResult::Some`] with up to `n` key/value pairs. If the iterator is +/// exhausted, this may be fewer than `n`, including zero items. +/// - [`KeyValueBatchResult::Err`] if an I/O error occurred while retrieving items. Most +/// iterator errors are non-reentrant. Once returned, the iterator should be considered +/// invalid and must be freed with [`fwd_free_iterator`]. +/// +/// Once an empty batch or items fewer than `n` is returned (iterator exhausted), subsequent calls +/// will continue returning empty batches. You may still call this safely, but freeing the +/// iterator with [`fwd_free_iterator`] is recommended. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `handle` is a valid pointer to a [`IteratorHandle`]. +/// * call [`fwd_free_owned_key_value_batch`] on the returned batch to free any allocated memory. +/// +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_iter_next_n( + handle: Option<&mut IteratorHandle<'_>>, + n: usize, +) -> KeyValueBatchResult { + invoke_with_handle(handle, |it| it.iter_next_n(n)) +} + +/// Consumes the [`IteratorHandle`], destroys the iterator, and frees the memory. +/// +/// # Arguments +/// +/// * `iterator` - A pointer to a [`IteratorHandle`] previously returned from a +/// function from this library. +/// +/// # Returns +/// +/// - [`VoidResult::NullHandlePointer`] if the provided iterator handle is null. +/// - [`VoidResult::Ok`] if the iterator was successfully freed. +/// - [`VoidResult::Err`] if the process panics while freeing the memory. +/// +/// # Safety +/// +/// The caller must ensure that the `iterator` is not null and that it points to +/// a valid [`IteratorHandle`] previously returned by a function from this library. +/// +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_free_iterator( + iterator: Option>>, +) -> VoidResult { + invoke_with_handle(iterator, drop) +} + +/// Gets a handle to the revision identified by the provided root hash. +/// +/// # Arguments +/// +/// * `db` - The database handle returned by [`fwd_open_db`]. +/// * `root` - The hash of the revision as a [`BorrowedBytes`]. +/// +/// # Returns +/// +/// - [`RevisionResult::NullHandlePointer`] if the provided database handle is null. +/// - [`RevisionResult::Ok`] containing a [`RevisionHandle`] and root hash if the revision exists. +/// - [`RevisionResult::Err`] if the revision cannot be fetched or the root hash is invalid. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `db` is a valid pointer to a [`DatabaseHandle`]. +/// * ensure that `root` is valid for [`BorrowedBytes`]. +/// * call [`fwd_free_revision`] to free the returned handle when it is no longer needed. +/// +/// [`BorrowedBytes`]: crate::value::BorrowedBytes +/// [`RevisionHandle`]: crate::revision::RevisionHandle +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_get_revision( + db: Option<&DatabaseHandle>, + root: HashKey, +) -> RevisionResult { + invoke_with_handle(db, move |db| db.get_revision(root.into())) +} + +/// Gets the value associated with the given key from the provided revision handle. +/// +/// # Arguments +/// +/// * `revision` - The revision handle returned by [`fwd_get_revision`]. +/// * `key` - The key to look up as a [`BorrowedBytes`]. +/// +/// # Returns +/// +/// - [`ValueResult::NullHandlePointer`] if the provided revision handle is null. +/// - [`ValueResult::None`] if the key was not found in the revision. +/// - [`ValueResult::Some`] if the key was found with the associated value. +/// - [`ValueResult::Err`] if an error occurred while retrieving the value. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `revision` is a valid pointer to a [`RevisionHandle`]. +/// * ensure that `key` is valid for [`BorrowedBytes`]. +/// * call [`fwd_free_owned_bytes`] to free the memory associated with the [`OwnedBytes`] +/// returned in the result. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_get_from_revision( + revision: Option<&RevisionHandle>, + key: BorrowedBytes, +) -> ValueResult { + invoke_with_handle(revision, move |rev| rev.val(key)) +} + +/// Consumes the [`RevisionHandle`] and frees the memory associated with it. +/// +/// # Arguments +/// +/// * `revision` - A pointer to a [`RevisionHandle`] previously returned by +/// [`fwd_get_revision`]. +/// +/// # Returns +/// +/// - [`VoidResult::NullHandlePointer`] if the provided revision handle is null. +/// - [`VoidResult::Ok`] if the revision handle was successfully freed. +/// - [`VoidResult::Err`] if the process panics while freeing the memory. +/// +/// # Safety +/// +/// The caller must ensure that the revision handle is valid and is not used again after +/// this function is called. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_free_revision(revision: Option>) -> VoidResult { + invoke_with_handle(revision, drop) +} + +/// Gets the value associated with the given key from the proposal provided. +/// +/// # Arguments +/// +/// * `handle` - The proposal handle returned by [`fwd_propose_on_db`] or +/// [`fwd_propose_on_proposal`]. +/// * `key` - The key to look up, as a [`BorrowedBytes`]. +/// +/// # Returns +/// +/// - [`ValueResult::NullHandlePointer`] if the provided database handle is null. +/// - [`ValueResult::None`] if the key was not found. +/// - [`ValueResult::Some`] if the key was found with the associated value. +/// - [`ValueResult::Err`] if an error occurred while retrieving the value. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `handle` is a valid pointer to a [`ProposalHandle`] +/// * ensure that `key` is valid for [`BorrowedBytes`] +/// * call [`fwd_free_owned_bytes`] to free the memory associated [`OwnedBytes`] +/// returned in the result. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_get_from_proposal( + handle: Option<&ProposalHandle<'_>>, + key: BorrowedBytes, +) -> ValueResult { + invoke_with_handle(handle, move |handle| handle.val(key)) +} + +/// Gets a value assoicated with the given root hash and key. +/// +/// The hash may refer to a historical revision or an existing proposal. +/// +/// # Arguments +/// +/// * `db` - The database handle returned by [`fwd_open_db`] +/// * `root` - The root hash to look up as a [`BorrowedBytes`] +/// * `key` - The key to look up as a [`BorrowedBytes`] +/// +/// # Returns +/// +/// - [`ValueResult::NullHandlePointer`] if the provided database handle is null. +/// - [`ValueResult::RevisionNotFound`] if no revision was found for the specified root. +/// - [`ValueResult::None`] if the key was not found. +/// - [`ValueResult::Some`] if the key was found with the associated value. +/// - [`ValueResult::Err`] if an error occurred while retrieving the value. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `db` is a valid pointer to a [`DatabaseHandle`] +/// * ensure that `root` is a valid for [`BorrowedBytes`] +/// * ensure that `key` is a valid for [`BorrowedBytes`] +/// * call [`fwd_free_owned_bytes`] to free the memory associated [`OwnedBytes`] +/// returned in the result. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_get_from_root( + db: Option<&DatabaseHandle>, + root: HashKey, + key: BorrowedBytes, +) -> ValueResult { + invoke_with_handle(db, move |db| db.get_from_root(root.into(), key)) +} + +/// Puts the given key-value pairs into the database. +/// +/// # Arguments +/// +/// * `db` - The database handle returned by [`fwd_open_db`] +/// * `values` - A [`BorrowedKeyValuePairs`] containing the key-value pairs to put. +/// +/// # Returns +/// +/// - [`HashResult::NullHandlePointer`] if the provided database handle is null. +/// - [`HashResult::None`] if the commit resulted in an empty database. +/// - [`HashResult::Some`] if the commit was successful, containing the new root hash. +/// - [`HashResult::Err`] if an error occurred while committing the batch. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `db` is a valid pointer to a [`DatabaseHandle`] +/// * ensure that `values` is valid for [`BorrowedKeyValuePairs`] +/// * call [`fwd_free_owned_bytes`] to free the memory associated with the +/// returned error ([`HashKey`] does not need to be freed as it is returned by +/// value). +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_batch( + db: Option<&DatabaseHandle>, + values: BorrowedKeyValuePairs<'_>, +) -> HashResult { + invoke_with_handle(db, move |db| db.create_batch(values)) +} + +/// Proposes a batch of operations to the database. +/// +/// # Arguments +/// +/// * `db` - The database handle returned by [`fwd_open_db`] +/// * `values` - A [`BorrowedKeyValuePairs`] containing the key-value pairs to put. +/// +/// # Returns +/// +/// - [`ProposalResult::NullHandlePointer`] if the provided database handle is null. +/// - [`ProposalResult::Ok`] if the proposal was created, with the proposal handle +/// and calculated root hash. +/// - [`ProposalResult::Err`] if an error occurred while creating the proposal. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `db` is a valid pointer to a [`DatabaseHandle`] +/// * ensure that `values` is valid for [`BorrowedKeyValuePairs`] +/// * call [`fwd_commit_proposal`] or [`fwd_free_proposal`] to free the memory +/// associated with the proposal. And, the caller must ensure this is done +/// before calling [`fwd_close_db`] to avoid memory leaks or undefined behavior. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_propose_on_db<'db>( + db: Option<&'db DatabaseHandle>, + values: BorrowedKeyValuePairs<'_>, +) -> ProposalResult<'db> { + invoke_with_handle(db, move |db| db.create_proposal_handle(values)) +} + +/// Proposes a batch of operations to the database on top of an existing proposal. +/// +/// # Arguments +/// +/// * `handle` - The proposal handle returned by [`fwd_propose_on_db`] or +/// [`fwd_propose_on_proposal`]. +/// * `values` - A [`BorrowedKeyValuePairs`] containing the key-value pairs to put. +/// +/// # Returns +/// +/// - [`ProposalResult::NullHandlePointer`] if the provided database handle is null. +/// - [`ProposalResult::Ok`] if the proposal was created, with the proposal handle +/// and calculated root hash. +/// - [`ProposalResult::Err`] if an error occurred while creating the proposal. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `handle` is a valid pointer to a [`ProposalHandle`] +/// * ensure that `values` is valid for [`BorrowedKeyValuePairs`] +/// * call [`fwd_commit_proposal`] or [`fwd_free_proposal`] to free the memory +/// associated with the proposal. And, the caller must ensure this is done +/// before calling [`fwd_close_db`] to avoid memory leaks or undefined behavior. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_propose_on_proposal<'db>( + handle: Option<&ProposalHandle<'db>>, + values: BorrowedKeyValuePairs<'_>, +) -> ProposalResult<'db> { + invoke_with_handle(handle, move |p| p.create_proposal_handle(values)) +} + +/// Commits a proposal to the database. +/// +/// This function will consume the proposal regardless of whether the commit +/// is successful. +/// +/// # Arguments +/// +/// * `handle` - The proposal handle returned by [`fwd_propose_on_db`] or +/// [`fwd_propose_on_proposal`]. +/// +/// # Returns +/// +/// # Returns +/// +/// - [`HashResult::NullHandlePointer`] if the provided database handle is null. +/// - [`HashResult::None`] if the commit resulted in an empty database. +/// - [`HashResult::Some`] if the commit was successful, containing the new root hash. +/// - [`HashResult::Err`] if an error occurred while committing the batch. +/// +/// # Safety +/// +/// The caller must: +/// * ensure that `handle` is a valid pointer to a [`ProposalHandle`] +/// * ensure that `handle` is not used again after this function is called. +/// * call [`fwd_free_owned_bytes`] to free the memory associated with the +/// returned error ([`HashKey`] does not need to be freed as it is returned +/// by value). +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_commit_proposal( + proposal: Option>>, +) -> HashResult { + invoke_with_handle(proposal, move |proposal| { + proposal.commit_proposal(|commit_time| { + metrics::counter!("firewood.ffi.commit_ms").increment(commit_time.as_millis()); + metrics::counter!("firewood.ffi.commit").increment(1); + }) + }) +} + +/// Consumes the [`ProposalHandle`], cancels the proposal, and frees the memory. +/// +/// # Arguments +/// +/// * `proposal` - A pointer to a [`ProposalHandle`] previously returned from a +/// function from this library. +/// +/// # Returns +/// +/// - [`VoidResult::NullHandlePointer`] if the provided proposal handle is null. +/// - [`VoidResult::Ok`] if the proposal was successfully cancelled and freed. +/// - [`VoidResult::Err`] if the process panics while freeing the memory. +/// +/// # Safety +/// +/// The caller must ensure that the `proposal` is not null and that it points to +/// a valid [`ProposalHandle`] previously returned by a function from this library. +/// +/// The caller must ensure that the proposal was not committed. [`fwd_commit_proposal`] +/// will consume the proposal automatically. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_free_proposal( + proposal: Option>>, +) -> VoidResult { + invoke_with_handle(proposal, drop) +} + +/// Get the root hash of the latest version of the database +/// +/// # Argument +/// +/// * `db` - The database handle returned by [`fwd_open_db`] +/// +/// # Returns +/// +/// - [`HashResult::NullHandlePointer`] if the provided database handle is null. +/// - [`HashResult::None`] if the database is empty. +/// - [`HashResult::Some`] with the root hash of the database. +/// - [`HashResult::Err`] if an error occurred while looking up the root hash. +/// +/// # Safety +/// +/// * ensure that `db` is a valid pointer to a [`DatabaseHandle`] +/// * call [`fwd_free_owned_bytes`] to free the memory associated with the +/// returned error ([`HashKey`] does not need to be freed as it is returned +/// by value). +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_root_hash(db: Option<&DatabaseHandle>) -> HashResult { + invoke_with_handle(db, DatabaseHandle::current_root_hash) +} + +/// Start metrics recorder for this process. +/// +/// # Returns +/// +/// - [`VoidResult::Ok`] if the recorder was initialized. +/// - [`VoidResult::Err`] if an error occurs during initialization. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_start_metrics() -> VoidResult { + invoke(metrics_setup::setup_metrics) +} + +/// Start metrics recorder and exporter for this process. +/// +/// # Arguments +/// +/// * `metrics_port` - the port where metrics will be exposed at +/// +/// # Returns +/// +/// - [`VoidResult::Ok`] if the recorder was initialized. +/// - [`VoidResult::Err`] if an error occurs during initialization. +/// +/// # Safety +/// +/// The caller must: +/// * call [`fwd_free_owned_bytes`] to free the memory associated with the +/// returned error (if any). +#[unsafe(no_mangle)] +pub extern "C" fn fwd_start_metrics_with_exporter(metrics_port: u16) -> VoidResult { + invoke(move || metrics_setup::setup_metrics_with_exporter(metrics_port)) +} + +/// Gather latest metrics for this process. +/// +/// # Returns +/// +/// - [`ValueResult::None`] if the gathered metrics resulted in an empty string. +/// - [`ValueResult::Some`] the gathered metrics as an [`OwnedBytes`] (with +/// guaranteed to be utf-8 data, not null terminated). +/// - [`ValueResult::Err`] if an error occurred while retrieving the value. +/// +/// # Safety +/// +/// The caller must: +/// * call [`fwd_free_owned_bytes`] to free the memory associated with the +/// returned error or value. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_gather() -> ValueResult { + invoke(metrics_setup::gather_metrics) +} + +/// Open a database with the given arguments. +/// +/// # Arguments +/// +/// See [`DatabaseHandleArgs`]. +/// +/// # Returns +/// +/// - [`HandleResult::Ok`] with the database handle if successful. +/// - [`HandleResult::Err`] if an error occurs while opening the database. +/// +/// # Safety +/// +/// The caller must: +/// - ensure that the database is freed with [`fwd_close_db`] when no longer needed. +/// - ensure that the database handle is freed only after freeing or committing +/// all proposals created on it. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_open_db(args: DatabaseHandleArgs) -> HandleResult { + invoke(move || DatabaseHandle::new(args)) +} + +/// Start logs for this process. +/// +/// # Arguments +/// +/// See [`LogArgs`]. +/// +/// # Returns +/// +/// - [`VoidResult::Ok`] if the recorder was initialized. +/// - [`VoidResult::Err`] if an error occurs during initialization. +/// +/// # Safety +/// +/// The caller must: +/// * call [`fwd_free_owned_bytes`] to free the memory associated with the +/// returned error (if any). +#[unsafe(no_mangle)] +pub extern "C" fn fwd_start_logs(args: LogArgs) -> VoidResult { + invoke(move || args.start_logging()) +} + +/// Close and free the memory for a database handle +/// +/// # Arguments +/// +/// * `db` - The database handle to close, previously returned from a call to [`fwd_open_db`]. +/// +/// # Returns +/// +/// - [`VoidResult::NullHandlePointer`] if the provided database handle is null. +/// - [`VoidResult::Ok`] if the database handle was successfully closed and freed. +/// - [`VoidResult::Err`] if the process panics while closing the database handle. +/// +/// # Safety +/// +/// Callers must ensure that: +/// +/// - `db` is a valid pointer to a [`DatabaseHandle`] returned by [`fwd_open_db`]. +/// - There are no handles to any open proposals. If so, they must be freed first +/// using [`fwd_free_proposal`]. +/// - Freeing the database handle does not free outstanding [`RevisionHandle`]s +/// returned by [`fwd_get_revision`]. To prevent leaks, free them separately +/// with [`fwd_free_revision`]. +/// - The database handle is not used after this function is called. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_close_db(db: Option>) -> VoidResult { + invoke_with_handle(db, drop) +} + +/// Consumes the [`OwnedBytes`] and frees the memory associated with it. +/// +/// # Arguments +/// +/// * `bytes` - The [`OwnedBytes`] struct to free, previously returned from any +/// function from this library. +/// +/// # Returns +/// +/// - [`VoidResult::Ok`] if the memory was successfully freed. +/// - [`VoidResult::Err`] if the process panics while freeing the memory. +/// +/// # Safety +/// +/// The caller must ensure that the `bytes` struct is valid and that the memory +/// it points to is uniquely owned by this object. However, if `bytes.ptr` is null, +/// this function does nothing. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_free_owned_bytes(bytes: OwnedBytes) -> VoidResult { + invoke(move || drop(bytes)) +} + +/// Consumes the [`OwnedKeyValueBatch`] and frees the memory associated with it. +/// +/// # Arguments +/// +/// * `batch` - The [`OwnedKeyValueBatch`] struct to free, previously returned from any +/// function from this library. +/// +/// # Returns +/// +/// - [`VoidResult::Ok`] if the memory was successfully freed. +/// - [`VoidResult::Err`] if the process panics while freeing the memory. +/// +/// # Safety +/// +/// The caller must ensure that the `batch` struct is valid and that the memory +/// it points to is uniquely owned by this object. However, if `batch.ptr` is null, +/// this function does nothing. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_free_owned_key_value_batch(batch: OwnedKeyValueBatch) -> VoidResult { + invoke(move || drop(batch)) +} + +/// Consumes the [`OwnedKeyValuePair`] and frees the memory associated with it. +/// +/// # Arguments +/// +/// * `kv` - The [`OwnedKeyValuePair`] struct to free, previously returned from any +/// function from this library. +/// +/// # Returns +/// +/// - [`VoidResult::Ok`] if the memory was successfully freed. +/// - [`VoidResult::Err`] if the process panics while freeing the memory. +/// +/// # Safety +/// +/// The caller must ensure that the `kv` struct is valid. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn fwd_free_owned_kv_pair(kv: OwnedKeyValuePair) -> VoidResult { + invoke(move || drop(kv)) +} diff --git a/firewood/ffi/src/logging.rs b/firewood/ffi/src/logging.rs new file mode 100644 index 000000000000..83923574258f --- /dev/null +++ b/firewood/ffi/src/logging.rs @@ -0,0 +1,124 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::BorrowedBytes; + +/// Arguments for initializing logging for the Firewood FFI. +#[repr(C)] +#[derive(Debug)] +pub struct LogArgs<'a> { + /// The file path where logs for this process are stored. + /// + /// If empty, this is set to `${TMPDIR}/firewood-log.txt`. + /// + /// This is required to be a valid UTF-8 string. + pub path: BorrowedBytes<'a>, + + /// The filter level for logs. + /// + /// If empty, this is set to `info`. + /// + /// This is required to be a valid UTF-8 string. + pub filter_level: BorrowedBytes<'a>, +} + +#[cfg(feature = "logger")] +impl LogArgs<'_> { + fn path(&self) -> std::io::Result> { + let path = self.path.as_str().map_err(|err| { + std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!("log path contains invalid utf-8: {err}"), + ) + })?; + if path.is_empty() { + Ok(std::borrow::Cow::Owned( + std::env::temp_dir().join("firewood-log.txt"), + )) + } else { + Ok(std::borrow::Cow::Borrowed(std::path::Path::new(path))) + } + } + + fn log_level(&self) -> std::io::Result<&str> { + let level = self.filter_level.as_str().map_err(|err| { + std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!("log level contains invalid utf-8: {err}"), + ) + })?; + if level.is_empty() { + Ok("info") + } else { + Ok(level) + } + } + + /// Starts logging to the specified file path with the given filter level. + /// + /// # Errors + /// + /// If the log file cannot be created or opened, or if the log level is invalid, + /// this will return an error. + pub fn start_logging(&self) -> std::io::Result<()> { + use env_logger::Target::Pipe; + use std::fs::OpenOptions; + + let log_path = self.path()?; + + if let Some(log_dir) = log_path.parent() { + std::fs::create_dir_all(log_dir).map_err(|e| { + std::io::Error::new( + e.kind(), + format!( + "failed to create log directory `{}`: {e}", + log_dir.display() + ), + ) + })?; + } + + let level = self.log_level()?; + let level = level.parse().map_err(|e| { + std::io::Error::new( + std::io::ErrorKind::InvalidInput, + format!("invalid log level `{level}`: {e}"), + ) + })?; + + let file = OpenOptions::new() + .create(true) + .write(true) + .truncate(false) + .open(&log_path) + .map_err(|e| { + std::io::Error::new( + e.kind(), + format!("failed to open log file `{}`: {e}", log_path.display()), + ) + })?; + + env_logger::Builder::new() + .filter_level(level) + .target(Pipe(Box::new(file))) + .try_init() + .map_err(|e| std::io::Error::other(format!("failed to initialize logger: {e}")))?; + + Ok(()) + } +} + +#[cfg(not(feature = "logger"))] +impl LogArgs<'_> { + /// Starts logging to the specified file path with the given filter level. + /// + /// # Errors + /// + /// This method will always return an error because the `logger` feature is not enabled. + pub fn start_logging(&self) -> std::io::Result<()> { + Err(std::io::Error::new( + std::io::ErrorKind::Unsupported, + "firewood-ffi was compiled without the `logger` feature. Logging is not available.", + )) + } +} diff --git a/firewood/ffi/src/metrics_setup.rs b/firewood/ffi/src/metrics_setup.rs new file mode 100644 index 000000000000..f37a61e02f38 --- /dev/null +++ b/firewood/ffi/src/metrics_setup.rs @@ -0,0 +1,284 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use parking_lot::Mutex; +use std::borrow::Cow; +use std::collections::{HashMap, HashSet}; +use std::error::Error; +use std::fmt::Write; +use std::net::Ipv6Addr; +use std::ops::Deref; +use std::sync::Arc; +use std::sync::OnceLock; +use std::sync::atomic::Ordering; +use std::time::SystemTime; + +use oxhttp::Server; +use oxhttp::model::{Body, Response, StatusCode}; +use std::net::Ipv4Addr; +use std::time::Duration; + +use chrono::{DateTime, Utc}; + +use metrics::Key; +use metrics_util::registry::{AtomicStorage, Registry}; + +static RECORDER: OnceLock = OnceLock::new(); + +/// Starts metrics recorder. +/// This happens on a per-process basis, meaning that the metrics system cannot +/// be initialized if it has already been set up in the same process. +pub fn setup_metrics() -> Result<(), Box> { + let inner = TextRecorderInner { + registry: Registry::atomic(), + help: Mutex::new(HashMap::new()), + }; + let recorder = TextRecorder { + inner: Arc::new(inner), + }; + + metrics::set_global_recorder(recorder.clone())?; + RECORDER + .set(recorder) + .map_err(|_| "recorder already initialized")?; + + Ok(()) +} + +/// Starts metrics recorder along with an exporter over a specified port. +/// This happens on a per-process basis, meaning that the metrics system +/// cannot be initialized if it has already been set up in the same process. +pub fn setup_metrics_with_exporter(metrics_port: u16) -> Result<(), Box> { + setup_metrics()?; + + let recorder = RECORDER.get().ok_or("recorder not initialized")?; + Server::new(move |request| { + if request.method() == "GET" { + Response::builder() + .status(StatusCode::OK) + .header("Content-Type", "text/plain") + .body(Body::from(recorder.stats())) + .expect("failed to build response") + } else { + Response::builder() + .status(StatusCode::METHOD_NOT_ALLOWED) + .body(Body::from("Method not allowed")) + .expect("failed to build response") + } + }) + .bind((Ipv4Addr::LOCALHOST, metrics_port)) + .bind((Ipv6Addr::LOCALHOST, metrics_port)) + .with_global_timeout(Duration::from_secs(60 * 60)) + .with_max_concurrent_connections(2) + .spawn()?; + Ok(()) +} + +/// Returns the latest metrics for this process. +pub fn gather_metrics() -> Result { + let Some(recorder) = RECORDER.get() else { + return Err(String::from("recorder not initialized")); + }; + Ok(recorder.stats()) +} + +/// Internal data structure for the [`TextRecorder`] containing the metrics registry and help text. +/// +/// This structure holds: +/// - A metrics registry that stores all counter and gauge values with atomic storage +/// - A mutex-protected map of help text for each metric name +/// +/// The atomic storage ensures thread-safe updates to metric values, while the mutex +/// protects the help text map during concurrent access. +#[derive(Debug)] +struct TextRecorderInner { + registry: Registry, + help: Mutex>, +} + +/// A metrics recorder that outputs metrics in Prometheus text exposition format. +/// +/// This recorder implements the [`metrics::Recorder`] trait and formats all +/// collected metrics as text in the format expected by Prometheus. It supports +/// counters and gauges, but not histograms. +/// +/// The recorder is thread-safe and can be shared across multiple threads. +/// All metrics are stored in memory and can be retrieved via [`Self::stats`]. +#[derive(Debug, Clone)] +struct TextRecorder { + inner: Arc, +} + +impl TextRecorder { + fn stats(&self) -> String { + let mut output = String::new(); + let systemtime_now = SystemTime::now(); + let utc_now: DateTime = systemtime_now.into(); + let epoch_duration = systemtime_now + .duration_since(SystemTime::UNIX_EPOCH) + .expect("system time is before Unix epoch"); + let epoch_ms = epoch_duration + .as_secs() + .saturating_mul(1000) + .saturating_add(u64::from(epoch_duration.subsec_millis())); + writeln!(output, "# {utc_now}").expect("write to string cannot fail"); + + let help_guard = self.inner.help.lock(); + + let counters = self.registry.get_counter_handles(); + let mut seen_counters = HashSet::new(); + for (key, counter) in counters { + let sanitized_key_name = self.sanitize_key_name(key.name()); + if !seen_counters.contains(sanitized_key_name.as_ref()) { + if let Some(help) = help_guard.get(sanitized_key_name.as_ref()) { + writeln!(output, "# HELP {sanitized_key_name} {help}").expect("write error"); + } + writeln!(output, "# TYPE {} counter", &sanitized_key_name).expect("write error"); + seen_counters.insert(sanitized_key_name.to_string()); + } + write!(output, "{sanitized_key_name}").expect("write error"); + self.write_labels(&mut output, key.labels()); + + writeln!(output, " {} {}", counter.load(Ordering::Relaxed), epoch_ms) + .expect("write error"); + } + + // Get gauge handles: Uses self.registry.get_gauge_handles() to retrieve all registered gauges + let gauges = self.registry.get_gauge_handles(); + // Track seen gauges. We don't reuse the hashset above to allow us to check for duplicates. + let mut seen_gauges = HashSet::new(); + for (key, gauge) in gauges { + let sanitized_key_name = self.sanitize_key_name(key.name()); + if !seen_gauges.contains(sanitized_key_name.as_ref()) { + // Output type declaration: Writes # TYPE {name} gauge for each unique gauge name + if let Some(help) = help_guard.get(sanitized_key_name.as_ref()) { + writeln!(output, "# HELP {sanitized_key_name} {help}").expect("write error"); + } + writeln!(output, "# TYPE {sanitized_key_name} gauge").expect("write error"); + seen_gauges.insert(sanitized_key_name.to_string()); + } + // Format metric line: Outputs the gauge name, labels (if any), current value, and timestamp + write!(output, "{sanitized_key_name}").expect("write error"); + self.write_labels(&mut output, key.labels()); + // Load gauge value: Uses gauge.load(Ordering::Relaxed) to get the current gauge value + let value = gauge.load(Ordering::Relaxed); + writeln!(output, " {} {}", f64::from_bits(value), epoch_ms).expect("write error"); + } + + // Prometheus does not support multiple TYPE declarations for the same metric, + // but we will emit them anyway, and panic if we're in debug mode. + debug_assert_eq!( + seen_gauges.intersection(&seen_counters).count(), + 0, + "duplicate name(s) for gauge and counter: {:?}", + seen_gauges.intersection(&seen_counters).collect::>() + ); + drop(help_guard); + writeln!(output).expect("write error"); + + output + } + + // helper to write labels to the output, minimizing allocations + fn write_labels<'a, I: Iterator>( + &self, + output: &mut impl Write, + labels: I, + ) { + let mut label_iter = labels.into_iter(); + if let Some(first_label) = label_iter.next() { + write!( + output, + "{{{}=\"{}\"", + first_label.key(), + first_label.value() + ) + .expect("write error"); + label_iter.for_each(|label| { + write!(output, ",{}=\"{}\"", label.key(), label.value()).expect("write error"); + }); + write!(output, "}}").expect("write error"); + } + } + + // remove dots from key names, if they are present + fn sanitize_key_name<'a>(&self, key_name: &'a str) -> Cow<'a, str> { + if key_name.contains('.') { + Cow::Owned(key_name.replace('.', "_")) + } else { + Cow::Borrowed(key_name) + } + } +} + +impl Deref for TextRecorder { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl metrics::Recorder for TextRecorder { + fn describe_counter( + &self, + key: metrics::KeyName, + _unit: Option, + description: metrics::SharedString, + ) { + self.inner + .help + .lock() + .insert(key.as_str().to_string(), description.to_string()); + } + + fn describe_gauge( + &self, + key: metrics::KeyName, + _unit: Option, + description: metrics::SharedString, + ) { + self.inner + .help + .lock() + .insert(key.as_str().to_string(), description.to_string()); + } + + fn describe_histogram( + &self, + _key: metrics::KeyName, + _unit: Option, + _description: metrics::SharedString, + ) { + } + + fn register_counter( + &self, + key: &metrics::Key, + _metadata: &metrics::Metadata<'_>, + ) -> metrics::Counter { + self.inner + .registry + .get_or_create_counter(key, |c| c.clone().into()) + } + + fn register_gauge( + &self, + key: &metrics::Key, + _metadata: &metrics::Metadata<'_>, + ) -> metrics::Gauge { + self.inner + .registry + .get_or_create_gauge(key, |c| c.clone().into()) + } + + fn register_histogram( + &self, + key: &metrics::Key, + _metadata: &metrics::Metadata<'_>, + ) -> metrics::Histogram { + self.inner + .registry + .get_or_create_histogram(key, |c| c.clone().into()) + } +} diff --git a/firewood/ffi/src/proofs.rs b/firewood/ffi/src/proofs.rs new file mode 100644 index 000000000000..8368f035fd5b --- /dev/null +++ b/firewood/ffi/src/proofs.rs @@ -0,0 +1,8 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +mod change; +mod range; + +pub use self::change::*; +pub use self::range::*; diff --git a/firewood/ffi/src/proofs/change.rs b/firewood/ffi/src/proofs/change.rs new file mode 100644 index 000000000000..ae38d9ad99af --- /dev/null +++ b/firewood/ffi/src/proofs/change.rs @@ -0,0 +1,259 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::{ + BorrowedBytes, CResult, ChangeProofResult, DatabaseHandle, HashKey, HashResult, Maybe, + NextKeyRangeResult, OwnedBytes, ValueResult, VoidResult, +}; + +/// Arguments for creating a change proof. +#[derive(Debug)] +#[repr(C)] +pub struct CreateChangeProofArgs<'a> { + /// The root hash of the starting revision. This must be provided. + /// If the root is not found in the database, the function will return + /// [`ChangeProofResult::RevisionNotFound`]. + pub start_root: HashKey, + /// The root hash of the ending revision. This must be provided. + /// If the root is not found in the database, the function will return + /// [`ChangeProofResult::RevisionNotFound`]. + pub end_root: HashKey, + /// The start key of the range to create the proof for. If `None`, the range + /// starts from the beginning of the keyspace. + pub start_key: Maybe>, + /// The end key of the range to create the proof for. If `None`, the range + /// ends at the end of the keyspace or until `max_length` items have been + /// included in the proof. + pub end_key: Maybe>, + /// The maximum number of key/value pairs to include in the proof. If the + /// range contains more items than this, the proof will be truncated. If + /// `0`, there is no limit. + pub max_length: u32, +} + +/// Arguments for verifying a change proof. +#[derive(Debug)] +#[repr(C)] +pub struct VerifyChangeProofArgs<'a> { + /// The change proof to verify. If null, the function will return + /// [`VoidResult::NullHandlePointer`]. We need a mutable reference to + /// update the validation context. + pub proof: Option<&'a mut ChangeProofContext>, + /// The root hash of the starting revision. This must match the starting + /// root of the proof. + pub start_root: HashKey, + /// The root hash of the ending revision. This must match the ending root of + /// the proof. + pub end_root: HashKey, + /// The lower bound of the key range that the proof is expected to cover. If + /// `None`, the proof is expected to cover from the start of the keyspace. + pub start_key: Maybe>, + /// The upper bound of the key range that the proof is expected to cover. If + /// `None`, the proof is expected to cover to the end of the keyspace. + pub end_key: Maybe>, + /// The maximum number of key/value pairs that the proof is expected to cover. + /// If the proof contains more items than this, it is considered invalid. If + /// `0`, there is no limit. + pub max_length: u32, +} + +/// FFI context for a parsed or generated change proof. +#[derive(Debug)] +pub struct ChangeProofContext { + _proof: (), // currently not implemented + _validation_context: (), // placeholder for future use + _commit_context: (), // placeholder for future use +} + +/// A key range that should be fetched to continue iterating through a range +/// or change proof that was truncated. Represents a half-open range +/// `[start_key, end_key)`. If `end_key` is `None`, the range is unbounded +/// and continues to the end of the keyspace. +#[derive(Debug)] +#[repr(C)] +pub struct NextKeyRange { + /// The start key of the next range to fetch. + pub start_key: OwnedBytes, + + /// If set, a non-inclusive upper bound for the next range to fetch. If not + /// set, the range is unbounded (this is the final range). + pub end_key: Maybe, +} + +/// Create a change proof for the given range of keys between two roots. +/// +/// # Arguments +/// +/// - `db` - The database to create the proof from. +/// - `args` - The arguments for creating the change proof. +/// +/// # Returns +/// +/// - [`ChangeProofResult::NullHandlePointer`] if the caller provided a null pointer. +/// - [`ChangeProofResult::RevisionNotFound`] if the caller provided a start or end root +/// that was not found in the database. The missing root hash is included in the result. +/// The start root is checked first, and if both are missing, only the start root is +/// reported. +/// - [`ChangeProofResult::Ok`] containing a pointer to the `ChangeProofContext` if the proof +/// was successfully created. +/// - [`ChangeProofResult::Err`] containing an error message if the proof could not be created. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_db_change_proof( + _db: Option<&DatabaseHandle>, + _args: CreateChangeProofArgs, +) -> ChangeProofResult { + CResult::from_err("not yet implemented") +} + +/// Verify a change proof and prepare a proposal to later commit or drop. +/// +/// # Arguments +/// +/// - `db` - The database to verify the proof against. +/// - `args` - The arguments for verifying the change proof. +/// +/// # Returns +/// +/// - [`VoidResult::NullHandlePointer`] if the caller provided a null pointer to either +/// the database or the proof. +/// - [`VoidResult::Ok`] if the proof was successfully verified. +/// - [`VoidResult::Err`] containing an error message if the proof could not be verified +/// +/// # Thread Safety +/// +/// It is not safe to call this function concurrently with the same proof context +/// nor is it safe to call any other function that accesses the same proof context +/// concurrently. The caller must ensure exclusive access to the proof context +/// for the duration of the call. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_db_verify_change_proof( + _db: Option<&DatabaseHandle>, + _args: VerifyChangeProofArgs, +) -> VoidResult { + CResult::from_err("not yet implemented") +} + +/// Verify and commit a change proof to the database. +/// +/// If the proof has already been verified, the previously prepared proposal will be +/// committed instead of re-verifying. If the proof has not been verified, it will be +/// verified now. If the prepared proposal is no longer valid (e.g., the database has +/// changed since it was prepared), a new proposal will be created and committed. +/// +/// The proof context will be updated with additional information about the committed +/// proof to allow for optimized introspection of the committed changes. +/// +/// # Arguments +/// +/// - `db` - The database to commit the changes to. +/// - `args` - The arguments for verifying the change proof. +/// +/// # Returns +/// +/// - [`HashResult::NullHandlePointer`] if the caller provided a null pointer to either +/// the database or the proof. +/// - [`HashResult::None`] if the proof resulted in an empty database (i.e., all keys were deleted). +/// - [`HashResult::Some`] containing the new root hash if the proof was successfully verified +/// - [`HashResult::Err`] containing an error message if the proof could not be verified or committed. +/// +/// # Thread Safety +/// +/// It is not safe to call this function concurrently with the same proof context +/// nor is it safe to call any other function that accesses the same proof context +/// concurrently. The caller must ensure exclusive access to the proof context +/// for the duration of the call. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_db_verify_and_commit_change_proof( + _db: Option<&DatabaseHandle>, + _args: VerifyChangeProofArgs, +) -> HashResult { + CResult::from_err("not yet implemented") +} + +/// Returns the next key range that should be fetched after processing the +/// current set of operations in a change proof that was truncated. +/// +/// Can be called multiple times to get subsequent disjoint key ranges until +/// it returns [`NextKeyRangeResult::None`], indicating there are no more keys to +/// fetch and the proof is complete. +/// +/// # Arguments +/// +/// - `proof` - A [`ChangeProofContext`] previously returned from the create +/// methods and has been prepared into a proposal or already committed. +/// +/// # Returns +/// +/// - [`NextKeyRangeResult::NullHandlePointer`] if the caller provided a null pointer. +/// - [`NextKeyRangeResult::NotPrepared`] if the proof has not been prepared into +/// a proposal nor committed to the database. +/// - [`NextKeyRangeResult::None`] if there are no more keys to fetch. +/// - [`NextKeyRangeResult::Some`] containing the next key range to fetch. +/// - [`NextKeyRangeResult::Err`] containing an error message if the next key range +/// could not be determined. +/// +/// # Thread Safety +/// +/// It is not safe to call this function concurrently with the same proof context +/// nor is it safe to call any other function that accesses the same proof context +/// concurrently. The caller must ensure exclusive access to the proof context +/// for the duration of the call. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_change_proof_find_next_key( + _proof: Option<&mut ChangeProofContext>, +) -> NextKeyRangeResult { + CResult::from_err("not yet implemented") +} + +/// Serialize a `ChangeProof` to bytes. +/// +/// # Arguments +/// +/// - `proof` - A [`ChangeProofContext`] previously returned from the create +/// method. If from a parsed proof, the proof will not be verified before +/// serialization. +/// +/// # Returns +/// +/// - [`ValueResult::NullHandlePointer`] if the caller provided a null pointer. +/// - [`ValueResult::Some`] containing the serialized bytes if successful. +/// - [`ValueResult::Err`] if the caller provided a null pointer. +/// +/// The other [`ValueResult`] variants are not used. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_change_proof_to_bytes(_proof: Option<&ChangeProofContext>) -> ValueResult { + CResult::from_err("not yet implemented") +} + +/// Deserialize a `ChangeProof` from bytes. +/// +/// # Arguments +/// +/// * `bytes` - The bytes to deserialize the proof from. +/// +/// # Returns +/// +/// - [`ChangeProofResult::NullHandlePointer`] if the caller provided a null or zero-length slice. +/// - [`ChangeProofResult::Ok`] containing a pointer to the `ChangeProofContext` if the proof +/// was successfully parsed. This does not imply that the proof is valid, only that it is +/// well-formed. The verify method must be called to ensure the proof is cryptographically valid. +/// - [`ChangeProofResult::Err`] containing an error message if the proof could not be parsed. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_change_proof_from_bytes(_bytes: BorrowedBytes) -> ChangeProofResult { + CResult::from_err("not yet implemented") +} + +/// Frees the memory associated with a `ChangeProofContext`. +/// +/// # Arguments +/// +/// * `proof` - The `ChangeProofContext` to free, previously returned from any Rust function. +/// +/// # Returns +/// +/// - [`VoidResult::Ok`] if the memory was successfully freed. +/// - [`VoidResult::Err`] if the process panics while freeing the memory. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_free_change_proof(proof: Option>) -> VoidResult { + crate::invoke_with_handle(proof, drop) +} diff --git a/firewood/ffi/src/proofs/range.rs b/firewood/ffi/src/proofs/range.rs new file mode 100644 index 000000000000..1bd76b705871 --- /dev/null +++ b/firewood/ffi/src/proofs/range.rs @@ -0,0 +1,498 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::num::NonZeroUsize; + +use firewood::{ + logger::warn, + v2::api::{self, DbView, FrozenRangeProof, HashKey}, +}; + +use crate::{ + BorrowedBytes, DatabaseHandle, HashResult, Maybe, NextKeyRange, NextKeyRangeResult, + RangeProofResult, ValueResult, VoidResult, +}; + +/// Arguments for creating a range proof. +#[derive(Debug)] +#[repr(C)] +pub struct CreateRangeProofArgs<'a> { + /// The root hash of the revision to prove. + pub root: crate::HashKey, + /// The start key of the range to prove. If `None`, the range starts from the + /// beginning of the keyspace. + /// + /// The start key must be less than the end key if both are provided. + pub start_key: Maybe>, + /// The end key of the range to prove. If `None`, the range ends at the end + /// of the keyspace or until `max_length` items have been been included in + /// the proof. + /// + /// If provided, end key is inclusive if not truncated. Otherwise, the end + /// key will be the final key in the returned key-value pairs. + pub end_key: Maybe>, + /// The maximum number of key/value pairs to include in the proof. If the + /// range contains more items than this, the proof will be truncated. If + /// `0`, there is no limit. + pub max_length: u32, +} + +/// Arguments for verifying a range proof. +#[derive(Debug)] +#[repr(C)] +pub struct VerifyRangeProofArgs<'a, 'db> { + /// The range proof to verify. If null, the function will return + /// [`VoidResult::NullHandlePointer`]. We need a mutable reference to + /// update the validation context. + pub proof: Option<&'a mut RangeProofContext<'db>>, + /// The root hash to verify the proof against. This must match the calculated + /// hash of the root of the proof. + pub root: crate::HashKey, + /// The lower bound of the key range that the proof is expected to cover. If + /// `None`, the proof is expected to cover from the start of the keyspace. + /// + /// Must be present if the range proof contains a lower bound proof and must + /// be absent if the range proof does not contain a lower bound proof. + pub start_key: Maybe>, + /// The upper bound of the key range that the proof is expected to cover. If + /// `None`, the proof is expected to cover to the end of the keyspace. + /// + /// This is ignored if the proof is truncated and does not cover the full, + /// in which case the upper bound key is the final key in the key-value pairs. + pub end_key: Maybe>, + /// The maximum number of key/value pairs that the proof is expected to cover. + /// If the proof contains more items than this, it is considered invalid. If + /// `0`, there is no limit. + pub max_length: u32, +} + +/// FFI context for for a parsed or generated range proof. +#[derive(Debug)] +pub struct RangeProofContext<'db> { + proof: FrozenRangeProof, + state: RangeProofState<'db>, +} + +#[derive(Debug)] +enum RangeProofState<'db> { + Unverified, + Verified, + Proposed(crate::ProposalHandle<'db>), + Committed(Option), +} + +impl From for RangeProofContext<'_> { + fn from(proof: FrozenRangeProof) -> Self { + Self { + proof, + state: RangeProofState::Unverified, + } + } +} + +impl<'db> RangeProofState<'db> { + const fn is_verified(&self) -> bool { + !matches!(self, Self::Unverified) + } + + const fn is_proposed_or_committed(&self) -> bool { + matches!(self, Self::Proposed(_) | Self::Committed(_)) + } + + const fn is_committed(&self) -> bool { + matches!(self, Self::Committed(_)) + } + + fn take_proposal(&mut self) -> Option> { + match std::mem::replace(self, Self::Unverified) { + Self::Proposed(proposal) => Some(proposal), + other => { + // put it back (so we don't need to write unsafe/panicking code) + *self = other; + None + } + } + } + + fn root_hash(&self) -> Result, api::Error> { + match self { + Self::Committed(root) => Ok(root.clone()), + Self::Proposed(proposal) => proposal.root_hash(), + _ => Ok(None), + } + } +} + +impl<'db> RangeProofContext<'db> { + fn verify( + &mut self, + _root: HashKey, + _start_key: Option<&[u8]>, + _end_key: Option<&[u8]>, + _max_length: Option, + ) -> Result<(), api::Error> { + if !self.state.is_verified() { + return Ok(()); + } + + warn!("range proof verification not yet implemented"); + self.state = RangeProofState::Verified; + Ok(()) + } + + fn verify_and_propose( + &mut self, + db: &'db crate::DatabaseHandle, + root: HashKey, + start_key: Option<&[u8]>, + end_key: Option<&[u8]>, + max_length: Option, + ) -> Result<(), api::Error> { + if self.state.is_proposed_or_committed() { + return Ok(()); + } + + self.verify(root, start_key, end_key, max_length)?; + + let proposal = db.merge_key_value_range(start_key, end_key, self.proof.key_values())?; + self.state = RangeProofState::Proposed(proposal.handle); + + Ok(()) + } + + fn verify_and_commit( + &mut self, + db: &'db crate::DatabaseHandle, + root: HashKey, + start_key: Option<&[u8]>, + end_key: Option<&[u8]>, + max_length: Option, + ) -> Result, api::Error> { + if self.state.is_committed() { + return self.state.root_hash(); + } + + self.verify(root, start_key, end_key, max_length)?; + + let proposal_handle = if let Some(proposal) = self.state.take_proposal() { + proposal + } else { + db.merge_key_value_range(start_key, end_key, self.proof.key_values())? + .handle + }; + + let hash = proposal_handle.commit_proposal(|commit_time| { + metrics::counter!("firewood.ffi.commit_ms").increment(commit_time.as_millis()); + metrics::counter!("firewood.ffi.merge").increment(1); + })?; + + self.state = RangeProofState::Committed(hash.clone()); + Ok(hash) + } +} + +/// Generate a range proof for the given range of keys for the latest revision. +/// +/// # Arguments +/// +/// - `db` - The database to create the proof from. +/// - `args` - The arguments for creating the range proof. +/// +/// # Returns +/// +/// - [`RangeProofResult::NullHandlePointer`] if the caller provided a null pointer. +/// - [`RangeProofResult::RevisionNotFound`] if the caller provided a root that was +/// not found in the database. The missing root hash is included in the result. +/// - [`RangeProofResult::Ok`] containing a pointer to the `RangeProofContext` if the proof +/// was successfully created. +/// - [`RangeProofResult::Err`] containing an error message if the proof could not be created. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_db_range_proof( + db: Option<&DatabaseHandle>, + args: CreateRangeProofArgs, +) -> RangeProofResult<'static> { + // static lifetime is safe because the returned `RangeProofResult` does not + // retain a reference to the provided database handle. + + crate::invoke_with_handle(db, |db| { + let view = db.get_root(args.root.into())?; + view.range_proof( + args.start_key + .as_ref() + .map(BorrowedBytes::as_slice) + .into_option(), + args.end_key + .as_ref() + .map(BorrowedBytes::as_slice) + .into_option(), + NonZeroUsize::new(args.max_length as usize), + ) + }) +} + +/// Verify a range proof against the given start and end keys and root hash. The +/// proof will be updated with the validation context if the proof is valid to +/// avoid re-verifying it during commit. +/// +/// # Arguments +/// +/// - `args` - The arguments for verifying the range proof. +/// +/// # Returns +/// +/// - [`VoidResult::NullHandlePointer`] if the caller provided a null pointer to the proof. +/// - [`VoidResult::Ok`] if the proof was successfully verified. +/// - [`VoidResult::Err`] containing an error message if the proof could not be verified. +/// +/// # Thread Safety +/// +/// It is not safe to call this function concurrently with the same proof context +/// nor is it safe to call any other function that accesses the same proof context +/// concurrently. The caller must ensure exclusive access to the proof context +/// for the duration of the call. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_range_proof_verify(args: VerifyRangeProofArgs) -> VoidResult { + let VerifyRangeProofArgs { + proof, + root, + start_key, + end_key, + max_length, + } = args; + + crate::invoke_with_handle(proof, |ctx| { + let start_key = start_key.into_option(); + let end_key = end_key.into_option(); + ctx.verify( + root.into(), + start_key.as_deref(), + end_key.as_deref(), + NonZeroUsize::new(max_length as usize), + ) + }) +} + +/// Verify a range proof and prepare a proposal to later commit or drop. If the +/// proof has already been verified, the cached validation context will be used +/// to avoid re-verifying the proof. +/// +/// # Arguments +/// +/// - `db` - The database to verify the proof against. +/// - `args` - The arguments for verifying the range proof. +/// +/// # Returns +/// +/// - [`VoidResult::NullHandlePointer`] if the caller provided a null pointer to either +/// the database or the proof. +/// - [`VoidResult::Ok`] if the proof was successfully verified. +/// - [`VoidResult::Err`] containing an error message if the proof could not be verified +/// +/// # Thread Safety +/// +/// It is not safe to call this function concurrently with the same proof context +/// nor is it safe to call any other function that accesses the same proof context +/// concurrently. The caller must ensure exclusive access to the proof context +/// for the duration of the call. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_db_verify_range_proof<'db>( + db: Option<&'db DatabaseHandle>, + args: VerifyRangeProofArgs<'_, 'db>, +) -> VoidResult { + let VerifyRangeProofArgs { + proof, + root, + start_key, + end_key, + max_length, + } = args; + + let handle = db.and_then(|db| proof.map(|p| (db, p))); + + crate::invoke_with_handle(handle, |(db, ctx)| { + let start_key = start_key.into_option(); + let end_key = end_key.into_option(); + ctx.verify_and_propose( + db, + root.into(), + start_key.as_deref(), + end_key.as_deref(), + NonZeroUsize::new(max_length as usize), + ) + }) +} + +/// Verify and commit a range proof to the database. +/// +/// If a proposal was previously prepared by a call to [`fwd_db_verify_range_proof`], +/// it will be committed instead of re-verifying the proof. If the proof has not yet +/// been verified, it will be verified now. If the prepared proposal is no longer +/// valid (e.g., the database has changed since it was prepared), a new proposal +/// will be created and committed. +/// +/// The proof context will be updated with additional information about the committed +/// proof to allow for optimized introspection of the committed changes. +/// +/// # Arguments +/// +/// - `db` - The database to commit the changes to. +/// - `args` - The arguments for verifying the range proof. +/// +/// # Returns +/// +/// - [`HashResult::NullHandlePointer`] if the caller provided a null pointer to either +/// the database or the proof. +/// - [`HashResult::None`] if the proof resulted in an empty database (i.e., all keys were deleted). +/// - [`HashResult::Some`] containing the new root hash if the proof was successfully verified +/// - [`HashResult::Err`] containing an error message if the proof could not be verified or committed. +/// +/// # Thread Safety +/// +/// It is not safe to call this function concurrently with the same proof context +/// nor is it safe to call any other function that accesses the same proof context +/// concurrently. The caller must ensure exclusive access to the proof context +/// for the duration of the call. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_db_verify_and_commit_range_proof<'db>( + db: Option<&'db DatabaseHandle>, + args: VerifyRangeProofArgs<'_, 'db>, +) -> HashResult { + let VerifyRangeProofArgs { + proof, + root, + start_key, + end_key, + max_length, + } = args; + + let handle = db.and_then(|db| proof.map(|p| (db, p))); + + crate::invoke_with_handle(handle, |(db, ctx)| { + let start_key = start_key.into_option(); + let end_key = end_key.into_option(); + ctx.verify_and_commit( + db, + root.into(), + start_key.as_deref(), + end_key.as_deref(), + NonZeroUsize::new(max_length as usize), + ) + }) +} + +/// Returns the next key range that should be fetched after processing the +/// current set of key-value pairs in a range proof that was truncated. +/// +/// Can be called multiple times to get subsequent disjoint key ranges until +/// it returns [`NextKeyRangeResult::None`], indicating there are no more keys to +/// fetch and the proof is complete. +/// +/// # Arguments +/// +/// - `proof` - A [`RangeProofContext`] previously returned from the create +/// methods and has been prepared into a proposal or already committed. +/// +/// # Returns +/// +/// - [`NextKeyRangeResult::NullHandlePointer`] if the caller provided a null pointer. +/// - [`NextKeyRangeResult::NotPrepared`] if the proof has not been prepared into +/// a proposal nor committed to the database. +/// - [`NextKeyRangeResult::None`] if there are no more keys to fetch. +/// - [`NextKeyRangeResult::Some`] containing the next key range to fetch. +/// - [`NextKeyRangeResult::Err`] containing an error message if the next key range +/// could not be determined. +/// +/// # Thread Safety +/// +/// It is not safe to call this function concurrently with the same proof context +/// nor is it safe to call any other function that accesses the same proof context +/// concurrently. The caller must ensure exclusive access to the proof context +/// for the duration of the call. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_range_proof_find_next_key( + proof: Option<&mut RangeProofContext>, +) -> NextKeyRangeResult { + // TODO(#352): proper implementation, this naively retuns the last key in + // in the range, which is correct, but not sufficient. + crate::invoke_with_handle(proof, |ctx| match ctx.state { + RangeProofState::Unverified | RangeProofState::Verified => NextKeyRangeResult::NotPrepared, + RangeProofState::Proposed(_) | RangeProofState::Committed(_) => { + if ctx.proof.end_proof().is_empty() { + // unbounded, so we are done + NextKeyRangeResult::None + } else { + match ctx.proof.key_values().last() { + Some((key, _)) => NextKeyRangeResult::Some(NextKeyRange { + start_key: key.clone().into(), + end_key: None.into(), + }), + None => { + // no key-values in the proof, so we are done + NextKeyRangeResult::None + } + } + } + } + }) +} + +/// Serialize a `RangeProof` to bytes. +/// +/// # Arguments +/// +/// - `proof` - A [`RangeProofContext`] previously returned from the create +/// method. If from a parsed proof, the proof will not be verified before +/// serialization. +/// +/// # Returns +/// +/// - [`ValueResult::NullHandlePointer`] if the caller provided a null pointer. +/// - [`ValueResult::Some`] containing the serialized bytes if successful. +/// - [`ValueResult::Err`] if the caller provided a null pointer. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_range_proof_to_bytes(proof: Option<&RangeProofContext>) -> ValueResult { + crate::invoke_with_handle(proof, |ctx| { + let mut vec = Vec::new(); + ctx.proof.write_to_vec(&mut vec); + vec + }) +} + +/// Deserialize a `RangeProof` from bytes. +/// +/// # Arguments +/// +/// - `bytes` - The bytes to deserialize the proof from. +/// +/// # Returns +/// +/// - [`RangeProofResult::NullHandlePointer`] if the caller provided a null or zero-length slice. +/// - [`RangeProofResult::Ok`] containing a pointer to the `RangeProofContext` if the proof +/// was successfully parsed. This does not imply that the proof is valid, only that it is +/// well-formed. The verify method must be called to ensure the proof is cryptographically valid. +/// - [`RangeProofResult::Err`] containing an error message if the proof could not be parsed. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_range_proof_from_bytes( + bytes: BorrowedBytes<'_>, +) -> RangeProofResult<'static> { + crate::invoke(move || { + FrozenRangeProof::from_slice(&bytes).map_err(|err| { + api::Error::ProofError(firewood::proof::ProofError::Deserialization(err)) + }) + }) +} + +/// Frees the memory associated with a `RangeProofContext`. +/// +/// # Arguments +/// +/// * `proof` - The `RangeProofContext` to free, previously returned from any Rust function. +/// +/// # Returns +/// +/// - [`VoidResult::Ok`] if the memory was successfully freed. +/// - [`VoidResult::Err`] if the process panics while freeing the memory. +#[unsafe(no_mangle)] +pub extern "C" fn fwd_free_range_proof(proof: Option>) -> VoidResult { + crate::invoke_with_handle(proof, drop) +} diff --git a/firewood/ffi/src/proposal.rs b/firewood/ffi/src/proposal.rs new file mode 100644 index 000000000000..cbceefc3ed55 --- /dev/null +++ b/firewood/ffi/src/proposal.rs @@ -0,0 +1,200 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use firewood::v2::api::{self, BoxKeyValueIter, DbView, HashKey, IntoBatchIter, Proposal as _}; + +use crate::iterator::CreateIteratorResult; +use metrics::counter; + +/// An opaque wrapper around a Proposal that also retains a reference to the +/// database handle it was created from. +#[derive(Debug)] +pub struct ProposalHandle<'db> { + hash_key: Option, + proposal: firewood::db::Proposal<'db>, + handle: &'db crate::DatabaseHandle, +} + +impl<'db> DbView for ProposalHandle<'db> { + type Iter<'view> + = as DbView>::Iter<'view> + where + Self: 'view; + + fn root_hash(&self) -> Result, api::Error> { + self.proposal.root_hash() + } + + fn val(&self, key: K) -> Result, api::Error> { + self.proposal.val(key) + } + + fn single_key_proof(&self, key: K) -> Result { + self.proposal.single_key_proof(key) + } + + fn range_proof( + &self, + first_key: Option, + last_key: Option, + limit: Option, + ) -> Result { + self.proposal.range_proof(first_key, last_key, limit) + } + + fn iter_option( + &self, + first_key: Option, + ) -> Result, api::Error> { + self.proposal.iter_option(first_key) + } +} + +impl ProposalHandle<'_> { + /// Returns the root hash of the proposal. + #[must_use] + pub fn hash_key(&self) -> Option { + self.hash_key.clone().map(Into::into) + } + + /// Consume and commit a proposal. + /// + /// # Arguments + /// + /// - `token`: An callback function that will be called with the duration + /// of the commit operation. This will be dropped without being called if + /// the commit fails. + /// + /// # Errors + /// + /// This function will return an error if committing the proposal fails or if the + /// proposal is empty. + pub fn commit_proposal( + self, + token: impl FnOnce(coarsetime::Duration), + ) -> Result, api::Error> { + let ProposalHandle { + hash_key, + proposal, + handle, + } = self; + + // promote the proposal to the handle's cached view so that it can be used + // for future reads while the proposal is being committed + if let Some(ref hash_key) = hash_key { + _ = handle.get_root(hash_key.clone()); + } + + let start_time = coarsetime::Instant::now(); + proposal.commit()?; + let commit_time = start_time.elapsed(); + + // clear the cached view so that it does not hold onto the proposal view + handle.clear_cached_view(); + + token(commit_time); + + Ok(hash_key) + } + + /// Creates an iterator on the proposal starting from the given key. + #[must_use] + #[allow(clippy::missing_panics_doc)] + pub fn iter_from(&self, first_key: Option<&[u8]>) -> CreateIteratorResult<'_> { + let it = self + .iter_option(first_key) + .expect("infallible; see issue #1329"); + CreateIteratorResult((Box::new(it) as BoxKeyValueIter<'_>).into()) + } +} +#[derive(Debug)] +pub struct CreateProposalResult<'db> { + pub handle: ProposalHandle<'db>, + pub start_time: coarsetime::Instant, +} + +impl<'db> CreateProposalResult<'db> { + pub(crate) fn new( + handle: &'db crate::DatabaseHandle, + f: impl FnOnce() -> Result, api::Error>, + ) -> Result { + let start_time = coarsetime::Instant::now(); + let proposal = f()?; + let propose_time = start_time.elapsed(); + counter!("firewood.ffi.propose_ms").increment(propose_time.as_millis()); + counter!("firewood.ffi.propose").increment(1); + + let hash_key = proposal.root_hash()?; + + Ok(CreateProposalResult { + handle: ProposalHandle { + hash_key, + proposal, + handle, + }, + start_time, + }) + } +} + +/// A trait that abstracts over database handles and proposal handles for creating proposals. +/// +/// This trait allows functions to work with both [`DatabaseHandle`] and [`ProposalHandle`] +/// uniformly when creating new proposals. It provides a common interface for: +/// - Getting the underlying database handle +/// - Creating proposals from key-value pairs +/// - Creating proposal handles with timing information +/// +/// This abstraction enables proposal chaining (creating proposals on top of other proposals) +/// while maintaining a consistent API. +/// +/// [`DatabaseHandle`]: crate::DatabaseHandle +pub trait CView<'db> { + /// Returns a reference to the database handle that is ultimately used to + /// create the proposal. For the database handle, this returns itself. For, + /// a proposal handle, this returns the handle that was used to create the + /// proposal. + fn handle(&self) -> &'db crate::DatabaseHandle; + + /// Create a [`firewood::db::Proposal`] with the provided key-value pairs. + /// + /// # Errors + /// + /// This function will return a database error if the proposal could not be + /// created. + fn create_proposal( + self, + values: impl IntoBatchIter, + ) -> Result, api::Error>; + + /// Create a [`ProposalHandle`] from the values and return it with timing + /// information. + /// + /// # Errors + /// + /// This function will return a database error if the proposal could not be + /// created or if the proposal is empty. + fn create_proposal_handle( + self, + values: impl IntoBatchIter, + ) -> Result, api::Error> + where + Self: Sized, + { + let handle = self.handle(); + CreateProposalResult::new(handle, || self.create_proposal(values)) + } +} + +impl<'db> CView<'db> for &ProposalHandle<'db> { + fn handle(&self) -> &'db crate::DatabaseHandle { + self.handle + } + + fn create_proposal( + self, + values: impl IntoBatchIter, + ) -> Result, api::Error> { + self.proposal.propose(values) + } +} diff --git a/firewood/ffi/src/revision.rs b/firewood/ffi/src/revision.rs new file mode 100644 index 000000000000..eb73f15e12cb --- /dev/null +++ b/firewood/ffi/src/revision.rs @@ -0,0 +1,74 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::CreateIteratorResult; +use firewood::v2::api; +use firewood::v2::api::{ArcDynDbView, BoxKeyValueIter, DbView, HashKey}; + +#[derive(Debug)] +pub struct RevisionHandle { + view: ArcDynDbView, +} + +impl RevisionHandle { + /// Creates a new revision handle for the provided database view. + pub(crate) fn new(view: ArcDynDbView) -> RevisionHandle { + RevisionHandle { view } + } + + /// Creates an iterator on the revision starting from the given key. + #[must_use] + #[allow(clippy::missing_panics_doc)] + pub fn iter_from(&self, first_key: Option<&[u8]>) -> CreateIteratorResult<'_> { + let it = self + .view + .iter_option(first_key) + .expect("infallible; see issue #1329"); + CreateIteratorResult(it.into()) + } +} + +impl DbView for RevisionHandle { + type Iter<'view> + = BoxKeyValueIter<'view> + where + Self: 'view; + + fn root_hash(&self) -> Result, api::Error> { + self.view.root_hash() + } + + fn val(&self, key: K) -> Result, api::Error> { + self.view.val(key.as_ref()) + } + + fn single_key_proof(&self, key: K) -> Result { + self.view.single_key_proof(key.as_ref()) + } + + fn range_proof( + &self, + first_key: Option, + last_key: Option, + limit: Option, + ) -> Result { + self.view.range_proof( + first_key.as_ref().map(AsRef::as_ref), + last_key.as_ref().map(AsRef::as_ref), + limit, + ) + } + + fn iter_option( + &self, + first_key: Option, + ) -> Result, api::Error> { + self.view.iter_option(first_key.as_ref().map(AsRef::as_ref)) + } +} + +#[derive(Debug)] +pub struct GetRevisionResult { + pub handle: RevisionHandle, + pub root_hash: HashKey, +} diff --git a/firewood/ffi/src/value.rs b/firewood/ffi/src/value.rs new file mode 100644 index 000000000000..c80f2a610380 --- /dev/null +++ b/firewood/ffi/src/value.rs @@ -0,0 +1,87 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +mod borrowed; +mod display_hex; +mod hash_key; +mod kvp; +mod owned; +mod results; + +pub use self::borrowed::{BorrowedBytes, BorrowedKeyValuePairs, BorrowedSlice}; +use self::display_hex::DisplayHex; +pub use self::hash_key::HashKey; +pub use self::kvp::{KeyValuePair, OwnedKeyValueBatch, OwnedKeyValuePair}; +pub use self::owned::{OwnedBytes, OwnedSlice}; +pub(crate) use self::results::{CResult, NullHandleResult}; +pub use self::results::{ + ChangeProofResult, HandleResult, HashResult, IteratorResult, KeyValueBatchResult, + KeyValueResult, NextKeyRangeResult, ProposalResult, RangeProofResult, RevisionResult, + ValueResult, VoidResult, +}; + +/// Maybe is a C-compatible optional type using a tagged union pattern. +/// +/// FFI methods and types can use this to represent optional values where `Optional` +/// does not work due to it not having a C-compatible layout. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(C)] +pub enum Maybe { + /// No value present. + None, + /// A value is present. + Some(T), +} + +impl Maybe { + /// Returns true if the `Maybe` contains a value. + pub const fn is_some(&self) -> bool { + matches!(self, Maybe::Some(_)) + } + + /// Returns true if the `Maybe` does not contain a value. + pub const fn is_none(&self) -> bool { + matches!(self, Maybe::None) + } + + /// Converts from `&Maybe` to `Maybe<&T>`. + pub const fn as_ref(&self) -> Maybe<&T> { + match self { + Maybe::None => Maybe::None, + Maybe::Some(v) => Maybe::Some(v), + } + } + + /// Converts from `&mut Maybe` to `Maybe<&mut T>`. + pub const fn as_mut(&mut self) -> Maybe<&mut T> { + match self { + Maybe::None => Maybe::None, + Maybe::Some(v) => Maybe::Some(v), + } + } + + /// Maps a `Maybe` to `Maybe` by applying a function to a contained value. + pub fn map U>(self, f: F) -> Maybe { + match self { + Maybe::None => Maybe::None, + Maybe::Some(v) => Maybe::Some(f(v)), + } + } + + /// Converts from `Maybe` to `Option`. + pub fn into_option(self) -> Option { + match self { + Maybe::None => None, + Maybe::Some(v) => Some(v), + } + } +} + +impl From> for Maybe { + fn from(opt: Option) -> Self { + match opt { + None => Maybe::None, + Some(v) => Maybe::Some(v), + } + } +} diff --git a/firewood/ffi/src/value/borrowed.rs b/firewood/ffi/src/value/borrowed.rs new file mode 100644 index 000000000000..39eb86a87a18 --- /dev/null +++ b/firewood/ffi/src/value/borrowed.rs @@ -0,0 +1,177 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::fmt; + +use crate::value::KeyValuePair; + +/// A type alias for a borrowed byte slice. +/// +/// C callers can use this to pass in a byte slice that will not be freed by Rust +/// code. +/// +/// C callers must ensure that the pointer, if not null, points to a valid slice +/// of bytes of length `len`. C callers must also ensure that the slice is valid +/// for the duration of the C function call that was passed this slice. +pub type BorrowedBytes<'a> = BorrowedSlice<'a, u8>; + +/// A type alias for a borrowed slice of [`KeyValuePair`]s. +/// +/// C callers can use this to pass in a slice of key-value pairs that will not +/// be freed by Rust code. +/// +/// C callers must ensure that the pointer, if not null, points to a valid slice +/// of key-value pairs of length `len`. C callers must also ensure that the slice +/// is valid for the duration of the C function call that was passed this slice. +pub type BorrowedKeyValuePairs<'a> = BorrowedSlice<'a, KeyValuePair<'a>>; + +/// A borrowed byte slice. Used to represent data that was passed in from C +/// callers and will not be freed or retained by Rust code. +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct BorrowedSlice<'a, T> { + /// A pointer to the slice of bytes. This can be null if the slice is empty. + /// + /// If the pointer is not null, it must point to a valid slice of `len` + /// elements sized and aligned for `T`. + /// + /// As a note, [`NonNull`] is not appropriate here because [`NonNull`] pointer + /// provenance requires mutable access to the pointer, which is not an invariant + /// we want to enforce here. We want (and require) the pointer to be immutable. + /// + /// [`NonNull`]: std::ptr::NonNull + ptr: *const T, + /// The length of the slice. It is ignored if the pointer is null; however, + /// if the pointer is not null, it must be equal to the number of elements + /// pointed to by `ptr`. + len: usize, + /// This is not exposed to C callers, but is used by Rust to track the + /// lifetime of the slice passed in to C functions. + marker: std::marker::PhantomData<&'a [T]>, +} + +impl<'a, T> BorrowedSlice<'a, T> { + /// Creates a slice from the given pointer and length. + #[must_use] + pub const fn as_slice(&self) -> &'a [T] { + if self.ptr.is_null() { + &[] + } else { + // SAFETY: if the pointer is not null, we are assuming the caller has + // upheld the invariant that the pointer is valid for the length `len` + // `T` aligned elements. The phantom marker ensures that the lifetime + // of the returned slice is the same as the lifetime of the `BorrowedSlice`. + unsafe { std::slice::from_raw_parts(self.ptr, self.len) } + } + } + + /// Creates a new `BorrowedSlice` from the given rust slice. + #[must_use] + pub const fn from_slice(slice: &'a [T]) -> Self { + let len = slice.len(); + Self { + ptr: std::ptr::from_ref(slice).cast(), + len, + marker: std::marker::PhantomData, + } + } + + /// Returns true if the pointer is null. + /// This is used to differentiate between a nil slice and an empty slice. + #[must_use] + pub const fn is_null(&self) -> bool { + self.ptr.is_null() + } +} + +impl std::ops::Deref for BorrowedSlice<'_, T> { + type Target = [T]; + + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl AsRef<[T]> for BorrowedSlice<'_, T> { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +impl std::borrow::Borrow<[T]> for BorrowedSlice<'_, T> { + fn borrow(&self) -> &[T] { + self.as_slice() + } +} + +impl std::hash::Hash for BorrowedSlice<'_, T> { + fn hash(&self, state: &mut H) { + self.as_slice().hash(state); + } +} + +impl PartialEq for BorrowedSlice<'_, T> { + fn eq(&self, other: &Self) -> bool { + self.as_slice() == other.as_slice() + } +} + +impl Eq for BorrowedSlice<'_, T> {} + +impl PartialOrd for BorrowedSlice<'_, T> { + fn partial_cmp(&self, other: &Self) -> Option { + self.as_slice().partial_cmp(other.as_slice()) + } +} + +impl Ord for BorrowedSlice<'_, T> { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_slice().cmp(other.as_slice()) + } +} + +impl<'a, T> IntoIterator for BorrowedSlice<'a, T> { + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + + fn into_iter(self) -> Self::IntoIter { + self.as_slice().iter() + } +} + +impl fmt::Display for BorrowedBytes<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let precision = f.precision().unwrap_or(64); + write!(f, "{:.precision$}", super::DisplayHex(self.as_slice())) + } +} + +impl fmt::Pointer for BorrowedBytes<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.ptr.fmt(f) + } +} + +impl<'a> BorrowedBytes<'a> { + /// Creates a new [`str`] from this borrowed byte slice. + /// + /// # Errors + /// + /// If the slice is not valid UTF-8, an error is returned. + pub const fn as_str(&self) -> Result<&'a str, std::str::Utf8Error> { + // C callers are expected to pass a valid UTF-8 string for the path, even + // on Windows. Go does not handle UTF-16 paths on Windows, like Rust does, + // so we do not need to handle that here as well. + std::str::from_utf8(self.as_slice()) + } +} + +// send/sync rules for references apply here: the pointer is send and sync if and +// only if the value is sync. the value does not need to be send for the pointer +// to be send because this pointer is not moving the value across threads, only +// the reference to the value. + +// SAFETY: described above +unsafe impl Send for BorrowedSlice<'_, T> {} +// SAFETY: described above +unsafe impl Sync for BorrowedSlice<'_, T> {} diff --git a/firewood/ffi/src/value/display_hex.rs b/firewood/ffi/src/value/display_hex.rs new file mode 100644 index 000000000000..10a6941c39a4 --- /dev/null +++ b/firewood/ffi/src/value/display_hex.rs @@ -0,0 +1,78 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::fmt; + +/// Implementation of `Display` for a slice that displays the bytes in hexadecimal format. +/// +/// If the `precision` is set, it will display only that many bytes in hex, +/// followed by an ellipsis and the number of remaining bytes. +pub struct DisplayHex<'a>(pub(super) &'a [u8]); + +impl fmt::Display for DisplayHex<'_> { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + #![expect(clippy::indexing_slicing, clippy::arithmetic_side_effects)] + + match f.precision() { + Some(p) if p < self.0.len() => { + display_hex_bytes(&self.0[..p], f)?; + f.write_fmt(format_args!("... ({} remaining bytes)", self.0.len() - p))?; + } + _ => display_hex_bytes(self.0, f)?, + } + + Ok(()) + } +} + +#[inline] +fn display_hex_bytes(bytes: &[u8], f: &mut fmt::Formatter<'_>) -> fmt::Result { + const WIDTH: usize = size_of::() * 2; + + // SAFETY: it is trivially safe to transmute integer types, as long as the + // offset is aligned, which `align_to` guarantees. + let (before, aligned, after) = unsafe { bytes.align_to::() }; + + for &byte in before { + write!(f, "{byte:02x}")?; + } + + for &word in aligned { + let word = usize::from_be(word); + write!(f, "{word:0WIDTH$x}")?; + } + + for &byte in after { + write!(f, "{byte:02x}")?; + } + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(feature = "ethhash")] + use firewood::v2::api::HashKeyExt; + use test_case::test_case; + + #[test_case(&[], "", None; "empty slice")] + #[test_case(&[], "", Some(42); "empty slice with precision")] + #[test_case(b"abc", "616263", None; "short slice")] + #[test_case(b"abc", "61... (2 remaining bytes)", Some(1); "short slice with precision")] + #[test_case(b"abc", "616263", Some(16); "short slice with long precision")] + #[test_case(firewood_storage::TrieHash::empty().as_ref(), "0000000000000000000000000000000000000000000000000000000000000000", None; "empty trie hash")] + #[test_case(firewood_storage::TrieHash::empty().as_ref(), "00000000000000000000000000000000... (16 remaining bytes)", Some(16); "empty trie hash with precision")] + #[cfg_attr(feature = "ethhash", test_case(firewood_storage::TrieHash::default_root_hash().as_deref().expect("feature = \"ethhash\""), "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", None; "empty rlp hash"))] + #[cfg_attr(feature = "ethhash", test_case(firewood_storage::TrieHash::default_root_hash().as_deref().expect("feature = \"ethhash\""), "56e81f171bcc55a6ff8345e692c0f86e... (16 remaining bytes)", Some(16); "empty rlp hash with precision"))] + fn test_display_hex(input: &[u8], expected: &str, precision: Option) { + let input = DisplayHex(input); + if let Some(p) = precision { + assert_eq!(format!("{input:.p$}"), expected); + } else { + assert_eq!(format!("{input}"), expected); + } + } +} diff --git a/firewood/ffi/src/value/hash_key.rs b/firewood/ffi/src/value/hash_key.rs new file mode 100644 index 000000000000..4527396c0a50 --- /dev/null +++ b/firewood/ffi/src/value/hash_key.rs @@ -0,0 +1,38 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::fmt; + +/// A database hash key, used in FFI functions that require hashes. +/// This type requires no allocation and can be copied freely and +/// dropped without any additional overhead. +/// +/// This is useful because it is the same size as 4 words which is equivalent +/// to 2 heap-allocated slices (pointer + length each), or 1.5 vectors (which +/// uses an extra word for allocation capacity) and it can be passed around +/// without needing to allocate or deallocate memory. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +// Must use `repr(C)` instead of `repr(transparent)` to ensure it is a struct +// with one field instead of a type alias of an array of 32 element, which is +// necessary for FFI compatibility so that `HashKey` can be passed by value; +// otherwise, it would look like a pointer to an array of 32 bytes. +#[repr(C)] +pub struct HashKey([u8; 32]); + +impl fmt::Display for HashKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + super::DisplayHex(&self.0).fmt(f) + } +} + +impl From for HashKey { + fn from(value: firewood::v2::api::HashKey) -> Self { + Self(value.into()) + } +} + +impl From for firewood::v2::api::HashKey { + fn from(value: HashKey) -> Self { + value.0.into() + } +} diff --git a/firewood/ffi/src/value/kvp.rs b/firewood/ffi/src/value/kvp.rs new file mode 100644 index 000000000000..6dda75b866e4 --- /dev/null +++ b/firewood/ffi/src/value/kvp.rs @@ -0,0 +1,104 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::fmt; + +use crate::value::BorrowedBytes; +use crate::{OwnedBytes, OwnedSlice}; +use firewood::v2::api; + +/// A type alias for a rust-owned byte slice. +pub type OwnedKeyValueBatch = OwnedSlice; + +/// A `KeyValue` represents a key-value pair, passed to the FFI. +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct KeyValuePair<'a> { + pub key: BorrowedBytes<'a>, + pub value: BorrowedBytes<'a>, +} + +impl<'a> KeyValuePair<'a> { + pub fn new((key, value): &'a (impl AsRef<[u8]>, impl AsRef<[u8]>)) -> Self { + Self { + key: BorrowedBytes::from_slice(key.as_ref()), + value: BorrowedBytes::from_slice(value.as_ref()), + } + } +} + +impl fmt::Display for KeyValuePair<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let precision = f.precision().unwrap_or(64); + write!( + f, + "Key: {:.precision$}, Value: {:.precision$}", + self.key, self.value + ) + } +} + +impl<'a> api::TryIntoBatch for KeyValuePair<'a> { + type Key = BorrowedBytes<'a>; + type Value = BorrowedBytes<'a>; + type Error = std::convert::Infallible; + + #[inline] + fn try_into_batch(self) -> Result, Self::Error> { + // Check if the value pointer is null (nil slice in Go) + // vs non-null but empty (empty slice []byte{} in Go) + Ok(if self.value.is_null() { + api::BatchOp::DeleteRange { prefix: self.key } + } else { + api::BatchOp::Put { + key: self.key, + value: self.value, + } + }) + } +} + +impl api::KeyValuePair for KeyValuePair<'_> { + #[inline] + fn try_into_tuple(self) -> Result<(Self::Key, Self::Value), Self::Error> { + Ok((self.key, self.value)) + } +} + +impl<'a> api::TryIntoBatch for &KeyValuePair<'a> { + type Key = BorrowedBytes<'a>; + type Value = BorrowedBytes<'a>; + type Error = std::convert::Infallible; + + #[inline] + fn try_into_batch(self) -> Result, Self::Error> { + (*self).try_into_batch() + } +} + +impl api::KeyValuePair for &KeyValuePair<'_> { + #[inline] + fn try_into_tuple(self) -> Result<(Self::Key, Self::Value), Self::Error> { + (*self).try_into_tuple() + } +} + +/// Owned version of `KeyValuePair`, returned to ffi callers. +/// +/// C callers must free this using [`crate::fwd_free_owned_kv_pair`], +/// not the C standard library's `free` function. +#[repr(C)] +#[derive(Debug, Clone)] +pub struct OwnedKeyValuePair { + pub key: OwnedBytes, + pub value: OwnedBytes, +} + +impl From<(Box<[u8]>, Box<[u8]>)> for OwnedKeyValuePair { + fn from(value: (Box<[u8]>, Box<[u8]>)) -> Self { + OwnedKeyValuePair { + key: value.0.into(), + value: value.1.into(), + } + } +} diff --git a/firewood/ffi/src/value/owned.rs b/firewood/ffi/src/value/owned.rs new file mode 100644 index 000000000000..ca268cc2e950 --- /dev/null +++ b/firewood/ffi/src/value/owned.rs @@ -0,0 +1,161 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::{fmt, ptr::NonNull}; + +/// A type alias for a rust-owned byte slice. +pub type OwnedBytes = OwnedSlice; + +/// A Rust-owned vector of bytes that can be passed to C code. +/// +/// C callers must free this memory using the respective FFI function for the +/// concrete type (but not using the `free` function from the C standard library). +#[derive(Debug)] +#[repr(C)] +pub struct OwnedSlice { + ptr: Option>, + len: usize, +} + +impl OwnedSlice { + /// Dereferences the pointer to the owned slice, returning a slice of the contained type. + #[must_use] + pub const fn as_slice(&self) -> &[T] { + match self.ptr { + // SAFETY: if the pointer is not null, we are assuming the caller has not changed + // it from when we originally created the `OwnedSlice`. + Some(ptr) => unsafe { std::slice::from_raw_parts(ptr.as_ptr(), self.len) }, + None => &[], + } + } + + /// Returns a mutable slice of the owned slice, allowing modification of the contained type. + #[must_use] + pub const fn as_mut_slice(&mut self) -> &mut [T] { + match self.ptr { + // SAFETY: if the pointer is not null, we are assuming the caller has not changed + // it from when we originally created the `OwnedSlice`. + Some(ptr) => unsafe { std::slice::from_raw_parts_mut(ptr.as_ptr(), self.len) }, + None => &mut [], + } + } + + /// Transforms the owned slice into a boxed slice, consuming the original. + #[must_use] + pub fn into_boxed_slice(self) -> Box<[T]> { + self.into() + } + + fn take_box(&mut self) -> Box<[T]> { + match self.ptr.take() { + // SAFETY: if the pointer is not null, we are assuming the caller has not changed + // it from when we originally created the `OwnedSlice`. The owned slice was created + // from a `Box::leak`, so we can safely convert it back using `Box::from_raw`. + Some(ptr) => unsafe { + Box::from_raw(std::ptr::slice_from_raw_parts_mut(ptr.as_ptr(), self.len)) + }, + None => Box::new([]), + } + } +} + +impl Clone for OwnedSlice { + fn clone(&self) -> Self { + self.as_slice().to_vec().into() + } +} + +impl AsRef<[T]> for OwnedSlice { + fn as_ref(&self) -> &[T] { + self.as_slice() + } +} + +impl AsMut<[T]> for OwnedSlice { + fn as_mut(&mut self) -> &mut [T] { + self.as_mut_slice() + } +} + +impl std::borrow::Borrow<[T]> for OwnedSlice { + fn borrow(&self) -> &[T] { + self.as_slice() + } +} + +impl std::borrow::BorrowMut<[T]> for OwnedSlice { + fn borrow_mut(&mut self) -> &mut [T] { + self.as_mut_slice() + } +} + +impl std::hash::Hash for OwnedSlice { + fn hash(&self, state: &mut H) { + self.as_slice().hash(state); + } +} + +impl PartialEq for OwnedSlice { + fn eq(&self, other: &Self) -> bool { + self.as_slice() == other.as_slice() + } +} + +impl Eq for OwnedSlice {} + +impl PartialOrd for OwnedSlice { + fn partial_cmp(&self, other: &Self) -> Option { + self.as_slice().partial_cmp(other.as_slice()) + } +} + +impl Ord for OwnedSlice { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_slice().cmp(other.as_slice()) + } +} + +impl From> for OwnedSlice { + fn from(data: Box<[T]>) -> Self { + let len = data.len(); + let ptr = NonNull::from(Box::leak(data)).cast::(); + Self { + ptr: Some(ptr), + len, + } + } +} + +impl From> for OwnedSlice { + fn from(data: Vec) -> Self { + data.into_boxed_slice().into() + } +} + +impl From> for Box<[T]> { + fn from(mut owned: OwnedSlice) -> Self { + owned.take_box() + } +} + +impl Drop for OwnedSlice { + fn drop(&mut self) { + drop(self.take_box()); + } +} + +impl fmt::Display for OwnedBytes { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + super::DisplayHex(self.as_slice()).fmt(f) + } +} + +// send/sync rules for owned values apply here: if the value is send, the pointer +// is send. if the value is sync, the pointer is sync. This is because we own the +// value and whether or not the pointer can traverse threads is determined by +// the value itself. + +// SAFETY: described above +unsafe impl Send for OwnedSlice {} +// SAFETY: described above +unsafe impl Sync for OwnedSlice {} diff --git a/firewood/ffi/src/value/results.rs b/firewood/ffi/src/value/results.rs new file mode 100644 index 000000000000..ce25ac64b58d --- /dev/null +++ b/firewood/ffi/src/value/results.rs @@ -0,0 +1,606 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use firewood::merkle; +use firewood::v2::api; +use std::fmt; + +use crate::revision::{GetRevisionResult, RevisionHandle}; +use crate::{ + ChangeProofContext, CreateIteratorResult, CreateProposalResult, HashKey, IteratorHandle, + NextKeyRange, OwnedBytes, OwnedKeyValueBatch, OwnedKeyValuePair, ProposalHandle, + RangeProofContext, +}; + +/// The result type returned from an FFI function that returns no value but may +/// return an error. +#[derive(Debug)] +#[repr(C)] +pub enum VoidResult { + /// The caller provided a null pointer to the input handle. + NullHandlePointer, + + /// The operation was successful and no error occurred. + Ok, + + /// An error occurred and the message is returned as an [`OwnedBytes`]. Its + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +impl From<()> for VoidResult { + fn from((): ()) -> Self { + VoidResult::Ok + } +} + +impl From> for VoidResult { + fn from(value: Result<(), E>) -> Self { + match value { + Ok(()) => VoidResult::Ok, + Err(err) => VoidResult::Err(err.to_string().into_bytes().into()), + } + } +} + +/// The result type returned from the open or create database functions. +#[derive(Debug)] +#[repr(C)] +pub enum HandleResult { + /// The database was opened or created successfully and the handle is + /// returned as an opaque pointer. + /// + /// The caller must ensure that [`fwd_close_db`] is called to free resources + /// associated with this handle when it is no longer needed. + /// + /// [`fwd_close_db`]: crate::fwd_close_db + Ok(Box), + + /// An error occurred and the message is returned as an [`OwnedBytes`]. If + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +impl From> for HandleResult { + fn from(value: Result) -> Self { + match value { + Ok(handle) => HandleResult::Ok(Box::new(handle)), + Err(err) => HandleResult::Err(err.to_string().into_bytes().into()), + } + } +} + +/// A result type returned from FFI functions that retrieve a single value. +#[derive(Debug)] +#[repr(C)] +pub enum ValueResult { + /// The caller provided a null pointer to a database handle. + NullHandlePointer, + /// The provided root was not found in the database. + RevisionNotFound(HashKey), + /// The provided key was not found in the database or proposal. + None, + /// A value was found and is returned. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this value. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Some(OwnedBytes), + /// An error occurred and the message is returned as an [`OwnedBytes`]. If + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +impl From> for ValueResult { + fn from(value: Result) -> Self { + match value { + Ok(data) => ValueResult::Some(data.into_bytes().into()), + Err(err) => ValueResult::Err(err.to_string().into_bytes().into()), + } + } +} + +impl From>, api::Error>> for ValueResult { + fn from(value: Result>, api::Error>) -> Self { + match value { + Ok(None) => ValueResult::None, + Err(api::Error::RevisionNotFound { provided }) => ValueResult::RevisionNotFound( + HashKey::from(provided.unwrap_or_else(api::HashKey::empty)), + ), + Ok(Some(data)) => ValueResult::Some(data.into()), + Err(err) => ValueResult::Err(err.to_string().into_bytes().into()), + } + } +} + +impl From>, firewood::db::DbError>> for ValueResult { + fn from(value: Result>, firewood::db::DbError>) -> Self { + value.map_err(api::Error::from).into() + } +} + +impl From> for ValueResult { + fn from(value: Vec) -> Self { + value.into_boxed_slice().into() + } +} + +impl From> for ValueResult { + fn from(value: Box<[u8]>) -> Self { + ValueResult::Some(value.into()) + } +} + +/// A result type returned from FFI functions return the database root hash. This +/// may or may not be after a mutation. +#[derive(Debug)] +#[repr(C)] +pub enum HashResult { + /// The caller provided a null pointer to a database handle. + NullHandlePointer, + /// The proposal resulted in an empty database or the database currently has + /// no root hash. + None, + /// The mutation was successful and the root hash is returned, if this result + /// was from a mutation. Otherwise, this is the current root hash of the + /// database. + Some(HashKey), + /// An error occurred and the message is returned as an [`OwnedBytes`]. If + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +impl From, E>> for HashResult { + fn from(value: Result, E>) -> Self { + match value { + Ok(None) => HashResult::None, + Ok(Some(hash)) => HashResult::Some(HashKey::from(hash)), + Err(err) => HashResult::Err(err.to_string().into_bytes().into()), + } + } +} + +/// A result type returned from FFI functions that create or parse range proofs. +/// +/// The caller must ensure that [`fwd_free_range_proof`] is called to +/// free the memory associated with the returned context when it is no longer +/// needed. +/// +/// [`fwd_free_range_proof`]: crate::fwd_free_range_proof +#[derive(Debug)] +#[repr(C)] +pub enum RangeProofResult<'db> { + /// The caller provided a null pointer to the input handle. + NullHandlePointer, + /// The provided root was not found in the database. + RevisionNotFound(HashKey), + /// A range proof was requested on an empty trie. + EmptyTrie, + /// The proof was successfully created or parsed. + /// + /// If the value was parsed from a serialized proof, this does not imply that + /// the proof is valid, only that it is well-formed. The verify method must + /// be called to ensure the proof is cryptographically valid. + Ok(Box>), + /// An error occurred and the message is returned as an [`OwnedBytes`]. If + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +impl From> for RangeProofResult<'_> { + fn from(value: Result) -> Self { + match value { + Ok(proof) => RangeProofResult::Ok(Box::new(proof.into())), + Err(api::Error::RevisionNotFound { provided }) => RangeProofResult::RevisionNotFound( + HashKey::from(provided.unwrap_or_else(api::HashKey::empty)), + ), + Err(api::Error::RangeProofOnEmptyTrie) => RangeProofResult::EmptyTrie, + Err(err) => RangeProofResult::Err(err.to_string().into_bytes().into()), + } + } +} + +/// A result type returned from FFI functions that create or parse change proofs. +/// +/// The caller must ensure that [`fwd_free_change_proof`] is called to +/// free the memory associated with the returned context when it is no longer +/// needed. +/// +/// [`fwd_free_change_proof`]: crate::fwd_free_change_proof +#[derive(Debug)] +#[repr(C)] +pub enum ChangeProofResult { + /// The caller provided a null pointer to the input handle. + NullHandlePointer, + /// The provided root was not found in the database. + RevisionNotFound(HashKey), + /// The proof was successfully created or parsed. + /// + /// If the value was parsed from a serialized proof, this does not imply that + /// the proof is valid, only that it is well-formed. The verify method must + /// be called to ensure the proof is cryptographically valid. + Ok(Box), + /// An error occurred and the message is returned as an [`OwnedBytes`]. If + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +#[derive(Debug)] +#[repr(C)] +pub enum NextKeyRangeResult { + /// The caller provided a null pointer to the input handle. + NullHandlePointer, + /// The proof has not prepared into a proposal nor committed to the database. + NotPrepared, + /// There are no more keys to fetch. + None, + /// The next key range to fetch is returned. + Some(NextKeyRange), + /// An error occurred and the message is returned as an [`OwnedBytes`]. If + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +/// A result type returned from FFI functions that create a proposal but do not +/// commit it to the database. +#[derive(Debug)] +#[repr(C)] +pub enum ProposalResult<'db> { + /// The caller provided a null pointer to a database handle. + NullHandlePointer, + /// Buulding the proposal was successful and the proposal ID and root hash + /// are returned. + Ok { + /// An opaque pointer to the [`ProposalHandle`] that can be use to create + /// an additional proposal or later commit. The caller must ensure that this + /// pointer is freed with [`fwd_free_proposal`] if it is not committed. + /// + /// [`fwd_free_proposal`]: crate::fwd_free_proposal + // note: opaque pointers mut be boxed because the FFI does not the structure definition. + handle: Box>, + /// The root hash of the proposal. Zeroed if the proposal resulted in an + /// empty database. + root_hash: HashKey, + }, + /// An error occurred and the message is returned as an [`OwnedBytes`]. If + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +/// A result type returned from FFI functions that create an iterator +#[derive(Debug)] +#[repr(C)] +pub enum IteratorResult<'db> { + /// The caller provided a null pointer to a revision/proposal handle. + NullHandlePointer, + /// Building the iterator was successful and the iterator handle is returned + Ok { + /// An opaque pointer to the [`IteratorHandle`]. + /// The value should be freed with [`fwd_free_iterator`] + /// + /// [`fwd_free_iterator`]: crate::fwd_free_iterator + handle: Box>, + }, + /// An error occurred and the message is returned as an [`OwnedBytes`]. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +/// A result type returned from iterator FFI functions +#[derive(Debug)] +#[repr(C)] +pub enum KeyValueResult { + /// The caller provided a null pointer to an iterator handle. + NullHandlePointer, + /// The iterator is exhausted + None, + /// The next item is returned. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with the key and the value of this pair. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Some(OwnedKeyValuePair), + /// An error occurred and the message is returned as an [`OwnedBytes`]. The + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +impl From>> for KeyValueResult { + fn from(value: Option>) -> Self { + match value { + Some(value) => match value { + Ok(value) => KeyValueResult::Some(value.into()), + Err(err) => KeyValueResult::Err(err.to_string().into_bytes().into()), + }, + None => KeyValueResult::None, + } + } +} + +/// A result type returned from iterator FFI functions +#[derive(Debug)] +#[repr(C)] +pub enum KeyValueBatchResult { + /// The caller provided a null pointer to an iterator handle. + NullHandlePointer, + /// The next batch of items on iterator are returned. + Some(OwnedKeyValueBatch), + /// An error occurred and the message is returned as an [`OwnedBytes`]. If + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +impl From, api::Error>> for KeyValueBatchResult { + fn from(value: Result, api::Error>) -> Self { + match value { + Ok(pairs) => { + let values: Vec<_> = pairs.into_iter().map(Into::into).collect(); + KeyValueBatchResult::Some(values.into()) + } + Err(err) => KeyValueBatchResult::Err(err.to_string().into_bytes().into()), + } + } +} + +impl<'db> From> for IteratorResult<'db> { + fn from(value: CreateIteratorResult<'db>) -> Self { + IteratorResult::Ok { + handle: Box::new(value.0), + } + } +} + +impl<'db, E: fmt::Display> From, E>> for IteratorResult<'db> { + fn from(value: Result, E>) -> Self { + match value { + Ok(res) => res.into(), + Err(err) => IteratorResult::Err(err.to_string().into_bytes().into()), + } + } +} + +/// A result type returned from FFI functions that get a revision +#[derive(Debug)] +#[repr(C)] +pub enum RevisionResult { + /// The caller provided a null pointer to a database handle. + NullHandlePointer, + /// The provided root was not found in the database. + RevisionNotFound(HashKey), + /// Getting the revision was successful and the revision handle and root + /// hash are returned. + Ok { + /// An opaque pointer to the [`RevisionHandle`]. + /// The value should be freed with [`fwd_free_revision`] + /// + /// [`fwd_free_revision`]: crate::fwd_free_revision + handle: Box, + /// The root hash of the revision. + root_hash: HashKey, + }, + /// An error occurred and the message is returned as an [`OwnedBytes`]. The + /// value is guaranteed to contain only valid UTF-8. + /// + /// The caller must call [`fwd_free_owned_bytes`] to free the memory + /// associated with this error. + /// + /// [`fwd_free_owned_bytes`]: crate::fwd_free_owned_bytes + Err(OwnedBytes), +} + +impl From for RevisionResult { + fn from(value: GetRevisionResult) -> Self { + RevisionResult::Ok { + handle: Box::new(value.handle), + root_hash: HashKey::from(value.root_hash), + } + } +} + +impl From> for RevisionResult { + fn from(value: Result) -> Self { + match value { + Ok(res) => res.into(), + Err(api::Error::RevisionNotFound { provided }) => RevisionResult::RevisionNotFound( + HashKey::from(provided.unwrap_or_else(api::HashKey::empty)), + ), + Err(err) => RevisionResult::Err(err.to_string().into_bytes().into()), + } + } +} + +impl<'db, E: fmt::Display> From, E>> for ProposalResult<'db> { + fn from(value: Result, E>) -> Self { + match value { + Ok(CreateProposalResult { handle, .. }) => ProposalResult::Ok { + root_hash: handle.hash_key().unwrap_or_default(), + handle: Box::new(handle), + }, + Err(err) => ProposalResult::Err(err.to_string().into_bytes().into()), + } + } +} + +/// Helper trait to handle the different result types returned from FFI functions. +/// +/// Once Try trait is stable, we can use that instead of this trait: +/// +/// ```ignore +/// impl std::ops::FromResidual> for VoidResult { +/// #[inline] +/// fn from_residual(residual: Option) -> Self { +/// match residual { +/// None => VoidResult::NullHandlePointer, +/// // no other branches are needed because `std::convert::Infallible` is uninhabited +/// // this compiles without error because the compiler knows that Some(_) is impossible +/// // see: https://github.com/rust-lang/rust/blob/3fb1b53a9dbfcdf37a4b67d35cde373316829930/library/core/src/option.rs#L2627-L2631 +/// // and: https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types +/// } +/// } +/// } +/// ``` +pub(crate) trait NullHandleResult: CResult { + fn null_handle_pointer_error() -> Self; +} + +pub(crate) trait CResult: Sized { + fn from_err(err: impl ToString) -> Self; + + fn from_panic(panic: Box) -> Self + where + Self: Sized, + { + Self::from_err(Panic::from(panic)) + } +} + +macro_rules! impl_null_handle_result { + ($($Enum:ty),* $(,)?) => { + $( + impl NullHandleResult for $Enum { + fn null_handle_pointer_error() -> Self { + Self::NullHandlePointer + } + } + )* + }; +} + +macro_rules! impl_cresult { + ($($Enum:ty),* $(,)?) => { + $( + impl CResult for $Enum { + fn from_err(err: impl ToString) -> Self { + Self::Err(err.to_string().into_bytes().into()) + } + } + )* + }; +} + +impl_null_handle_result!( + VoidResult, + ValueResult, + HashResult, + RangeProofResult<'_>, + ChangeProofResult, + NextKeyRangeResult, + ProposalResult<'_>, + IteratorResult<'_>, + RevisionResult, + KeyValueBatchResult, + KeyValueResult, +); + +impl_cresult!( + VoidResult, + ValueResult, + HashResult, + HandleResult, + RangeProofResult<'_>, + ChangeProofResult, + NextKeyRangeResult, + ProposalResult<'_>, + IteratorResult<'_>, + RevisionResult, + KeyValueBatchResult, + KeyValueResult, +); + +enum Panic { + Static(&'static str), + Formatted(String), + SendSyncErr(Box), + SendErr(Box), + Unknown(#[expect(unused)] Box), + // TODO: add variant to capture backtrace with panic hook + // https://doc.rust-lang.org/stable/std/panic/fn.set_hook.html +} + +impl From> for Panic { + fn from(panic: Box) -> Self { + macro_rules! downcast { + ($Variant:ident($panic:ident)) => { + let $panic = match $panic.downcast() { + Ok(panic) => return Panic::$Variant(*panic), + Err(panic) => panic, + }; + }; + } + + downcast!(Static(panic)); + downcast!(Formatted(panic)); + downcast!(SendSyncErr(panic)); + downcast!(SendErr(panic)); + + Self::Unknown(panic) + } +} + +impl fmt::Display for Panic { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Panic::Static(msg) => f.pad(msg), + Panic::Formatted(msg) => f.pad(msg), + Panic::SendSyncErr(err) => err.fmt(f), + Panic::SendErr(err) => err.fmt(f), + Panic::Unknown(_) => f.pad("unknown panic type recovered"), + } + } +} diff --git a/firewood/ffi/test-build-equivalency.sh b/firewood/ffi/test-build-equivalency.sh new file mode 100755 index 000000000000..a815795bb81c --- /dev/null +++ b/firewood/ffi/test-build-equivalency.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Always work from the repo root +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +cd "$REPO_ROOT" + +# Define paths to libraries (relative to repo root) +NIX_LIB="ffi/result/lib/libfirewood_ffi.a" # Default path for the nix build +CARGO_LIB="target/maxperf/libfirewood_ffi.a" + +# Create temporary directory and ensure cleanup on exit +TMPDIR=$(mktemp -d) +trap "rm -rf $TMPDIR" EXIT + +echo "Building with cargo (using nix dev shell)..." +nix develop ./ffi#default --command bash -c "cargo fetch --locked --verbose && cargo build-static-ffi" + +echo "Building with nix..." +cd ffi && nix build .#firewood-ffi && cd .. + +echo "" +echo "=== File Size Comparison ===" +ls -lh "$CARGO_LIB" "$NIX_LIB" + +echo "" +echo "=== Symbol Count Comparison ===" +# Extract symbols to temporary files for comparison +nm "$NIX_LIB" | sort > "$TMPDIR/nix-symbols.txt" +nm "$CARGO_LIB" | sort > "$TMPDIR/cargo-symbols.txt" + +NIX_SYMBOLS=$(wc -l < "$TMPDIR/nix-symbols.txt") +CARGO_SYMBOLS=$(wc -l < "$TMPDIR/cargo-symbols.txt") +echo "Nix build: $NIX_SYMBOLS symbols" +echo "Cargo build: $CARGO_SYMBOLS symbols" +if [ "$NIX_SYMBOLS" -eq "$CARGO_SYMBOLS" ]; then + echo "✅ Symbol counts are both $NIX_SYMBOLS" +else + echo "❌ Symbol counts differ" + echo "" + echo "=== Symbol Differences ===" + echo "Symbols only in Nix build:" + # Show lines that exist in the old file (nix) but not in the new file (cargo) + diff --unchanged-line-format="" --old-line-format="%L" --new-line-format="" "$TMPDIR/nix-symbols.txt" "$TMPDIR/cargo-symbols.txt" || true + echo "" + echo "Symbols only in Cargo build:" + # Show lines that exist in the new file (cargo) but not in the old file (nix) + diff --unchanged-line-format="" --old-line-format="" --new-line-format="%L" "$TMPDIR/nix-symbols.txt" "$TMPDIR/cargo-symbols.txt" || true +fi diff --git a/firewood/ffi/tests/eth/BUILD.bazel b/firewood/ffi/tests/eth/BUILD.bazel new file mode 100644 index 000000000000..a2b42548e4e8 --- /dev/null +++ b/firewood/ffi/tests/eth/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_test") + +go_test( + name = "eth_test", + srcs = ["eth_compatibility_test.go"], + deps = [ + "//firewood/ffi", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + ], +) diff --git a/firewood/ffi/tests/eth/eth_compatibility_test.go b/firewood/ffi/tests/eth/eth_compatibility_test.go new file mode 100644 index 000000000000..9f4218068566 --- /dev/null +++ b/firewood/ffi/tests/eth/eth_compatibility_test.go @@ -0,0 +1,356 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package eth + +import ( + "context" + "encoding/binary" + "math/rand" + "path" + "slices" + "testing" + + firewood "github.com/ava-labs/firewood-go-ethhash/ffi" + "github.com/ava-labs/libevm/common" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/core/state" + "github.com/ava-labs/libevm/core/types" + "github.com/ava-labs/libevm/crypto" + "github.com/ava-labs/libevm/rlp" + "github.com/ava-labs/libevm/trie/trienode" + "github.com/ava-labs/libevm/triedb" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" +) + +const ( + commit byte = iota + createAccount + updateAccount + deleteAccount + addStorage + updateStorage + deleteStorage + maxStep +) + +var ( + stepMap = map[byte]string{ + commit: "commit", + createAccount: "createAccount", + updateAccount: "updateAccount", + deleteAccount: "deleteAccount", + addStorage: "addStorage", + updateStorage: "updateStorage", + deleteStorage: "deleteStorage", + } +) + +type merkleTriePair struct { + fwdDB *firewood.Database + accountTrie state.Trie + ethDatabase state.Database + + lastRoot common.Hash + require *require.Assertions + + // current state + currentAddrs []common.Address + currentStorageInputIndices map[common.Address]uint64 + inputCounter uint64 + + // pending changes to both firewood and eth database + openStorageTries map[common.Address]state.Trie + pendingFwdKeys [][]byte + pendingFwdVals [][]byte +} + +func newMerkleTriePair(t *testing.T) *merkleTriePair { + r := require.New(t) + + file := path.Join(t.TempDir(), "test.db") + cfg := firewood.DefaultConfig() + db, err := firewood.New(file, cfg) + r.NoError(err) + + tdb := state.NewDatabaseWithConfig(rawdb.NewMemoryDatabase(), triedb.HashDefaults) + ethRoot := types.EmptyRootHash + tr, err := tdb.OpenTrie(ethRoot) + r.NoError(err) + t.Cleanup(func() { + r.NoError(db.Close(context.Background())) //nolint:usetesting // t.Context() will already be cancelled + }) + + return &merkleTriePair{ + fwdDB: db, + accountTrie: tr, + ethDatabase: tdb, + openStorageTries: make(map[common.Address]state.Trie), + currentStorageInputIndices: make(map[common.Address]uint64), + require: r, + } +} + +// commit writes the pending changes to both tries and clears the pending changes +func (tr *merkleTriePair) commit() { + mergedNodeSet := trienode.NewMergedNodeSet() + for addr, str := range tr.openStorageTries { + accountStateRoot, set, err := str.Commit(false) + tr.require.NoError(err) + // A no-op change returns a nil set, which will cause merge to panic. + if set != nil { + tr.require.NoError(mergedNodeSet.Merge(set)) + } + + acc, err := tr.accountTrie.GetAccount(addr) + tr.require.NoError(err) + // If the account was deleted, we can skip updating the account's + // state root. + if acc == nil { + continue + } + + acc.Root = accountStateRoot + tr.require.NoError(tr.accountTrie.UpdateAccount(addr, acc)) + + accHash := crypto.Keccak256(addr[:]) + tr.pendingFwdKeys = append(tr.pendingFwdKeys, accHash[:]) + updatedAccountRLP, err := rlp.EncodeToBytes(acc) + tr.require.NoError(err) + tr.pendingFwdVals = append(tr.pendingFwdVals, updatedAccountRLP) + } + + updatedRoot, set, err := tr.accountTrie.Commit(true) + tr.require.NoError(err) + + // A no-op change returns a nil set, which will cause merge to panic. + if set != nil { + tr.require.NoError(mergedNodeSet.Merge(set)) + } + + tr.require.NoError(tr.ethDatabase.TrieDB().Update(updatedRoot, tr.lastRoot, 0, mergedNodeSet, nil)) + tr.lastRoot = updatedRoot + + fwdRoot, err := tr.fwdDB.Update(tr.pendingFwdKeys, tr.pendingFwdVals) + tr.require.NoError(err) + tr.require.Equal(updatedRoot, common.Hash(fwdRoot)) + + tr.pendingFwdKeys = nil + tr.pendingFwdVals = nil + tr.openStorageTries = make(map[common.Address]state.Trie) + + tr.accountTrie, err = tr.ethDatabase.OpenTrie(tr.lastRoot) + tr.require.NoError(err) +} + +// createAccount generates a new, unique account and adds it to both tries and the tracked +// current state. +func (tr *merkleTriePair) createAccount() { + tr.inputCounter++ + addr := common.BytesToAddress(crypto.Keccak256Hash(binary.BigEndian.AppendUint64(nil, tr.inputCounter)).Bytes()) + accHash := crypto.Keccak256Hash(addr[:]) + acc := &types.StateAccount{ + Nonce: 1, + Balance: uint256.NewInt(100), + Root: types.EmptyRootHash, + CodeHash: types.EmptyCodeHash[:], + } + accountRLP, err := rlp.EncodeToBytes(acc) + tr.require.NoError(err) + + err = tr.accountTrie.UpdateAccount(addr, acc) + tr.require.NoError(err) + tr.currentAddrs = append(tr.currentAddrs, addr) + + tr.pendingFwdKeys = append(tr.pendingFwdKeys, accHash[:]) + tr.pendingFwdVals = append(tr.pendingFwdVals, accountRLP) +} + +// selectAccount returns a random account and account hash for the provided index +// assumes: addrIndex < len(tr.currentAddrs) +func (tr *merkleTriePair) selectAccount(addrIndex int) (common.Address, common.Hash) { + addr := tr.currentAddrs[addrIndex] + return addr, crypto.Keccak256Hash(addr[:]) +} + +// updateAccount selects a random account, increments its nonce, and adds the update +// to the pending changes for both tries. +func (tr *merkleTriePair) updateAccount(addrIndex int) { + addr, accHash := tr.selectAccount(addrIndex) + acc, err := tr.accountTrie.GetAccount(addr) + tr.require.NoError(err) + acc.Nonce++ + acc.CodeHash = crypto.Keccak256Hash(acc.CodeHash[:]).Bytes() + acc.Balance.Add(acc.Balance, uint256.NewInt(3)) + accountRLP, err := rlp.EncodeToBytes(acc) + tr.require.NoError(err) + + err = tr.accountTrie.UpdateAccount(addr, acc) + tr.require.NoError(err) + + tr.pendingFwdKeys = append(tr.pendingFwdKeys, accHash[:]) + tr.pendingFwdVals = append(tr.pendingFwdVals, accountRLP) +} + +// deleteAccount selects a random account and deletes it from both tries and the tracked +// current state. +func (tr *merkleTriePair) deleteAccount(accountIndex int) { + deleteAddr, accHash := tr.selectAccount(accountIndex) + + tr.require.NoError(tr.accountTrie.DeleteAccount(deleteAddr)) + tr.currentAddrs = slices.DeleteFunc(tr.currentAddrs, func(addr common.Address) bool { + return deleteAddr == addr + }) + + tr.pendingFwdKeys = append(tr.pendingFwdKeys, accHash[:]) + tr.pendingFwdVals = append(tr.pendingFwdVals, nil) +} + +// openStorageTrie opens the storage trie for the provided account address. +// Uses an already opened trie, if there's a pending update to the ethereum nested +// storage trie. +// +// must maintain a map of currently open storage tries, so we can defer committing them +// until commit as opposed to after each storage update. +// This mimics the actual handling of state commitments in the EVM where storage tries are all committed immediately +// before updating the account trie along with the updated storage trie roots: +// https://github.com/ava-labs/libevm/blob/0bfe4a0380c86d7c9bf19fe84368b9695fcb96c7/core/state/statedb.go#L1155 +// +// If we attempt to commit the storage tries after each operation, then attempting to re-open the storage trie +// with an updated storage trie root from ethDatabase will fail since the storage trie root will not have been +// persisted yet - leading to a missing trie node error. +func (tr *merkleTriePair) openStorageTrie(addr common.Address) state.Trie { + storageTrie, ok := tr.openStorageTries[addr] + if ok { + return storageTrie + } + + acc, err := tr.accountTrie.GetAccount(addr) + tr.require.NoError(err) + storageTrie, err = tr.ethDatabase.OpenStorageTrie(tr.lastRoot, addr, acc.Root, tr.accountTrie) + tr.require.NoError(err) + tr.openStorageTries[addr] = storageTrie + return storageTrie +} + +// addStorage selects an account and adds a new storage key-value pair to the account. +func (tr *merkleTriePair) addStorage(accountIndex int) { + addr, accHash := tr.selectAccount(accountIndex) + // Increment storageInputIndices for the account and take the next input to generate + // a new storage key-value pair for the account. + tr.currentStorageInputIndices[addr]++ + storageIndex := tr.currentStorageInputIndices[addr] + key := crypto.Keccak256Hash(binary.BigEndian.AppendUint64(nil, storageIndex)) + keyHash := crypto.Keccak256Hash(key[:]) + val := crypto.Keccak256Hash(keyHash[:]) + + str := tr.openStorageTrie(addr) + err := str.UpdateStorage(addr, key[:], val[:]) + tr.require.NoError(err) + + // Update storage key-value pair in firewood + tr.pendingFwdKeys = append(tr.pendingFwdKeys, append(accHash[:], keyHash[:]...)) + encodedVal, err := rlp.EncodeToBytes(val[:]) + tr.require.NoError(err) + tr.pendingFwdVals = append(tr.pendingFwdVals, encodedVal) + + tr.currentStorageInputIndices[addr]++ +} + +// updateStorage selects an account and updates an existing storage key-value pair +// note: this may "update" a key-value pair that doesn't exist if it was previously deleted. +func (tr *merkleTriePair) updateStorage(accountIndex int, storageIndexInput uint64) { + addr, accHash := tr.selectAccount(accountIndex) + storageIndex := tr.currentStorageInputIndices[addr] + storageIndex %= storageIndexInput + + storageKey := crypto.Keccak256Hash(binary.BigEndian.AppendUint64(nil, storageIndex)) + storageKeyHash := crypto.Keccak256Hash(storageKey[:]) + tr.inputCounter++ + updatedValInput := binary.BigEndian.AppendUint64(storageKeyHash[:], tr.inputCounter) + updatedVal := crypto.Keccak256Hash(updatedValInput[:]) + + str := tr.openStorageTrie(addr) + tr.require.NoError(str.UpdateStorage(addr, storageKey[:], updatedVal[:])) + + tr.pendingFwdKeys = append(tr.pendingFwdKeys, append(accHash[:], storageKeyHash[:]...)) + updatedValRLP, err := rlp.EncodeToBytes(updatedVal[:]) + tr.require.NoError(err) + tr.pendingFwdVals = append(tr.pendingFwdVals, updatedValRLP[:]) +} + +// deleteStorage selects an account and deletes an existing storage key-value pair +// note: this may "delete" a key-value pair that doesn't exist if it was previously deleted. +func (tr *merkleTriePair) deleteStorage(accountIndex int, storageIndexInput uint64) { + addr, accHash := tr.selectAccount(accountIndex) + storageIndex := tr.currentStorageInputIndices[addr] + storageIndex %= storageIndexInput + storageKey := crypto.Keccak256Hash(binary.BigEndian.AppendUint64(nil, storageIndex)) + storageKeyHash := crypto.Keccak256Hash(storageKey[:]) + + str := tr.openStorageTrie(addr) + tr.require.NoError(str.DeleteStorage(addr, storageKey[:])) + + tr.pendingFwdKeys = append(tr.pendingFwdKeys, append(accHash[:], storageKeyHash[:]...)) + tr.pendingFwdVals = append(tr.pendingFwdVals, nil) +} + +func FuzzFirewoodTree(f *testing.F) { + for randSeed := range int64(5) { + rand := rand.New(rand.NewSource(randSeed)) + steps := make([]byte, 32) + _, err := rand.Read(steps) + if err != nil { + f.Fatal(err) + } + f.Add(randSeed, steps) + } + f.Fuzz(func(t *testing.T, randSeed int64, byteSteps []byte) { + tr := newMerkleTriePair(t) + rand := rand.New(rand.NewSource(randSeed)) + + for range 10 { + tr.createAccount() + } + tr.commit() + + const maxSteps = 1000 + if len(byteSteps) > maxSteps { + byteSteps = byteSteps[:maxSteps] + } + + for _, step := range byteSteps { + step = step % maxStep + t.Log(stepMap[step]) + switch step { + case commit: + tr.commit() + case createAccount: + tr.createAccount() + case updateAccount: + if len(tr.currentAddrs) > 0 { + tr.updateAccount(rand.Intn(len(tr.currentAddrs))) + } + case deleteAccount: + if len(tr.currentAddrs) > 0 { + tr.deleteAccount(rand.Intn(len(tr.currentAddrs))) + } + case addStorage: + if len(tr.currentAddrs) > 0 { + tr.addStorage(rand.Intn(len(tr.currentAddrs))) + } + case updateStorage: + if len(tr.currentAddrs) > 0 { + tr.updateStorage(rand.Intn(len(tr.currentAddrs)), rand.Uint64()) + } + case deleteStorage: + if len(tr.currentAddrs) > 0 { + tr.deleteStorage(rand.Intn(len(tr.currentAddrs)), rand.Uint64()) + } + default: + t.Fatalf("unknown step: %d", step) + } + } + }) +} diff --git a/firewood/ffi/tests/eth/go.mod b/firewood/ffi/tests/eth/go.mod new file mode 100644 index 000000000000..4ea0559a2e39 --- /dev/null +++ b/firewood/ffi/tests/eth/go.mod @@ -0,0 +1,72 @@ +module github.com/ava-labs/firewood/ffi/tests/eth + +go 1.24.0 + +toolchain go1.24.9 + +require ( + github.com/ava-labs/firewood-go-ethhash/ffi v0.0.0 // this is replaced to use the parent folder + github.com/ava-labs/libevm v1.13.14-0.2.0.release + github.com/holiman/uint256 v1.3.2 + github.com/stretchr/testify v1.10.0 +) + +require ( + github.com/DataDog/zstd v1.5.2 // indirect + github.com/VictoriaMetrics/fastcache v1.12.1 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/cockroachdb/errors v1.9.1 // indirect + github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect + github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 // indirect + github.com/cockroachdb/redact v1.1.3 // indirect + github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect + github.com/consensys/bavard v0.1.13 // indirect + github.com/consensys/gnark-crypto v0.12.1 // indirect + github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 // indirect + github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect + github.com/ethereum/c-kzg-4844 v0.4.0 // indirect + github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect + github.com/getsentry/sentry-go v0.18.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/holiman/bloomfilter/v2 v2.0.3 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mmcloughlin/addchain v0.4.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.62.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/rogpeppe/go-internal v1.12.0 // indirect + github.com/shirou/gopsutil v3.21.11+incompatible // indirect + github.com/supranational/blst v0.3.14 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/tmplfunc v0.0.3 // indirect +) + +replace github.com/ava-labs/firewood-go-ethhash/ffi => ../../ diff --git a/firewood/ffi/tests/eth/go.sum b/firewood/ffi/tests/eth/go.sum new file mode 100644 index 000000000000..a553aa139038 --- /dev/null +++ b/firewood/ffi/tests/eth/go.sum @@ -0,0 +1,508 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= +github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/ava-labs/libevm v1.13.14-0.2.0.release h1:uKGCc5/ceeBbfAPRVtBUxbQt50WzB2pEDb8Uy93ePgQ= +github.com/ava-labs/libevm v1.13.14-0.2.0.release/go.mod h1:+Iol+sVQ1KyoBsHf3veyrBmHCXr3xXRWq6ZXkgVfNLU= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= +github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f h1:otljaYPt5hWxV3MUfO5dFPFiOXg9CyG5/kCfayTqsJ4= +github.com/cockroachdb/datadriven v1.0.3-0.20230413201302-be42291fc80f/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= +github.com/cockroachdb/logtags v0.0.0-20211118104740-dabe8e521a4f/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvDmeyi+l/FS/VtA00IWvjeFvjen1m1l1A= +github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= +github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= +github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= +github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233 h1:d28BXYi+wUpz1KBmiF9bWrjEMacUEREV6MBi2ODnrfQ= +github.com/crate-crypto/go-ipa v0.0.0-20231025140028-3c0104f4b233/go.mod h1:geZJZH3SzKCqnz5VT0q/DyIG/tvu/dZk+VIfXicupJs= +github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= +github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY= +github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 h1:BAIP2GihuqhwdILrV+7GJel5lyPV3u1+PgzrWLc0TkE= +github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46/go.mod h1:QNpY22eby74jVhqH4WhDLDwxc/vqsern6pW+u2kbkpc= +github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= +github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA= +github.com/holiman/uint256 v1.3.2/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= +github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= +github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= +github.com/kataras/neffos v0.0.14/go.mod h1:8lqADm8PnbeFfL7CLXh1WHw53dG27MC3pgi2R1rmoTE= +github.com/kataras/pio v0.0.2/go.mod h1:hAoW0t9UmXi4R5Oyq5Z4irTbaTsOemSrDGUtaTl7Dro= +github.com/kataras/sitemap v0.0.5/go.mod h1:KY2eugMKiPwsJgx7+U103YZehfvNGOXURubcGyk0Bz8= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= +github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= +github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= +github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= +github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/supranational/blst v0.3.14 h1:xNMoHRJOTwMn63ip6qoWJ2Ymgvj7E2b9jY2FAwY+qRo= +github.com/supranational/blst v0.3.14/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= +github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA= +golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ= +golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20191120175047-4206685974f2/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= +rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= diff --git a/firewood/ffi/tests/firewood/BUILD.bazel b/firewood/ffi/tests/firewood/BUILD.bazel new file mode 100644 index 000000000000..d6633815021e --- /dev/null +++ b/firewood/ffi/tests/firewood/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_test") + +go_test( + name = "firewood_test", + srcs = ["merkle_compatibility_test.go"], + deps = [ + "//database", + "//database/memdb", + "//ids", + "//x/merkledb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/firewood/ffi/tests/firewood/go.mod b/firewood/ffi/tests/firewood/go.mod new file mode 100644 index 000000000000..f2eb01aba20c --- /dev/null +++ b/firewood/ffi/tests/firewood/go.mod @@ -0,0 +1,57 @@ +module github.com/ava-labs/firewood/ffi/tests/firewood + +go 1.24.0 + +toolchain go1.24.9 + +require ( + github.com/ava-labs/firewood-go/ffi v0.0.0 // this is replaced to use the parent folder + github.com/stretchr/testify v1.10.0 +) + +require github.com/ava-labs/avalanchego v1.13.1 + +require ( + github.com/BurntSushi/toml v1.2.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/google/renameio/v2 v2.0.0 // indirect + github.com/gorilla/rpc v1.2.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.22.0 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.62.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + go.opentelemetry.io/otel v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect + go.opentelemetry.io/otel/metric v1.22.0 // indirect + go.opentelemetry.io/otel/sdk v1.22.0 // indirect + go.opentelemetry.io/otel/trace v1.22.0 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/term v0.37.0 // indirect + golang.org/x/text v0.31.0 // indirect + gonum.org/v1/gonum v0.11.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed // indirect + google.golang.org/grpc v1.66.0 // indirect + google.golang.org/protobuf v1.36.5 // indirect + gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) + +replace github.com/ava-labs/firewood-go/ffi => ../../ diff --git a/firewood/ffi/tests/firewood/go.sum b/firewood/ffi/tests/firewood/go.sum new file mode 100644 index 000000000000..321999ea8f96 --- /dev/null +++ b/firewood/ffi/tests/firewood/go.sum @@ -0,0 +1,110 @@ +github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/ava-labs/avalanchego v1.13.1 h1:sviA3MJbY00xYl77ru4vs9yiz7uTnAYfHpqYFucoXEE= +github.com/ava-labs/avalanchego v1.13.1/go.mod h1:h8VRoqOhLRzqSlBpgFSOtCIu2Hey2FxgjD3pBkOXOY8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg= +github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= +github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk= +github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/sanity-io/litter v1.5.1 h1:dwnrSypP6q56o3lFxTU+t2fwQ9A+U5qrXVO4Qg9KwVU= +github.com/sanity-io/litter v1.5.1/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/thepudds/fzgen v0.4.3 h1:srUP/34BulQaEwPP/uHZkdjUcUjIzL7Jkf4CBVryiP8= +github.com/thepudds/fzgen v0.4.3/go.mod h1:BhhwtRhzgvLWAjjcHDJ9pEiLD2Z9hrVIFjBCHJ//zJ4= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= +go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e h1:4qufH0hlUYs6AO6XmZC3GqfDPGSXHVXUFR6OND+iJX4= +golang.org/x/exp v0.0.0-20241215155358-4a5509556b9e/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/term v0.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= +golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= +google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed h1:J6izYgfBXAI3xTKLgxzTmUltdYaLsuBxFCgDHWJ/eXg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c= +google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= +google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/firewood/ffi/tests/firewood/merkle_compatibility_test.go b/firewood/ffi/tests/firewood/merkle_compatibility_test.go new file mode 100644 index 000000000000..a3df63d9f071 --- /dev/null +++ b/firewood/ffi/tests/firewood/merkle_compatibility_test.go @@ -0,0 +1,437 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +package firewood + +import ( + "context" + "fmt" + "math/rand" + "path/filepath" + "slices" + "testing" + + firewood "github.com/ava-labs/firewood-go/ffi" + + "github.com/ava-labs/avalanchego/database" + "github.com/ava-labs/avalanchego/database/memdb" + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/x/merkledb" + "github.com/stretchr/testify/require" +) + +const ( + keySize = 4 + valSize = 4 + maxBatchSize = 5 + maxNumKeys = 10_000 +) + +const ( + dbGet byte = iota + dbUpdate + dbBatch + checkDBHash + createProposalOnProposal + createProposalOnDB + proposalGet + commitProposal + maxStep +) + +var stepMap = map[byte]string{ + dbGet: "dbGet", + dbUpdate: "dbUpdate", + dbBatch: "dbBatch", + checkDBHash: "checkDBHash", + createProposalOnProposal: "createProposalOnProposal", + createProposalOnDB: "createProposalOnDB", + proposalGet: "proposalGet", + commitProposal: "commitProposal", +} + +func newTestFirewoodDatabase(t *testing.T) *firewood.Database { + t.Helper() + + dbFile := filepath.Join(t.TempDir(), "test.db") + db, err := newFirewoodDatabase(dbFile) + require.NoError(t, err) + t.Cleanup(func() { + require.NoError(t, db.Close(context.Background())) //nolint:usetesting // t.Context() will already be cancelled + }) + return db +} + +func newFirewoodDatabase(dbFile string) (*firewood.Database, error) { + conf := firewood.DefaultConfig() + f, err := firewood.New(dbFile, conf) + if err != nil { + return nil, fmt.Errorf("failed to create new database at filepath %q: %w", dbFile, err) + } + return f, nil +} + +type tree struct { + require *require.Assertions + rand *rand.Rand + + id int + nextID int + merkleDB merkledb.MerkleDB + fwdDB *firewood.Database + + children []*proposal + + proposals map[int]*proposal + keys [][]byte +} + +type proposal struct { + parentID int + id int + merkleView merkledb.View + fwdView *firewood.Proposal + + children []*proposal +} + +func newTestTree(t *testing.T, rand *rand.Rand) *tree { + r := require.New(t) + + memdb := memdb.New() + merkleDB, err := merkledb.New(context.Background(), memdb, merkledb.NewConfig()) + r.NoError(err) + + tr := &tree{ + merkleDB: merkleDB, + fwdDB: newTestFirewoodDatabase(t), + proposals: make(map[int]*proposal), + children: make([]*proposal, 0), + require: r, + rand: rand, + keys: createRandomByteSlices(min(1, rand.Intn(maxNumKeys)), keySize, rand), + } + return tr +} + +func (tr *tree) selectRandomProposal() *proposal { + if len(tr.proposals) == 0 { + return nil + } + + proposalIDs := make([]int, 0, len(tr.proposals)) + for proposalID := range tr.proposals { + proposalIDs = append(proposalIDs, proposalID) + } + slices.Sort(proposalIDs) + selectedProposalID := tr.rand.Intn(len(proposalIDs)) + return tr.proposals[selectedProposalID] +} + +func (tr *tree) dropAllProposals() { + // Drop all firewood proposals out of order (allowed by firewood). + for _, p := range tr.proposals { + tr.require.NoError(p.fwdView.Drop()) + } + // Free pointers at the root to allow garbage collection. + // MerkleDB does not require explicitly dropping merkle views, so clearing the + // pointers at the root is sufficient. + tr.children = nil + tr.proposals = make(map[int]*proposal) +} + +func (tr *tree) dbUpdate() { + key := tr.keys[tr.rand.Intn(len(tr.keys))] + val := createRandomSlice(valSize, tr.rand) + + // Insert the key-value pair into both databases. + tr.require.NoError(tr.merkleDB.Put(key, val)) + _, err := tr.fwdDB.Update([][]byte{key}, [][]byte{val}) + tr.require.NoError(err) + + tr.dropAllProposals() +} + +func (tr *tree) createRandomBatch(numKeys int) ([][]byte, [][]byte) { + keys := tr.selectRandomKeys(numKeys) + vals := createRandomByteSlices(len(keys), valSize, tr.rand) + return keys, vals +} + +func (tr *tree) selectRandomKeys(numKeys int) [][]byte { + numKeys = min(numKeys, len(tr.keys)) + selectedKeys := make([][]byte, numKeys) + for i := 0; i < numKeys; i++ { + selectedKeys[i] = tr.keys[tr.rand.Intn(len(tr.keys))] + } + return selectedKeys +} + +func (tr *tree) dbGet() { + keys := tr.selectRandomKeys(maxBatchSize) + for _, key := range keys { + fwdVal, fwdErr := tr.fwdDB.Get(key) + merkleVal, merkleErr := tr.merkleDB.GetValue(context.Background(), key) + tr.testGetResult(merkleVal, merkleErr, fwdVal, fwdErr) + } +} + +func (tr *tree) testGetResult(merkleVal []byte, merkleErr error, fwdVal []byte, fwdErr error) { + if merkleErr == database.ErrNotFound { + tr.require.Nil(merkleVal) + tr.require.NoError(fwdErr) + tr.require.Nil(fwdVal) + return + } + tr.require.NoError(merkleErr) + tr.require.NoError(fwdErr) + tr.require.Equal(fwdVal, merkleVal) +} + +func (tr *tree) dbBatch() { + batchSize := tr.rand.Intn(maxBatchSize) + 1 // XXX: ensure at least one KV pair to avoid firewood empty revision errors + keys, vals := tr.createRandomBatch(batchSize) + + batch := tr.merkleDB.NewBatch() + for i := range len(keys) { + tr.require.NoError(batch.Put(keys[i], vals[i])) + } + tr.require.NoError(batch.Write()) + + _, err := tr.fwdDB.Update(keys, vals) + tr.require.NoError(err) + + tr.dropAllProposals() +} + +func (tr *tree) commitRandomProposal() { + childIndex := tr.rand.Intn(len(tr.children)) // assumes non-zero number of children + + commitProposal := tr.children[childIndex] + tr.require.NoError(commitProposal.fwdView.Commit()) + tr.require.NoError(commitProposal.merkleView.CommitToDB(context.Background())) + delete(tr.proposals, commitProposal.id) + + remainingChildren := tr.children + for i := 0; i < len(remainingChildren); i++ { + dropChild := remainingChildren[i] + if dropChild.id == commitProposal.id { + continue + } + tr.require.NoError(dropChild.fwdView.Drop()) + delete(tr.proposals, dropChild.id) + + remainingChildren = append(remainingChildren, dropChild.children...) + } + + tr.children = commitProposal.children +} + +func (tr *tree) checkDBHash() { + // Get the root hash from both databases. + merkleRoot, err := tr.merkleDB.GetMerkleRoot(context.Background()) + tr.require.NoError(err) + + fwdRoot, err := tr.fwdDB.Root() + tr.require.NoError(err) + + // Compare the root hashes. + tr.require.Equal(merkleRoot, ids.ID(fwdRoot)) +} + +func (tr *tree) createProposalOnProposal() { + pr := tr.selectRandomProposal() + + if pr == nil { + return + } + + batchSize := tr.rand.Intn(maxBatchSize) + 1 // ensure at least one key-value pair + keys, vals := tr.createRandomBatch(batchSize) + + fwdPr := pr.fwdView + merkleView := pr.merkleView + + fwdChildPr, err := fwdPr.Propose(keys, vals) + tr.require.NoError(err) + + merkleViewChange := merkledb.ViewChanges{} + for i := range keys { + merkleViewChange.BatchOps = append(merkleViewChange.BatchOps, database.BatchOp{ + Key: keys[i], + Value: vals[i], + }) + } + merkleChildView, err := merkleView.NewView(context.Background(), merkleViewChange) + tr.require.NoError(err) + + fwdRoot, err := fwdChildPr.Root() + tr.require.NoError(err) + merkleRoot, err := merkleChildView.GetMerkleRoot(context.Background()) + tr.require.NoError(err) + tr.require.Equal(merkleRoot, ids.ID(fwdRoot)) + + tr.nextID++ + newProposal := &proposal{ + parentID: pr.id, + id: tr.nextID, + merkleView: merkleChildView, + fwdView: fwdChildPr, + } + pr.children = append(pr.children, newProposal) + tr.proposals[newProposal.id] = newProposal +} + +func (tr *tree) createProposalOnDB() { + batchSize := tr.rand.Intn(maxBatchSize) + 1 // ensure at least one key-value pair + keys, vals := tr.createRandomBatch(batchSize) + fwdPr, err := tr.fwdDB.Propose(keys, vals) + tr.require.NoError(err) + + merkleViewChange := merkledb.ViewChanges{} + for i := range keys { + merkleViewChange.BatchOps = append(merkleViewChange.BatchOps, database.BatchOp{ + Key: keys[i], + Value: vals[i], + }) + } + merkleChildView, err := tr.merkleDB.NewView(context.Background(), merkleViewChange) + tr.require.NoError(err) + + fwdRoot, err := fwdPr.Root() + tr.require.NoError(err) + merkleRoot, err := merkleChildView.GetMerkleRoot(context.Background()) + tr.require.NoError(err) + tr.require.Equal(merkleRoot, ids.ID(fwdRoot)) + + tr.nextID++ + newProposal := &proposal{ + parentID: tr.id, + id: tr.nextID, + merkleView: merkleChildView, + fwdView: fwdPr, + } + tr.children = append(tr.children, newProposal) + tr.proposals[newProposal.id] = newProposal +} + +func (tr *tree) proposalGet() { + pr := tr.selectRandomProposal() + if pr == nil { + return + } + + keys := tr.selectRandomKeys(maxBatchSize) + for _, key := range keys { + fwdVal, fwdErr := pr.fwdView.Get(key) + merkleVal, merkleErr := pr.merkleView.GetValue(context.Background(), key) + + tr.testGetResult(merkleVal, merkleErr, fwdVal, fwdErr) + } +} + +func (tr *tree) commitProposal() { + if len(tr.children) == 0 { + return // no proposals to commit + } + tr.commitRandomProposal() +} + +func fuzzTree(t *testing.T, randSource int64, byteSteps []byte) { + rand := rand.New(rand.NewSource(randSource)) + + if len(byteSteps) > 100 { + byteSteps = byteSteps[:100] // limit the number of steps to 100 + } + + tr := newTestTree(t, rand) + + // TODO: replace randomly generated values with bytes from the fuzzer + for _, step := range byteSteps { + step = step % maxStep + // Make this two lines so debugger displays the stepStr value + stepStr := stepMap[step] + t.Log(stepStr) + switch step { + case dbGet: + tr.dbGet() + case dbUpdate: + tr.dbUpdate() + case dbBatch: + tr.dbBatch() + case checkDBHash: + tr.checkDBHash() + case createProposalOnProposal: + tr.createProposalOnProposal() + case createProposalOnDB: + tr.createProposalOnDB() + case proposalGet: + tr.proposalGet() + case commitProposal: + tr.commitProposal() + } + } +} + +func FuzzTree(f *testing.F) { + // Add interesting sequences to the fuzzer with a few different random seeds. + for i := range 5 { + f.Add(int64(i), []byte{ + createProposalOnDB, + createProposalOnDB, + createProposalOnProposal, + createProposalOnProposal, + createProposalOnDB, + dbGet, + proposalGet, + createProposalOnDB, + createProposalOnProposal, + commitProposal, + checkDBHash, + createProposalOnDB, + createProposalOnProposal, + commitProposal, + }) + f.Add(int64(i), []byte{ + dbUpdate, + dbGet, + dbBatch, + createProposalOnDB, + checkDBHash, + createProposalOnProposal, + commitProposal, + checkDBHash, + commitProposal, + }) + f.Add(int64(i), []byte{ + dbBatch, + dbBatch, + dbBatch, + dbGet, + createProposalOnDB, + createProposalOnProposal, + commitProposal, + commitProposal, + checkDBHash, + }) + } + f.Fuzz(fuzzTree) +} + +func createRandomSlice(maxSize int, rand *rand.Rand) []byte { + sliceSize := rand.Intn(maxSize) + 1 // always create non-empty slices + slice := make([]byte, sliceSize) + _, err := rand.Read(slice) + if err != nil { + panic(err) + } + return slice +} + +func createRandomByteSlices(numSlices int, maxSliceSize int, rand *rand.Rand) [][]byte { + slices := make([][]byte, numSlices) + for i := 0; i < numSlices; i++ { + slices[i] = createRandomSlice(maxSliceSize, rand) + } + return slices +} diff --git a/firewood/firewood-macros/BUILD.bazel b/firewood/firewood-macros/BUILD.bazel new file mode 100644 index 000000000000..b5bef6da30fa --- /dev/null +++ b/firewood/firewood-macros/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_rust//rust:defs.bzl", "rust_proc_macro") + +exports_files(["Cargo.toml"]) + +rust_proc_macro( + name = "firewood-macros", + srcs = glob(["src/**/*.rs"]), + crate_root = "src/lib.rs", + edition = "2024", + visibility = ["//firewood:__subpackages__"], + deps = [ + "@firewood_crates//:proc-macro2", + "@firewood_crates//:quote", + "@firewood_crates//:syn", + ], +) diff --git a/firewood/firewood-macros/Cargo.toml b/firewood/firewood-macros/Cargo.toml new file mode 100644 index 000000000000..f3e5fb905c6c --- /dev/null +++ b/firewood/firewood-macros/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "firewood-macros" +version.workspace = true +edition.workspace = true +authors = [ + "Ron Kuris ", +] +description = "Proc macros for Firewood metrics" +license-file.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true + +[lib] +proc-macro = true + +[dependencies] +# Regular dependencies +proc-macro2 = "1.0" +quote = "1.0" +syn = { version = "2.0", features = ["full", "extra-traits"] } + +[dev-dependencies] +# Workspace dependencies +coarsetime.workspace = true +metrics.workspace = true +# Regular dependencies +trybuild = "1.0" + +[lints] +workspace = true diff --git a/firewood/firewood-macros/README.md b/firewood/firewood-macros/README.md new file mode 100644 index 000000000000..35bfeebd145f --- /dev/null +++ b/firewood/firewood-macros/README.md @@ -0,0 +1,158 @@ +# Firewood Macros + +A Rust procedural macro crate providing zero-allocation metrics instrumentation for the Firewood database. + +## Overview + +This crate provides the `#[metrics]` attribute macro that automatically instruments functions with performance metrics collection. The macro is designed for high-performance applications where allocation overhead during metrics collection is unacceptable. + +## Features + +- **Zero Runtime Allocations**: Uses compile-time string concatenation and static label arrays +- **Automatic Timing**: Measures function execution time with microsecond precision +- **Success/Failure Tracking**: Automatically labels metrics based on `Result` return values +- **Metric Descriptions**: Optional human-readable descriptions for better observability +- **Compile-time Validation**: Ensures functions return `Result` types + +## Usage + +Add the dependency to your `Cargo.toml`: + +```toml +[dependencies] +firewood-macros.workspace = true +metrics = "0.24" +coarsetime = "0.1" +``` + +### Basic Usage + +```rust +use firewood_macros::metrics; + +#[metrics("firewood.example")] +fn example() -> Result, DatabaseError> { + // Your function implementation + Ok(vec![]) +} +``` + +### With Description + +```rust +#[metrics("firewood.example", "example operation")] +fn example(user: User) -> Result<(), DatabaseError> { + // Your function implementation + Ok(()) +} +``` + +## Generated Metrics + +For each instrumented function, the macro generates two metrics: + +1. **Count Metric** (base name): Tracks the number of function calls +2. **Timing Metric** (base name + "_ms"): Tracks execution time in milliseconds + +Both metrics include a `success` label: + +- `success="true"` for `Ok(_)` results +- `success="false"` for `Err(_)` results + +### Example Output + +For `#[metrics("firewood.query", "data retrieval")]`: + +- `firewood.example{success="true"}` - Count of successful queries +- `firewood.example{success="false"}` - Count of failed queries +- `firewood.example_ms{success="true"}` - Timing of successful queries +- `firewood.example_ms{success="false"}` - Timing of failed queries + +## Requirements + +- Functions must return a `Result` type +- The `metrics` and `coarsetime` crates must be available in scope +- Rust 1.70+ (for `is_some_and` method) + +## Performance Characteristics + +### Zero Allocations + +The macro generates code that avoids all runtime allocations: + +```rust +// Static label arrays (no allocation) +static __METRICS_LABELS_SUCCESS: &[(&str, &str)] = &[("success", "true")]; +static __METRICS_LABELS_ERROR: &[(&str, &str)] = &[("success", "false")]; + +// Compile-time string concatenation (no allocation) +metrics::counter!(concat!("my.metric", "_ms"), labels) +``` + +### Minimal Overhead + +- Single timestamp capture at function start, using the coarsetime crate, which is known to be extremely fast +- Branch-free label selection based on `Result::is_err()` +- Direct counter increments without intermediate allocations + +## Implementation Details + +### Code Generation + +The macro transforms this: + +```rust +#[metrics("my.operation")] +fn my_function() -> Result { + Ok("result".to_string()) +} +``` + +Into approximately this: + +```rust +fn my_function() -> Result { + // Register metrics (once per process) + static __METRICS_REGISTERED: std::sync::Once = std::sync::Once::new(); + __METRICS_REGISTERED.call_once(|| { + metrics::describe_counter!("my.operation", "Operation counter"); + metrics::describe_counter!(concat!("my.operation", "_ms"), "Operation timing"); + }); + + // Start timing + let __metrics_start = coarsetime::Instant::now(); + + // Execute original function + let __metrics_result = (|| { + Ok("result".to_string()) + })(); + + // Record metrics + static __METRICS_LABELS_SUCCESS: &[(&str, &str)] = &[("success", "true")]; + static __METRICS_LABELS_ERROR: &[(&str, &str)] = &[("success", "false")]; + let __metrics_labels = if __metrics_result.is_err() { + __METRICS_LABELS_ERROR + } else { + __METRICS_LABELS_SUCCESS + }; + + metrics::counter!("my.operation", __metrics_labels).increment(1); + metrics::counter!(concat!("my.operation", "_ms"), __metrics_labels) + .increment(__metrics_start.elapsed().as_millis()); + + __metrics_result +} +``` + +## Testing + +The crate includes comprehensive tests: + +```bash +cargo test -p firewood-macros +``` + +## License + +This crate is part of the Firewood project and follows the same licensing terms. +See LICENSE.md at the top level for details. diff --git a/firewood/firewood-macros/src/lib.rs b/firewood/firewood-macros/src/lib.rs new file mode 100644 index 000000000000..b6d8a30af686 --- /dev/null +++ b/firewood/firewood-macros/src/lib.rs @@ -0,0 +1,293 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! Proc macros for Firewood metrics + +use proc_macro::TokenStream; +use quote::quote; +use syn::parse::{Parse, ParseStream}; +use syn::{ItemFn, Lit, ReturnType, Token, parse_macro_input}; + +/// Arguments for the metrics macro +struct MetricsArgs { + name: String, + description: Option, +} + +impl Parse for MetricsArgs { + fn parse(input: ParseStream) -> syn::Result { + let name_lit: Lit = input.parse()?; + let name = match name_lit { + Lit::Str(s) => s.value(), + _ => { + return Err(syn::Error::new_spanned( + name_lit, + "Expected string literal for metric name", + )); + } + }; + + let description = if input.parse::().is_ok() { + let desc_lit: Lit = input.parse()?; + match desc_lit { + Lit::Str(s) => Some(s.value()), + _ => { + return Err(syn::Error::new_spanned( + desc_lit, + "Expected string literal for description", + )); + } + } + } else { + None + }; + + Ok(MetricsArgs { name, description }) + } +} + +/// A proc macro attribute that automatically adds metrics timing to functions. +/// +/// This macro adds timing instrumentation to functions that return `Result`. +/// It generates two counters: +/// 1. A count counter with the provided prefix that increments by 1 +/// 2. A timing counter with the prefix + "_ms" that records elapsed time in milliseconds +/// +/// Both counters include a "success" label that is "true" for Ok results and "false" for Err results. +/// The metrics are automatically registered with descriptions for better observability. +/// +/// # Usage +/// ```rust,ignore +/// use firewood_macros::metrics; +/// +/// // Basic usage with just a metric name +/// #[metrics("my.operation")] +/// fn my_function() -> Result { +/// // function body +/// Ok("success".to_string()) +/// } +/// +/// // With an optional description +/// #[metrics("my.operation", "Description of what this operation does")] +/// fn my_function_with_desc() -> Result { +/// // function body +/// Ok("success".to_string()) +/// } +/// ``` +/// +/// # Generated Code +/// The macro transforms the function to include: +/// - Metric registration with descriptions at the beginning +/// - A timer start at the beginning of the function +/// - Metrics collection before returning, with success/failure labels +/// - Preservation of the original return value +/// +/// # Requirements +/// - The function must return a `Result` type +/// - The `metrics` and `coarsetime` crates must be available +#[proc_macro_attribute] +pub fn metrics(args: TokenStream, input: TokenStream) -> TokenStream { + let input_fn = parse_macro_input!(input as ItemFn); + + // Parse the attribute arguments - expecting metric name and optional description + let (metric_prefix, description) = if args.is_empty() { + return syn::Error::new_spanned( + &input_fn, + "Expected string literal for metric prefix, e.g., #[metrics(\"my.operation\")] or #[metrics(\"my.operation\", \"description\")]", + ) + .to_compile_error() + .into(); + } else { + match syn::parse::(args) { + Ok(parsed_args) => (parsed_args.name, parsed_args.description), + Err(e) => { + return syn::Error::new( + e.span(), + "Expected string literal(s) for metric name and optional description", + ) + .to_compile_error() + .into(); + } + } + }; + + // Validate that the function returns a Result + let return_type = match &input_fn.sig.output { + ReturnType::Type(_, ty) => ty, + ReturnType::Default => { + return syn::Error::new_spanned( + &input_fn.sig, + "Function must return a Result to use #[metrics] attribute", + ) + .to_compile_error() + .into(); + } + }; + + // Check if it's a Result type (this is a simple check, could be more sophisticated) + let is_result = match return_type.as_ref() { + syn::Type::Path(type_path) => type_path + .path + .segments + .last() + .is_some_and(|seg| seg.ident == "Result"), + _ => false, + }; + + if !is_result { + return syn::Error::new_spanned( + return_type, + "Function must return a Result to use #[metrics] attribute", + ) + .to_compile_error() + .into(); + } + + let args = MetricsArgs { + name: metric_prefix, + description, + }; + + let expanded = generate_metrics_wrapper(&input_fn, &args); + TokenStream::from(expanded) +} + +fn generate_metrics_wrapper(input_fn: &ItemFn, args: &MetricsArgs) -> proc_macro2::TokenStream { + let fn_vis = &input_fn.vis; + let fn_sig = &input_fn.sig; + let fn_block = &input_fn.block; + let fn_attrs = &input_fn.attrs; + let metric_prefix = &args.name; + + // Generate description registration code if description is provided + let registration_code = if let Some(desc) = &args.description { + let count_desc = format!("Number of {desc} operations"); + let timing_desc = format!("Timing of {desc} operations in milliseconds"); + quote! { + // Register metrics with descriptions (only runs once due to static guard) + static __METRICS_REGISTERED: std::sync::Once = std::sync::Once::new(); + __METRICS_REGISTERED.call_once(|| { + metrics::describe_counter!(#metric_prefix, #count_desc); + metrics::describe_counter!(concat!(#metric_prefix, "_ms"), #timing_desc); + }); + } + } else { + quote! { + // Register metrics without descriptions (only runs once due to static guard) + static __METRICS_REGISTERED: std::sync::Once = std::sync::Once::new(); + __METRICS_REGISTERED.call_once(|| { + metrics::describe_counter!(#metric_prefix, "Operation counter"); + metrics::describe_counter!(concat!(#metric_prefix, "_ms"), "Operation timing in milliseconds"); + }); + } + }; + + quote! { + #(#fn_attrs)* + #fn_vis #fn_sig { + #registration_code + + let __metrics_start = coarsetime::Instant::now(); + + let __metrics_result = { #fn_block }; + + // Use static label arrays to avoid runtime allocation + static __METRICS_LABELS_SUCCESS: &[(&str, &str)] = &[("success", "true")]; + static __METRICS_LABELS_ERROR: &[(&str, &str)] = &[("success", "false")]; + let __metrics_labels = if __metrics_result.is_err() { + __METRICS_LABELS_ERROR + } else { + __METRICS_LABELS_SUCCESS + }; + + // Increment count counter (base name) + metrics::counter!(#metric_prefix, __metrics_labels).increment(1); + + // Increment timing counter (base name + "_ms") using compile-time concatenation + metrics::counter!(concat!(#metric_prefix, "_ms"), __metrics_labels) + .increment(__metrics_start.elapsed().as_millis()); + + __metrics_result + } + } +} + +#[cfg(test)] +mod tests { + #![expect(clippy::unwrap_used)] + + use super::*; + + #[test] + fn test_proc_macro_compilation() { + // Test that the proc macro generates compilable code + let t = trybuild::TestCases::new(); + t.pass("tests/compile_pass/*.rs"); + t.compile_fail("tests/compile_fail/*.rs"); + } + + #[test] + fn test_metrics_args_parsing() { + // Test single argument parsing + let input = quote::quote! { "test.metric" }; + let parsed: MetricsArgs = syn::parse2(input).unwrap(); + assert_eq!(parsed.name, "test.metric"); + assert_eq!(parsed.description, None); + + // Test two argument parsing + let input = quote::quote! { "test.metric", "test description" }; + let parsed: MetricsArgs = syn::parse2(input).unwrap(); + assert_eq!(parsed.name, "test.metric"); + assert_eq!(parsed.description, Some("test description".to_string())); + } + + #[test] + fn test_invalid_args_parsing() { + // Test that invalid arguments fail to parse + let input = quote::quote! { 123 }; + let result: syn::Result = syn::parse2(input); + assert!(result.is_err()); + + // Test that too many arguments fail + let input = quote::quote! { "test.metric", "description", "extra" }; + let result: syn::Result = syn::parse2(input); + assert!(result.is_err()); + } + + #[test] + fn test_generated_code_structure() { + // Test that the proc macro generates the expected code structure + use syn::{ItemFn, parse_quote}; + + let input: ItemFn = parse_quote! { + fn test_function() -> Result<(), &'static str> { + Ok(()) + } + }; + + let args = MetricsArgs { + name: "test.metric".to_string(), + description: Some("test description".to_string()), + }; + + let result = generate_metrics_wrapper(&input, &args); + let generated_code = result.to_string(); + + // Verify key components are present in the generated code + assert!(generated_code.contains("__METRICS_LABELS_SUCCESS")); + assert!(generated_code.contains("__METRICS_LABELS_ERROR")); + assert!(generated_code.contains("test.metric")); + assert!( + generated_code.contains("coarsetime") + && generated_code.contains("Instant") + && generated_code.contains("now") + ); + assert!(generated_code.contains("metrics") && generated_code.contains("counter")); + assert!(generated_code.contains("Number of test description operations")); + assert!(generated_code.contains("Timing of test description operations")); + + // Check for the _ms suffix - it should be generated by concat! + assert!(generated_code.contains("concat") && generated_code.contains('!')); + assert!(generated_code.contains("_ms")); + } +} diff --git a/firewood/firewood-macros/tests/compile_fail/invalid_args.rs b/firewood/firewood-macros/tests/compile_fail/invalid_args.rs new file mode 100644 index 000000000000..da5cc65af250 --- /dev/null +++ b/firewood/firewood-macros/tests/compile_fail/invalid_args.rs @@ -0,0 +1,9 @@ +// Test that metrics macro fails with invalid arguments +use firewood_macros::metrics; + +#[metrics(123)] +fn function_with_invalid_arg() -> Result<(), &'static str> { + Ok(()) +} + +fn main() {} diff --git a/firewood/firewood-macros/tests/compile_fail/invalid_args.stderr b/firewood/firewood-macros/tests/compile_fail/invalid_args.stderr new file mode 100644 index 000000000000..936dbbcb4483 --- /dev/null +++ b/firewood/firewood-macros/tests/compile_fail/invalid_args.stderr @@ -0,0 +1,5 @@ +error: Expected string literal(s) for metric name and optional description + --> tests/compile_fail/invalid_args.rs:4:11 + | +4 | #[metrics(123)] + | ^^^ diff --git a/firewood/firewood-macros/tests/compile_fail/no_args.rs b/firewood/firewood-macros/tests/compile_fail/no_args.rs new file mode 100644 index 000000000000..75a0da7d0486 --- /dev/null +++ b/firewood/firewood-macros/tests/compile_fail/no_args.rs @@ -0,0 +1,9 @@ +// Test that metrics macro fails when no arguments are provided +use firewood_macros::metrics; + +#[metrics()] +fn function_without_args() -> Result<(), &'static str> { + Ok(()) +} + +fn main() {} diff --git a/firewood/firewood-macros/tests/compile_fail/no_args.stderr b/firewood/firewood-macros/tests/compile_fail/no_args.stderr new file mode 100644 index 000000000000..b2035da74ab6 --- /dev/null +++ b/firewood/firewood-macros/tests/compile_fail/no_args.stderr @@ -0,0 +1,7 @@ +error: Expected string literal for metric prefix, e.g., #[metrics("my.operation")] or #[metrics("my.operation", "description")] + --> tests/compile_fail/no_args.rs:5:1 + | +5 | / fn function_without_args() -> Result<(), &'static str> { +6 | | Ok(()) +7 | | } + | |_^ diff --git a/firewood/firewood-macros/tests/compile_fail/non_result_return.rs b/firewood/firewood-macros/tests/compile_fail/non_result_return.rs new file mode 100644 index 000000000000..0dceede2de97 --- /dev/null +++ b/firewood/firewood-macros/tests/compile_fail/non_result_return.rs @@ -0,0 +1,9 @@ +// Test that metrics macro fails when function doesn't return Result +use firewood_macros::metrics; + +#[metrics("test.invalid")] +fn function_without_result() -> i32 { + 42 +} + +fn main() {} diff --git a/firewood/firewood-macros/tests/compile_fail/non_result_return.stderr b/firewood/firewood-macros/tests/compile_fail/non_result_return.stderr new file mode 100644 index 000000000000..5acb329a183a --- /dev/null +++ b/firewood/firewood-macros/tests/compile_fail/non_result_return.stderr @@ -0,0 +1,5 @@ +error: Function must return a Result to use #[metrics] attribute + --> tests/compile_fail/non_result_return.rs:5:33 + | +5 | fn function_without_result() -> i32 { + | ^^^ diff --git a/firewood/firewood-macros/tests/compile_pass/basic_usage.rs b/firewood/firewood-macros/tests/compile_pass/basic_usage.rs new file mode 100644 index 000000000000..1b9c6198cf6f --- /dev/null +++ b/firewood/firewood-macros/tests/compile_pass/basic_usage.rs @@ -0,0 +1,22 @@ +// Test that basic metrics macro usage compiles correctly +use firewood_macros::metrics; + +#[metrics("test.basic")] +fn test_basic_function() -> Result<(), &'static str> { + Ok(()) +} + +#[metrics("test.with_description", "test operation")] +fn test_function_with_description() -> Result> { + Ok("success".to_string()) +} + +#[metrics("test.complex")] +async fn test_async_function() -> Result, std::io::Error> { + Ok(vec![1, 2, 3]) +} + +fn main() { + // These functions should compile but we don't need to call them + // since this is just a compilation test +} diff --git a/firewood/firewood-macros/tests/compile_pass/with_attributes.rs b/firewood/firewood-macros/tests/compile_pass/with_attributes.rs new file mode 100644 index 000000000000..fceaf2b12f76 --- /dev/null +++ b/firewood/firewood-macros/tests/compile_pass/with_attributes.rs @@ -0,0 +1,33 @@ +// Test that metrics macro works with other function attributes +use firewood_macros::metrics; + +#[derive(Debug)] +struct TestError; + +impl std::fmt::Display for TestError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "TestError") + } +} + +impl std::error::Error for TestError {} + +#[metrics("test.with_doc", "documented function")] +/// This function has documentation +pub fn documented_function() -> Result { + Ok(42) +} + +#[inline] +#[metrics("test.inline")] +fn inline_function() -> Result<(), TestError> { + Ok(()) +} + +#[allow(dead_code)] +#[metrics("test.allowed", "function with allow attribute")] +fn function_with_allow() -> Result { + Ok(true) +} + +fn main() {} diff --git a/firewood/firewood/BUILD.bazel b/firewood/firewood/BUILD.bazel new file mode 100644 index 000000000000..2aa4d49a5a7b --- /dev/null +++ b/firewood/firewood/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_rust//rust:defs.bzl", "rust_library") + +exports_files(["Cargo.toml"]) + +rust_library( + name = "firewood", + srcs = glob(["src/**/*.rs"]), + crate_features = [ + "ethhash", + "logger", + ], + crate_root = "src/lib.rs", + edition = "2024", + proc_macro_deps = [ + "//firewood/firewood-macros", + "@firewood_crates//:bytemuck_derive", + "@firewood_crates//:derive-where", + ], + visibility = ["//firewood:__subpackages__"], + deps = [ + "//firewood/storage:firewood-storage", + "@firewood_crates//:bytemuck", + "@firewood_crates//:coarsetime", + "@firewood_crates//:fastrace", + "@firewood_crates//:fjall", + "@firewood_crates//:hex", + "@firewood_crates//:integer-encoding", + "@firewood_crates//:metrics", + "@firewood_crates//:parking_lot", + "@firewood_crates//:rayon", + "@firewood_crates//:thiserror", + "@firewood_crates//:typed-builder", + "@firewood_crates//:weak-table", + ], +) diff --git a/firewood/firewood/Cargo.toml b/firewood/firewood/Cargo.toml new file mode 100644 index 000000000000..ca6daa98ab66 --- /dev/null +++ b/firewood/firewood/Cargo.toml @@ -0,0 +1,86 @@ +[package] +name = "firewood" +version.workspace = true +edition.workspace = true +authors = [ + "Angel Leon ", + "Austin Larson <78000745+alarso16@users.noreply.github.com>", + "Cesar <137245636+nytzuga@users.noreply.github.com>", + "Dan Laine ", + "Dan Sover ", + "Hao Hao ", + "Patrick O'Grady ", + "Richard Pringle ", + "Ron Kuris ", + "Sam Batschelet ", + "xinifinity <113067541+xinifinity@users.noreply.github.com>", +] +description = "Firewood is an embedded key-value store, optimized to store blockchain state." +license-file.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true + +[dependencies] +# Workspace dependencies +bytemuck_derive.workspace = true +bytemuck.workspace = true +coarsetime.workspace = true +fastrace.workspace = true +firewood-macros.workspace = true +hex.workspace = true +integer-encoding.workspace = true +metrics.workspace = true +thiserror.workspace = true +# Regular dependencies +typed-builder = "0.23.1" +rayon = "1.11.0" +parking_lot.workspace = true +fjall = "2.11.2" +derive-where = "1.6.0" +weak-table = "0.3.2" + +[features] +default = [] +nightly = [] +io-uring = ["firewood-storage/io-uring"] +logger = ["firewood-storage/logger"] +branch_factor_256 = ["firewood-storage/branch_factor_256"] +ethhash = ["firewood-storage/ethhash"] + +[dev-dependencies] +# Workspace dependencies +clap = { workspace = true, features = ['derive'] } +criterion.workspace = true +env_logger.workspace = true +ethereum-types.workspace = true +firewood-storage = { workspace = true, features = ["test_utils"] } +firewood-triehash.workspace = true +hex-literal.workspace = true +pprof = { workspace = true, features = ["flamegraph"] } +rand.workspace = true +tempfile.workspace = true +test-case.workspace = true +# Regular dependencies +ctor = "0.6.1" +hash-db = "0.16.0" +plain_hasher = "0.2.3" +rlp = "0.6.1" +sha3 = "0.10.8" + +[[bench]] +name = "hashops" +harness = false + +[target.'cfg(target_os = "linux")'.dependencies] +firewood-storage = { workspace = true, features = ["io-uring"] } + +[target.'cfg(not(target_os = "linux"))'.dependencies] +firewood-storage.workspace = true + +[lints] +workspace = true + +[package.metadata.cargo-machete] +ignored = ["coarsetime", "hex-literal"] diff --git a/firewood/firewood/benches/hashops.rs b/firewood/firewood/benches/hashops.rs new file mode 100644 index 000000000000..8e9e79a0266e --- /dev/null +++ b/firewood/firewood/benches/hashops.rs @@ -0,0 +1,136 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// hash benchmarks; run with 'cargo bench' + +use criterion::profiler::Profiler; +use criterion::{BatchSize, Criterion, criterion_group, criterion_main}; +use firewood::db::{BatchOp, DbConfig}; +use firewood::merkle::Merkle; +use firewood::v2::api::{Db as _, Proposal as _}; +use firewood_storage::{MemStore, NodeStore}; +use pprof::ProfilerGuard; +use rand::{Rng, distr::Alphanumeric}; +use std::fs::File; +use std::iter::repeat_with; +use std::os::raw::c_int; +use std::path::Path; +use std::sync::Arc; + +// To enable flamegraph output +// cargo bench --bench hashops -- --profile-time=N +enum FlamegraphProfiler { + Init(c_int), + Active(ProfilerGuard<'static>), +} + +fn file_error_panic(path: &Path) -> impl FnOnce(T) -> U { + |_| panic!("Error on file `{}`", path.display()) +} + +impl Profiler for FlamegraphProfiler { + #[expect(clippy::unwrap_used)] + fn start_profiling(&mut self, _benchmark_id: &str, _benchmark_dir: &Path) { + if let Self::Init(frequency) = self { + let guard = ProfilerGuard::new(*frequency).unwrap(); + *self = Self::Active(guard); + } + } + + #[expect(clippy::unwrap_used)] + fn stop_profiling(&mut self, _benchmark_id: &str, benchmark_dir: &Path) { + std::fs::create_dir_all(benchmark_dir).unwrap(); + let filename = "firewood-flamegraph.svg"; + let flamegraph_path = benchmark_dir.join(filename); + let flamegraph_file = + File::create(&flamegraph_path).unwrap_or_else(file_error_panic(&flamegraph_path)); + + #[expect(clippy::unwrap_used)] + if let Self::Active(profiler) = self { + profiler + .report() + .build() + .unwrap() + .flamegraph(flamegraph_file) + .unwrap_or_else(file_error_panic(&flamegraph_path)); + } + } +} + +// This benchmark peeks into the merkle layer and times how long it takes +// to insert NKEYS with a key length of KEYSIZE +fn bench_merkle(criterion: &mut Criterion) { + let rng = &firewood_storage::SeededRng::from_option(Some(1234)); + + criterion + .benchmark_group("Merkle") + .sample_size(30) + .bench_function("insert", |b| { + b.iter_batched( + || { + let store = Arc::new(MemStore::new(vec![])); + let nodestore = NodeStore::new_empty_proposal(store); + let merkle = Merkle::from(nodestore); + + let keys: Vec> = + repeat_with(|| rng.sample_iter(&Alphanumeric).take(KEYSIZE).collect()) + .take(NKEYS) + .collect(); + + (merkle, keys) + }, + #[expect(clippy::unwrap_used)] + |(mut merkle, keys)| { + for key in keys { + merkle.insert(&key, Box::new(*b"v")).unwrap(); + } + let _frozen = merkle.hash(); + }, + BatchSize::SmallInput, + ); + }); +} + +#[expect(clippy::unwrap_used)] +fn bench_db(criterion: &mut Criterion) { + const KEY_LEN: usize = 4; + let rng = &firewood_storage::SeededRng::from_option(Some(1234)); + + criterion + .benchmark_group("Db") + .sample_size(30) + .bench_function("commit", |b| { + b.iter_batched( + || { + let batch_ops: Vec<_> = + repeat_with(|| rng.sample_iter(&Alphanumeric).take(KEY_LEN).collect()) + .map(|key: Vec<_>| BatchOp::Put { + key, + value: vec![b'v'], + }) + .take(N) + .collect(); + batch_ops + }, + |batch_ops| { + let db_path = std::env::temp_dir(); + let db_path = db_path.join("benchmark_db"); + let cfg = DbConfig::builder(); + + let db = + firewood::db::Db::new(db_path, cfg.clone().truncate(true).build()).unwrap(); + + db.propose(batch_ops).unwrap().commit().unwrap(); + }, + BatchSize::SmallInput, + ); + }); +} + +criterion_group! { + name = benches; + config = Criterion::default().with_profiler(FlamegraphProfiler::Init(100)); + targets = bench_merkle::<3, 4>, bench_merkle<3, 32>, bench_db::<100> +} + +criterion_main!(benches); diff --git a/firewood/firewood/examples/insert.rs b/firewood/firewood/examples/insert.rs new file mode 100644 index 000000000000..b2f252bdd674 --- /dev/null +++ b/firewood/firewood/examples/insert.rs @@ -0,0 +1,140 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// This example isn't an actual benchmark, it's just an example of how to +// insert some random keys using the front-end API. + +use clap::Parser; +use std::collections::HashMap; +use std::error::Error; +use std::num::NonZeroUsize; +use std::ops::RangeInclusive; +use std::time::Instant; + +use firewood::db::{BatchOp, Db, DbConfig}; +use firewood::manager::RevisionManagerConfig; +use firewood::v2::api::{Db as _, DbView, KeyType, Proposal as _, ValueType}; +use rand::{Rng, distr::Alphanumeric}; + +#[derive(Parser, Debug)] +struct Args { + #[arg(short, long, default_value = "1-64", value_parser = string_to_range)] + keylen: RangeInclusive, + #[arg(short, long, default_value = "32", value_parser = string_to_range)] + valuelen: RangeInclusive, + #[arg(short, long, default_value_t = 1)] + batch_size: usize, + #[arg(short, long, default_value_t = 100)] + number_of_batches: usize, + #[arg(short = 'p', long, default_value_t = 0, value_parser = clap::value_parser!(u16).range(0..=100))] + read_verify_percent: u16, + #[arg(short, long)] + seed: Option, + #[arg(short, long, default_value_t = NonZeroUsize::new(20480).expect("is non-zero"))] + cache_size: NonZeroUsize, + #[arg(short, long, default_value_t = true)] + truncate: bool, + #[arg(short, long, default_value_t = 128)] + revisions: usize, +} + +fn string_to_range(input: &str) -> Result, Box> { + //::Err> { + let parts: Vec<&str> = input.split('-').collect(); + #[expect(clippy::indexing_slicing)] + match parts.len() { + 1 => Ok(input.parse()?..=input.parse()?), + 2 => Ok(parts[0].parse()?..=parts[1].parse()?), + _ => Err("Too many dashes in input string".into()), + } +} + +/// cargo run --release --example insert +fn main() -> Result<(), Box> { + let args = Args::parse(); + + let mgrcfg = RevisionManagerConfig::builder() + .node_cache_size(args.cache_size) + .max_revisions(args.revisions) + .build(); + let cfg = DbConfig::builder() + .truncate(args.truncate) + .manager(mgrcfg) + .build(); + + let db = Db::new("rev_db", cfg).expect("db initiation should succeed"); + + let keys = args.batch_size; + let start = Instant::now(); + + let rng = &firewood_storage::SeededRng::from_option(args.seed); + + for _ in 0..args.number_of_batches { + let keylen = rng.random_range(args.keylen.clone()); + let valuelen = rng.random_range(args.valuelen.clone()); + let batch = (0..keys) + .map(|_| { + ( + rng.sample_iter(&Alphanumeric) + .take(keylen) + .collect::>(), + rng.sample_iter(&Alphanumeric) + .take(valuelen) + .collect::>(), + ) + }) + .map(|(key, value)| BatchOp::Put { key, value }) + .collect::>(); + + let verify = get_keys_to_verify(rng, &batch, args.read_verify_percent); + + #[expect(clippy::unwrap_used)] + let proposal = db.propose(batch.clone()).unwrap(); + proposal.commit()?; + verify_keys(&db, verify)?; + } + + let duration = start.elapsed(); + println!( + "Generated and inserted {} batches of size {keys} in {duration:?}", + args.number_of_batches + ); + + Ok(()) +} + +fn get_keys_to_verify<'a, K: KeyType + 'a, V: ValueType + 'a>( + rng: &firewood_storage::SeededRng, + batch: impl IntoIterator>, + pct: u16, +) -> HashMap<&'a [u8], &'a [u8]> { + if pct == 0 { + HashMap::new() + } else { + batch + .into_iter() + .filter(|_last_key| rng.random_range(0..=100u16.saturating_sub(pct)) == 0) + .map(|op| { + if let BatchOp::Put { key, value } = op { + (key.as_ref(), value.as_ref()) + } else { + unreachable!() + } + }) + .collect() + } +} + +fn verify_keys( + db: &impl firewood::v2::api::Db, + verify: HashMap<&[u8], &[u8]>, +) -> Result<(), firewood::v2::api::Error> { + if !verify.is_empty() { + let hash = db.root_hash()?.expect("root hash should exist"); + let revision = db.revision(hash)?; + for (key, value) in verify { + assert_eq!(Some(value), revision.val(key)?.as_deref()); + } + } + Ok(()) +} diff --git a/firewood/firewood/src/db.rs b/firewood/firewood/src/db.rs new file mode 100644 index 000000000000..c96d5d6b1b38 --- /dev/null +++ b/firewood/firewood/src/db.rs @@ -0,0 +1,1253 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::missing_errors_doc, + reason = "Found 12 occurrences after enabling the lint." +)] + +#[cfg(test)] +mod tests; + +use crate::iter::MerkleKeyValueIter; +use crate::merkle::{Merkle, Value}; +pub use crate::v2::api::BatchOp; +use crate::v2::api::{ + self, ArcDynDbView, FrozenProof, FrozenRangeProof, HashKey, IntoBatchIter, KeyType, + KeyValuePair, OptionalHashKeyExt, +}; + +use crate::manager::{ConfigManager, RevisionManager, RevisionManagerConfig}; +use firewood_storage::{ + CheckOpt, CheckerReport, Committed, FileBacked, FileIoError, HashedNodeReader, + ImmutableProposal, NodeStore, Parentable, ReadableStorage, TrieReader, +}; +use metrics::{counter, describe_counter}; +use std::io::Write; +use std::num::NonZeroUsize; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use thiserror::Error; +use typed_builder::TypedBuilder; + +use crate::merkle::parallel::ParallelMerkle; + +#[derive(Error, Debug)] +#[non_exhaustive] +/// Represents the different types of errors that can occur in the database. +pub enum DbError { + /// I/O error + #[error("I/O error: {0:?}")] + FileIo(#[from] FileIoError), +} + +/// Metrics for the database. +/// TODO: Add more metrics +pub struct DbMetrics { + proposals: metrics::Counter, +} + +impl std::fmt::Debug for DbMetrics { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("DbMetrics").finish() + } +} + +impl api::DbView for NodeStore +where + NodeStore: TrieReader, +{ + type Iter<'view> + = MerkleKeyValueIter<'view, Self> + where + Self: 'view; + + fn root_hash(&self) -> Result, api::Error> { + Ok(HashedNodeReader::root_hash(self).or_default_root_hash()) + } + + fn val(&self, key: K) -> Result, api::Error> { + let merkle = Merkle::from(self); + Ok(merkle.get_value(key.as_ref())?) + } + + fn single_key_proof(&self, key: K) -> Result { + let merkle = Merkle::from(self); + merkle.prove(key.as_ref()).map_err(api::Error::from) + } + + fn range_proof( + &self, + first_key: Option, + last_key: Option, + limit: Option, + ) -> Result { + Merkle::from(self).range_proof( + first_key.as_ref().map(AsRef::as_ref), + last_key.as_ref().map(AsRef::as_ref), + limit, + ) + } + + fn iter_option(&self, first_key: Option) -> Result, api::Error> { + match first_key { + Some(key) => Ok(MerkleKeyValueIter::from_key(self, key)), + None => Ok(MerkleKeyValueIter::from(self)), + } + } +} + +#[allow(dead_code)] +#[derive(Clone, Debug)] +pub enum UseParallel { + Never, + BatchSize(usize), + Always, +} + +/// Database configuration. +#[derive(Clone, TypedBuilder, Debug)] +#[non_exhaustive] +pub struct DbConfig { + /// Whether to create the DB if it doesn't exist. + #[builder(default = true)] + pub create_if_missing: bool, + /// Whether to truncate the DB when opening it. If set, the DB will be reset and all its + /// existing contents will be lost. + #[builder(default = false)] + pub truncate: bool, + /// Revision manager configuration. + #[builder(default = RevisionManagerConfig::builder().build())] + pub manager: RevisionManagerConfig, + // Whether to perform parallel proposal creation. If set to BatchSize, then firewood + // performs parallel proposal creation if the batch is >= to the BatchSize value. + // TODO: Experimentally determine the right value for BatchSize. + #[builder(default = UseParallel::BatchSize(8))] + pub use_parallel: UseParallel, + /// `RootStore` directory path + #[builder(default = None)] + pub root_store_dir: Option, +} + +#[derive(Debug)] +/// A database instance. +pub struct Db { + metrics: Arc, + manager: RevisionManager, + use_parallel: UseParallel, +} + +impl api::Db for Db { + type Historical = NodeStore; + + type Proposal<'db> + = Proposal<'db> + where + Self: 'db; + + fn revision(&self, root_hash: HashKey) -> Result, api::Error> { + let nodestore = self.manager.revision(root_hash)?; + Ok(nodestore) + } + + fn root_hash(&self) -> Result, api::Error> { + Ok(self.manager.root_hash()?.or_default_root_hash()) + } + + fn all_hashes(&self) -> Result, api::Error> { + Ok(self.manager.all_hashes()) + } + + fn propose(&self, batch: impl IntoBatchIter) -> Result, api::Error> { + self.propose_with_parent(batch, &self.manager.current_revision()) + } +} + +impl Db { + /// Create a new database instance. + pub fn new>(db_path: P, cfg: DbConfig) -> Result { + let metrics = Arc::new(DbMetrics { + proposals: counter!("firewood.proposals"), + }); + describe_counter!("firewood.proposals", "Number of proposals created"); + let config_manager = ConfigManager::builder() + .create(cfg.create_if_missing) + .truncate(cfg.truncate) + .root_store_dir(cfg.root_store_dir) + .manager(cfg.manager) + .build(); + + let manager = RevisionManager::new(db_path.as_ref().to_path_buf(), config_manager)?; + let db = Self { + metrics, + manager, + use_parallel: cfg.use_parallel, + }; + Ok(db) + } + + /// Synchronously get a view, either committed or proposed + pub fn view(&self, root_hash: HashKey) -> Result { + self.manager.view(root_hash).map_err(Into::into) + } + + /// Dump the Trie of the latest revision. + pub fn dump(&self, w: &mut dyn Write) -> Result<(), std::io::Error> { + let latest_rev_nodestore = self.manager.current_revision(); + let merkle = Merkle::from(latest_rev_nodestore); + merkle.dump(w).map_err(std::io::Error::other) + } + + /// Get a copy of the database metrics + pub fn metrics(&self) -> Arc { + self.metrics.clone() + } + + /// Check the database for consistency + pub fn check(&self, opt: CheckOpt) -> CheckerReport { + let latest_rev_nodestore = self.manager.current_revision(); + latest_rev_nodestore.check(opt) + } + + /// Create a proposal with a specified parent. A proposal is created in parallel if `use_parallel` + /// is `Always` or if `use_parallel` is `BatchSize` and the batch is >= to the `BatchSize` value. + /// + /// # Panics + /// + /// Panics if the revision manager cannot create a thread pool. + #[fastrace::trace(name = "propose")] + fn propose_with_parent( + &self, + batch: impl IntoBatchIter, + parent: &NodeStore, + ) -> Result, api::Error> { + // If use_parallel is BatchSize, then perform parallel proposal creation if the batch + // size is >= BatchSize. + let batch = batch.into_iter(); + let use_parallel = match self.use_parallel { + UseParallel::Never => false, + UseParallel::Always => true, + UseParallel::BatchSize(required_size) => batch.size_hint().0 >= required_size, + }; + let immutable = if use_parallel { + let mut parallel_merkle = ParallelMerkle::default(); + let _span = fastrace::Span::enter_with_local_parent("parallel_merkle"); + parallel_merkle.create_proposal(parent, batch, self.manager.threadpool())? + } else { + let proposal = NodeStore::new(parent)?; + let mut merkle = Merkle::from(proposal); + let span = fastrace::Span::enter_with_local_parent("merkleops"); + for res in batch.into_batch_iter::() { + match res? { + BatchOp::Put { key, value } => { + merkle.insert(key.as_ref(), value.as_ref().into())?; + } + BatchOp::Delete { key } => { + merkle.remove(key.as_ref())?; + } + BatchOp::DeleteRange { prefix } => { + merkle.remove_prefix(prefix.as_ref())?; + } + } + } + + drop(span); + let _span = fastrace::Span::enter_with_local_parent("freeze"); + let nodestore = merkle.into_inner(); + Arc::new(nodestore.try_into()?) + }; + self.manager.add_proposal(immutable.clone()); + + self.metrics.proposals.increment(1); + + Ok(Proposal { + nodestore: immutable, + db: self, + }) + } + + /// Merge a range of key-values into a new proposal on top of the current + /// root revision. + /// + /// All items within the range `(first_key..=last_key)` will be replaced with + /// the provided key-values from the iterator. I.e., any existing keys within + /// the range that are not present in the provided key-values will be deleted, + /// any duplicate keys will be overwritten, and any new keys will be inserted. + /// + /// Invariant: `key_values` must be sorted by key in ascending order; however, + /// because debug assertions are disabled, this is not checked. + pub fn merge_key_value_range( + &self, + first_key: Option, + last_key: Option, + key_values: impl IntoIterator, + ) -> Result, api::Error> { + self.merge_key_value_range_with_parent( + first_key, + last_key, + key_values, + &self.manager.current_revision(), + ) + } + + /// Merge a range of key-values into a new proposal on top of a specified parent. + /// + /// All items within the range `(first_key..=last_key)` will be replaced with + /// the provided key-values from the iterator. I.e., any existing keys within + /// the range that are not present in the provided key-values will be deleted, + /// any duplicate keys will be overwritten, and any new keys will be inserted. + /// + /// Invariant: `key_values` must be sorted by key in ascending order; however, + /// because debug assertions are disabled, this is not checked. + pub fn merge_key_value_range_with_parent( + &self, + first_key: Option, + last_key: Option, + key_values: impl IntoIterator, + parent: &NodeStore, + ) -> Result, api::Error> + where + NodeStore: TrieReader, + { + let merkle = Merkle::from(parent); + let merge_ops = merkle.merge_key_value_range(first_key, last_key, key_values); + self.propose_with_parent(merge_ops, merkle.nodestore()) + } +} + +#[derive(Debug)] +/// A user-visible database proposal +pub struct Proposal<'db> { + nodestore: Arc, FileBacked>>, + db: &'db Db, +} + +impl api::DbView for Proposal<'_> { + type Iter<'view> + = MerkleKeyValueIter<'view, NodeStore, FileBacked>> + where + Self: 'view; + + fn root_hash(&self) -> Result, api::Error> { + api::DbView::root_hash(&*self.nodestore) + } + + fn val(&self, key: K) -> Result, api::Error> { + api::DbView::val(&*self.nodestore, key) + } + + fn single_key_proof(&self, key: K) -> Result { + api::DbView::single_key_proof(&*self.nodestore, key) + } + + fn range_proof( + &self, + first_key: Option, + last_key: Option, + limit: Option, + ) -> Result { + api::DbView::range_proof(&*self.nodestore, first_key, last_key, limit) + } + + fn iter_option(&self, first_key: Option) -> Result, api::Error> { + api::DbView::iter_option(&*self.nodestore, first_key) + } +} + +impl<'db> api::Proposal for Proposal<'db> { + type Proposal = Proposal<'db>; + + fn propose(&self, batch: impl IntoBatchIter) -> Result { + self.create_proposal(batch) + } + + fn commit(self) -> Result<(), api::Error> { + Ok(self.db.manager.commit(self.nodestore)?) + } +} + +impl Proposal<'_> { + #[crate::metrics("firewood.proposal.create", "database proposal creation")] + fn create_proposal(&self, batch: impl IntoBatchIter) -> Result { + self.db.propose_with_parent(batch, &self.nodestore) + } +} + +#[cfg(test)] +mod test { + #![expect(clippy::unwrap_used)] + + use core::iter::Take; + use std::collections::HashMap; + use std::iter::Peekable; + use std::num::NonZeroUsize; + use std::ops::{Deref, DerefMut}; + use std::path::PathBuf; + + use firewood_storage::{ + CheckOpt, CheckerError, HashedNodeReader, IntoHashType, NodeStore, TrieHash, + }; + + use crate::db::{Db, Proposal, UseParallel}; + use crate::manager::RevisionManagerConfig; + use crate::v2::api::{Db as _, DbView, Proposal as _}; + + use super::{BatchOp, DbConfig}; + + /// A chunk of an iterator, provided by [`IterExt::chunk_fold`] to the folding + /// function. + type Chunk<'chunk, 'base, T> = &'chunk mut Take<&'base mut Peekable>; + + trait IterExt: Iterator { + /// Asynchronously folds the iterator with chunks of a specified size. The last + /// chunk may be smaller than the specified size. + /// + /// The folding function is a closure that takes an accumulator and a + /// chunk of the underlying iterator, and returns a new accumulator. + /// + /// # Panics + /// + /// If the folding function does not consume the entire chunk, it will panic. + /// + /// If the folding function panics, the iterator will be dropped (because this + /// method consumes `self`). + fn chunk_fold(self, chunk_size: NonZeroUsize, init: B, mut f: F) -> B + where + Self: Sized, + F: for<'a, 'b> FnMut(B, Chunk<'a, 'b, Self>) -> B, + { + let chunk_size = chunk_size.get(); + let mut iter = self.peekable(); + let mut acc = init; + while iter.peek().is_some() { + let mut chunk = iter.by_ref().take(chunk_size); + acc = f(acc, chunk.by_ref()); + assert!(chunk.next().is_none(), "entire chunk was not consumed"); + } + acc + } + } + + impl IterExt for T {} + + #[test] + fn test_proposal_reads() { + let db = TestDb::new(); + let batch = vec![BatchOp::Put { + key: b"k", + value: b"v", + }]; + let proposal = db.propose(batch).unwrap(); + assert_eq!(&*proposal.val(b"k").unwrap().unwrap(), b"v"); + + assert_eq!(proposal.val(b"notfound").unwrap(), None); + proposal.commit().unwrap(); + + let batch = vec![BatchOp::Put { + key: b"k", + value: b"v2", + }]; + let proposal = db.propose(batch).unwrap(); + assert_eq!(&*proposal.val(b"k").unwrap().unwrap(), b"v2"); + + let committed = db.root_hash().unwrap().unwrap(); + let historical = db.revision(committed).unwrap(); + assert_eq!(&*historical.val(b"k").unwrap().unwrap(), b"v"); + } + + #[test] + fn reopen_test() { + let db = TestDb::new(); + let initial_root = db.root_hash().unwrap(); + let batch = vec![ + BatchOp::Put { + key: b"a", + value: b"1", + }, + BatchOp::Put { + key: b"b", + value: b"2", + }, + ]; + let proposal = db.propose(batch).unwrap(); + proposal.commit().unwrap(); + println!("{:?}", db.root_hash().unwrap().unwrap()); + + let db = db.reopen(); + println!("{:?}", db.root_hash().unwrap().unwrap()); + let committed = db.root_hash().unwrap().unwrap(); + let historical = db.revision(committed).unwrap(); + assert_eq!(&*historical.val(b"a").unwrap().unwrap(), b"1"); + drop(historical); + + let db = db.replace(); + println!("{:?}", db.root_hash().unwrap()); + assert!(db.root_hash().unwrap() == initial_root); + } + + #[test] + // test that dropping a proposal removes it from the list of known proposals + // /-> P1 - will get committed + // R1 --> P2 - will get dropped + // \-> P3 - will get orphaned, but it's still known + fn test_proposal_scope_historic() { + let db = TestDb::new(); + let batch1 = vec![BatchOp::Put { + key: b"k1", + value: b"v1", + }]; + let proposal1 = db.propose(batch1).unwrap(); + assert_eq!(&*proposal1.val(b"k1").unwrap().unwrap(), b"v1"); + + let batch2 = vec![BatchOp::Put { + key: b"k2", + value: b"v2", + }]; + let proposal2 = db.propose(batch2).unwrap(); + assert_eq!(&*proposal2.val(b"k2").unwrap().unwrap(), b"v2"); + + let batch3 = vec![BatchOp::Put { + key: b"k3", + value: b"v3", + }]; + let proposal3 = db.propose(batch3).unwrap(); + assert_eq!(&*proposal3.val(b"k3").unwrap().unwrap(), b"v3"); + + // the proposal is dropped here, but the underlying + // nodestore is still accessible because it's referenced by the revision manager + // The third proposal remains referenced + let p2hash = proposal2.root_hash().unwrap().unwrap(); + assert!(db.all_hashes().unwrap().contains(&p2hash)); + drop(proposal2); + + // commit the first proposal + proposal1.commit().unwrap(); + // Ensure we committed the first proposal's data + let committed = db.root_hash().unwrap().unwrap(); + let historical = db.revision(committed).unwrap(); + assert_eq!(&*historical.val(b"k1").unwrap().unwrap(), b"v1"); + + // the second proposal shouldn't be available to commit anymore + assert!(!db.all_hashes().unwrap().contains(&p2hash)); + + // the third proposal should still be contained within the all_hashes list + // would be deleted if another proposal was committed and proposal3 was dropped here + let hash3 = proposal3.root_hash().unwrap().unwrap(); + assert!(db.manager.all_hashes().contains(&hash3)); + } + + #[test] + // test that dropping a proposal removes it from the list of known proposals + // R1 - base revision + // \-> P1 - will get committed + // \-> P2 - will get dropped + // \-> P3 - will get orphaned, but it's still known + fn test_proposal_scope_orphan() { + let db = TestDb::new(); + let batch1 = vec![BatchOp::Put { + key: b"k1", + value: b"v1", + }]; + let proposal1 = db.propose(batch1).unwrap(); + assert_eq!(&*proposal1.val(b"k1").unwrap().unwrap(), b"v1"); + + let batch2 = vec![BatchOp::Put { + key: b"k2", + value: b"v2", + }]; + let proposal2 = proposal1.propose(batch2).unwrap(); + assert_eq!(&*proposal2.val(b"k2").unwrap().unwrap(), b"v2"); + + let batch3 = vec![BatchOp::Put { + key: b"k3", + value: b"v3", + }]; + let proposal3 = proposal2.propose(batch3).unwrap(); + assert_eq!(&*proposal3.val(b"k3").unwrap().unwrap(), b"v3"); + + // the proposal is dropped here, but the underlying + // nodestore is still accessible because it's referenced by the revision manager + // The third proposal remains referenced + let p2hash = proposal2.root_hash().unwrap().unwrap(); + assert!(db.all_hashes().unwrap().contains(&p2hash)); + drop(proposal2); + + // commit the first proposal + proposal1.commit().unwrap(); + // Ensure we committed the first proposal's data + let committed = db.root_hash().unwrap().unwrap(); + let historical = db.revision(committed).unwrap(); + assert_eq!(&*historical.val(b"k1").unwrap().unwrap(), b"v1"); + + // the second proposal shouldn't be available to commit anymore + assert!(!db.all_hashes().unwrap().contains(&p2hash)); + + // the third proposal should still be contained within the all_hashes list + let hash3 = proposal3.root_hash().unwrap().unwrap(); + assert!(db.manager.all_hashes().contains(&hash3)); + + // moreover, the data from the second and third proposals should still be available + // through proposal3 + assert_eq!(&*proposal3.val(b"k2").unwrap().unwrap(), b"v2"); + assert_eq!(&*proposal3.val(b"k3").unwrap().unwrap(), b"v3"); + } + + #[test] + fn test_view_sync() { + let db = TestDb::new(); + + // Create and commit some data to get a historical revision + let batch = vec![BatchOp::Put { + key: b"historical_key", + value: b"historical_value", + }]; + let proposal = db.propose(batch).unwrap(); + let historical_hash = proposal.root_hash().unwrap().unwrap(); + proposal.commit().unwrap(); + + // Create a new proposal (uncommitted) + let batch = vec![BatchOp::Put { + key: b"proposal_key", + value: b"proposal_value", + }]; + let proposal = db.propose(batch).unwrap(); + let proposal_hash = proposal.root_hash().unwrap().unwrap(); + + // Test that view_sync can find the historical revision + let historical_view = db.view(historical_hash).unwrap(); + let value = historical_view.val(b"historical_key").unwrap().unwrap(); + assert_eq!(&*value, b"historical_value"); + + // Test that view_sync can find the proposal + let proposal_view = db.view(proposal_hash).unwrap(); + let value = proposal_view.val(b"proposal_key").unwrap().unwrap(); + assert_eq!(&*value, b"proposal_value"); + } + + #[test] + fn test_propose_parallel_reopen() { + fn insert_commit(db: &TestDb, kv: u8) { + let keys: Vec<[u8; 1]> = vec![[kv; 1]]; + let vals: Vec> = vec![Box::new([kv; 1])]; + let kviter = keys.iter().zip(vals.iter()); + let proposal = db.propose(kviter).unwrap(); + proposal.commit().unwrap(); + } + + // Create, insert, close, open, insert + let db = TestDb::new_with_config( + DbConfig::builder() + .use_parallel(UseParallel::Always) + .build(), + ); + insert_commit(&db, 1); + let db = db.reopen(); + insert_commit(&db, 2); + // Check that the keys are still there after the commits + let committed = db.revision(db.root_hash().unwrap().unwrap()).unwrap(); + let keys: Vec<[u8; 1]> = vec![[1; 1], [2; 1]]; + let vals: Vec> = vec![Box::new([1; 1]), Box::new([2; 1])]; + let kviter = keys.iter().zip(vals.iter()); + for (k, v) in kviter { + assert_eq!(&committed.val(k).unwrap().unwrap(), v); + } + drop(db); + + // Open-db1, insert, open-db2, insert + let db1 = TestDb::new_with_config( + DbConfig::builder() + .use_parallel(UseParallel::Always) + .build(), + ); + insert_commit(&db1, 1); + let db2 = TestDb::new_with_config( + DbConfig::builder() + .use_parallel(UseParallel::Always) + .build(), + ); + insert_commit(&db2, 2); + let committed1 = db1.revision(db1.root_hash().unwrap().unwrap()).unwrap(); + let committed2 = db2.revision(db2.root_hash().unwrap().unwrap()).unwrap(); + let keys: Vec<[u8; 1]> = vec![[1; 1], [2; 1]]; + let vals: Vec> = vec![Box::new([1; 1]), Box::new([2; 1])]; + let mut kviter = keys.iter().zip(vals.iter()); + let (k, v) = kviter.next().unwrap(); + assert_eq!(&committed1.val(k).unwrap().unwrap(), v); + let (k, v) = kviter.next().unwrap(); + assert_eq!(&committed2.val(k).unwrap().unwrap(), v); + } + + #[test] + fn test_propose_parallel() { + const N: usize = 100; + let db = TestDb::new_with_config( + DbConfig::builder() + .use_parallel(UseParallel::Always) + .build(), + ); + + // Test an empty proposal + let keys: Vec<[u8; 0]> = Vec::new(); + let vals: Vec> = Vec::new(); + + let kviter = keys.iter().zip(vals.iter()); + let proposal = db.propose(kviter).unwrap(); + proposal.commit().unwrap(); + + // Create a proposal consisting of a single entry and an empty key. + let keys: Vec<[u8; 0]> = vec![[0; 0]]; + + // Note that if the value is [], then it is interpreted as a DeleteRange. + // Instead, set value to [0] + let vals: Vec> = vec![Box::new([0; 1])]; + + let kviter = keys.iter().zip(vals.iter()); + let proposal = db.propose(kviter).unwrap(); + + let kviter = keys.iter().zip(vals.iter()); + for (k, v) in kviter { + assert_eq!(&proposal.val(k).unwrap().unwrap(), v); + } + proposal.commit().unwrap(); + + // Check that the key is still there after the commit + let committed = db.revision(db.root_hash().unwrap().unwrap()).unwrap(); + let kviter = keys.iter().zip(vals.iter()); + for (k, v) in kviter { + assert_eq!(&committed.val(k).unwrap().unwrap(), v); + } + + // Create a proposal that deletes the previous entry + let vals: Vec> = vec![Box::new([0; 0])]; + let kviter = keys.iter().zip(vals.iter()); + let proposal = db.propose(kviter).unwrap(); + + let kviter = keys.iter().zip(vals.iter()); + for (k, _v) in kviter { + assert_eq!(proposal.val(k).unwrap(), None); + } + proposal.commit().unwrap(); + + // Create a proposal that inserts 0 to 999 + let (keys, vals): (Vec<_>, Vec<_>) = (0..1000) + .map(|i| { + ( + format!("key{i}").into_bytes(), + Box::from(format!("value{i}").as_bytes()), + ) + }) + .unzip(); + + let kviter = keys.iter().zip(vals.iter()); + let proposal = db.propose(kviter).unwrap(); + let kviter = keys.iter().zip(vals.iter()); + for (k, v) in kviter { + assert_eq!(&proposal.val(k).unwrap().unwrap(), v); + } + proposal.commit().unwrap(); + + // Create a proposal that deletes all of the even entries + let (keys, vals): (Vec<_>, Vec<_>) = (0..1000) + .filter_map(|i| { + if i % 2 != 0 { + Some::<(Vec, Box<[u8]>)>((format!("key{i}").into_bytes(), Box::new([]))) + } else { + None + } + }) + .unzip(); + + let kviter = keys.iter().zip(vals.iter()); + let proposal = db.propose(kviter).unwrap(); + let kviter = keys.iter().zip(vals.iter()); + for (k, _v) in kviter { + assert_eq!(proposal.val(k).unwrap(), None); + } + proposal.commit().unwrap(); + + // Create a proposal that deletes using empty prefix + let keys: Vec<[u8; 0]> = vec![[0; 0]]; + let vals: Vec> = vec![Box::new([0; 0])]; + let kviter = keys.iter().zip(vals.iter()); + let proposal = db.propose(kviter).unwrap(); + proposal.commit().unwrap(); + + // Create N keys and values like (key0, value0)..(keyN, valueN) + let rng = firewood_storage::SeededRng::from_env_or_random(); + let (keys, vals): (Vec<_>, Vec<_>) = (0..N) + .map(|i| { + ( + rng.random::<[u8; 32]>(), + Box::from(format!("value{i}").as_bytes()), + ) + }) + .unzip(); + + // Looping twice to test that we are reusing the thread pool. + for _ in 0..2 { + let kviter = keys.iter().zip(vals.iter()); + let proposal = db.propose(kviter).unwrap(); + + // iterate over the keys and values again, checking that the values are in the correct proposal + let kviter = keys.iter().zip(vals.iter()); + + for (k, v) in kviter { + assert_eq!(&proposal.val(k).unwrap().unwrap(), v); + } + proposal.commit().unwrap(); + } + } + + /// Test that proposing on a proposal works as expected + /// + /// Test creates two batches and proposes them, and verifies that the values are in the correct proposal. + /// It then commits them one by one, and verifies the latest committed version is correct. + #[test] + fn test_propose_on_proposal() { + // number of keys and values to create for this test + const N: usize = 20; + + let db = TestDb::new(); + + // create N keys and values like (key0, value0)..(keyN, valueN) + let (keys, vals): (Vec<_>, Vec<_>) = (0..N) + .map(|i| { + ( + format!("key{i}").into_bytes(), + Box::from(format!("value{i}").as_bytes()), + ) + }) + .unzip(); + + // create two batches, one with the first half of keys and values, and one with the last half keys and values + let mut kviter = keys.iter().zip(vals.iter()); + + // create two proposals, second one has a base of the first one + let proposal1 = db.propose(kviter.by_ref().take(N / 2)).unwrap(); + let proposal2 = proposal1.propose(kviter).unwrap(); + + // iterate over the keys and values again, checking that the values are in the correct proposal + let mut kviter = keys.iter().zip(vals.iter()); + + // first half of the keys should be in both proposals + for (k, v) in kviter.by_ref().take(N / 2) { + assert_eq!(&proposal1.val(k).unwrap().unwrap(), v); + assert_eq!(&proposal2.val(k).unwrap().unwrap(), v); + } + + // remaining keys should only be in the second proposal + for (k, v) in kviter { + // second half of keys are in the second proposal + assert_eq!(&proposal2.val(k).unwrap().unwrap(), v); + // but not in the first + assert_eq!(proposal1.val(k).unwrap(), None); + } + + proposal1.commit().unwrap(); + + // all keys are still in the second proposal (first is no longer accessible) + for (k, v) in keys.iter().zip(vals.iter()) { + assert_eq!(&proposal2.val(k).unwrap().unwrap(), v); + } + + // commit the second proposal + proposal2.commit().unwrap(); + + // all keys are in the database + let committed = db.root_hash().unwrap().unwrap(); + let revision = db.revision(committed).unwrap(); + + for (k, v) in keys.into_iter().zip(vals.into_iter()) { + assert_eq!(revision.val(k).unwrap().unwrap(), v); + } + } + + #[test] + fn fuzz_checker() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let db = TestDb::new(); + + // takes about 0.3s on a mac to run 50 times + for _ in 0..50 { + // create a batch of 10 random key-value pairs + let batch = (0..10).fold(vec![], |mut batch, _| { + let key: [u8; 32] = rng.random(); + let value: [u8; 8] = rng.random(); + batch.push(BatchOp::Put { + key: key.to_vec(), + value, + }); + if rng.random_range(0..5) == 0 { + let addon: [u8; 32] = rng.random(); + let key = [key, addon].concat(); + let value: [u8; 8] = rng.random(); + batch.push(BatchOp::Put { key, value }); + } + batch + }); + let proposal = db.propose(batch).unwrap(); + proposal.commit().unwrap(); + + // check the database for consistency, sometimes checking the hashes + let hash_check = rng.random(); + let report = db.check(CheckOpt { + hash_check, + progress_bar: None, + }); + if report + .errors + .iter() + .filter(|e| !matches!(e, CheckerError::AreaLeaks(_))) + .count() + != 0 + { + db.dump(&mut std::io::stdout()).unwrap(); + panic!("error: {:?}", report.errors); + } + } + } + + #[test] + fn test_deep_propose() { + const NUM_KEYS: NonZeroUsize = const { NonZeroUsize::new(2).unwrap() }; + const NUM_PROPOSALS: usize = 100; + + let db = TestDb::new(); + + let ops = (0..(NUM_KEYS.get() * NUM_PROPOSALS)) + .map(|i| (format!("key{i}"), format!("value{i}"))) + .collect::>(); + + let proposals = ops.iter().chunk_fold( + NUM_KEYS, + Vec::>::with_capacity(NUM_PROPOSALS), + |mut proposals, ops| { + let proposal = if let Some(parent) = proposals.last() { + parent.propose(ops).unwrap() + } else { + db.propose(ops).unwrap() + }; + + proposals.push(proposal); + proposals + }, + ); + + let last_proposal_root_hash = proposals.last().unwrap().root_hash().unwrap().unwrap(); + + // commit the proposals + for proposal in proposals { + proposal.commit().unwrap(); + } + + // get the last committed revision + let last_root_hash = db.root_hash().unwrap().unwrap(); + let committed = db.revision(last_root_hash.clone()).unwrap(); + + // the last root hash should be the same as the last proposal root hash + assert_eq!(last_root_hash, last_proposal_root_hash); + + // check that all the keys and values are still present + for (k, v) in &ops { + let found = committed.val(k).unwrap(); + assert_eq!( + found.as_deref(), + Some(v.as_bytes()), + "Value for key {k:?} should be {v:?} but was {found:?}", + ); + } + } + + /// Test that reading from a proposal during commit works as expected + #[test] + fn test_read_during_commit() { + use crate::db::Proposal; + + const CHANNEL_CAPACITY: usize = 8; + + let testdb = TestDb::new(); + let db = &testdb.db; + + let (tx, rx) = std::sync::mpsc::sync_channel::>(CHANNEL_CAPACITY); + let (result_tx, result_rx) = std::sync::mpsc::sync_channel(CHANNEL_CAPACITY); + + // scope will block until all scope-spawned threads finish + std::thread::scope(|scope| { + // Commit task + scope.spawn(move || { + while let Ok(proposal) = rx.recv() { + let result = proposal.commit(); + // send result back to the main thread, both for synchronization and stopping the + // test on error + result_tx.send(result).unwrap(); + } + }); + scope.spawn(move || { + // Proposal creation + for id in 0u32..5000 { + // insert a key of length 32 and a value of length 8, + // rotating between all zeroes through all 255 + let batch = vec![BatchOp::Put { + key: [id as u8; 32], + value: [id as u8; 8], + }]; + let proposal = db.propose(batch).unwrap(); + let last_hash = proposal.root_hash().unwrap().unwrap(); + let view = db.view(last_hash).unwrap(); + + tx.send(proposal).unwrap(); + + let key = [id as u8; 32]; + let value = view.val(&key).unwrap().unwrap(); + assert_eq!(&*value, &[id as u8; 8]); + result_rx.recv().unwrap().unwrap(); + } + // close the channel, which will cause the commit task to exit + drop(tx); + }); + }); + } + + #[test] + fn test_resurrect_unpersisted_root() { + let db = TestDb::new(); + + // First, create a revision to retrieve + let key = b"key"; + let value = b"value"; + let batch = vec![BatchOp::Put { key, value }]; + + let proposal = db.propose(batch).unwrap(); + let root_hash = proposal.root_hash().unwrap().unwrap(); + proposal.commit().unwrap(); + + let root_address = db + .revision(root_hash.clone()) + .unwrap() + .root_address() + .unwrap(); + + // Next, overwrite the kv-pair with a new revision + let new_value = b"new_value"; + let batch = vec![BatchOp::Put { + key, + value: new_value, + }]; + + let proposal = db.propose(batch).unwrap(); + proposal.commit().unwrap(); + + // Finally, reopen the database and make sure that we can retrieve the first revision + let db = db.reopen(); + + let latest_root_hash = db.root_hash().unwrap().unwrap(); + let latest_revision = db.revision(latest_root_hash).unwrap(); + + let latest_value = latest_revision.val(key).unwrap().unwrap(); + assert_eq!(new_value, latest_value.as_ref()); + + let node_store = + NodeStore::with_root(root_hash.into_hash_type(), root_address, latest_revision); + + let retrieved_value = node_store.val(key).unwrap().unwrap(); + assert_eq!(value, retrieved_value.as_ref()); + } + + /// Verifies that persisted revisions are still accessible when reopening the database. + #[test] + fn test_root_store() { + let db = TestDb::new_with_root_store(DbConfig::builder().build()); + + // First, create a revision to retrieve + let key = b"key"; + let value = b"value"; + let batch = vec![BatchOp::Put { key, value }]; + + let proposal = db.propose(batch).unwrap(); + let root_hash = proposal.root_hash().unwrap().unwrap(); + proposal.commit().unwrap(); + + // Next, overwrite the kv-pair with a new revision + let new_value = b"new_value"; + let batch = vec![BatchOp::Put { + key, + value: new_value, + }]; + + let proposal = db.propose(batch).unwrap(); + proposal.commit().unwrap(); + + // Reopen the database and verify that the database can access a persisted revision + let db = db.reopen(); + + let view = db.view(root_hash).unwrap(); + let retrieved_value = view.val(key).unwrap().unwrap(); + assert_eq!(value, retrieved_value.as_ref()); + } + + #[test] + fn test_rootstore_empty_db_reopen() { + let db = TestDb::new_with_root_store(DbConfig::builder().build()); + + db.reopen(); + } + + /// Verifies that revisions exceeding the in-memory limit can still be retrieved. + #[test] + fn test_root_store_with_capped_max_revisions() { + const NUM_REVISIONS: usize = 10; + + let dbconfig = DbConfig::builder() + .manager(RevisionManagerConfig::builder().max_revisions(5).build()) + .build(); + let db = TestDb::new_with_root_store(dbconfig); + + // Create and commit 10 proposals + let key = b"root_store"; + let revisions: HashMap = (0..NUM_REVISIONS) + .map(|i| { + let value = i.to_be_bytes(); + let batch = vec![BatchOp::Put { key, value }]; + let proposal = db.propose(batch).unwrap(); + let root_hash = proposal.root_hash().unwrap().unwrap(); + proposal.commit().unwrap(); + + (root_hash, value) + }) + .collect(); + + // Verify that we can access all revisions with their correct values + for (root_hash, value) in &revisions { + let revision = db.revision(root_hash.clone()).unwrap(); + let retrieved_value = revision.val(key).unwrap().unwrap(); + assert_eq!(value.as_slice(), retrieved_value.as_ref()); + } + + let db = db.reopen(); + + // Verify that we can access all revisions with their correct values + // after reopening + for (root_hash, value) in &revisions { + let revision = db.revision(root_hash.clone()).unwrap(); + let retrieved_value = revision.val(key).unwrap().unwrap(); + assert_eq!(value.as_slice(), retrieved_value.as_ref()); + } + } + + // Testdb is a helper struct for testing the Db. Once it's dropped, the directory and file disappear + pub(super) struct TestDb { + db: Db, + tmpdir: tempfile::TempDir, + dbconfig: DbConfig, + } + impl Deref for TestDb { + type Target = Db; + fn deref(&self) -> &Self::Target { + &self.db + } + } + impl DerefMut for TestDb { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.db + } + } + + impl TestDb { + pub fn new() -> Self { + TestDb::new_with_config(DbConfig::builder().build()) + } + + pub fn new_with_config(dbconfig: DbConfig) -> Self { + let tmpdir = tempfile::tempdir().unwrap(); + let dbpath: PathBuf = [tmpdir.path().to_path_buf(), PathBuf::from("testdb")] + .iter() + .collect(); + let db = Db::new(dbpath, dbconfig.clone()).unwrap(); + TestDb { + db, + tmpdir, + dbconfig, + } + } + + /// Creates a new test database with `RootStore` enabled. + /// + /// Overrides `root_store_dir` in dbconfig to provide a directory for `RootStore`. + pub fn new_with_root_store(dbconfig: DbConfig) -> Self { + let tmpdir = tempfile::tempdir().unwrap(); + let dbpath: PathBuf = [tmpdir.path().to_path_buf(), PathBuf::from("testdb")] + .iter() + .collect(); + let root_store_dir = tmpdir.as_ref().join("root_store"); + + let dbconfig = DbConfig { + root_store_dir: Some(root_store_dir), + ..dbconfig + }; + + let db = Db::new(dbpath, dbconfig.clone()).unwrap(); + TestDb { + db, + tmpdir, + dbconfig, + } + } + + /// Reopens the database at the same path, preserving existing data. + /// + /// This method closes the current database instance (releasing the advisory lock), + /// then opens it again at the same path while keeping the same configuration. + pub fn reopen(self) -> Self { + let path = self.path(); + let TestDb { + db, + tmpdir, + dbconfig, + } = self; + + drop(db); + + let db = Db::new(path, dbconfig.clone()).unwrap(); + TestDb { + db, + tmpdir, + dbconfig, + } + } + + /// Replaces the database with a fresh instance at the same path. + /// + /// This method closes the current database instance (releasing the advisory lock), + /// and creates a new database. This completely resets the database, removing all + /// existing data and starting fresh. The new database instance will use the default + /// configuration with truncation enabled. + /// + /// This is useful for testing scenarios where you want to start with a clean slate + /// while maintaining the same temporary directory structure. + pub fn replace(self) -> Self { + let path = self.path(); + let TestDb { + db, + tmpdir, + dbconfig: _, + } = self; + + drop(db); + + let dbconfig = DbConfig::builder().truncate(true).build(); + let db = Db::new(path, dbconfig.clone()).unwrap(); + TestDb { + db, + tmpdir, + dbconfig, + } + } + + pub fn path(&self) -> PathBuf { + [self.tmpdir.path().to_path_buf(), PathBuf::from("testdb")] + .iter() + .collect() + } + } +} diff --git a/firewood/firewood/src/db/tests.rs b/firewood/firewood/src/db/tests.rs new file mode 100644 index 000000000000..db77235fa532 --- /dev/null +++ b/firewood/firewood/src/db/tests.rs @@ -0,0 +1,8 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect(clippy::unwrap_used)] + +mod merge; + +use super::test::TestDb; diff --git a/firewood/firewood/src/db/tests/merge.rs b/firewood/firewood/src/db/tests/merge.rs new file mode 100644 index 000000000000..cdb701d55e07 --- /dev/null +++ b/firewood/firewood/src/db/tests/merge.rs @@ -0,0 +1,252 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::{ + db::BatchOp, + v2::api::{Db, DbView, Proposal}, +}; + +use super::*; +use test_case::test_case; + +#[test_case( + &[], + None, + None, + &[], + &[]; + "empty everything - no initial data, no merge data" + )] +#[test_case( + &[(b"key1", b"val1"), (b"key2", b"val2"), (b"key3", b"val3")], + Some(b"key1".as_slice()), + Some(b"key3".as_slice()), + &[(b"key1", b"new1"), (b"key2", b"new2"), (b"key3", b"new3")], + &[(b"key1", Some(b"new1")), (b"key2", Some(b"new2")), (b"key3", Some(b"new3"))]; + "basic happy path - update all values in range" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3"), (b"d", b"4")], + Some(b"b".as_slice()), + Some(b"c".as_slice()), + &[], + &[(b"a", Some(b"1")), (b"b", None), (b"c", None), (b"d", Some(b"4"))]; + "empty input iterator - deletes all keys in range" + )] +#[test_case( + &[], + None, + None, + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3")], + &[(b"a", Some(b"1")), (b"b", Some(b"2")), (b"c", Some(b"3"))]; + "empty base trie - insert all keys" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3")], + None, + None, + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3")], + &[(b"a", Some(b"1")), (b"b", Some(b"2")), (b"c", Some(b"3"))]; + "no changes - identical key-values" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3")], + Some(b"a".as_slice()), + Some(b"c".as_slice()), + &[(b"x", b"10"), (b"y", b"20"), (b"z", b"30")], + &[(b"a", None), (b"b", None), (b"c", None), (b"x", Some(b"10")), (b"y", Some(b"20")), (b"z", Some(b"30"))]; + "full replacement - completely different keys" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3"), (b"d", b"4")], + Some(b"b".as_slice()), + Some(b"c".as_slice()), + &[(b"b", b"new2"), (b"c2", b"inserted")], + &[(b"a", Some(b"1")), (b"b", Some(b"new2")), (b"c", None), (b"c2", Some(b"inserted")), (b"d", Some(b"4"))]; + "partial overlap - mix of updates, inserts, deletes" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3")], + Some(b"b".as_slice()), + Some(b"b".as_slice()), + &[(b"b", b"updated")], + &[(b"a", Some(b"1")), (b"b", Some(b"updated")), (b"c", Some(b"3"))]; + "single key range - first_key equals last_key" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3")], + None, + None, + &[(b"x", b"10"), (b"y", b"20")], + &[(b"a", None), (b"b", None), (b"c", None), (b"x", Some(b"10")), (b"y", Some(b"20"))]; + "unbounded range - replace entire trie" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3"), (b"d", b"4")], + Some(b"b".as_slice()), + None, + &[(b"b", b"new2"), (b"c", b"new3")], + &[(b"a", Some(b"1")), (b"b", Some(b"new2")), (b"c", Some(b"new3")), (b"d", None)]; + "left-bounded only - from key b to end" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3"), (b"d", b"4")], + None, + Some(b"c".as_slice()), + &[(b"a", b"new1"), (b"b", b"new2")], + &[(b"a", Some(b"new1")), (b"b", Some(b"new2")), (b"c", None), (b"d", Some(b"4"))]; + "right-bounded only - from start to key c" + )] +#[test_case( + &[(b"a", b"1"), (b"e", b"5"), (b"f", b"6")], + Some(b"b".as_slice()), + Some(b"d".as_slice()), + &[(b"b", b"2"), (b"c", b"3"), (b"d", b"4")], + &[(b"a", Some(b"1")), (b"b", Some(b"2")), (b"c", Some(b"3")), (b"d", Some(b"4")), (b"e", Some(b"5")), (b"f", Some(b"6"))]; + "gap range - merge into range with no existing keys" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3")], + Some(b"b".as_slice()), + Some(b"c".as_slice()), + &[(b"b", b"updated"), (b"c", b"3")], + &[(b"a", Some(b"1")), (b"b", Some(b"updated")), (b"c", Some(b"3"))]; + "value updates only - same keys, one different value" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3"), (b"d", b"4"), (b"e", b"5")], + Some(b"b".as_slice()), + Some(b"d".as_slice()), + &[], + &[(b"a", Some(b"1")), (b"b", None), (b"c", None), (b"d", None), (b"e", Some(b"5"))]; + "delete middle range - empty iterator deletes b, c, d" + )] +#[test_case( + &[(b"app", b"1"), (b"apple", b"2"), (b"application", b"3")], + Some(b"app".as_slice()), + Some(b"application".as_slice()), + &[(b"app", b"new1"), (b"apply", b"4")], + &[(b"app", Some(b"new1")), (b"apple", None), (b"application", None), (b"apply", Some(b"4"))]; + "common prefix keys - test branch navigation" + )] +#[test_case( + &[(b"a", b"1"), (b"b", b"2"), (b"c", b"3"), (b"d", b"4"), (b"e", b"5")], + Some(b"b".as_slice()), + Some(b"d".as_slice()), + &[(b"b2", b"new"), (b"c", b"updated")], + &[(b"a", Some(b"1")), (b"b", None), (b"b2", Some(b"new")), (b"c", Some(b"updated")), (b"d", None), (b"e", Some(b"5"))]; + "boundary precision - a and e should remain unchanged" + )] +fn test_merge_key_value_range( + initial_kvs: &[(&[u8], &[u8])], + first_key: Option<&[u8]>, + last_key: Option<&[u8]>, + merge_kvs: &[(&[u8], &[u8])], + expected_kvs: &[(&[u8], Option<&[u8]>)], +) { + let db = TestDb::new(); + + if !initial_kvs.is_empty() { + db.propose(initial_kvs).unwrap().commit().unwrap(); + } + + let proposal = db + .merge_key_value_range(first_key, last_key, merge_kvs) + .unwrap(); + + for (key, expected_value) in expected_kvs { + let actual_value = proposal.val(key).unwrap(); + match expected_value { + Some(v) => { + assert_eq!( + actual_value.as_deref(), + Some(*v), + "Key {key:?} should have value {v:?}, but got {actual_value:?}" + ); + } + None => { + assert!( + actual_value.is_none(), + "Key {key:?} should be deleted, but got {actual_value:?}" + ); + } + } + } + + let merge_root_hash = proposal.root_hash().unwrap(); + + // Create a fresh database with the same initial state + let db2 = TestDb::new(); + if !initial_kvs.is_empty() { + db2.propose(initial_kvs).unwrap().commit().unwrap(); + } + + // Apply the expected operations manually + let mut batch = Vec::new(); + if let Some(root) = db2.root_hash().unwrap() { + batch.extend( + db2.revision(root) + .unwrap() + .iter_option(first_key) + .unwrap() + .take_while(|res| { + if let Some(last_key) = last_key { + match res { + Ok((key, _)) => **key <= *last_key, + Err(_) => true, + } + } else { + true + } + }) + .map(|res| res.map(|(key, _)| BatchOp::Delete { key })), + ); + } + batch.extend(merge_kvs.iter().map(|(key, value)| { + Ok(BatchOp::Put { + key: (*key).into(), + value, + }) + })); + + let manual_proposal = db2.propose(batch).unwrap(); + let manual_root_hash = manual_proposal.root_hash().unwrap(); + + assert_eq!( + merge_root_hash, manual_root_hash, + "Root hash from merge should match root hash from manual operations" + ); + + // Commit the proposal and verify persistence + proposal.commit().unwrap(); + + // Verify the committed state + if let Some(root) = db.root_hash().unwrap() { + let committed = db.revision(root).unwrap(); + for (key, expected_value) in expected_kvs { + let actual_value = committed.val(key).unwrap(); + match expected_value { + Some(v) => { + assert_eq!( + actual_value.as_deref(), + Some(*v), + "After commit, key {key:?} should have value {v:?}, but got {actual_value:?}" + ); + } + None => { + assert!( + actual_value.is_none(), + "After commit, key {key:?} should be deleted, but got {actual_value:?}" + ); + } + } + } + } else { + for (key, expected_value) in expected_kvs { + assert!( + expected_value.is_none(), + "Database is empty, but expected key {key:?} to have value {expected_value:?}" + ); + } + } +} diff --git a/firewood/firewood/src/iter.rs b/firewood/firewood/src/iter.rs new file mode 100644 index 000000000000..8314afee66a3 --- /dev/null +++ b/firewood/firewood/src/iter.rs @@ -0,0 +1,1361 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +mod try_extend; + +pub(crate) use self::try_extend::TryExtend; +use crate::merkle::{Key, Value}; + +use firewood_storage::{ + BranchNode, Child, FileIoError, NibblesIterator, Node, PathBuf, PathComponent, PathIterItem, + SharedNode, TriePathFromUnpackedBytes, TrieReader, +}; +use std::cmp::Ordering; +use std::iter::FusedIterator; + +/// Represents an ongoing iteration over a node and its children. +enum IterationNode { + /// This node has not been returned yet. + Unvisited { + /// The key (as nibbles) of this node. + key: Key, + node: SharedNode, + }, + /// This node has been returned. Track which child to visit next. + Visited { + /// The key (as nibbles) of this node. + key: Key, + /// Returns the non-empty children of this node and their positions + /// in the node's children array. + children_iter: Box + Send>, + }, +} + +impl std::fmt::Debug for IterationNode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Unvisited { key, node } => f + .debug_struct("Unvisited") + .field("key", key) + .field("node", node) + .finish(), + Self::Visited { + key, + children_iter: _, + } => f.debug_struct("Visited").field("key", key).finish(), + } + } +} + +#[derive(Debug)] +enum NodeIterState { + /// The iterator state is lazily initialized when `poll_next` is called + /// for the first time. The iteration start key is stored here. + StartFromKey(Key), + Iterating { + /// Each element is a node that will be visited (i.e. returned) + /// or has been visited but has unvisited children. + /// On each call to `poll_next` we pop the next element. + /// If it's unvisited, we visit it. + /// If it's visited, we push its next child onto this stack. + iter_stack: Vec, + }, +} + +#[derive(Debug)] +/// An iterator of nodes in order starting from a specific point in the trie. +pub struct MerkleNodeIter<'a, T> { + state: NodeIterState, + merkle: &'a T, +} + +impl From for NodeIterState { + fn from(key: Key) -> Self { + Self::StartFromKey(key) + } +} + +impl<'a, T: TrieReader> MerkleNodeIter<'a, T> { + /// Returns a new iterator that will iterate over all the nodes in `merkle` + /// with keys greater than or equal to `key`. + pub(super) fn new(merkle: &'a T, key: Key) -> Self { + Self { + state: NodeIterState::from(key), + merkle, + } + } +} + +impl Iterator for MerkleNodeIter<'_, T> { + type Item = Result<(Key, SharedNode), FileIoError>; + + fn next(&mut self) -> Option { + 'outer: loop { + match &mut self.state { + NodeIterState::StartFromKey(key) => { + match get_iterator_intial_state(self.merkle, key) { + Ok(state) => self.state = state, + Err(e) => return Some(Err(e)), + } + } + NodeIterState::Iterating { iter_stack } => { + while let Some(mut iter_node) = iter_stack.pop() { + match iter_node { + IterationNode::Unvisited { key, node } => { + match &*node { + Node::Leaf(_) => {} + Node::Branch(branch) => { + // `node` is a branch node. Visit its children next. + iter_stack.push(IterationNode::Visited { + key: key.clone(), + children_iter: Box::new(as_enumerated_children_iter( + branch, + )), + }); + } + } + + let key = key_from_nibble_iter(key.iter().copied()); + return Some(Ok((key, node))); + } + IterationNode::Visited { + ref key, + ref mut children_iter, + } => { + // We returned `node` already. Visit its next child. + let Some((pos, child)) = children_iter.next() else { + // We visited all this node's descendants. Go back to its parent. + continue; + }; + + let child = match child { + Child::AddressWithHash(addr, _) => { + match self.merkle.read_node(addr) { + Ok(node) => node, + Err(e) => return Some(Err(e)), + } + } + Child::Node(node) => node.clone().into(), + Child::MaybePersisted(maybe_persisted, _) => { + // For MaybePersisted, we need to get the node + match maybe_persisted.as_shared_node(self.merkle) { + Ok(node) => node, + Err(e) => return Some(Err(e)), + } + } + }; + + let child_partial_path = child.partial_path().iter().copied(); + + // The child's key is its parent's key, followed by the child's index, + // followed by the child's partial path (if any). + let child_key: Key = key + .iter() + .copied() + .chain(Some(pos.as_u8())) + .chain(child_partial_path) + .collect(); + + // There may be more children of this node to visit. + // Visit it again after visiting its `child`. + iter_stack.push(iter_node); + + iter_stack.push(IterationNode::Unvisited { + key: child_key, + node: child, + }); + + continue 'outer; + } + } + } + + return None; + } + } + } + } +} + +impl FusedIterator for MerkleNodeIter<'_, T> {} + +/// Returns the initial state for an iterator over the given `merkle` which starts at `key`. +fn get_iterator_intial_state( + merkle: &T, + key: &[u8], +) -> Result { + let Some(root) = merkle.root_node() else { + // This merkle is empty. + return Ok(NodeIterState::Iterating { iter_stack: vec![] }); + }; + let mut node = root; + + // Invariant: `matched_key_nibbles` is the path before `node`'s + // partial path at the start of each loop iteration. + let mut matched_key_nibbles = vec![]; + + let mut unmatched_key_nibbles = NibblesIterator::new(key); + + let mut iter_stack: Vec = vec![]; + + loop { + // See if `node`'s key is a prefix of `key`. + let partial_path = node.partial_path(); + + let (comparison, new_unmatched_key_nibbles) = + compare_partial_path(partial_path.iter(), unmatched_key_nibbles); + unmatched_key_nibbles = new_unmatched_key_nibbles; + + matched_key_nibbles.extend(partial_path.iter()); + + match comparison { + Ordering::Less => { + // `node` is before `key`. It shouldn't be visited + // and neither should its descendants. + return Ok(NodeIterState::Iterating { iter_stack }); + } + Ordering::Greater => { + // `node` is after `key`. Visit it first. + iter_stack.push(IterationNode::Unvisited { + key: Box::from(matched_key_nibbles), + node, + }); + return Ok(NodeIterState::Iterating { iter_stack }); + } + Ordering::Equal => match &*node { + Node::Leaf(_) => { + iter_stack.push(IterationNode::Unvisited { + key: matched_key_nibbles.clone().into_boxed_slice(), + node, + }); + return Ok(NodeIterState::Iterating { iter_stack }); + } + Node::Branch(branch) => { + let Some(next_unmatched_key_nibble) = unmatched_key_nibbles.next() else { + // There is no more key to traverse. + iter_stack.push(IterationNode::Unvisited { + key: matched_key_nibbles.clone().into_boxed_slice(), + node, + }); + + return Ok(NodeIterState::Iterating { iter_stack }); + }; + let next_unmatched_key_nibble = + PathComponent::try_new(next_unmatched_key_nibble).expect("valid nibble"); + + // There is no child at `next_unmatched_key_nibble`. + // We'll visit `node`'s first child at index > `next_unmatched_key_nibble` + // first (if it exists). + iter_stack.push(IterationNode::Visited { + key: matched_key_nibbles.clone().into_boxed_slice(), + children_iter: Box::new( + as_enumerated_children_iter(branch) + .filter(move |(pos, _)| *pos > next_unmatched_key_nibble), + ), + }); + + let child = &branch.children[next_unmatched_key_nibble]; + node = match child { + None => return Ok(NodeIterState::Iterating { iter_stack }), + Some(Child::AddressWithHash(addr, _)) => merkle.read_node(*addr)?, + Some(Child::Node(node)) => (*node).clone().into(), // TODO can we avoid cloning this? + Some(Child::MaybePersisted(maybe_persisted, _)) => { + // For MaybePersisted, we need to get the node + maybe_persisted.as_shared_node(merkle)? + } + }; + + matched_key_nibbles.push(next_unmatched_key_nibble.as_u8()); + } + }, + } + } +} + +#[derive(Debug)] +/// An iterator of key-value pairs in order starting from a specific point in the trie. +pub struct MerkleKeyValueIter<'a, T> { + iter: MerkleNodeIter<'a, T>, +} + +impl<'a, T: TrieReader> From<&'a T> for MerkleKeyValueIter<'a, T> { + fn from(merkle: &'a T) -> Self { + Self { + iter: MerkleNodeIter::new(merkle, Box::new([])), + } + } +} + +impl<'a, T: TrieReader> MerkleKeyValueIter<'a, T> { + /// Construct a [`MerkleKeyValueIter`] that will iterate over all the key-value pairs in `merkle` + /// starting from a particular key + pub fn from_key>(merkle: &'a T, key: K) -> Self { + Self { + iter: MerkleNodeIter::new(merkle, key.as_ref().into()), + } + } +} + +impl Iterator for MerkleKeyValueIter<'_, T> { + type Item = Result<(Key, Value), FileIoError>; + + fn next(&mut self) -> Option { + self.iter.find_map(|result| { + result + .map(|(key, node)| { + match &*node { + Node::Branch(branch) => { + let Some(value) = branch.value.as_ref() else { + // This node doesn't have a value to return. + // Continue to the next node. + return None; + }; + Some((key, value.clone())) + } + Node::Leaf(leaf) => Some((key, leaf.value.clone())), + } + }) + .transpose() + }) + } +} + +impl FusedIterator for MerkleKeyValueIter<'_, T> {} + +#[derive(Debug)] +enum PathIteratorState<'a> { + Iterating { + /// The key, as nibbles, of the node at `address`, without the + /// node's partial path (if any) at the end. + /// Invariant: If this node has a parent, the parent's key is a + /// prefix of the key we're traversing to. + /// Note the node at `address` may not have a key which is a + /// prefix of the key we're traversing to. + matched_key: Vec, + unmatched_key: NibblesIterator<'a>, + node: SharedNode, + }, + Exhausted, +} + +/// Iterates over all nodes on the path to a given key starting from the root. +/// +/// All nodes are branch nodes except possibly the last, which may be a leaf. +/// All returned nodes have keys which are a prefix of the given key. +/// If the given key is in the trie, the last node is at that key. +#[derive(Debug)] +pub struct PathIterator<'a, 'b, T> { + state: PathIteratorState<'b>, + merkle: &'a T, +} + +impl<'a, 'b, T: TrieReader> PathIterator<'a, 'b, T> { + pub(super) fn new(merkle: &'a T, key: &'b [u8]) -> Result { + let Some(root) = merkle.root_node() else { + return Ok(Self { + state: PathIteratorState::Exhausted, + merkle, + }); + }; + + Ok(Self { + merkle, + state: PathIteratorState::Iterating { + matched_key: vec![], + unmatched_key: NibblesIterator::new(key), + node: root, + }, + }) + } +} + +impl Iterator for PathIterator<'_, '_, T> { + type Item = Result; + + fn next(&mut self) -> Option { + // destructuring is necessary here because we need mutable access to `state` + // at the same time as immutable access to `merkle`. + let Self { state, merkle } = &mut *self; + + match state { + PathIteratorState::Exhausted => None, + PathIteratorState::Iterating { + matched_key, + unmatched_key, + node, + } => { + let partial_path = match &**node { + Node::Branch(branch) => &branch.partial_path, + Node::Leaf(leaf) => &leaf.partial_path, + }; + + let (comparison, unmatched_key) = + compare_partial_path(partial_path.iter(), unmatched_key); + + match comparison { + Ordering::Less | Ordering::Greater => { + self.state = PathIteratorState::Exhausted; + None + } + Ordering::Equal => { + matched_key.extend(partial_path.iter()); + let node_key = PathBuf::path_from_unpacked_bytes(matched_key) + .expect("valid components"); + + match &**node { + Node::Leaf(_) => { + // We're at a leaf so we're done. + let node = node.clone(); + self.state = PathIteratorState::Exhausted; + Some(Ok(PathIterItem { + key_nibbles: node_key, + node, + next_nibble: None, + })) + } + Node::Branch(branch) => { + // We're at a branch whose key is a prefix of `key`. + // Find its child (if any) that matches the next nibble in the key. + let saved_node = node.clone(); + let Some(next_unmatched_key_nibble) = unmatched_key.next() else { + // We're at the node at `key` so we're done. + self.state = PathIteratorState::Exhausted; + return Some(Ok(PathIterItem { + key_nibbles: node_key, + node: saved_node, + next_nibble: None, + })); + }; + let next_unmatched_key_nibble = + PathComponent::try_new(next_unmatched_key_nibble) + .expect("valid nibble"); + + let child = &branch.children[next_unmatched_key_nibble]; + match child { + None => { + // There's no child at the index of the next nibble in the key. + // There's no node at `key` in this trie so we're done. + self.state = PathIteratorState::Exhausted; + Some(Ok(PathIterItem { + key_nibbles: node_key, + node: saved_node, + next_nibble: None, + })) + } + Some(Child::AddressWithHash(child_addr, _)) => { + let child = match merkle.read_node(*child_addr) { + Ok(child) => child, + Err(e) => return Some(Err(e)), + }; + + matched_key.push(next_unmatched_key_nibble.as_u8()); + + *node = child; + + Some(Ok(PathIterItem { + key_nibbles: node_key, + node: saved_node, + next_nibble: Some(next_unmatched_key_nibble), + })) + } + Some(Child::Node(child)) => { + matched_key.push(next_unmatched_key_nibble.as_u8()); + + *node = child.clone().into(); + + Some(Ok(PathIterItem { + key_nibbles: node_key, + node: saved_node, + next_nibble: Some(next_unmatched_key_nibble), + })) + } + Some(Child::MaybePersisted(maybe_persisted, _)) => { + let child = match maybe_persisted.as_shared_node(merkle) { + Ok(child) => child, + Err(e) => return Some(Err(e)), + }; + + matched_key.push(next_unmatched_key_nibble.as_u8()); + *node = child; + + Some(Ok(PathIterItem { + key_nibbles: node_key, + node: saved_node, + next_nibble: Some(next_unmatched_key_nibble), + })) + } + } + } + } + } + } + } + } + } +} + +/// Takes in an iterator over a node's partial path and an iterator over the +/// unmatched portion of a key. +/// The first returned element is: +/// * [`Ordering::Less`] if the node is before the key. +/// * [`Ordering::Equal`] if the node is a prefix of the key. +/// * [`Ordering::Greater`] if the node is after the key. +/// +/// The second returned element is the unmatched portion of the key after the +/// partial path has been matched. +fn compare_partial_path<'a, I1, I2>( + partial_path_iter: I1, + mut unmatched_key_nibbles_iter: I2, +) -> (Ordering, I2) +where + I1: Iterator, + I2: Iterator, +{ + for next_partial_path_nibble in partial_path_iter { + let Some(next_key_nibble) = unmatched_key_nibbles_iter.next() else { + return (Ordering::Greater, unmatched_key_nibbles_iter); + }; + + match next_partial_path_nibble.cmp(&next_key_nibble) { + Ordering::Less => return (Ordering::Less, unmatched_key_nibbles_iter), + Ordering::Greater => return (Ordering::Greater, unmatched_key_nibbles_iter), + Ordering::Equal => {} + } + } + + (Ordering::Equal, unmatched_key_nibbles_iter) +} + +/// Returns an iterator that returns (`pos`,`child`) for each non-empty child of `branch`, +/// where `pos` is the position of the child in `branch`'s children array. +fn as_enumerated_children_iter( + branch: &BranchNode, +) -> impl Iterator + use<> { + branch + .children + .clone() + .into_iter() + .filter_map(|(pos, child)| child.map(|child| (pos, child))) +} + +#[cfg(feature = "branch_factor_256")] +fn key_from_nibble_iter>(nibbles: Iter) -> Key { + nibbles.collect() +} + +#[cfg(not(feature = "branch_factor_256"))] +fn key_from_nibble_iter>(mut nibbles: Iter) -> Key { + let mut data = Vec::with_capacity(nibbles.size_hint().0 / 2); + + while let (Some(hi), Some(lo)) = (nibbles.next(), nibbles.next()) { + let byte = hi + .checked_shl(4) + .and_then(|v| v.checked_add(lo)) + .expect("Nibble overflow while constructing byte"); + data.push(byte); + } + + data.into_boxed_slice() +} + +#[cfg(test)] +#[expect(clippy::indexing_slicing, clippy::unwrap_used)] +mod tests { + use super::*; + use crate::merkle::Merkle; + use firewood_storage::{ImmutableProposal, MemStore, MutableProposal, NodeStore}; + use std::sync::Arc; + use test_case::test_case; + + macro_rules! path { + ($($elem:expr),* $(,)?)=>{ + [ + $( + PathComponent::ALL[$elem], + )* + ] + }; + } + + pub(super) fn create_test_merkle() -> Merkle> { + let memstore = MemStore::new(vec![]); + let memstore = Arc::new(memstore); + let nodestore = NodeStore::new_empty_proposal(memstore); + Merkle::from(nodestore) + } + + #[test_case(&[]; "empty key")] + #[test_case(&[1]; "non-empty key")] + fn path_iterate_empty_merkle_empty_key(key: &[u8]) { + let merkle = create_test_merkle(); + let mut iter = merkle.path_iter(key).unwrap(); + assert!(iter.next().is_none()); + } + + #[test_case(&[],false; "empty key")] + #[test_case(&[0xBE,0xE0],false; "prefix of singleton key")] + #[test_case(&[0xBE, 0xEF],true; "match singleton key")] + #[test_case(&[0xBE, 0xEF,0x10],true; "suffix of singleton key")] + #[test_case(&[0xF0],false; "no key nibbles match singleton key")] + fn path_iterate_singleton_merkle(key: &[u8], should_yield_elt: bool) { + let mut merkle = create_test_merkle(); + + merkle.insert(&[0xBE, 0xEF], Box::new([0x42])).unwrap(); + + let mut iter = merkle.path_iter(key).unwrap(); + let node = match iter.next() { + Some(Ok(item)) => item, + Some(Err(e)) => panic!("{e:?}"), + None => { + assert!(!should_yield_elt); + return; + } + }; + + assert!(should_yield_elt); + #[cfg(not(feature = "branch_factor_256"))] + assert_eq!(*node.key_nibbles, path![0x0B, 0x0E, 0x0E, 0x0F]); + #[cfg(feature = "branch_factor_256")] + assert_eq!(*node.key_nibbles, path![0xBE, 0xEF]); + assert_eq!(node.node.as_leaf().unwrap().value, Box::from([0x42])); + assert_eq!(node.next_nibble, None); + + assert!(iter.next().is_none()); + } + + #[test_case(&[0x00, 0x00, 0x00, 0xFF]; "leaf key")] + #[test_case(&[0x00, 0x00, 0x00, 0xFF, 0x01]; "leaf key suffix")] + fn path_iterate_non_singleton_merkle_seek_leaf(key: &[u8]) { + let merkle = created_populated_merkle(); + + let mut iter = merkle.path_iter(key).unwrap(); + + let node = match iter.next() { + Some(Ok(node)) => node, + Some(Err(e)) => panic!("{e:?}"), + None => panic!("unexpected end of iterator"), + }; + #[cfg(not(feature = "branch_factor_256"))] + assert_eq!(*node.key_nibbles, path![0x00, 0x00]); + #[cfg(feature = "branch_factor_256")] + assert_eq!(*node.key_nibbles, path![0]); + assert_eq!(node.next_nibble, Some(PathComponent::ALL[0])); + assert!(node.node.as_branch().unwrap().value.is_none()); + + let node = match iter.next() { + Some(Ok(node)) => node, + Some(Err(e)) => panic!("{e:?}"), + None => panic!("unexpected end of iterator"), + }; + #[cfg(not(feature = "branch_factor_256"))] + assert_eq!(*node.key_nibbles, path![0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + #[cfg(feature = "branch_factor_256")] + assert_eq!(*node.key_nibbles, path![0, 0, 0]); + + assert_eq!(node.next_nibble, PathComponent::ALL.last().copied()); + + assert_eq!( + node.node.as_branch().unwrap().value, + Some(vec![0x00, 0x00, 0x00].into_boxed_slice()), + ); + + let node = match iter.next() { + Some(Ok(node)) => node, + Some(Err(e)) => panic!("{e:?}"), + None => panic!("unexpected end of iterator"), + }; + #[cfg(not(feature = "branch_factor_256"))] + assert_eq!( + *node.key_nibbles, + path![0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F] + ); + assert_eq!(node.next_nibble, None); + assert_eq!( + node.node.as_leaf().unwrap().value, + Box::from([0x00, 0x00, 0x00, 0x0FF]) + ); + + assert!(iter.next().is_none()); + } + + #[test_case(&[0x00, 0x00, 0x00]; "branch key")] + #[test_case(&[0x00, 0x00, 0x00, 0x10]; "branch key suffix (but not a leaf key)")] + fn path_iterate_non_singleton_merkle_seek_branch(key: &[u8]) { + let merkle = created_populated_merkle(); + + let mut iter = merkle.path_iter(key).unwrap(); + + let node = match iter.next() { + Some(Ok(node)) => node, + Some(Err(e)) => panic!("{e:?}"), + None => panic!("unexpected end of iterator"), + }; + // TODO: make this branch factor 16 compatible + #[cfg(not(feature = "branch_factor_256"))] + assert_eq!(*node.key_nibbles, path![0x00, 0x00]); + + assert!(node.node.as_branch().unwrap().value.is_none()); + assert_eq!(node.next_nibble, Some(PathComponent::ALL[0])); + + let node = match iter.next() { + Some(Ok(node)) => node, + Some(Err(e)) => panic!("{e:?}"), + None => panic!("unexpected end of iterator"), + }; + #[cfg(not(feature = "branch_factor_256"))] + assert_eq!(*node.key_nibbles, path![0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); + assert_eq!( + node.node.as_branch().unwrap().value, + Some(vec![0x00, 0x00, 0x00].into_boxed_slice()), + ); + assert_eq!(node.next_nibble, None); + + assert!(iter.next().is_none()); + } + + #[test] + fn key_value_iterate_empty() { + let merkle = create_test_merkle(); + let iter = merkle.key_value_iter_from_key(b"x".to_vec().into_boxed_slice()); + assert_iterator_is_exhausted(iter); + } + + #[test] + fn node_iterate_empty() { + let merkle = create_test_merkle(); + let iter = MerkleNodeIter::new(merkle.nodestore(), Box::new([])); + assert_iterator_is_exhausted(iter); + } + + #[test] + fn node_iterate_root_only() { + let mut merkle = create_test_merkle(); + + merkle.insert(&[0x00], Box::new([0x00])).unwrap(); + + let mut iter = MerkleNodeIter::new(merkle.nodestore(), Box::new([])); + + let (key, node) = iter.next().unwrap().unwrap(); + + assert_eq!(key, vec![0x00].into_boxed_slice()); + assert_eq!(node.as_leaf().unwrap().value.to_vec(), vec![0x00]); + + assert_iterator_is_exhausted(iter); + } + + /// Returns a new [Merkle] with the following key-value pairs: + /// Note each hex symbol in the keys below is a nibble (not two nibbles). + /// Each hex symbol in the values below is a byte. + /// 000000 --> 000000 + /// 00000001 -->00000001 + /// 000000FF --> 000000FF + /// 00D0D0 --> 00D0D0 + /// 00FF --> 00FF + /// structure: + /// 00 <-- branch with no value + /// 0/ D| \F + /// 000 0D0 F <-- leaf with no partial path + /// 0/ \F + /// 1 F + /// + /// The number next to each branch is the position of the child in the branch's children array. + fn created_populated_merkle() -> Merkle> { + let mut merkle = create_test_merkle(); + + merkle + .insert(&[0x00, 0x00, 0x00], Box::new([0x00, 0x00, 0x00])) + .unwrap(); + merkle + .insert( + &[0x00, 0x00, 0x00, 0x01], + Box::new([0x00, 0x00, 0x00, 0x01]), + ) + .unwrap(); + merkle + .insert( + &[0x00, 0x00, 0x00, 0xFF], + Box::new([0x00, 0x00, 0x00, 0xFF]), + ) + .unwrap(); + merkle + .insert(&[0x00, 0xD0, 0xD0], Box::new([0x00, 0xD0, 0xD0])) + .unwrap(); + merkle + .insert(&[0x00, 0xFF], Box::new([0x00, 0xFF])) + .unwrap(); + merkle + } + + #[test] + fn node_iterator_no_start_key() { + let merkle = created_populated_merkle(); + + let mut iter = MerkleNodeIter::new(merkle.nodestore(), Box::new([])); + + // Covers case of branch with no value + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00].into_boxed_slice()); + let node = node.as_branch().unwrap(); + assert!(node.value.is_none()); + + // Covers case of branch with value + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0x00, 0x00].into_boxed_slice()); + let node = node.as_branch().unwrap(); + assert_eq!(node.value.clone().unwrap().to_vec(), vec![0x00, 0x00, 0x00]); + + // Covers case of leaf with partial path + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0x00, 0x00, 0x01].into_boxed_slice()); + let node = node.as_leaf().unwrap(); + assert_eq!(node.clone().value.to_vec(), vec![0x00, 0x00, 0x00, 0x01]); + + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0x00, 0x00, 0xFF].into_boxed_slice()); + let node = node.as_leaf().unwrap(); + assert_eq!(node.clone().value.to_vec(), vec![0x00, 0x00, 0x00, 0xFF]); + + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0xD0, 0xD0].into_boxed_slice()); + let node = node.as_leaf().unwrap(); + assert_eq!(node.clone().value.to_vec(), vec![0x00, 0xD0, 0xD0]); + + // Covers case of leaf with no partial path + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0xFF].into_boxed_slice()); + let node = node.as_leaf().unwrap(); + assert_eq!(node.clone().value.to_vec(), vec![0x00, 0xFF]); + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn node_iterator_start_key_between_nodes() { + let merkle = created_populated_merkle(); + + let mut iter = MerkleNodeIter::new( + merkle.nodestore(), + vec![0x00, 0x00, 0x01].into_boxed_slice(), + ); + + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0xD0, 0xD0].into_boxed_slice()); + assert_eq!( + node.as_leaf().unwrap().clone().value.to_vec(), + vec![0x00, 0xD0, 0xD0] + ); + + // Covers case of leaf with no partial path + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0xFF].into_boxed_slice()); + assert_eq!( + node.as_leaf().unwrap().clone().value.to_vec(), + vec![0x00, 0xFF] + ); + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn node_iterator_start_key_on_node() { + let merkle = created_populated_merkle(); + + let mut iter = MerkleNodeIter::new( + merkle.nodestore(), + vec![0x00, 0xD0, 0xD0].into_boxed_slice(), + ); + + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0xD0, 0xD0].into_boxed_slice()); + assert_eq!( + node.as_leaf().unwrap().clone().value.to_vec(), + vec![0x00, 0xD0, 0xD0] + ); + + // Covers case of leaf with no partial path + let (key, node) = iter.next().unwrap().unwrap(); + assert_eq!(key, vec![0x00, 0xFF].into_boxed_slice()); + assert_eq!( + node.as_leaf().unwrap().clone().value.to_vec(), + vec![0x00, 0xFF] + ); + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn node_iterator_start_key_after_last_key() { + let merkle = created_populated_merkle(); + + let iter = MerkleNodeIter::new(merkle.nodestore(), vec![0xFF].into_boxed_slice()); + + assert_iterator_is_exhausted(iter); + } + + #[test_case(Some(&[u8::MIN]); "Starting at first key")] + #[test_case(None; "No start specified")] + #[test_case(Some(&[128u8]); "Starting in middle")] + #[test_case(Some(&[u8::MAX]); "Starting at last key")] + fn key_value_iterate_many(start: Option<&[u8]>) { + let mut merkle = create_test_merkle(); + + // insert all values from u8::MIN to u8::MAX, with the key and value the same + for k in u8::MIN..=u8::MAX { + merkle.insert(&[k], Box::new([k])).unwrap(); + } + + let mut iter = match start { + Some(start) => merkle.key_value_iter_from_key(start.to_vec().into_boxed_slice()), + None => merkle.key_value_iter(), + }; + + // we iterate twice because we should get a None then start over + #[expect(clippy::indexing_slicing)] + for k in start.map(|r| r[0]).unwrap_or_default()..=u8::MAX { + let next = iter.next().map(|kv| { + let (k, v) = kv.unwrap(); + assert_eq!(&*k, &*v); + k + }); + + assert_eq!(next, Some(vec![k].into_boxed_slice())); + } + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_fused_empty() { + let merkle = create_test_merkle(); + assert_iterator_is_exhausted(merkle.key_value_iter()); + } + + #[test] + fn key_value_table_test() { + let mut merkle = create_test_merkle(); + + let max: u8 = 100; + // Insert key-values in reverse order to ensure iterator + // doesn't just return the keys in insertion order. + for i in (0..=max).rev() { + for j in (0..=max).rev() { + let key = &[i, j]; + let value = Box::new([i, j]); + + merkle.insert(key, value).unwrap(); + } + } + + // Test with no start key + let mut iter = merkle.key_value_iter(); + for i in 0..=max { + for j in 0..=max { + let expected_key = vec![i, j]; + let expected_value = vec![i, j]; + + assert_eq!( + iter.next().unwrap().unwrap(), + ( + expected_key.into_boxed_slice(), + expected_value.into_boxed_slice(), + ), + "i: {i}, j: {j}", + ); + } + } + assert_iterator_is_exhausted(iter); + + // Test with start key + for i in 0..=max { + let mut iter = merkle.key_value_iter_from_key(vec![i].into_boxed_slice()); + for j in 0..=max { + let expected_key = vec![i, j]; + let expected_value = vec![i, j]; + assert_eq!( + iter.next().unwrap().unwrap(), + ( + expected_key.into_boxed_slice(), + expected_value.into_boxed_slice(), + ), + "i: {i}, j: {j}", + ); + } + if i == max { + assert_iterator_is_exhausted(iter); + } else { + assert_eq!( + iter.next().unwrap().unwrap(), + ( + vec![i + 1, 0].into_boxed_slice(), + vec![i + 1, 0].into_boxed_slice(), + ), + "i: {i}", + ); + } + } + } + + #[test] + fn key_value_fused_full() { + let mut merkle = create_test_merkle(); + + let last = vec![0x00, 0x00, 0x00]; + + let mut key_values = vec![vec![0x00], vec![0x00, 0x00], last.clone()]; + + // branchs with paths (or extensions) will be present as well as leaves with siblings + for kv in u8::MIN..=u8::MAX { + let mut last = last.clone(); + last.push(kv); + key_values.push(last); + } + + for kv in &key_values { + merkle.insert(kv, kv.clone().into_boxed_slice()).unwrap(); + } + + let mut iter = merkle.key_value_iter(); + + for kv in &key_values { + let next = iter.next().unwrap().unwrap(); + assert_eq!(&*next.0, &*next.1); + assert_eq!(&*next.1, &**kv); + } + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_root_with_empty_value() { + let mut merkle = create_test_merkle(); + + let key = vec![].into_boxed_slice(); + let value = [0x00]; + + merkle.insert(&key, value.into()).unwrap(); + + let mut iter = merkle.key_value_iter(); + + assert_eq!(iter.next().unwrap().unwrap(), (key, value.into())); + } + + #[test] + fn key_value_get_branch_and_leaf() { + let mut merkle = create_test_merkle(); + + let first_leaf = [0x00, 0x00]; + let second_leaf = [0x00, 0x0f]; + let branch = [0x00]; + + merkle.insert(&first_leaf, first_leaf.into()).unwrap(); + merkle.insert(&second_leaf, second_leaf.into()).unwrap(); + + merkle.insert(&branch, branch.into()).unwrap(); + + let immutable_merkle: Merkle, _>> = + merkle.try_into().unwrap(); + println!("{}", immutable_merkle.dump_to_string().unwrap()); + merkle = immutable_merkle.fork().unwrap(); + + let mut iter = merkle.key_value_iter(); + + assert_eq!( + iter.next().unwrap().unwrap(), + (branch.into(), branch.into()) + ); + + assert_eq!( + iter.next().unwrap().unwrap(), + (first_leaf.into(), first_leaf.into()) + ); + + assert_eq!( + iter.next().unwrap().unwrap(), + (second_leaf.into(), second_leaf.into()) + ); + } + + #[test] + fn key_value_start_at_key_not_in_trie() { + let mut merkle = create_test_merkle(); + + let first_key = 0x00; + let intermediate = 0x80; + + assert!(first_key < intermediate); + + let key_values = [ + vec![first_key], + vec![intermediate, intermediate], + vec![intermediate, intermediate, intermediate], + ]; + assert!(key_values[0] < key_values[1]); + assert!(key_values[1] < key_values[2]); + + for key in &key_values { + merkle.insert(key, key.clone().into_boxed_slice()).unwrap(); + } + + let mut iter = merkle.key_value_iter_from_key(vec![intermediate].into_boxed_slice()); + + let first_expected = key_values[1].as_slice(); + let first = iter.next().unwrap().unwrap(); + + assert_eq!(&*first.0, &*first.1); + assert_eq!(&*first.1, first_expected); + + let second_expected = key_values[2].as_slice(); + let second = iter.next().unwrap().unwrap(); + + assert_eq!(&*second.0, &*second.1); + assert_eq!(&*second.1, second_expected); + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_start_at_key_on_branch_with_no_value() { + let sibling_path = 0x00; + let branch_path = 0x0f; + let children = 0..=0x0f; + + let mut merkle = create_test_merkle(); + + children.clone().for_each(|child_path| { + let key = vec![sibling_path, child_path]; + + merkle.insert(&key, key.clone().into()).unwrap(); + }); + + let mut keys: Vec<_> = children + .map(|child_path| { + let key = vec![branch_path, child_path]; + + merkle.insert(&key, key.clone().into()).unwrap(); + + key + }) + .collect(); + + keys.sort(); + + let start = keys.iter().position(|key| key[0] == branch_path).unwrap(); + let keys = &keys[start..]; + + let mut iter = merkle.key_value_iter_from_key(vec![branch_path].into_boxed_slice()); + + for key in keys { + let next = iter.next().unwrap().unwrap(); + + assert_eq!(&*next.0, &*next.1); + assert_eq!(&*next.0, key); + } + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_start_at_key_on_branch_with_value() { + let sibling_path = 0x00; + let branch_path = 0x0f; + let branch_key = vec![branch_path]; + + let children = (0..=0xf).map(|val| (val << 4) + val); // 0x00, 0x11, ... 0xff + + let mut merkle = create_test_merkle(); + + merkle + .insert(&branch_key, branch_key.clone().into()) + .unwrap(); + + children.clone().for_each(|child_path| { + let key = vec![sibling_path, child_path]; + + merkle.insert(&key, key.clone().into()).unwrap(); + }); + + let mut keys: Vec<_> = children + .map(|child_path| { + let key = vec![branch_path, child_path]; + + merkle.insert(&key, key.clone().into()).unwrap(); + + key + }) + .chain(Some(branch_key.clone())) + .collect(); + + keys.sort(); + + let start = keys.iter().position(|key| key == &branch_key).unwrap(); + let keys = &keys[start..]; + + let mut iter = merkle.key_value_iter_from_key(branch_key.into_boxed_slice()); + + for key in keys { + let next = iter.next().unwrap().unwrap(); + + assert_eq!(&*next.0, &*next.1); + assert_eq!(&*next.0, key); + } + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_start_at_key_on_extension() { + let missing = 0x0a; + let children = (0..=0x0f).filter(|x| *x != missing); + let mut merkle = create_test_merkle(); + + let keys: Vec<_> = children + .map(|child_path| { + let key = vec![child_path]; + + merkle.insert(&key, key.clone().into()).unwrap(); + + key + }) + .collect(); + + let keys = &keys[(missing as usize)..]; + + let mut iter = merkle.key_value_iter_from_key(vec![missing].into_boxed_slice()); + + for key in keys { + let next = iter.next().unwrap().unwrap(); + + assert_eq!(&*next.0, &*next.1); + assert_eq!(&*next.0, key); + } + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_start_at_key_overlapping_with_extension_but_greater() { + let start_key = 0x0a; + let shared_path = 0x09; + // 0x0900, 0x0901, ... 0x0a0f + // path extension is 0x090 + let children = (0..=0x0f).map(|val| vec![shared_path, val]); + + let mut merkle = create_test_merkle(); + + children.for_each(|key| { + merkle.insert(&key, key.clone().into()).unwrap(); + }); + + let iter = merkle.key_value_iter_from_key(vec![start_key].into_boxed_slice()); + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_start_at_key_overlapping_with_extension_but_smaller() { + let start_key = 0x00; + let shared_path = 0x09; + // 0x0900, 0x0901, ... 0x0a0f + // path extension is 0x090 + let children = (0..=0x0f).map(|val| vec![shared_path, val]); + + let mut merkle = create_test_merkle(); + + let keys: Vec<_> = children + .inspect(|key| { + merkle.insert(key, key.clone().into()).unwrap(); + }) + .collect(); + + let mut iter = merkle.key_value_iter_from_key(vec![start_key].into_boxed_slice()); + + for key in keys { + let next = iter.next().unwrap().unwrap(); + + assert_eq!(&*next.0, &*next.1); + assert_eq!(&*next.0, key); + } + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_start_at_key_between_siblings() { + let missing = 0xaa; + let children = (0..=0xf) + .map(|val| (val << 4) + val) // 0x00, 0x11, ... 0xff + .filter(|x| *x != missing); + let mut merkle = create_test_merkle(); + + let keys: Vec<_> = children + .map(|child_path| { + let key = vec![child_path]; + + merkle.insert(&key, key.clone().into()).unwrap(); + + key + }) + .collect(); + + let keys = &keys[((missing >> 4) as usize)..]; + + let mut iter = merkle.key_value_iter_from_key(vec![missing].into_boxed_slice()); + + for key in keys { + let next = iter.next().unwrap().unwrap(); + + assert_eq!(&*next.0, &*next.1); + assert_eq!(&*next.0, key); + } + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_start_at_key_greater_than_all_others_leaf() { + let key = [0x00]; + let greater_key = [0xff]; + let mut merkle = create_test_merkle(); + merkle.insert(&key, key.into()).unwrap(); + + let iter = merkle.key_value_iter_from_key(greater_key); + + assert_iterator_is_exhausted(iter); + } + + #[test] + fn key_value_start_at_key_greater_than_all_others_branch() { + let greatest = 0xff; + let children = (0..=0xf) + .map(|val| (val << 4) + val) // 0x00, 0x11, ... 0xff + .filter(|x| *x != greatest); + let mut merkle = create_test_merkle(); + + let keys: Vec<_> = children + .map(|child_path| { + let key = vec![child_path]; + + merkle.insert(&key, key.clone().into()).unwrap(); + + key + }) + .collect(); + + let keys = &keys[((greatest >> 4) as usize)..]; + + let mut iter = merkle.key_value_iter_from_key(vec![greatest].into_boxed_slice()); + + for key in keys { + let next = iter.next().unwrap().unwrap(); + + assert_eq!(&*next.0, &*next.1); + assert_eq!(&*next.0, key); + } + + assert_iterator_is_exhausted(iter); + } + + fn assert_iterator_is_exhausted(mut iter: I) { + assert!(iter.next().is_none()); + } +} diff --git a/firewood/firewood/src/iter/try_extend.rs b/firewood/firewood/src/iter/try_extend.rs new file mode 100644 index 000000000000..f6322d4b51dc --- /dev/null +++ b/firewood/firewood/src/iter/try_extend.rs @@ -0,0 +1,75 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +/// An extension trait for extendable collections to handle iterators that yield +/// `Result`. +pub(crate) trait TryExtend: Extend { + /// Lazily collect an iterator over results into an extendable collection of the Ok value. + /// + /// Returns early if an error is encountered returning that error. + fn try_extend>, E>(&mut self, iter: I) -> Result<(), E> { + let mut error = None; + + self.extend(Shunt { + iter: iter.into_iter(), + error: &mut error, + }); + + if let Some(e) = error { Err(e) } else { Ok(()) } + } +} + +impl, T> TryExtend for C {} + +struct Shunt<'a, I, E> { + iter: I, + error: &'a mut Option, +} + +impl>, T, E> Iterator for Shunt<'_, I, E> { + type Item = T; + + fn next(&mut self) -> Option { + if self.error.is_some() { + return None; + } + + match self.iter.next() { + Some(Ok(item)) => Some(item), + Some(Err(e)) => { + *self.error = Some(e); + None + } + None => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + if self.error.is_some() { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_try_extend() { + let input = [Ok(0), Ok(1), Err("error"), Ok(3)]; + let mut collection = Vec::new(); + + let mut iter = input.into_iter(); + let result = collection.try_extend(iter.by_ref()); + assert_eq!(result, Err("error")); + assert_eq!(iter.next(), Some(Ok(3))); + assert_eq!(iter.next(), None); + assert_eq!(*collection, [0, 1]); + // vec should allocate for 4 elements because of the size hint + assert_eq!(collection.capacity(), 4); + } +} diff --git a/firewood/firewood/src/lib.rs b/firewood/firewood/src/lib.rs new file mode 100644 index 000000000000..24768dc3b316 --- /dev/null +++ b/firewood/firewood/src/lib.rs @@ -0,0 +1,174 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! # Firewood: Compaction-Less Database Optimized for Efficiently Storing Recent Merkleized Blockchain State +//! +//! Firewood is an embedded key-value store, optimized to store recent Merkleized blockchain +//! state with minimal overhead. Firewood is implemented from the ground up to directly +//! store trie nodes on-disk. Unlike most of state management approaches in the field, +//! it is not built on top of a generic KV store such as LevelDB/RocksDB. Firewood, like a +//! B+-tree based database, directly uses the trie structure as the index on-disk. Thus, +//! there is no additional "emulation" of the logical trie to flatten out the data structure +//! to feed into the underlying database that is unaware of the data being stored. The convenient +//! byproduct of this approach is that iteration is still fast (for serving state sync queries) +//! but compaction is not required to maintain the index. Firewood was first conceived to provide +//! a very fast storage layer for the EVM but could be used on any blockchain that +//! requires authenticated state. +//! +//! Firewood only attempts to support queries from recent revisions and will actively clean up +//! unused older revisions when state diffs are committed. The number of revisions is +//! configured when the database is opened. +//! +//! Firewood provides OS-level crash recovery, but not machine-level crash recovery. That is, +//! if the firewood process crashes, the OS will flush the cache leave the system in a valid state. +//! No protection is (currently) offered to handle machine failures. +//! +//! # Design Philosophy & Overview +//! +//! With some on-going academic research efforts and increasing demand of faster local storage +//! solutions for the chain state, we realized there are mainly two different regimes of designs. +//! +//! - "Archival" Storage: this style of design emphasizes on the ability to hold all historical +//! data and retrieve a revision of any wold state at a reasonable performance. To economically +//! store all historical certified data, usually copy-on-write merkle tries are used to just +//! capture the changes made by a committed block. The entire storage consists of a forest of these +//! "delta" tries. The total size of the storage will keep growing over the chain length and an ideal, +//! well-executed plan for this is to make sure the performance degradation is reasonable or +//! well-contained with respect to the ever-increasing size of the index. This design is useful +//! for nodes which serve as the backend for some indexing service (e.g., chain explorer) or as a +//! query portal to some user agent (e.g., wallet apps). Blockchains with delayed finality may also +//! need this because the "canonical" branch of the chain could switch (but not necessarily a +//! practical concern nowadays) to a different fork at times. +//! +//! - "Validation" Storage: this regime optimizes for the storage footprint and the performance of +//! operations upon the latest/recent states. With the assumption that the chain's total state +//! size is relatively stable over ever-coming blocks, one can just make the latest state +//! persisted and available to the blockchain system as that's what matters for most of the time. +//! While one can still keep some volatile state versions in memory for mutation and VM +//! execution, the final commit to some state works on a singleton so the indexed merkle tries +//! may be typically updated in place. It is also possible (e.g., Firewood) to allow some +//! infrequent access to historical versions with higher cost, and/or allow fast access to +//! versions of the store within certain limited recency. This style of storage is useful for +//! the blockchain systems where only (or mostly) the latest state is required and data footprint +//! should remain constant or grow slowly if possible for sustainability. Validators who +//! directly participate in the consensus and vote for the blocks, for example, can largely +//! benefit from such a design. +//! +//! In Firewood, we take a closer look at the second regime and have come up with a simple but +//! robust architecture that fulfills the need for such blockchain storage. However, firewood +//! can also efficiently handle the first regime. +//! +//! ## Storage Model +//! +//! Firewood is built by layers of abstractions that totally decouple the layout/representation +//! of the data on disk from the actual logical data structure it retains: +//! +//! - The storage module has a [`firewood_storage::NodeStore`] which has a generic parameter identifying +//! the state of the nodestore, and a storage type. +//! +//! There are three states for a nodestore: +//! - [`firewood_storage::Committed`] for revisions that are committed +//! - [`firewood_storage::ImmutableProposal`] for revisions that are proposals against committed versions +//! - [`firewood_storage::MutableProposal`] for revisions where nodes are still being added. +//! +//! For more information on these node states, see their associated documentation. +//! +//! The storage type is either a file or memory. Memory storage is used for creating temporary +//! merkle tries for proofs as well as testing. Nodes are identified by their offset within the +//! storage medium (a memory array or a disk file). +//! +//! ## Node caching +//! +//! Once committed, nodes never change until they expire for re-use. This means that a node cache +//! can reduce the amount of serialization and deserialization of nodes. The size of the cache, in +//! nodes, is specified when the database is opened. +//! +//! In short, a Read-Modify-Write (RMW) style normal operation flow is as follows in Firewood: +//! +//! - Create a [`firewood_storage::MutableProposal`] [`firewood_storage::NodeStore`] from the most recent [`firewood_storage::Committed`] one. +//! - Traverse the trie, starting at the root. Make a new root node by duplicating the existing +//! root from the committed one and save that in memory. As you continue traversing, make copies +//! of each node accessed if they are not already in memory. +//! +//! - Make changes to the trie, in memory. Each node you've accessed is currently in memory and is +//! owned by the [`firewood_storage::MutableProposal`]. Adding a node simply means adding a reference to it. +//! +//! - If you delete a node, mark it as deleted in the proposal and remove the child reference to it. +//! +//! - After making all mutations, convert the [`firewood_storage::MutableProposal`] to an [`firewood_storage::ImmutableProposal`]. This +//! involves walking the in-memory trie and converting them to a [`firewood_storage::SharedNode`]. +//! +//! - Since the root is guaranteed to be new, the new root will reference all of the new revision. +//! +//! A commit involves allocating space for the nmodes and writing them as well as the freelist to disk. +//! +// Instead of using a `compile_error!`, cause clippy to hard fail if the target is not 64-bit. This +// is a workaround for the fact that the `clippy::cast_possible_truncation` lint does not delineate +// between 64-bit and non-64-bit targets with respect to `usize -> u64` casts and vice versa which +// leads to a lot of unecessary `TryInto` casts. This also allows 32-bit builds to compile as long +// as `clippy` is not part of the build process albeit with the risk of truncation errors. +#![cfg_attr( + not(target_pointer_width = "64"), + forbid( + clippy::cast_possible_truncation, + reason = "non-64 bit target likely to cause issues during u64 to usize conversions" + ) +)] + +#[cfg(all(feature = "ethhash", feature = "branch_factor_256"))] +compile_error!( + "feature \"ethhash\" and feature \"branch_factor_256\" cannot be enabled at the same time" +); + +/// Database module for Firewood. +pub mod db; + +/// Iterator module, for both node and key-value streams +pub mod iter; + +/// Database manager module +pub mod manager; + +/// Merkle module, containing merkle operations +pub mod merkle; + +/// Proof module +pub mod proof; + +/// Change, Range, and Key proofs for the Merkle Trie +// TODO: push `proof` and `range_proof` modules into this module +pub mod proofs; + +// Re-export the proc macro from firewood-macros +pub use firewood_macros::metrics; + +/// Range proof module +pub mod range_proof; + +/// Root store module +pub mod root_store; + +/// Version 2 API +pub mod v2; + +/// Expose the storage logger +pub use firewood_storage::logger; + +#[cfg(all(test, feature = "logger"))] +#[ctor::ctor] +/// `ctor` will ensure this function is invoked before any tests are run so we +/// can initialize the logger consistently across all tests without having to +/// manually call it in each test. +/// +/// This is technically black magic as it runs before `main` is invoked, which +/// violates some of the Rust guarantees. But, it is convenient to ensure the +/// logger is initialized for all tests. +/// +/// In the event of unexpected behavior in testing, disable this first before +/// looking elsewhere. +fn init_logger() { + env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")) + .is_test(true) + .try_init() + .ok(); +} diff --git a/firewood/firewood/src/manager.rs b/firewood/firewood/src/manager.rs new file mode 100644 index 000000000000..8b83e85c4c87 --- /dev/null +++ b/firewood/firewood/src/manager.rs @@ -0,0 +1,449 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::cast_precision_loss, + reason = "Found 2 occurrences after enabling the lint." +)] +#![expect( + clippy::default_trait_access, + reason = "Found 3 occurrences after enabling the lint." +)] + +use parking_lot::{Mutex, RwLock}; +use std::collections::{HashMap, VecDeque}; +use std::num::NonZero; +use std::path::PathBuf; +use std::sync::{Arc, OnceLock, Weak}; + +use firewood_storage::logger::{trace, warn}; +use metrics::gauge; +use rayon::{ThreadPool, ThreadPoolBuilder}; +use typed_builder::TypedBuilder; +use weak_table::WeakValueHashMap; + +use crate::merkle::Merkle; +use crate::root_store::RootStore; +use crate::v2::api::{ArcDynDbView, HashKey, OptionalHashKeyExt}; + +pub use firewood_storage::CacheReadStrategy; +use firewood_storage::{ + BranchNode, Committed, FileBacked, FileIoError, HashedNodeReader, ImmutableProposal, + IntoHashType, NodeStore, TrieHash, +}; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TypedBuilder)] +/// Revision manager configuratoin +pub struct RevisionManagerConfig { + /// The number of historical revisions to keep in memory. + #[builder(default = 128)] + max_revisions: usize, + + /// The size of the node cache + #[builder(default_code = "NonZero::new(1500000).expect(\"non-zero\")")] + node_cache_size: NonZero, + + #[builder(default_code = "NonZero::new(40000).expect(\"non-zero\")")] + free_list_cache_size: NonZero, + + #[builder(default = CacheReadStrategy::WritesOnly)] + cache_read_strategy: CacheReadStrategy, +} + +#[derive(Clone, Debug, TypedBuilder)] +#[non_exhaustive] +/// Configuration manager that contains both truncate and revision manager config +pub struct ConfigManager { + /// Whether to create the DB if it doesn't exist. + #[builder(default = true)] + pub create: bool, + /// Whether to truncate the DB when opening it. If set, the DB will be reset and all its + /// existing contents will be lost. + #[builder(default = false)] + pub truncate: bool, + /// `RootStore` directory path + #[builder(default = None)] + pub root_store_dir: Option, + /// Revision manager configuration. + #[builder(default = RevisionManagerConfig::builder().build())] + pub manager: RevisionManagerConfig, +} + +type CommittedRevision = Arc>; +type ProposedRevision = Arc, FileBacked>>; + +#[derive(Debug)] +pub(crate) struct RevisionManager { + /// Maximum number of revisions to keep on disk + max_revisions: usize, + + /// The list of revisions that are on disk; these point to the different roots + /// stored in the filebacked storage. + historical: RwLock>, + proposals: Mutex>, + // committing_proposals: VecDeque>, + by_hash: RwLock>, + by_rootstore: Mutex>>>, + threadpool: OnceLock, + root_store: Option, +} + +#[derive(Debug, thiserror::Error)] +pub(crate) enum RevisionManagerError { + #[error("Revision for {provided:?} not found")] + RevisionNotFound { provided: HashKey }, + #[error("Revision for {provided:?} has no address")] + RevisionWithoutAddress { provided: HashKey }, + #[error( + "The proposal cannot be committed since it is not a direct child of the most recent commit. Proposal parent: {provided:?}, current root: {expected:?}" + )] + NotLatest { + provided: Option, + expected: Option, + }, + #[error("An IO error occurred during the commit: {0}")] + FileIoError(#[from] FileIoError), + #[error("A RootStore error occurred: {0}")] + RootStoreError(#[source] Box), +} + +impl RevisionManager { + pub fn new(filename: PathBuf, config: ConfigManager) -> Result { + let fb = FileBacked::new( + filename, + config.manager.node_cache_size, + config.manager.free_list_cache_size, + config.truncate, + config.create, + config.manager.cache_read_strategy, + )?; + + // Acquire an advisory lock on the database file to prevent multiple processes + // from opening the same database simultaneously + fb.lock()?; + + let root_store: Option = match config.root_store_dir { + Some(path) => Some(RootStore::new(path).map_err(RevisionManagerError::RootStoreError)?), + None => None, + }; + + let storage = Arc::new(fb); + let nodestore = Arc::new(NodeStore::open(storage.clone())?); + let manager = Self { + max_revisions: config.manager.max_revisions, + historical: RwLock::new(VecDeque::from([nodestore.clone()])), + by_hash: RwLock::new(Default::default()), + proposals: Mutex::new(Default::default()), + // committing_proposals: Default::default(), + by_rootstore: Mutex::new(WeakValueHashMap::new()), + threadpool: OnceLock::new(), + root_store, + }; + + if let Some(hash) = nodestore.root_hash().or_default_root_hash() { + manager.by_hash.write().insert(hash, nodestore.clone()); + } + + if config.truncate { + nodestore.flush_header_with_padding()?; + } + + // On startup, we always write the latest revision to RootStore + if let Some(root_hash) = manager.current_revision().root_hash() { + let root_address = manager.current_revision().root_address().ok_or( + RevisionManagerError::RevisionWithoutAddress { + provided: root_hash.clone(), + }, + )?; + + if let Some(store) = &manager.root_store { + store + .add_root(&root_hash, &root_address) + .map_err(RevisionManagerError::RootStoreError)?; + } + } + + Ok(manager) + } + + /// Commit a proposal + /// To commit a proposal involves a few steps: + /// 1. Commit check. + /// The proposal's parent must be the last committed revision, otherwise the commit fails. + /// It only contains the address of the nodes that are deleted, which should be very small. + /// 2. Revision reaping. + /// If more than the maximum number of revisions are kept in memory, the + /// oldest revision is removed from memory. If `RootStore` does not exist, + /// the oldest revision's nodes are added to the free list for space reuse. + /// Otherwise, the oldest revision's nodes are preserved on disk, which + /// is useful for historical queries. + /// 3. Persist to disk. This includes flushing everything to disk. + /// 4. Persist the revision to `RootStore`. + /// 5. Set last committed revision. + /// Set last committed revision in memory. + /// 6. Proposal Cleanup. + /// Any other proposals that have this proposal as a parent should be reparented to the committed version. + #[fastrace::trace(short_name = true)] + #[crate::metrics("firewood.proposal.commit", "proposal commit to storage")] + pub fn commit(&self, proposal: ProposedRevision) -> Result<(), RevisionManagerError> { + // 1. Commit check + let current_revision = self.current_revision(); + if !proposal.parent_hash_is(current_revision.root_hash()) { + return Err(RevisionManagerError::NotLatest { + provided: proposal.root_hash(), + expected: current_revision.root_hash(), + }); + } + + let mut committed = proposal.as_committed(¤t_revision); + + // 2. Revision reaping + // When we exceed max_revisions, remove the oldest revision from memory. + // If `RootStore` does not exist, add the oldest revision's nodes to the free list. + // If you crash after freeing some of these, then the free list will point to nodes that are not actually free. + // TODO: Handle the case where we get something off the free list that is not free + while self.historical.read().len() >= self.max_revisions { + let oldest = self + .historical + .write() + .pop_front() + .expect("must be present"); + let oldest_hash = oldest.root_hash().or_default_root_hash(); + if let Some(ref hash) = oldest_hash { + self.by_hash.write().remove(hash); + } + + // We reap the revision's nodes only if `RootStore` does not exist. + if self.root_store.is_none() { + // This `try_unwrap` is safe because nobody else will call `try_unwrap` on this Arc + // in a different thread, so we don't have to worry about the race condition where + // the Arc we get back is not usable as indicated in the docs for `try_unwrap`. + // This guarantee is there because we have a `&mut self` reference to the manager, so + // the compiler guarantees we are the only one using this manager. + match Arc::try_unwrap(oldest) { + Ok(oldest) => oldest.reap_deleted(&mut committed)?, + Err(original) => { + warn!("Oldest revision could not be reaped; still referenced"); + self.historical.write().push_front(original); + break; + } + } + } + gauge!("firewood.active_revisions").set(self.historical.read().len() as f64); + gauge!("firewood.max_revisions").set(self.max_revisions as f64); + } + + // 3. Persist to disk. + // TODO: We can probably do this in another thread, but it requires that + // we move the header out of NodeStore, which is in a future PR. + committed.persist()?; + + // 4. Persist revision to root store + if let Some(store) = &self.root_store + && let (Some(hash), Some(address)) = (committed.root_hash(), committed.root_address()) + { + store + .add_root(&hash, &address) + .map_err(RevisionManagerError::RootStoreError)?; + } + + // 5. Set last committed revision + let committed: CommittedRevision = committed.into(); + self.historical.write().push_back(committed.clone()); + if let Some(hash) = committed.root_hash().or_default_root_hash() { + self.by_hash.write().insert(hash, committed.clone()); + } + + // 6. Proposal Cleanup + // Free proposal that is being committed as well as any proposals no longer + // referenced by anyone else. + self.proposals + .lock() + .retain(|p| !Arc::ptr_eq(&proposal, p) && Arc::strong_count(p) > 1); + + // then reparent any proposals that have this proposal as a parent + for p in &*self.proposals.lock() { + proposal.commit_reparent(p); + } + + if crate::logger::trace_enabled() { + let merkle = Merkle::from(committed); + if let Ok(s) = merkle.dump_to_string() { + trace!("{s}"); + } + } + + Ok(()) + } + + /// View the database at a specific hash. + /// To view the database at a specific hash involves a few steps: + /// 1. Try to find it in committed revisions. + /// 2. Try to find it in proposals. + pub fn view(&self, root_hash: HashKey) -> Result { + // 1. Try to find it in committed revisions. + if let Ok(committed) = self.revision(root_hash.clone()) { + return Ok(committed); + } + + // 2. Try to find it in proposals. + let proposal = self + .proposals + .lock() + .iter() + .find(|p| p.root_hash().as_ref() == Some(&root_hash)) + .cloned() + .ok_or(RevisionManagerError::RevisionNotFound { + provided: root_hash, + })?; + + Ok(proposal) + } + + pub fn add_proposal(&self, proposal: ProposedRevision) { + self.proposals.lock().push(proposal); + } + + /// TODO: should we support fetching all hashes from `RootStore`? + pub fn all_hashes(&self) -> Vec { + self.historical + .read() + .iter() + .filter_map(|r| r.root_hash().or_default_root_hash()) + .chain( + self.proposals + .lock() + .iter() + .filter_map(|p| p.root_hash().or_default_root_hash()), + ) + .collect() + } + + /// Retrieve a committed revision by its root hash. + /// To retrieve a revision involves a few steps: + /// 1. Check the in-memory revision manager. + /// 2. Check the in-memory `RootStore` cache. + /// 3. Check the persistent `RootStore`. + pub fn revision(&self, root_hash: HashKey) -> Result { + // 1. Check the in-memory revision manager. + if let Some(revision) = self.by_hash.read().get(&root_hash).cloned() { + return Ok(revision); + } + + let mut cache_guard = self.by_rootstore.lock(); + + // 2. Check the in-memory `RootStore` cache. + if let Some(nodestore) = cache_guard.get(&root_hash) { + return Ok(nodestore); + } + + // 3. Check the persistent `RootStore`. + // If the revision exists, get its root address and construct a NodeStore for it. + let root_address = match &self.root_store { + Some(store) => store + .get(&root_hash) + .map_err(RevisionManagerError::RootStoreError)? + .ok_or(RevisionManagerError::RevisionNotFound { + provided: root_hash.clone(), + })?, + None => { + return Err(RevisionManagerError::RevisionNotFound { + provided: root_hash.clone(), + }); + } + }; + + let nodestore = Arc::new(NodeStore::with_root( + root_hash.clone().into_hash_type(), + root_address, + self.current_revision(), + )); + + // Cache the nodestore (stored as a weak reference). + cache_guard.insert(root_hash, nodestore.clone()); + + Ok(nodestore) + } + + pub fn root_hash(&self) -> Result, RevisionManagerError> { + Ok(self.current_revision().root_hash()) + } + + pub fn current_revision(&self) -> CommittedRevision { + self.historical + .read() + .back() + .expect("there is always one revision") + .clone() + } + + /// Gets or creates a threadpool associated with the revision manager. + /// + /// # Panics + /// + /// Panics if the it cannot create a thread pool. + pub fn threadpool(&self) -> &ThreadPool { + // Note that OnceLock currently doesn't support get_or_try_init (it is available in a + // nightly release). The get_or_init should be replaced with get_or_try_init once it + // is available to allow the error to be passed back to the caller. + self.threadpool.get_or_init(|| { + ThreadPoolBuilder::new() + .num_threads(BranchNode::MAX_CHILDREN) + .build() + .expect("Error in creating threadpool") + }) + } +} + +#[cfg(test)] +#[allow(clippy::unwrap_used)] +mod tests { + use super::*; + use tempfile::NamedTempFile; + + #[test] + fn test_file_advisory_lock() { + // Create a temporary file for testing + let temp_file = NamedTempFile::new().unwrap(); + let db_path = temp_file.path().to_path_buf(); + + let config = ConfigManager::builder() + .create(true) + .truncate(false) + .build(); + + // First database instance should open successfully + let first_manager = RevisionManager::new(db_path.clone(), config.clone()); + assert!( + first_manager.is_ok(), + "First database should open successfully" + ); + + // Second database instance should fail to open due to file locking + let second_manager = RevisionManager::new(db_path.clone(), config.clone()); + assert!( + second_manager.is_err(), + "Second database should fail to open" + ); + + // Verify the error message contains the expected information + let error = second_manager.unwrap_err(); + let error_string = error.to_string(); + + assert!( + error_string.contains("database may be opened by another instance"), + "Error is missing 'database may be opened by another instance', got: {error_string}" + ); + + // The file lock is held by the FileBacked instance. When we drop the first_manager, + // the Arc should be dropped, releasing the file lock. + drop(first_manager.unwrap()); + + // Now the second database should open successfully + let third_manager = RevisionManager::new(db_path, config); + assert!( + third_manager.is_ok(), + "Database should open after first instance is dropped" + ); + } +} diff --git a/firewood/firewood/src/merkle/merge.rs b/firewood/firewood/src/merkle/merge.rs new file mode 100644 index 000000000000..7de746266599 --- /dev/null +++ b/firewood/firewood/src/merkle/merge.rs @@ -0,0 +1,278 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use firewood_storage::{FileIoError, TrieReader}; + +use crate::{ + db::BatchOp, + iter::MerkleKeyValueIter, + merkle::Key, + v2::api::{BatchIter, KeyType, KeyValuePair}, +}; + +/// Serializes a sequence of key-value pairs merged with the base merkle trie +/// as a sequence of [`BatchOp`]s. +/// +/// The key-value range is considered total, meaning keys within the specified +/// bounds that are present within the base trie but not in the key-value iterator +/// will be yielded as [`BatchOp::Delete`] or [`BatchOp::DeleteRange`] operations. +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub(super) struct MergeKeyValueIter<'a, T, I, K> +where + T: TrieReader, + I: Iterator, + K: KeyType, +{ + trie: ReturnableIterator, K>>, + kvp: ReturnableIterator>, +} + +impl<'a, T, I, K> MergeKeyValueIter<'a, T, I, K> +where + T: TrieReader, + I: Iterator, + K: KeyType, +{ + pub fn new( + merkle: &'a crate::merkle::Merkle, + first_key: Option, + last_key: Option, + kvp_iter: impl IntoIterator, + ) -> Self { + let base_iter = match first_key { + Some(k) => merkle.key_value_iter_from_key(k), + None => merkle.key_value_iter(), + }; + + Self { + trie: ReturnableIterator::new(KeyRangeIter::new(base_iter, last_key)), + kvp: ReturnableIterator::new(KeyRangeIter::new(kvp_iter.into_iter(), None)), + } + } +} + +impl Iterator for MergeKeyValueIter<'_, T, I, K> +where + T: TrieReader, + I: Iterator, + K: KeyType, +{ + type Item = Result< + BatchOp::Key>, ::Value>, + FileIoError, + >; + + fn next(&mut self) -> Option { + loop { + break match (self.trie.next(), self.kvp.next()) { + // we've exhausted both iterators + (None, None) => None, + + (Some(Err(err)), kvp) => { + if let Some(kvp) = kvp { + self.kvp.set_next(kvp); + } + + Some(Err(err)) + } + (trie, Some(Err(err))) => { + if let Some(trie) = trie { + self.trie.set_next(trie); + } + + Some(Err(err.into())) + } + + // only the trie iterator has remaining items. + (Some(Ok((key, _))), None) => Some(Ok(BatchOp::Delete { + key: EitherKey::Left(key), + })), + + // only kvp iterator has remaining items. + (None, Some(Ok((key, value)))) => Some(Ok(BatchOp::Put { + key: EitherKey::Right(key), + value, + })), + + (Some(Ok((base_key, node_value))), Some(Ok((kvp_key, kvp_value)))) => { + match <[u8] as Ord>::cmp(&base_key, kvp_key.as_ref()) { + std::cmp::Ordering::Less => { + // retain the kvp iterator's current item. + self.kvp.set_next(Ok((kvp_key, kvp_value))); + + // trie key is less than next kvp key, so it must be deleted. + Some(Ok(BatchOp::Delete { + key: EitherKey::Left(base_key), + })) + } + std::cmp::Ordering::Equal => { + // retain neither iterator's current item. + + if *node_value == *kvp_value.as_ref() { + // skip since value is unchanged + continue; + } + + // values differ, so we need to insert the new value + Some(Ok(BatchOp::Put { + key: EitherKey::Right(kvp_key), + value: kvp_value, + })) + } + std::cmp::Ordering::Greater => { + // retain the trie iterator's current item. + self.trie.set_next(Ok((base_key, node_value))); + // trie key is greater than next kvp key, so we need to insert it. + Some(Ok(BatchOp::Put { + key: EitherKey::Right(kvp_key), + value: kvp_value, + })) + } + } + } + }; + } + } +} + +/// Similar to a peekable iterator. Instead of peeking at the next item, it allows +/// you to put it back to be returned on the next call to `next()`. +struct ReturnableIterator { + iter: I, + next: Option, +} + +impl ReturnableIterator { + const fn new(iter: I) -> Self { + Self { iter, next: None } + } + + const fn set_next(&mut self, head: I::Item) -> Option { + self.next.replace(head) + } +} + +impl Iterator for ReturnableIterator { + type Item = I::Item; + + fn next(&mut self) -> Option { + self.next.take().or_else(|| self.iter.next()) + } + + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + let head_count = usize::from(self.next.is_some()); + ( + lower.saturating_add(head_count), + upper.and_then(|u| u.checked_add(head_count)), + ) + } +} + +enum KeyRangeIter { + Unfiltered { iter: I }, + Filtered { iter: I, last_key: K }, + Exhausted, +} + +impl KeyRangeIter { + fn new(iter: I, last_key: Option) -> Self { + match last_key { + Some(k) => KeyRangeIter::Filtered { iter, last_key: k }, + None => KeyRangeIter::Unfiltered { iter }, + } + } +} + +impl, T: KeyValuePair, K: KeyType> Iterator for KeyRangeIter { + type Item = Result<(T::Key, T::Value), T::Error>; + + fn next(&mut self) -> Option { + match self { + KeyRangeIter::Unfiltered { iter } => iter.next().map(T::try_into_tuple), + KeyRangeIter::Filtered { iter, last_key } => match iter.next().map(T::try_into_tuple) { + Some(Ok((key, value))) if key.as_ref() <= last_key.as_ref() => { + Some(Ok((key, value))) + } + Some(Err(e)) => Some(Err(e)), + _ => { + *self = KeyRangeIter::Exhausted; + None + } + }, + KeyRangeIter::Exhausted => None, + } + } + + fn size_hint(&self) -> (usize, Option) { + match self { + KeyRangeIter::Unfiltered { iter } => iter.size_hint(), + KeyRangeIter::Filtered { iter, .. } => { + let (_, upper) = iter.size_hint(); + (0, upper) + } + KeyRangeIter::Exhausted => (0, Some(0)), + } + } +} + +#[derive(Debug)] +pub(super) enum EitherKey { + Left(L), + Right(R), +} + +impl EitherKey { + fn as_key(&self) -> &[u8] { + match self { + EitherKey::Left(key) => key.as_ref(), + EitherKey::Right(key) => key.as_ref(), + } + } +} + +impl AsRef<[u8]> for EitherKey { + fn as_ref(&self) -> &[u8] { + self.as_key() + } +} + +impl std::borrow::Borrow<[u8]> for EitherKey { + fn borrow(&self) -> &[u8] { + self.as_key() + } +} + +impl std::ops::Deref for EitherKey { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + self.as_key() + } +} + +impl PartialEq for EitherKey { + fn eq(&self, other: &V) -> bool { + self.as_key() == other.as_ref() + } +} + +impl Eq for EitherKey {} + +impl PartialOrd for EitherKey { + fn partial_cmp(&self, other: &V) -> Option { + Some(self.as_key().cmp(other.as_ref())) + } +} + +impl Ord for EitherKey { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_key().cmp(other.as_key()) + } +} + +impl std::hash::Hash for EitherKey { + fn hash(&self, state: &mut H) { + self.as_key().hash(state); + } +} diff --git a/firewood/firewood/src/merkle/mod.rs b/firewood/firewood/src/merkle/mod.rs new file mode 100644 index 000000000000..41c8aaeed958 --- /dev/null +++ b/firewood/firewood/src/merkle/mod.rs @@ -0,0 +1,1117 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#[cfg(test)] +pub(crate) mod tests; + +mod merge; +/// Parallel merkle +pub mod parallel; + +use crate::iter::{MerkleKeyValueIter, PathIterator, TryExtend}; +use crate::proof::{Proof, ProofCollection, ProofError, ProofNode}; +use crate::range_proof::RangeProof; +use crate::v2::api::{ + self, BatchIter, FrozenProof, FrozenRangeProof, KeyType, KeyValuePair, ValueType, +}; +use firewood_storage::{ + BranchNode, Child, Children, FileIoError, HashType, HashedNodeReader, ImmutableProposal, + IntoHashType, LeafNode, MaybePersistedNode, MutableProposal, NibblesIterator, Node, NodeStore, + Parentable, Path, PathComponent, ReadableStorage, SharedNode, TrieHash, TrieReader, + ValueDigest, +}; +use metrics::counter; +use std::collections::HashSet; +use std::fmt::Debug; +use std::io::Error; +use std::iter::once; +use std::num::NonZeroUsize; +use std::sync::Arc; + +/// Keys are boxed u8 slices +pub type Key = Box<[u8]>; + +/// Values are boxed u8 slices +pub type Value = Box<[u8]>; + +macro_rules! write_attributes { + ($writer:ident, $node:expr, $value:expr) => { + if !$node.partial_path.0.is_empty() { + write!($writer, " pp={:x}", $node.partial_path) + .map_err(|e| FileIoError::from_generic_no_file(e, "write attributes"))?; + } + if !$value.is_empty() { + match std::str::from_utf8($value) { + Ok(string) if string.chars().all(char::is_alphanumeric) => { + write!($writer, " val={:.6}", string) + .map_err(|e| FileIoError::from_generic_no_file(e, "write attributes"))?; + if string.len() > 6 { + $writer.write_all(b"...").map_err(|e| { + FileIoError::from_generic_no_file(e, "write attributes") + })?; + } + } + _ => { + let hex = hex::encode($value); + write!($writer, " val={:.6}", hex) + .map_err(|e| FileIoError::from_generic_no_file(e, "write attributes"))?; + if hex.len() > 6 { + $writer.write_all(b"...").map_err(|e| { + FileIoError::from_generic_no_file(e, "write attributes") + })?; + } + } + } + } + }; +} + +/// Returns the value mapped to by `key` in the subtrie rooted at `node`. +fn get_helper( + nodestore: &T, + node: &Node, + key: &[u8], +) -> Result, FileIoError> { + // 4 possibilities for the position of the `key` relative to `node`: + // 1. The node is at `key` + // 2. The key is above the node (i.e. its ancestor) + // 3. The key is below the node (i.e. its descendant) + // 4. Neither is an ancestor of the other + let path_overlap = PrefixOverlap::from(key, node.partial_path()); + let unique_key = path_overlap.unique_a; + let unique_node = path_overlap.unique_b; + + match ( + unique_key.split_first().map(|(index, path)| (*index, path)), + unique_node.split_first(), + ) { + (_, Some(_)) => { + // Case (2) or (4) + Ok(None) + } + (None, None) => Ok(Some(node.clone().into())), // 1. The node is at `key` + (Some((child_index, remaining_key)), None) => { + let child_index = PathComponent::try_new(child_index).expect("index is in bounds"); + // 3. The key is below the node (i.e. its descendant) + match node { + Node::Leaf(_) => Ok(None), + Node::Branch(node) => match node.children[child_index].as_ref() { + None => Ok(None), + Some(Child::Node(child)) => get_helper(nodestore, child, remaining_key), + Some(Child::AddressWithHash(addr, _)) => { + let child = nodestore.read_node(*addr)?; + get_helper(nodestore, &child, remaining_key) + } + Some(Child::MaybePersisted(maybe_persisted, _)) => { + let child = maybe_persisted.as_shared_node(nodestore)?; + get_helper(nodestore, &child, remaining_key) + } + }, + } + } + } +} + +#[derive(Debug)] +/// Merkle operations against a nodestore +pub struct Merkle { + nodestore: T, +} + +impl Merkle { + pub(crate) fn into_inner(self) -> T { + self.nodestore + } +} + +impl From for Merkle { + fn from(nodestore: T) -> Self { + Merkle { nodestore } + } +} + +impl Merkle { + pub(crate) fn root(&self) -> Option { + self.nodestore.root_node() + } + + pub(crate) const fn nodestore(&self) -> &T { + &self.nodestore + } + + /// Returns a proof that the given key has a certain value, + /// or that the key isn't in the trie. + /// + /// ## Errors + /// + /// Returns an error if the trie is empty or an error occurs while reading from storage. + pub fn prove(&self, key: &[u8]) -> Result { + let Some(root) = self.root() else { + return Err(ProofError::Empty); + }; + + // Get the path to the key + let path_iter = self.path_iter(key)?; + let mut proof = Vec::new(); + for node in path_iter { + let node = node?; + proof.push(ProofNode::from(node)); + } + + if proof.is_empty() { + // No nodes, even the root, are before `key`. + // The root alone proves the non-existence of `key`. + // TODO reduce duplicate code with ProofNode::from + let child_hashes = if let Some(branch) = root.as_branch() { + branch.children_hashes() + } else { + Children::new() + }; + + proof.push(ProofNode { + // key is expected to be in nibbles + key: root.partial_path().as_components().into(), + // partial len is the number of nibbles in the path leading to this node, + // which is always zero for the root node. + partial_len: 0, + value_digest: root + .value() + .map(|value| ValueDigest::Value(value.to_vec().into_boxed_slice())), + child_hashes, + }); + } + + Ok(Proof::new(proof.into_boxed_slice())) + } + + /// Verify that a range proof is valid for the specified key range and root hash. + /// + /// This method validates a range proof by constructing a partial trie from the proof data + /// and verifying that it produces the expected root hash. The proof may contain fewer + /// key-value pairs than requested if the peer chose to limit the response size. + /// + /// # Parameters + /// + /// * `first_key` - The requested start of the range (inclusive). + /// - If `Some(key)`, verifies the proof covers keys >= this key + /// - If `None`, verifies the proof starts from the beginning of the trie + /// + /// * `last_key` - The requested end of the range (inclusive). + /// - If `Some(key)`, represents the upper bound that was requested + /// - If `None`, indicates no upper bound was specified + /// - Note: The proof may contain fewer keys than requested if the peer limited the response + /// + /// * `root_hash` - The expected root hash of the trie. The constructed partial trie + /// from the proof must produce this exact hash for the proof to be valid. + /// + /// * `proof` - The range proof to verify, containing: + /// - Start proof: Merkle proof for the lower boundary + /// - End proof: Merkle proof for the upper boundary + /// - Key-value pairs: The actual entries within the range + /// + /// # Returns + /// + /// Returns the constructed [`Merkle, _>`] that was built and + /// verified from the proof data, if the proof is valid. + /// + /// # Verification Process + /// + /// The verification follows these steps: + /// 1. **Structural validation**: Verify the proof structure is well-formed + /// - Check that start/end proofs are consistent with the key range + /// - Ensure key-value pairs are in the correct order + /// - Validate that boundary proofs correctly bound the key-value pairs + /// + /// 2. **Proposal construction**: Build a proposal trie containing the proof data + /// - Insert all key-value pairs from the proof + /// - Incorporate nodes from the start and end proofs + /// - Handle edge cases for empty ranges or partial proofs + /// + /// 3. **Hash verification**: Compute the root hash of the constructed proposal + /// - The computed hash must match the provided `root_hash` exactly + /// - Any mismatch indicates an invalid or tampered proof + /// + /// # Errors + /// + /// * [`api::Error::ProofError`] - The proof structure is malformed or inconsistent + /// * [`api::Error::InvalidRange`] - The proof boundaries don't match the requested range + /// * [`api::Error::ParentNotLatest`] - The computed root hash doesn't match the expected hash + /// * [`api::Error`] - Other errors during proposal construction or verification + /// + /// # Examples + /// + /// ```ignore + /// // Verify a range proof received from a peer + /// let verified_proposal = merkle.verify_range_proof( + /// Some(b"alice"), + /// Some(b"charlie"), + /// &expected_root_hash, + /// &range_proof + /// )?; + /// ``` + /// + /// # Implementation Notes + /// + /// - Structural validation is performed first to avoid expensive proposal construction + /// for obviously invalid proofs + /// - The method is designed to handle partial proofs where the peer provides less + /// data than requested, which is common for large ranges + /// - Future optimization: Consider caching partial verification results for + /// incremental range proof verification + pub fn verify_range_proof( + &self, + _first_key: Option, + _last_key: Option, + _root_hash: &TrieHash, + _proof: &RangeProof, + ) -> Result<(), api::Error> { + todo!() + } + + /// Merges a sequence of key-value pairs with the base merkle trie, yielding + /// a sequence of [`BatchOp`]s that describe the changes. + /// + /// The key-value range is considered total, meaning keys within the inclusive + /// bounds that are present within the base trie but not in the key-value iterator + /// will be yielded as [`BatchOp::Delete`] or [`BatchOp::DeleteRange`] operations. + /// + /// # Invariant + /// + /// The key-value pairs provided by the `key_values` iterator must be sorted in + /// ascending order, not contain duplicates, and must lie within the specified + /// `first_key` and `last_key` bounds (if provided). Behavior is unspecified if + /// this invariant is violated and no verification is performed. + /// + /// # Errors + /// + /// Returns an error if there is an issue reading from the underlying trie storage. + /// + /// [`BatchOp`]: crate::db::BatchOp + /// [`BatchOp::Delete`]: crate::db::BatchOp::Delete + /// [`BatchOp::DeleteRange`]: crate::db::BatchOp::DeleteRange + pub fn merge_key_value_range( + &self, + first_key: Option, + last_key: Option, + key_values: impl IntoIterator>, + ) -> impl BatchIter { + merge::MergeKeyValueIter::new(self, first_key, last_key, key_values) + } + + pub(crate) fn path_iter<'a>( + &self, + key: &'a [u8], + ) -> Result, FileIoError> { + PathIterator::new(&self.nodestore, key) + } + + pub(super) fn key_value_iter(&self) -> MerkleKeyValueIter<'_, T> { + MerkleKeyValueIter::from(&self.nodestore) + } + + pub(super) fn key_value_iter_from_key>( + &self, + key: K, + ) -> MerkleKeyValueIter<'_, T> { + // TODO danlaine: change key to &[u8] + MerkleKeyValueIter::from_key(&self.nodestore, key.as_ref()) + } + + /// Generate a cryptographic proof for a range of key-value pairs in the Merkle trie. + /// + /// This method creates a range proof that can be used to verify the existence (or absence) + /// of a contiguous set of keys within the trie. The proof includes boundary proofs and + /// the actual key-value pairs within the specified range. + /// + /// # Parameters + /// + /// * `start_key` - The optional lower bound of the range (inclusive). + /// - If `Some(key)`, the proof will include all keys >= this key + /// - If `None`, the proof starts from the beginning of the trie + /// + /// * `end_key` - The optional upper bound of the range (inclusive). + /// - If `Some(key)`, the proof will include all keys <= this key + /// - If `None`, the proof extends to the end of the trie + /// + /// * `limit` - Optional maximum number of key-value pairs to include in the proof. + /// - If `Some(n)`, at most n key-value pairs will be included + /// - If `None`, all key-value pairs in the range will be included + /// - Useful for paginating through large ranges + /// - **NOTE**: avalanchego's limit is based on the entire packet size and not the + /// number of key-value pairs. Currently, we only limit by the number of pairs. + /// + /// # Returns + /// + /// A `FrozenRangeProof` containing: + /// - Start proof: Merkle proof for the first key in the range + /// - End proof: Merkle proof for the last key in the range + /// - Key-value pairs: All entries within the specified bounds (up to the limit) + /// + /// # Errors + /// + /// * `api::Error::InvalidRange` - If `start_key` > `end_key` when both are provided. + /// This ensures the range bounds are logically consistent. + /// + /// * `api::Error::RangeProofOnEmptyTrie` - If the trie is empty and the caller + /// requests a proof for the entire trie (both `start_key` and `end_key` are `None`). + /// This prevents generating meaningless proofs for non-existent data. + /// + /// * `api::Error` - Various other errors can occur during proof generation, such as: + /// - I/O errors when reading nodes from storage + /// - Corrupted trie structure + /// - Invalid node references + /// + /// # Examples + /// + /// ```ignore + /// // Prove all keys between "alice" and "charlie" + /// let proof = merkle.range_proof( + /// Some(b"alice"), + /// Some(b"charlie"), + /// None + /// ).await?; + /// + /// // Prove the first 100 keys starting from "alice" + /// let proof = merkle.range_proof( + /// Some(b"alice"), + /// None, + /// Some(NonZeroUsize::new(100).unwrap()) + /// ).await?; + /// + /// // Prove that no keys exist in a range + /// let proof = merkle.range_proof( + /// Some(b"aardvark"), + /// Some(b"aaron"), + /// None + /// ).await?; + /// ``` + pub(super) fn range_proof( + &self, + start_key: Option<&[u8]>, + end_key: Option<&[u8]>, + limit: Option, + ) -> Result { + if let (Some(k1), Some(k2)) = (&start_key, &end_key) + && k1 > k2 + { + return Err(api::Error::InvalidRange { + start_key: k1.to_vec().into(), + end_key: k2.to_vec().into(), + }); + } + + let mut iter = match start_key { + // TODO: fix the call-site to force the caller to do the allocation + Some(key) => self.key_value_iter_from_key(key.to_vec().into_boxed_slice()), + None => self.key_value_iter(), + }; + + // fetch the first key from the stream + let first_result = iter.next(); + + // transpose the Option> to Result, E> + // If this is an error, the ? operator will return it + let Some((first_key, first_value)) = first_result.transpose()? else { + // The trie is empty. + if start_key.is_none() && end_key.is_none() { + // The caller requested a range proof over an empty trie. + return Err(api::Error::RangeProofOnEmptyTrie); + } + + let start_proof = start_key + .map(|start_key| self.prove(start_key)) + .transpose()? + .unwrap_or_default(); + + let end_proof = end_key + .map(|end_key| self.prove(end_key)) + .transpose()? + .unwrap_or_default(); + + return Ok(RangeProof::new(start_proof, end_proof, Box::new([]))); + }; + + let start_proof = self.prove(&first_key)?; + let limit = limit.map(|old_limit| old_limit.get().saturating_sub(1)); + + let mut key_values = vec![(first_key, first_value)]; + + // we stop iterating if either we hit the limit or the key returned was larger + // than the largest key requested + key_values.try_extend(iter.take(limit.unwrap_or(usize::MAX)).take_while(|kv| { + // no last key asked for, so keep going + let Some(last_key) = end_key else { + return true; + }; + + // return the error if there was one + let Ok(kv) = kv else { + return true; + }; + + // keep going if the key returned is less than the last key requested + *kv.0 <= *last_key + }))?; + + let end_proof = key_values + .last() + .map(|(largest_key, _)| self.prove(largest_key)) + .transpose()? + .unwrap_or_default(); + + Ok(RangeProof::new( + start_proof, + end_proof, + key_values.into_boxed_slice(), + )) + } + + pub(crate) fn get_value(&self, key: &[u8]) -> Result, FileIoError> { + let Some(node) = self.get_node(key)? else { + return Ok(None); + }; + Ok(node.value().map(|v| v.to_vec().into_boxed_slice())) + } + + pub(crate) fn get_node(&self, key: &[u8]) -> Result, FileIoError> { + let Some(root) = self.root() else { + return Ok(None); + }; + + let key = Path::from_nibbles_iterator(NibblesIterator::new(key)); + get_helper(&self.nodestore, &root, &key) + } +} + +impl Merkle { + /// Dump a node, recursively, to a dot file + pub(crate) fn dump_node( + &self, + node: &MaybePersistedNode, + hash: Option<&HashType>, + seen: &mut HashSet, + writer: &mut W, + ) -> Result<(), FileIoError> { + writeln!(writer, " {node}[label=\"{node}") + .map_err(Error::other) + .map_err(|e| FileIoError::new(e, None, 0, None))?; + if let Some(hash) = hash { + write!(writer, " H={hash:.6?}") + .map_err(Error::other) + .map_err(|e| FileIoError::new(e, None, 0, None))?; + } + + match &*node.as_shared_node(&self.nodestore)? { + Node::Branch(b) => { + write_attributes!(writer, b, &b.value.clone().unwrap_or(Box::from([]))); + writeln!(writer, "\"]") + .map_err(|e| FileIoError::from_generic_no_file(e, "write branch"))?; + for (childidx, child) in &b.children { + let (child, child_hash) = match child { + None => continue, + Some(node) => (node.as_maybe_persisted_node(), node.hash()), + }; + + let inserted = seen.insert(format!("{child}")); + if inserted { + writeln!(writer, " {node} -> {child}[label=\"{childidx:x}\"]") + .map_err(|e| FileIoError::from_generic_no_file(e, "write branch"))?; + self.dump_node(&child, child_hash, seen, writer)?; + } else { + // We have already seen this child, which shouldn't happen. + // Indicate this with a red edge. + writeln!( + writer, + " {node} -> {child}[label=\"{childidx:x} (dup)\" color=red]" + ) + .map_err(|e| FileIoError::from_generic_no_file(e, "write branch"))?; + } + } + } + Node::Leaf(l) => { + write_attributes!(writer, l, &l.value); + writeln!(writer, "\" shape=rect]") + .map_err(|e| FileIoError::from_generic_no_file(e, "write leaf"))?; + } + } + Ok(()) + } + + /// Dump the trie to a dot file. + /// + /// This function is primarily used in testing, but also has an API implementation + /// + /// Dot files can be rendered using `dot -Tpng -o output.png input.dot` + /// or online at + /// + /// # Errors + /// + /// Returns an error if writing to the output writer fails. + pub(crate) fn dump(&self, writer: &mut W) -> Result<(), Error> { + let root = self.nodestore.root_as_maybe_persisted_node(); + + writeln!(writer, "digraph Merkle {{\n rankdir=LR;").map_err(Error::other)?; + if let (Some(root), Some(root_hash)) = (root, self.nodestore.root_hash()) { + writeln!(writer, " root -> {root}") + .map_err(Error::other) + .map_err(|e| FileIoError::new(e, None, 0, None)) + .map_err(Error::other)?; + let mut seen = HashSet::new(); + self.dump_node(&root, Some(&root_hash.into_hash_type()), &mut seen, writer) + .map_err(Error::other)?; + } + writeln!(writer, "}}") + .map_err(Error::other) + .map_err(|e| FileIoError::new(e, None, 0, None)) + .map_err(Error::other)?; + + Ok(()) + } + /// Dump the trie to a string (for testing or logging). + /// + /// This is a convenience function for tests that need the dot output as a string. + /// + /// # Errors + /// + /// Returns an error if writing to the string fails. + pub(crate) fn dump_to_string(&self) -> Result { + let mut buffer = Vec::new(); + self.dump(&mut buffer)?; + String::from_utf8(buffer).map_err(Error::other) + } +} + +impl Merkle> { + /// Forks the current Merkle trie into a new mutable proposal. + /// + /// ## Errors + /// + /// Returns an error if the nodestore cannot be created. See [`NodeStore::new`]. + pub fn fork(&self) -> Result>, FileIoError> { + NodeStore::new(&self.nodestore).map(Into::into) + } +} + +impl TryFrom>> + for Merkle, S>> +{ + type Error = FileIoError; + fn try_from(m: Merkle>) -> Result { + Ok(Merkle { + nodestore: m.nodestore.try_into()?, + }) + } +} + +#[expect(clippy::missing_errors_doc)] +impl Merkle> { + /// Convert a merkle backed by an `MutableProposal` into an `ImmutableProposal` + /// + /// This function is only used in benchmarks and tests + /// + /// ## Panics + /// + /// Panics if the conversion fails. This should only be used in tests or benchmarks. + #[must_use] + pub fn hash(self) -> Merkle, S>> { + self.try_into().expect("failed to convert") + } + + fn read_for_update(&mut self, child: Child) -> Result { + match child { + Child::Node(node) => Ok(node), + Child::AddressWithHash(addr, _) => self.nodestore.read_for_update(addr.into()), + Child::MaybePersisted(node, _) => self.nodestore.read_for_update(node), + } + } + + /// Map `key` to `value` in the trie. + /// Each element of key is 2 nibbles. + pub fn insert(&mut self, key: &[u8], value: Value) -> Result<(), FileIoError> { + self.insert_from_iter(NibblesIterator::new(key), value) + } + + /// Map `key` to `value` in the trie when `key` is a `NibblesIterator` + pub fn insert_from_iter( + &mut self, + key: NibblesIterator<'_>, + value: Value, + ) -> Result<(), FileIoError> { + let key = Path::from_nibbles_iterator(key); + let root = self.nodestore.root_mut(); + let Some(root_node) = std::mem::take(root) else { + // The trie is empty. Create a new leaf node with `value` and set + // it as the root. + let root_node = Node::Leaf(LeafNode { + partial_path: key, + value, + }); + *root = root_node.into(); + return Ok(()); + }; + + let root_node = self.insert_helper(root_node, key.as_ref(), value)?; + *self.nodestore.root_mut() = root_node.into(); + Ok(()) + } + + /// Map `key` to `value` into the subtrie rooted at `node`. + /// Each element of `key` is 1 nibble. + /// Returns the new root of the subtrie. + #[expect(clippy::missing_panics_doc)] + pub fn insert_helper( + &mut self, + mut node: Node, + key: &[u8], + value: Value, + ) -> Result { + // 4 possibilities for the position of the `key` relative to `node`: + // 1. The node is at `key` + // 2. The key is above the node (i.e. its ancestor) + // 3. The key is below the node (i.e. its descendant) + // 4. Neither is an ancestor of the other + let path_overlap = PrefixOverlap::from(key, node.partial_path().as_ref()); + + let unique_key = path_overlap.unique_a; + let unique_node = path_overlap.unique_b; + + match ( + unique_key + .split_first() + .map(|(index, path)| (*index, path.into())), + unique_node + .split_first() + .map(|(index, path)| (*index, path.into())), + ) { + (None, None) => { + // 1. The node is at `key` + node.update_value(value); + counter!("firewood.insert", "merkle" => "update").increment(1); + Ok(node) + } + (None, Some((child_index, partial_path))) => { + let child_index = PathComponent::try_new(child_index).expect("valid component"); + // 2. The key is above the node (i.e. its ancestor) + // Make a new branch node and insert the current node as a child. + // ... ... + // | --> | + // node key + // | + // node + let mut branch = BranchNode { + partial_path: path_overlap.shared.into(), + value: Some(value), + children: Children::new(), + }; + + // Shorten the node's partial path since it has a new parent. + node.update_partial_path(partial_path); + branch.children[child_index] = Some(Child::Node(node)); + counter!("firewood.insert", "merkle"=>"above").increment(1); + + Ok(Node::Branch(Box::new(branch))) + } + (Some((child_index, partial_path)), None) => { + let child_index = PathComponent::try_new(child_index).expect("valid component"); + // 3. The key is below the node (i.e. its descendant) + // ... ... + // | | + // node --> node + // | | + // ... (key may be below) ... (key is below) + match node { + Node::Branch(ref mut branch) => { + let Some(child) = branch.children.take(child_index) else { + // There is no child at this index. + // Create a new leaf and put it here. + let new_leaf = Node::Leaf(LeafNode { + value, + partial_path, + }); + branch.children[child_index] = Some(Child::Node(new_leaf)); + counter!("firewood.insert", "merkle"=>"below").increment(1); + return Ok(node); + }; + let child = self.read_for_update(child)?; + let child = self.insert_helper(child, partial_path.as_ref(), value)?; + branch.children[child_index] = Some(Child::Node(child)); + Ok(node) + } + Node::Leaf(leaf) => { + // Turn this node into a branch node and put a new leaf as a child. + let mut branch = BranchNode { + partial_path: leaf.partial_path, + value: Some(leaf.value), + children: Children::new(), + }; + + let new_leaf = Node::Leaf(LeafNode { + value, + partial_path, + }); + + branch.children[child_index] = Some(Child::Node(new_leaf)); + + counter!("firewood.insert", "merkle"=>"split").increment(1); + Ok(Node::Branch(Box::new(branch))) + } + } + } + (Some((key_index, key_partial_path)), Some((node_index, node_partial_path))) => { + let key_index = PathComponent::try_new(key_index).expect("valid component"); + let node_index = PathComponent::try_new(node_index).expect("valid component"); + // 4. Neither is an ancestor of the other + // ... ... + // | | + // node --> branch + // | | \ + // node key + // Make a branch node that has both the current node and a new leaf node as children. + let mut branch = BranchNode { + partial_path: path_overlap.shared.into(), + value: None, + children: Children::new(), + }; + + node.update_partial_path(node_partial_path); + branch.children[node_index] = Some(Child::Node(node)); + + let new_leaf = Node::Leaf(LeafNode { + value, + partial_path: key_partial_path, + }); + branch.children[key_index] = Some(Child::Node(new_leaf)); + + counter!("firewood.insert", "merkle" => "split").increment(1); + Ok(Node::Branch(Box::new(branch))) + } + } + } + + /// Removes the value associated with the given `key`. + /// Returns the value that was removed, if any. + /// Otherwise returns `None`. + /// Each element of `key` is 2 nibbles. + pub fn remove(&mut self, key: &[u8]) -> Result, FileIoError> { + self.remove_from_iter(NibblesIterator::new(key)) + } + + /// Removes the value associated with the given `key` where `key` is a `NibblesIterator` + /// Returns the value that was removed, if any. + /// Otherwise returns `None`. + /// Each element of `key` is 2 nibbles. + pub fn remove_from_iter( + &mut self, + key: NibblesIterator<'_>, + ) -> Result, FileIoError> { + let key = Path::from_nibbles_iterator(key); + let root = self.nodestore.root_mut(); + let Some(root_node) = std::mem::take(root) else { + // The trie is empty. There is nothing to remove. + counter!("firewood.remove", "prefix" => "false", "result" => "nonexistent") + .increment(1); + return Ok(None); + }; + + let (root_node, removed_value) = self.remove_helper(root_node, &key)?; + *self.nodestore.root_mut() = root_node; + if removed_value.is_some() { + counter!("firewood.remove", "prefix" => "false", "result" => "success").increment(1); + } else { + counter!("firewood.remove", "prefix" => "false", "result" => "nonexistent") + .increment(1); + } + Ok(removed_value) + } + + /// Removes the value associated with the given `key` from the subtrie rooted at `node`. + /// Returns the new root of the subtrie and the value that was removed, if any. + /// Each element of `key` is 1 nibble. + fn remove_helper( + &mut self, + node: Node, + key: &[u8], + ) -> Result<(Option, Option), FileIoError> { + // 4 possibilities for the position of the `key` relative to `node`: + // 1. The node is at `key` + // 2. The key is above the node (i.e. its ancestor) + // 3. The key is below the node (i.e. its descendant) + // 4. Neither is an ancestor of the other + let path_overlap = PrefixOverlap::from(key, node.partial_path().as_ref()); + + let unique_key = path_overlap.unique_a; + let unique_node = path_overlap.unique_b; + + match ( + unique_key + .split_first() + .map(|(index, path)| (*index, Path::from(path))), + unique_node.split_first(), + ) { + (_, Some(_)) => { + // Case (2) or (4) + Ok((Some(node), None)) + } + (None, None) => { + // 1. The node is at `key` + match node { + Node::Branch(mut branch) => { + let Some(removed_value) = branch.value.take() else { + // The branch has no value. Return the node as is. + return Ok((Some(Node::Branch(branch)), None)); + }; + + Ok((self.flatten_branch(branch)?, Some(removed_value))) + } + Node::Leaf(leaf) => Ok((None, Some(leaf.value))), + } + } + (Some((child_index, child_partial_path)), None) => { + let child_index = PathComponent::try_new(child_index).expect("valid component"); + // 3. The key is below the node (i.e. its descendant) + match node { + // we found a non-matching leaf node, so the value does not exist + Node::Leaf(_) => Ok((Some(node), None)), + Node::Branch(mut branch) => { + let Some(child) = branch.children.take(child_index) else { + // child does not exist, so the value does not exist + return Ok((Some(Node::Branch(branch)), None)); + }; + let child = self.read_for_update(child)?; + + let (child, removed_value) = + self.remove_helper(child, child_partial_path.as_ref())?; + + branch.children[child_index] = child.map(Child::Node); + + Ok((self.flatten_branch(branch)?, removed_value)) + } + } + } + } + } + + /// Removes any key-value pairs with keys that have the given `prefix`. + /// Returns the number of key-value pairs removed. + pub fn remove_prefix(&mut self, prefix: &[u8]) -> Result { + self.remove_prefix_from_iter(NibblesIterator::new(prefix)) + } + + /// Removes any key-value pairs with keys that have the given `prefix` where `prefix` is a `NibblesIterator` + /// Returns the number of key-value pairs removed. + pub fn remove_prefix_from_iter( + &mut self, + prefix: NibblesIterator<'_>, + ) -> Result { + let prefix = Path::from_nibbles_iterator(prefix); + let root = self.nodestore.root_mut(); + let Some(root_node) = std::mem::take(root) else { + // The trie is empty. There is nothing to remove. + counter!("firewood.remove", "prefix" => "true", "result" => "nonexistent").increment(1); + return Ok(0); + }; + + let mut deleted = 0; + let root_node = self.remove_prefix_helper(root_node, &prefix, &mut deleted)?; + counter!("firewood.remove", "prefix" => "true", "result" => "success") + .increment(deleted as u64); + *self.nodestore.root_mut() = root_node; + Ok(deleted) + } + + fn remove_prefix_helper( + &mut self, + node: Node, + key: &[u8], + deleted: &mut usize, + ) -> Result, FileIoError> { + // 4 possibilities for the position of the `key` relative to `node`: + // 1. The node is at `key`, in which case we need to delete this node and all its children. + // 2. The key is above the node (i.e. its ancestor), so the parent needs to be restructured (TODO). + // 3. The key is below the node (i.e. its descendant), so continue traversing the trie. + // 4. Neither is an ancestor of the other, in which case there's no work to do. + let path_overlap = PrefixOverlap::from(key, node.partial_path().as_ref()); + + let unique_key = path_overlap.unique_a; + let unique_node = path_overlap.unique_b; + + match ( + unique_key + .split_first() + .map(|(index, path)| (*index, Path::from(path))), + unique_node.split_first(), + ) { + (None, _) => { + // 1. The node is at `key`, or we're just above it + // so we can start deleting below here + match node { + Node::Branch(branch) => { + if branch.value.is_some() { + // a KV pair was in the branch itself + *deleted = deleted.saturating_add(1); + } + self.delete_children(branch, deleted)?; + } + Node::Leaf(_) => { + // the prefix matched only a leaf, so we remove it and indicate only one item was removed + *deleted = deleted.saturating_add(1); + } + } + Ok(None) + } + (_, Some(_)) => { + // Case (2) or (4) + Ok(Some(node)) + } + (Some((child_index, child_partial_path)), None) => { + let child_index = PathComponent::try_new(child_index).expect("valid component"); + // 3. The key is below the node (i.e. its descendant) + match node { + Node::Leaf(_) => Ok(Some(node)), + Node::Branch(mut branch) => { + let Some(child) = branch.children.take(child_index) else { + return Ok(Some(Node::Branch(branch))); + }; + let child = self.read_for_update(child)?; + + let child = + self.remove_prefix_helper(child, child_partial_path.as_ref(), deleted)?; + + branch.children[child_index] = child.map(Child::Node); + + self.flatten_branch(branch) + } + } + } + } + } + + /// Recursively deletes all children of a branch node. + fn delete_children( + &mut self, + mut branch: Box, + deleted: &mut usize, + ) -> Result<(), FileIoError> { + if branch.value.is_some() { + // a KV pair was in the branch itself + *deleted = deleted.saturating_add(1); + } + for (_, child) in &mut branch.children { + let Some(child) = child.take() else { + continue; + }; + let child = self.read_for_update(child)?; + match child { + Node::Branch(child_branch) => { + self.delete_children(child_branch, deleted)?; + } + Node::Leaf(_) => { + *deleted = deleted.saturating_add(1); + } + } + } + Ok(()) + } + + /// Flattens a branch node into a new node. + /// + /// - If the branch has no value and no children, returns `None`. + /// - If the branch has a value and no children, it becomes a leaf node. + /// - If the branch has no value and exactly one child, it is replaced by that child + /// with an updated partial path. + /// - If the branch has a value and any children, it is returned as-is. + /// - If the branch has no value and multiple children, it is returned as-is. + fn flatten_branch( + &mut self, + mut branch_node: Box, + ) -> Result, FileIoError> { + let mut children_iter = branch_node.children.each_mut().into_iter(); + + let (child_index, child) = loop { + let Some((child_index, child_slot)) = children_iter.next() else { + // The branch has no children. Turn it into a leaf. + return match branch_node.value { + Some(value) => Ok(Some(Node::Leaf(LeafNode { + value, + partial_path: branch_node.partial_path, + }))), + None => Ok(None), + }; + }; + + let Some(child) = child_slot.take() else { + continue; + }; + + if branch_node.value.is_some() || children_iter.any(|(_, slot)| slot.is_some()) { + // put the child back in its slot since we removed it + child_slot.replace(child); + + // explicitly drop the iterator to release the mutable borrow on branch_node + drop(children_iter); + + // The branch has a value or more than 1 child, so it can't be flattened. + return Ok(Some(Node::Branch(branch_node))); + } + + // we have found the only child + break (child_index, child); + }; + + // The branch has only 1 child. Remove the branch and return the child. + let mut child = self.read_for_update(child)?; + + // The child's partial path is the concatenation of its (now removed) parent, + // its (former) child index, and its partial path. + let child_partial_path = Path::from_nibbles_iterator( + branch_node + .partial_path + .iter() + .chain(once(&child_index.as_u8())) + .chain(child.partial_path().iter()) + .copied(), + ); + child.update_partial_path(child_partial_path); + + Ok(Some(child)) + } +} + +/// Returns an iterator where each element is the result of combining +/// 2 nibbles of `nibbles`. If `nibbles` is odd length, panics in +/// debug mode and drops the final nibble in release mode. +pub fn nibbles_to_bytes_iter(nibbles: &[u8]) -> impl Iterator { + debug_assert_eq!(nibbles.len() & 1, 0); + #[expect(clippy::indexing_slicing)] + nibbles.chunks_exact(2).map(|p| (p[0] << 4) | p[1]) +} + +/// The [`PrefixOverlap`] type represents the _shared_ and _unique_ parts of two potentially overlapping slices. +/// As the type-name implies, the `shared` property only constitues a shared *prefix*. +/// The `unique_*` properties, [`unique_a`][`PrefixOverlap::unique_a`] and [`unique_b`][`PrefixOverlap::unique_b`] +/// are set based on the argument order passed into the [`from`][`PrefixOverlap::from`] constructor. +#[derive(Debug)] +struct PrefixOverlap<'a, T> { + shared: &'a [T], + unique_a: &'a [T], + unique_b: &'a [T], +} + +impl<'a, T: PartialEq> PrefixOverlap<'a, T> { + fn from(a: &'a [T], b: &'a [T]) -> Self { + let split_index = a + .iter() + .zip(b) + .position(|(a, b)| *a != *b) + .unwrap_or_else(|| std::cmp::min(a.len(), b.len())); + + let (shared, unique_a) = a.split_at(split_index); + let unique_b = b.get(split_index..).expect(""); + + Self { + shared, + unique_a, + unique_b, + } + } +} diff --git a/firewood/firewood/src/merkle/parallel.rs b/firewood/firewood/src/merkle/parallel.rs new file mode 100644 index 000000000000..7694cc159ca7 --- /dev/null +++ b/firewood/firewood/src/merkle/parallel.rs @@ -0,0 +1,492 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::db::BatchOp; +use crate::merkle::{Key, Merkle, Value}; +use crate::v2::api::IntoBatchIter; +use firewood_storage::logger::error; +use firewood_storage::{ + BranchNode, Child, Children, FileBacked, FileIoError, ImmutableProposal, LeafNode, + MaybePersistedNode, MutableProposal, NibblesIterator, Node, NodeReader, NodeStore, Parentable, + Path, PathComponent, +}; +use rayon::ThreadPool; +use std::iter::once; +use std::ops::Deref; +use std::sync::mpsc::{Receiver, SendError, Sender}; +use std::sync::{Arc, mpsc}; + +#[derive(Debug)] +struct WorkerSender(mpsc::Sender>); + +impl std::ops::Deref for WorkerSender { + type Target = mpsc::Sender>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +/// Response returned from a worker to the main thread. Includes the new root of the subtrie +/// at the given first path component and the deleted nodes. +#[derive(Debug)] +struct Response { + first_path_component: PathComponent, + root: Option, + deleted_nodes: Vec, +} + +#[derive(Debug)] +pub enum CreateProposalError { + FileIoError(FileIoError), + SendError, + InvalidConversionToPathComponent, +} + +impl From for CreateProposalError { + fn from(err: FileIoError) -> Self { + CreateProposalError::FileIoError(err) + } +} + +impl From>> for CreateProposalError { + fn from(_err: SendError>) -> Self { + CreateProposalError::SendError + } +} + +/// `ParallelMerkle` safely performs parallel modifications to a Merkle trie. It does this +/// by creating a worker for each subtrie from the root, and allowing the the workers to +/// perform inserts and removes to their subtries. +#[derive(Debug, Default)] +pub struct ParallelMerkle { + workers: Children>, +} + +impl ParallelMerkle { + /// Force the root (if necessary) into a branch with no partial path to allow the clean + /// separation of the trie into an array of subtries that can be operated on independently + /// by the worker threads. + fn force_root( + &self, + proposal: &mut NodeStore, + ) -> Result, CreateProposalError> { + // There are 3 different cases to handle depending on the value of the root node. + // + // 1. If root is None, create a branch node with an empty partial path and a None for + // value. Create Nones for all of its children. + // 2. If the existing root has a partial path, then create a new root with an empty + // partial path and a None for a value. Push down the previous root as a child. Note + // that this modified Merkle trie is not currently valid and may need to be updated + // during the post-processing step. + // 3. If the existing root does not have a partial path, then there is nothing we need + // to do if it is a branch. If it is a leaf, then convert it into a branch. + // + // Cases 2 and 3 are handled by `force_branch_for_insert`. This function returns a branch + // node with an empty partial path. + proposal.root_mut().take().map_or_else( + || { + // Empty trie. Create a branch node with an empty partial path and a None for a value. + Ok(BranchNode { + partial_path: Path::default(), + value: None, + children: Children::default(), + } + .into()) + }, + |node| { + // Returns an error if it cannot convert a child index into a path component. + node.force_branch_for_insert() + .map_err(|_| CreateProposalError::InvalidConversionToPathComponent) + }, + ) + } + + /// After performing parallel modifications, it may be necessary to perform post processing to + /// return the Merkle trie to the correct canonical form. This involves checking if the Merkle + /// trie has an extra root node. If it does, apply a transform to return the trie to a valid + /// state by following the steps below: + /// + /// If the root node has: + /// 0 children and no value, the trie is empty. Just delete the root. + /// 0 children and a value (from an empty key), the root should be a leaf + /// 1 child and no value, the child should be the root (need to update partial path) + /// In all other cases, the root is already correct. + fn postprocess_trie( + &self, + nodestore: &mut NodeStore, + mut branch: Box, + ) -> Result, FileIoError> { + let mut children_iter = branch + .children + .iter_mut() + .filter_map(|(index, child)| child.as_mut().map(|child| (index, child))); + + let first_child = children_iter.next(); + match first_child { + None => { + Ok(branch.value.map(|value| { + // There is a value for the empty key. Create a leaf with the value and return. + Node::Leaf(LeafNode { + value, + partial_path: Path::default(), // Partial path should be empty + }) + })) + } + Some((child_index, child)) => { + // Check if the root has a value or if there is more than one child. If yes, then + // just return the root unmodified + if branch.value.is_some() || children_iter.next().is_some() { + drop(children_iter); + return Ok(Some(Node::Branch(branch))); + } + + // Return the child as the new root. Update its partial path to include the index value. + let mut child = match child { + Child::Node(child_node) => std::mem::take(child_node), + Child::AddressWithHash(addr, _) => nodestore.read_for_update((*addr).into())?, + Child::MaybePersisted(maybe_persisted, _) => { + nodestore.read_for_update(maybe_persisted.clone())? + } + }; + + // The child's partial path is the concatenation of its (now removed) parent, which + // should always be empty because of our prepare step, its (former) child index, and + // its partial path. Because the parent's partial path should always be empty, we + // can omit it and start with the `child_index`. + let partial_path = Path::from_nibbles_iterator( + once(child_index.as_u8()).chain(child.partial_path().iter().copied()), + ); + child.update_partial_path(partial_path); + Ok(Some(child)) + } + } + } + + /// Call by a worker to processes requests from `child_receiver` and send back a response on + /// `response_sender` once the main thread closes the child sender. + fn worker_event_loop( + mut merkle: Merkle>, + first_path_component: PathComponent, + child_receiver: Receiver>, + response_sender: Sender>, + ) -> Result<(), Box>>> { + // Wait for a message on the receiver child channel. Break out of loop when the sender has + // closed the child sender. + while let Ok(request) = child_receiver.recv() { + if let Err(err) = match request { + // insert a key-value pair into the subtrie + BatchOp::Put { key, value } => { + let mut nibbles_iter = NibblesIterator::new(&key); + nibbles_iter.next(); // Skip the first nibble + merkle.insert_from_iter(nibbles_iter, value) + } + BatchOp::Delete { key } => { + let mut nibbles_iter = NibblesIterator::new(&key); + nibbles_iter.next(); // Skip the first nibble + merkle.remove_from_iter(nibbles_iter).map(|_| ()) + } + BatchOp::DeleteRange { prefix } => { + let mut nibbles_iter = NibblesIterator::new(&prefix); + nibbles_iter.next(); // Skip the first nibble + merkle.remove_prefix_from_iter(nibbles_iter).map(|_| ()) + } + } { + response_sender.send(Err(err))?; + break; // Stop handling additional requests + } + } + // The main thread has closed the channel. Hash this subtrie and send back the worker's + // response where the root is a Child::MaybePersisted. + let mut nodestore = merkle.into_inner(); + let response = nodestore + .root_mut() + .take() + .map(|root| { + #[cfg(not(feature = "ethhash"))] + let (root_node, root_hash) = NodeStore::::hash_helper( + root, + Path::from(&[first_path_component.as_u8()]), + )?; + #[cfg(feature = "ethhash")] + let (root_node, root_hash) = + nodestore.hash_helper(root, Path::from(&[first_path_component.as_u8()]))?; + Ok(Child::MaybePersisted(root_node, root_hash)) + }) + .transpose() + .map(|hashed_root| Response { + first_path_component, + root: hashed_root, + deleted_nodes: nodestore.take_deleted_nodes(), + }); + response_sender.send(response)?; + Ok(()) + } + + /// Creates a worker for performing operations on a subtrie, with the subtrie being determined + /// by the value of the `first_path_component`. + fn create_worker( + pool: &ThreadPool, + proposal: &NodeStore, + root_branch: &mut BranchNode, + first_path_component: PathComponent, + response_sender: Sender>, + ) -> Result { + // Create a channel for the coordinator (main thread) to send messages to this worker. + let (child_sender, child_receiver) = mpsc::channel(); + + // The root's child becomes the root node of the worker + let child_root = root_branch + .children + .get_mut(first_path_component) + .take() + .map(|child| -> Result<_, FileIoError> { + match child { + Child::Node(node) => Ok(node), + Child::AddressWithHash(address, _) => { + Ok(proposal.read_node(address)?.deref().clone()) + } + Child::MaybePersisted(maybe_persisted, _) => { + Ok(maybe_persisted.as_shared_node(proposal)?.deref().clone()) + } + } + }) + .transpose()?; + + // Build a nodestore from the child node + let worker_nodestore = NodeStore::from_root(proposal, child_root); + + // Spawn a worker from the threadpool for this nibble. The worker will send messages to the coordinator + // using `worker_sender`. + pool.spawn(move || { + if let Err(err) = ParallelMerkle::worker_event_loop( + Merkle::from(worker_nodestore), + first_path_component, + child_receiver, + response_sender, + ) { + error!("Worker cannot send to main thread using response channel: {err:?}"); + } + }); + Ok(WorkerSender(child_sender)) + } + + // Collect responses from the workers, each representing the root of a subtrie and merge them into the + // root node of the main trie. + fn merge_children( + &mut self, + response_channel: Receiver>, + proposal: &mut NodeStore, + root_branch: &mut BranchNode, + ) -> Result<(), FileIoError> { + while let Ok(response) = response_channel.recv() { + match response { + Ok(response) => { + // Adding deleted nodes (from calling read_for_update) from the child's nodestore. + proposal.delete_nodes(response.deleted_nodes.as_slice()); + + // Set the child at index to response.root which is the root of the child's subtrie. + *root_branch.children.get_mut(response.first_path_component) = response.root; + } + Err(err) => { + return Err(err); // Early termination. + } + } + } + Ok(()) + } + + /// Get a worker from the worker pool based on the `first_path_component` value. Create a worker if + /// it doesn't exist already. + fn worker( + &mut self, + pool: &ThreadPool, + proposal: &NodeStore, + root_branch: &mut BranchNode, + first_path_component: PathComponent, + response_sender: Sender>, + ) -> Result<&mut WorkerSender, FileIoError> { + // Find the worker's state corresponding to the first nibble which is stored in an array. + let worker_option = self.workers.get_mut(first_path_component); + + // Create a new worker if it doesn't exist. Not using `get_or_insert_with` with worker_option + // because it is possible to generate a FileIoError within the closure. + match worker_option { + Some(worker) => Ok(worker), + None => Ok(worker_option.insert(ParallelMerkle::create_worker( + pool, + proposal, + root_branch, + first_path_component, + response_sender, + )?)), + } + } + + /// Removes all of the entries in the trie. For the root entry, the value is removed but the + /// root itself will remain. An empty root will only be removed during post processing. + fn remove_all_entries( + &self, + root_branch: &mut BranchNode, + ) -> Result<(), SendError>> { + for worker in self + .workers + .iter() + .filter_map(|(_, worker)| worker.as_ref()) + { + worker.send(BatchOp::DeleteRange { + prefix: Box::default(), // Empty prefix + })?; + } + // Also set the root value to None but does not delete the root. + root_branch.value = None; + Ok(()) + } + + /// The parent thread may receive a `SendError` if the worker that it is sending to has + /// returned to the threadpool after encountering a `FileIoError`. This function should + /// be called after receiving a `SendError` to find and propagate the `FileIoError`. + fn find_fileio_error( + response_receiver: &Receiver>, + ) -> Result<(), FileIoError> { + // Go through the messages in the response channel without blocking to see if we can + // find the FileIoError that caused the worker to close the channel, resulting in a + // send error. If we can find it, then we propagate the FileIoError. Note that + // successful responses can be in the response channel ahead of the FileIoError. + // These are sent from workers that completed their requests without encountering + // a FileIoError. + for result in response_receiver.try_iter() { + let _ = result?; // explicitly ignore the successful Response + } + Ok(()) + } + + /// Creates a parallel proposal in 4 steps: Prepare, Split, Merge, and Post-process. In the + /// Prepare step, the trie is modified to ensure that the root is a branch node with no + /// partial path. In the split step, entries from the batch are sent to workers that + /// independently modify their sub-tries. In the merge step, the sub-tries are merged back + /// to the main trie. Finally, in the post-processing step, the trie is returned to its + /// canonical form. + /// + /// # Errors + /// + /// Returns a `CreateProposalError::FileIoError` if it encounters an error fetching nodes + /// from storage, a `CreateProposalError::SendError` if it is unable to send messages to + /// the workers, and a `CreateProposalError::InvalidConversionToPathComponent` if it is + /// unable to convert a u8 index into a path component. + pub fn create_proposal( + &mut self, + parent: &NodeStore, + batch: impl IntoBatchIter, + pool: &ThreadPool, + ) -> Result, FileBacked>>, CreateProposalError> { + // Create a mutable nodestore from the parent + let mut mutable_nodestore = NodeStore::new(parent)?; + + // Prepare step: Force the root into a branch with no partial path in preparation for + // performing parallel modifications to the trie. + let mut root_branch = self.force_root(&mut mutable_nodestore)?; + + // Create a response channel the workers use to send messages back to the coordinator (us) + let (response_sender, response_receiver) = mpsc::channel(); + + // Split step: for each operation in the batch, send a request to the worker that is + // responsible for the sub-trie corresponding to the operation's first nibble. + for res in batch.into_batch_iter::() { + let op = res?; + // Get the first nibble of the key to determine which worker to send the request to. + // + // Need to handle an empty key. Since the partial_path of the root must be empty, an + // empty key should always be for the root node. There are 3 cases to consider. + // + // Insert: The main thread modifies the value of the root. + // + // Remove: The main thread removes any value at the root. However, it should not delete + // the root node, which, if necessary later, will be done in post processing. + // + // Remove Prefix: + // For a remove prefix, we would need to remove everything. We do this by sending + // a remove prefix with an empty prefix to all of the children, then removing the + // value of the root node. + let mut key_nibbles = NibblesIterator::new(op.key().as_ref()); + let Some(first_path_component) = key_nibbles.next() else { + match &op { + BatchOp::Put { key: _, value } => { + root_branch.value = Some(value.as_ref().into()); + } + BatchOp::Delete { key: _ } => { + root_branch.value = None; + } + BatchOp::DeleteRange { prefix: _ } => { + // Calling remove prefix with an empty prefix is equivalent to a remove all. + if let Err(err) = self.remove_all_entries(&mut root_branch) { + // A send error is most likely due to a worker returning to the thread pool + // after it encountered a FileIoError. Try to find the FileIoError in the + // response channel and return that instead. + ParallelMerkle::find_fileio_error(&response_receiver)?; + return Err(err.into()); + } + } + } + continue; // Done with this empty key operation. + }; + + // Verify that the worker index taken from the first nibble is valid. + let first_path_component = PathComponent::try_new(first_path_component) + .ok_or(CreateProposalError::InvalidConversionToPathComponent)?; + + // Get the worker that is responsible for this nibble. The worker will be created if it + // doesn't already exist. + let worker = self.worker( + pool, + &mutable_nodestore, + &mut root_branch, + first_path_component, + response_sender.clone(), + )?; + + // Send the current operation to the worker. + // TODO: Currently the key from the BatchOp is copied to a Box<[u8]> before it is sent + // to the worker. It may be possible to send a nibble iterator instead of a + // Box<[u8]> to the worker if we use rayon scoped threads. This change would + // eliminate a memory copy but may require some code refactoring. + if let Err(err) = match &op { + BatchOp::Put { key: _, value } => worker.send(BatchOp::Put { + key: op.key().as_ref().into(), + value: value.as_ref().into(), + }), + BatchOp::Delete { key: _ } => worker.send(BatchOp::Delete { + key: op.key().as_ref().into(), + }), + BatchOp::DeleteRange { prefix: _ } => worker.send(BatchOp::DeleteRange { + prefix: op.key().as_ref().into(), + }), + } { + // A send error is most likely due to a worker returning to the thread pool + // after it encountered a FileIoError. Try to find the FileIoError in the + // response channel and return that instead. + ParallelMerkle::find_fileio_error(&response_receiver)?; + return Err(err.into()); + } + } + + // Drop the sender response channel from the parent thread. + drop(response_sender); + + // Setting the workers to default will close the senders to the workers. This will cause the + // workers to send back their responses. + self.workers = Children::default(); + + // Merge step: Collect the results from the workers and merge them as children to the root. + self.merge_children(response_receiver, &mut mutable_nodestore, &mut root_branch)?; + + // Post-process step: return the trie to its canonical form. + *mutable_nodestore.root_mut() = + self.postprocess_trie(&mut mutable_nodestore, root_branch)?; + + let immutable: Arc, FileBacked>> = + Arc::new(mutable_nodestore.try_into()?); + + Ok(immutable) + } +} diff --git a/firewood/firewood/src/merkle/tests/ethhash.rs b/firewood/firewood/src/merkle/tests/ethhash.rs new file mode 100644 index 000000000000..22e90118fa17 --- /dev/null +++ b/firewood/firewood/src/merkle/tests/ethhash.rs @@ -0,0 +1,184 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::v2::api::OptionalHashKeyExt; + +use super::*; +use ethereum_types::H256; +use hash_db::Hasher; +use plain_hasher::PlainHasher; +use sha3::{Digest, Keccak256}; +use test_case::test_case; + +#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)] +pub struct KeccakHasher; + +impl KeccakHasher { + fn trie_root(items: I) -> H256 + where + I: IntoIterator, + K: AsRef<[u8]> + Ord, + V: AsRef<[u8]>, + { + firewood_triehash::trie_root::(items) + } +} + +impl Hasher for KeccakHasher { + type Out = H256; + type StdHasher = PlainHasher; + const LENGTH: usize = 32; + + #[inline] + fn hash(x: &[u8]) -> Self::Out { + let mut hasher = Keccak256::new(); + hasher.update(x); + let result = hasher.finalize(); + H256::from_slice(result.as_slice()) + } +} + +#[test_case([("doe", "reindeer")])] +#[test_case([("doe", "reindeer"),("dog", "puppy"),("dogglesworth", "cat")])] +#[test_case([("doe", "reindeer"),("dog", "puppy"),("dogglesworth", "cacatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatt")])] +#[test_case([("dogglesworth", "cacatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatcatt")])] +fn test_root_hash_eth_compatible(kvs: I) +where + I: Clone + IntoIterator, + K: AsRef<[u8]> + Ord, + V: AsRef<[u8]>, +{ + let merkle = init_merkle(kvs.clone()); + let firewood_hash = merkle.nodestore.root_hash().unwrap_or_else(TrieHash::empty); + let eth_hash: TrieHash = KeccakHasher::trie_root(kvs).to_fixed_bytes().into(); + assert_eq!(firewood_hash, eth_hash); +} + +#[test_case( + "0000000000000000000000000000000000000002", + "f844802ca00000000000000000000000000000000000000000000000000000000000000000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + &[], + "c00ca9b8e6a74b03f6b1ae2db4a65ead348e61b74b339fe4b117e860d79c7821" + )] +#[test_case( + "0000000000000000000000000000000000000002", + "f844802ca00000000000000000000000000000000000000000000000000000000000000000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + &[ + ("48078cfed56339ea54962e72c37c7f588fc4f8e5bc173827ba75cb10a63a96a5", "a00200000000000000000000000000000000000000000000000000000000000000") + ], + "91336bf4e6756f68e1af0ad092f4a551c52b4a66860dc31adbd736f0acbadaf6" + )] +#[test_case( + "0000000000000000000000000000000000000002", + "f844802ca00000000000000000000000000000000000000000000000000000000000000000a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + &[ + ("48078cfed56339ea54962e72c37c7f588fc4f8e5bc173827ba75cb10a63a96a5", "a00200000000000000000000000000000000000000000000000000000000000000"), + ("0e81f83a84964b811dd1b8328262a9f57e6bc3e5e7eb53627d10437c73c4b8da", "a02800000000000000000000000000000000000000000000000000000000000000"), + ], + "c267104830880c966c2cc8c669659e4bfaf3126558dbbd6216123b457944001b" + )] +fn test_eth_compatible_accounts( + account: &str, + account_value: &str, + key_suffixes_and_values: &[(&str, &str)], + expected_root: &str, +) { + use sha3::Digest as _; + use sha3::Keccak256; + + let account = make_key(account); + let expected_key_hash = Keccak256::digest(&account); + + let items = once(( + Box::from(expected_key_hash.as_slice()), + make_key(account_value), + )) + .chain(key_suffixes_and_values.iter().map(|(key_suffix, value)| { + let key = expected_key_hash + .iter() + .copied() + .chain(make_key(key_suffix).iter().copied()) + .collect(); + let value = make_key(value); + (key, value) + })) + .collect::, Box<_>)>>(); + + let merkle = init_merkle(items); + let firewood_hash = merkle.nodestore.root_hash(); + + assert_eq!( + firewood_hash, + TrieHash::try_from(&*make_key(expected_root)).ok() + ); +} + +/// helper method to convert a hex encoded string into a boxed slice +fn make_key(hex_str: &str) -> Key { + hex::decode(hex_str).unwrap().into_boxed_slice() +} + +#[test] +fn test_root_hash_random_deletions() { + use rand::seq::SliceRandom; + let rng = firewood_storage::SeededRng::from_option(Some(42)); + let max_len0 = 8; + let max_len1 = 4; + let keygen = || { + let (len0, len1): (usize, usize) = { + ( + rng.random_range(1..=max_len0), + rng.random_range(1..=max_len1), + ) + }; + (0..len0) + .map(|_| rng.random_range(0..2)) + .chain((0..len1).map(|_| rng.random())) + .collect() + }; + + for i in 0..10 { + let mut items = std::collections::HashMap::::new(); + + for _ in 0..10 { + let val = (0..8).map(|_| rng.random()).collect(); + items.insert(keygen(), val); + } + + let mut items_ordered: Vec<_> = items.iter().map(|(k, v)| (k.clone(), v.clone())).collect(); + items_ordered.sort_unstable(); + items_ordered.shuffle(&mut &rng); + + let mut committed_merkle = init_merkle(&items); + + for (k, v) in items_ordered { + let mut merkle = committed_merkle.fork().unwrap(); + assert_eq!(merkle.get_value(&k).unwrap().as_deref(), Some(v.as_ref())); + + merkle.remove(&k).unwrap(); + + // assert_eq(None) and not assert(is_none) for better error messages + assert_eq!(merkle.get_value(&k).unwrap().as_deref(), None); + + items.remove(&k); + + for (k, v) in &items { + assert_eq!(merkle.get_value(k).unwrap().as_deref(), Some(v.as_ref())); + } + + committed_merkle = into_committed(merkle.hash(), committed_merkle.nodestore()); + + let h: TrieHash = KeccakHasher::trie_root(&items).to_fixed_bytes().into(); + + let h0 = committed_merkle + .nodestore() + .root_hash() + .or_default_root_hash() + .unwrap(); + + assert_eq!(h, h0); + } + + println!("i = {i}"); + } +} diff --git a/firewood/firewood/src/merkle/tests/mod.rs b/firewood/firewood/src/merkle/tests/mod.rs new file mode 100644 index 000000000000..3863163ecfb1 --- /dev/null +++ b/firewood/firewood/src/merkle/tests/mod.rs @@ -0,0 +1,797 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect(clippy::indexing_slicing, clippy::unwrap_used)] + +#[cfg(feature = "ethhash")] +mod ethhash; +// TODO: get the hashes from merkledb and verify compatibility with branch factor 256 +mod proof; +mod range; +#[cfg(not(any(feature = "ethhash", feature = "branch_factor_256")))] +mod triehash; + +use std::collections::HashMap; +use std::fmt::Write; + +use super::*; +use firewood_storage::{Committed, MemStore, MutableProposal, NodeStore, RootReader, TrieHash}; + +// Returns n random key-value pairs. +fn generate_random_kvs(rng: &firewood_storage::SeededRng, n: usize) -> Vec<(Vec, Vec)> { + let mut kvs: Vec<(Vec, Vec)> = Vec::new(); + for _ in 0..n { + let key_len = rng.random_range(1..=4096); + let key: Vec = (0..key_len).map(|_| rng.random()).collect(); + + let val_len = rng.random_range(1..=4096); + let val: Vec = (0..val_len).map(|_| rng.random()).collect(); + + kvs.push((key, val)); + } + + kvs +} + +fn into_committed( + merkle: Merkle, MemStore>>, + parent: &NodeStore, +) -> Merkle> { + let ns = merkle.into_inner(); + ns.flush_freelist().unwrap(); + ns.flush_header().unwrap(); + let mut ns = ns.as_committed(parent); + ns.flush_nodes().unwrap(); + ns.into() +} + +pub(crate) fn init_merkle(iter: I) -> Merkle> +where + I: Clone + IntoIterator, + K: AsRef<[u8]>, + V: AsRef<[u8]>, +{ + let memstore = Arc::new(MemStore::new(Vec::with_capacity(64 * 1024))); + let base = Merkle::from(NodeStore::new_empty_committed(memstore.clone())); + let mut merkle = base.fork().unwrap(); + + for (k, v) in iter.clone() { + let key = k.as_ref(); + let value = v.as_ref(); + + merkle.insert(key, value.into()).unwrap(); + + assert_eq!( + merkle.get_value(key).unwrap().as_deref(), + Some(value), + "Failed to insert key: {key:?}", + ); + } + + for (k, v) in iter.clone() { + let key = k.as_ref(); + let value = v.as_ref(); + + assert_eq!( + merkle.get_value(key).unwrap().as_deref(), + Some(value), + "Failed to get key after insert: {key:?}", + ); + } + + let merkle = merkle.hash(); + + for (k, v) in iter.clone() { + let key = k.as_ref(); + let value = v.as_ref(); + + assert_eq!( + merkle.get_value(key).unwrap().as_deref(), + Some(value), + "Failed to get key after hashing: {key:?}" + ); + } + + let merkle = into_committed(merkle, base.nodestore()); + + for (k, v) in iter { + let key = k.as_ref(); + let value = v.as_ref(); + + assert_eq!( + merkle.get_value(key).unwrap().as_deref(), + Some(value), + "Failed to get key after committing: {key:?}" + ); + } + + merkle +} + +// generate pseudorandom data, but prefix it with some known data +// The number of fixed data points is 100; you specify how much random data you want +#[expect(clippy::arithmetic_side_effects)] +fn fixed_and_pseudorandom_data( + rng: &firewood_storage::SeededRng, + random_count: u32, +) -> HashMap<[u8; 32], [u8; 20]> { + let mut items = HashMap::new(); + for i in 0..100_u32 { + let mut key: [u8; 32] = [0; 32]; + let mut value: [u8; 20] = [0; 20]; + for (index, d) in i.to_be_bytes().iter().enumerate() { + key[index] = *d; + value[index] = *d; + } + items.insert(key, value); + + let mut more_key: [u8; 32] = [0; 32]; + for (index, d) in (i + 10).to_be_bytes().iter().enumerate() { + more_key[index] = *d; + } + items.insert(more_key, value); + } + + for _ in 0..random_count { + let key = rng.random::<[u8; 32]>(); + let val = rng.random::<[u8; 20]>(); + items.insert(key, val); + } + items +} + +fn increase_key(key: &[u8; 32]) -> [u8; 32] { + let mut new_key = *key; + for ch in new_key.iter_mut().rev() { + let overflow; + (*ch, overflow) = ch.overflowing_add(1); + if !overflow { + break; + } + } + new_key +} + +fn decrease_key(key: &[u8; 32]) -> [u8; 32] { + let mut new_key = *key; + for ch in new_key.iter_mut().rev() { + let overflow; + (*ch, overflow) = ch.overflowing_sub(1); + if !overflow { + break; + } + } + new_key +} + +#[test] +fn test_get_regression() { + let mut merkle = create_in_memory_merkle(); + + merkle.insert(&[0], Box::new([0])).unwrap(); + assert_eq!(merkle.get_value(&[0]).unwrap(), Some(Box::from([0]))); + + merkle.insert(&[1], Box::new([1])).unwrap(); + assert_eq!(merkle.get_value(&[1]).unwrap(), Some(Box::from([1]))); + + merkle.insert(&[2], Box::new([2])).unwrap(); + assert_eq!(merkle.get_value(&[2]).unwrap(), Some(Box::from([2]))); + + let merkle = merkle.hash(); + + assert_eq!(merkle.get_value(&[0]).unwrap(), Some(Box::from([0]))); + assert_eq!(merkle.get_value(&[1]).unwrap(), Some(Box::from([1]))); + assert_eq!(merkle.get_value(&[2]).unwrap(), Some(Box::from([2]))); + + for result in merkle.path_iter(&[2]).unwrap() { + result.unwrap(); + } +} + +#[test] +fn insert_one() { + let mut merkle = create_in_memory_merkle(); + merkle.insert(b"abc", Box::new([])).unwrap(); +} + +fn create_in_memory_merkle() -> Merkle> { + let memstore = MemStore::new(vec![]); + + let nodestore = NodeStore::new_empty_proposal(memstore.into()); + + Merkle { nodestore } +} + +#[test] +fn test_insert_and_get() { + let mut merkle = create_in_memory_merkle(); + + // insert values + for key_val in u8::MIN..=u8::MAX { + let key = vec![key_val]; + let val = Box::new([key_val]); + + merkle.insert(&key, val.clone()).unwrap(); + + let fetched_val = merkle.get_value(&key).unwrap(); + + // make sure the value was inserted + assert_eq!(fetched_val.as_deref(), val.as_slice().into()); + } + + // make sure none of the previous values were forgotten after initial insert + for key_val in u8::MIN..=u8::MAX { + let key = vec![key_val]; + let val = vec![key_val]; + + let fetched_val = merkle.get_value(&key).unwrap(); + + assert_eq!(fetched_val.as_deref(), val.as_slice().into()); + } +} + +#[test] +fn overwrite_leaf() { + let key = &[0x00]; + let val = &[1]; + let overwrite = &[2]; + + let mut merkle = create_in_memory_merkle(); + + merkle.insert(key, val[..].into()).unwrap(); + + assert_eq!( + merkle.get_value(key).unwrap().as_deref(), + Some(val.as_slice()) + ); + + merkle.insert(key, overwrite[..].into()).unwrap(); + + assert_eq!( + merkle.get_value(key).unwrap().as_deref(), + Some(overwrite.as_slice()) + ); +} + +#[test] +fn remove_root() { + let key0 = vec![0]; + let val0 = [0]; + let key1 = vec![0, 1]; + let val1 = [0, 1]; + let key2 = vec![0, 1, 2]; + let val2 = [0, 1, 2]; + let key3 = vec![0, 1, 15]; + let val3 = [0, 1, 15]; + + let mut merkle = create_in_memory_merkle(); + + merkle.insert(&key0, Box::from(val0)).unwrap(); + merkle.insert(&key1, Box::from(val1)).unwrap(); + merkle.insert(&key2, Box::from(val2)).unwrap(); + merkle.insert(&key3, Box::from(val3)).unwrap(); + // Trie is: + // key0 + // | + // key1 + // / \ + // key2 key3 + + // Test removal of root when it's a branch with 1 branch child + let removed_val = merkle.remove(&key0).unwrap(); + assert_eq!(removed_val, Some(Box::from(val0))); + assert!(merkle.get_value(&key0).unwrap().is_none()); + // Removing an already removed key is a no-op + assert!(merkle.remove(&key0).unwrap().is_none()); + + // Trie is: + // key1 + // / \ + // key2 key3 + // Test removal of root when it's a branch with multiple children + assert_eq!(merkle.remove(&key1).unwrap(), Some(Box::from(val1))); + assert!(merkle.get_value(&key1).unwrap().is_none()); + assert!(merkle.remove(&key1).unwrap().is_none()); + + // Trie is: + // key1 (now has no value) + // / \ + // key2 key3 + let removed_val = merkle.remove(&key2).unwrap(); + assert_eq!(removed_val, Some(Box::from(val2))); + assert!(merkle.get_value(&key2).unwrap().is_none()); + assert!(merkle.remove(&key2).unwrap().is_none()); + + // Trie is: + // key3 + let removed_val = merkle.remove(&key3).unwrap(); + assert_eq!(removed_val, Some(Box::from(val3))); + assert!(merkle.get_value(&key3).unwrap().is_none()); + assert!(merkle.remove(&key3).unwrap().is_none()); + + assert!(merkle.nodestore.root_node().is_none()); +} + +#[test] +fn remove_prefix_exact() { + let mut merkle = two_byte_all_keys(); + for key_val in u8::MIN..=u8::MAX { + let key = [key_val]; + let got = merkle.remove_prefix(&key).unwrap(); + assert_eq!(got, 1); + let got = merkle.get_value(&key).unwrap(); + assert!(got.is_none()); + } +} + +fn two_byte_all_keys() -> Merkle> { + let mut merkle = create_in_memory_merkle(); + for key_val in u8::MIN..=u8::MAX { + let key = [key_val, key_val]; + let val = [key_val]; + + merkle.insert(&key, Box::new(val)).unwrap(); + let got = merkle.get_value(&key).unwrap().unwrap(); + assert_eq!(&*got, val); + } + merkle +} + +#[test] +fn remove_prefix_all() { + let mut merkle = two_byte_all_keys(); + let got = merkle.remove_prefix(&[]).unwrap(); + assert_eq!(got, 256); +} + +#[test] +fn remove_prefix_partial() { + let mut merkle = create_in_memory_merkle(); + merkle + .insert(b"abc", Box::from(b"value".as_slice())) + .unwrap(); + merkle + .insert(b"abd", Box::from(b"value".as_slice())) + .unwrap(); + let got = merkle.remove_prefix(b"ab").unwrap(); + assert_eq!(got, 2); +} + +#[test] +fn remove_many() { + let mut merkle = create_in_memory_merkle(); + + // insert key-value pairs + for key_val in u8::MIN..=u8::MAX { + let key = [key_val]; + let val = [key_val]; + + merkle.insert(&key, Box::new(val)).unwrap(); + let got = merkle.get_value(&key).unwrap().unwrap(); + assert_eq!(&*got, val); + } + + // remove key-value pairs + for key_val in u8::MIN..=u8::MAX { + let key = [key_val]; + let val = [key_val]; + + let got = merkle.remove(&key).unwrap().unwrap(); + assert_eq!(&*got, val); + + // Removing an already removed key is a no-op + assert!(merkle.remove(&key).unwrap().is_none()); + + let got = merkle.get_value(&key).unwrap(); + assert!(got.is_none()); + } + assert!(merkle.nodestore.root_node().is_none()); +} + +#[test] +fn remove_prefix() { + let mut merkle = create_in_memory_merkle(); + + // insert key-value pairs + for key_val in u8::MIN..=u8::MAX { + let key = [key_val, key_val]; + let val = [key_val]; + + merkle.insert(&key, Box::new(val)).unwrap(); + let got = merkle.get_value(&key).unwrap().unwrap(); + assert_eq!(&*got, val); + } + + // remove key-value pairs with prefix [0] + let prefix = [0]; + assert_eq!(merkle.remove_prefix(&[0]).unwrap(), 1); + + // make sure all keys with prefix [0] were removed + for key_val in u8::MIN..=u8::MAX { + let key = [key_val, key_val]; + let got = merkle.get_value(&key).unwrap(); + if key[0] == prefix[0] { + assert!(got.is_none()); + } else { + assert!(got.is_some()); + } + } +} + +#[test] +fn get_empty_proof() { + let merkle = create_in_memory_merkle().hash(); + let proof = merkle.prove(b"any-key"); + assert!(matches!(proof.unwrap_err(), ProofError::Empty)); +} + +#[test] +fn single_key_proof() { + const TEST_SIZE: usize = 1; + + let mut merkle = create_in_memory_merkle(); + + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let kvs = generate_random_kvs(&rng, TEST_SIZE); + + for (key, val) in &kvs { + merkle.insert(key, val.clone().into_boxed_slice()).unwrap(); + } + + let merkle = merkle.hash(); + + let root_hash = merkle.nodestore.root_hash().unwrap(); + + for (key, value) in kvs { + let proof = merkle.prove(&key).unwrap(); + + proof + .verify(key.clone(), Some(value.clone()), &root_hash) + .unwrap(); + + { + // Test that the proof is invalid when the value is different + let mut value = value.clone(); + value[0] = value[0].wrapping_add(1); + assert!(proof.verify(key.clone(), Some(value), &root_hash).is_err()); + } + + { + // Test that the proof is invalid when the hash is different + assert!(proof.verify(key, Some(value), &TrieHash::empty()).is_err()); + } + } +} + +#[test] +fn empty_range_proof() { + let merkle = create_in_memory_merkle(); + + assert!(matches!( + merkle.range_proof(None, None, None).unwrap_err(), + api::Error::RangeProofOnEmptyTrie + )); +} + +#[test] +fn test_insert_leaf_suffix() { + // key_2 is a suffix of key, which is a leaf + let key = vec![0xff]; + let val = [1]; + let key_2 = vec![0xff, 0x00]; + let val_2 = [2]; + + let mut merkle = create_in_memory_merkle(); + + merkle.insert(&key, Box::new(val)).unwrap(); + merkle.insert(&key_2, Box::new(val_2)).unwrap(); + + let got = merkle.get_value(&key).unwrap().unwrap(); + + assert_eq!(*got, val); + + let got = merkle.get_value(&key_2).unwrap().unwrap(); + assert_eq!(*got, val_2); +} + +#[test] +fn test_insert_leaf_prefix() { + // key_2 is a prefix of key, which is a leaf + let key = vec![0xff, 0x00]; + let val = [1]; + let key_2 = vec![0xff]; + let val_2 = [2]; + + let mut merkle = create_in_memory_merkle(); + + merkle.insert(&key, Box::new(val)).unwrap(); + merkle.insert(&key_2, Box::new(val_2)).unwrap(); + + let got = merkle.get_value(&key).unwrap().unwrap(); + assert_eq!(*got, val); + + let got = merkle.get_value(&key_2).unwrap().unwrap(); + assert_eq!(*got, val_2); +} + +#[test] +fn test_insert_sibling_leaf() { + // The node at key is a branch node with children key_2 and key_3. + // TODO assert in this test that key is the parent of key_2 and key_3. + // i.e. the node types are branch, leaf, leaf respectively. + let key = vec![0xff]; + let val = [1]; + let key_2 = vec![0xff, 0x00]; + let val_2 = [2]; + let key_3 = vec![0xff, 0x0f]; + let val_3 = [3]; + + let mut merkle = create_in_memory_merkle(); + + merkle.insert(&key, Box::new(val)).unwrap(); + merkle.insert(&key_2, Box::new(val_2)).unwrap(); + merkle.insert(&key_3, Box::new(val_3)).unwrap(); + + let got = merkle.get_value(&key).unwrap().unwrap(); + assert_eq!(*got, val); + + let got = merkle.get_value(&key_2).unwrap().unwrap(); + assert_eq!(*got, val_2); + + let got = merkle.get_value(&key_3).unwrap().unwrap(); + assert_eq!(*got, val_3); +} + +#[test] +fn test_insert_branch_as_branch_parent() { + let key = vec![0xff, 0xf0]; + let val = [1]; + let key_2 = vec![0xff, 0xf0, 0x00]; + let val_2 = [2]; + let key_3 = vec![0xff]; + let val_3 = [3]; + + let mut merkle = create_in_memory_merkle(); + + merkle.insert(&key, Box::new(val)).unwrap(); + // key is a leaf + + merkle.insert(&key_2, Box::new(val_2)).unwrap(); + // key is branch with child key_2 + + merkle.insert(&key_3, Box::new(val_3)).unwrap(); + // key_3 is a branch with child key + // key is a branch with child key_3 + + let got = merkle.get_value(&key).unwrap().unwrap(); + assert_eq!(&*got, val); + + let got = merkle.get_value(&key_2).unwrap().unwrap(); + assert_eq!(&*got, val_2); + + let got = merkle.get_value(&key_3).unwrap().unwrap(); + assert_eq!(&*got, val_3); +} + +#[test] +fn test_insert_overwrite_branch_value() { + let key = vec![0xff]; + let val = [1]; + let key_2 = vec![0xff, 0x00]; + let val_2 = [2]; + let overwrite = [3]; + + let mut merkle = create_in_memory_merkle(); + + merkle.insert(&key, Box::new(val)).unwrap(); + merkle.insert(&key_2, Box::new(val_2)).unwrap(); + + let got = merkle.get_value(&key).unwrap().unwrap(); + assert_eq!(*got, val); + + let got = merkle.get_value(&key_2).unwrap().unwrap(); + assert_eq!(*got, val_2); + + merkle.insert(&key, Box::new(overwrite)).unwrap(); + + let got = merkle.get_value(&key).unwrap().unwrap(); + assert_eq!(*got, overwrite); + + let got = merkle.get_value(&key_2).unwrap().unwrap(); + assert_eq!(*got, val_2); +} + +#[test] +fn test_delete_one_child_with_branch_value() { + let mut merkle = create_in_memory_merkle(); + // insert a parent with a value + merkle.insert(&[0], Box::new([42u8])).unwrap(); + // insert child1 with a value + merkle.insert(&[0, 1], Box::new([43u8])).unwrap(); + // insert child2 with a value + merkle.insert(&[0, 2], Box::new([44u8])).unwrap(); + + // now delete one of the children + let deleted = merkle.remove(&[0, 1]).unwrap(); + assert_eq!(deleted, Some([43u8].to_vec().into_boxed_slice())); + + // make sure the parent still has the correct value + let got = merkle.get_value(&[0]).unwrap().unwrap(); + assert_eq!(*got, [42u8]); + + // and check the remaining child + let other_child = merkle.get_value(&[0, 2]).unwrap().unwrap(); + assert_eq!(*other_child, [44u8]); +} + +#[test] +fn test_root_hash_simple_insertions() -> Result<(), Error> { + init_merkle([ + ("do", "verb"), + ("doe", "reindeer"), + ("dog", "puppy"), + ("doge", "coin"), + ("horse", "stallion"), + ("ddd", "ok"), + ]) + .dump_to_string() + .unwrap(); + Ok(()) +} + +#[test] +fn test_root_hash_fuzz_insertions() -> Result<(), FileIoError> { + let rng = firewood_storage::SeededRng::from_option(Some(42)); + let max_len0 = 8; + let max_len1 = 4; + let keygen = || { + let (len0, len1): (usize, usize) = { + ( + rng.random_range(1..=max_len0), + rng.random_range(1..=max_len1), + ) + }; + let key: Vec = (0..len0) + .map(|_| rng.random_range(0..2)) + .chain((0..len1).map(|_| rng.random())) + .collect(); + key + }; + + // TODO: figure out why this fails if we use more than 27 iterations with branch_factor_256 + for _ in 0..27 { + let mut items = Vec::new(); + + for _ in 0..100 { + let val: Vec = (0..256).map(|_| rng.random()).collect(); + items.push((keygen(), val)); + } + + init_merkle(items); + } + + Ok(()) +} + +#[test] +fn test_delete_child() { + let items = vec![("do", "verb")]; + let merkle = init_merkle(items); + let mut merkle = merkle.fork().unwrap(); + + assert_eq!(merkle.remove(b"does_not_exist").unwrap(), None); + assert_eq!(&*merkle.get_value(b"do").unwrap().unwrap(), b"verb"); +} + +#[test] +fn test_delete_some() { + let items = (0..100) + .map(|n| { + let key = format!("key{n}"); + let val = format!("value{n}"); + (key.as_bytes().to_vec(), val.as_bytes().to_vec()) + }) + .collect::, Vec)>>(); + let mut merkle = init_merkle(items.clone()).fork().unwrap(); + merkle.remove_prefix(b"key1").unwrap(); + for item in items { + let (key, val) = item; + if key.starts_with(b"key1") { + assert!(merkle.get_value(&key).unwrap().is_none()); + } else { + assert_eq!(&*merkle.get_value(&key).unwrap().unwrap(), val.as_slice()); + } + } +} + +#[test] +fn test_root_hash_reversed_deletions() -> Result<(), FileIoError> { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let max_len0 = 8; + let max_len1 = 4; + let keygen = || { + let (len0, len1): (usize, usize) = { + ( + rng.random_range(1..=max_len0), + rng.random_range(1..=max_len1), + ) + }; + (0..len0) + .map(|_| rng.random_range(0..2)) + .chain((0..len1).map(|_| rng.random())) + .collect() + }; + + for _ in 0..10 { + let mut items: Vec<(Key, Value)> = (0..10) + .map(|_| keygen()) + .map(|key| { + let val = (0..8).map(|_| rng.random()).collect(); + (key, val) + }) + .collect(); + + items.sort_unstable(); + items.dedup_by_key(|(k, _)| k.clone()); + + let init_merkle = create_in_memory_merkle(); + let init_immutable_merkle = init_merkle.hash(); + + let (hashes, complete_immutable_merkle) = items.iter().fold( + (vec![], init_immutable_merkle), + |(mut hashes, immutable_merkle), (k, v)| { + let root_hash = immutable_merkle.nodestore.root_hash(); + hashes.push(root_hash); + let mut merkle = immutable_merkle.fork().unwrap(); + merkle.insert(k, v.clone()).unwrap(); + (hashes, merkle.hash()) + }, + ); + + let (new_hashes, _) = items.iter().rev().fold( + (vec![], complete_immutable_merkle), + |(mut new_hashes, immutable_merkle_before_removal), (k, _)| { + let before = immutable_merkle_before_removal.dump_to_string().unwrap(); + let mut merkle = Merkle::from( + NodeStore::new(immutable_merkle_before_removal.nodestore()).unwrap(), + ); + merkle.remove(k).unwrap(); + let immutable_merkle_after_removal: Merkle, _>> = + merkle.try_into().unwrap(); + new_hashes.push(( + immutable_merkle_after_removal.nodestore.root_hash(), + k, + before, + immutable_merkle_after_removal.dump_to_string().unwrap(), + )); + (new_hashes, immutable_merkle_after_removal) + }, + ); + + for (expected_hash, (actual_hash, key, before_removal, after_removal)) in + hashes.into_iter().rev().zip(new_hashes) + { + let key = key.iter().fold(String::new(), |mut s, b| { + let _ = write!(s, "{b:02x}"); + s + }); + assert_eq!( + actual_hash, expected_hash, + "\n\nkey: {key}\nbefore:\n{before_removal}\nafter:\n{after_removal}\n\nexpected:\n{expected_hash:?}\nactual:\n{actual_hash:?}\n", + ); + } + } + + Ok(()) +} + +#[test] +fn remove_nonexistent_with_one() { + let items = [("do", "verb")]; + let mut merkle = init_merkle(items).fork().unwrap(); + + assert_eq!(merkle.remove(b"does_not_exist").unwrap(), None); + assert_eq!(&*merkle.get_value(b"do").unwrap().unwrap(), b"verb"); +} diff --git a/firewood/firewood/src/merkle/tests/proof.rs b/firewood/firewood/src/merkle/tests/proof.rs new file mode 100644 index 000000000000..82ed412fbeb0 --- /dev/null +++ b/firewood/firewood/src/merkle/tests/proof.rs @@ -0,0 +1,305 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use firewood_storage::Preimage; +use firewood_storage::logger::debug; + +use super::*; + +#[test] +fn range_proof_invalid_bounds() { + let merkle = create_in_memory_merkle().hash(); + + let start_key = &[0x01]; + let end_key = &[0x00]; + + match merkle.range_proof(Some(start_key), Some(end_key), NonZeroUsize::new(1)) { + Err(api::Error::InvalidRange { + start_key: first_key, + end_key: last_key, + }) if *first_key == *start_key && *last_key == *end_key => (), + Err(api::Error::InvalidRange { .. }) => panic!("wrong bounds on InvalidRange error"), + _ => panic!("expected InvalidRange error"), + } +} + +#[test] +fn full_range_proof() { + let merkle = init_merkle((u8::MIN..=u8::MAX).map(|k| ([k], [k]))); + + let rangeproof = merkle.range_proof(None, None, None).unwrap(); + assert_eq!(rangeproof.key_values().len(), u8::MAX as usize + 1); + assert_ne!(rangeproof.start_proof(), rangeproof.end_proof()); + let left_proof = merkle.prove(&[u8::MIN]).unwrap(); + let right_proof = merkle.prove(&[u8::MAX]).unwrap(); + assert_eq!(rangeproof.start_proof(), &left_proof); + assert_eq!(rangeproof.end_proof(), &right_proof); + + let rangeproof = roundtrip_range_proof(&rangeproof); + assert_eq!(rangeproof.key_values().len(), u8::MAX as usize + 1); + assert_ne!(rangeproof.start_proof(), rangeproof.end_proof()); + let left_proof = merkle.prove(&[u8::MIN]).unwrap(); + let right_proof = merkle.prove(&[u8::MAX]).unwrap(); + assert_eq!(rangeproof.start_proof(), &left_proof); + assert_eq!(rangeproof.end_proof(), &right_proof); +} + +#[test] +fn single_value_range_proof() { + const RANDOM_KEY: u8 = 42; + + let merkle = init_merkle((u8::MIN..=u8::MAX).map(|k| ([k], [k]))); + + let rangeproof = merkle + .range_proof(Some(&[RANDOM_KEY]), None, NonZeroUsize::new(1)) + .unwrap(); + assert_eq!(rangeproof.start_proof(), rangeproof.end_proof()); + assert_eq!(rangeproof.key_values().len(), 1); + + let rangeproof = roundtrip_range_proof(&rangeproof); + assert_eq!(rangeproof.start_proof(), rangeproof.end_proof()); + assert_eq!(rangeproof.key_values().len(), 1); +} + +#[test] +fn shared_path_proof() { + let key1 = b"key1"; + let value1 = b"1"; + + let key2 = b"key2"; + let value2 = b"2"; + + let merkle = init_merkle([(key1, value1), (key2, value2)]); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + let key = key1; + let proof = merkle.prove(key).unwrap(); + proof.verify(key, Some(value1), &root_hash).unwrap(); + + let key = key2; + let proof = merkle.prove(key).unwrap(); + proof.verify(key, Some(value2), &root_hash).unwrap(); +} + +#[test] +fn single_key_proof_with_one_node() { + let key = b"key"; + let value = b"value"; + + let merkle = init_merkle([(key, value)]); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + let proof = merkle.prove(key).unwrap(); + proof.verify(key, Some(value), &root_hash).unwrap(); +} + +#[test] +fn two_key_proof_without_shared_path() { + let key1 = &[0x00]; + let key2 = &[0xff]; + + let merkle = init_merkle([(key1, key1), (key2, key2)]); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + let proof = merkle.prove(key1).unwrap(); + proof.verify(key1, Some(key1), &root_hash).unwrap(); + + let proof = merkle.prove(key2).unwrap(); + proof.verify(key2, Some(key2), &root_hash).unwrap(); +} + +#[test] +fn test_empty_tree_proof() { + let items: Vec<(&str, &str)> = Vec::new(); + let merkle = init_merkle(items); + let key = "x".as_ref(); + + let proof_err = merkle.prove(key).unwrap_err(); + assert!(matches!(proof_err, ProofError::Empty), "{proof_err:?}"); +} + +#[test] +fn test_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + let set = fixed_and_pseudorandom_data(&rng, 500); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + for (key, val) in items { + let proof = merkle.prove(key).unwrap(); + assert!(!proof.is_empty()); + proof.verify(key, Some(val), &root_hash).unwrap(); + } +} + +#[test] +fn test_proof_end_with_leaf() { + let merkle = init_merkle([ + ("do", "verb"), + ("doe", "reindeer"), + ("dog", "puppy"), + ("doge", "coin"), + ("horse", "stallion"), + ("ddd", "ok"), + ]); + let root_hash = merkle.nodestore().root_hash().unwrap(); + + let key = b"doe"; + + let proof = merkle.prove(key).unwrap(); + assert!(!proof.is_empty()); + + proof.verify(key, Some(b"reindeer"), &root_hash).unwrap(); +} + +#[test] +fn test_proof_end_with_branch() { + let items = [ + ("d", "verb"), + ("do", "verb"), + ("doe", "reindeer"), + ("e", "coin"), + ]; + let merkle = init_merkle(items); + let root_hash = merkle.nodestore().root_hash().unwrap(); + + let key = b"d"; + + let proof = merkle.prove(key).unwrap(); + assert!(!proof.is_empty()); + + proof.verify(key, Some(b"verb"), &root_hash).unwrap(); +} + +#[test] +fn test_bad_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + let set = fixed_and_pseudorandom_data(&rng, 800); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + let root_hash = merkle.nodestore().root_hash().unwrap(); + + for (key, value) in items { + let proof = merkle.prove(key).unwrap(); + assert!(!proof.is_empty()); + + // Delete an entry from the generated proofs. + let mut new_proof = proof.into_mutable(); + new_proof.pop(); + + // TODO: verify error result matches expected error + assert!(new_proof.verify(key, Some(value), &root_hash).is_err()); + } +} + +#[test] +fn exclusion_with_proof_value_present() { + // Build a trie where an ancestor on the path has a value + let mut merkle = crate::merkle::tests::create_in_memory_merkle(); + // Parent has a value + merkle.insert(&[0u8], Box::from([0u8])).unwrap(); + // Child under the same branch + merkle.insert(&[0u8, 1u8], Box::from([1u8])).unwrap(); + + let merkle = merkle.hash(); + let root_hash = merkle.nodestore.root_hash().unwrap(); + debug!("{}", merkle.dump_to_string().unwrap()); + debug!("root_hash: {root_hash:?}"); + + // Non-existent key under the same parent branch + let missing = [0u8, 2u8]; + let proof = merkle.prove(&missing).unwrap(); + + debug!("{proof:#?}"); + assert_eq!( + proof.as_ref().first().unwrap().to_hash(), + root_hash.clone().into_hash_type() + ); + + // Ensure at least one node in the proof carries a value (proof value present) + assert!(proof.as_ref().iter().any(|n| n.value_digest.is_some())); + + // Exclusion should verify with expected None even if proof includes node values + proof + .verify(missing, Option::<&[u8]>::None, &root_hash) + .unwrap(); +} + +#[test] +fn proof_path_construction_and_corruption() { + use crate::proof::{Proof, ProofNode}; + + // Build a trie with several entries + let mut merkle = crate::merkle::tests::create_in_memory_merkle(); + merkle.insert(b"a", Box::from(b"1".as_slice())).unwrap(); + merkle.insert(b"ab", Box::from(b"2".as_slice())).unwrap(); + merkle.insert(b"abc", Box::from(b"3".as_slice())).unwrap(); + merkle.insert(b"abd", Box::from(b"4".as_slice())).unwrap(); + + let merkle = merkle.hash(); + let root_hash = merkle.nodestore.root_hash().unwrap(); + + // Inclusion proof for an existing key + let key = b"abc"; + let val = b"3"; + let proof = merkle.prove(key).unwrap(); + debug!("proof: {proof:#?}"); + debug!("root_hash: {root_hash:?}"); + debug!("{}", merkle.dump_to_string().unwrap()); + + // Positive: check path monotonicity (each node key is a prefix of the next) + let nodes = proof.as_ref(); + for w in nodes.windows(2) { + let cur = w[0].key.as_ref(); + let nxt = w[1].key.as_ref(); + assert!(nxt.starts_with(cur), "proof path not prefix-ordered"); + } + + // Sanity: proof verifies + proof.verify(key, Some(val.as_slice()), &root_hash).unwrap(); + + // Negative: corrupt the path by clearing children of the first node + let mut corrupt: Proof> = proof.clone().into_mutable(); + if let Some(first) = (*corrupt).first_mut() { + // Set all child hashes to empty so traversal fails + first.child_hashes = Children::new(); + } + let corrupt = corrupt.into_immutable(); + let err = corrupt + .verify(key, Some(val.as_slice()), &root_hash) + .unwrap_err(); + // Node traversal should fail + assert!(matches!( + err, + crate::proof::ProofError::NodeNotInTrie | crate::proof::ProofError::UnexpectedHash + )); +} + +#[test] +fn range_proof_serialization_roundtrip() { + let merkle = init_merkle((u8::MIN..=u8::MAX).map(|k| ([k], [k]))); + + let start_key = &[42u8]; + let end_key = &[84u8]; + + let rangeproof = merkle + .range_proof(Some(start_key), Some(end_key), NonZeroUsize::new(10)) + .unwrap(); + + drop(roundtrip_range_proof(&rangeproof)); +} + +fn roundtrip_range_proof(proof: &FrozenRangeProof) -> FrozenRangeProof { + let mut serialized = Vec::new(); + proof.write_to_vec(&mut serialized); + let deserialized = FrozenRangeProof::from_slice(&serialized).unwrap(); + assert_eq!(proof, &deserialized); + deserialized +} diff --git a/firewood/firewood/src/merkle/tests/range.rs b/firewood/firewood/src/merkle/tests/range.rs new file mode 100644 index 000000000000..393bd3bee006 --- /dev/null +++ b/firewood/firewood/src/merkle/tests/range.rs @@ -0,0 +1,973 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use super::*; +use crate::range_proof::RangeProof; + +type KeyValuePairs = Vec<(Box<[u8]>, Box<[u8]>)>; + +#[test] +// Tests that missing keys can also be proven. The test explicitly uses a single +// entry trie and checks for missing keys both before and after the single entry. +fn test_missing_key_proof() { + let items = [("k", "v")]; + let merkle = init_merkle(items); + let root_hash = merkle.nodestore().root_hash().unwrap(); + + for key in ["a", "j", "l", "z"] { + let proof = merkle.prove(key.as_ref()).unwrap(); + assert!(!proof.is_empty()); + assert!(proof.len() == 1); + + proof.verify(key, None::<&[u8]>, &root_hash).unwrap(); + } +} + +#[test] +// Tests normal range proof with both edge proofs as the existent proof. +// The test cases are generated randomly. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 4096); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + for _ in 0..10 { + let start = rng.random_range(0..items.len()); + let end = rng.random_range(0..items.len() - start) + start - 1; + + if end <= start { + continue; + } + + let start_proof = merkle.prove(items[start].0).unwrap(); + let end_proof = merkle.prove(items[end - 1].0).unwrap(); + + let key_values: KeyValuePairs = items[start..end] + .iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof( + Some(items[start].0), + Some(items[end - 1].0), + &root_hash, + &range_proof, + ) + .unwrap(); + } +} + +#[test] +// Tests a few cases which the proof is wrong. +// The prover is expected to detect the error. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_bad_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 4096); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + for _ in 0..10 { + let start = rng.random_range(0..items.len()); + let end = rng.random_range(0..items.len() - start) + start - 1; + + if end <= start { + continue; + } + + let _proof = merkle + .prove(items[start].0) + .unwrap() + .join(merkle.prove(items[end - 1].0).unwrap()); + + let mut keys: Vec<[u8; 32]> = Vec::new(); + let mut vals: Vec<[u8; 20]> = Vec::new(); + for item in &items[start..end] { + keys.push(*item.0); + vals.push(*item.1); + } + + let test_case: u32 = rng.random_range(0..6); + let index = rng.random_range(0..end - start); + match test_case { + 0 => { + // Modified key + keys[index] = rng.random::<[u8; 32]>(); // In theory it can't be same + } + 1 => { + // Modified val + vals[index] = rng.random::<[u8; 20]>(); // In theory it can't be same + } + 2 => { + // Gapped entry slice + if index == 0 || index == end - start - 1 { + continue; + } + keys.remove(index); + vals.remove(index); + } + 3 => { + // Out of order + let index_1 = rng.random_range(0..end - start); + let index_2 = rng.random_range(0..end - start); + if index_1 == index_2 { + continue; + } + keys.swap(index_1, index_2); + vals.swap(index_1, index_2); + } + 4 => { + // Set random key to empty, do nothing + keys[index] = [0; 32]; + } + 5 => { + // Set random value to nil + vals[index] = [0; 20]; + } + _ => unreachable!(), + } + + let key_values: KeyValuePairs = keys + .iter() + .zip(vals.iter()) + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let start_proof = merkle.prove(items[start].0).unwrap(); + let end_proof = merkle.prove(items[end - 1].0).unwrap(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + assert!( + merkle + .verify_range_proof( + Some(items[start].0), + Some(items[end - 1].0), + &root_hash, + &range_proof, + ) + .is_err() + ); + } +} + +#[test] +// Tests normal range proof with two non-existent proofs. +// The test cases are generated randomly. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_range_proof_with_non_existent_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 4096); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + for _ in 0..10 { + let start = rng.random_range(0..items.len()); + let end = rng.random_range(0..items.len() - start) + start - 1; + + if end <= start { + continue; + } + + // Short circuit if the decreased key is same with the previous key + let first = decrease_key(items[start].0); + if start != 0 && first.as_ref() == items[start - 1].0.as_ref() { + continue; + } + // Short circuit if the decreased key is underflow + if &first > items[start].0 { + continue; + } + // Short circuit if the increased key is same with the next key + let last = increase_key(items[end - 1].0); + if end != items.len() && last.as_ref() == items[end].0.as_ref() { + continue; + } + // Short circuit if the increased key is overflow + if &last < items[end - 1].0 { + continue; + } + + let start_proof = merkle.prove(&first).unwrap(); + let end_proof = merkle.prove(&last).unwrap(); + + let key_values: KeyValuePairs = items[start..end] + .iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof(Some(&first), Some(&last), &root_hash, &range_proof) + .unwrap(); + } + + // Special case, two edge proofs for two edge key. + let first = &[0; 32]; + let last = &[255; 32]; + + let start_proof = merkle.prove(first).unwrap(); + let end_proof = merkle.prove(last).unwrap(); + + let key_values: KeyValuePairs = items + .into_iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof(Some(first), Some(last), &root_hash, &range_proof) + .unwrap(); +} + +#[test] +// Tests such scenarios: +// - There exists a gap between the first element and the left edge proof +// - There exists a gap between the last element and the right edge proof +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_range_proof_with_invalid_non_existent_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 4096); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + // Case 1 + let mut start = 100; + let mut end = 200; + let first = decrease_key(items[start].0); + + let start_proof = merkle.prove(&first).unwrap(); + let end_proof = merkle.prove(items[end - 1].0).unwrap(); + + start = 105; // Gap created + let key_values: KeyValuePairs = items[start..end] + .iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + assert!( + merkle + .verify_range_proof( + Some(&first), + Some(items[end - 1].0), + &root_hash, + &range_proof, + ) + .is_err() + ); + + // Case 2 + start = 100; + end = 200; + let last = increase_key(items[end - 1].0); + + let start_proof_2 = merkle.prove(items[start].0).unwrap(); + let end_proof_2 = merkle.prove(&last).unwrap(); + + end = 195; // Capped slice + let key_values_2: KeyValuePairs = items[start..end] + .iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof_2 = + RangeProof::new(start_proof_2, end_proof_2, key_values_2.into_boxed_slice()); + + let root_hash_2 = merkle.nodestore().root_hash().unwrap(); + + assert!( + merkle + .verify_range_proof( + Some(items[start].0), + Some(&last), + &root_hash_2, + &range_proof_2, + ) + .is_err() + ); +} + +#[test] +// Tests the proof with only one element. The first edge proof can be existent one or +// non-existent one. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_one_element_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 4096); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + // One element with existent edge proof, both edge proofs + // point to the SAME key. + let start = 1000; + let proof = merkle.prove(items[start].0).unwrap(); + assert!(!proof.is_empty()); + + let key_values = vec![( + items[start].0.to_vec().into_boxed_slice(), + items[start].1.to_vec().into_boxed_slice(), + )]; + + let range_proof = RangeProof::new( + proof.clone(), // Same proof for start and end + proof, + key_values.into_boxed_slice(), + ); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof( + Some(items[start].0), + Some(items[start].0), + &root_hash, + &range_proof, + ) + .unwrap(); + + // One element with left non-existent edge proof + let first = decrease_key(items[start].0); + let start_proof_2 = merkle.prove(&first).unwrap(); + let end_proof_2 = merkle.prove(items[start].0).unwrap(); + + let key_values_2 = vec![( + items[start].0.to_vec().into_boxed_slice(), + items[start].1.to_vec().into_boxed_slice(), + )]; + + let range_proof_2 = + RangeProof::new(start_proof_2, end_proof_2, key_values_2.into_boxed_slice()); + + merkle + .verify_range_proof( + Some(&first), + Some(items[start].0), + &root_hash, + &range_proof_2, + ) + .unwrap(); + + // One element with right non-existent edge proof + let last = increase_key(items[start].0); + let start_proof_3 = merkle.prove(items[start].0).unwrap(); + let end_proof_3 = merkle.prove(&last).unwrap(); + + let key_values_3 = vec![( + items[start].0.to_vec().into_boxed_slice(), + items[start].1.to_vec().into_boxed_slice(), + )]; + + let range_proof_3 = + RangeProof::new(start_proof_3, end_proof_3, key_values_3.into_boxed_slice()); + + merkle + .verify_range_proof( + Some(items[start].0), + Some(&last), + &root_hash, + &range_proof_3, + ) + .unwrap(); + + // One element with two non-existent edge proofs + let start_proof_4 = merkle.prove(&first).unwrap(); + let end_proof_4 = merkle.prove(&last).unwrap(); + + let key_values_4 = vec![( + items[start].0.to_vec().into_boxed_slice(), + items[start].1.to_vec().into_boxed_slice(), + )]; + + let range_proof_4 = + RangeProof::new(start_proof_4, end_proof_4, key_values_4.into_boxed_slice()); + + merkle + .verify_range_proof(Some(&first), Some(&last), &root_hash, &range_proof_4) + .unwrap(); + + // Test the mini trie with only a single element. + let key = rng.random::<[u8; 32]>(); + let val = rng.random::<[u8; 20]>(); + let merkle_mini = init_merkle(vec![(key, val)]); + + let first = &[0; 32]; + let start_proof_5 = merkle_mini.prove(first).unwrap(); + let end_proof_5 = merkle_mini.prove(&key).unwrap(); + + let key_values_5 = vec![( + key.to_vec().into_boxed_slice(), + val.to_vec().into_boxed_slice(), + )]; + + let range_proof_5 = + RangeProof::new(start_proof_5, end_proof_5, key_values_5.into_boxed_slice()); + + let root_hash_mini = merkle_mini.nodestore().root_hash().unwrap(); + + merkle_mini + .verify_range_proof(Some(first), Some(&key), &root_hash_mini, &range_proof_5) + .unwrap(); +} + +#[test] +// Tests the range proof with all elements. +// The edge proofs can be nil. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_all_elements_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 4096); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + let item_iter = items.clone().into_iter(); + let _keys: Vec<&[u8]> = item_iter.clone().map(|item| item.0.as_ref()).collect(); + let _vals: Vec<&[u8; 20]> = item_iter.map(|item| item.1).collect(); + + let empty_proof = Proof::empty(); + let empty_key: [u8; 32] = [0; 32]; + + let key_values: KeyValuePairs = items + .iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new( + empty_proof.clone(), + empty_proof, + key_values.into_boxed_slice(), + ); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof(Some(&empty_key), Some(&empty_key), &root_hash, &range_proof) + .unwrap(); + + // With edge proofs, it should still work. + let start = 0; + let end = &items.len() - 1; + let start_proof_2 = merkle.prove(items[start].0).unwrap(); + let end_proof_2 = merkle.prove(items[end].0).unwrap(); + + let key_values_2: KeyValuePairs = items + .iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof_2 = + RangeProof::new(start_proof_2, end_proof_2, key_values_2.into_boxed_slice()); + + merkle + .verify_range_proof( + Some(items[start].0), + Some(items[end].0), + &root_hash, + &range_proof_2, + ) + .unwrap(); + + // Even with non-existent edge proofs, it should still work. + let first = &[0; 32]; + let last = &[255; 32]; + let start_proof_3 = merkle.prove(first).unwrap(); + let end_proof_3 = merkle.prove(last).unwrap(); + + let key_values_3: KeyValuePairs = items + .iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof_3 = + RangeProof::new(start_proof_3, end_proof_3, key_values_3.into_boxed_slice()); + + merkle + .verify_range_proof(Some(first), Some(last), &root_hash, &range_proof_3) + .unwrap(); +} + +#[test] +// Tests the range proof with "no" element. The first edge proof must +// be a non-existent proof. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_empty_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 4096); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + let cases = [(items.len() - 1, false)]; + for c in &cases { + let first = increase_key(items[c.0].0); + let proof = merkle.prove(&first).unwrap(); + assert!(!proof.is_empty()); + + // key and value vectors are intentionally empty. + let key_values: KeyValuePairs = Vec::new(); + + let range_proof = RangeProof::new(proof.clone(), proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + if c.1 { + assert!( + merkle + .verify_range_proof(Some(&first), Some(&first), &root_hash, &range_proof,) + .is_err() + ); + } else { + merkle + .verify_range_proof(Some(&first), Some(&first), &root_hash, &range_proof) + .unwrap(); + } + } +} + +#[test] +// Focuses on the small trie with embedded nodes. If the gapped +// node is embedded in the trie, it should be detected too. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_gapped_range_proof() { + let mut items = Vec::new(); + // Sorted entries + for i in 0..10_u32 { + let mut key = [0; 32]; + for (index, d) in i.to_be_bytes().iter().enumerate() { + key[index] = *d; + } + items.push((key, i.to_be_bytes())); + } + let merkle = init_merkle(items.clone()); + + let first = 2; + let last = 8; + let start_proof = merkle.prove(&items[first].0).unwrap(); + let end_proof = merkle.prove(&items[last - 1].0).unwrap(); + + let middle = usize::midpoint(first, last) - first; + let key_values: KeyValuePairs = items[first..last] + .iter() + .enumerate() + .filter(|(pos, _)| *pos != middle) + .map(|(_, item)| { + ( + item.0.to_vec().into_boxed_slice(), + item.1.to_vec().into_boxed_slice(), + ) + }) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + assert!( + merkle + .verify_range_proof( + Some(&items[0].0), + Some(&items[items.len() - 1].0), + &root_hash, + &range_proof, + ) + .is_err() + ); +} + +#[test] +// Tests the element is not in the range covered by proofs. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_same_side_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 4096); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + let pos = 1000; + let mut last = decrease_key(items[pos].0); + let mut first = last; + first = decrease_key(&first); + + let start_proof = merkle.prove(&first).unwrap(); + let end_proof = merkle.prove(&last).unwrap(); + + let key_values = vec![( + items[pos].0.to_vec().into_boxed_slice(), + items[pos].1.to_vec().into_boxed_slice(), + )]; + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + assert!( + merkle + .verify_range_proof(Some(&first), Some(&last), &root_hash, &range_proof,) + .is_err() + ); + + first = increase_key(items[pos].0); + last = first; + last = increase_key(&last); + + let start_proof_2 = merkle.prove(&first).unwrap(); + let end_proof_2 = merkle.prove(&last).unwrap(); + + let key_values_2 = vec![( + items[pos].0.to_vec().into_boxed_slice(), + items[pos].1.to_vec().into_boxed_slice(), + )]; + + let range_proof_2 = + RangeProof::new(start_proof_2, end_proof_2, key_values_2.into_boxed_slice()); + + assert!( + merkle + .verify_range_proof(Some(&first), Some(&last), &root_hash, &range_proof_2,) + .is_err() + ); +} + +#[test] +// Tests the range starts from zero. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_single_side_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + for _ in 0..10 { + let mut set = HashMap::new(); + for _ in 0..4096_u32 { + let key = rng.random::<[u8; 32]>(); + let val = rng.random::<[u8; 20]>(); + set.insert(key, val); + } + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + let cases = vec![0, 1, 100, 1000, items.len() - 1]; + for case in cases { + let start = &[0; 32]; + let start_proof = merkle.prove(start).unwrap(); + let end_proof = merkle.prove(items[case].0).unwrap(); + + let key_values: KeyValuePairs = items + .iter() + .take(case + 1) + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = + RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof(Some(start), Some(items[case].0), &root_hash, &range_proof) + .unwrap(); + } + } +} + +#[test] +// Tests the range ends with 0xffff...fff. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_reverse_single_side_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + for _ in 0..10 { + let mut set = HashMap::new(); + for _ in 0..1024_u32 { + let key = rng.random::<[u8; 32]>(); + let val = rng.random::<[u8; 20]>(); + set.insert(key, val); + } + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + let cases = vec![0, 1, 100, 1000, items.len() - 1]; + for case in cases { + let end = &[255; 32]; + + let start_proof = merkle.prove(items[case].0).unwrap(); + let end_proof = merkle.prove(end).unwrap(); + + let key_values: KeyValuePairs = items + .iter() + .skip(case) + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = + RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof(Some(items[case].0), Some(end), &root_hash, &range_proof) + .unwrap(); + } + } +} + +#[test] +// Tests the range starts with zero and ends with 0xffff...fff. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_both_sides_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + for _ in 0..10 { + let mut set = HashMap::new(); + for _ in 0..4096_u32 { + let key = rng.random::<[u8; 32]>(); + let val = rng.random::<[u8; 20]>(); + set.insert(key, val); + } + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + let start = &[0; 32]; + let end = &[255; 32]; + let start_proof = merkle.prove(start).unwrap(); + let end_proof = merkle.prove(end).unwrap(); + + let key_values: KeyValuePairs = items + .into_iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof(Some(start), Some(end), &root_hash, &range_proof) + .unwrap(); + } +} + +#[test] +// Tests normal range proof with both edge proofs +// as the existent proof, but with an extra empty value included, which is a +// noop technically, but practically should be rejected. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_empty_value_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 512); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + // Create a new entry with a slightly modified key + let mid_index = items.len() / 2; + let key = increase_key(items[mid_index - 1].0); + let empty_value: [u8; 20] = [0; 20]; + items.splice(mid_index..mid_index, [(&key, &empty_value)].iter().copied()); + + let start = 1; + let end = items.len() - 1; + + let start_proof = merkle.prove(items[start].0).unwrap(); + let end_proof = merkle.prove(items[end - 1].0).unwrap(); + + let key_values: KeyValuePairs = items + .iter() + .skip(start) + .take(end - start) + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + assert!( + merkle + .verify_range_proof( + Some(items[start].0), + Some(items[end - 1].0), + &root_hash, + &range_proof, + ) + .is_err() + ); +} + +#[test] +// Tests the range proof with all elements, +// but with an extra empty value included, which is a noop technically, but +// practically should be rejected. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_all_elements_empty_value_range_proof() { + let rng = firewood_storage::SeededRng::from_env_or_random(); + + let set = fixed_and_pseudorandom_data(&rng, 512); + let mut items = set.iter().collect::>(); + items.sort_unstable(); + let merkle = init_merkle(items.clone()); + + // Create a new entry with a slightly modified key + let mid_index = items.len() / 2; + let key = increase_key(items[mid_index - 1].0); + let empty_value: [u8; 20] = [0; 20]; + items.splice(mid_index..mid_index, [(&key, &empty_value)].iter().copied()); + + let start = 0; + let end = items.len() - 1; + + let start_proof = merkle.prove(items[start].0).unwrap(); + let end_proof = merkle.prove(items[end].0).unwrap(); + + let key_values: KeyValuePairs = items + .iter() + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + assert!( + merkle + .verify_range_proof( + Some(items[start].0), + Some(items[end].0), + &root_hash, + &range_proof, + ) + .is_err() + ); +} + +#[test] +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_range_proof_keys_with_shared_prefix() { + let items = vec![ + ( + hex::decode("aa10000000000000000000000000000000000000000000000000000000000000") + .expect("Decoding failed"), + hex::decode("02").expect("Decoding failed"), + ), + ( + hex::decode("aa20000000000000000000000000000000000000000000000000000000000000") + .expect("Decoding failed"), + hex::decode("03").expect("Decoding failed"), + ), + ]; + let merkle = init_merkle(items.clone()); + + let start = hex::decode("0000000000000000000000000000000000000000000000000000000000000000") + .expect("Decoding failed"); + let end = hex::decode("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + .expect("Decoding failed"); + + let start_proof = merkle.prove(&start).unwrap(); + let end_proof = merkle.prove(&end).unwrap(); + + let key_values: KeyValuePairs = items + .iter() + .map(|(k, v)| (k.clone().into_boxed_slice(), v.clone().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof(Some(&start), Some(&end), &root_hash, &range_proof) + .unwrap(); +} + +#[test] +// Tests a malicious proof, where the proof is more or less the +// whole trie. This is to match corresponding test in geth. +#[ignore = "https://github.com/ava-labs/firewood/issues/738"] +fn test_bloadted_range_proof() { + // Use a small trie + let mut items = Vec::new(); + for i in 0..100_u32 { + let mut key: [u8; 32] = [0; 32]; + let mut value: [u8; 20] = [0; 20]; + for (index, d) in i.to_be_bytes().iter().enumerate() { + key[index] = *d; + value[index] = *d; + } + items.push((key, value)); + } + let merkle = init_merkle(items.clone()); + + // In the 'malicious' case, we add proofs for every single item + // (but only one key/value pair used as leaf) + let mut proof = Proof::empty().into_mutable(); + let mut keys = Vec::new(); + let mut vals = Vec::new(); + for (i, item) in items.iter().enumerate() { + let cur_proof = merkle.prove(&item.0).unwrap(); + assert!(!cur_proof.is_empty()); + proof.extend(cur_proof); + if i == 50 { + keys.push(item.0.as_ref()); + vals.push(item.1); + } + } + + // Create start and end proofs (same key in this case since only one key-value pair) + let start_proof = merkle.prove(keys[0]).unwrap(); + let end_proof = merkle.prove(keys[keys.len() - 1]).unwrap(); + + // Convert to the format expected by RangeProof + let key_values: KeyValuePairs = keys + .iter() + .zip(vals.iter()) + .map(|(k, v)| (k.to_vec().into_boxed_slice(), v.to_vec().into_boxed_slice())) + .collect(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values.into_boxed_slice()); + + let root_hash = merkle.nodestore().root_hash().unwrap(); + + merkle + .verify_range_proof( + Some(keys[0]), + Some(keys[keys.len() - 1]), + &root_hash, + &range_proof, + ) + .unwrap(); +} diff --git a/firewood/firewood/src/merkle/tests/triehash.rs b/firewood/firewood/src/merkle/tests/triehash.rs new file mode 100644 index 000000000000..3e2a2a1e623b --- /dev/null +++ b/firewood/firewood/src/merkle/tests/triehash.rs @@ -0,0 +1,28 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use super::*; +use test_case::test_case; + +#[test_case(vec![], None; "empty trie")] +#[test_case(vec![(&[0],&[0])], Some("073615413d814b23383fc2c8d8af13abfffcb371b654b98dbf47dd74b1e4d1b9"); "root")] +#[test_case(vec![(&[0,1],&[0,1])], Some("28e67ae4054c8cdf3506567aa43f122224fe65ef1ab3e7b7899f75448a69a6fd"); "root with partial path")] +#[test_case(vec![(&[0],&[1;32])], Some("ba0283637f46fa807280b7d08013710af08dfdc236b9b22f9d66e60592d6c8a3"); "leaf value >= 32 bytes")] +#[test_case(vec![(&[0],&[0]),(&[0,1],&[1;32])], Some("3edbf1fdd345db01e47655bcd0a9a456857c4093188cf35c5c89b8b0fb3de17e"); "branch value >= 32 bytes")] +#[test_case(vec![(&[0],&[0]),(&[0,1],&[0,1])], Some("c3bdc20aff5cba30f81ffd7689e94e1dbeece4a08e27f0104262431604cf45c6"); "root with leaf child")] +#[test_case(vec![(&[0],&[0]),(&[0,1],&[0,1]),(&[0,1,2],&[0,1,2])], Some("229011c50ad4d5c2f4efe02b8db54f361ad295c4eee2bf76ea4ad1bb92676f97"); "root with branch child")] +#[test_case(vec![(&[0],&[0]),(&[0,1],&[0,1]),(&[0,8],&[0,8]),(&[0,1,2],&[0,1,2])], Some("a683b4881cb540b969f885f538ba5904699d480152f350659475a962d6240ef9"); "root with branch child and leaf child")] +fn test_root_hash_merkledb_compatible(kvs: Vec<(&[u8], &[u8])>, expected_hash: Option<&str>) { + let merkle = init_merkle(kvs); + let Some(got_hash) = merkle.nodestore.root_hash() else { + assert!(expected_hash.is_none()); + return; + }; + + let expected_hash = expected_hash.unwrap(); + + // This hash is from merkledb + let expected_hash: [u8; 32] = hex::decode(expected_hash).unwrap().try_into().unwrap(); + + assert_eq!(got_hash, TrieHash::from(expected_hash)); +} diff --git a/firewood/firewood/src/proof.rs b/firewood/firewood/src/proof.rs new file mode 100644 index 000000000000..251f47fc4ca5 --- /dev/null +++ b/firewood/firewood/src/proof.rs @@ -0,0 +1,418 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::missing_errors_doc, + reason = "Found 1 occurrences after enabling the lint." +)] + +use firewood_storage::{ + Children, FileIoError, HashType, Hashable, IntoHashType, IntoSplitPath, NibblesIterator, Path, + PathBuf, PathComponent, PathIterItem, Preimage, SplitPath, TrieHash, TriePath, ValueDigest, +}; +use thiserror::Error; + +use crate::merkle::Value; + +#[derive(Debug, Error)] +#[non_exhaustive] +/// Reasons why a proof is invalid +pub enum ProofError { + /// Non-monotonic range decrease + #[error("non-monotonic range increase")] + NonMonotonicIncreaseRange, + + /// Unexpected hash + #[error("unexpected hash")] + UnexpectedHash, + + /// Unexpected value + #[error("unexpected value")] + UnexpectedValue, + + /// Value mismatch + #[error("value mismatch")] + ValueMismatch, + + /// Expected value but got None + #[error("expected value but got None")] + ExpectedValue, + + /// Proof is empty + #[error("proof can't be empty")] + Empty, + + /// Each proof node key should be a prefix of the proven key + #[error("each proof node key should be a prefix of the proven key")] + ShouldBePrefixOfProvenKey, + + /// Each proof node key should be a prefix of the next key + #[error("each proof node key should be a prefix of the next key")] + ShouldBePrefixOfNextKey, + + /// Child index is out of bounds + #[error("child index is out of bounds")] + ChildIndexOutOfBounds, + + /// Only nodes with even length key can have values + #[error("only nodes with even length key can have values")] + ValueAtOddNibbleLength, + + /// Node not in trie + #[error("node not in trie")] + NodeNotInTrie, + + /// Error from the merkle package + #[error("{0:?}")] + IO(#[from] FileIoError), + + /// Error deserializing a proof + #[error("error deserializing a proof: {0}")] + Deserialization(crate::proofs::ReadError), + + /// Empty range + #[error("empty range")] + EmptyRange, +} + +#[derive(Clone, PartialEq, Eq)] +#[non_exhaustive] +/// A node in a proof. +pub struct ProofNode { + /// The key this node is at. Each byte is a nibble. + pub key: PathBuf, + /// The length of the key prefix that is shared with the previous node. + pub partial_len: usize, + /// None if the node does not have a value. + /// Otherwise, the node's value or the hash of its value. + pub value_digest: Option>, + /// The hash of each child, or None if the child does not exist. + pub child_hashes: Children>, +} + +impl std::fmt::Debug for ProofNode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + // Filter the missing children and only show the present ones with their indices + let child_hashes = self.child_hashes.iter_present().collect::>(); + // Compute the hash and render it as well + let hash = firewood_storage::Preimage::to_hash(self); + + f.debug_struct("ProofNode") + .field("key", &self.key) + .field("partial_len", &self.partial_len) + .field("value_digest", &self.value_digest) + .field("child_hashes", &child_hashes) + .field("hash", &hash) + .finish() + } +} + +impl Hashable for ProofNode { + type LeadingPath<'a> + = &'a [PathComponent] + where + Self: 'a; + + type PartialPath<'a> + = &'a [PathComponent] + where + Self: 'a; + + type FullPath<'a> + = &'a [PathComponent] + where + Self: 'a; + + fn parent_prefix_path(&self) -> Self::LeadingPath<'_> { + let (prefix, _) = self.key.split_at(self.partial_len); + prefix + } + + fn partial_path(&self) -> Self::PartialPath<'_> { + let (_, suffix) = self.key.split_at(self.partial_len); + suffix + } + + fn full_path(&self) -> Self::FullPath<'_> { + &self.key + } + + fn value_digest(&self) -> Option> { + self.value_digest.as_ref().map(ValueDigest::as_ref) + } + + fn children(&self) -> Children> { + self.child_hashes.clone() + } +} + +impl From for ProofNode { + fn from(item: PathIterItem) -> Self { + let child_hashes = if let Some(branch) = item.node.as_branch() { + branch.children_hashes() + } else { + Children::new() + }; + + let partial_len = item + .key_nibbles + .len() + .saturating_sub(item.node.partial_path().len()); + + Self { + key: item.key_nibbles, + partial_len, + value_digest: item + .node + .value() + .map(|value| ValueDigest::Value(value.to_vec().into_boxed_slice())), + child_hashes, + } + } +} + +/// A proof that a given key-value pair either exists or does not exist in a trie. +#[derive(Clone, Debug, PartialEq, Eq, Default)] +pub struct Proof(T); + +impl Proof { + /// Verify a proof + pub fn verify, V: AsRef<[u8]>>( + &self, + key: K, + expected_value: Option, + root_hash: &TrieHash, + ) -> Result<(), ProofError> { + verify_opt_value_digest(expected_value, self.value_digest(key, root_hash)?) + } + + /// Returns the value digest associated with the given `key` in the trie revision + /// with the given `root_hash`. If the key does not exist in the trie, returns `None`. + /// Returns an error if the proof is invalid or doesn't prove the key for the + /// given revision. + pub fn value_digest>( + &self, + key: K, + root_hash: &TrieHash, + ) -> Result>, ProofError> { + let key = Path(NibblesIterator::new(key.as_ref()).collect()); + + let Some(last_node) = self.0.as_ref().last() else { + return Err(ProofError::Empty); + }; + + let mut expected_hash = root_hash.clone().into_hash_type(); + + let mut iter = self.0.as_ref().iter().peekable(); + while let Some(node) = iter.next() { + if node.to_hash() != expected_hash { + return Err(ProofError::UnexpectedHash); + } + + // Assert that only nodes whose keys are an even number of nibbles + // have a `value_digest`. + #[cfg(not(feature = "branch_factor_256"))] + if !node.full_path().len().is_multiple_of(2) && node.value_digest().is_some() { + return Err(ProofError::ValueAtOddNibbleLength); + } + + if let Some(next_node) = iter.peek() { + // Assert that every node's key is a prefix of `key`, except for the last node, + // whose key can be equal to or a suffix of `key` in an exclusion proof. + if next_nibble(node.full_path(), key.as_components()).is_none() { + return Err(ProofError::ShouldBePrefixOfProvenKey); + } + + // Assert that every node's key is a prefix of the next node's key. + let next_node_index = next_nibble(node.full_path(), next_node.full_path()); + + let Some(next_nibble) = next_node_index else { + return Err(ProofError::ShouldBePrefixOfNextKey); + }; + + expected_hash = node.children()[next_nibble] + .as_ref() + .ok_or(ProofError::NodeNotInTrie)? + .clone(); + } + } + + if last_node.full_path().path_eq(key.as_components()) { + return Ok(last_node.value_digest()); + } + + // This is an exclusion proof. + Ok(None) + } + + /// Returns the length of the proof. + #[must_use] + pub fn len(&self) -> usize { + self.0.as_ref().len() + } + + /// Returns true if the proof is empty. + #[must_use] + pub fn is_empty(&self) -> bool { + self.0.as_ref().is_empty() + } +} + +impl std::ops::Deref for Proof { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::DerefMut for Proof { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Proof { + /// Constructs a new proof from a collection of proof nodes. + #[inline] + #[must_use] + pub const fn new(proof: T) -> Self { + Self(proof) + } +} + +impl Proof { + /// Constructs a new empty proof. + #[inline] + #[must_use] + pub const fn empty() -> Self { + Self::new(EmptyProofCollection) + } + + /// Converts an empty immutable proof into an empty mutable proof. + #[inline] + #[must_use] + pub const fn into_mutable(self) -> Proof> { + Proof::new(Vec::new()) + } +} + +impl Proof> { + /// Converts an immutable proof into a mutable proof. + #[inline] + #[must_use] + pub fn into_mutable(self) -> Proof> { + Proof::new(self.0.into_vec()) + } +} + +impl Proof> { + /// Converts a mutable proof into an immutable proof. + #[inline] + #[must_use] + pub fn into_immutable(self) -> Proof> { + Proof::new(self.0.into_boxed_slice()) + } +} + +impl Proof +where + T: Hashable, + V: ProofCollection + IntoIterator + FromIterator, +{ + /// Joins two proofs into one. + #[inline] + #[must_use] + pub fn join + IntoIterator>( + self, + other: Proof, + ) -> Proof { + self.into_iter().chain(other).collect() + } +} + +impl> FromIterator for Proof { + #[inline] + fn from_iter>(iter: I) -> Self { + Proof(iter.into_iter().collect()) + } +} + +impl> Extend for Proof { + #[inline] + fn extend>(&mut self, iter: I) { + self.0.extend(iter); + } +} + +impl> IntoIterator for Proof { + type Item = V::Node; + type IntoIter = V::IntoIter; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +/// A trait representing a collection of proof nodes. +/// +/// This allows [`Proof`] to be generic over different types of collections such +/// a `Box<[T]>` or `Vec`, where `T` implements the `Hashable` trait. +pub trait ProofCollection: AsRef<[Self::Node]> { + /// The type of nodes in the proof collection. + type Node: Hashable; +} + +impl ProofCollection for [T] { + type Node = T; +} + +impl ProofCollection for Box<[T]> { + type Node = T; +} + +impl ProofCollection for Vec { + type Node = T; +} + +/// A zero-sized type to represent an empty proof collection. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct EmptyProofCollection; + +impl AsRef<[ProofNode]> for EmptyProofCollection { + #[inline] + fn as_ref(&self) -> &[ProofNode] { + &[] + } +} + +impl ProofCollection for EmptyProofCollection { + type Node = ProofNode; +} + +/// Returns the next nibble in `c` after `b`. +/// Returns None if `b` is not a strict prefix of `c`. +fn next_nibble(b: impl IntoSplitPath, c: impl IntoSplitPath) -> Option { + let b = b.into_split_path(); + let c = c.into_split_path(); + match b.longest_common_prefix(c).split_first_parts() { + (None, Some((c, _)), _) => Some(c), + _ => None, + } +} + +fn verify_opt_value_digest( + expected_value: Option>, + found_value: Option>>, +) -> Result<(), ProofError> { + match (expected_value, found_value) { + (None, None) => Ok(()), + (Some(_), None) => Err(ProofError::ExpectedValue), + (None, Some(_)) => Err(ProofError::UnexpectedValue), + (Some(ref expected), Some(found)) if found.verify(expected) => Ok(()), + (Some(_), Some(_)) => Err(ProofError::ValueMismatch), + } +} diff --git a/firewood/firewood/src/proofs.rs b/firewood/firewood/src/proofs.rs new file mode 100644 index 000000000000..6ab58f28f9e3 --- /dev/null +++ b/firewood/firewood/src/proofs.rs @@ -0,0 +1,45 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +mod bitmap; +mod de; +mod header; +mod proof_type; +mod reader; +mod ser; +#[cfg(test)] +mod tests; + +pub use self::header::InvalidHeader; +pub use self::reader::ReadError; + +mod magic { + pub const PROOF_HEADER: &[u8; 8] = b"fwdproof"; + + pub const PROOF_VERSION: u8 = 0; + + #[cfg(not(feature = "ethhash"))] + pub const HASH_MODE: u8 = 0; + #[cfg(feature = "ethhash")] + pub const HASH_MODE: u8 = 1; + + pub const fn hash_mode_name(v: u8) -> &'static str { + match v { + 0 => "sha256", + 1 => "keccak256", + _ => "unknown", + } + } + + #[cfg(not(feature = "branch_factor_256"))] + pub const BRANCH_FACTOR: u8 = 16; + #[cfg(feature = "branch_factor_256")] + pub const BRANCH_FACTOR: u8 = 0; // 256 wrapped to 0 + + pub const fn widen_branch_factor(v: u8) -> u16 { + match v { + 0 => 256, + _ => v as u16, + } + } +} diff --git a/firewood/firewood/src/proofs/bitmap.rs b/firewood/firewood/src/proofs/bitmap.rs new file mode 100644 index 000000000000..2ae53df87ec0 --- /dev/null +++ b/firewood/firewood/src/proofs/bitmap.rs @@ -0,0 +1,131 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use firewood_storage::{Children, PathComponent}; + +#[derive(Clone, Copy, PartialEq, Eq, bytemuck_derive::Pod, bytemuck_derive::Zeroable)] +#[repr(C)] +/// A bitmap indicating which children are present in a node. +pub(super) struct ChildrenMap([u8; ChildrenMap::SIZE]); + +impl ChildrenMap { + const SIZE: usize = firewood_storage::BranchNode::MAX_CHILDREN / 8; + + /// Create a new `ChildrenMap` from the given children array. + pub fn new(children: &Children>) -> Self { + let mut map = Self([0_u8; Self::SIZE]); + + for (i, _) in children.iter_present() { + map.set(i); + } + + map + } + + #[cfg(test)] + pub fn len(self) -> usize { + self.0.iter().map(|b| b.count_ones() as usize).sum() + } + + pub const fn get(self, index: PathComponent) -> bool { + #![expect(clippy::indexing_slicing)] + let i = index.as_usize(); + self.0[i / 8] & (1 << (i % 8)) != 0 + } + + pub const fn set(&mut self, index: PathComponent) { + #![expect(clippy::indexing_slicing)] + let i = index.as_usize(); + self.0[i / 8] |= 1 << (i % 8); + } + + pub fn iter_indices(self) -> impl Iterator { + PathComponent::ALL.into_iter().filter(move |&i| self.get(i)) + } +} + +impl std::fmt::Display for ChildrenMap { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + f.debug_list().entries(self.iter_indices()).finish() + } else { + write!(f, "{self:b}") + } + } +} + +#[cfg(not(feature = "branch_factor_256"))] +impl std::fmt::Binary for ChildrenMap { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:016b}", u16::from_le_bytes(self.0)) + } +} + +#[cfg(feature = "branch_factor_256")] +impl std::fmt::Binary for ChildrenMap { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let [a, b] = bytemuck::cast::<_, [[u8; 16]; 2]>(self.0); + let a = u128::from_le_bytes(a); + let b = u128::from_le_bytes(b); + write!(f, "{a:0128b}{b:0128b}") + } +} + +impl std::fmt::Debug for ChildrenMap { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(self, f) + } +} + +#[cfg(test)] +mod tests { + #![expect(clippy::unwrap_used)] + + use super::*; + + use firewood_storage::{Children, PathComponent}; + use test_case::test_case; + + #[test_case(Children::new(), &[]; "empty")] + #[test_case({ + let mut children = Children::new(); + children[PathComponent::ALL[0]] = Some(()); + children + }, &[PathComponent::ALL[0]]; "first")] + #[test_case({ + let mut children = Children::new(); + children[PathComponent::ALL[1]] = Some(()); + children + }, &[PathComponent::ALL[1]]; "second")] + #[test_case({ + let mut children = Children::new(); + children[PathComponent::ALL.last().copied().unwrap()] = Some(()); + children + }, &[PathComponent::ALL.last().copied().unwrap()]; "last")] + #[test_case({ + let mut children = Children::new(); + for (_, slot) in children.iter_mut().step_by(2) { + *slot = Some(()); + } + children + }, &PathComponent::ALL.into_iter().step_by(2).collect::>(); "evens")] + #[test_case({ + let mut children = Children::new(); + for (_, slot) in children.iter_mut().skip(1).step_by(2) { + *slot = Some(()); + } + children + }, &PathComponent::ALL.into_iter().skip(1).step_by(2).collect::>(); "odds")] + #[test_case(Children::from_fn(|_| Some(())), &PathComponent::ALL; "all")] + fn test_children_map(children: Children>, indicies: &[PathComponent]) { + let map = ChildrenMap::new(&children); + assert_eq!(map.len(), indicies.len()); + + assert!( + indicies.iter().copied().eq(map.iter_indices()), + "expected {:?}, got {:?}", + indicies, + map.iter_indices().collect::>() + ); + } +} diff --git a/firewood/firewood/src/proofs/de.rs b/firewood/firewood/src/proofs/de.rs new file mode 100644 index 000000000000..95e9e0fdcbc8 --- /dev/null +++ b/firewood/firewood/src/proofs/de.rs @@ -0,0 +1,255 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#[cfg(feature = "ethhash")] +use firewood_storage::HashType; +use firewood_storage::{Children, PathBuf, TrieHash, TriePathFromUnpackedBytes, ValueDigest}; +use integer_encoding::VarInt; + +use crate::{ + proof::{Proof, ProofNode}, + proofs::{ + bitmap::ChildrenMap, + header::{Header, InvalidHeader}, + proof_type::ProofType, + reader::{ProofReader, ReadError, ReadItem, V0Reader, Version0}, + }, + v2::api::FrozenRangeProof, +}; + +impl FrozenRangeProof { + /// Parses a `FrozenRangeProof` from the given byte slice. + /// + /// Currently only V0 proofs are supported. See [`FrozenRangeProof::write_to_vec`] + /// for the serialization format. + /// + /// # Errors + /// + /// Returns a [`ReadError`] if the data is invalid. See the enum variants for + /// the possible reasons. + pub fn from_slice(data: &[u8]) -> Result { + let mut reader = ProofReader::new(data); + + let header = reader.read_item::
()?; + header + .validate(Some(ProofType::Range)) + .map_err(ReadError::InvalidHeader)?; + + match header.version { + 0 => { + let mut reader = V0Reader::new(reader, header); + let this = reader.read_v0_item()?; + if reader.remainder().is_empty() { + Ok(this) + } else { + Err(reader.invalid_item( + "trailing bytes", + "no data after the proof", + format!("{} bytes", reader.remainder().len()), + )) + } + } + found => Err(ReadError::InvalidHeader( + InvalidHeader::UnsupportedVersion { found }, + )), + } + } +} + +impl Version0 for Box<[T]> { + fn read_v0_item(reader: &mut V0Reader<'_>) -> Result { + let num_items = reader + .read_item::() + .map_err(|err| err.set_item("array length"))?; + + // FIXME: we must somehow validate `num_items` matches what is expected + // An incorrect, or unexpectedly large value could lead to DoS via OOM + // or panicing + (0..num_items).map(|_| reader.read_v0_item()).collect() + } +} + +impl Version0 for FrozenRangeProof { + fn read_v0_item(reader: &mut V0Reader<'_>) -> Result { + let start_proof = reader.read_v0_item()?; + let end_proof = reader.read_v0_item()?; + let key_values = reader.read_v0_item()?; + + Ok(Self::new( + Proof::new(start_proof), + Proof::new(end_proof), + key_values, + )) + } +} + +impl Version0 for ProofNode { + fn read_v0_item(reader: &mut V0Reader<'_>) -> Result { + let key = reader.read_v0_item()?; + let partial_len = reader.read_item()?; + let value_digest = reader.read_item()?; + + let children_map = reader.read_item::()?; + + let mut child_hashes = Children::new(); + for idx in children_map.iter_indices() { + child_hashes[idx] = Some(reader.read_item()?); + } + + Ok(ProofNode { + key, + partial_len, + value_digest, + child_hashes, + }) + } +} + +impl Version0 for PathBuf { + fn read_v0_item(reader: &mut V0Reader<'_>) -> Result { + let bytes = reader.read_item::<&[u8]>()?; + TriePathFromUnpackedBytes::path_from_unpacked_bytes(bytes).map_err(|_| { + reader.invalid_item( + "path", + "valid nibbles", + format!("invalid nibbles: {}", hex::encode(bytes)), + ) + }) + } +} + +impl Version0 for (Box<[u8]>, Box<[u8]>) { + fn read_v0_item(reader: &mut V0Reader<'_>) -> Result { + Ok((reader.read_item()?, reader.read_item()?)) + } +} + +impl<'a> ReadItem<'a> for Header { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + reader + .read_chunk::<{ size_of::
() }>() + .map_err(|err| err.set_item("header")) + .copied() + .map(bytemuck::cast) + } +} + +impl<'a> ReadItem<'a> for usize { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + match u64::decode_var(reader.remainder()) { + Some((n, size)) => { + reader.advance(size); + Ok(n as usize) + } + None if reader.remainder().is_empty() => Err(reader.incomplete_item("varint", 1)), + #[expect(clippy::indexing_slicing)] + None => Err(reader.invalid_item( + "varint", + "byte with no MSB within 9 bytes", + format!( + "{:?}", + &reader.remainder()[..reader.remainder().len().min(10)] + ), + )), + } + } +} + +impl<'a> ReadItem<'a> for &'a [u8] { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + let len = reader.read_item::()?; + reader.read_slice(len) + } +} + +impl<'a> ReadItem<'a> for Box<[u8]> { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + reader.read_item::<&[u8]>().map(Box::from) + } +} + +impl<'a> ReadItem<'a> for u8 { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + reader + .read_chunk::<1>() + .map(|&[b]| b) + .map_err(|err| err.set_item("u8")) + } +} + +impl<'a, T: ReadItem<'a>> ReadItem<'a> for Option { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + match reader + .read_item::() + .map_err(|err| err.set_item("option discriminant"))? + { + 0 => Ok(None), + 1 => Ok(Some(reader.read_item::()?)), + found => Err(reader.invalid_item("option discriminant", "0 or 1", found)), + } + } +} + +impl<'a> ReadItem<'a> for ValueDigest<&'a [u8]> { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + match reader + .read_item::() + .map_err(|err| err.set_item("value digest discriminant"))? + { + 0 => Ok(ValueDigest::Value(reader.read_item()?)), + #[cfg(not(feature = "ethhash"))] + 1 => Ok(ValueDigest::Hash(reader.read_item()?)), + found => Err(reader.invalid_item( + "value digest discriminant", + "0 (value) or 1 (hash)", + found, + )), + } + } +} + +impl<'a> ReadItem<'a> for ValueDigest> { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + reader.read_item::>().map(|vd| match vd { + ValueDigest::Value(v) => ValueDigest::Value(v.into()), + #[cfg(not(feature = "ethhash"))] + ValueDigest::Hash(h) => ValueDigest::Hash(h), + }) + } +} + +impl<'a> ReadItem<'a> for TrieHash { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + reader + .read_chunk::<{ size_of::() }>() + .map_err(|err| err.set_item("trie hash")) + .copied() + .map(TrieHash::from) + } +} + +impl<'a> ReadItem<'a> for ChildrenMap { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + reader + .read_chunk::<{ size_of::() }>() + .map_err(|err| err.set_item("children map")) + .copied() + .map(bytemuck::cast) + } +} + +#[cfg(feature = "ethhash")] +impl<'a> ReadItem<'a> for HashType { + fn read_item(reader: &mut ProofReader<'a>) -> Result { + match reader + .read_item::() + .map_err(|err| err.set_item("hash type discriminant"))? + { + 0 => Ok(HashType::Hash(reader.read_item()?)), + 1 => Ok(HashType::Rlp(reader.read_item::<&[u8]>()?.into())), + found => { + Err(reader.invalid_item("hash type discriminant", "0 (hash) or 1 (rlp)", found)) + } + } + } +} diff --git a/firewood/firewood/src/proofs/header.rs b/firewood/firewood/src/proofs/header.rs new file mode 100644 index 000000000000..3fbdbcba4467 --- /dev/null +++ b/firewood/firewood/src/proofs/header.rs @@ -0,0 +1,161 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::proofs::{magic, proof_type::ProofType}; + +/// A fixed-size header at the beginning of every serialized proof. +/// +/// # Format +/// +/// - 8 bytes: A magic value to identify the file type. This is `b"fwdproof"`. +/// - 1 byte: The version of the proof format. Currently `0`. +/// - 1 byte: The hash mode used in the proof. Currently `0` for sha256, `1` for +/// keccak256. +/// - 1 byte: The branching factor of the trie. Currently `16` or `0` for `256`. +/// - 1 byte: The type of proof. See [`ProofType`]. +/// - 20 bytes: Reserved for future use and to pad the header to 32 bytes. Ignored +/// when reading, and set to zero when writing. +#[derive(Debug, Clone, Copy, bytemuck_derive::Pod, bytemuck_derive::Zeroable)] +#[repr(C)] +pub struct Header { + pub(super) magic: [u8; 8], + pub(super) version: u8, + pub(super) hash_mode: u8, + pub(super) branch_factor: u8, + pub(super) proof_type: u8, + pub(super) _reserved: [u8; 20], +} + +const _: () = { + assert!(size_of::
() == 32); +}; + +impl From for Header { + fn from(proof_type: ProofType) -> Self { + Self { + magic: *magic::PROOF_HEADER, + version: magic::PROOF_VERSION, + hash_mode: magic::HASH_MODE, + branch_factor: magic::BRANCH_FACTOR, + proof_type: proof_type as u8, + _reserved: [0; 20], + } + } +} + +impl Header { + /// Validates the header, returning the discovered proof type if valid. + /// + /// If `expected_type` is `Some`, the proof type must match (in which case the return + /// value can be ignored). + /// + /// # Errors + /// + /// Returns an [`InvalidHeader`] if the header is invalid. See the enum variants for + /// possible reasons. + pub(super) fn validate( + &self, + expected_type: Option, + ) -> Result { + if self.magic != *magic::PROOF_HEADER { + return Err(InvalidHeader::InvalidMagic { found: self.magic }); + } + + if self.version != magic::PROOF_VERSION { + return Err(InvalidHeader::UnsupportedVersion { + found: self.version, + }); + } + + if self.hash_mode != magic::HASH_MODE { + return Err(InvalidHeader::UnsupportedHashMode { + found: self.hash_mode, + }); + } + + if self.branch_factor != magic::BRANCH_FACTOR { + return Err(InvalidHeader::UnsupportedBranchFactor { + found: self.branch_factor, + }); + } + + match (ProofType::new(self.proof_type), expected_type) { + (None, expected) => Err(InvalidHeader::InvalidProofType { + found: self.proof_type, + expected, + }), + (Some(found), Some(expected)) if found != expected => { + Err(InvalidHeader::InvalidProofType { + found: self.proof_type, + expected: Some(expected), + }) + } + (Some(found), _) => Ok(found), + } + } +} + +/// Error when validating the header. +#[derive(Debug, thiserror::Error)] +pub enum InvalidHeader { + /// Expected a static byte string to prefix the input. + #[error("invalid magic: found {:016x}; expected {:016x}", u64::from_be_bytes(*found), u64::from_be_bytes(*magic::PROOF_HEADER))] + InvalidMagic { + /// The actual bytes found in place where the magic header was expected. + found: [u8; 8], + }, + /// The proof was encoded with an unrecognized version. + #[error( + "unsupported proof version: found {found:02x}; expected {:02x}", + magic::PROOF_VERSION + )] + UnsupportedVersion { + /// The version byte found instead of a supported version. + found: u8, + }, + /// The proof was encoded for an unsupported hash mode. + #[error( + "unsupported hash mode: found {found:02x} ({}); expected {:02x} ({})", + magic::hash_mode_name(*found), + magic::HASH_MODE, + magic::hash_mode_name(magic::HASH_MODE) + )] + UnsupportedHashMode { + /// The flag indicating which hash mode created this proof. + found: u8, + }, + /// The proof was encoded for an unsupported branching factor. + #[error( + "unsupported branch factor: found {}; expected {}", + magic::widen_branch_factor(*found), + magic::widen_branch_factor(magic::BRANCH_FACTOR) + )] + UnsupportedBranchFactor { + /// The actual branch factor encoded in the header. + found: u8, + }, + /// The header indicated an unexpected or invalid proof type. + #[error( + "invalid proof type: found {found:02x} ({}); expected {}", + ProofType::new(*found).map_or("unknown", ProofType::name), + DisplayProofType(*expected), + )] + InvalidProofType { + /// The flag from the header. + found: u8, + /// The expected type, if any. Otherwise any type was expected and we + /// found an unknown value. + expected: Option, + }, +} + +struct DisplayProofType(Option); + +impl std::fmt::Display for DisplayProofType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.0 { + Some(pt) => write!(f, "{:02x} ({})", pt as u8, pt.name()), + None => write!(f, "one of 0x00 (single), 0x01 (range), 0x02 (change)"), + } + } +} diff --git a/firewood/firewood/src/proofs/proof_type.rs b/firewood/firewood/src/proofs/proof_type.rs new file mode 100644 index 000000000000..fe8b019ac4ff --- /dev/null +++ b/firewood/firewood/src/proofs/proof_type.rs @@ -0,0 +1,50 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +/// The type of serialized proof. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ProofType { + /// A proof for a single key/value pair. + /// + /// A proof is a sequence of nodes from the root to a specific node. + /// Each node in the path includes the hash of its child nodes, allowing + /// for verification of the integrity of the path. + /// + /// A single proof includes the full key and value (if present) of the target + /// node. + Single = 0, + /// A range proof for all key/value pairs over a specific key range. + /// + /// A range proof includes a key proof for the beginning and end of the + /// range, as well as all key/value pairs in the range. + Range = 1, + /// A change proof for all key/value pairs that changed between two + /// versions of the tree. + /// + /// A change proof includes a key proof for the beginning and end of the + /// changed range, as well as all key/value pairs that changed. + Change = 2, +} + +impl ProofType { + /// Parse a byte into a [`ProofType`]. + #[must_use] + pub const fn new(v: u8) -> Option { + match v { + 0 => Some(ProofType::Single), + 1 => Some(ProofType::Range), + 2 => Some(ProofType::Change), + _ => None, + } + } + + /// Human readable name for the [`ProofType`] + #[must_use] + pub const fn name(self) -> &'static str { + match self { + ProofType::Single => "single", + ProofType::Range => "range", + ProofType::Change => "change", + } + } +} diff --git a/firewood/firewood/src/proofs/reader.rs b/firewood/firewood/src/proofs/reader.rs new file mode 100644 index 000000000000..0d417acbbad4 --- /dev/null +++ b/firewood/firewood/src/proofs/reader.rs @@ -0,0 +1,171 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::proofs::header::{Header, InvalidHeader}; + +pub(super) trait ReadItem<'a>: Sized { + /// Reads an item from the given reader, or terrminates with an error. + fn read_item(data: &mut ProofReader<'a>) -> Result; +} + +pub(super) trait Version0: Sized { + fn read_v0_item(reader: &mut V0Reader<'_>) -> Result; +} + +pub(super) struct ProofReader<'a> { + data: &'a [u8], + offset: usize, +} + +impl<'a> ProofReader<'a> { + #[must_use] + pub const fn new(data: &'a [u8]) -> Self { + Self { data, offset: 0 } + } + + pub fn read_chunk(&mut self) -> Result<&'a [u8; N], ReadError> { + if let Some((chunk, _)) = self.remainder().split_first_chunk::() { + #[expect(clippy::arithmetic_side_effects)] + { + self.offset += N; + } + Ok(chunk) + } else { + Err(self.incomplete_item(std::any::type_name::<[u8; N]>(), N)) + } + } + + pub fn read_slice(&mut self, n: usize) -> Result<&'a [u8], ReadError> { + if self.remainder().len() >= n { + let (slice, _) = self.remainder().split_at(n); + #[expect(clippy::arithmetic_side_effects)] + { + self.offset += n; + } + Ok(slice) + } else { + Err(self.incomplete_item("byte slice", n)) + } + } + + pub(super) fn read_item>(&mut self) -> Result { + T::read_item(self) + } + + pub fn remainder(&self) -> &'a [u8] { + #![expect(clippy::indexing_slicing)] + &self.data[self.offset..] + } + + pub fn advance(&mut self, n: usize) { + #![expect(clippy::arithmetic_side_effects)] + debug_assert!(self.offset + n <= self.data.len()); + self.offset += n; + } + + #[must_use] + pub const fn incomplete_item(&self, item: &'static str, expected: usize) -> ReadError { + ReadError::IncompleteItem { + item, + offset: self.offset, + expected, + #[expect(clippy::arithmetic_side_effects)] + found: self.data.len() - self.offset, + } + } + + #[must_use] + pub fn invalid_item( + &self, + item: &'static str, + expected: &'static str, + found: impl ToString, + ) -> ReadError { + ReadError::InvalidItem { + item, + offset: self.offset, + expected, + found: found.to_string(), + } + } +} + +pub(super) struct V0Reader<'a> { + inner: ProofReader<'a>, + header: Header, +} + +impl<'a> V0Reader<'a> { + #[must_use] + pub fn new(inner: ProofReader<'a>, header: Header) -> Self { + let this = Self { inner, header }; + debug_assert_eq!(this.header().version, 0); + this + } + + pub fn read_v0_item(&mut self) -> Result { + T::read_v0_item(self) + } + + pub const fn header(&self) -> &Header { + &self.header + } +} + +impl<'a> std::ops::Deref for V0Reader<'a> { + type Target = ProofReader<'a>; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl std::ops::DerefMut for V0Reader<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner + } +} + +/// Error that ocurred while reading an item from the byte stream. +#[derive(Debug, thiserror::Error)] +pub enum ReadError { + /// Insufficient data in the byte stream. + #[error("incomplete {item} at offset {offset}: expected {expected} bytes, but found {found}")] + IncompleteItem { + /// The specific item that was trying to parse. + item: &'static str, + /// The offset in the byte stream where the error ocurred. + offset: usize, + /// The expected length of the input (for this item). + expected: usize, + /// The number of bytes found in the byte stream. + found: usize, + }, + /// An item was invalid after parsing. + #[error("invalid {item} at offset {offset}: expected {expected}, but found {found}")] + InvalidItem { + /// The item that was trying to parse. + item: &'static str, + /// The offset in the byte stream where the error ocurred. + offset: usize, + /// A hint at what was expected. + expected: &'static str, + /// Message indicating what was actually found. + found: String, + }, + /// Failed to validate the header. + #[error("invalid header: {0}")] + InvalidHeader(InvalidHeader), +} + +impl ReadError { + pub(super) const fn set_item(mut self, item: &'static str) -> Self { + match &mut self { + Self::IncompleteItem { item: e_item, .. } | Self::InvalidItem { item: e_item, .. } => { + *e_item = item; + } + Self::InvalidHeader(_) => {} + } + self + } +} diff --git a/firewood/firewood/src/proofs/ser.rs b/firewood/firewood/src/proofs/ser.rs new file mode 100644 index 000000000000..18d6a7cbb2b6 --- /dev/null +++ b/firewood/firewood/src/proofs/ser.rs @@ -0,0 +1,201 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use firewood_storage::{PathBuf, PathComponentSliceExt, ValueDigest}; +use integer_encoding::VarInt; + +use crate::{ + proof::ProofNode, + proofs::{bitmap::ChildrenMap, header::Header, proof_type::ProofType}, + v2::api::FrozenRangeProof, +}; + +impl FrozenRangeProof { + /// Serializes this proof into the provided byte vector. + /// + /// # Format + /// + /// The V0 serialization format for a range proof is: + /// + #[expect( + rustdoc::private_intra_doc_links, + reason = "Header and ProofType are not exported" + )] + /// - A 32-byte [`Header`] with the proof type set to [`ProofType::Range`]. + /// - The start proof, serialized as a _sequence_ of [`ProofNode`]s + /// - The end proof, serialized as a _sequence_ of [`ProofNode`]s + /// - The key-value pairs, serialized as a _sequence_ of `(key, value)` tuples. + /// + /// Each [`ProofNode`] is serialized as: + /// - The key, serialized as a _sequence_ of bytes where each byte is a nibble + /// of the appropriate branching factor. E.g., if the trie has a branching + /// factor of 16, each byte is only the lower 4 bits of the byte and the + /// upper 4 bits are all zero. + /// - A variable-length integer indicating the length of the parent's key of + /// the `key`. I.e., `key[partial_len..]` is the partial path of this node. + /// - The value digest: + /// - If there is no value for the node, a single byte with the value `0`. + /// - If there is a value for the node, a single byte with the value `1` + /// followed by: + /// - If the value digest is of a full value, a single byte with the value + /// `0` followed by the value serialized as a _sequence_ of bytes. + /// - If the value digest is of a hash, a single byte with the value `1` + /// followed by the hash serialized as exactly 32 bytes. + /// - See [`ValueDigest::make_hash`] as to when a value digest is a hash. + /// - The children bitmap, which is a fixed-size bit field where each bit + /// indicates whether the corresponding child is present. The size of the + /// bitmap is `branching_factor / 8` bytes. E.g., if the branching factor is + /// 16, the bitmap is 2 bytes (16 bits) and if the branching factor is 256, + /// the bitmap is 32 bytes (256 bits). All zero bits indicate that the node + /// is a leaf node and no children follow. + /// - For each child that is present, as indicated by the bitmap, the child's + /// node ID is serialized. + /// - If the trie is using MerkleDB hashing, the ID is a fixed 32-byte + /// sha256 hash. + /// - If the trie is using Ethereum hashing, the ID is serialized as: + /// - A single byte with the value `0` if the ID is a keccak256 hash; + /// followed by the fixed 32-byte hash. + /// - A single byte with the value `1` if the ID is an RLP encoded node; + /// followed by the RLP encoded bytes serialized as a _sequence_ of + /// bytes. This occurs when the hash input (RLP encoded node) is smaller + /// than 32 bytes; in which case, the hash result is the input value + /// unhashed. + /// + /// Each _sequence_ mentioned above is prefixed with a variable-length integer + /// indicating the number of items in the sequence. + /// + /// Variable-length integers are encoded using unsigned LEB128. + pub fn write_to_vec(&self, out: &mut Vec) { + Header::from(ProofType::Range).write_item(out); + self.write_item(out); + } +} + +trait PushVarInt { + fn push_var_int(&mut self, v: VI); +} + +impl PushVarInt for Vec { + fn push_var_int(&mut self, v: VI) { + let mut buf = [0u8; 10]; + let n = v.encode_var(&mut buf); + #[expect(clippy::indexing_slicing)] + self.extend_from_slice(&buf[..n]); + } +} + +trait WriteItem { + fn write_item(&self, out: &mut Vec); +} + +impl WriteItem for FrozenRangeProof { + fn write_item(&self, out: &mut Vec) { + self.start_proof().write_item(out); + self.end_proof().write_item(out); + self.key_values().write_item(out); + } +} + +impl WriteItem for ProofNode { + fn write_item(&self, out: &mut Vec) { + self.key.write_item(out); + out.push_var_int(self.partial_len); + self.value_digest.write_item(out); + ChildrenMap::new(&self.child_hashes).write_item(out); + for (_, child) in self.child_hashes.iter_present() { + child.write_item(out); + } + } +} + +impl WriteItem for PathBuf { + fn write_item(&self, out: &mut Vec) { + out.push_var_int(self.len()); + out.extend_from_slice(self.as_byte_slice()); + } +} + +impl WriteItem for Option { + fn write_item(&self, out: &mut Vec) { + if let Some(v) = self { + out.push(1); + v.write_item(out); + } else { + out.push(0); + } + } +} + +impl WriteItem for [T] { + fn write_item(&self, out: &mut Vec) { + out.push_var_int(self.len()); + for item in self { + item.write_item(out); + } + } +} + +impl WriteItem for [u8] { + fn write_item(&self, out: &mut Vec) { + out.push_var_int(self.len()); + out.extend_from_slice(self); + } +} + +impl> WriteItem for ValueDigest { + fn write_item(&self, out: &mut Vec) { + match self.make_hash() { + ValueDigest::Value(v) => { + out.push(0); + v.write_item(out); + } + #[cfg(not(feature = "ethhash"))] + ValueDigest::Hash(h) => { + out.push(1); + h.write_item(out); + } + } + } +} + +impl WriteItem for Header { + fn write_item(&self, out: &mut Vec) { + out.extend_from_slice(bytemuck::bytes_of(self)); + } +} + +impl WriteItem for firewood_storage::TrieHash { + fn write_item(&self, out: &mut Vec) { + out.extend_from_slice(self.as_ref()); + } +} + +#[cfg(feature = "ethhash")] +impl WriteItem for firewood_storage::HashType { + fn write_item(&self, out: &mut Vec) { + match self { + firewood_storage::HashType::Hash(h) => { + out.push(0); + h.write_item(out); + } + firewood_storage::HashType::Rlp(h) => { + out.push(1); + h.write_item(out); + } + } + } +} + +impl WriteItem for ChildrenMap { + fn write_item(&self, out: &mut Vec) { + out.extend_from_slice(bytemuck::bytes_of(self)); + } +} + +impl, V: AsRef<[u8]>> WriteItem for (K, V) { + fn write_item(&self, out: &mut Vec) { + let (key, value) = self; + key.as_ref().write_item(out); + value.as_ref().write_item(out); + } +} diff --git a/firewood/firewood/src/proofs/tests.rs b/firewood/firewood/src/proofs/tests.rs new file mode 100644 index 000000000000..408935f748c2 --- /dev/null +++ b/firewood/firewood/src/proofs/tests.rs @@ -0,0 +1,226 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect(clippy::unwrap_used, clippy::indexing_slicing)] + +use integer_encoding::VarInt; +use test_case::test_case; + +use crate::{ + proofs::{header::InvalidHeader, magic, proof_type::ProofType, reader::ReadError}, + v2::api::FrozenRangeProof, +}; + +fn create_valid_range_proof() -> (FrozenRangeProof, Vec) { + let merkle = crate::merkle::tests::init_merkle((0u8..=10).map(|k| ([k], [k]))); + let proof = merkle + .range_proof(Some(&[2u8]), Some(&[8u8]), std::num::NonZeroUsize::new(5)) + .unwrap(); + let mut serialized = Vec::new(); + proof.write_to_vec(&mut serialized); + (proof, serialized) +} + +#[test_case( + |data| data[0..8].copy_from_slice(b"badmagic"), + |err| matches!(err, InvalidHeader::InvalidMagic { found } if found == b"badmagic"); + "invalid magic" +)] +#[test_case( + |data| data[8] = 99, + |err| matches!(err, InvalidHeader::UnsupportedVersion { found: 99 }); + "unsupported version" +)] +#[test_case( + |data| data[9] = 99, + |err| matches!(err, InvalidHeader::UnsupportedHashMode { found: 99 }); + "unsupported hash mode" +)] +#[test_case( + |data| data[10] = 99, + |err| matches!(err, InvalidHeader::UnsupportedBranchFactor { found: 99 }); + "unsupported branch factor" +)] +#[test_case( + |data| data[11] = 99, + |err| matches!(err, InvalidHeader::InvalidProofType { found: 99, expected: Some(ProofType::Range) }); + "invalid proof type" +)] +#[test_case( + |data| data[11] = ProofType::Change as u8, + |err| matches!(err, InvalidHeader::InvalidProofType { found: 2, expected: Some(ProofType::Range) }); + "wrong proof type" +)] +fn test_invalid_header( + mutator: impl FnOnce(&mut Vec), + expected: impl FnOnce(&InvalidHeader) -> bool, +) { + let (_, mut data) = create_valid_range_proof(); + + mutator(&mut data); + + match FrozenRangeProof::from_slice(&data) { + Err(ReadError::InvalidHeader(err)) => assert!(expected(&err), "unexpected error: {err}"), + other => panic!("Expected ReadError::InvalidHeader, got: {other:?}"), + } +} + +#[test_case( + |_, data| data.truncate(20), + "header", + 32, // expected len + 20; // found len + "incomplete header" +)] +#[test_case( + |_, data| data.truncate(31), + "header", + 32, // expected len + 31; // found len + "header one byte short" +)] +#[test_case( + |_, data| data.truncate(32), + "array length", + 1, // expected len + 0; // found len + "no varint after header" +)] +#[cfg_attr(not(feature = "branch_factor_256"), test_case( + |proof, data| { + #[expect(clippy::arithmetic_side_effects)] + data.truncate( + 32 + + proof.start_proof().len().required_space() + + proof.start_proof()[0].key.len().required_space() + // truncate after the key length varint but before the key bytes + ); + }, + "byte slice", + 1, // expected len + 0; // found len + "truncated node key" +))] +fn test_incomplete_item( + mutator: impl FnOnce(&FrozenRangeProof, &mut Vec), + item: &'static str, + expected_len: usize, + found_len: usize, +) { + let (proof, mut data) = create_valid_range_proof(); + + eprintln!("data len: {}", data.len()); + eprintln!("proof: {proof:#?}"); + eprintln!("data: {}", hex::encode(&data)); + + mutator(&proof, &mut data); + + match FrozenRangeProof::from_slice(&data) { + Err(ReadError::IncompleteItem { + item: found_item, + offset: _, + expected, + found, + }) => { + assert_eq!( + found_item, item, + "unexpected `item` value, got: {found_item}, wanted: {item}; {data:?}" + ); + assert_eq!( + expected, expected_len, + "unexpected `expected` value, got: {expected}, wanted: {expected_len}; {data:?}" + ); + assert_eq!( + found, found_len, + "unexpected `found` value, got: {found}, wanted: {found_len}; {data:?}" + ); + } + other => panic!("Expected ReadError::IncompleteItem, got: {other:?}"), + } +} + +#[test_case( + |proof, data| data[32 + + proof.start_proof().len().required_space() + + proof.start_proof()[0].key.len().required_space() + + proof.start_proof()[0].key.len() + + proof.start_proof()[0].partial_len.required_space() + // Corrupt the option discriminant for the value digest (should be 0 or 1) + ] = 3, // invalid option discriminant + "option discriminant", + "0 or 1", + "3"; + "invalid option discriminant" +)] +#[test_case( + |_, data| data[32..42].copy_from_slice(&[0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89]), + "array length", + "byte with no MSB within 9 bytes", + "[128, 129, 130, 131, 132, 133, 134, 135, 136, 137]"; + "invalid varint" +)] +#[test_case( + |_, data| data.extend_from_slice(&[0xFF; 100]), // extend data with invalid trailing bytes + "trailing bytes", + "no data after the proof", + "100 bytes"; + "extra trailing bytes" +)] +fn test_invalid_item( + mutator: impl FnOnce(&FrozenRangeProof, &mut Vec), + item: &'static str, + expected: &'static str, + found: &'static str, +) { + let (proof, mut data) = create_valid_range_proof(); + + mutator(&proof, &mut data); + + match FrozenRangeProof::from_slice(&data) { + Err(ReadError::InvalidItem { + item: found_item, + offset: _, + expected: found_expected, + found: found_found, + }) => { + assert_eq!( + found_item, item, + "unexpected `item` value, got: {found_item}, wanted: {item}" + ); + assert_eq!( + found_expected, expected, + "unexpected `expected` value, got: {found_expected}, wanted: {expected}" + ); + assert_eq!( + found_found, found, + "unexpected `found` value, got: {found_found}, wanted: {found}" + ); + } + other => panic!("Expected ReadError::InvalidItem, got: {other:?}"), + } +} + +#[test] +fn test_empty_proof() { + #[rustfmt::skip] + let bytes = [ + b'f', b'w', b'd', b'p', b'r', b'o', b'o', b'f', // magic + 0, // version + magic::HASH_MODE, + magic::BRANCH_FACTOR, + ProofType::Range as u8, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // reserved + 0, // start proof length = 0 + 0, // end proof length = 0 + 0, // key-value pairs length = 0 + ]; + + match FrozenRangeProof::from_slice(&bytes) { + Ok(proof) => { + assert!(proof.start_proof().is_empty()); + assert!(proof.end_proof().is_empty()); + assert!(proof.key_values().is_empty()); + } + Err(err) => panic!("Expected valid empty proof, got error: {err}"), + } +} diff --git a/firewood/firewood/src/range_proof.rs b/firewood/firewood/src/range_proof.rs new file mode 100644 index 000000000000..1cd9969ab5d9 --- /dev/null +++ b/firewood/firewood/src/range_proof.rs @@ -0,0 +1,252 @@ +// Copyright (C) 2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::proof::{Proof, ProofCollection}; + +/// A range proof is a cryptographic proof that demonstrates a contiguous set of key-value pairs +/// exists within a Merkle trie with a given root hash. +/// +/// Range proofs are used to efficiently prove the presence (or absence) of multiple consecutive +/// keys in a trie without revealing the entire trie structure. They consist of: +/// - A start proof: proves the existence of the first key in the range (or the nearest key before it) +/// - An end proof: proves the existence of the last key in the range (or the nearest key after it) +/// - The actual key-value pairs within the range +/// +/// This allows verification that: +/// 1. The provided key-value pairs are indeed part of the trie +/// 2. There are no other keys between the start and end of the range +/// 3. The trie has the claimed root hash +/// +/// Range proofs are particularly useful in blockchain contexts for: +/// - State synchronization between nodes +/// - Light client verification +/// - Efficient auditing of specific key ranges +#[derive(Debug, PartialEq)] +pub struct RangeProof { + start_proof: Proof, + end_proof: Proof, + key_values: Box<[(K, V)]>, +} + +impl RangeProof +where + K: AsRef<[u8]>, + V: AsRef<[u8]>, + H: ProofCollection, +{ + /// Create a new range proof with the given start and end proofs + /// and the key-value pairs that are included in the proof. + /// + /// # Parameters + /// + /// * `start_proof` - A Merkle proof for the first key in the range, or if the range + /// starts before any existing key, a proof for the nearest key that comes after + /// the start of the range. This proof establishes the lower boundary of the range + /// and ensures no keys exist between the range start and the first included key. + /// May be empty if proving from the very beginning of the trie. + /// + /// * `end_proof` - A Merkle proof for the last key in the range, or if the range + /// extends beyond all existing keys, a proof for the nearest key that comes before + /// the end of the range. This proof establishes the upper boundary of the range + /// and ensures no keys exist between the last included key and the range end. + /// May be empty if proving to the very end of the trie. + /// + /// * `key_values` - The actual key-value pairs that exist within the proven range. + /// These are the consecutive entries from the trie that fall within the boundaries + /// established by the start and end proofs. The keys should be in lexicographic + /// order as they appear in the trie. May be empty if proving the absence of keys + /// in a range. + #[must_use] + pub const fn new( + start_proof: Proof, + end_proof: Proof, + key_values: Box<[(K, V)]>, + ) -> Self { + Self { + start_proof, + end_proof, + key_values, + } + } + + /// Returns a reference to the start proof, which may be empty. + #[must_use] + pub const fn start_proof(&self) -> &Proof { + &self.start_proof + } + + /// Returns a reference to the end proof, which may be empty. + #[must_use] + pub const fn end_proof(&self) -> &Proof { + &self.end_proof + } + + /// Returns the key-value pairs included in the range proof, which may be empty. + #[must_use] + pub const fn key_values(&self) -> &[(K, V)] { + &self.key_values + } + + /// Returns true if the range proof is empty, meaning it has no start or end proof + /// and no key-value pairs. + #[must_use] + pub fn is_empty(&self) -> bool { + self.start_proof.is_empty() && self.end_proof.is_empty() && self.key_values.is_empty() + } + + /// Returns an iterator over the key-value pairs in this range proof. + /// + /// The iterator yields references to the key-value pairs in the order they + /// appear in the proof (which should be lexicographic order as they appear + /// in the trie). + #[must_use] + pub fn iter(&self) -> RangeProofIter<'_, K, V> { + RangeProofIter(self.key_values.iter()) + } +} + +/// An iterator over the key-value pairs in a [`RangeProof`]. +/// +/// This iterator yields references to the key-value pairs contained within +/// the range proof in the order they appear (lexicographic order). +#[derive(Debug)] +pub struct RangeProofIter<'a, K, V>(std::slice::Iter<'a, (K, V)>); + +impl<'a, K, V> Iterator for RangeProofIter<'a, K, V> { + type Item = &'a (K, V); + + fn next(&mut self) -> Option { + self.0.next() + } + + fn size_hint(&self) -> (usize, Option) { + self.0.size_hint() + } +} + +impl ExactSizeIterator for RangeProofIter<'_, K, V> {} + +impl std::iter::FusedIterator for RangeProofIter<'_, K, V> {} + +impl<'a, K, V, H> IntoIterator for &'a RangeProof +where + K: AsRef<[u8]>, + V: AsRef<[u8]>, + H: ProofCollection, +{ + type Item = &'a (K, V); + type IntoIter = RangeProofIter<'a, K, V>; + + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +#[cfg(test)] +mod tests { + #![expect(clippy::unwrap_used, reason = "Tests can use unwrap")] + #![expect(clippy::indexing_slicing, reason = "Tests can use indexing")] + + use crate::v2::api::TryIntoBatch; + + use super::*; + + #[test] + fn test_range_proof_iterator() { + // Create test data + let key_values: Box<[(Vec, Vec)]> = Box::new([ + (b"key1".to_vec(), b"value1".to_vec()), + (b"key2".to_vec(), b"value2".to_vec()), + (b"key3".to_vec(), b"value3".to_vec()), + ]); + + // Create empty proofs for testing + let start_proof = Proof::empty(); + let end_proof = Proof::empty(); + + let range_proof = RangeProof::new(start_proof, end_proof, key_values); + + // Test basic iterator functionality + let mut iter = range_proof.iter(); + assert_eq!(iter.len(), 3); + + let first = iter.next().unwrap(); + assert_eq!(first.0, b"key1"); + assert_eq!(first.1, b"value1"); + + let second = iter.next().unwrap(); + assert_eq!(second.0, b"key2"); + assert_eq!(second.1, b"value2"); + + let third = iter.next().unwrap(); + assert_eq!(third.0, b"key3"); + assert_eq!(third.1, b"value3"); + + assert!(iter.next().is_none()); + } + + #[test] + fn test_range_proof_into_iterator() { + let key_values: Box<[(Vec, Vec)]> = Box::new([ + (b"a".to_vec(), b"alpha".to_vec()), + (b"b".to_vec(), b"beta".to_vec()), + ]); + + let start_proof = Proof::empty(); + let end_proof = Proof::empty(); + let range_proof = RangeProof::new(start_proof, end_proof, key_values); + + // Test that we can use for-loop syntax + let mut items = Vec::new(); + for item in &range_proof { + items.push(item); + } + + assert_eq!(items.len(), 2); + assert_eq!(items[0].0, b"a"); + assert_eq!(items[0].1, b"alpha"); + assert_eq!(items[1].0, b"b"); + assert_eq!(items[1].1, b"beta"); + } + + #[test] + fn test_keyvaluepair_iter_trait() { + let key_values: Box<[(Vec, Vec)]> = + Box::new([(b"test".to_vec(), b"data".to_vec())]); + + let start_proof = Proof::empty(); + let end_proof = Proof::empty(); + let range_proof = RangeProof::new(start_proof, end_proof, key_values); + + // Test that our iterator implements KeyValuePairIter + let iter = range_proof.iter(); + + // Verify we can call methods from KeyValuePairIter + let batch_iter = iter.map(TryIntoBatch::try_into_batch); + let batches: Vec<_> = batch_iter.collect::>().unwrap(); + + assert_eq!(batches.len(), 1); + // The batch should be a Put operation since value is non-empty + if let crate::v2::api::BatchOp::Put { key, value } = &batches[0] { + assert_eq!(key.as_ref() as &[u8], b"test"); + assert_eq!(value.as_ref() as &[u8], b"data"); + } else { + panic!("Expected Put operation"); + } + } + + #[test] + fn test_empty_range_proof_iterator() { + let key_values: Box<[(Vec, Vec)]> = Box::new([]); + let start_proof = Proof::empty(); + let end_proof = Proof::empty(); + let range_proof = RangeProof::new(start_proof, end_proof, key_values); + + let mut iter = range_proof.iter(); + assert_eq!(iter.len(), 0); + assert!(iter.next().is_none()); + + let items: Vec<_> = range_proof.into_iter().collect(); + assert!(items.is_empty()); + } +} diff --git a/firewood/firewood/src/root_store.rs b/firewood/firewood/src/root_store.rs new file mode 100644 index 000000000000..43641cdab6c0 --- /dev/null +++ b/firewood/firewood/src/root_store.rs @@ -0,0 +1,80 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use fjall::{Config, Keyspace, PartitionCreateOptions, PartitionHandle, PersistMode}; +use std::path::Path; + +use derive_where::derive_where; +use firewood_storage::{LinearAddress, TrieHash}; + +const FJALL_PARTITION_NAME: &str = "firewood"; + +#[derive_where(Debug)] +#[derive_where(skip_inner)] +pub struct RootStore { + keyspace: Keyspace, + items: PartitionHandle, +} + +impl RootStore { + /// Creates or opens an instance of `RootStore`. + /// + /// Args: + /// - path: the directory where `RootStore` will write to. + /// + /// # Errors + /// + /// Will return an error if unable to create or open an instance of `RootStore`. + pub fn new>( + path: P, + ) -> Result> { + let keyspace = Config::new(path).open()?; + let items = + keyspace.open_partition(FJALL_PARTITION_NAME, PartitionCreateOptions::default())?; + + Ok(Self { keyspace, items }) + } + + /// `add_root` persists a revision's address to `RootStore`. + /// + /// Args: + /// - hash: the hash of the revision + /// - address: the address of the revision + /// + /// # Errors + /// + /// Will return an error if unable to persist the revision address to the + /// underlying datastore + pub fn add_root( + &self, + hash: &TrieHash, + address: &LinearAddress, + ) -> Result<(), Box> { + self.items.insert(**hash, address.get().to_be_bytes())?; + + self.keyspace.persist(PersistMode::Buffer)?; + + Ok(()) + } + + /// `get` returns the address of a revision. + /// + /// Args: + /// - hash: the hash of the revision + /// + /// # Errors + /// + /// Will return an error if unable to query the underlying datastore. + pub fn get( + &self, + hash: &TrieHash, + ) -> Result, Box> { + let Some(v) = self.items.get(**hash)? else { + return Ok(None); + }; + + let array: [u8; 8] = v.as_ref().try_into()?; + + Ok(LinearAddress::new(u64::from_be_bytes(array))) + } +} diff --git a/firewood/firewood/src/v2/api.rs b/firewood/firewood/src/v2/api.rs new file mode 100644 index 000000000000..9d3ae9ab9962 --- /dev/null +++ b/firewood/firewood/src/v2/api.rs @@ -0,0 +1,499 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::manager::RevisionManagerError; +use crate::merkle::parallel::CreateProposalError; +use crate::merkle::{Key, Value}; +use crate::proof::{Proof, ProofError, ProofNode}; +use firewood_storage::{FileIoError, TrieHash}; +use std::fmt::Debug; +use std::num::NonZeroUsize; +use std::sync::Arc; + +pub use crate::range_proof::RangeProof; +pub use crate::v2::batch_op::{BatchIter, BatchOp, IntoBatchIter, KeyValuePair, TryIntoBatch}; + +/// A `KeyType` is something that can be xcast to a u8 reference, +/// and can be sent and shared across threads. References with +/// lifetimes are not allowed (hence 'static) +pub trait KeyType: AsRef<[u8]> + Debug {} + +impl KeyType for T where T: AsRef<[u8]> + Debug {} + +/// A `ValueType` is the same as a `KeyType`. However, these could +/// be a different type from the `KeyType` on a given API call. +/// For example, you might insert `{key: "key", value: [0u8]}` +/// This also means that the type of all the keys for a single +/// API call must be the same, as well as the type of all values +/// must be the same. +pub trait ValueType: AsRef<[u8]> + Debug {} + +impl ValueType for T where T: AsRef<[u8]> + Debug {} + +/// The type and size of a single hash key +/// These are 256-bit hashes that are used for a variety of reasons: +/// - They identify a version of the datastore at a specific point +/// in time +/// - They are used to provide integrity at different points in a +/// proof +pub type HashKey = firewood_storage::TrieHash; + +/// An extension trait for the [`HashKey`] type to provide additional methods. +pub trait HashKeyExt: Sized { + /// Default root hash for an empty database. + fn default_root_hash() -> Option; +} + +/// An extension trait for an optional `HashKey` type to provide additional methods. +pub trait OptionalHashKeyExt: Sized { + /// Returns the default root hash if the current value is [`None`]. + fn or_default_root_hash(self) -> Option; +} + +#[cfg(not(feature = "ethhash"))] +impl HashKeyExt for HashKey { + /// Creates a new `HashKey` representing the empty root hash. + #[inline] + fn default_root_hash() -> Option { + None + } +} + +#[cfg(feature = "ethhash")] +impl HashKeyExt for HashKey { + #[inline] + fn default_root_hash() -> Option { + const EMPTY_RLP_HASH: [u8; size_of::()] = [ + // "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" + 0x56, 0xe8, 0x1f, 0x17, 0x1b, 0xcc, 0x55, 0xa6, 0xff, 0x83, 0x45, 0xe6, 0x92, 0xc0, + 0xf8, 0x6e, 0x5b, 0x48, 0xe0, 0x1b, 0x99, 0x6c, 0xad, 0xc0, 0x01, 0x62, 0x2f, 0xb5, + 0xe3, 0x63, 0xb4, 0x21, + ]; + + Some(EMPTY_RLP_HASH.into()) + } +} + +impl OptionalHashKeyExt for Option { + #[inline] + fn or_default_root_hash(self) -> Option { + self.or_else(HashKey::default_root_hash) + } +} + +/// A frozen proof is a proof that is stored in immutable memory. +pub type FrozenRangeProof = RangeProof>; + +/// A frozen proof uses an immutable collection of proof nodes. +pub type FrozenProof = Proof>; + +/// Errors returned through the API +#[derive(thiserror::Error, Debug)] +#[non_exhaustive] +pub enum Error { + /// A given hash key is not available in the database + #[error("Revision for {provided:?} not found")] + RevisionNotFound { + /// the provided hash key + provided: Option, + }, + + /// A committed revision does not have an address. + #[error("Revision for {provided:?} has no address")] + RevisionWithoutAddress { provided: HashKey }, + + /// Incorrect root hash for commit + #[error( + "The proposal cannot be committed since it is not a direct child of the most recent commit. Proposal parent: {provided:?}, current root: {expected:?}" + )] + ParentNotLatest { + /// the provided root hash + provided: Option, + /// the expected root hash + expected: Option, + }, + + /// Invalid range + #[error("Invalid range: {start_key:?} > {end_key:?}")] + InvalidRange { + /// The provided starting key + start_key: Key, + /// The provided ending key + end_key: Key, + }, + + #[error("IO error: {0}")] + /// An IO error occurred + IO(#[from] std::io::Error), + + #[error("File IO error: {0}")] + /// A file I/O error occurred + FileIO(#[from] FileIoError), + + #[error("RootStore error: {0}")] + /// A `RootStore` error occurred + RootStoreError(#[source] Box), + + /// Cannot commit a committed proposal + #[error("Cannot commit a committed proposal")] + AlreadyCommitted, + + /// Internal error + #[error("Internal error")] + InternalError(Box), + + /// Range too small + #[error("Range too small")] + RangeTooSmall, + + /// Request `RangeProof` for empty trie + #[error("request RangeProof for empty trie")] + RangeProofOnEmptyTrie, + + /// Request `RangeProof` for empty range + #[error("the latest revision is empty and has no root hash")] + LatestIsEmpty, + + /// Sibling already committed + #[error("sibling already committed")] + SiblingCommitted, + + /// Proof error + #[error("proof error")] + ProofError(#[from] ProofError), + + /// An invalid root hash was provided + #[error(transparent)] + InvalidRootHash(#[from] firewood_storage::InvalidTrieHashLength), + + // Error sending to worker + #[error("send error to worker")] + SendErrorToWorker, + + // Error converting a u8 index into a path component + #[error("error converting a u8 index into a path component")] + InvalidConversionToPathComponent, +} + +impl From for Error { + fn from(value: std::convert::Infallible) -> Self { + match value {} + } +} + +impl From for Error { + fn from(err: RevisionManagerError) -> Self { + use RevisionManagerError::{ + FileIoError, NotLatest, RevisionNotFound, RevisionWithoutAddress, RootStoreError, + }; + match err { + NotLatest { provided, expected } => Self::ParentNotLatest { provided, expected }, + RevisionNotFound { provided } => Self::RevisionNotFound { + provided: Some(provided), + }, + RevisionWithoutAddress { provided } => Self::RevisionWithoutAddress { provided }, + FileIoError(io_err) => Self::FileIO(io_err), + RootStoreError(err) => Self::RootStoreError(err), + } + } +} + +impl From for Error { + fn from(value: crate::db::DbError) -> Self { + match value { + crate::db::DbError::FileIo(err) => Error::FileIO(err), + } + } +} + +impl From for Error { + fn from(value: CreateProposalError) -> Self { + match value { + CreateProposalError::FileIoError(err) => Error::FileIO(err), + CreateProposalError::SendError => Error::SendErrorToWorker, + CreateProposalError::InvalidConversionToPathComponent => { + Error::InvalidConversionToPathComponent + } + } + } +} + +/// The database interface. The methods here operate on the most +/// recently committed revision, and allow the creation of a new +/// [`Proposal`] or a new [`DbView`] based on a specific historical +/// revision. +pub trait Db { + /// The type of a historical revision + type Historical: DbView; + + /// The type of a proposal + type Proposal<'db>: DbView + Proposal + where + Self: 'db; + + /// Get a reference to a specific view based on a hash + /// + /// # Arguments + /// + /// - `hash` - Identifies the revision for the view + #[expect(clippy::missing_errors_doc)] + fn revision(&self, hash: TrieHash) -> Result, Error>; + + /// Get the hash of the most recently committed version + /// + /// # Note + /// + /// If the database is empty, this will return None, unless the ethhash feature is enabled. + /// In that case, we return the special ethhash compatible empty trie hash. + #[expect(clippy::missing_errors_doc)] + fn root_hash(&self) -> Result, Error>; + + /// Get all the hashes available + #[expect(clippy::missing_errors_doc)] + fn all_hashes(&self) -> Result, Error>; + + /// Propose a change to the database via a batch + /// + /// This proposal assumes it is based off the most recently + /// committed transaction + /// + /// # Arguments + /// + /// * `data` - A batch consisting of [`BatchOp::Put`] and [`BatchOp::Delete`] + /// operations to apply + #[expect(clippy::missing_errors_doc)] + fn propose(&self, data: impl IntoBatchIter) -> Result, Error>; +} + +/// A view of the database at a specific time. +/// +/// There are a few ways to create a [`DbView`]: +/// 1. From [`Db::revision`] which gives you a view for a specific +/// historical revision +/// 2. From [`Db::propose`] which is a view on top of the most recently +/// committed revision with changes applied; or +/// 3. From [`Proposal::propose`] which is a view on top of another proposal. +pub trait DbView { + /// The type of a stream of key/value pairs + type Iter<'view>: Iterator> + where + Self: 'view; + + /// Get the root hash for the current [`DbView`] + /// + /// # Note + /// + /// If the database is empty, this will return None, unless the ethhash feature is enabled. + /// In that case, we return the special ethhash compatible empty trie hash. + #[expect(clippy::missing_errors_doc)] + fn root_hash(&self) -> Result, Error>; + + /// Get the value of a specific key + #[expect(clippy::missing_errors_doc)] + fn val(&self, key: K) -> Result, Error>; + + /// Obtain a proof for a single key + #[expect(clippy::missing_errors_doc)] + fn single_key_proof(&self, key: K) -> Result; + + /// Obtain a range proof over a set of keys + /// + /// # Arguments + /// + /// * `first_key` - If None, start at the lowest key + /// * `last_key` - If None, continue to the end of the database + /// * `limit` - The maximum number of keys in the range proof + #[expect(clippy::missing_errors_doc)] + fn range_proof( + &self, + first_key: Option, + last_key: Option, + limit: Option, + ) -> Result; + + /// Obtain a stream over the keys/values of this view, using an optional starting point + /// + /// # Arguments + /// + /// * `first_key` - If None, start at the lowest key + /// + /// # Note + /// + /// If you always want to start at the beginning, [`DbView::iter`] is easier to use + /// If you always provide a key, [`DbView::iter_from`] is easier to use + #[expect(clippy::missing_errors_doc)] + fn iter_option(&self, first_key: Option) -> Result, Error>; + + /// Obtain a stream over the keys/values of this view, starting from the beginning + #[expect(clippy::missing_errors_doc)] + #[expect(clippy::iter_not_returning_iterator)] + fn iter(&self) -> Result, Error> { + self.iter_option(Option::::None) + } + + /// Obtain a stream over the key/values, starting at a specific key + #[expect(clippy::missing_errors_doc)] + fn iter_from(&self, first_key: K) -> Result, Error> { + self.iter_option(Some(first_key)) + } +} + +/// A boxed iterator over key/value pairs. +pub type BoxKeyValueIter<'view> = + Box> + 'view>; + +/// A dynamic dyspatch version of [`DbView`] that can be shared. +pub type ArcDynDbView = Arc; + +/// A dyn-safe version of [`DbView`]. +pub trait DynDbView: Debug + Send + Sync + 'static { + /// Get the root hash for the current [`DynDbView`] + /// + /// # Note + /// + /// If the database is empty, this will return None, unless the ethhash feature is enabled. + /// In that case, we return the special ethhash compatible empty trie hash. + #[expect(clippy::missing_errors_doc)] + fn root_hash(&self) -> Result, Error>; + + /// Get the value of a specific key + #[expect(clippy::missing_errors_doc)] + fn val(&self, key: &[u8]) -> Result, Error>; + + /// Obtain a proof for a single key + #[expect(clippy::missing_errors_doc)] + fn single_key_proof(&self, key: &[u8]) -> Result; + + /// Obtain a range proof over a set of keys + /// + /// # Arguments + /// + /// * `first_key` - If None, start at the lowest key + /// * `last_key` - If None, continue to the end of the database + /// * `limit` - The maximum number of keys in the range proof + #[expect(clippy::missing_errors_doc)] + fn range_proof( + &self, + first_key: Option<&[u8]>, + last_key: Option<&[u8]>, + limit: Option, + ) -> Result; + + /// Obtain a stream over the keys/values of this view, using an optional starting point + /// + /// # Arguments + /// + /// * `first_key` - If None, start at the lowest key + /// + /// # Note + /// + /// If you always want to start at the beginning, [`DbView::iter`] is easier to use + /// If you always provide a key, [`DbView::iter_from`] is easier to use + #[expect(clippy::missing_errors_doc)] + fn iter_option(&self, first_key: Option<&[u8]>) -> Result, Error>; + + /// Obtain a stream over the keys/values of this view, starting from the beginning + #[expect(clippy::missing_errors_doc)] + #[expect(clippy::iter_not_returning_iterator)] + fn iter(&self) -> Result, Error> { + self.iter_option(None) + } + + /// Obtain a stream over the key/values, starting at a specific key + #[expect(clippy::missing_errors_doc)] + fn iter_from(&self, first_key: &[u8]) -> Result, Error> { + self.iter_option(Some(first_key)) + } +} + +impl DynDbView for T +where + for<'view> T::Iter<'view>: Sized, +{ + fn root_hash(&self) -> Result, Error> { + DbView::root_hash(self) + } + + fn val(&self, key: &[u8]) -> Result, Error> { + DbView::val(self, key) + } + + fn single_key_proof(&self, key: &[u8]) -> Result { + DbView::single_key_proof(self, key) + } + + fn range_proof( + &self, + first_key: Option<&[u8]>, + last_key: Option<&[u8]>, + limit: Option, + ) -> Result { + DbView::range_proof(self, first_key, last_key, limit) + } + + fn iter_option(&self, first_key: Option<&[u8]>) -> Result, Error> { + // NOTE: `Result::map` does not work here because the compiler cannot correctly + // infer the unsizing operation + match DbView::iter_option(self, first_key) { + Ok(iter) => Ok(Box::new(iter)), + Err(e) => Err(e), + } + } +} + +/// A proposal for a new revision of the database. +/// +/// A proposal may be committed, which consumes the +/// [`Proposal`] and return the generic type `T`, which +/// is the same thing you get if you call [`Db::root_hash`] +/// immediately after committing, and then call +/// [`Db::revision`] with the returned revision. +/// +/// A proposal type must also implement everything in a +/// [`DbView`], which means you can fetch values from it or +/// obtain proofs. +pub trait Proposal: DbView { + /// The type of a proposal + type Proposal: DbView + Proposal; + + /// Commit this revision + #[expect(clippy::missing_errors_doc)] + fn commit(self) -> Result<(), Error>; + + /// Propose a new revision on top of an existing proposal + /// + /// # Arguments + /// + /// * `data` - the batch changes to apply + /// + /// # Return value + /// + /// A new proposal + #[expect(clippy::missing_errors_doc)] + fn propose(&self, data: impl IntoBatchIter) -> Result; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[cfg(feature = "ethhash")] + fn test_ethhash_compat_default_root_hash_equals_empty_rlp_hash() { + use sha3::Digest as _; + + assert_eq!( + TrieHash::default_root_hash(), + sha3::Keccak256::digest(rlp::NULL_RLP) + .as_slice() + .try_into() + .ok(), + ); + } + + #[test] + #[cfg(not(feature = "ethhash"))] + fn test_firewood_default_root_hash_equals_none() { + assert_eq!(TrieHash::default_root_hash(), None); + } +} diff --git a/firewood/firewood/src/v2/batch_op.rs b/firewood/firewood/src/v2/batch_op.rs new file mode 100644 index 000000000000..23f2315f18f1 --- /dev/null +++ b/firewood/firewood/src/v2/batch_op.rs @@ -0,0 +1,309 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use firewood_storage::FileIoError; + +use crate::v2::api::{KeyType, ValueType}; + +/// A key/value pair operation. +/// +/// Put (upsert), Delete (single key), or Prefix Delete (range) are supported. +#[derive(Debug, Clone, Copy)] +#[non_exhaustive] +pub enum BatchOp { + /// Upsert a key/value pair + Put { + /// the key + key: K, + + /// the value + value: V, + }, + + /// Delete a key + Delete { + /// The key + key: K, + }, + + /// Delete a range of keys by prefix + DeleteRange { + /// The prefix of the keys to delete + prefix: K, + }, +} + +impl BatchOp { + /// Get the key of this operation + #[must_use] + pub const fn key(&self) -> &K { + match self { + BatchOp::Put { key, .. } + | BatchOp::Delete { key } + | BatchOp::DeleteRange { prefix: key } => key, + } + } + + /// Get the value of this operation + #[must_use] + pub const fn value(&self) -> Option<&V> { + match self { + BatchOp::Put { value, .. } => Some(value), + _ => None, + } + } + + /// Convert this operation into a borrowed version, where the key and value + /// are references to the original data. + #[must_use] + pub const fn borrowed(&self) -> BatchOp<&K, &V> { + match self { + BatchOp::Put { key, value } => BatchOp::Put { key, value }, + BatchOp::Delete { key } => BatchOp::Delete { key }, + BatchOp::DeleteRange { prefix } => BatchOp::DeleteRange { prefix }, + } + } + + /// Erases the key and value types, returning a [`BatchOp`] with the key + /// and value dereferenced to `&[u8]`. + #[inline] + #[must_use] + pub fn as_ref(&self) -> BatchOp<&[u8], &[u8]> { + match self { + BatchOp::Put { key, value } => BatchOp::Put { + key: key.as_ref(), + value: value.as_ref(), + }, + BatchOp::Delete { key } => BatchOp::Delete { key: key.as_ref() }, + BatchOp::DeleteRange { prefix } => BatchOp::DeleteRange { + prefix: prefix.as_ref(), + }, + } + } +} + +impl BatchOp<&[u8], &[u8]> { + fn eq_impl(self, other: Self) -> bool { + std::mem::discriminant(&self) == std::mem::discriminant(&other) + && self.key() == other.key() + && self.value() == other.value() + } + + fn hash_impl(self, state: &mut H) { + use std::hash::Hash; + std::mem::discriminant(&self).hash(state); + self.key().hash(state); + if let Some(value) = self.value() { + value.hash(state); + } + } +} + +impl PartialEq> for BatchOp +where + K1: KeyType, + K2: KeyType, + V1: ValueType, + V2: ValueType, +{ + fn eq(&self, other: &BatchOp) -> bool { + BatchOp::eq_impl(self.as_ref(), other.as_ref()) + } +} + +impl Eq for BatchOp {} + +impl std::hash::Hash for BatchOp { + fn hash(&self, state: &mut H) { + BatchOp::hash_impl(self.as_ref(), state); + } +} + +/// A key/value pair that can be converted into a batch operation. +/// +/// The difference between this trait and [`TryIntoBatch`] is that this trait +/// is only used in places where the operations are expected to all be `Put` +/// operations. Empty values are not treated as `DeleteRange` operations here. +pub trait KeyValuePair: TryIntoBatch { + /// Convert this into a tuple of key and value. + /// + /// # Errors + /// + /// Returns an error if the conversion fails. E.g., if a read from storage + /// is required to obtain the key or value. + fn try_into_tuple(self) -> Result<(Self::Key, Self::Value), Self::Error>; +} + +impl KeyValuePair for (K, V) { + fn try_into_tuple(self) -> Result<(Self::Key, Self::Value), Self::Error> { + Ok(self) + } +} + +impl KeyValuePair for &(K, V) { + fn try_into_tuple(self) -> Result<(Self::Key, Self::Value), Self::Error> { + let (key, value) = self; + Ok((key, value)) + } +} + +impl, E: Into> KeyValuePair + for Result +{ + fn try_into_tuple(self) -> Result<(Self::Key, Self::Value), Self::Error> { + match self { + Ok(t) => t.try_into_tuple().map_err(|e| match e {}), + Err(e) => Err(e), + } + } +} + +/// A key/value pair that can be used in a batch. +pub trait TryIntoBatch { + /// The key type + type Key: KeyType; + + /// The value type + type Value: ValueType; + + /// The error type. It is preferable to use an error that is convertible into + /// [`FileIoError`] instead of the type directly to allow for better compiler + /// optimizations. + /// + /// E.g., [`std::convert::Infallible`] is preferred over [`FileIoError`] when + /// there is no possibility of error so that the compiler can optimize away + /// error handling. + type Error: Into; + + /// Convert this key-value pair into a [`BatchOp`]. + /// + /// # Errors + /// + /// Returns an error if the conversion fails. E.g., if a read from storage + /// is required to obtain the key or value. + fn try_into_batch(self) -> Result, Self::Error>; +} + +impl<'a, K: KeyType, V: ValueType> TryIntoBatch for &'a (K, V) { + type Key = &'a K; + type Value = &'a V; + type Error = std::convert::Infallible; + + #[inline] + fn try_into_batch(self) -> Result, Self::Error> { + // this converting `&'a (K, V)` into `(&'a K, &'a V)` + let (key, value) = self; + (key, value).try_into_batch() + } +} + +impl TryIntoBatch for (K, V) { + type Key = K; + type Value = V; + type Error = std::convert::Infallible; + + #[inline] + fn try_into_batch(self) -> Result, Self::Error> { + let (key, value) = self; + if value.as_ref().is_empty() { + Ok(BatchOp::DeleteRange { prefix: key }) + } else { + Ok(BatchOp::Put { key, value }) + } + } +} + +impl TryIntoBatch for BatchOp { + type Key = K; + type Value = V; + type Error = std::convert::Infallible; + + fn try_into_batch(self) -> Result, Self::Error> { + Ok(self) + } +} + +impl<'a, K: KeyType, V: ValueType> TryIntoBatch for &'a BatchOp { + type Key = &'a K; + type Value = &'a V; + type Error = std::convert::Infallible; + + fn try_into_batch(self) -> Result, Self::Error> { + Ok(self.borrowed()) + } +} + +impl TryIntoBatch for Result +where + T: TryIntoBatch, + E: Into, +{ + type Key = T::Key; + type Value = T::Value; + type Error = E; + + fn try_into_batch(self) -> Result, Self::Error> { + match self { + Ok(t) => t.try_into_batch().map_err(|e| match e {}), + Err(e) => Err(e), + } + } +} + +/// An extension trait for iterators that yield [`TryIntoBatch`]s. +pub trait BatchIter: + Iterator> +{ + /// An associated type for the iterator item's key type. This is a convenience + /// requirement to avoid needing to build up nested generic associated types. + /// E.g., `<::Item as KeyValuePair>::Key` + type Key: KeyType; + + /// An associated type for the iterator item's value type. This is a convenience + /// requirement to avoid needing to build up nested generic associated types. + /// E.g., `<::Item as KeyValuePair>::Value` + type Value: ValueType; + + /// An associated type for the iterator item's error type. This is a convenience + /// requirement to avoid needing to build up nested generic associated types. + /// E.g., `<::Item as KeyValuePair>::Error` + type Error: Into; +} + +impl> BatchIter for I { + type Key = ::Key; + type Value = ::Value; + type Error = ::Error; +} + +/// An extension trait for types that can be converted into an iterator of batch +/// operations. +pub trait IntoBatchIter: IntoIterator { + /// Convert this type into an iterator of batch operations. + /// + /// This is a convenience method that maps over the iterator returned by + /// [`IntoIterator::into_iter`] and calls [`TryIntoBatch::try_into_batch`] + /// on each item. Additionally, the error type is converted into the specified + /// error type `E` using the `Into` trait. + /// + /// The pass-through of the error type `E` allows for better compiler optimizations + /// by allowing error handling to be omitted during monomorphization when the error + /// type is `Infallible` or another type that can be optimized away. + fn into_batch_iter(self) -> std::iter::Map> + where + Self: Sized, + FileIoError: Into, + { + self.into_iter().map(|item| { + item.try_into_batch() + .map_err(Into::::into) + .map_err(Into::::into) + }) + } +} + +impl> IntoBatchIter for T {} + +/// Type alias for `fn(T) -> Result, E>` where `T: TryIntoBatch`. +pub type MapIntoBatchFn = + fn(T) -> Result::Key, ::Value>, E>; diff --git a/firewood/firewood/src/v2/mod.rs b/firewood/firewood/src/v2/mod.rs new file mode 100644 index 000000000000..f8c1ad60f7f8 --- /dev/null +++ b/firewood/firewood/src/v2/mod.rs @@ -0,0 +1,8 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +/// The public API +pub mod api; + +/// A batch operation and associated types +mod batch_op; diff --git a/firewood/fwdctl/Cargo.toml b/firewood/fwdctl/Cargo.toml new file mode 100644 index 000000000000..b82452d21fc3 --- /dev/null +++ b/firewood/fwdctl/Cargo.toml @@ -0,0 +1,55 @@ +[package] +name = "firewood-fwdctl" +version.workspace = true +edition.workspace = true +authors = [ + "Dan Laine ", + "Dan Sover ", + "Hao Hao ", + "Richard Pringle ", + "Ron Kuris ", + "Sam Batschelet ", + "xinifinity <113067541+xinifinity@users.noreply.github.com>", + "zdf ", +] +description = "Command-line tool for Firewood, an embedded key-value store optimized for blockchain state." +license-file.workspace = true +homepage.workspace = true +repository.workspace = true +rust-version.workspace = true + +[[bin]] +name = "fwdctl" +path = "src/main.rs" + +[dependencies] +# Workspace dependencies +clap = { workspace = true, features = ["cargo", "string"] } +env_logger.workspace = true +firewood.workspace = true +firewood-storage.workspace = true +hex.workspace = true +log.workspace = true +nonzero_ext.workspace = true +# Regular dependencies +csv = "1.4.0" +indicatif = "0.18.3" +askama = "0.14.0" +num-format = "0.4.4" + +[features] +ethhash = ["firewood/ethhash"] +logger = ["firewood/logger"] + +[dev-dependencies] +# Workspace dependencies +firewood-storage = { workspace = true, features = ["test_utils"] } +rand.workspace = true +# Regular dependencies +anyhow = "1.0.100" +assert_cmd = "2.1.1" +predicates = "3.1.3" +serial_test = "3.2.0" + +[lints] +workspace = true diff --git a/firewood/fwdctl/README.md b/firewood/fwdctl/README.md new file mode 100644 index 000000000000..b5afe1b00e20 --- /dev/null +++ b/firewood/fwdctl/README.md @@ -0,0 +1,56 @@ +# fwdctl + +`fwdctl` is a small CLI designed to make it easy to experiment with firewood locally. + +## Building locally + +```sh +cargo build --release --bin fwdctl +``` + +To use + +```sh +./target/release/fwdctl -h +``` + +## Supported commands + +* `fwdctl create`: Create a new firewood database. +* `fwdctl get`: Get the code associated with a key in the database. +* `fwdctl insert`: Insert a key/value pair into the generic key/value store. +* `fwdctl delete`: Delete a key/value pair from the database. +* `fwdctl root`: Get the root hash of the key/value trie. +* `fwdctl dump`: Dump the contents of the key/value store. + +## Examples + +* fwdctl create + +```sh +# Check available options when creating a database, including the defaults. +$ fwdctl create -h +# Create a new, blank instance of firewood using the default name "firewood.db". +$ fwdctl create firewood.db +``` + +* fwdctl get KEY + +```sh +# Get the value associated with a key in the database, if it exists. +fwdctl get KEY +``` + +* fwdctl insert KEY VALUE + +```sh +# Insert a key/value pair into the database. +fwdctl insert KEY VALUE +``` + +* fwdctl delete KEY + +```sh +# Delete a key from the database, along with the associated value. +fwdctl delete KEY +``` diff --git a/firewood/fwdctl/build.rs b/firewood/fwdctl/build.rs new file mode 100644 index 000000000000..a92302cacef6 --- /dev/null +++ b/firewood/fwdctl/build.rs @@ -0,0 +1,36 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::process::Command; + +fn main() { + // Get the git commit SHA + let git_sha = match Command::new("git").args(["rev-parse", "HEAD"]).output() { + Ok(output) => { + if output.status.success() { + String::from_utf8_lossy(&output.stdout).trim().to_string() + } else { + let error_msg = String::from_utf8_lossy(&output.stderr); + format!("git error: {}", error_msg.trim()) + } + } + Err(e) => { + format!("git not found: {e}") + } + }; + + // Check if ethhash feature is enabled + let ethhash_feature = if cfg!(feature = "ethhash") { + "ethhash" + } else { + "-ethhash" + }; + + // Make the git SHA and ethhash status available to the main.rs file + println!("cargo:rustc-env=GIT_COMMIT_SHA={git_sha}"); + println!("cargo:rustc-env=ETHHASH_FEATURE={ethhash_feature}"); + + // Re-run this build script if the git HEAD changes + println!("cargo:rerun-if-changed=.git/HEAD"); + println!("cargo:rerun-if-changed=.git/index"); +} diff --git a/firewood/fwdctl/src/check.rs b/firewood/fwdctl/src/check.rs new file mode 100644 index 000000000000..9da7b621781f --- /dev/null +++ b/firewood/fwdctl/src/check.rs @@ -0,0 +1,306 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::collections::BTreeMap; +use std::path::PathBuf; +use std::sync::Arc; + +use askama::Template; +use clap::Args; +use firewood::v2::api; +use firewood_storage::{CacheReadStrategy, CheckOpt, DBStats, FileBacked, NodeStore}; +use indicatif::{ProgressBar, ProgressFinish, ProgressStyle}; +use nonzero_ext::nonzero; +use num_format::{Locale, ToFormattedString}; + +use crate::DatabasePath; + +// TODO: (optionally) add a fix option +#[derive(Args, Debug)] +pub struct Options { + #[command(flatten)] + pub database: DatabasePath, + + /// Whether to perform hash check + #[arg( + long, + required = false, + default_value_t = false, + help = "Should perform hash check" + )] + pub hash_check: bool, + + /// Whether to fix observed inconsistencies + #[arg( + long, + required = false, + default_value_t = false, + help = "Should fix observed inconsistencies" + )] + pub fix: bool, +} + +pub(super) fn run(opts: &Options) -> Result<(), api::Error> { + let db_path = PathBuf::from(&opts.database.dbpath); + let node_cache_size = nonzero!(1usize); + let free_list_cache_size = nonzero!(1usize); + + let fb = FileBacked::new( + db_path, + node_cache_size, + free_list_cache_size, + false, + false, // don't create if missing + CacheReadStrategy::WritesOnly, // we scan the database once - no need to cache anything + )?; + let storage = Arc::new(fb); + + let progress_bar = ProgressBar::no_length() + .with_style( + ProgressStyle::with_template("{wide_bar} {bytes}/{total_bytes} [{msg}]") + .expect("valid template") + .progress_chars("#>-"), + ) + .with_finish(ProgressFinish::WithMessage("Check Completed!".into())); + + let check_ops = CheckOpt { + hash_check: opts.hash_check, + progress_bar: Some(progress_bar), + }; + + let nodestore = NodeStore::open(storage)?; + let db_stats = if opts.fix { + let (nodestore, report) = nodestore.check_and_fix(check_ops); + if let Err(e) = nodestore { + println!("Error fixing database: {e}"); + } + println!("Fixed Errors ({}):", report.fixed.len()); + for error in report.fixed { + println!("\t{error}"); + } + println!(); + println!("Unfixable Errors ({}):", report.unfixable.len(),); + for (error, io_error) in report.unfixable { + println!("\t{error}"); + if let Some(io_error) = io_error { + println!("\t\tError encountered while fixing: {io_error}"); + } + } + report.db_stats + } else { + let report = nodestore.check(check_ops); + println!("Errors ({}):", report.errors.len()); + for error in report.errors { + println!("\t{error}"); + } + report.db_stats + }; + println!(); + + print_stats_report(db_stats); + + Ok(()) +} + +fn calculate_area_totals(area_counts: &BTreeMap) -> (u64, u64) { + let total_area_count = area_counts.values().sum::(); + let total_area_bytes = area_counts + .iter() + .map(|(area_size, count)| area_size.saturating_mul(*count)) + .sum::(); + (total_area_count, total_area_bytes) +} + +#[derive(Template)] +#[template( + source = r" +Basic Stats: + Firewood Image Size / High Watermark (high_watermark): {{high_watermark}} + Total Key-Value Count (kv_count): {{kv_count}} + Total Key-Value Bytes (kv_bytes): {{kv_bytes}} + +Trie Stats: + Branching Factor Distribution: {{branching_factors}} + Depth Distribution: {{depths}} + +Branch Area Stats: + Total Branch Data Bytes (branch_bytes): {{branch_bytes}} + Total Branch Area Count (branch_area_count): {{total_branch_area_count}} + Total Branch Area Bytes (branch_area_bytes): {{total_branch_area_bytes}} + Branch Area Distribution: {{branch_area_counts}} + Branches that Can Fit Into Smaller Area (low_occupancy_branch_area): {{low_occupancy_branch_area_count}} ({{low_occupancy_branch_area_percent}}) + +Leaf Area Stats: + Total Leaf Data Bytes (leaf_bytes): {{leaf_bytes}} + Total Leaf Area Count (leaf_area_count): {{total_leaf_area_count}} + Total Leaf Area Bytes (leaf_area_bytes): {{total_leaf_area_bytes}} + Leaf Area Distribution: {{leaf_area_counts}} + Leaves that Can Fit Into Smaller Area (low_occupancy_leaf_area): {{low_occupancy_leaf_area_count}} ({{low_occupancy_leaf_area_percent}}) + +Free List Area Stats: + Total Free List Area Count (free_list_area_count): {{total_free_list_area_count}} + Total Free List Area Bytes (free_list_area_bytes): {{total_free_list_area_bytes}} + Free List Area Distribution: {{free_list_area_counts}} + +Alignment Stats: + Trie Areas Spanning Extra Page Due to Unalignment: {{trie_area_extra_unaligned_page}} ({{trie_area_extra_unaligned_page_percent}}) + Free List Areas Spanning Extra Page Due to Unalignment: {{free_list_area_extra_unaligned_page}} ({{free_list_area_extra_unaligned_page_percent}}) + Trie Nodes Spanning Extra Page Due to Unalignment: {{trie_node_extra_unaligned_page}} ({{trie_node_extra_unaligned_page_percent}}%) + +Advanced Stats: + Storage Overhead: high_watermark / kv_bytes = {{storage_overhead}} + Internal Fragmentation: 1 - (branch_bytes + leaf_bytes) / (branch_area_bytes + leaf_area_bytes) = {{internal_fragmentation}} + Areas that Can Fit Into Smaller Area: low_occupancy_branch_area + low_occupancy_leaf_area = {{low_occupancy_area_count}} ({{low_occupancy_area_percent}}) +", + ext = "txt" +)] +struct DBStatsReport { + // Basic stats + high_watermark: String, + kv_count: String, + kv_bytes: String, + // Trie stats + branching_factors: String, + depths: String, + // Branch area stats + branch_bytes: String, + total_branch_area_count: String, + total_branch_area_bytes: String, + branch_area_counts: String, + low_occupancy_branch_area_count: String, + low_occupancy_branch_area_percent: String, + // Leaf area stats + leaf_bytes: String, + total_leaf_area_count: String, + total_leaf_area_bytes: String, + leaf_area_counts: String, + low_occupancy_leaf_area_count: String, + low_occupancy_leaf_area_percent: String, + // Free list area stats + total_free_list_area_count: String, + total_free_list_area_bytes: String, + free_list_area_counts: String, + // Alignment stats + trie_area_extra_unaligned_page: String, + trie_area_extra_unaligned_page_percent: String, + free_list_area_extra_unaligned_page: String, + free_list_area_extra_unaligned_page_percent: String, + // Node stats + trie_node_extra_unaligned_page: String, + trie_node_extra_unaligned_page_percent: String, + // Advanced stats + storage_overhead: String, + internal_fragmentation: String, + low_occupancy_area_count: String, + low_occupancy_area_percent: String, +} + +fn format_u64(value: u64) -> String { + value.to_formatted_string(&Locale::en) +} + +fn format_map(map: &BTreeMap) -> String { + map.iter() + .map(|(key, value)| { + format!( + "{}: {}", + key.to_formatted_string(&Locale::en), + value.to_formatted_string(&Locale::en) + ) + }) + .collect::>() + .join(", ") +} + +#[expect(clippy::cast_precision_loss)] +fn format_percent(numerator: u64, denominator: u64) -> String { + format!("{:.2}%", (numerator as f64 / denominator as f64) * 100.0) +} + +#[expect(clippy::cast_precision_loss)] +fn format_multiple(num: u64, base: u64) -> String { + format!("{:.2}x", num as f64 / base as f64) +} + +fn print_stats_report(db_stats: DBStats) { + let (total_branch_area_count, total_branch_area_bytes) = + calculate_area_totals(&db_stats.trie_stats.branch_area_counts); + let (total_leaf_area_count, total_leaf_area_bytes) = + calculate_area_totals(&db_stats.trie_stats.leaf_area_counts); + let total_trie_area_count = total_branch_area_count.saturating_add(total_leaf_area_count); + let total_trie_area_bytes = total_branch_area_bytes.saturating_add(total_leaf_area_bytes); + + let (total_free_list_area_count, total_free_list_area_bytes) = + calculate_area_totals(&db_stats.free_list_stats.area_counts); + + let total_trie_bytes = db_stats + .trie_stats + .branch_bytes + .saturating_add(db_stats.trie_stats.leaf_bytes); + let total_low_occupancy_area_count = db_stats + .trie_stats + .low_occupancy_branch_area_count + .saturating_add(db_stats.trie_stats.low_occupancy_leaf_area_count); + + let report = DBStatsReport { + high_watermark: format_u64(db_stats.high_watermark), + kv_count: format_u64(db_stats.trie_stats.kv_count), + kv_bytes: format_u64(db_stats.trie_stats.kv_bytes), + branching_factors: format_map(&db_stats.trie_stats.branching_factors), + depths: format_map(&db_stats.trie_stats.depths), + branch_bytes: format_u64(db_stats.trie_stats.branch_bytes), + total_branch_area_count: format_u64(total_branch_area_count), + total_branch_area_bytes: format_u64(total_branch_area_bytes), + branch_area_counts: format_map(&db_stats.trie_stats.branch_area_counts), + low_occupancy_branch_area_count: format_u64( + db_stats.trie_stats.low_occupancy_branch_area_count, + ), + low_occupancy_branch_area_percent: format_percent( + db_stats.trie_stats.low_occupancy_branch_area_count, + total_branch_area_count, + ), + leaf_bytes: format_u64(db_stats.trie_stats.leaf_bytes), + total_leaf_area_count: format_u64(total_leaf_area_count), + total_leaf_area_bytes: format_u64(total_leaf_area_bytes), + leaf_area_counts: format_map(&db_stats.trie_stats.leaf_area_counts), + low_occupancy_leaf_area_count: format_u64( + db_stats.trie_stats.low_occupancy_leaf_area_count, + ), + low_occupancy_leaf_area_percent: format_percent( + db_stats.trie_stats.low_occupancy_leaf_area_count, + total_leaf_area_count, + ), + total_free_list_area_count: format_u64(total_free_list_area_count), + total_free_list_area_bytes: format_u64(total_free_list_area_bytes), + free_list_area_counts: format_map(&db_stats.free_list_stats.area_counts), + trie_area_extra_unaligned_page: format_u64(db_stats.trie_stats.area_extra_unaligned_page), + trie_area_extra_unaligned_page_percent: format_percent( + db_stats.trie_stats.area_extra_unaligned_page, + total_trie_area_count, + ), + free_list_area_extra_unaligned_page: format_u64( + db_stats.free_list_stats.area_extra_unaligned_page, + ), + free_list_area_extra_unaligned_page_percent: format_percent( + db_stats.free_list_stats.area_extra_unaligned_page, + total_free_list_area_count, + ), + trie_node_extra_unaligned_page: format_u64(db_stats.trie_stats.node_extra_unaligned_page), + trie_node_extra_unaligned_page_percent: format_percent( + db_stats.trie_stats.node_extra_unaligned_page, + total_trie_area_count, + ), + storage_overhead: format_multiple(db_stats.high_watermark, db_stats.trie_stats.kv_bytes), + internal_fragmentation: format_percent( + total_trie_area_bytes.saturating_sub(total_trie_bytes), + total_trie_area_bytes, + ), + low_occupancy_area_count: format_u64(total_low_occupancy_area_count), + low_occupancy_area_percent: format_percent( + total_low_occupancy_area_count, + total_trie_area_count, + ), + }; + + println!("{report}"); +} diff --git a/firewood/fwdctl/src/create.rs b/firewood/fwdctl/src/create.rs new file mode 100644 index 000000000000..71490b75b571 --- /dev/null +++ b/firewood/fwdctl/src/create.rs @@ -0,0 +1,62 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use clap::{Args, value_parser}; +use firewood::db::{Db, DbConfig}; +use firewood::v2::api; + +use crate::DatabasePath; + +#[derive(Args, Debug)] +pub struct Options { + #[command(flatten)] + pub database: DatabasePath, + + #[arg( + long, + required = false, + value_parser = value_parser!(bool), + default_missing_value = "false", + default_value_t = true, + value_name = "TRUNCATE", + help = "Whether to truncate the DB when opening it. If set, the DB will be reset and all its + existing contents will be lost" + )] + pub truncate: bool, + + /// WAL Config + #[arg( + long, + required = false, + default_value_t = 22, + value_name = "WAL_FILE_NBIT", + help = "Size of WAL file." + )] + file_nbit: u64, + + #[arg( + long, + required = false, + default_value_t = 100, + value_name = "Wal_MAX_REVISIONS", + help = "Number of revisions to keep from the past. This preserves a rolling window + of the past N commits to the database." + )] + max_revisions: u32, +} + +pub(super) fn new(opts: &Options) -> DbConfig { + DbConfig::builder().truncate(opts.truncate).build() +} + +pub(super) fn run(opts: &Options) -> Result<(), api::Error> { + let db_config = new(opts); + log::debug!("database configuration parameters: \n{db_config:?}\n"); + + Db::new(opts.database.dbpath.clone(), db_config)?; + println!( + "created firewood database in {}", + opts.database.dbpath.display() + ); + Ok(()) +} diff --git a/firewood/fwdctl/src/delete.rs b/firewood/fwdctl/src/delete.rs new file mode 100644 index 000000000000..f59e71166f8b --- /dev/null +++ b/firewood/fwdctl/src/delete.rs @@ -0,0 +1,34 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use clap::Args; +use firewood::db::{BatchOp, Db, DbConfig}; +use firewood::v2::api::{self, Db as _, Proposal as _}; + +use crate::DatabasePath; + +#[derive(Debug, Args)] +pub struct Options { + #[command(flatten)] + pub database: DatabasePath, + + /// The key to delete + #[arg(required = true, value_name = "KEY", help = "Key to delete")] + pub key: String, +} + +pub(super) fn run(opts: &Options) -> Result<(), api::Error> { + log::debug!("deleting key {opts:?}"); + let cfg = DbConfig::builder().create_if_missing(false).truncate(false); + + let db = Db::new(opts.database.dbpath.clone(), cfg.build())?; + + let batch: Vec> = vec![BatchOp::Delete { + key: opts.key.clone(), + }]; + let proposal = db.propose(batch)?; + proposal.commit()?; + + println!("key {} deleted successfully", opts.key); + Ok(()) +} diff --git a/firewood/fwdctl/src/dump.rs b/firewood/fwdctl/src/dump.rs new file mode 100644 index 000000000000..f1c3b776d944 --- /dev/null +++ b/firewood/fwdctl/src/dump.rs @@ -0,0 +1,350 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. +use clap::Args; +use firewood::db::{Db, DbConfig}; +use firewood::iter::MerkleKeyValueIter; +use firewood::merkle::{Key, Value}; +use firewood::v2::api::{self, Db as _}; +use firewood_storage::FileIoError; +use std::borrow::Cow; +use std::error::Error; +use std::fs::File; +use std::io::{BufWriter, Write}; +use std::path::PathBuf; + +use crate::DatabasePath; + +type KeyFromStream = Option>; + +#[derive(Debug, clap::ValueEnum, Clone, PartialEq)] +pub enum OutputFormat { + Csv, + Json, + Stdout, + Dot, +} + +#[derive(Debug, Args)] +pub struct Options { + #[command(flatten)] + pub database: DatabasePath, + + /// The key to start dumping from (if no key is provided, start from the beginning). + /// Defaults to None. + #[arg( + short = 's', + long, + required = false, + value_name = "START_KEY", + value_parser = key_parser, + help = "Start dumping from this key (inclusive)." + )] + pub start_key: Option, + + /// The key to stop dumping to (if no key is provided, stop to the end). + /// Defaults to None. + #[arg( + short = 'S', + long, + required = false, + value_name = "STOP_KEY", + value_parser = key_parser, + help = "Stop dumping to this key (inclusive)." + )] + pub stop_key: Option, + + /// The key to start dumping from (if no key is provided, start from the beginning) in hex format. + /// Defaults to None. + #[arg( + long, + required = false, + conflicts_with = "start_key", + value_name = "START_KEY_HEX", + value_parser = key_parser_hex, + help = "Start dumping from this key (inclusive) in hex format. Conflicts with start_key" + )] + pub start_key_hex: Option, + + /// The key to stop dumping to (if no key is provided, stop to the end) in hex format. + /// Defaults to None. + #[arg( + long, + required = false, + conflicts_with = "stop_key", + value_name = "STOP_KEY_HEX", + value_parser = key_parser_hex, + help = "Stop dumping to this key (inclusive) in hex format. Conflicts with stop_key" + )] + pub stop_key_hex: Option, + + /// The max number of the keys going to be dumped. + /// Defaults to None. + #[arg( + short = 'm', + long, + required = false, + value_name = "MAX_KEY_COUNT", + help = "Maximum number of keys going to be dumped." + )] + pub max_key_count: Option, + + /// The output format of database dump. + /// Defaults to "stdout" + #[arg( + short = 'o', + long, + required = false, + value_name = "OUTPUT_FORMAT", + value_enum, + default_value_t = OutputFormat::Stdout, + help = "Output format of database dump, default to stdout. CSV, JSON, and DOT formats are available." + )] + pub output_format: OutputFormat, + + /// The output file name of database dump. + /// Output format must be set when the file name is set. + #[arg( + short = 'f', + long, + requires = "output_format", + value_name = "OUTPUT_FILE_NAME", + default_value = "dump", + help = "Output file name of database dump, default to dump. Output format must be set when the file name is set." + )] + pub output_file_name: PathBuf, + + #[arg(short = 'x', long, help = "Print the keys and values in hex format.")] + pub hex: bool, +} + +pub(super) fn run(opts: &Options) -> Result<(), api::Error> { + log::debug!("dump database {opts:?}"); + + // Check if dot format is used with unsupported options + if opts.output_format == OutputFormat::Dot { + if opts.start_key.is_some() || opts.start_key_hex.is_some() { + return Err(api::Error::InternalError(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Dot format does not support --start-key or --start-key-hex options", + )))); + } + if opts.stop_key.is_some() || opts.stop_key_hex.is_some() { + return Err(api::Error::InternalError(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Dot format does not support --stop-key or --stop-key-hex options", + )))); + } + if opts.max_key_count.is_some() { + return Err(api::Error::InternalError(Box::new(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "Dot format does not support --max-key-count option", + )))); + } + } + + let cfg = DbConfig::builder().create_if_missing(false).truncate(false); + let db = Db::new(opts.database.dbpath.clone(), cfg.build())?; + let latest_hash = db.root_hash()?; + let Some(latest_hash) = latest_hash else { + println!("Database is empty"); + return Ok(()); + }; + let latest_rev = db.revision(latest_hash)?; + + let Some(mut output_handler) = + create_output_handler(opts, &db).expect("Error creating output handler") + else { + // dot format is generated in the handler + return Ok(()); + }; + + let start_key = opts + .start_key + .clone() + .or(opts.start_key_hex.clone()) + .unwrap_or_default(); + let stop_key = opts.stop_key.clone().or(opts.stop_key_hex.clone()); + let mut key_count: u32 = 0; + + let mut iter = MerkleKeyValueIter::from_key(&latest_rev, start_key); + + while let Some(item) = iter.next() { + match item { + Ok((key, value)) => { + output_handler.handle_record(&key, &value)?; + + key_count = key_count.saturating_add(1); + + if (stop_key.as_ref().is_some_and(|stop_key| key >= *stop_key)) + || key_count_exceeded(opts.max_key_count, key_count) + { + handle_next_key(iter.next()); + break; + } + } + Err(e) => return Err(e.into()), + } + } + output_handler.flush()?; + + Ok(()) +} + +fn key_count_exceeded(max: Option, key_count: u32) -> bool { + max.is_some_and(|max| key_count >= max) +} + +fn u8_to_string(data: &[u8]) -> Cow<'_, str> { + String::from_utf8_lossy(data) +} + +fn key_parser(s: &str) -> Result, std::io::Error> { + Ok(Box::from(s.as_bytes())) +} + +fn key_parser_hex(s: &str) -> Result, std::io::Error> { + hex::decode(s) + .map(Vec::into_boxed_slice) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e)) +} + +// Helper function to convert key and value to a string +fn key_value_to_string(key: &[u8], value: &[u8], hex: bool) -> (String, String) { + let key_str = if hex { + hex::encode(key) + } else { + u8_to_string(key).to_string() + }; + let value_str = if hex { + hex::encode(value) + } else { + u8_to_string(value).to_string() + }; + (key_str, value_str) +} + +fn handle_next_key(next_key: KeyFromStream) { + match next_key { + Some(Ok((key, _))) => { + println!( + "Next key is {0}, resume with \"--start-key={0}\" or \"--start-key-hex={1}\".", + u8_to_string(&key), + hex::encode(&key) + ); + } + Some(Err(e)) => { + eprintln!("Error occurred while fetching the next key: {e}."); + } + None => { + println!("There is no next key. Data dump completed."); + } + } +} + +trait OutputHandler { + fn handle_record(&mut self, key: &[u8], value: &[u8]) -> Result<(), std::io::Error>; + fn flush(&mut self) -> Result<(), std::io::Error>; +} + +struct CsvOutputHandler { + writer: csv::Writer, + hex: bool, +} + +impl OutputHandler for CsvOutputHandler { + fn handle_record(&mut self, key: &[u8], value: &[u8]) -> Result<(), std::io::Error> { + let (key_str, value_str) = key_value_to_string(key, value, self.hex); + self.writer.write_record(&[key_str, value_str])?; + Ok(()) + } + + fn flush(&mut self) -> Result<(), std::io::Error> { + self.writer.flush()?; + Ok(()) + } +} + +struct JsonOutputHandler { + writer: BufWriter, + hex: bool, + is_first: bool, +} + +impl OutputHandler for JsonOutputHandler { + fn handle_record(&mut self, key: &[u8], value: &[u8]) -> Result<(), std::io::Error> { + let (key_str, value_str) = key_value_to_string(key, value, self.hex); + if self.is_first { + self.writer.write_all(b"{\n")?; + self.is_first = false; + } else { + self.writer.write_all(b",\n")?; + } + + write!(self.writer, r#" "{key_str}": "{value_str}""#)?; + Ok(()) + } + + fn flush(&mut self) -> Result<(), std::io::Error> { + let _ = self.writer.write(b"\n}\n"); + self.writer.flush()?; + Ok(()) + } +} + +struct StdoutOutputHandler { + hex: bool, +} + +impl OutputHandler for StdoutOutputHandler { + fn handle_record(&mut self, key: &[u8], value: &[u8]) -> Result<(), std::io::Error> { + let (key_str, value_str) = key_value_to_string(key, value, self.hex); + println!("'{key_str}': '{value_str}'"); + Ok(()) + } + fn flush(&mut self) -> Result<(), std::io::Error> { + Ok(()) + } +} + +fn create_output_handler( + opts: &Options, + db: &Db, +) -> Result>, Box> { + let hex = opts.hex; + let mut file_name = opts.output_file_name.clone(); + let extension = match opts.output_format { + OutputFormat::Csv => "csv", + OutputFormat::Json => "json", + OutputFormat::Stdout => "txt", + OutputFormat::Dot => "dot", + }; + file_name.set_extension(extension); + match opts.output_format { + OutputFormat::Csv => { + println!("Dumping to {}", file_name.display()); + let file = File::create(file_name)?; + Ok(Some(Box::new(CsvOutputHandler { + writer: csv::Writer::from_writer(file), + hex, + }))) + } + OutputFormat::Json => { + println!("Dumping to {}", file_name.display()); + let file = File::create(file_name)?; + Ok(Some(Box::new(JsonOutputHandler { + writer: BufWriter::new(file), + hex, + is_first: true, + }))) + } + OutputFormat::Stdout => Ok(Some(Box::new(StdoutOutputHandler { hex }))), + OutputFormat::Dot => { + println!("Dumping to {}", file_name.display()); + let file = File::create(file_name)?; + let mut writer = BufWriter::new(file); + // For dot format, we generate the output immediately since it doesn't use streaming + db.dump(&mut writer)?; + Ok(None) + } + } +} diff --git a/firewood/fwdctl/src/get.rs b/firewood/fwdctl/src/get.rs new file mode 100644 index 000000000000..7f357fbcc953 --- /dev/null +++ b/firewood/fwdctl/src/get.rs @@ -0,0 +1,48 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use clap::Args; + +use firewood::db::{Db, DbConfig}; +use firewood::v2::api::{self, Db as _, DbView as _}; + +use crate::DatabasePath; + +#[derive(Debug, Args)] +pub struct Options { + #[command(flatten)] + pub database: DatabasePath, + + /// The key to get the value for + #[arg(required = true, value_name = "KEY", help = "Key to get")] + pub key: String, +} + +pub(super) fn run(opts: &Options) -> Result<(), api::Error> { + log::debug!("get key value pair {opts:?}"); + let cfg = DbConfig::builder().create_if_missing(false).truncate(false); + + let db = Db::new(opts.database.dbpath.clone(), cfg.build())?; + + let hash = db.root_hash()?; + + let Some(hash) = hash else { + println!("Database is empty"); + return Ok(()); + }; + + let rev = db.revision(hash)?; + + match rev.val(opts.key.as_bytes()) { + Ok(Some(val)) => { + let s = String::from_utf8_lossy(val.as_ref()); + println!("{s:?}"); + Ok(()) + } + Ok(None) => { + eprintln!("Key '{}' not found", opts.key); + Ok(()) + } + Err(e) => Err(e), + } +} diff --git a/firewood/fwdctl/src/graph.rs b/firewood/fwdctl/src/graph.rs new file mode 100644 index 000000000000..fbc14477db20 --- /dev/null +++ b/firewood/fwdctl/src/graph.rs @@ -0,0 +1,24 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use clap::Args; +use firewood::db::{Db, DbConfig}; +use firewood::v2::api; +use std::io::stdout; + +use crate::DatabasePath; + +#[derive(Debug, Args)] +pub struct Options { + #[command(flatten)] + pub database: DatabasePath, +} + +pub(super) fn run(opts: &Options) -> Result<(), api::Error> { + log::debug!("dump database {opts:?}"); + let cfg = DbConfig::builder().create_if_missing(false).truncate(false); + + let db = Db::new(opts.database.dbpath.clone(), cfg.build())?; + db.dump(&mut stdout())?; + Ok(()) +} diff --git a/firewood/fwdctl/src/insert.rs b/firewood/fwdctl/src/insert.rs new file mode 100644 index 000000000000..bce652195cf2 --- /dev/null +++ b/firewood/fwdctl/src/insert.rs @@ -0,0 +1,39 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use clap::Args; +use firewood::db::{BatchOp, Db, DbConfig}; +use firewood::v2::api::{self, Db as _, Proposal as _}; + +use crate::DatabasePath; + +#[derive(Debug, Args)] +pub struct Options { + #[command(flatten)] + pub database: DatabasePath, + + /// The key to insert + #[arg(required = true, value_name = "KEY", help = "Key to insert")] + pub key: String, + + /// The value to insert + #[arg(required = true, value_name = "VALUE", help = "Value to insert")] + pub value: String, +} + +pub(super) fn run(opts: &Options) -> Result<(), api::Error> { + log::debug!("inserting key value pair {opts:?}"); + let cfg = DbConfig::builder().create_if_missing(false).truncate(false); + + let db = Db::new(opts.database.dbpath.clone(), cfg.build())?; + + let batch: Vec, Vec>> = vec![BatchOp::Put { + key: opts.key.clone().into(), + value: opts.value.bytes().collect(), + }]; + let proposal = db.propose(batch)?; + proposal.commit()?; + + println!("{}", opts.key); + Ok(()) +} diff --git a/firewood/fwdctl/src/main.rs b/firewood/fwdctl/src/main.rs new file mode 100644 index 000000000000..3dfd7021af36 --- /dev/null +++ b/firewood/fwdctl/src/main.rs @@ -0,0 +1,95 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![doc = include_str!("../README.md")] + +use std::path::PathBuf; + +use clap::{Parser, Subcommand}; +use firewood::v2::api; + +pub mod check; +pub mod create; +pub mod delete; +pub mod dump; +pub mod get; +pub mod graph; +pub mod insert; +pub mod root; + +#[derive(Clone, Debug, Parser)] +pub struct DatabasePath { + /// The database path. Defaults to firewood.db + #[arg( + long = "db", + short = 'd', + required = false, + value_name = "DB_NAME", + default_value_os_t = default_db_path(), + help = "Name of the database" + )] + pub dbpath: PathBuf, +} + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +#[command(propagate_version = true)] +#[command(version = concat!(env!("CARGO_PKG_VERSION"), " (", env!("GIT_COMMIT_SHA"), ", ", env!("ETHHASH_FEATURE"), ")"))] +struct Cli { + #[command(subcommand)] + command: Commands, + #[arg( + long, + short = 'l', + required = false, + help = "Log level. Respects RUST_LOG.", + value_name = "LOG_LEVEL", + num_args = 1, + value_parser = ["debug", "info"], + default_value_t = String::from("info"), + )] + log_level: String, +} + +#[derive(Subcommand)] +enum Commands { + /// Create a new firewood database + Create(create::Options), + /// Insert a key/value pair into the database + Insert(insert::Options), + /// Get values associated with a key + Get(get::Options), + /// Delete values associated with a key + Delete(delete::Options), + /// Display key/value trie root hash + Root(root::Options), + /// Dump contents of key/value store + Dump(dump::Options), + /// Produce a dot file of the database + Graph(graph::Options), + /// Runs the checker on the database + Check(check::Options), +} + +fn main() -> Result<(), api::Error> { + let cli = Cli::parse(); + + env_logger::init_from_env( + env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, cli.log_level.clone()), + ); + + match &cli.command { + Commands::Create(opts) => create::run(opts), + Commands::Insert(opts) => insert::run(opts), + Commands::Get(opts) => get::run(opts), + Commands::Delete(opts) => delete::run(opts), + Commands::Root(opts) => root::run(opts), + Commands::Dump(opts) => dump::run(opts), + Commands::Graph(opts) => graph::run(opts), + Commands::Check(opts) => check::run(opts), + } +} + +fn default_db_path() -> PathBuf { + PathBuf::from("firewood.db") +} diff --git a/firewood/fwdctl/src/root.rs b/firewood/fwdctl/src/root.rs new file mode 100644 index 000000000000..522253808e27 --- /dev/null +++ b/firewood/fwdctl/src/root.rs @@ -0,0 +1,26 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use clap::Args; + +use firewood::db::{Db, DbConfig}; +use firewood::v2::api::{self, Db as _}; + +use crate::DatabasePath; + +#[derive(Debug, Args)] +pub struct Options { + #[command(flatten)] + pub database: DatabasePath, +} + +pub(super) fn run(opts: &Options) -> Result<(), api::Error> { + let cfg = DbConfig::builder().create_if_missing(false).truncate(false); + + let db = Db::new(opts.database.dbpath.clone(), cfg.build())?; + + let hash = db.root_hash()?; + + println!("{hash:?}"); + Ok(()) +} diff --git a/firewood/fwdctl/tests/cli.rs b/firewood/fwdctl/tests/cli.rs new file mode 100644 index 000000000000..aa072c7b51c0 --- /dev/null +++ b/firewood/fwdctl/tests/cli.rs @@ -0,0 +1,637 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use anyhow::{Result, anyhow}; +use predicates::prelude::*; +use serial_test::serial; +use std::fs::{self, remove_file}; +use std::path::{Path, PathBuf}; + +const PRG: &str = "fwdctl"; +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +macro_rules! cargo_bin_cmd { + () => { + ::assert_cmd::cargo::cargo_bin_cmd!("fwdctl") + }; +} + +// Removes the firewood database on disk +fn fwdctl_delete_db() -> Result<()> { + if let Err(e) = remove_file(tmpdb::path()) { + eprintln!("failed to delete testing dir: {e}"); + return Err(anyhow!(e)); + } + + Ok(()) +} + +#[test] +#[serial] +fn fwdctl_prints_version() -> Result<()> { + let expected_version_output: String = format!("{PRG} {VERSION}"); + + // version is defined and succeeds with the desired output + cargo_bin_cmd!() + .args(["-V"]) + .assert() + .success() + .stdout(predicate::str::contains(expected_version_output)); + + Ok(()) +} + +#[test] +#[serial] +fn fwdctl_creates_database() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_insert_successful() -> Result<()> { + // Create db + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + // Insert data + cargo_bin_cmd!() + .arg("insert") + .args(["year"]) + .args(["2023"]) + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::contains("year")); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_get_successful() -> Result<()> { + // Create db and insert data + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("insert") + .args(["year"]) + .args(["2023"]) + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::contains("year")); + + // Get value back out + cargo_bin_cmd!() + .arg("get") + .args(["year"]) + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::contains("2023")); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_delete_successful() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("insert") + .args(["year"]) + .args(["2023"]) + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::contains("year")); + + // Delete key -- prints raw data of deleted value + cargo_bin_cmd!() + .arg("delete") + .args(["year"]) + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::contains("key year deleted successfully")); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_root_hash() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("insert") + .args(["year"]) + .args(["2023"]) + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::contains("year")); + + // Get root + cargo_bin_cmd!() + .arg("root") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::is_empty().not()); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_dump() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("insert") + .args(["year"]) + .args(["2023"]) + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::contains("year")); + + // Get root + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success() + .stdout(predicate::str::contains("2023")); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_dump_with_start_stop_and_max() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["a"]) + .args(["1"]) + .assert() + .success() + .stdout(predicate::str::contains("a")); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["b"]) + .args(["2"]) + .assert() + .success() + .stdout(predicate::str::contains("b")); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["c"]) + .args(["3"]) + .assert() + .success() + .stdout(predicate::str::contains("c")); + + // Test stop in the middle + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--stop-key"]) + .arg("b") + .assert() + .success() + .stdout(predicate::str::contains( + "Next key is c, resume with \"--start-key=c\"", + )); + + // Test stop in the end + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--stop-key"]) + .arg("c") + .assert() + .success() + .stdout(predicate::str::contains( + "There is no next key. Data dump completed.", + )); + + // Test start in the middle + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--start-key"]) + .arg("b") + .assert() + .success() + .stdout(predicate::str::starts_with("\'b")); + + // Test start and stop + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--start-key"]) + .arg("b") + .args(["--stop-key"]) + .arg("b") + .assert() + .success() + .stdout(predicate::str::starts_with("\'b")) + .stdout(predicate::str::contains( + "Next key is c, resume with \"--start-key=c\"", + )); + + // Test start and stop + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--start-key"]) + .arg("b") + .args(["--max-key-count"]) + .arg("1") + .assert() + .success() + .stdout(predicate::str::starts_with("\'b")) + .stdout(predicate::str::contains( + "Next key is c, resume with \"--start-key=c\"", + )); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_dump_with_csv_and_json() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["a"]) + .args(["1"]) + .assert() + .success() + .stdout(predicate::str::contains("a")); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["b"]) + .args(["2"]) + .assert() + .success() + .stdout(predicate::str::contains("b")); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["c"]) + .args(["3"]) + .assert() + .success() + .stdout(predicate::str::contains("c")); + + // Test output csv + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--output-format"]) + .arg("csv") + .assert() + .success() + .stdout(predicate::str::contains("Dumping to dump.csv")); + + let contents = fs::read_to_string("dump.csv").expect("Should read dump.csv file"); + assert_eq!(contents, "a,1\nb,2\nc,3\n"); + fs::remove_file("dump.csv").expect("Should remove dump.csv file"); + + // Test output json + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--output-format"]) + .arg("json") + .assert() + .success() + .stdout(predicate::str::contains("Dumping to dump.json")); + + let contents = fs::read_to_string("dump.json").expect("Should read dump.json file"); + assert_eq!( + contents, + "{\n \"a\": \"1\",\n \"b\": \"2\",\n \"c\": \"3\"\n}\n" + ); + fs::remove_file("dump.json").expect("Should remove dump.json file"); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_dump_with_file_name() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["a"]) + .args(["1"]) + .assert() + .success() + .stdout(predicate::str::contains("a")); + + // Test without output format + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--output-file-name"]) + .arg("test") + .assert() + .failure() + .stderr(predicate::str::contains("--output-format")); + + // Test output csv + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--output-format"]) + .arg("csv") + .args(["--output-file-name"]) + .arg("test") + .assert() + .success() + .stdout(predicate::str::contains("Dumping to test.csv")); + + let contents = fs::read_to_string("test.csv").expect("Should read test.csv file"); + assert_eq!(contents, "a,1\n"); + fs::remove_file("test.csv").expect("Should remove test.csv file"); + + // Test output json + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--output-format"]) + .arg("json") + .args(["--output-file-name"]) + .arg("test") + .assert() + .success() + .stdout(predicate::str::contains("Dumping to test.json")); + + let contents = fs::read_to_string("test.json").expect("Should read test.json file"); + assert_eq!(contents, "{\n \"a\": \"1\"\n}\n"); + fs::remove_file("test.json").expect("Should remove test.json file"); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_dump_with_hex() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["a"]) + .args(["1"]) + .assert() + .success() + .stdout(predicate::str::contains("a")); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["b"]) + .args(["2"]) + .assert() + .success() + .stdout(predicate::str::contains("b")); + + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args(["c"]) + .args(["3"]) + .assert() + .success() + .stdout(predicate::str::contains("c")); + + // Test without output format + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--start-key"]) + .arg("a") + .args(["--start-key-hex"]) + .arg("61") + .assert() + .failure() + .stderr(predicate::str::contains("--start-key")) + .stderr(predicate::str::contains("--start-key-hex")); + + // Test start with hex value + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--start-key-hex"]) + .arg("62") + .assert() + .success() + .stdout(predicate::str::starts_with("\'b")); + + // Test stop with hex value + cargo_bin_cmd!() + .arg("dump") + .arg("--db") + .arg(tmpdb::path()) + .args(["--stop-key-hex"]) + .arg("62") + .assert() + .success() + .stdout(predicate::str::starts_with("\'a")) + .stdout(predicate::str::contains("Next key is c")) + .stdout(predicate::str::contains("--start-key=c")) + .stdout(predicate::str::contains("--start-key-hex=63")); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_check_empty_db() -> Result<()> { + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + cargo_bin_cmd!() + .arg("check") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + fwdctl_delete_db() +} + +#[test] +#[serial] +fn fwdctl_check_db_with_data() -> Result<()> { + use rand::{Rng, distr::Alphanumeric}; + let rng = firewood_storage::SeededRng::from_env_or_random(); + let mut sample_iter = rng.sample_iter(Alphanumeric).map(char::from); + + cargo_bin_cmd!() + .arg("create") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + // TODO: bulk loading data instead of inserting one by one + for _ in 0..4 { + let key = sample_iter.by_ref().take(64).collect::(); + let value = sample_iter.by_ref().take(10).collect::(); + cargo_bin_cmd!() + .arg("insert") + .arg("--db") + .arg(tmpdb::path()) + .args([key]) + .args([value]) + .assert() + .success(); + } + + cargo_bin_cmd!() + .arg("check") + .arg("--db") + .arg(tmpdb::path()) + .assert() + .success(); + + fwdctl_delete_db() +} + +// A module to create a temporary database name for use in +// tests. The directory will be one of: +// - cargo's compile-time CARGO_TARGET_TMPDIR, if that exists +// - the value of the TMPDIR environment, if that is set, or +// - fallback to /tmp + +// using cargo's CARGO_TARGET_TMPDIR ensures that multiple runs +// of this in different directories will have different databases + +mod tmpdb { + use std::sync::OnceLock; + + use super::*; + + const FIREWOOD_TEST_DB_NAME: &str = "test_firewood"; + const TARGET_TMP_DIR: Option<&str> = option_env!("CARGO_TARGET_TMPDIR"); + + pub fn path() -> &'static Path { + static PATH: OnceLock = OnceLock::new(); + PATH.get_or_init(|| { + TARGET_TMP_DIR + .map(PathBuf::from) + .or_else(|| std::env::var("TMPDIR").ok().map(PathBuf::from)) + .unwrap_or(std::env::temp_dir()) + .join(FIREWOOD_TEST_DB_NAME) + }) + .as_path() + } +} diff --git a/firewood/justfile b/firewood/justfile new file mode 100644 index 000000000000..d0885778f5f0 --- /dev/null +++ b/firewood/justfile @@ -0,0 +1,140 @@ +# List available recipes +default: + ./scripts/run-just.sh --list + +# Build ffi with nix +build-ffi-nix: check-nix + cd ffi && nix build + +# Check if the git branch is clean +check-clean-branch: + #!/usr/bin/env bash + set -euo pipefail + + git add --all + git update-index --really-refresh >> /dev/null + + # Show the status of the working tree. + git status --short + + # Exits if any uncommitted changes are found. + git diff-index --quiet HEAD + +# Check if the FFI flake is up-to-date (requires clean git tree) +check-ffi-flake: check-nix + #!/usr/bin/env bash + set -euo pipefail + ./scripts/run-just.sh update-ffi-flake + ./scripts/run-just.sh check-clean-branch + +# Check if the golang version is set consistently (requires clean git tree) +check-golang-version: check-nix + #!/usr/bin/env bash + set -euo pipefail + + # Exit only at the end if any of the checks set FAILED=1 + FAILED= + + cd ffi + + TOOLCHAIN_VERSION=$(nix develop --command bash -c "go mod edit -json | jq -r '.Toolchain'") + echo "toolchain version in ffi/go.mod is ${TOOLCHAIN_VERSION}" + + ETH_TESTS_VERSION=$(nix develop --command bash -c "cd tests/eth && go mod edit -json | jq -r '.Toolchain'") + echo "toolchain version in ffi/tests/eth/go.mod is ${ETH_TESTS_VERSION}" + + if [[ "${TOOLCHAIN_VERSION}" != "${ETH_TESTS_VERSION}" ]]; then + echo "❌ toolchain version in ffi/tests/eth/go.mod should be ${TOOLCHAIN_VERSION}" + FAILED=1 + fi + + FIREWOOD_TESTS_VERSION=$(nix develop --command bash -c "cd tests/firewood && go mod edit -json | jq -r '.Toolchain'") + echo "toolchain version in ffi/tests/firewood/go.mod is ${FIREWOOD_TESTS_VERSION}" + + if [[ "${TOOLCHAIN_VERSION}" != "${FIREWOOD_TESTS_VERSION}" ]]; then + echo "❌ toolchain version in ffi/tests/firewood/go.mod should be ${TOOLCHAIN_VERSION}" + FAILED=1 + fi + + NIX_VERSION=$(nix run .#go -- version | awk '{print $3}') + echo "golang provided by ffi/flake.nix is ${NIX_VERSION}" + + if [[ "${TOOLCHAIN_VERSION}" != "${NIX_VERSION}" ]]; then + echo "❌ golang provided by ffi/flake/nix should be ${TOOLCHAIN_VERSION}" + echo "It will be necessary to update the golang.url in ffi/flake.nix to point to a SHA of"\ + "AvalancheGo whose nix/go/flake.nix provides ${TOOLCHAIN_VERSION}." + fi + + if [[ -n "${FAILED}" ]]; then + exit 1 + fi + +# Check if nix is installed +check-nix: + #!/usr/bin/env bash + set -euo pipefail + if ! command -v nix &> /dev/null; then + echo "Error: 'nix' is not installed." >&2 + echo "" >&2 + echo "To install nix:" >&2 + echo " - Visit: https://github.com/DeterminateSystems/nix-installer" >&2 + echo " - Or run: curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install" >&2 + exit 1 + fi + +# Adds go workspace for user experience consistency +setup-go-workspace: + #!/usr/bin/env bash + set -euo pipefail + if [ -f "go.work" ]; then + rm go.work go.work.sum + fi + go work init ./ffi ./ffi/tests/eth ./ffi/tests/firewood + +# Run all checks of ffi built with nix +test-ffi-nix: test-ffi-nix-build-equivalency test-ffi-nix-go-bindings + +# Test ffi build equivalency between nix and cargo +test-ffi-nix-build-equivalency: check-nix + #!/usr/bin/env bash + set -euo pipefail + + echo "Testing ffi build equivalency between nix and cargo" + + bash -x ./ffi/test-build-equivalency.sh + +# Test golang ffi bindings using the nix-built artifacts +test-ffi-nix-go-bindings: build-ffi-nix + #!/usr/bin/env bash + set -euo pipefail + + echo "running ffi tests against bindings built by nix..." + + cd ffi + + # Need to capture the flake path before changing directories to + # result/ffi because `result` is a nix store symlink so ../../ + # won't resolve to the ffi path containing the flake. + FLAKE_PATH="$PWD" + + # This runs golang outside a nix shell to validate viability + # without the env setup performed by a nix shell + GO="nix run $FLAKE_PATH#go" + + cd result/ffi + + # - cgocheck2 is expensive but provides complete pointer checks + # - use hash mode ethhash since the flake builds with `--features ethhash,logger` + GOEXPERIMENT=cgocheck2 TEST_FIREWOOD_HASH_MODE=ethhash ${GO} test ./... + +# Ensure the FFI flake is up-to-date +update-ffi-flake: check-nix + #!/usr/bin/env bash + set -euo pipefail + cd ffi + + echo "ensuring flake lock file is current for golang" + nix flake update golang + + echo "checking for a consistent golang verion" + ../scripts/run-just.sh check-golang-version diff --git a/firewood/scripts/run-just.sh b/firewood/scripts/run-just.sh new file mode 100755 index 000000000000..377bffdcc24e --- /dev/null +++ b/firewood/scripts/run-just.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +set -euo pipefail + +if command -v just &> /dev/null; then + exec just "$@" +elif command -v nix &> /dev/null; then + exec nix run nixpkgs#just -- "$@" +else + echo "Error: Neither 'just' nor 'nix' is installed." >&2 + echo "" >&2 + echo "Please install one of the following:" >&2 + echo "" >&2 + echo "Option 1 - Install just:" >&2 + echo " - Visit: https://github.com/casey/just#installation" >&2 + echo " - Or use cargo: cargo install just" >&2 + echo "" >&2 + echo "Option 2 - Install nix:" >&2 + echo " - Visit: https://github.com/DeterminateSystems/nix-installer" >&2 + echo " - Or run: curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install" >&2 + exit 1 +fi diff --git a/firewood/storage/BUILD.bazel b/firewood/storage/BUILD.bazel new file mode 100644 index 000000000000..c9f9e487a021 --- /dev/null +++ b/firewood/storage/BUILD.bazel @@ -0,0 +1,45 @@ +load("@rules_rust//rust:defs.bzl", "rust_library") + +exports_files(["Cargo.toml"]) + +rust_library( + name = "firewood-storage", + srcs = glob(["src/**/*.rs"]), + crate_features = [ + "ethhash", + "logger", + ], + crate_root = "src/lib.rs", + edition = "2024", + proc_macro_deps = [ + "@firewood_crates//:aquamarine", + "@firewood_crates//:bytemuck_derive", + "@firewood_crates//:derive-where", + "@firewood_crates//:enum-as-inner", + ], + visibility = ["//firewood:__subpackages__"], + deps = [ + "@firewood_crates//:bitfield", + "@firewood_crates//:bitflags", + "@firewood_crates//:bumpalo", + "@firewood_crates//:bytemuck", + "@firewood_crates//:bytes", + "@firewood_crates//:coarsetime", + "@firewood_crates//:fastrace", + "@firewood_crates//:hex", + "@firewood_crates//:indicatif", + "@firewood_crates//:integer-encoding", + "@firewood_crates//:log", + "@firewood_crates//:lru", + "@firewood_crates//:metrics", + "@firewood_crates//:nonzero_ext", + "@firewood_crates//:parking_lot", + "@firewood_crates//:rlp", + "@firewood_crates//:semver", + "@firewood_crates//:sha2", + "@firewood_crates//:sha3", + "@firewood_crates//:smallvec", + "@firewood_crates//:thiserror", + "@firewood_crates//:triomphe", + ], +) diff --git a/firewood/storage/Cargo.toml b/firewood/storage/Cargo.toml new file mode 100644 index 000000000000..b3be6bfb0ad8 --- /dev/null +++ b/firewood/storage/Cargo.toml @@ -0,0 +1,72 @@ +[package] +name = "firewood-storage" +version.workspace = true +edition.workspace = true +authors = [ + "Aaron Buchwald ", + "Ron Kuris ", + "Suyan Qu <36519575+qusuyan@users.noreply.github.com>", +] +description = "Storage layer for Firewood, an embedded key-value store optimized for blockchain state." +license-file.workspace = true +homepage.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# Workspace dependencies +aquamarine.workspace = true +bytemuck.workspace = true +bytemuck_derive.workspace = true +coarsetime.workspace = true +fastrace.workspace = true +hex.workspace = true +integer-encoding.workspace = true +metrics.workspace = true +nonzero_ext.workspace = true +rand = { workspace = true, optional = true } +sha2.workspace = true +smallvec.workspace = true +thiserror.workspace = true +# Regular dependencies +bitfield = "0.19.4" +bitflags = "2.10.0" +derive-where = "1.6.0" +enum-as-inner = "0.6.1" +indicatif = "0.18.3" +lru = "0.16.2" +semver = "1.0.27" +triomphe = "0.1.15" +parking_lot.workspace = true +# Optional dependencies +bytes = { version = "1.11.0", optional = true } +io-uring = { version = "0.7.11", optional = true } +log = { version = "0.4.28", optional = true } +rlp = { version = "0.6.1", optional = true } +sha3 = { version = "0.10.8", optional = true } +bumpalo = { version = "3.19.0", features = ["collections", "std"] } + +[dev-dependencies] +# Workspace dependencies +criterion = { workspace = true, features = ["html_reports"] } +pprof = { workspace = true, features = ["flamegraph"] } +rand.workspace = true +tempfile.workspace = true +test-case.workspace = true + +[features] +logger = ["log"] +branch_factor_256 = [] +io-uring = ["dep:io-uring"] +ethhash = ["dep:rlp", "dep:sha3", "dep:bytes"] +test_utils = ["dep:rand"] + +[[bench]] +name = "serializer" +harness = false + +[lints] +workspace = true diff --git a/firewood/storage/benches/serializer.rs b/firewood/storage/benches/serializer.rs new file mode 100644 index 000000000000..6005d7c49f5c --- /dev/null +++ b/firewood/storage/benches/serializer.rs @@ -0,0 +1,140 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::assigning_clones, + reason = "Found 1 occurrences after enabling the lint." +)] +#![expect( + clippy::unwrap_used, + reason = "Found 7 occurrences after enabling the lint." +)] + +use std::fs::File; +use std::os::raw::c_int; + +use criterion::profiler::Profiler; +use criterion::{Bencher, Criterion, criterion_group, criterion_main}; +use firewood_storage::{Children, LeafNode, Node, Path, PathComponent}; +use pprof::ProfilerGuard; +use smallvec::SmallVec; + +use std::path::Path as FsPath; + +// For flamegraphs: +// cargo bench --bench serializer -- --profile-time=5 + +enum FlamegraphProfiler { + Init(c_int), + Active(ProfilerGuard<'static>), +} + +fn file_error_panic(path: &FsPath) -> impl FnOnce(T) -> U { + |_| panic!("Error on file `{}`", path.display()) +} + +impl Profiler for FlamegraphProfiler { + #[expect(clippy::unwrap_used)] + fn start_profiling(&mut self, _benchmark_id: &str, _benchmark_dir: &FsPath) { + if let Self::Init(frequency) = self { + let guard = ProfilerGuard::new(*frequency).unwrap(); + *self = Self::Active(guard); + } + } + + #[expect(clippy::unwrap_used)] + fn stop_profiling(&mut self, _benchmark_id: &str, benchmark_dir: &FsPath) { + std::fs::create_dir_all(benchmark_dir).unwrap(); + let filename = "firewood-flamegraph.svg"; + let flamegraph_path = benchmark_dir.join(filename); + let flamegraph_file = + File::create(&flamegraph_path).unwrap_or_else(file_error_panic(&flamegraph_path)); + + if let Self::Active(profiler) = self { + profiler + .report() + .build() + .unwrap() + .flamegraph(flamegraph_file) + .unwrap_or_else(file_error_panic(&flamegraph_path)); + } + } +} + +fn manual_serializer(b: &mut Bencher, input: &Node) { + b.iter(|| to_bytes(input)); +} + +fn manual_deserializer(b: &mut Bencher, input: &Vec) { + let (_area_index, input) = input + .as_slice() + .split_first() + .expect("always has at least one byte"); + b.iter(|| Node::from_reader(&mut std::io::Cursor::new(input)).expect("to deserialize node")); +} + +fn to_bytes(input: &Node) -> Vec { + let mut bytes = Vec::new(); + input.as_bytes(firewood_storage::AreaIndex::MIN, &mut bytes); + bytes +} + +fn leaf(c: &mut Criterion) { + let mut group = c.benchmark_group("leaf"); + let input = Node::Leaf(LeafNode { + partial_path: Path(SmallVec::from_slice(&[0, 1])), + value: Box::new([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]), + }); + + group.bench_with_input("manual", &input, manual_serializer); + group.bench_with_input("from_reader", &to_bytes(&input), manual_deserializer); + group.finish(); +} + +fn branch(c: &mut Criterion) { + let mut group = c.benchmark_group("has_value"); + let mut input = Node::Branch(Box::new(firewood_storage::BranchNode { + partial_path: Path(SmallVec::from_slice(&[0, 1])), + value: Some(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9].into_boxed_slice()), + children: Children::from_fn(|i| { + if i.as_u8() == 0 { + Some(firewood_storage::Child::AddressWithHash( + firewood_storage::LinearAddress::new(1).unwrap(), + firewood_storage::HashType::from([0; 32]), + )) + } else { + None + } + }), + })); + + group.bench_with_input("manual", &input, manual_serializer); + group.bench_with_input("from_reader", &to_bytes(&input), manual_deserializer); + group.finish(); + + let mut group = c.benchmark_group("1_child"); + input.as_branch_mut().unwrap().value = None; + group.bench_with_input("manual", &input, manual_serializer); + group.bench_with_input("from_reader", &to_bytes(&input), manual_deserializer); + group.finish(); + + let child = input.as_branch().unwrap().children[PathComponent::ALL[0]].clone(); + let mut group = c.benchmark_group("2_child"); + input.as_branch_mut().unwrap().children[PathComponent::ALL[1]] = child.clone(); + group.bench_with_input("manual", &input, manual_serializer); + group.bench_with_input("from_reader", &to_bytes(&input), manual_deserializer); + group.finish(); + + let mut group = c.benchmark_group("16_child"); + input.as_branch_mut().unwrap().children = Children::from_fn(|_| child.clone()); + group.bench_with_input("manual", &input, manual_serializer); + group.bench_with_input("from_reader", &to_bytes(&input), manual_deserializer); + group.finish(); +} + +criterion_group!( + name = serializers; + config = Criterion::default().with_profiler(FlamegraphProfiler::Init(100)); + targets = leaf, branch +); +criterion_main!(serializers); diff --git a/firewood/storage/src/checker/mod.rs b/firewood/storage/src/checker/mod.rs new file mode 100644 index 000000000000..d4dbdf841893 --- /dev/null +++ b/firewood/storage/src/checker/mod.rs @@ -0,0 +1,1360 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +mod range_set; +pub(crate) use range_set::LinearAddressRangeSet; + +use crate::logger::warn; +use crate::nodestore::alloc::FreeAreaWithMetadata; +use crate::nodestore::primitives::{AreaIndex, area_size_iter}; +use crate::{ + CheckerError, Committed, FileIoError, HashType, HashedNodeReader, ImmutableProposal, + IntoHashType, LinearAddress, MutableProposal, Node, NodeReader, NodeStore, Path, + ReadableStorage, RootReader, StoredAreaParent, TrieNodeParent, WritableStorage, +}; + +#[cfg(not(feature = "ethhash"))] +use crate::hashednode::hash_node; + +use std::cmp::Ordering; +use std::collections::BTreeMap; +use std::ops::Range; +use std::sync::Arc; + +use indicatif::ProgressBar; + +const OS_PAGE_SIZE: u64 = 4096; + +#[inline] +// return u64 since the start address may be 0 +const fn page_number(addr: LinearAddress) -> u64 { + addr.get() / OS_PAGE_SIZE +} + +fn extra_read_pages(addr: LinearAddress, bytes: u64) -> Option { + let start_page = page_number(addr); + let end_page = page_number(addr.advance(bytes.saturating_sub(1))?); + let pages_read = end_page.saturating_sub(start_page).saturating_add(1); // Include the first page + let min_pages = bytes.saturating_add(OS_PAGE_SIZE - 1) / OS_PAGE_SIZE; // Round up to the nearest page + Some(pages_read.saturating_sub(min_pages)) +} + +#[cfg(feature = "ethhash")] +fn is_valid_key(key: &Path) -> bool { + const VALID_ETH_KEY_SIZES: [usize; 2] = [64, 128]; // in number of nibbles - two nibbles make a byte + VALID_ETH_KEY_SIZES.contains(&key.0.len()) +} + +#[cfg(not(feature = "ethhash"))] +fn is_valid_key(key: &Path) -> bool { + key.0.len().is_multiple_of(2) +} + +/// Options for the checker +#[derive(Debug)] +pub struct CheckOpt { + /// Whether to check the hash of the nodes + pub hash_check: bool, + /// Optional progress bar to show the checker progress + pub progress_bar: Option, +} + +/// Report of the checker results. +#[derive(Debug)] +pub struct CheckerReport { + /// Errors encountered during the check + pub errors: Vec, + /// Statistics about the database + pub db_stats: DBStats, +} + +/// All statistics about the given database image +#[derive(Debug, Default)] +pub struct DBStats { + /// The high watermark of the database + pub high_watermark: u64, + /// Statistics about the trie + pub trie_stats: TrieStats, + /// Statistics about the free list + pub free_list_stats: FreeListsStats, +} + +/// Statistics about the trie +#[derive(Debug, PartialEq)] +pub struct TrieStats { + /// The total number of bytes of compressed branch nodes + pub branch_bytes: u64, + /// The total number of bytes of compressed leaf nodes + pub leaf_bytes: u64, + /// The number of key-value pairs stored in the trie + pub kv_count: u64, + /// The total number of bytes of for key-value pairs stored in the trie + pub kv_bytes: u64, + /// Branching factor distribution of each branch node + pub branching_factors: BTreeMap, + /// Depth distribution of each leaf node + pub depths: BTreeMap, + /// The distribution of area sizes for branch nodes + pub branch_area_counts: BTreeMap, + /// The distribution of area sizes for leaf nodes + pub leaf_area_counts: BTreeMap, + /// Branches that can fit into a smaller area + pub low_occupancy_branch_area_count: u64, + /// Leaves that can fit into a smaller area + pub low_occupancy_leaf_area_count: u64, + /// The number of areas that span an extra page due to not being aligned + pub area_extra_unaligned_page: u64, + /// The number of nodes that span an extra page due to not being aligned + pub node_extra_unaligned_page: u64, +} + +impl Default for TrieStats { + fn default() -> Self { + Self { + branch_bytes: 0, + leaf_bytes: 0, + kv_count: 0, + kv_bytes: 0, + branching_factors: BTreeMap::new(), + depths: BTreeMap::new(), + branch_area_counts: area_size_iter().map(|(_, size)| (size, 0)).collect(), + leaf_area_counts: area_size_iter().map(|(_, size)| (size, 0)).collect(), + low_occupancy_branch_area_count: 0, + low_occupancy_leaf_area_count: 0, + area_extra_unaligned_page: 0, + node_extra_unaligned_page: 0, + } + } +} + +/// Statistics about the free list +#[derive(Debug, PartialEq)] +pub struct FreeListsStats { + /// The distribution of area sizes in the free lists + pub area_counts: BTreeMap, + /// The number of free areas that span an extra page due to not being aligned + pub area_extra_unaligned_page: u64, +} + +impl Default for FreeListsStats { + fn default() -> Self { + Self { + area_counts: area_size_iter().map(|(_, size)| (size, 0)).collect(), + area_extra_unaligned_page: 0, + } + } +} + +struct SubTrieMetadata { + root_address: LinearAddress, + root_hash: HashType, + parent: TrieNodeParent, + depth: usize, + path_prefix: Path, + #[cfg(feature = "ethhash")] + has_peers: bool, +} + +/// [`NodeStore`] checker +#[expect(clippy::result_large_err)] +impl NodeStore +where + NodeStore: HashedNodeReader, +{ + /// Go through the filebacked storage and check for any inconsistencies. It proceeds in the following steps: + /// 1. Check the header + /// 2. traverse the trie and check the nodes + /// 3. check the free list + /// 4. report leaked areas (areas that have not yet been visited) + /// # Errors + /// Returns a [`CheckerError`] if the database is inconsistent. + pub fn check(&self, opt: CheckOpt) -> CheckerReport { + // 1. Check the header + let high_watermark = self.size(); + let mut visited = match LinearAddressRangeSet::new(high_watermark) { + Ok(visited) => visited, + Err(e) => { + return CheckerReport { + errors: vec![e], + db_stats: DBStats::default(), + }; + } + }; + + let mut errors = Vec::new(); + + // 2. traverse the trie and check the nodes + if let Some(progress_bar) = &opt.progress_bar { + progress_bar.set_length(high_watermark); + progress_bar.set_message("Traversing the trie..."); + } + let trie_stats = self + .root_as_maybe_persisted_node() + .and_then(|node| self.root_hash().map(|root_hash| (node, root_hash))) + .and_then(|(root, root_hash)| { + if let Some(root_address) = root.as_linear_address() { + let (trie_stats, trie_errors) = self.visit_trie( + root_address, + root_hash.into_hash_type(), + &mut visited, + opt.progress_bar.as_ref(), + opt.hash_check, + ); + errors.extend(trie_errors); + Some(trie_stats) + } else { + errors.push(CheckerError::UnpersistedRoot); + None + } + }) + .unwrap_or_default(); + + // 3. check the free list - this can happen in parallel with the trie traversal + if let Some(progress_bar) = &opt.progress_bar { + progress_bar.set_message("Traversing free lists..."); + } + let (free_list_stats, free_list_traverse_errors) = + self.visit_freelist(&mut visited, opt.progress_bar.as_ref()); + errors.extend(free_list_traverse_errors); + + // 4. report leaked areas (areas that have not yet been visited) + if let Some(progress_bar) = &opt.progress_bar { + progress_bar.set_message("Checking leaked areas..."); + } + let leaked_ranges = visited.complement(); + if !leaked_ranges.is_empty() { + warn!("Found leaked ranges: {leaked_ranges}"); + errors.push(CheckerError::AreaLeaks(leaked_ranges)); + } + + CheckerReport { + errors, + db_stats: DBStats { + high_watermark, + trie_stats, + free_list_stats, + }, + } + } + + fn visit_trie( + &self, + root_address: LinearAddress, + root_hash: HashType, + visited: &mut LinearAddressRangeSet, + progress_bar: Option<&ProgressBar>, + hash_check: bool, + ) -> (TrieStats, Vec) { + let trie = SubTrieMetadata { + root_address, + root_hash, + parent: TrieNodeParent::Root, + depth: 0, + path_prefix: Path::new(), + #[cfg(feature = "ethhash")] + has_peers: false, + }; + let mut trie_stats = TrieStats::default(); + let errors = self + .visit_trie_helper(trie, visited, &mut trie_stats, progress_bar, hash_check) + .err() + .unwrap_or_default(); + (trie_stats, errors) + } + + /// Recursively traverse the trie from the given root node. + #[expect(clippy::too_many_lines)] + fn visit_trie_helper( + &self, + subtrie: SubTrieMetadata, + visited: &mut LinearAddressRangeSet, + trie_stats: &mut TrieStats, + progress_bar: Option<&ProgressBar>, + hash_check: bool, + ) -> Result<(), Vec> { + let SubTrieMetadata { + root_address: subtrie_root_address, + root_hash: subtrie_root_hash, + parent, + depth, + path_prefix, + #[cfg(feature = "ethhash")] + has_peers, + } = subtrie; + + // check that address is aligned + self.check_area_aligned(subtrie_root_address, StoredAreaParent::TrieNode(parent))?; + + // read the node from the disk - we avoid cache since we will never visit the same node twice + let (area_index, area_size) = + self.area_index_and_size(subtrie_root_address) + .map_err(|e| { + vec![CheckerError::IO { + error: e, + parent: StoredAreaParent::TrieNode(parent), + }] + })?; + let (node, node_bytes) = self + .read_node_with_num_bytes_from_disk(subtrie_root_address) + .map_err(|e| { + vec![CheckerError::IO { + error: e, + parent: StoredAreaParent::TrieNode(parent), + }] + })?; + + // check if the node fits in the area, equal is not allowed due to 1-byte area size index + if node_bytes > area_size { + return Err(vec![CheckerError::NodeLargerThanArea { + area_start: subtrie_root_address, + area_size, + node_bytes, + parent, + }]); + } + + // if the node has a value, check that the key is valid + let mut current_path_prefix = path_prefix.clone(); + current_path_prefix.0.extend_from_slice(node.partial_path()); + if node.value().is_some() && !is_valid_key(¤t_path_prefix) { + return Err(vec![CheckerError::InvalidKey { + key: current_path_prefix, + address: subtrie_root_address, + parent, + }]); + } + + // compute the hash of the node and check it against the stored hash + if hash_check { + #[cfg(feature = "ethhash")] + let hash = Self::compute_node_ethhash(&node, &path_prefix, has_peers); + #[cfg(not(feature = "ethhash"))] + let hash = hash_node(&node, &path_prefix); + if hash != subtrie_root_hash { + return Err(vec![CheckerError::HashMismatch { + path: current_path_prefix, + address: subtrie_root_address, + parent, + parent_stored_hash: subtrie_root_hash, + computed_hash: hash, + }]); + } + } + + // check that the area is within bounds and does not intersect with other areas and mark it as visiteds + visited.insert_area( + subtrie_root_address, + area_size, + StoredAreaParent::TrieNode(parent), + )?; + + // at this point we have checked this area is correct - update progress bar, collect stats, and recursively traverse the children + update_progress_bar(progress_bar, visited); + + // collect trie stats + { + if let Some(value) = node.value() { + // collect kv count + trie_stats.kv_count = trie_stats.kv_count.saturating_add(1); + // collect kv pair bytes - this is the minimum number of bytes needed to store the data + let key_bytes = current_path_prefix.0.len().div_ceil(2); + let value_bytes = value.len(); + trie_stats.kv_bytes = trie_stats + .kv_bytes + .saturating_add(key_bytes as u64) + .saturating_add(value_bytes as u64); + } + // collect the number of areas that requires reading an extra page due to not being aligned + if extra_read_pages(subtrie_root_address, area_size) + .expect("impossible since we checked in visited.insert_area()") + > 0 + { + trie_stats.area_extra_unaligned_page = + trie_stats.area_extra_unaligned_page.saturating_add(1); + } + // collect the number of nodes that requires reading an extra page due to not being aligned + if extra_read_pages(subtrie_root_address, node_bytes) + .expect("impossible since we checked in visited.insert_area()") + > 0 + { + trie_stats.node_extra_unaligned_page = + trie_stats.node_extra_unaligned_page.saturating_add(1); + } + } + + // collect more stats and recursively traverse the children + let mut errors = Vec::new(); + match node.as_ref() { + Node::Branch(branch) => { + let persist_info = branch.persist_info(); + let num_children = persist_info.count(); + { + // update the branch area count + let branch_area_count = trie_stats + .branch_area_counts + .get_mut(&area_size) + .expect("area size is initialized when trie_stats is created and we checked that node_bytes <= area_size"); + *branch_area_count = branch_area_count.saturating_add(1); + // collect the branch bytes + trie_stats.branch_bytes = trie_stats.branch_bytes.saturating_add(node_bytes); + // collect low occupancy area count, add 1 for the area size index byte + let smallest_area_index = AreaIndex::from_size(node_bytes) + .expect("impossible since we checked that node_bytes <= area_size"); + if smallest_area_index < area_index { + trie_stats.low_occupancy_branch_area_count = + trie_stats.low_occupancy_branch_area_count.saturating_add(1); + } + // collect the branching factor distribution + let branching_factor_count = trie_stats + .branching_factors + .entry(num_children) + .or_insert(0); + *branching_factor_count = branching_factor_count.saturating_add(1); + } + + // this is an internal node, traverse the children + for (nibble, (address, hash)) in persist_info + .into_iter() + .filter_map(|(idx, slot)| slot.map(|child| (idx, child))) + { + let parent = TrieNodeParent::Parent(subtrie_root_address, nibble); + let mut child_path_prefix = current_path_prefix.clone(); + child_path_prefix.0.push(nibble.as_u8()); + let child_subtrie = SubTrieMetadata { + root_address: address, + root_hash: hash.clone(), + parent, + depth: depth.saturating_add(1), + path_prefix: child_path_prefix, + #[cfg(feature = "ethhash")] + has_peers: num_children != 1, + }; + if let Err(e) = self.visit_trie_helper( + child_subtrie, + visited, + trie_stats, + progress_bar, + hash_check, + ) { + errors.extend(e); + } + } + } + Node::Leaf(_) => { + // update the leaf area count + let leaf_area_count = trie_stats + .leaf_area_counts + .get_mut(&area_size) + .expect("area size is initialized when trie_stats is created and we checked that node_bytes <= area_size"); + *leaf_area_count = leaf_area_count.saturating_add(1); + // collect the leaf bytes + trie_stats.leaf_bytes = trie_stats.leaf_bytes.saturating_add(node_bytes); + // collect low occupancy area count, add 1 for the area size index byte + let smallest_area_index = AreaIndex::from_size(node_bytes) + .expect("impossible since we checked that node_bytes <= area_size"); + if smallest_area_index < area_index { + trie_stats.low_occupancy_leaf_area_count = + trie_stats.low_occupancy_leaf_area_count.saturating_add(1); + } + // collect the depth distribution + let depth_count = trie_stats.depths.entry(depth).or_insert(0); + *depth_count = depth_count.saturating_add(1); + } + } + + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } + } + + /// Traverse all the free areas in the freelist + fn visit_freelist( + &self, + visited: &mut LinearAddressRangeSet, + progress_bar: Option<&ProgressBar>, + ) -> (FreeListsStats, Vec) { + let mut area_counts: BTreeMap = + area_size_iter().map(|(_, size)| (size, 0)).collect(); + let mut area_extra_unaligned_page = 0u64; + let mut errors = Vec::new(); + + let mut free_list_iter = self.free_list_iter(AreaIndex::MIN); + while let Some((free_area, parent)) = free_list_iter.next_with_metadata() { + let FreeAreaWithMetadata { + addr, + area_index, + free_list_id, + } = match free_area { + Ok(free_area) => free_area, + Err(e) => { + errors.push(CheckerError::IO { + error: e, + parent: StoredAreaParent::FreeList(parent), + }); + free_list_iter.move_to_next_free_list(); + continue; + } + }; + + // check that the area is aligned + if let Err(e) = self.check_area_aligned(addr, StoredAreaParent::FreeList(parent)) { + errors.push(e); + free_list_iter.move_to_next_free_list(); + continue; + } + + // check that the area size matches the free list id (if it is in the correct free list) + let area_size = area_index.size(); + if free_list_id != area_index { + errors.push(CheckerError::FreelistAreaSizeMismatch { + address: addr, + size: area_size, + actual_free_list: free_list_id, + expected_free_list: area_index, + parent, + }); + free_list_iter.move_to_next_free_list(); + continue; + } + + // check the free area is within bounds and does not intersect with other areas + if let Err(e) = visited.insert_area(addr, area_size, StoredAreaParent::FreeList(parent)) + { + errors.push(e); + free_list_iter.move_to_next_free_list(); + continue; + } + update_progress_bar(progress_bar, visited); + + // collect the free list stats + { + // collect the free lists area distribution + let area_count = area_counts + .get_mut(&area_size) + .expect("area size is initialized when free_list_stats is created"); + *area_count = area_count.saturating_add(1); + // collect the multi-page area count + if extra_read_pages(addr, area_size) + .expect("impossible since we checked in visited.insert_area()") + > 0 + { + area_extra_unaligned_page = area_extra_unaligned_page.saturating_add(1); + } + } + } + + ( + FreeListsStats { + area_counts, + area_extra_unaligned_page, + }, + errors, + ) + } + + const fn check_area_aligned( + &self, + address: LinearAddress, + parent: StoredAreaParent, + ) -> Result<(), CheckerError> { + if !address.is_aligned() { + return Err(CheckerError::AreaMisaligned { address, parent }); + } + Ok(()) + } +} + +/// Report of the fix operation +#[derive(Debug)] +pub struct FixReport { + /// Errors that were fixed + pub fixed: Vec, + /// Errors that were not fixed, either because they are unfixable or because an IO error occurred + pub unfixable: Vec<(CheckerError, Option)>, + /// Statistics about the database + pub db_stats: DBStats, +} + +impl NodeStore { + /// Check the node store and fix any errors found. + /// Returns a report of the fix operation. + // TODO: return a committed revision instead of an immutable proposal + pub fn check_and_fix( + &self, + opt: CheckOpt, + ) -> ( + Result, S>, FileIoError>, + FixReport, + ) { + let check_report = self.check(opt); + let mut proposal = match NodeStore::::new(self) { + Ok(proposal) => proposal, + Err(e) => { + let report = FixReport { + fixed: Vec::new(), + unfixable: check_report.errors.into_iter().map(|e| (e, None)).collect(), + db_stats: check_report.db_stats, + }; + return (Err(e), report); + } + }; + let fix_report = proposal.fix(check_report); + let immutable_proposal = NodeStore::, S>::try_from(proposal); + (immutable_proposal, fix_report) + } +} + +impl NodeStore { + fn fix(&mut self, check_report: CheckerReport) -> FixReport { + let mut fixed = Vec::new(); + let mut unfixable = Vec::new(); + + for error in check_report.errors { + match error.parent() { + Some(StoredAreaParent::TrieNode(_)) => { + warn!("Fix for trie node error not yet implemented"); + unfixable.push((error, None)); + } + Some(StoredAreaParent::FreeList(free_list_parent)) => { + if let Err(e) = self.truncate_free_list(free_list_parent) { + unfixable.push((error, Some(e))); + } else { + fixed.push(error); + } + } + None => { + if let CheckerError::AreaLeaks(ranges) = &error { + { + let _leaked_areas = self.split_all_leaked_ranges(ranges, None); + // TODO: add _leaked_areas to the free list + } + unfixable.push((error, None)); + } else { + unfixable.push((error, None)); + } + } + } + } + + FixReport { + fixed, + unfixable, + db_stats: check_report.db_stats, + } + } +} + +impl NodeStore +where + NodeStore: NodeReader, +{ + /// Wrapper around `split_into_leaked_areas` that iterates over a collection of ranges. + fn split_all_leaked_ranges<'a>( + &self, + leaked_ranges: impl IntoIterator>, + progress_bar: Option<&ProgressBar>, + ) -> impl Iterator { + leaked_ranges + .into_iter() + .flat_map(move |range| self.split_range_into_leaked_areas(range, progress_bar)) + } + + /// Split a range of addresses into leaked areas that can be stored in the free list. + /// We assume that all space within `leaked_range` are leaked and the stored areas are contiguous. + /// Returns error if the last leaked area extends beyond the end of the range. + fn split_range_into_leaked_areas( + &self, + leaked_range: Range<&LinearAddress>, + progress_bar: Option<&ProgressBar>, + ) -> Vec<(LinearAddress, AreaIndex)> { + let mut leaked = Vec::new(); + let mut current_addr = *leaked_range.start; + + // First attempt to read the valid stored areas from the leaked range + loop { + let (area_index, area_size) = match self.read_leaked_area(current_addr) { + Ok(area_index_and_size) => area_index_and_size, + Err(e) => { + warn!("Error reading stored area at {current_addr}: {e}"); + break; + } + }; + + let next_addr = current_addr + .advance(area_size) + .expect("address overflow is impossible"); + match next_addr.cmp(leaked_range.end) { + Ordering::Equal => { + // we have reached the end of the leaked area, done + leaked.push((current_addr, area_index)); + if let Some(progress_bar) = progress_bar { + progress_bar.inc(area_size); + } + return leaked; + } + Ordering::Greater => { + // the last area extends beyond the leaked area - this means the leaked area overlaps with an area we have visited + warn!( + "Leaked area extends beyond {leaked_range:?}: {current_addr} -> {next_addr}" + ); + break; + } + Ordering::Less => { + // continue to the next area + leaked.push((current_addr, area_index)); + if let Some(progress_bar) = progress_bar { + progress_bar.inc(area_size); + } + current_addr = next_addr; + } + } + } + + // We encountered an error, split the rest of the leaked range into areas using heuristics + // The heuristic is to split the leaked range into areas of the largest size possible - we assume `AREA_SIZE` is in ascending order + for (area_index, area_size) in area_size_iter().rev() { + loop { + let next_addr = current_addr + .advance(area_size) + .expect("address overflow is impossible"); + if next_addr <= *leaked_range.end { + leaked.push((current_addr, area_index)); + if let Some(progress_bar) = progress_bar { + progress_bar.inc(area_size); + } + current_addr = next_addr; + } else { + break; + } + } + } + + // we assume that all areas are aligned to `MIN_AREA_SIZE`, in which case leaked ranges can always be split into free areas perfectly + debug_assert!(current_addr == *leaked_range.end); + leaked + } +} + +fn update_progress_bar(progress_bar: Option<&ProgressBar>, range_set: &LinearAddressRangeSet) { + if let Some(progress_bar) = progress_bar { + progress_bar.set_position( + range_set + .bytes_in_set() + .checked_add(crate::nodestore::NodeStoreHeader::SIZE) + .expect("overflow can only happen if max_addr >= U64_MAX + NODE_STORE_START_ADDR"), + ); + } +} + +#[cfg(test)] +mod test { + #![expect(clippy::unwrap_used)] + #![expect(clippy::indexing_slicing)] + + use nonzero_ext::nonzero; + + use super::*; + use crate::linear::memory::MemStore; + use crate::nodestore::NodeStoreHeader; + use crate::nodestore::alloc::FreeLists; + use crate::nodestore::alloc::test_utils::{ + test_write_free_area, test_write_header, test_write_new_node, test_write_zeroed_area, + }; + use crate::nodestore::primitives::area_size_iter; + use crate::{ + BranchNode, Child, Children, FreeListParent, LeafNode, NodeStore, Path, PathComponent, + area_index, hash_node, + }; + + #[derive(Debug)] + struct TestTrie { + nodes: Vec<(Node, LinearAddress)>, + high_watermark: u64, + root_address: LinearAddress, + root_hash: HashType, + stats: TrieStats, + } + + /// Generate a test trie with the following structure: + /// + #[cfg_attr(doc, aquamarine::aquamarine)] + /// ```mermaid + /// graph TD + /// Root["Root Node
partial_path: [2]
children: [0] -> Branch"] + /// Branch["Branch Node
partial_path: [3]
path: 0x203
children: [1] -> Leaf"] + /// Leaf["Leaf Node
partial_path: [4, 5]
path: 0x2031454545...45 (32 bytes)
value: [6, 7, 8]"] + /// + /// Root -->|"nibble 0"| Branch + /// Branch -->|"nibble 1"| Leaf + /// ``` + #[expect(clippy::arithmetic_side_effects)] + fn gen_test_trie(nodestore: &mut NodeStore) -> TestTrie { + let mut high_watermark = NodeStoreHeader::SIZE; + let mut total_branch_bytes_written = 0; + let mut total_leaf_bytes_written = 0; + let mut branch_area_counts: BTreeMap = + area_size_iter().map(|(_, size)| (size, 0)).collect(); + let mut leaf_area_counts: BTreeMap = + area_size_iter().map(|(_, size)| (size, 0)).collect(); + let leaf = Node::Leaf(LeafNode { + partial_path: Path::from_nibbles_iterator(std::iter::repeat_n([4, 5], 30).flatten()), + value: Box::new([6, 7, 8]), + }); + let leaf_addr = LinearAddress::new(high_watermark).unwrap(); + let leaf_hash = hash_node(&leaf, &Path::from([2, 0, 3, 1])); + let (bytes_written, stored_area_size) = + test_write_new_node(nodestore, &leaf, high_watermark); + high_watermark += stored_area_size; + total_leaf_bytes_written += bytes_written; + let area_count = leaf_area_counts.get_mut(&stored_area_size).unwrap(); + *area_count = area_count.saturating_add(1); + + let mut branch_children = Children::new(); + branch_children[PathComponent::ALL[1]] = Some(Child::AddressWithHash(leaf_addr, leaf_hash)); + let branch = Node::Branch(Box::new(BranchNode { + partial_path: Path::from([3]), + value: None, + children: branch_children, + })); + let branch_addr = LinearAddress::new(high_watermark).unwrap(); + let branch_hash = hash_node(&branch, &Path::from([2, 0])); + let (bytes_written, stored_area_size) = + test_write_new_node(nodestore, &branch, high_watermark); + high_watermark += stored_area_size; + total_branch_bytes_written += bytes_written; + let area_count = branch_area_counts.get_mut(&stored_area_size).unwrap(); + *area_count = area_count.saturating_add(1); + + let mut root_children = Children::new(); + root_children[PathComponent::ALL[0]] = + Some(Child::AddressWithHash(branch_addr, branch_hash)); + let root = Node::Branch(Box::new(BranchNode { + partial_path: Path::from([2]), + value: None, + children: root_children, + })); + let root_addr = LinearAddress::new(high_watermark).unwrap(); + let root_hash = hash_node(&root, &Path::new()); + let (bytes_written, stored_area_size) = + test_write_new_node(nodestore, &root, high_watermark); + high_watermark += stored_area_size; + total_branch_bytes_written += bytes_written; + let area_count = branch_area_counts.get_mut(&stored_area_size).unwrap(); + *area_count = area_count.saturating_add(1); + + // write the header + test_write_header( + nodestore, + high_watermark, + Some(root_addr), + FreeLists::default(), + ); + + let trie_stats = TrieStats { + branch_bytes: total_branch_bytes_written, + leaf_bytes: total_leaf_bytes_written, + kv_count: 1, + kv_bytes: 32 + 3, // 32 bytes for the key, 3 bytes for the value + branch_area_counts, + leaf_area_counts, + branching_factors: BTreeMap::from([(1, 2)]), + depths: BTreeMap::from([(2, 1)]), + low_occupancy_branch_area_count: 0, + low_occupancy_leaf_area_count: 0, + area_extra_unaligned_page: 0, + node_extra_unaligned_page: 0, + }; + + TestTrie { + nodes: vec![(leaf, leaf_addr), (branch, branch_addr), (root, root_addr)], + high_watermark, + root_address: root_addr, + root_hash, + stats: trie_stats, + } + } + + #[derive(Debug)] + struct TestFreelist { + high_watermark: u64, + free_ranges: Vec>, + errors: Vec, + stats: FreeListsStats, + } + + // Free list 1: 2048 bytes + // Free list 2: 8192 bytes + // Free list 3: 96 bytes + // ---------------------------------------------------------------------------------------------------------------------------------------------------- + // | header | empty | free_list1_area3 | free_list1_area2 | overlap | free_list1_area1 | free_list2_area1 | free_list2_area2 | gap | free_list3_area1 | + // ---------------------------------------------------------------------------------------------------------------------------------------------------- + // ^ free_list1_area1 and free_list1_area2 overlap by 16 bytes ^ 1 byte + // ^ 16 empty bytes to ensure that free_list1_area1, free_list1_area2, and free_list2_area1 are page-aligned ^ missaligned + #[expect(clippy::arithmetic_side_effects)] + fn gen_test_freelist_with_errors( + nodestore: &mut NodeStore, + ) -> TestFreelist { + const AREA_INDEX1: AreaIndex = area_index!(9); // 2048 + const AREA_INDEX2: AreaIndex = area_index!(12); // 16384 + const AREA_INDEX3: AreaIndex = area_index!(3); // 96 + + let mut free_lists = FreeLists::default(); + let mut high_watermark = NodeStoreHeader::SIZE + 16; // + 16 to create overlap + + // first free list + let area_size1 = AREA_INDEX1.size(); + let mut next_free_block1 = None; + + test_write_free_area(nodestore, next_free_block1, AREA_INDEX1, high_watermark); + let free_list1_area3 = LinearAddress::new(high_watermark).unwrap(); + next_free_block1 = Some(free_list1_area3); + high_watermark += area_size1; + + test_write_free_area(nodestore, next_free_block1, AREA_INDEX1, high_watermark); + let free_list1_area2 = LinearAddress::new(high_watermark).unwrap(); + next_free_block1 = Some(free_list1_area2); + high_watermark += area_size1; + + let intersection_end = LinearAddress::new(high_watermark).unwrap(); + high_watermark -= 16; // create an overlap with free_list1_area2 and restore to page-aligned address + let intersection_start = LinearAddress::new(high_watermark).unwrap(); + test_write_free_area(nodestore, next_free_block1, AREA_INDEX1, high_watermark); + let free_list1_area1 = LinearAddress::new(high_watermark).unwrap(); + next_free_block1 = Some(free_list1_area1); + high_watermark += area_size1; + + free_lists[AREA_INDEX1.as_usize()] = next_free_block1; + + // second free list + let area_size2 = AREA_INDEX2.size(); + let mut next_free_block2 = None; + + test_write_free_area(nodestore, next_free_block2, AREA_INDEX2, high_watermark); + let free_list2_area2 = LinearAddress::new(high_watermark).unwrap(); + next_free_block2 = Some(free_list2_area2); + high_watermark += area_size2; + + test_write_free_area(nodestore, next_free_block2, AREA_INDEX2, high_watermark); + let free_list2_area1 = LinearAddress::new(high_watermark).unwrap(); + next_free_block2 = Some(free_list2_area1); + high_watermark += area_size2; + let expected_high_watermark = high_watermark; + + free_lists[AREA_INDEX2.as_usize()] = next_free_block2; + + // third free list + high_watermark += 1; // + 1 to create gap + let area_size3 = AREA_INDEX3.size(); + let mut next_free_block3 = None; + test_write_free_area(nodestore, next_free_block3, AREA_INDEX3, high_watermark); + let free_list3_area1 = LinearAddress::new(high_watermark).unwrap(); + next_free_block3 = Some(free_list3_area1); + high_watermark += area_size3; + + free_lists[AREA_INDEX3.as_usize()] = next_free_block3; + + // write header + test_write_header(nodestore, high_watermark, None, free_lists); + + let expected_start_addr = free_lists[AREA_INDEX1.as_usize()].unwrap(); + let expected_end_addr = LinearAddress::new(expected_high_watermark).unwrap(); + let expected_free_areas = vec![expected_start_addr..expected_end_addr]; + let expected_freelist_errors = vec![ + CheckerError::AreaMisaligned { + address: free_list3_area1, + parent: StoredAreaParent::FreeList(FreeListParent::FreeListHead(AREA_INDEX3)), + }, + CheckerError::AreaIntersects { + start: free_list1_area2, + size: area_size1, + intersection: vec![intersection_start..intersection_end], + parent: StoredAreaParent::FreeList(FreeListParent::PrevFreeArea { + area_size_idx: AREA_INDEX1, + parent_addr: free_list1_area1, + }), + }, + ]; + let mut area_counts = area_size_iter() + .map(|(_, size)| (size, 0)) + .collect::>(); + area_counts.insert(area_size1, 1); + area_counts.insert(area_size2, 2); + let expected_free_lists_stats = FreeListsStats { + area_counts, + area_extra_unaligned_page: 0, + }; + + TestFreelist { + high_watermark, + free_ranges: expected_free_areas, + errors: expected_freelist_errors, + stats: expected_free_lists_stats, + } + } + + use std::collections::HashMap; + + #[test] + // This test creates a simple trie and checks that the checker traverses it correctly. + // We use primitive calls here to do a low-level check. + fn checker_traverse_correct_trie() { + let memstore = MemStore::new(vec![]); + let mut nodestore = NodeStore::new_empty_committed(memstore.into()); + + let test_trie = gen_test_trie(&mut nodestore); + // let (_, high_watermark, (root_addr, root_hash)) = gen_test_trie(&mut nodestore); + + // verify that all of the space is accounted for - since there is no free area + let mut visited = LinearAddressRangeSet::new(test_trie.high_watermark).unwrap(); + let (stats, errors) = nodestore.visit_trie( + test_trie.root_address, + test_trie.root_hash, + &mut visited, + None, + true, + ); + let complement = visited.complement(); + assert_eq!(complement.into_iter().collect::>(), vec![]); + assert_eq!(stats, test_trie.stats); + assert_eq!(errors, vec![]); + } + + #[test] + // This test permutes the simple trie with a wrong hash and checks that the checker detects it. + fn checker_traverse_trie_with_wrong_hash() { + let memstore = MemStore::new(vec![]); + let mut nodestore = NodeStore::new_empty_committed(memstore.into()); + + let mut test_trie = gen_test_trie(&mut nodestore); + let root_addr = test_trie.root_address; + + // find the root node and replace the branch hash with an incorrect (default) hash + let (branch_node, branch_addr) = test_trie + .nodes + .iter_mut() + .find(|(node, _)| matches!(node, Node::Branch(b) if *b.partial_path.0 == [3])) + .unwrap(); + + let branch = branch_node.as_branch_mut().unwrap(); + let branch_addr = *branch_addr; + + // Replace branch hash with a wrong hash + let (leaf_addr, _) = branch.children[PathComponent::ALL[1]] + .as_ref() + .unwrap() + .persist_info() + .unwrap(); + branch.children[PathComponent::ALL[1]] = + Some(Child::AddressWithHash(leaf_addr, HashType::empty())); + test_write_new_node(&nodestore, branch_node, branch_addr.get()); + + // Compute the current branch hash + #[cfg(feature = "ethhash")] + let computed_hash = NodeStore::::compute_node_ethhash( + branch_node, + &Path::from([2, 0]), + false, + ); + #[cfg(not(feature = "ethhash"))] + let computed_hash = hash_node(branch_node, &Path::from([2, 0])); + + // Get parent stored hash + let (root_node, _) = test_trie + .nodes + .iter() + .find(|(node, _)| matches!(node, Node::Branch(b) if *b.partial_path.0 == [2])) + .unwrap(); + let root_branch = root_node.as_branch().unwrap(); + let (_, parent_stored_hash) = root_branch.children[PathComponent::ALL[0]] + .as_ref() + .unwrap() + .persist_info() + .unwrap(); + let parent_stored_hash = parent_stored_hash.clone(); + + // run the checker and verify that it returns the HashMismatch error + let mut visited = LinearAddressRangeSet::new(test_trie.high_watermark).unwrap(); + let (_, errors) = nodestore.visit_trie( + test_trie.root_address, + test_trie.root_hash, + &mut visited, + None, + true, + ); + + let expected_error = CheckerError::HashMismatch { + address: branch_addr, + path: Path::from([2, 0, 3]), + parent: TrieNodeParent::Parent(root_addr, PathComponent::ALL[0]), + parent_stored_hash, + computed_hash, + }; + assert_eq!(errors, vec![expected_error]); + } + + #[test] + fn traverse_correct_freelist() { + let rng = crate::SeededRng::from_env_or_random(); + + let memstore = MemStore::new(vec![]); + let mut nodestore = NodeStore::new_empty_committed(memstore.into()); + + // write free areas + let mut high_watermark = NodeStoreHeader::SIZE; + let mut free_area_counts: BTreeMap = + area_size_iter().map(|(_, size)| (size, 0)).collect(); + let mut extra_unaligned_page_read = 0u64; + let mut freelist = FreeLists::default(); + for (area_index, area_size) in area_size_iter() { + let mut next_free_block = None; + let num_free_areas = rng.random_range(0..4); + for _ in 0..num_free_areas { + test_write_free_area(&nodestore, next_free_block, area_index, high_watermark); + next_free_block = Some(LinearAddress::new(high_watermark).unwrap()); + let start_addr = LinearAddress::new(high_watermark).unwrap(); + if extra_read_pages(start_addr, area_size).unwrap() > 0 { + extra_unaligned_page_read = extra_unaligned_page_read.saturating_add(1); + } + high_watermark += area_size; + } + freelist[area_index.as_usize()] = next_free_block; + if num_free_areas > 0 { + free_area_counts.insert(area_size, num_free_areas); + } + } + let expected_free_lists_stats = FreeListsStats { + area_counts: free_area_counts, + area_extra_unaligned_page: extra_unaligned_page_read, + }; + + // write header + test_write_header(&mut nodestore, high_watermark, None, freelist); + + // test that the we traversed all the free areas + let mut visited = LinearAddressRangeSet::new(high_watermark).unwrap(); + let (actual_free_lists_stats, free_list_errors) = + nodestore.visit_freelist(&mut visited, None); + let complement = visited.complement(); + assert_eq!(complement.into_iter().collect::>(), vec![]); + assert_eq!(free_list_errors, vec![]); + assert_eq!(actual_free_lists_stats, expected_free_lists_stats); + } + + #[test] + fn traverse_freelist_should_skip_offspring_of_incorrect_areas() { + let memstore = MemStore::new(vec![]); + let mut nodestore = NodeStore::new_empty_committed(memstore.into()); + let TestFreelist { + high_watermark, + free_ranges, + errors, + stats, + } = gen_test_freelist_with_errors(&mut nodestore); + + // test that the we traversed all the free areas + let mut visited = LinearAddressRangeSet::new(high_watermark).unwrap(); + let (actual_free_lists_stats, free_list_errors) = + nodestore.visit_freelist(&mut visited, None); + assert_eq!(visited.into_iter().collect::>(), free_ranges); + assert_eq!(actual_free_lists_stats, stats); + assert_eq!(free_list_errors, errors); + } + + #[test] + fn fix_freelist_with_overlap() { + let memstore = MemStore::new(vec![]); + let mut nodestore = NodeStore::new_empty_committed(memstore.into()); + let TestFreelist { + high_watermark, + free_ranges: _, + errors, + stats, + } = gen_test_freelist_with_errors(&mut nodestore); + let expected_error_num = errors.len(); + + // fix the freelist + let mut proposal = NodeStore::::new(&nodestore).unwrap(); + let fix_report = proposal.fix(CheckerReport { + errors, + db_stats: DBStats { + high_watermark, + trie_stats: TrieStats::default(), + free_list_stats: stats, + }, + }); + assert_eq!(fix_report.fixed.len(), expected_error_num); + assert_eq!(fix_report.unfixable.len(), 0); + + let immutable_proposal = + NodeStore::, _>::try_from(proposal).unwrap(); + let mut visited = LinearAddressRangeSet::new(high_watermark).unwrap(); + let (_, free_list_errors) = immutable_proposal.visit_freelist(&mut visited, None); + assert_eq!(free_list_errors, vec![]); + } + + #[test] + // This test creates a linear set of free areas and free them. + // When traversing it should break consecutive areas. + fn split_correct_range_into_leaked_areas() { + use rand::seq::IteratorRandom; + + let mut rng = crate::SeededRng::from_env_or_random(); + + let memstore = MemStore::new(vec![]); + let mut nodestore = NodeStore::new_empty_committed(memstore.into()); + + let num_areas = 10; + + // randomly insert areas into the nodestore + let mut high_watermark = NodeStoreHeader::SIZE; + let mut stored_areas = Vec::new(); + for _ in 0..num_areas { + let (area_size_index, area_size) = area_size_iter().choose(&mut rng).unwrap(); + let area_addr = LinearAddress::new(high_watermark).unwrap(); + test_write_free_area(&nodestore, None, area_size_index, high_watermark); + stored_areas.push((area_addr, area_size_index, area_size)); + high_watermark += area_size; + } + test_write_header(&mut nodestore, high_watermark, None, FreeLists::default()); + + // randomly pick some areas as leaked + let mut leaked = Vec::new(); + let mut expected_free_areas = HashMap::new(); + let mut area_to_free = None; + for (area_start, area_size_index, area_size) in &stored_areas { + if rng.random::() < 0.5 { + // we free this area + expected_free_areas.insert(*area_start, *area_size_index); + let area_to_free_start = area_to_free.map_or(*area_start, |(start, _)| start); + let area_to_free_end = area_start.checked_add(*area_size).unwrap(); + area_to_free = Some((area_to_free_start, area_to_free_end)); + } else { + // we are not freeing this area, free the aggregated areas before this one + if let Some((start, end)) = area_to_free { + leaked.push(start..end.into()); + area_to_free = None; + } + } + } + if let Some((start, end)) = area_to_free { + leaked.push(start..end.into()); + } + + // check the leaked areas + let leaked_ranges = leaked + .iter() + .map(|Range { start, end }| Range { start, end }); + let leaked_areas: HashMap<_, _> = nodestore + .split_all_leaked_ranges(leaked_ranges, None) + .collect(); + + // assert that all leaked areas end up on the free list + assert_eq!(leaked_areas, expected_free_areas); + } + + #[test] + // This test creates a linear set of free areas and free them. + // When traversing it should break consecutive areas. + #[expect(clippy::arithmetic_side_effects)] + fn split_range_of_zeros_into_leaked_areas() { + let memstore = MemStore::new(vec![]); + let nodestore = NodeStore::new_empty_committed(memstore.into()); + + let expected_leaked_area_indices = vec![ + area_index!(8), + area_index!(7), + area_index!(4), + area_index!(2), + AreaIndex::MIN, + ]; + let expected_leaked_area_sizes = expected_leaked_area_indices + .iter() + .map(|i| i.size()) + .collect::>(); + assert_eq!(expected_leaked_area_sizes, vec![1024, 768, 128, 64, 16]); + let expected_offsets = expected_leaked_area_sizes + .iter() + .scan(0, |acc, i| { + let offset = *acc; + *acc += i; + LinearAddress::new(NodeStoreHeader::SIZE + offset) + }) + .collect::>(); + + // write an zeroed area + let leaked_range_size = expected_leaked_area_sizes.iter().sum(); + test_write_zeroed_area(&nodestore, leaked_range_size, NodeStoreHeader::SIZE); + + // check the leaked areas + let leaked_range = &nonzero!(NodeStoreHeader::SIZE).into() + ..&LinearAddress::new( + NodeStoreHeader::SIZE + .checked_add(leaked_range_size) + .unwrap(), + ) + .unwrap(); + let (leaked_areas_offsets, leaked_area_size_indices): (Vec, Vec) = + nodestore + .split_range_into_leaked_areas(leaked_range, None) + .into_iter() + .unzip(); + + // assert that all leaked areas end up on the free list + assert_eq!(leaked_areas_offsets, expected_offsets); + assert_eq!(leaked_area_size_indices, expected_leaked_area_indices); + } + + #[test] + // With both valid and invalid areas in the range, return the valid areas until reaching one invalid area, then use heuristics to split the rest of the range. + #[expect(clippy::arithmetic_side_effects)] + fn split_range_into_leaked_areas_test() { + let memstore = MemStore::new(vec![]); + let nodestore = NodeStore::new_empty_committed(memstore.into()); + + // write two free areas + let mut high_watermark = NodeStoreHeader::SIZE; + test_write_free_area(&nodestore, None, area_index!(8), high_watermark); // 1024 + high_watermark += area_index!(8).size(); + test_write_free_area(&nodestore, None, area_index!(7), high_watermark); // 768 + high_watermark += area_index!(7).size(); + // write an zeroed area + test_write_zeroed_area(&nodestore, 768, high_watermark); + high_watermark += 768; + // write another free area + test_write_free_area(&nodestore, None, area_index!(8), high_watermark); // 1024 + high_watermark += area_index!(8).size(); + + let expected_indices = vec![ + area_index!(8), + area_index!(7), + area_index!(8), + area_index!(7), + ]; + let expected_sizes = expected_indices + .iter() + .map(|i| i.size()) + .collect::>(); + let expected_offsets = expected_sizes + .iter() + .scan(0, |acc, i| { + let offset = *acc; + *acc += i; + LinearAddress::new(NodeStoreHeader::SIZE + offset) + }) + .collect::>(); + + // check the leaked areas + let leaked_range = + &nonzero!(NodeStoreHeader::SIZE).into()..&LinearAddress::new(high_watermark).unwrap(); + let (leaked_areas_offsets, leaked_area_size_indices): (Vec, Vec) = + nodestore + .split_range_into_leaked_areas(leaked_range, None) + .into_iter() + .unzip(); + + assert_eq!(leaked_areas_offsets, expected_offsets); + assert_eq!(leaked_area_size_indices, expected_indices); + } +} diff --git a/firewood/storage/src/checker/range_set.rs b/firewood/storage/src/checker/range_set.rs new file mode 100644 index 000000000000..52bf271b4d70 --- /dev/null +++ b/firewood/storage/src/checker/range_set.rs @@ -0,0 +1,810 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![warn(clippy::pedantic)] + +use std::collections::BTreeMap; +use std::fmt::{Debug, Display}; +use std::ops::Range; + +use crate::iter::write_limited_with_sep; +use crate::nodestore::NodeStoreHeader; +use crate::{CheckerError, LinearAddress, StoredAreaParent}; + +const MAX_AREAS_TO_DISPLAY: usize = 10; + +#[derive(Debug, Default)] +// BTreeMap: range end --> range start +// To check if a value is in the range set, we will find the range with the smallest end that is greater than or equal to the given value +pub struct RangeSet(BTreeMap); + +struct CoalescingRanges<'a, T> { + prev_adjacent_range: Option>, + intersecting_ranges: Vec>, + next_adjacent_range: Option>, +} + +impl RangeSet { + pub const fn new() -> Self { + Self(BTreeMap::new()) + } + + // returns disjoint ranges that will coalesce with the given range in ascending order + // We look at all ranges whose end is greater than or equal to the given range's start + // For each range, there are 5 cases: + // Case 1: The range is before the given range + // Range x in RangeSet: |----| + // Given Range: |--------| + // Result: this will not happen since the end of x is less than the start of the given range + // Case 2: The end of the range is equal to the start of the given range + // Range x in RangeSet: |--------| + // Given Range: |--------| + // Result: prev_adjacent_range = Some(x) + // Case 3: The range intersects with the given range + // Range x in RangeSet: |----------| + // Given Range: |-----------| + // Result: intersecting_ranges = [x, ...] + // or: + // Range x in RangeSet: |----------------| + // Given Range: |--------| + // or: + // Range x in RangeSet: |--------| + // Given Range: |-----------------| + // or: + // Range x in RangeSet: |------------| + // Given Range: |--------| + // Result: intersecting_ranges = [.., x, ..] + // Case 4: The start of the range is equal to the end of the given range + // Range x in RangeSet: |--------| + // Given Range: |--------| + // Result: next_adjacent_range = Some(x), and we are done iterating through the ranges + // Case 5: The range is after the given range + // Range x in RangeSet: |--------| + // Given Range: |--------| + // Result: We are done iterating through the ranges + fn get_coalescing_ranges(&self, range: &Range) -> CoalescingRanges<'_, T> { + let mut prev_adjacent_range = None; + let mut intersecting_ranges = Vec::new(); + let mut next_adjacent_range = None; + + let next_items = self.0.range(range.start.clone()..); + // all ranges will have next_range_end >= range.start and next_range_end >= next_range_start + for (next_range_end, next_range_start) in next_items { + if next_range_end == &range.start { + // Case 2: The end of the range is equal to the start of the given range - this can only happen to the first item + prev_adjacent_range = Some(next_range_start..next_range_end); + } else if next_range_start < &range.end { + // Case 3: The range intersects with the given range + intersecting_ranges.push(next_range_start..next_range_end); + } else if next_range_start == &range.end { + // Case 4: The start of the range is equal to the end of the given range + next_adjacent_range = Some(next_range_start..next_range_end); + break; + } else { + // Case 5: the range is after the given range + break; + } + } + + CoalescingRanges { + prev_adjacent_range, + intersecting_ranges, + next_adjacent_range, + } + } + + // Try inserting the range + // if allow_intersecting is false and the range intersects with existing ranges, return error with the intersection + fn insert_range_helper( + &mut self, + range: Range, + allow_intersecting: bool, + ) -> Result<(), Vec>> { + // if the range is empty, do nothing + if range.is_empty() { + return Ok(()); + } + + let CoalescingRanges { + prev_adjacent_range: prev_consecutive_range, + intersecting_ranges, + next_adjacent_range: next_consecutive_range, + } = self.get_coalescing_ranges(&range); + + // if the insert needs to be disjoint but we found intersecting ranges, return error with the intersection + if !allow_intersecting && !intersecting_ranges.is_empty() { + let intersections = intersecting_ranges + .into_iter() + .map(|intersecting_range| { + let start = + std::cmp::max(range.start.clone(), intersecting_range.start.clone()); + let end = std::cmp::min(range.end.clone(), intersecting_range.end.clone()); + start..end + }) + .collect(); + return Err(intersections); + } + + // find the new start and end after the coalescing + let coalesced_start = match (&prev_consecutive_range, intersecting_ranges.first()) { + (Some(prev_range), _) => prev_range.start.clone(), + (None, Some(first_intersecting_range)) => { + std::cmp::min(range.start, first_intersecting_range.start.clone()) + } + (None, None) => range.start, + }; + let coalesced_end = match (&next_consecutive_range, intersecting_ranges.last()) { + (Some(next_range), _) => next_range.end.clone(), + (None, Some(last_intersecting_range)) => { + std::cmp::max(range.end, last_intersecting_range.end.clone()) + } + (None, None) => range.end, + }; + + // remove the coalescing ranges + let remove_ranges_iter = prev_consecutive_range + .into_iter() + .chain(intersecting_ranges) + .chain(next_consecutive_range); + let remove_keys = remove_ranges_iter + .map(|range| range.end.clone()) + .collect::>(); + for key in remove_keys { + self.0.remove(&key); + } + + // insert the new range after coalescing + self.0.insert(coalesced_end, coalesced_start); + Ok(()) + } + + /// Insert the range into the range set. + #[cfg(test)] + pub fn insert_range(&mut self, range: Range) { + self.insert_range_helper(range, true) + .expect("insert range should always success if we allow intersecting area insert"); + } + + /// Insert the given range into the range set if the range does not intersect with existing ranges, otherwise return the error with the intersection + pub fn insert_disjoint_range(&mut self, range: Range) -> Result<(), Vec>> { + self.insert_range_helper(range, false) + } + + /// Returns the complement of the range set in the given range. + pub fn complement(&self, min: &T, max: &T) -> Self { + let mut complement_tree = BTreeMap::new(); + // first range will start from min + let mut start = min; + for (next_range_end, next_range_start) in &self.0 { + // insert the range from the previous end to the current start + if next_range_start > start { + if next_range_start >= max { + // we have reached the max - we are done + break; + } + complement_tree.insert(next_range_start.clone(), start.clone()); + } + start = std::cmp::max(start, next_range_end); // in case the entire range is smaller than min + } + + // insert the last range before the max + if start < max { + complement_tree.insert(max.clone(), start.clone()); + } + + Self(complement_tree) + } + + pub fn iter(&self) -> impl Iterator> { + self.into_iter() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } +} + +impl IntoIterator for RangeSet { + type Item = Range; + type IntoIter = + std::iter::Map< as IntoIterator>::IntoIter, fn((T, T)) -> Self::Item>; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter().map(|(end, start)| Range { start, end }) + } +} + +impl<'a, T: Debug> IntoIterator for &'a RangeSet { + type Item = Range<&'a T>; + type IntoIter = std::iter::Map< + std::collections::btree_map::Iter<'a, T, T>, + fn((&'a T, &'a T)) -> Self::Item, + >; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter().map(|(end, start)| Range { start, end }) + } +} + +/// A set of disjoint ranges of linear addresses in ascending order. +#[derive(Debug)] +pub struct LinearAddressRangeSet { + range_set: RangeSet, + max_addr: LinearAddress, + bytes_in_set: u64, +} + +#[expect(clippy::result_large_err)] +impl LinearAddressRangeSet { + const NODE_STORE_START_ADDR: LinearAddress = LinearAddress::new(NodeStoreHeader::SIZE).unwrap(); + + pub(super) fn new(db_size: u64) -> Result { + if db_size < NodeStoreHeader::SIZE { + return Err(CheckerError::InvalidDBSize { + db_size, + description: format!( + "db size should not be smaller than the header size ({})", + NodeStoreHeader::SIZE + ), + }); + } + + let max_addr = + LinearAddress::new(db_size).expect("db size will be valid due to previous check"); + + Ok(Self { + range_set: RangeSet::new(), + max_addr, + bytes_in_set: 0, + }) + } + + pub(super) fn insert_area( + &mut self, + addr: LinearAddress, + size: u64, + parent: StoredAreaParent, + ) -> Result<(), CheckerError> { + let start = addr; + let end = start.advance(size).ok_or(CheckerError::AreaOutOfBounds { + start, + size, + bounds: Self::NODE_STORE_START_ADDR..self.max_addr, + parent, + })?; // This can only happen due to overflow + if addr < Self::NODE_STORE_START_ADDR || end > self.max_addr { + return Err(CheckerError::AreaOutOfBounds { + start: addr, + size, + bounds: Self::NODE_STORE_START_ADDR..self.max_addr, + parent, + }); + } + + if let Err(intersection) = self.range_set.insert_disjoint_range(start..end) { + return Err(CheckerError::AreaIntersects { + start: addr, + size, + intersection, + parent, + }); + } + self.bytes_in_set = self + .bytes_in_set + .checked_add(size) + .expect("overflow can only happen if max_addr >= U64_MAX + NODE_STORE_START_ADDR"); + Ok(()) + } + + pub(super) fn complement(&self) -> Self { + let complement_set = self + .range_set + .complement(&Self::NODE_STORE_START_ADDR, &self.max_addr); + let bytes_in_complement = self + .max_addr + .distance_from(Self::NODE_STORE_START_ADDR) + .expect("checked in new()") + .checked_sub(self.bytes_in_set) + .expect( + "bytes_in_set is always less than or equal to max_addr - NODE_STORE_START_ADDR", + ); + Self { + range_set: complement_set, + max_addr: self.max_addr, + bytes_in_set: bytes_in_complement, + } + } + + pub(super) fn is_empty(&self) -> bool { + self.range_set.is_empty() + } + + pub(super) const fn bytes_in_set(&self) -> u64 { + self.bytes_in_set + } +} + +impl IntoIterator for LinearAddressRangeSet { + type Item = Range; + type IntoIter = as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.range_set.into_iter() + } +} + +impl<'a> IntoIterator for &'a LinearAddressRangeSet { + type Item = Range<&'a LinearAddress>; + type IntoIter = <&'a RangeSet as IntoIterator>::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + (&self.range_set).into_iter() + } +} + +impl Display for LinearAddressRangeSet { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + struct DisplayRange<'a>(Range<&'a LinearAddress>); + impl std::fmt::Display for DisplayRange<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let (start, end) = (self.0.start, self.0.end); + write!(f, "Address Range: [{start:#x}, {end:#x})") + } + } + + if self.range_set.is_empty() { + write!(f, "Linear Address Range Set: ") + } else { + write!(f, "Linear Address Range Set:\n\t")?; + write_limited_with_sep( + f, + self.range_set.iter().map(DisplayRange), + "\n\t", + Some(MAX_AREAS_TO_DISPLAY), + ) + } + } +} + +#[cfg(test)] +mod test_range_set { + use super::*; + + #[test] + fn test_create() { + let range_set: RangeSet = RangeSet::new(); + assert_eq!(range_set.into_iter().collect::>(), vec![]); + } + + #[test] + fn test_insert_range() { + let mut range_set = RangeSet::new(); + range_set.insert_range(0..10); + range_set.insert_range(20..30); + assert_eq!( + range_set.into_iter().collect::>(), + vec![0..10, 20..30] + ); + } + + #[test] + fn test_insert_empty_range() { + let mut range_set = RangeSet::new(); + range_set.insert_range(0..0); + range_set.insert_range(10..10); + #[expect(clippy::reversed_empty_ranges)] + range_set.insert_range(20..10); + #[expect(clippy::reversed_empty_ranges)] + range_set.insert_range(30..0); + assert_eq!(range_set.into_iter().collect::>(), vec![]); + } + + #[test] + fn test_insert_range_coalescing() { + // coalesce ranges that are disjoint + let mut range_set = RangeSet::new(); + range_set.insert_range(0..10); + range_set.insert_range(20..30); + range_set.insert_range(10..20); + assert_eq!(range_set.into_iter().collect::>(), vec![0..30]); + + // coalesce ranges that are partially overlapping + let mut range_set = RangeSet::new(); + range_set.insert_range(0..10); + range_set.insert_range(20..30); + range_set.insert_range(5..25); + assert_eq!(range_set.into_iter().collect::>(), vec![0..30]); + + // coalesce multiple ranges + let mut range_set = RangeSet::new(); + range_set.insert_range(5..10); + range_set.insert_range(15..20); + range_set.insert_range(25..30); + range_set.insert_range(0..25); + assert_eq!(range_set.into_iter().collect::>(), vec![0..30]); + } + + #[test] + fn test_insert_disjoint_range() { + // insert disjoint ranges + let mut range_set = RangeSet::new(); + assert!(range_set.insert_disjoint_range(0..10).is_ok()); + assert!(range_set.insert_disjoint_range(20..30).is_ok()); + assert!(range_set.insert_disjoint_range(12..18).is_ok()); + assert_eq!( + range_set.into_iter().collect::>(), + vec![0..10, 12..18, 20..30] + ); + + // insert consecutive ranges + let mut range_set = RangeSet::new(); + assert!(range_set.insert_disjoint_range(0..10).is_ok()); + assert!(range_set.insert_disjoint_range(20..30).is_ok()); + assert!(range_set.insert_disjoint_range(10..20).is_ok()); + assert_eq!(range_set.into_iter().collect::>(), vec![0..30]); + + // insert intersecting ranges + let mut range_set = RangeSet::new(); + assert!(range_set.insert_disjoint_range(0..10).is_ok()); + assert!(range_set.insert_disjoint_range(20..30).is_ok()); + assert!(matches!( + range_set.insert_disjoint_range(5..25), + Err(intersections) if intersections == vec![5..10, 20..25] + )); + assert_eq!( + range_set.into_iter().collect::>(), + vec![0..10, 20..30] + ); + + // insert with completely overlapping range + let mut range_set = RangeSet::new(); + assert!(range_set.insert_disjoint_range(0..10).is_ok()); + assert!(range_set.insert_disjoint_range(20..30).is_ok()); + assert!(range_set.insert_disjoint_range(40..50).is_ok()); + assert!(matches!( + range_set.insert_disjoint_range(5..45), + Err(intersections) if intersections == vec![5..10, 20..30, 40..45] + )); + assert_eq!( + range_set.into_iter().collect::>(), + vec![0..10, 20..30, 40..50] + ); + } + + #[test] + fn test_complement_with_empty() { + let range_set = RangeSet::new(); + assert_eq!( + range_set + .complement(&0, &40) + .into_iter() + .collect::>(), + vec![0..40] + ); + } + + #[test] + fn test_complement_with_different_bounds() { + let mut range_set = RangeSet::new(); + range_set.insert_range(0..10); + range_set.insert_range(20..30); + range_set.insert_range(40..50); + + // all ranges within bound + assert_eq!( + range_set + .complement(&0, &60) + .into_iter() + .collect::>(), + vec![10..20, 30..40, 50..60] + ); + + // some ranges entirely out of bound + assert_eq!( + range_set + .complement(&15, &35) + .into_iter() + .collect::>(), + vec![15..20, 30..35] + ); + + // some ranges are partially out of bound + assert_eq!( + range_set + .complement(&5, &45) + .into_iter() + .collect::>(), + vec![10..20, 30..40] + ); + + // test all ranges out of bound + assert_eq!( + range_set + .complement(&12, &18) + .into_iter() + .collect::>(), + vec![12..18] + ); + + // test complement empty + assert_eq!( + range_set + .complement(&20, &30) + .into_iter() + .collect::>(), + vec![] + ); + + // test boundaries at range start and end + assert_eq!( + range_set + .complement(&0, &30) + .into_iter() + .collect::>(), + vec![10..20] + ); + + // test with equal bounds + assert_eq!( + range_set + .complement(&35, &35) + .into_iter() + .collect::>(), + vec![] + ); + + // test with reversed bounds + assert_eq!( + range_set + .complement(&30, &0) + .into_iter() + .collect::>(), + vec![] + ); + } + + #[test] + fn test_many_small_ranges() { + let mut range_set = RangeSet::new(); + // Insert many small ranges that will coalesce + for i in 0..1000 { + range_set.insert_range(i * 10..(i * 10 + 5)); + } + // Should result in 1000 separate single-element ranges + assert_eq!(range_set.into_iter().count(), 1000); + } + + #[test] + fn test_large_range_coalescing() { + let mut range_set = RangeSet::new(); + // Insert ranges that will eventually all coalesce into one + for i in 0..1000 { + range_set.insert_range(i * 10..(i * 10 + 5)); + } + // Fill the gaps + range_set.insert_range(0..10000); + assert_eq!(range_set.into_iter().collect::>(), vec![0..10000]); + } +} + +#[cfg(test)] +#[expect(clippy::unwrap_used)] +mod test_linear_address_range_set { + + use crate::{FreeListParent, PathComponent, TrieNodeParent, area_index}; + + use super::*; + use test_case::test_case; + + const TEST_PARENT: StoredAreaParent = StoredAreaParent::TrieNode(TrieNodeParent::Root); + + #[test] + fn test_empty() { + let visited = LinearAddressRangeSet::new(0x1000).unwrap(); + let visited_ranges = visited + .into_iter() + .map(|range| (range.start, range.end)) + .collect::>(); + assert_eq!(visited_ranges, vec![]); + } + + #[test] + fn test_insert_area() { + let start = 2048; + let size = 1024; + + let start_addr = LinearAddress::new(start).unwrap(); + let end_addr = LinearAddress::new(start + size).unwrap(); + + let mut visited = LinearAddressRangeSet::new(0x1000).unwrap(); + visited + .insert_area(start_addr, size, TEST_PARENT) + .expect("the given area should be within bounds"); + + let visited_ranges = visited + .into_iter() + .map(|range| (range.start, range.end)) + .collect::>(); + assert_eq!(visited_ranges, vec![(start_addr, end_addr)]); + } + + #[test] + fn test_consecutive_areas_merge() { + let start1 = 2048; + let size1 = 1024; + let start2 = start1 + size1; + let size2 = 1024; + + let start1_addr = LinearAddress::new(start1).unwrap(); + let start2_addr = LinearAddress::new(start2).unwrap(); + let end2_addr = LinearAddress::new(start2 + size2).unwrap(); + + let mut visited = LinearAddressRangeSet::new(0x1000).unwrap(); + visited + .insert_area(start1_addr, size1, TEST_PARENT) + .expect("the given area should be within bounds"); + + visited + .insert_area(start2_addr, size2, TEST_PARENT) + .expect("the given area should be within bounds"); + + let visited_ranges = visited + .into_iter() + .map(|range| (range.start, range.end)) + .collect::>(); + assert_eq!(visited_ranges, vec![(start1_addr, end2_addr),]); + } + + #[test] + fn test_intersecting_areas_will_fail() { + let start1 = 2048; + let size1 = 1024; + let start2 = start1 + size1 - 1; + let size2 = 1024; + + let start1_addr = LinearAddress::new(start1).unwrap(); + let end1_addr = LinearAddress::new(start1 + size1).unwrap(); + let start2_addr = LinearAddress::new(start2).unwrap(); + + let parent1 = + StoredAreaParent::TrieNode(TrieNodeParent::Parent(start1_addr, PathComponent::ALL[5])); + let parent2 = StoredAreaParent::FreeList(FreeListParent::FreeListHead(area_index!(3))); + + let mut visited = LinearAddressRangeSet::new(0x1000).unwrap(); + visited + .insert_area(start1_addr, size1, parent1) + .expect("the given area should be within bounds"); + + let error = visited + .insert_area(start2_addr, size2, parent2) + .expect_err("the given area should intersect with the first area"); + + assert!( + matches!(error, CheckerError::AreaIntersects { start, size, intersection, parent } if start == start2_addr && size == size2 && intersection == vec![start2_addr..end1_addr] && parent == parent2) + ); + + // try inserting in opposite order + let mut visited2 = LinearAddressRangeSet::new(0x1000).unwrap(); + visited2 + .insert_area(start2_addr, size2, parent2) + .expect("the given area should be within bounds"); + + let error = visited2 + .insert_area(start1_addr, size1, parent1) + .expect_err("the given area should intersect with the first area"); + + assert!( + matches!(error, CheckerError::AreaIntersects { start, size, intersection, parent } if start == start1_addr && size == size1 && intersection == vec![start2_addr..end1_addr] && parent == parent1) + ); + } + + #[test] + fn test_complement() { + let start1 = 3000; + let size1 = 1024; + let start2 = 4096; + let size2 = 1024; + let db_size = 0x2000; + + let db_begin = LinearAddressRangeSet::NODE_STORE_START_ADDR; + let start1_addr = LinearAddress::new(start1).unwrap(); + let end1_addr = LinearAddress::new(start1 + size1).unwrap(); + let start2_addr = LinearAddress::new(start2).unwrap(); + let end2_addr = LinearAddress::new(start2 + size2).unwrap(); + let db_end = LinearAddress::new(db_size).unwrap(); + + let mut visited = LinearAddressRangeSet::new(db_size).unwrap(); + visited + .insert_area(start1_addr, size1, TEST_PARENT) + .unwrap(); + visited + .insert_area(start2_addr, size2, TEST_PARENT) + .unwrap(); + + let complement = visited.complement().into_iter().collect::>(); + assert_eq!( + complement, + vec![ + db_begin..start1_addr, + end1_addr..start2_addr, + end2_addr..db_end, + ] + ); + } + + #[test] + fn test_complement_with_full_range() { + let db_size = 0x1000; + let start = 2048; + let size = db_size - start; + + let mut visited = LinearAddressRangeSet::new(db_size).unwrap(); + visited + .insert_area(LinearAddress::new(start).unwrap(), size, TEST_PARENT) + .unwrap(); + let complement = visited.complement().into_iter().collect::>(); + assert_eq!(complement, vec![]); + } + + #[test] + fn test_complement_with_empty() { + let db_size = LinearAddressRangeSet::NODE_STORE_START_ADDR; + let visited = LinearAddressRangeSet::new(db_size.get()).unwrap(); + let complement = visited.complement().into_iter().collect::>(); + assert_eq!(complement, vec![]); + } + + #[test_case(0, "Linear Address Range Set: "; "empty")] + #[test_case(1, "Linear Address Range Set:\n\ + \tAddress Range: [0x1000, 0x1010)"; "1 range")] + #[test_case(3, "Linear Address Range Set:\n\ + \tAddress Range: [0x1000, 0x1010)\n\ + \tAddress Range: [0x1020, 0x1030)\n\ + \tAddress Range: [0x1040, 0x1050)"; "3 ranges")] + #[test_case(10, "Linear Address Range Set:\n\ + \tAddress Range: [0x1000, 0x1010)\n\ + \tAddress Range: [0x1020, 0x1030)\n\ + \tAddress Range: [0x1040, 0x1050)\n\ + \tAddress Range: [0x1060, 0x1070)\n\ + \tAddress Range: [0x1080, 0x1090)\n\ + \tAddress Range: [0x10a0, 0x10b0)\n\ + \tAddress Range: [0x10c0, 0x10d0)\n\ + \tAddress Range: [0x10e0, 0x10f0)\n\ + \tAddress Range: [0x1100, 0x1110)\n\ + \tAddress Range: [0x1120, 0x1130)"; "10 ranges")] + #[test_case(11, "Linear Address Range Set:\n\ + \tAddress Range: [0x1000, 0x1010)\n\ + \tAddress Range: [0x1020, 0x1030)\n\ + \tAddress Range: [0x1040, 0x1050)\n\ + \tAddress Range: [0x1060, 0x1070)\n\ + \tAddress Range: [0x1080, 0x1090)\n\ + \tAddress Range: [0x10a0, 0x10b0)\n\ + \tAddress Range: [0x10c0, 0x10d0)\n\ + \tAddress Range: [0x10e0, 0x10f0)\n\ + \tAddress Range: [0x1100, 0x1110)\n\ + \tAddress Range: [0x1120, 0x1130)\n\ + \t... (1 more hidden)"; "11 ranges")] + #[test_case(20, "Linear Address Range Set:\n\ + \tAddress Range: [0x1000, 0x1010)\n\ + \tAddress Range: [0x1020, 0x1030)\n\ + \tAddress Range: [0x1040, 0x1050)\n\ + \tAddress Range: [0x1060, 0x1070)\n\ + \tAddress Range: [0x1080, 0x1090)\n\ + \tAddress Range: [0x10a0, 0x10b0)\n\ + \tAddress Range: [0x10c0, 0x10d0)\n\ + \tAddress Range: [0x10e0, 0x10f0)\n\ + \tAddress Range: [0x1100, 0x1110)\n\ + \tAddress Range: [0x1120, 0x1130)\n\ + \t... (10 more hidden)"; "20 ranges")] + fn test_display(items: usize, expected: &str) { + let mut range_set = LinearAddressRangeSet::new(0x2000).unwrap(); + for i in 0..items { + #[allow(clippy::arithmetic_side_effects)] + let offset = i as u64 * 0x20 + 0x1000; + range_set + .insert_area(LinearAddress::new(offset).unwrap(), 0x10, TEST_PARENT) + .unwrap(); + } + assert_eq!(format!("{range_set}"), expected); + } +} diff --git a/firewood/storage/src/hashednode.rs b/firewood/storage/src/hashednode.rs new file mode 100644 index 000000000000..4eb0c681000e --- /dev/null +++ b/firewood/storage/src/hashednode.rs @@ -0,0 +1,190 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::{ + Children, HashType, HashableShunt, IntoSplitPath, Node, Path, PathComponent, SplitPath, +}; +use smallvec::SmallVec; + +impl<'a, P: SplitPath> HashableShunt<'a, P, &'a [PathComponent]> { + /// Creates a new [`HashableShunt`] from the given `node` at the given `prefix`. + pub fn from_node(prefix: P, node: &'a Node) -> Self { + match node { + Node::Branch(node) => { + // All child hashes should be filled in. + // TODO danlaine: Enforce this with the type system. + debug_assert!( + node.children + .iter() + .all(|(_, c)| !matches!(c, Some(crate::Child::Node(_)))), + "branch children: {:?}", + node.children + ); + Self::new( + prefix, + node.partial_path.as_components(), + node.value.as_deref().map(ValueDigest::Value), + node.children_hashes(), + ) + } + Node::Leaf(node) => Self::new( + prefix, + node.partial_path.as_components(), + Some(ValueDigest::Value(&node.value)), + Children::new(), + ), + } + } +} + +/// Returns the hash of `node`, which is at the given `path_prefix`. +#[must_use] +pub fn hash_node(node: &Node, path_prefix: &Path) -> HashType { + HashableShunt::from_node(path_prefix.as_components(), node).to_hash() +} + +/// Returns the serialized representation of `node` used as the pre-image +/// when hashing the node. The node is at the given `path_prefix`. +#[must_use] +pub fn hash_preimage(node: &Node, path_prefix: &Path) -> Box<[u8]> { + // Key, 3 options, value digest + #[expect(clippy::arithmetic_side_effects)] + let est_len = node.partial_path().len() + path_prefix.len() + 3 + HashType::empty().len(); + let mut buf = Vec::with_capacity(est_len); + HashableShunt::from_node(path_prefix.as_components(), node).write(&mut buf); + buf.into_boxed_slice() +} + +pub trait HasUpdate { + fn update>(&mut self, data: T); +} + +impl HasUpdate for Vec { + fn update>(&mut self, data: T) { + self.extend_from_slice(data.as_ref()); + } +} + +impl> HasUpdate for SmallVec { + fn update>(&mut self, data: T) { + self.extend_from_slice(data.as_ref()); + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +/// A `ValueDigest` is either a node's value or the hash of its value. +pub enum ValueDigest { + /// The node's value. + Value(T), + #[cfg(not(feature = "ethhash"))] + /// For MerkleDB hashing, the digest is the hash of the value if it is 32 + /// bytes or longer. + Hash(HashType), +} + +impl> ValueDigest { + /// Verifies that the value or hash matches the expected value. + pub fn verify(&self, expected: impl AsRef<[u8]>) -> bool { + match self { + Self::Value(got_value) => { + // This proof proves that `key` maps to `got_value`. + got_value.as_ref() == expected.as_ref() + } + #[cfg(not(feature = "ethhash"))] + Self::Hash(got_hash) => { + use sha2::{Digest, Sha256}; + // This proof proves that `key` maps to a value + // whose hash is `got_hash`. + *got_hash == HashType::from(Sha256::digest(expected.as_ref())) + } + } + } + + /// Returns a `ValueDigest` that borrows from this one. + pub fn as_ref(&self) -> ValueDigest<&[u8]> { + match self { + Self::Value(v) => ValueDigest::Value(v.as_ref()), + #[cfg(not(feature = "ethhash"))] + Self::Hash(h) => ValueDigest::Hash(h.clone()), + } + } + + /// Convert the value to a hash if it is not already a hash. + /// + /// If the value is less than 32 bytes, it will be passed through as is + /// instead of hashing. + /// + /// If etherum hashing is enabled, this will always return the value as is. + pub fn make_hash(&self) -> ValueDigest<&[u8]> { + match self.as_ref() { + #[cfg(not(feature = "ethhash"))] + ValueDigest::Value(v) if v.len() >= 32 => { + use sha2::{Digest, Sha256}; + ValueDigest::Hash(HashType::from(Sha256::digest(v))) + } + + ValueDigest::Value(v) => ValueDigest::Value(v), + + #[cfg(not(feature = "ethhash"))] + ValueDigest::Hash(v) => ValueDigest::Hash(v), + } + } + + /// Maps the value inside this `ValueDigest` to another value. + pub fn map(self, f: impl FnOnce(T) -> O) -> ValueDigest { + match self { + Self::Value(v) => ValueDigest::Value(f(v)), + #[cfg(not(feature = "ethhash"))] + Self::Hash(h) => ValueDigest::Hash(h), + } + } +} + +impl> AsRef<[u8]> for ValueDigest { + fn as_ref(&self) -> &[u8] { + match self { + Self::Value(v) => v.as_ref(), + #[cfg(not(feature = "ethhash"))] + Self::Hash(h) => h.as_ref(), + } + } +} + +/// A node in the trie that can be hashed. +pub trait Hashable: std::fmt::Debug { + /// The type of the leading path. + type LeadingPath<'a>: IntoSplitPath + 'a + where + Self: 'a; + + /// The type of the partial path. + type PartialPath<'a>: IntoSplitPath + 'a + where + Self: 'a; + + /// The type of the full path. + type FullPath<'a>: IntoSplitPath + 'a + where + Self: 'a; + + /// The full path of this node's parent where each byte is a nibble. + fn parent_prefix_path(&self) -> Self::LeadingPath<'_>; + /// The partial path of this node where each byte is a nibble. + fn partial_path(&self) -> Self::PartialPath<'_>; + /// The full path of this node including the parent's prefix where each byte is a nibble. + fn full_path(&self) -> Self::FullPath<'_>; + /// The node's value or hash. + fn value_digest(&self) -> Option>; + /// Each element is a child's index and hash. + /// Yields 0 elements if the node is a leaf. + fn children(&self) -> Children>; +} + +/// A preimage of a hash. +pub trait Preimage: std::fmt::Debug { + /// Returns the hash of this preimage. + fn to_hash(&self) -> HashType; + + /// Write this hash preimage to `buf`. + fn write(&self, buf: &mut impl HasUpdate); +} diff --git a/firewood/storage/src/hashedshunt.rs b/firewood/storage/src/hashedshunt.rs new file mode 100644 index 000000000000..fe5bb1d230bf --- /dev/null +++ b/firewood/storage/src/hashedshunt.rs @@ -0,0 +1,88 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::{Children, HashType, Hashable, JoinedPath, SplitPath, ValueDigest}; + +/// A shunt for a hasheable trie that we can use to compute the hash of a node +/// using component parts. +pub struct HashableShunt<'a, P1, P2> { + parent_prefix: P1, + partial_path: P2, + value: Option>, + child_hashes: Children>, +} + +impl<'a, P1: SplitPath, P2: SplitPath> HashableShunt<'a, P1, P2> { + /// Creates a new [`HashableShunt`]. + #[must_use] + pub const fn new( + parent_prefix: P1, + partial_path: P2, + value: Option>, + child_hashes: Children>, + ) -> Self { + Self { + parent_prefix, + partial_path, + value, + child_hashes, + } + } + + /// Calculates the hash of this shunt. + pub fn to_hash(&self) -> HashType { + crate::Preimage::to_hash(self) + } +} + +impl std::fmt::Debug for HashableShunt<'_, P1, P2> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HashableShunt") + .field("parent_prefix", &self.parent_prefix.display()) + .field("partial_path", &self.partial_path.display()) + .field( + "value", + &self.value.as_ref().map(|v| v.as_ref().map(hex::encode)), + ) + .field("child_hashes", &self.child_hashes) + .field("hash", &self.to_hash()) + .finish() + } +} + +impl Hashable for HashableShunt<'_, P1, P2> { + type LeadingPath<'a> + = P1 + where + Self: 'a; + + type PartialPath<'a> + = P2 + where + Self: 'a; + + type FullPath<'a> + = JoinedPath + where + Self: 'a; + + fn parent_prefix_path(&self) -> Self::LeadingPath<'_> { + self.parent_prefix + } + + fn partial_path(&self) -> Self::PartialPath<'_> { + self.partial_path + } + + fn full_path(&self) -> Self::FullPath<'_> { + self.parent_prefix_path().append(self.partial_path()) + } + + fn value_digest(&self) -> Option> { + self.value.clone() + } + + fn children(&self) -> Children> { + self.child_hashes.clone() + } +} diff --git a/firewood/storage/src/hashers/ethhash.rs b/firewood/storage/src/hashers/ethhash.rs new file mode 100644 index 000000000000..a70966850d3c --- /dev/null +++ b/firewood/storage/src/hashers/ethhash.rs @@ -0,0 +1,281 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// Ethereum compatible hashing algorithm. + +#![cfg_attr( + feature = "ethhash", + expect( + clippy::too_many_lines, + reason = "Found 1 occurrences after enabling the lint." + ) +)] + +use crate::logger::warn; +use crate::{ + BranchNode, HashType, Hashable, Preimage, TrieHash, TriePath, ValueDigest, + hashednode::HasUpdate, logger::trace, +}; +use bitfield::bitfield; +use bytes::BytesMut; +use rlp::{Rlp, RlpStream}; +use sha3::{Digest, Keccak256}; +use smallvec::SmallVec; +use std::iter::once; + +impl HasUpdate for Keccak256 { + fn update>(&mut self, data: T) { + sha3::Digest::update(self, data); + } +} + +// Takes a set of nibbles and converts them to a set of bytes that we can hash +// The input consists of nibbles, but there may be an invalid nibble at the end of 0x10 +// which indicates that we need to set bit 5 of the first output byte +// The input may also have an odd number of nibbles, in which case the first output byte +// will have bit 4 set and the low nibble will be the low nibble of the first byte +// Restated: 00ABCCCC +// 0 is always 0 +// A is 1 if this is a leaf +// B is 1 if the input had an odd number of nibbles +// CCCC is the first nibble if B is 1, otherwise it is all 0s + +fn nibbles_to_eth_compact(nibbles: T, is_leaf: bool) -> SmallVec<[u8; 32]> { + // This is a bitfield that represents the first byte of the output, documented above + bitfield! { + struct CompactFirstByte(u8); + impl Debug; + impl new; + u8; + is_leaf, set_is_leaf: 5; + odd_nibbles, set_odd_nibbles: 4; + low_nibble, set_low_nibble: 3, 0; + } + + let nibbles = nibbles.as_component_slice(); + + let mut first_byte = CompactFirstByte(0); + first_byte.set_is_leaf(is_leaf); + + let (maybe_low_nibble, nibble_pairs) = nibbles.as_rchunks::<2>(); + if let &[low_nibble] = maybe_low_nibble { + // we have an odd number of nibbles + first_byte.set_odd_nibbles(true); + first_byte.set_low_nibble(low_nibble.as_u8()); + } else { + // as_rchunks can only return 0 or 1 element in the first slice if N is 2 + debug_assert!(maybe_low_nibble.is_empty()); + } + + // now assemble everything: the first byte, and the nibble pairs compacted back together + once(first_byte.0) + .chain(nibble_pairs.iter().map(|&[hi, lo]| hi.join(lo))) + .collect() +} + +impl Preimage for T { + fn to_hash(&self) -> HashType { + // first collect the thing that would be hashed, and if it's smaller than a hash, + // just use it directly + let mut collector = SmallVec::with_capacity(32); + self.write(&mut collector); + + trace!( + "SIZE WAS {} {}", + self.full_path().len(), + hex::encode(&collector), + ); + + if collector.len() >= 32 { + HashType::Hash(Keccak256::digest(collector).into()) + } else { + HashType::Rlp(collector) + } + } + + fn write(&self, buf: &mut impl HasUpdate) { + let is_account = self.full_path().len() == 64; + trace!("is_account: {is_account}"); + + let child_hashes = self.children(); + + let children = child_hashes.count(); + + if children == 0 { + // since there are no children, this must be a leaf + // we append two items, the partial_path, encoded, and the value + // note that leaves must always have a value, so we know there + // will be 2 items + + let mut rlp = RlpStream::new_list(2); + + rlp.append(&&*nibbles_to_eth_compact(self.partial_path(), true)); + + if is_account { + // we are a leaf that is at depth 32 + match self.value_digest() { + Some(ValueDigest::Value(bytes)) => { + let new_hash = Keccak256::digest(rlp::NULL_RLP).as_slice().to_vec(); + let bytes_mut = BytesMut::from(bytes); + if let Some(result) = replace_hash(bytes_mut, new_hash) { + rlp.append(&&*result); + } else { + rlp.append(&bytes); + } + } + None => { + rlp.append_empty_data(); + } + } + } else { + match self.value_digest() { + Some(ValueDigest::Value(bytes)) => rlp.append(&bytes), + None => rlp.append_empty_data(), + }; + } + + let bytes = rlp.out(); + trace!("partial path {:?}", self.partial_path().display()); + trace!("serialized leaf-rlp: {:?}", hex::encode(&bytes)); + buf.update(&bytes); + } else { + // for a branch, there are always 16 children and a value + // Child::None we encode as RLP empty_data (0x80) + let mut rlp = RlpStream::new_list(const { BranchNode::MAX_CHILDREN + 1 }); + for (_, child) in &child_hashes { + match child { + Some(HashType::Hash(hash)) => rlp.append(&hash.as_slice()), + Some(HashType::Rlp(rlp_bytes)) => rlp.append_raw(rlp_bytes, 1), + None => rlp.append_empty_data(), + }; + } + + // For branch nodes, we need to append the value as the 17th element in the RLP list. + // However, account nodes (depth 32) handle values differently - they don't store + // the value directly in the branch node, but rather in the account structure itself. + // This is because account nodes have special handling where the storage root hash + // gets replaced in the account data structure during serialization. + let digest = (!is_account).then(|| self.value_digest()).flatten(); + if let Some(ValueDigest::Value(digest)) = digest { + rlp.append(&digest); + } else { + rlp.append_empty_data(); + } + let bytes = rlp.out(); + trace!("pass 1 bytes {:02X?}", hex::encode(&bytes)); + + // we've collected all the children in bytes + + let updated_bytes = if is_account { + // need to get the value again + if let Some(ValueDigest::Value(rlp_encoded_bytes)) = self.value_digest() { + // rlp_encoded__bytes needs to be decoded + // TODO: Handle corruption + // needs to be the hash of the RLP encoding of the root node that + // would have existed here (instead of this account node) + // the "root node" is actually this branch node iff there is + // more than one child. If there is only one child, then the + // child is actually the root node, so we need the hash of that + // child here. + let replacement_hash = if children == 1 { + // we need to treat this child like it's a root node, so the partial path is + // actually one longer than it is reported + match child_hashes + .iter() + .find_map(|(_, c)| c.as_ref()) + .expect("we know there is exactly one child") + { + HashType::Hash(hash) => hash.clone(), + HashType::Rlp(rlp_bytes) => { + let mut rlp = RlpStream::new_list(2); + rlp.append(&&*nibbles_to_eth_compact(self.partial_path(), true)); + rlp.append_raw(rlp_bytes, 1); + let bytes = rlp.out(); + TrieHash::from(Keccak256::digest(bytes)) + } + } + } else { + TrieHash::from(Keccak256::digest(bytes)) + }; + trace!("replacement hash {:?}", hex::encode(&replacement_hash)); + + let bytes = replace_hash(rlp_encoded_bytes, replacement_hash) + .unwrap_or_else(|| BytesMut::from(rlp_encoded_bytes)); + trace!("updated encoded value {:02X?}", hex::encode(&bytes)); + bytes + } else { + // treat like non-account since it didn't have a value + warn!( + "Account node {:x?} without value", + self.full_path().display(), + ); + bytes.as_ref().into() + } + } else { + bytes.as_ref().into() + }; + + let partial_path = self.partial_path(); + if partial_path.is_empty() { + trace!("pass 2=bytes {:02X?}", hex::encode(&updated_bytes)); + buf.update(updated_bytes); + } else { + let mut final_bytes = RlpStream::new_list(2); + final_bytes.append(&&*nibbles_to_eth_compact(partial_path, is_account)); + // if the RLP is short enough, we can use it as-is, otherwise we hash it + // to make the maximum length 32 bytes + if updated_bytes.len() > 31 && !is_account { + let hashed_bytes = Keccak256::digest(updated_bytes); + final_bytes.append(&hashed_bytes.as_slice()); + } else { + final_bytes.append(&updated_bytes); + } + let final_bytes = final_bytes.out(); + trace!("pass 2 bytes {:02X?}", hex::encode(&final_bytes)); + buf.update(final_bytes); + } + } + } +} + +// TODO: we could be super fancy and just plunk the correct bytes into the existing BytesMut +fn replace_hash, U: AsRef<[u8]>>(bytes: T, new_hash: U) -> Option { + // rlp_encoded_bytes needs to be decoded + let rlp = Rlp::new(bytes.as_ref()); + let mut list = rlp.as_list().ok()?; + let replace = list.get_mut(2)?; + *replace = Vec::from(new_hash.as_ref()); + + trace!("inbound bytes: {}", hex::encode(bytes.as_ref())); + trace!("list length was {}", list.len()); + trace!("replacement hash {:?}", hex::encode(&new_hash)); + + let mut rlp = RlpStream::new_list(list.len()); + for item in list { + rlp.append(&item); + } + let bytes = rlp.out(); + trace!("updated encoded value {:02X?}", hex::encode(&bytes)); + Some(bytes) +} + +#[cfg(test)] +mod test { + use test_case::test_case; + + use crate::{PathComponent, TriePathFromUnpackedBytes}; + + #[test_case(&[], false, &[0x00])] + #[test_case(&[], true, &[0x20])] + #[test_case(&[1, 2, 3, 4, 5], false, &[0x11, 0x23, 0x45])] + #[test_case(&[0, 1, 2, 3, 4, 5], false, &[0x00, 0x01, 0x23, 0x45])] + #[test_case(&[15, 1, 12, 11, 8], true, &[0x3f, 0x1c, 0xb8])] + #[test_case(&[0, 15, 1, 12, 11, 8], true, &[0x20, 0x0f, 0x1c, 0xb8])] + fn test_hex_to_compact(hex: &[u8], has_value: bool, expected_compact: &[u8]) { + let path = <&[PathComponent]>::path_from_unpacked_bytes(hex).expect("valid path"); + assert_eq!( + &*super::nibbles_to_eth_compact(path, has_value), + expected_compact + ); + } +} diff --git a/firewood/storage/src/hashers/merkledb.rs b/firewood/storage/src/hashers/merkledb.rs new file mode 100644 index 000000000000..c82472da0ecf --- /dev/null +++ b/firewood/storage/src/hashers/merkledb.rs @@ -0,0 +1,95 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![cfg_attr( + not(feature = "ethhash"), + expect( + clippy::arithmetic_side_effects, + reason = "Found 1 occurrences after enabling the lint." + ) +)] + +use crate::hashednode::{HasUpdate, Hashable, Preimage}; +use crate::{TrieHash, TriePath, TriePathAsPackedBytes, ValueDigest}; +/// Merkledb compatible hashing algorithm. +use integer_encoding::VarInt; +use sha2::{Digest, Sha256}; + +const MAX_VARINT_SIZE: usize = 10; +const BITS_PER_NIBBLE: u64 = 4; + +impl HasUpdate for Sha256 { + fn update>(&mut self, data: T) { + sha2::Digest::update(self, data); + } +} + +impl Preimage for T { + fn to_hash(&self) -> TrieHash { + let mut hasher = Sha256::new(); + + self.write(&mut hasher); + hasher.finalize().into() + } + + fn write(&self, buf: &mut impl HasUpdate) { + let children = self.children(); + + let num_children = children.count() as u64; + + add_varint_to_buf(buf, num_children); + + for (index, hash) in &children { + if let Some(hash) = hash { + add_varint_to_buf(buf, u64::from(index.as_u8())); + buf.update(hash); + } + } + + // Add value digest (if any) to hash pre-image + add_value_digest_to_buf(buf, self.value_digest()); + + // Add key length (in bits) to hash pre-image + let key = self.full_path(); + let key_bit_len = BITS_PER_NIBBLE * key.len() as u64; + add_varint_to_buf(buf, key_bit_len); + // Add key to hash pre-image + key.as_packed_bytes().for_each(|byte| buf.update([byte])); + } +} + +fn add_value_digest_to_buf>( + buf: &mut H, + value_digest: Option>, +) { + let Some(value_digest) = value_digest else { + let value_exists: u8 = 0; + buf.update([value_exists]); + return; + }; + + let value_exists: u8 = 1; + buf.update([value_exists]); + + add_len_and_value_to_buf(buf, value_digest.make_hash()); +} + +#[inline] +/// Writes the length of `value` and `value` to `buf`. +fn add_len_and_value_to_buf>(buf: &mut H, value: V) { + let value_len = value.as_ref().len(); + buf.update([value_len as u8]); + buf.update(value); +} + +#[inline] +/// Encodes `value` as a varint and writes it to `buf`. +fn add_varint_to_buf(buf: &mut H, value: u64) { + let mut buf_arr = [0u8; MAX_VARINT_SIZE]; + let len = value.encode_var(&mut buf_arr); + buf.update( + buf_arr + .get(..len) + .expect("length is always less than MAX_VARINT_SIZE"), + ); +} diff --git a/firewood/storage/src/hashers/mod.rs b/firewood/storage/src/hashers/mod.rs new file mode 100644 index 000000000000..786b0a90333d --- /dev/null +++ b/firewood/storage/src/hashers/mod.rs @@ -0,0 +1,7 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#[cfg(feature = "ethhash")] +mod ethhash; +#[cfg(not(feature = "ethhash"))] +mod merkledb; diff --git a/firewood/storage/src/iter.rs b/firewood/storage/src/iter.rs new file mode 100644 index 000000000000..9dcbd82198bb --- /dev/null +++ b/firewood/storage/src/iter.rs @@ -0,0 +1,81 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! Internal utilities for working with iterators. + +/// Writes a limited number of items to a writer, separated by a specified separator. +/// +/// - If `limit` is `Some(0)`, it will only write the number of hidden items. +/// - If `limit` is `Some(n)`, it will write at most `n` items, followed by a message +/// indicating how many more items were not written. +/// - If `limit` is `None`, it will write all items without any limit. +/// Caution: if limit is None, this function will not work with iterators that do not terminate. +/// +/// # Arguments +/// - `writer`: The writer to which the items will be written. +/// - `iter`: An iterator of items that implement `std::fmt::Display`. +/// - `sep`: A separator that will be used between items. +/// - `limit`: An optional limit on the number of items to write. +/// +/// # Returns +/// A `std::fmt::Result` indicating success or failure of the write operation. +pub(crate) fn write_limited_with_sep( + writer: &mut (impl std::fmt::Write + ?Sized), + iter: impl IntoIterator, + sep: impl std::fmt::Display, + limit: Option, +) -> std::fmt::Result { + match limit { + Some(0) => { + let hidden_count = iter.into_iter().count(); + write!(writer, "({hidden_count} hidden)") + } + Some(limit) => { + let mut iter = iter.into_iter(); + let to_display_iter = iter.by_ref().take(limit); + write_all_with_sep(writer, to_display_iter, &sep)?; + + let hidden_count = iter.count(); + if hidden_count > 0 { + write!(writer, "{sep}... ({hidden_count} more hidden)")?; + } + Ok(()) + } + None => write_all_with_sep(writer, iter, &sep), + } +} + +// Helper function that writes all items in the iterator. +// Caution: this function will not work with iterators that do not terminate. +fn write_all_with_sep( + writer: &mut (impl std::fmt::Write + ?Sized), + iter: impl IntoIterator, + sep: &impl std::fmt::Display, +) -> std::fmt::Result { + let mut iter = iter.into_iter(); + if let Some(item) = iter.next() { + write!(writer, "{item}")?; + for item in iter { + write!(writer, "{sep}{item}")?; + } + } + Ok(()) +} + +#[cfg(test)] +mod tests { + #![expect(clippy::unwrap_used)] + + use super::*; + use test_case::test_case; + + #[test_case(Some(0usize), "(4 hidden)"; "with limit 0")] + #[test_case(Some(2usize), "apple, banana, ... (2 more hidden)"; "with limit 2")] + #[test_case(None, "apple, banana, cherry, date"; "without limit")] + fn test_write_iter(limit: Option, expected: &str) { + let mut output = String::new(); + let items = ["apple", "banana", "cherry", "date"]; + write_limited_with_sep(&mut output, &items, ", ", limit).unwrap(); + assert_eq!(output, expected); + } +} diff --git a/firewood/storage/src/lib.rs b/firewood/storage/src/lib.rs new file mode 100644 index 000000000000..0c290bb66dd8 --- /dev/null +++ b/firewood/storage/src/lib.rs @@ -0,0 +1,341 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![warn(missing_debug_implementations, rust_2018_idioms, missing_docs)] +#![deny(unsafe_code)] +#![cfg_attr( + not(target_pointer_width = "64"), + forbid( + clippy::cast_possible_truncation, + reason = "non-64 bit target likely to cause issues during u64 to usize conversions" + ) +)] + +//! # storage implements the storage of a [Node] on top of a `LinearStore` +//! +//! Nodes are stored at a [`LinearAddress`] within a [`ReadableStorage`]. +//! +//! The [`NodeStore`] maintains a free list and the [`LinearAddress`] of a root node. +//! +//! A [`NodeStore`] is backed by a [`ReadableStorage`] which is persisted storage. + +use std::fmt::{Display, Formatter, LowerHex, Result}; +use std::ops::Range; + +mod checker; +mod hashednode; +mod hashedshunt; +mod hashers; +mod iter; +mod linear; +mod node; +mod nodestore; +mod path; +#[cfg(any(test, feature = "test_utils"))] +mod test_utils; +mod trie_hash; +mod tries; +mod u4; + +/// Logger module for handling logging functionality +pub mod logger; + +#[macro_use] +/// Macros module for defining macros used in the storage module +pub mod macros; +// re-export these so callers don't need to know where they are +pub use checker::{CheckOpt, CheckerReport, DBStats, FreeListsStats, TrieStats}; +pub use hashednode::{Hashable, Preimage, ValueDigest, hash_node, hash_preimage}; +pub use hashedshunt::HashableShunt; +pub use linear::{FileIoError, ReadableStorage, WritableStorage}; +pub use node::path::{NibblesIterator, Path}; +pub use node::{ + BranchNode, Child, Children, ChildrenSlots, LeafNode, Node, PathIterItem, + branch::{HashType, IntoHashType}, +}; +pub use nodestore::{ + AreaIndex, Committed, HashedNodeReader, ImmutableProposal, LinearAddress, MutableProposal, + NodeReader, NodeStore, Parentable, RootReader, TrieReader, +}; +pub use path::{ + ComponentIter, IntoSplitPath, JoinedPath, PartialPath, PathBuf, PathCommonPrefix, + PathComponent, PathComponentSliceExt, PathGuard, SplitPath, TriePath, TriePathAsPackedBytes, + TriePathFromPackedBytes, TriePathFromUnpackedBytes, +}; +#[cfg(not(feature = "branch_factor_256"))] +pub use path::{PackedBytes, PackedPathComponents, PackedPathRef}; +pub use tries::{ + DuplicateKeyError, HashedKeyValueTrieRoot, HashedTrieNode, IterAscending, IterDescending, + KeyValueTrieRoot, TrieEdgeIter, TrieEdgeState, TrieNode, TrieValueIter, +}; +pub use u4::{TryFromIntError, U4}; + +pub use linear::filebacked::FileBacked; +pub use linear::memory::MemStore; +pub use node::persist::MaybePersistedNode; +#[cfg(any(test, feature = "test_utils"))] +pub use test_utils::SeededRng; +pub use trie_hash::{InvalidTrieHashLength, TrieHash}; + +/// A shared node, which is just a triophe Arc of a node +pub type SharedNode = triomphe::Arc; + +/// The strategy for caching nodes that are read +/// from the storage layer. Generally, we only want to +/// cache write operations, but for some read-heavy workloads +/// you can enable caching of branch reads or all reads. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[non_exhaustive] +pub enum CacheReadStrategy { + /// Only cache writes (no reads will be cached) + WritesOnly, + + /// Cache branch reads (reads that are not leaf nodes) + BranchReads, + + /// Cache all reads (leaves and branches) + All, +} + +impl Display for CacheReadStrategy { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + write!(f, "{self:?}") + } +} + +/// This enum encapsulates what points to the stored area. +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub enum StoredAreaParent { + /// The stored area is a trie node + TrieNode(TrieNodeParent), + /// The stored area is a free list + FreeList(FreeListParent), +} + +/// This enum encapsulates what points to the stored area allocated for a trie node. +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub enum TrieNodeParent { + /// The stored area is the root of the trie, so the header points to it + Root, + /// The stored area is not the root of the trie, so a parent trie node points to it + Parent(LinearAddress, PathComponent), +} + +/// This enum encapsulates what points to the stored area allocated for a free list. +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub enum FreeListParent { + /// The stored area is the head of the free list, so the header points to it + FreeListHead(AreaIndex), + /// The stored area is not the head of the free list, so a previous free area points to it + PrevFreeArea { + /// The size index of the area, helps with debugging and fixing + area_size_idx: AreaIndex, + /// The address of the previous free area + parent_addr: LinearAddress, + }, +} + +impl LowerHex for StoredAreaParent { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self { + StoredAreaParent::TrieNode(trie_parent) => LowerHex::fmt(trie_parent, f), + StoredAreaParent::FreeList(free_list_parent) => LowerHex::fmt(free_list_parent, f), + } + } +} + +impl LowerHex for TrieNodeParent { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self { + TrieNodeParent::Root => f.write_str("Root"), + TrieNodeParent::Parent(addr, index) => { + f.write_str("TrieNode@")?; + LowerHex::fmt(addr, f)?; + f.write_fmt(format_args!("[{index}]")) + } + } + } +} + +impl LowerHex for FreeListParent { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match self { + FreeListParent::FreeListHead(index) => f.write_fmt(format_args!("FreeLists[{index}]")), + FreeListParent::PrevFreeArea { + area_size_idx, + parent_addr, + } => { + f.write_fmt(format_args!("FreeArea[{area_size_idx}]@"))?; + LowerHex::fmt(parent_addr, f) + } + } + } +} + +use derive_where::derive_where; + +/// Errors returned by the checker +#[derive(thiserror::Error, Debug)] +#[derive_where(PartialEq, Eq)] +#[non_exhaustive] +pub enum CheckerError { + /// The file size is not valid + #[error("Invalid DB size ({db_size}): {description}")] + InvalidDBSize { + /// The size of the db + db_size: u64, + /// The description of the error + description: String, + }, + + /// Hash mismatch for a node + #[error( + "Hash mismatch for node {path:?} at address {address}: parent stored {parent_stored_hash}, computed {computed_hash}" + )] + HashMismatch { + /// The path of the node + path: Path, + /// The address of the node + address: LinearAddress, + /// The parent of the node + parent: TrieNodeParent, + /// The hash value stored in the parent node + parent_stored_hash: HashType, + /// The hash value computed for the node + computed_hash: HashType, + }, + + /// The address is out of bounds + #[error( + "stored area at {start:#x} with size {size} (parent: {parent:#x}) is out of bounds ({bounds:#x?})" + )] + AreaOutOfBounds { + /// Start of the `StoredArea` + start: LinearAddress, + /// Size of the `StoredArea` + size: u64, + /// Valid range of addresses + bounds: Range, + /// The parent of the `StoredArea` + parent: StoredAreaParent, + }, + + /// Stored areas intersect + #[error( + "stored area at {start:#x} with size {size} (parent: {parent:#x}) intersects with other stored areas: {intersection:#x?}" + )] + AreaIntersects { + /// Start of the `StoredArea` + start: LinearAddress, + /// Size of the `StoredArea` + size: u64, + /// The intersection + intersection: Vec>, + /// The parent of the `StoredArea` + parent: StoredAreaParent, + }, + + /// Node is larger than the area it is stored in + #[error( + "stored area at {area_start:#x} with size {area_size} (parent: {parent:#x}) stores a node of size {node_bytes}" + )] + NodeLargerThanArea { + /// Address of the area + area_start: LinearAddress, + /// Size of the area + area_size: u64, + /// Size of the node + node_bytes: u64, + /// The parent of the area + parent: TrieNodeParent, + }, + + /// Freelist area size does not match + #[error( + "Free area {address:#x} of size {size} (parent: {parent:#x}) is found in free list {actual_free_list} but it should be in freelist {expected_free_list}" + )] + FreelistAreaSizeMismatch { + /// Address of the free area + address: LinearAddress, + /// Actual size of the free area + size: u64, + /// Free list on which the area is stored + actual_free_list: AreaIndex, + /// Expected size of the area + expected_free_list: AreaIndex, + /// The parent of the free area + parent: FreeListParent, + }, + + /// The start address of a stored area is not a multiple of 16 + #[error( + "The start address of a stored area (parent: {parent:#x}) is not a multiple of {}: {address:#x}", + nodestore::primitives::AreaIndex::MIN_AREA_SIZE + )] + AreaMisaligned { + /// The start address of the stored area + address: LinearAddress, + /// The parent of the `StoredArea` + parent: StoredAreaParent, + }, + + /// Found leaked areas + #[error("Found leaked areas: {0}")] + #[derive_where(skip_inner)] + AreaLeaks(checker::LinearAddressRangeSet), + + /// The root is not persisted + #[error("The checker can only check persisted nodestores")] + UnpersistedRoot, + + #[error( + "The node {key:#x} at {address:#x} (parent: {parent:#x}) has a value but its path is not 32 or 64 bytes long" + )] + /// A value is found corresponding to an invalid key. + /// With ethhash, keys must be 32 or 64 bytes long. + /// Without ethhash, keys cannot contain half-bytes (i.e., odd number of nibbles). + InvalidKey { + /// The key found, or equivalently the path of the node that stores the value + key: Path, + /// Address of the node + address: LinearAddress, + /// Parent of the node + parent: TrieNodeParent, + }, + + /// IO error + #[error("IO error reading pointer stored at {parent:#x}: {error}")] + #[derive_where(skip_inner)] + IO { + /// The error + error: FileIoError, + /// parent of the area + parent: StoredAreaParent, + }, +} + +impl CheckerError { + const fn parent(&self) -> Option { + match self { + CheckerError::InvalidDBSize { .. } + | CheckerError::AreaLeaks(_) + | CheckerError::UnpersistedRoot => None, + CheckerError::AreaOutOfBounds { parent, .. } + | CheckerError::AreaIntersects { parent, .. } + | CheckerError::AreaMisaligned { parent, .. } + | CheckerError::IO { parent, .. } => Some(*parent), + CheckerError::HashMismatch { parent, .. } + | CheckerError::NodeLargerThanArea { parent, .. } + | CheckerError::InvalidKey { parent, .. } => Some(StoredAreaParent::TrieNode(*parent)), + CheckerError::FreelistAreaSizeMismatch { parent, .. } => { + Some(StoredAreaParent::FreeList(*parent)) + } + } + } +} + +impl From for Vec { + fn from(error: CheckerError) -> Self { + vec![error] + } +} diff --git a/firewood/storage/src/linear/filebacked.rs b/firewood/storage/src/linear/filebacked.rs new file mode 100644 index 000000000000..3e4d553d1e75 --- /dev/null +++ b/firewood/storage/src/linear/filebacked.rs @@ -0,0 +1,424 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// This synchronous file layer is a simple implementation of what we +// want to do for I/O. This uses a [Mutex] lock around a simple `File` +// object. Instead, we probably should use an IO system that can perform multiple +// read/write operations at once + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 5 occurrences after enabling the lint." +)] +#![expect( + clippy::indexing_slicing, + reason = "Found 3 occurrences after enabling the lint." +)] +#![expect( + clippy::missing_errors_doc, + reason = "Found 1 occurrences after enabling the lint." +)] +#![expect( + clippy::missing_fields_in_debug, + reason = "Found 1 occurrences after enabling the lint." +)] + +use parking_lot::Mutex; +use std::fs::{File, OpenOptions}; +use std::io::Read; +#[cfg(feature = "io-uring")] +use std::mem::ManuallyDrop; +use std::num::NonZero; +#[cfg(unix)] +use std::os::unix::fs::FileExt; +#[cfg(windows)] +use std::os::windows::fs::FileExt; +use std::path::PathBuf; + +use lru::LruCache; +use metrics::counter; + +use crate::{CacheReadStrategy, LinearAddress, MaybePersistedNode, SharedNode}; + +use super::{FileIoError, OffsetReader, ReadableStorage, WritableStorage}; + +/// A [`ReadableStorage`] and [`WritableStorage`] backed by a file +pub struct FileBacked { + fd: File, + filename: PathBuf, + cache: Mutex>, + free_list_cache: Mutex>>, + cache_read_strategy: CacheReadStrategy, + #[cfg(feature = "io-uring")] + pub(crate) ring: Mutex>, +} + +impl Drop for FileBacked { + fn drop(&mut self) { + #[cfg(feature = "io-uring")] + { + // non-blocking because we have mutable access to self + let ring = self.ring.get_mut(); + + // We are manually dropping the ring here to ensure that it is + // flushed and dropped before we unlock the file descriptor. + #[expect(unsafe_code)] + // SAFETY: this is the only time `ring` is dropped. Furthermore, + // `Drop` ensures that this is only ever called once in a context + // where we are guaranteed to never use `ring` again. + unsafe { + ManuallyDrop::drop(ring); + } + } + + _ = self.fd.unlock().ok(); + } +} + +// Manual implementation since ring doesn't implement Debug :( +impl std::fmt::Debug for FileBacked { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("FileBacked") + .field("fd", &self.fd) + .field("cache", &self.cache) + .field("free_list_cache", &self.free_list_cache) + .field("cache_read_strategy", &self.cache_read_strategy) + .finish() + } +} + +impl FileBacked { + /// Acquire an advisory lock on the underlying file to prevent multiple processes + /// from accessing it simultaneously + pub fn lock(&self) -> Result<(), FileIoError> { + self.fd.try_lock().map_err(|e| { + let context = + "unable to obtain advisory lock: database may be opened by another instance" + .to_string(); + // Convert TryLockError to a generic IO error for our FileIoError + let io_error = std::io::Error::new(std::io::ErrorKind::WouldBlock, e); + self.file_io_error(io_error, 0, Some(context)) + }) + } + + /// Make a write operation from a raw data buffer for this file + #[cfg(feature = "io-uring")] + pub(crate) fn make_op(&self, data: &[u8]) -> io_uring::opcode::Write { + use std::os::fd::AsRawFd as _; + + use io_uring::opcode::Write; + use io_uring::types; + + Write::new( + types::Fd(self.fd.as_raw_fd()), + data.as_ptr(), + data.len() as _, + ) + } + + #[cfg(feature = "io-uring")] + // The size of the kernel ring buffer. This buffer will control how many writes we do with + // a single system call. + // TODO: make this configurable + pub(crate) const RINGSIZE: u32 = 32; + + /// Create or open a file at a given path + pub fn new( + path: PathBuf, + node_cache_size: NonZero, + free_list_cache_size: NonZero, + truncate: bool, + create: bool, + cache_read_strategy: CacheReadStrategy, + ) -> Result { + let fd = OpenOptions::new() + .read(true) + .write(true) + .truncate(truncate) + .create(create) + .open(&path) + .map_err(|e| FileIoError { + inner: e, + filename: Some(path.clone()), + offset: 0, + context: Some("file open".to_string()), + })?; + + #[cfg(feature = "io-uring")] + let ring = { + // The kernel will stop the worker thread in this many ms if there is no work to do + const IDLETIME_MS: u32 = 1000; + + io_uring::IoUring::builder() + // we promise not to fork and we are the only issuer of writes to this ring + .dontfork() + .setup_single_issuer() + // completion queue should be larger than the request queue, we allocate double + .setup_cqsize(FileBacked::RINGSIZE * 2) + // start a kernel thread to do the IO + .setup_sqpoll(IDLETIME_MS) + .build(FileBacked::RINGSIZE) + .map_err(|e| FileIoError { + inner: e, + filename: Some(path.clone()), + offset: 0, + context: Some("IO-uring setup".to_string()), + })? + }; + + Ok(Self { + fd, + cache: Mutex::new(LruCache::new(node_cache_size)), + free_list_cache: Mutex::new(LruCache::new(free_list_cache_size)), + cache_read_strategy, + filename: path, + #[cfg(feature = "io-uring")] + ring: Mutex::new(ManuallyDrop::new(ring)), + }) + } +} + +impl ReadableStorage for FileBacked { + fn stream_from(&self, addr: u64) -> Result { + counter!("firewood.read_node", "from" => "file").increment(1); + Ok(PredictiveReader::new(self, addr)) + } + + fn size(&self) -> Result { + Ok(self + .fd + .metadata() + .map_err(|e| self.file_io_error(e, 0, Some("size".to_string())))? + .len()) + } + + fn read_cached_node(&self, addr: LinearAddress, mode: &'static str) -> Option { + let mut guard = self.cache.lock(); + let cached = guard.get(&addr).cloned(); + counter!("firewood.cache.node", "mode" => mode, "type" => if cached.is_some() { "hit" } else { "miss" }) + .increment(1); + cached + } + + fn free_list_cache(&self, addr: LinearAddress) -> Option> { + let mut guard = self.free_list_cache.lock(); + let cached = guard.pop(&addr); + counter!("firewood.cache.freelist", "type" => if cached.is_some() { "hit" } else { "miss" }).increment(1); + cached + } + + fn cache_read_strategy(&self) -> &CacheReadStrategy { + &self.cache_read_strategy + } + + fn cache_node(&self, addr: LinearAddress, node: SharedNode) { + match self.cache_read_strategy { + CacheReadStrategy::WritesOnly => { + // we don't cache reads + } + CacheReadStrategy::All => { + let mut guard = self.cache.lock(); + guard.put(addr, node); + } + CacheReadStrategy::BranchReads => { + if !node.is_leaf() { + let mut guard = self.cache.lock(); + guard.put(addr, node); + } + } + } + } + + fn filename(&self) -> Option { + Some(self.filename.clone()) + } +} + +impl WritableStorage for FileBacked { + fn write(&self, offset: u64, object: &[u8]) -> Result { + #[cfg(unix)] + { + self.fd + .write_at(object, offset) + .map_err(|e| self.file_io_error(e, offset, Some("write".to_string()))) + } + #[cfg(windows)] + { + self.fd + .seek_write(object, offset) + .map_err(|e| self.file_io_error(e, offset, Some("write".to_string()))) + } + } + + fn write_cached_nodes( + &self, + nodes: impl IntoIterator, + ) -> Result<(), FileIoError> { + let mut guard = self.cache.lock(); + for maybe_persisted_node in nodes { + // Since we know the node is in Allocated state, we can get both address and shared node + let (addr, shared_node) = maybe_persisted_node + .allocated_info() + .expect("node should be allocated"); + + guard.put(addr, shared_node); + // The node can now be read from the general cache, so we can delete the local copy + maybe_persisted_node.persist_at(addr); + } + Ok(()) + } + + fn invalidate_cached_nodes<'a>(&self, nodes: impl Iterator) { + let mut guard = self.cache.lock(); + for addr in nodes.filter_map(MaybePersistedNode::as_linear_address) { + guard.pop(&addr); + } + } + + fn add_to_free_list_cache(&self, addr: LinearAddress, next: Option) { + let mut guard = self.free_list_cache.lock(); + guard.put(addr, next); + } +} + +const PREDICTIVE_READ_BUFFER_SIZE: usize = 1024; + +/// A reader that can predictively read from a file, avoiding reading past boundaries, but reading in 1k chunks +struct PredictiveReader<'a> { + fd: &'a File, + buffer: [u8; PREDICTIVE_READ_BUFFER_SIZE], + offset: u64, + len: usize, + pos: usize, + started: coarsetime::Instant, +} + +impl<'a> PredictiveReader<'a> { + fn new(fb: &'a FileBacked, start: u64) -> Self { + let fd = &fb.fd; + + Self { + fd, + buffer: [0u8; PREDICTIVE_READ_BUFFER_SIZE], + offset: start, + len: 0, + pos: 0, + started: coarsetime::Instant::now(), + } + } +} + +impl Drop for PredictiveReader<'_> { + fn drop(&mut self) { + let elapsed = self.started.elapsed(); + counter!("firewood.io.read_ms").increment(elapsed.as_millis()); + counter!("firewood.io.read").increment(1); + } +} + +impl Read for PredictiveReader<'_> { + fn read(&mut self, buf: &mut [u8]) -> Result { + if self.len == self.pos { + let bytes_left_in_page = PREDICTIVE_READ_BUFFER_SIZE + - (self.offset % PREDICTIVE_READ_BUFFER_SIZE as u64) as usize; + #[cfg(unix)] + let read = self + .fd + .read_at(&mut self.buffer[..bytes_left_in_page], self.offset)?; + #[cfg(windows)] + let read = self + .fd + .seek_read(&mut self.buffer[..bytes_left_in_page], self.offset)?; + self.offset += read as u64; + self.len = read; + self.pos = 0; + } + let max_to_return = std::cmp::min(buf.len(), self.len - self.pos); + buf[..max_to_return].copy_from_slice(&self.buffer[self.pos..self.pos + max_to_return]); + self.pos += max_to_return; + Ok(max_to_return) + } +} + +impl OffsetReader for PredictiveReader<'_> { + fn offset(&self) -> u64 { + self.offset - self.len as u64 + self.pos as u64 + } +} + +#[cfg(test)] +mod test { + #![expect(clippy::unwrap_used)] + + use super::*; + use nonzero_ext::nonzero; + use std::io::Write; + use tempfile::NamedTempFile; + + #[test] + fn basic_reader_test() { + let mut tf = NamedTempFile::new().unwrap(); + let path = tf.path().to_path_buf(); + let output = tf.as_file_mut(); + write!(output, "hello world").unwrap(); + + // whole thing at once, this is always less than 1K so it should + // read the whole thing in + let fb = FileBacked::new( + path, + nonzero!(10usize), + nonzero!(10usize), + false, + true, + CacheReadStrategy::WritesOnly, + ) + .unwrap(); + + let mut reader = fb.stream_from(0).unwrap(); + let mut buf: String = String::new(); + assert_eq!(reader.read_to_string(&mut buf).unwrap(), 11); + assert_eq!(buf, "hello world".to_string()); + assert_eq!(0, reader.read(&mut [0u8; 1]).unwrap()); + + // byte at a time + let mut reader = fb.stream_from(0).unwrap(); + for ch in b"hello world" { + let mut buf = [0u8; 1]; + let read = reader.read(&mut buf).unwrap(); + assert_eq!(read, 1); + assert_eq!(buf[0], *ch); + } + assert_eq!(0, reader.read(&mut [0u8; 1]).unwrap()); + + // with offset + let mut reader = fb.stream_from(6).unwrap(); + buf = String::new(); + assert_eq!(reader.read_to_string(&mut buf).unwrap(), 5); + assert_eq!(buf, "world".to_string()); + } + + #[test] + fn big_file() { + let mut tf = NamedTempFile::new().unwrap(); + let path = tf.path().to_path_buf(); + let output = tf.as_file_mut(); + for _ in 0..1000 { + write!(output, "hello world").unwrap(); + } + + let fb = FileBacked::new( + path, + nonzero!(10usize), + nonzero!(10usize), + false, + true, + CacheReadStrategy::WritesOnly, + ) + .unwrap(); + + let mut reader = fb.stream_from(0).unwrap(); + let mut buf: String = String::new(); + assert_eq!(reader.read_to_string(&mut buf).unwrap(), 11000); + assert_eq!(buf.len(), 11000); + } +} diff --git a/firewood/storage/src/linear/memory.rs b/firewood/storage/src/linear/memory.rs new file mode 100644 index 000000000000..feaf7499db94 --- /dev/null +++ b/firewood/storage/src/linear/memory.rs @@ -0,0 +1,95 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 3 occurrences after enabling the lint." +)] +#![expect( + clippy::indexing_slicing, + reason = "Found 1 occurrences after enabling the lint." +)] + +use super::{FileIoError, OffsetReader, ReadableStorage, WritableStorage}; +use metrics::counter; +use parking_lot::Mutex; +use std::io::Cursor; + +#[derive(Debug, Default)] +/// An in-memory impelementation of [`WritableStorage`] and [`ReadableStorage`] +pub struct MemStore { + bytes: Mutex>, +} + +impl MemStore { + /// Create a new, empty [`MemStore`] + #[must_use] + pub const fn new(bytes: Vec) -> Self { + Self { + bytes: Mutex::new(bytes), + } + } +} + +impl WritableStorage for MemStore { + fn write(&self, offset: u64, object: &[u8]) -> Result { + let offset = offset as usize; + let mut guard = self.bytes.lock(); + if offset + object.len() > guard.len() { + guard.resize(offset + object.len(), 0); + } + guard[offset..offset + object.len()].copy_from_slice(object); + Ok(object.len()) + } +} + +impl ReadableStorage for MemStore { + fn stream_from(&self, addr: u64) -> Result { + counter!("firewood.read_node", "from" => "memory").increment(1); + let bytes = self + .bytes + .lock() + .get(addr as usize..) + .unwrap_or_default() + .to_owned(); + + Ok(Cursor::new(bytes)) + } + + fn size(&self) -> Result { + Ok(self.bytes.lock().len() as u64) + } +} + +#[expect(clippy::unwrap_used)] +#[cfg(test)] +mod test { + use super::*; + use std::io::Read; + use test_case::test_case; + + #[test_case(&[(0,&[1, 2, 3])],(0,&[1, 2, 3]); "write to empty store")] + #[test_case(&[(0,&[1, 2, 3])],(1,&[2, 3]); "read from middle of store")] + #[test_case(&[(0,&[1, 2, 3])],(2,&[3]); "read from end of store")] + #[test_case(&[(0,&[1, 2, 3])],(3,&[]); "read past end of store")] + #[test_case(&[(0,&[1, 2, 3]),(3,&[4,5,6])],(0,&[1, 2, 3,4,5,6]); "write to end of store")] + #[test_case(&[(0,&[1, 2, 3]),(0,&[4])],(0,&[4,2,3]); "overwrite start of store")] + #[test_case(&[(0,&[1, 2, 3]),(1,&[4])],(0,&[1,4,3]); "overwrite middle of store")] + #[test_case(&[(0,&[1, 2, 3]),(2,&[4])],(0,&[1,2,4]); "overwrite end of store")] + #[test_case(&[(0,&[1, 2, 3]),(2,&[4,5])],(0,&[1,2,4,5]); "overwrite/extend end of store")] + fn test_in_mem_write_linear_store(writes: &[(u64, &[u8])], expected: (u64, &[u8])) { + let store = MemStore { + bytes: Mutex::new(vec![]), + }; + assert_eq!(store.size().unwrap(), 0); + + for write in writes { + store.write(write.0, write.1).unwrap(); + } + + let mut reader = store.stream_from(expected.0).unwrap(); + let mut read_bytes = vec![]; + reader.read_to_end(&mut read_bytes).unwrap(); + assert_eq!(read_bytes, expected.1); + } +} diff --git a/firewood/storage/src/linear/mod.rs b/firewood/storage/src/linear/mod.rs new file mode 100644 index 000000000000..f01ad468f920 --- /dev/null +++ b/firewood/storage/src/linear/mod.rs @@ -0,0 +1,224 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! A `LinearStore` provides a view of a set of bytes at +//! a given time. A `LinearStore` has three different types, +//! which refer to another base type, as follows: +//! ```mermaid +//! stateDiagram-v2 +//! R1(Committed) --> R2(Committed) +//! R2(Committed) --> R3(FileBacked) +//! P1(Proposed) --> R3(FileBacked) +//! P2(Proposed) --> P1(Proposed) +//! ``` +//! +//! Each type is described in more detail below. + +#![expect( + clippy::missing_errors_doc, + reason = "Found 4 occurrences after enabling the lint." +)] + +use std::fmt::Debug; +use std::io::{Cursor, Read}; +use std::ops::Deref; +use std::path::PathBuf; + +use crate::{CacheReadStrategy, LinearAddress, MaybePersistedNode, SharedNode}; +pub(super) mod filebacked; +pub mod memory; + +/// An error that occurs when reading or writing to a [`ReadableStorage`] or [`WritableStorage`] +/// +/// This error is used to wrap errors that occur when reading or writing to a file. +/// It contains the filename, offset, and context of the error. +#[derive(Debug)] +pub struct FileIoError { + inner: std::io::Error, + filename: Option, + offset: u64, + context: Option, +} + +impl From for FileIoError { + fn from(error: std::convert::Infallible) -> Self { + match error {} + } +} + +impl FileIoError { + /// Create a new [`FileIoError`] from a generic error + /// + /// Only use this constructor if you do not have any file or line information. + /// + /// # Arguments + /// + /// * `error` - The error to wrap + pub fn from_generic_no_file(error: T, context: &str) -> Self { + Self { + inner: std::io::Error::other(error.to_string()), + filename: None, + offset: 0, + context: Some(context.into()), + } + } + + /// Create a new [`FileIoError`] + /// + /// # Arguments + /// + /// * `inner` - The inner error + /// * `filename` - The filename of the file that caused the error + /// * `offset` - The offset of the file that caused the error + /// * `context` - The context of this error + #[must_use] + pub const fn new( + inner: std::io::Error, + filename: Option, + offset: u64, + context: Option, + ) -> Self { + Self { + inner, + filename, + offset, + context, + } + } + + #[cfg(test)] + pub(crate) fn context(&self) -> Option<&str> { + self.context.as_deref() + } +} + +impl std::error::Error for FileIoError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + Some(&self.inner) + } +} + +impl std::fmt::Display for FileIoError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{inner} at offset {offset} of file '{filename}' {context}", + inner = self.inner, + offset = self.offset, + filename = self + .filename + .as_ref() + .unwrap_or(&PathBuf::from("[unknown]")) + .display(), + context = self.context.as_ref().unwrap_or(&String::new()) + ) + } +} + +impl Deref for FileIoError { + type Target = std::io::Error; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} +/// Trait for readable storage. +pub trait ReadableStorage: Debug + Sync + Send { + /// Stream data from the specified address. + /// + /// # Arguments + /// + /// * `addr` - The address from which to stream the data. + /// + /// # Returns + /// + /// A `Result` containing a boxed `Read` trait object, or an `Error` if the operation fails. + fn stream_from(&self, addr: u64) -> Result; + + /// Return the size of the underlying storage, in bytes + fn size(&self) -> Result; + + /// Read a node from the cache (if any) + fn read_cached_node(&self, _addr: LinearAddress, _mode: &'static str) -> Option { + None + } + + /// Fetch the next pointer from the freelist cache + fn free_list_cache(&self, _addr: LinearAddress) -> Option> { + None + } + + /// Return the cache read strategy for this readable storage + fn cache_read_strategy(&self) -> &CacheReadStrategy { + &CacheReadStrategy::WritesOnly + } + + /// Cache a node for future reads + fn cache_node(&self, _addr: LinearAddress, _node: SharedNode) {} + + /// Return the filename of the underlying storage + fn filename(&self) -> Option { + None + } + + /// Convert an `io::Error` into a `FileIoError` + fn file_io_error( + &self, + error: std::io::Error, + offset: u64, + context: Option, + ) -> FileIoError { + FileIoError { + inner: error, + filename: self.filename(), + offset, + context, + } + } +} + +/// Trait for writable storage. +pub trait WritableStorage: ReadableStorage { + /// Writes the given object at the specified offset. + /// + /// # Arguments + /// + /// * `offset` - The offset at which to write the object. + /// * `object` - The object to write. + /// + /// # Returns + /// + /// The number of bytes written, or an error if the write operation fails. + fn write(&self, offset: u64, object: &[u8]) -> Result; + + /// Write all nodes to the cache (if any) and persist them + fn write_cached_nodes( + &self, + _nodes: impl IntoIterator, + ) -> Result<(), FileIoError> { + Ok(()) + } + + /// Invalidate all nodes that are part of a specific revision, as these will never be referenced again + fn invalidate_cached_nodes<'a>( + &self, + _addresses: impl Iterator, + ) { + } + + /// Add a new entry to the freelist cache + fn add_to_free_list_cache(&self, _addr: LinearAddress, _next: Option) {} +} + +pub trait OffsetReader: Read { + fn offset(&self) -> u64; +} + +impl OffsetReader for Cursor +where + Cursor: Read, +{ + fn offset(&self) -> u64 { + self.position() + } +} diff --git a/firewood/storage/src/logger.rs b/firewood/storage/src/logger.rs new file mode 100644 index 000000000000..890b56bf35da --- /dev/null +++ b/firewood/storage/src/logger.rs @@ -0,0 +1,54 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +// Supports making the logging operations a true runtime no-op +// Since we're a library, we can't really use the logging level +// static shortcut + +#[cfg(feature = "logger")] +pub use log::{debug, error, info, trace, warn}; + +/// Returns true if the trace log level is enabled +#[cfg(feature = "logger")] +#[must_use] +pub fn trace_enabled() -> bool { + log::log_enabled!(log::Level::Trace) +} + +#[cfg(not(feature = "logger"))] +pub use noop_logger::{debug, error, info, trace, trace_enabled, warn}; + +#[cfg(not(feature = "logger"))] +mod noop_logger { + #[macro_export] + /// A noop logger, when the logger feature is disabled + macro_rules! noop { + ($($arg:tt)+) => { + if false { + // This is a no-op. If we had an empty macro, the compiler and + // clippy would generate warnings about variables in the + // expressions passed into the macro going unused. + // + // This is a workaround to avoid that. The `false` branch will + // never be execute, the expressions passed in will never be + // evaluated, this string will never be constructed, and the + // compiler will completely eliminate this branch when any + // level of optimization is enabled. + let _ = format!($($arg)+); + } + }; + } + + pub use noop as debug; + pub use noop as error; + pub use noop as info; + pub use noop as trace; + pub use noop as warn; + + /// `trace_enabled` for a noop logger is always false + #[inline] + #[must_use] + pub const fn trace_enabled() -> bool { + false + } +} diff --git a/firewood/storage/src/macros.rs b/firewood/storage/src/macros.rs new file mode 100644 index 000000000000..1188fb70fa3d --- /dev/null +++ b/firewood/storage/src/macros.rs @@ -0,0 +1,89 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#[macro_export] +/// Macro to register and use a counter metric with description and labels. +/// This macro is a wrapper around the `metrics` crate's `counter!` and `describe_counter!` +/// macros. It ensures that the description is registered just once. +/// +/// Usage: +/// `firewood_counter!("metric_name", "description")` +/// `firewood_counter!("metric_name", "description", "label" => "value")` +/// +/// Call `.increment(val)` or `.absolute(val)` on the result as appropriate. +macro_rules! firewood_counter { + // With labels + ($name:expr, $desc:expr, $($labels:tt)+) => { + { + static ONCE: std::sync::Once = std::sync::Once::new(); + ONCE.call_once(|| { + metrics::describe_counter!($name, $desc); + }); + metrics::counter!($name, $($labels)+) + } + }; + // No labels + ($name:expr, $desc:expr) => { + { + static ONCE: std::sync::Once = std::sync::Once::new(); + ONCE.call_once(|| { + metrics::describe_counter!($name, $desc); + }); + metrics::counter!($name) + } + }; +} + +#[macro_export] +/// Macro to register and use a gauge metric with description and labels. +/// This macro is a wrapper around the `metrics` crate's `gauge!` and `describe_gauge!` +/// macros. It ensures that the description is registered just once. +/// +/// Usage: +/// `firewood_gauge!("metric_name", "description")` +/// `firewood_gauge!("metric_name", "description", "label" => "value")` +/// +/// Call `.increment(val)` or `.decrement(val)` on the result as appropriate. +macro_rules! firewood_gauge { + // With labels + ($name:expr, $desc:expr, $($labels:tt)+) => { + { + static ONCE: std::sync::Once = std::sync::Once::new(); + ONCE.call_once(|| { + metrics::describe_counter!($name, $desc); + }); + metrics::gauge!($name, $($labels)+) + } + }; + // No labels + ($name:expr, $desc:expr) => { + { + static ONCE: std::sync::Once = std::sync::Once::new(); + ONCE.call_once(|| { + metrics::describe_counter!($name, $desc); + }); + metrics::gauge!($name) + } + }; +} + +#[macro_export] +#[cfg(test)] +/// Macro to create an `AreaIndex` from a literal value at compile time. +/// This macro performs bounds checking at compile time and panics if the value is out of bounds. +/// +/// Usage: +/// `area_index!(0)` - creates an `AreaIndex` with value 0 +/// `area_index!(23)` - creates an `AreaIndex` with value 23 +/// +/// The macro will panic at compile time if the value is negative or >= `NUM_AREA_SIZES`. +macro_rules! area_index { + ($v:expr) => { + const { + match $crate::nodestore::primitives::AreaIndex::new($v as u8) { + Some(v) => v, + None => panic!("Constant area index out of bounds"), + } + } + }; +} diff --git a/firewood/storage/src/node/branch.rs b/firewood/storage/src/node/branch.rs new file mode 100644 index 000000000000..25f96d1f2d18 --- /dev/null +++ b/firewood/storage/src/node/branch.rs @@ -0,0 +1,507 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::match_same_arms, + reason = "Found 1 occurrences after enabling the lint." +)] + +use crate::node::ExtendableBytes; +use crate::node::children::Children; +use crate::{LeafNode, LinearAddress, MaybePersistedNode, Node, Path, PathComponent, SharedNode}; +use std::fmt::{Debug, Formatter}; +use std::io::Read; + +/// The type of a hash. For ethereum compatible hashes, this might be a RLP encoded +/// value if it's small enough to fit in less than 32 bytes. For merkledb compatible +/// hashes, it's always a `TrieHash`. +#[cfg(feature = "ethhash")] +pub type HashType = ethhash::HashOrRlp; + +#[cfg(not(feature = "ethhash"))] +/// The type of a hash. For non-ethereum compatible hashes, this is always a `TrieHash`. +pub type HashType = crate::TrieHash; + +/// A trait to convert a value into a [`HashType`]. +/// +/// This is used to allow different hash types to be conditionally used, e.g., when the +/// `ethhash` feature is enabled. When not enabled, this suppresses the clippy warnings +/// about useless `.into()` calls. +pub trait IntoHashType { + /// Converts the value into a `HashType`. + #[must_use] + fn into_hash_type(self) -> HashType; +} + +#[cfg(feature = "ethhash")] +impl IntoHashType for crate::TrieHash { + #[inline] + fn into_hash_type(self) -> HashType { + self.into() + } +} + +#[cfg(not(feature = "ethhash"))] +impl IntoHashType for crate::TrieHash { + #[inline] + fn into_hash_type(self) -> HashType { + self + } +} + +pub(crate) trait Serializable { + fn write_to(&self, vec: &mut W); + + fn from_reader(reader: R) -> Result + where + Self: Sized; +} + +/// An extension trait for [`Read`] for convenience methods when +/// reading serialized data. +pub(crate) trait ReadSerializable: Read { + /// Read a single byte from the reader. + fn read_byte(&mut self) -> Result { + let mut this = 0; + self.read_exact(std::slice::from_mut(&mut this))?; + Ok(this) + } + + /// Reads a fixed amount of bytes from the reader into a vector + fn read_fixed_len(&mut self, len: usize) -> Result, std::io::Error> { + let mut buf = Vec::with_capacity(len); + self.take(len as u64).read_to_end(&mut buf)?; + if buf.len() != len { + return Err(std::io::Error::new( + std::io::ErrorKind::UnexpectedEof, + "not enough bytes read", + )); + } + Ok(buf) + } + + /// Read a value of type `T` from the reader. + fn next_value(&mut self) -> Result { + T::from_reader(self) + } +} + +impl ReadSerializable for T {} + +#[derive(PartialEq, Eq, Clone, Debug)] +/// A child of a branch node. +pub enum Child { + /// There is a child at this index, but we haven't hashed it + /// or allocated space in storage for it yet. + Node(Node), + + /// We know the child's persisted address and hash. + AddressWithHash(LinearAddress, HashType), + + /// A `MaybePersisted` child + MaybePersisted(MaybePersistedNode, HashType), +} + +impl Child { + /// Return a mutable reference to the underlying Node if the child + /// is a [`Child::Node`] variant, otherwise None. + #[must_use] + pub const fn as_mut_node(&mut self) -> Option<&mut Node> { + match self { + Child::Node(node) => Some(node), + _ => None, + } + } + + /// Return the persisted address of the child if it is a [`Child::AddressWithHash`] or [`Child::MaybePersisted`] variant, otherwise None. + #[must_use] + pub fn persisted_address(&self) -> Option { + match self { + Child::AddressWithHash(addr, _) => Some(*addr), + Child::MaybePersisted(maybe_persisted, _) => maybe_persisted.as_linear_address(), + Child::Node(_) => None, + } + } + + /// Return the unpersisted node if the child is an unpersisted [`Child::MaybePersisted`] + /// variant, otherwise None. + #[must_use] + pub fn unpersisted(&self) -> Option<&MaybePersistedNode> { + if let Child::MaybePersisted(maybe_persisted, _) = self { + maybe_persisted.unpersisted() + } else { + None + } + } + + /// Return the hash of the child if it is a [`Child::AddressWithHash`] or [`Child::MaybePersisted`] variant, otherwise None. + #[must_use] + pub const fn hash(&self) -> Option<&HashType> { + match self { + Child::AddressWithHash(_, hash) => Some(hash), + Child::MaybePersisted(_, hash) => Some(hash), + Child::Node(_) => None, + } + } + + /// Return the persistence information (address and hash) of the child if it is persisted. + /// + /// This method returns `Some((address, hash))` for: + /// - [`Child::AddressWithHash`] variants (already persisted) + /// - [`Child::MaybePersisted`] variants that have been persisted + /// + /// Returns `None` for: + /// - [`Child::Node`] variants (unpersisted nodes) + /// - [`Child::MaybePersisted`] variants that are not yet persisted + #[must_use] + pub fn persist_info(&self) -> Option<(LinearAddress, &HashType)> { + match self { + Child::AddressWithHash(addr, hash) => Some((*addr, hash)), + Child::MaybePersisted(maybe_persisted, hash) => { + maybe_persisted.as_linear_address().map(|addr| (addr, hash)) + } + Child::Node(_) => None, + } + } + + /// Return a `MaybePersistedNode` from a child + /// + /// This is used in the dump utility, but otherwise should be avoided, + /// as it may create an unnecessary `MaybePersistedNode` + #[must_use] + pub fn as_maybe_persisted_node(&self) -> MaybePersistedNode { + match self { + Child::Node(node) => MaybePersistedNode::from(SharedNode::from(node.clone())), + Child::AddressWithHash(addr, _) => MaybePersistedNode::from(*addr), + Child::MaybePersisted(maybe_persisted, _) => maybe_persisted.clone(), + } + } +} + +#[cfg(feature = "ethhash")] +mod ethhash { + use sha2::Digest as _; + use sha3::Keccak256; + use smallvec::SmallVec; + use std::{ + fmt::{Display, Formatter}, + io::Read, + }; + + use crate::TrieHash; + use crate::node::ExtendableBytes; + + use super::Serializable; + + #[derive(Clone)] + pub enum HashOrRlp { + Hash(TrieHash), + // TODO: this slice is never larger than 32 bytes so smallvec is probably not our best container + // the length is stored in a `usize` but it could be in a `u8` and it will never overflow + Rlp(SmallVec<[u8; 32]>), + } + + /// Manual implementation of [`Debug`](std::fmt::Debug) so that the RLP bytes + /// are displayed as hex rather than raw bytes, which is more useful for + /// debugging purposes. + impl std::fmt::Debug for HashOrRlp { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + HashOrRlp::Hash(h) => write!(f, "Hash({h})"), + HashOrRlp::Rlp(r) => write!(f, "Rlp({})", hex::encode(r)), + } + } + } + + impl HashOrRlp { + /// Creates a new `TrieHash` from the default value, which is the all zeros. + /// + /// ``` + /// assert_eq!( + /// firewood_storage::HashType::empty(), + /// firewood_storage::HashType::from([0; 32]), + /// ) + /// ``` + #[must_use] + pub fn empty() -> Self { + TrieHash::empty().into() + } + + pub fn as_slice(&self) -> &[u8] { + self + } + + pub fn into_triehash(self) -> TrieHash { + self.into() + } + + // used in PartialEq and Hash impls and is to trick clippy into not caring + // about creating an owned instance for comparison + fn as_triehash(&self) -> TrieHash { + self.into() + } + } + + impl PartialEq for HashOrRlp { + fn eq(&self, other: &TrieHash) -> bool { + match self { + HashOrRlp::Hash(h) => h == other, + HashOrRlp::Rlp(r) => Keccak256::digest(r.as_ref()).as_slice() == other.as_ref(), + } + } + } + + impl PartialEq for TrieHash { + fn eq(&self, other: &HashOrRlp) -> bool { + match other { + HashOrRlp::Hash(h) => h == self, + HashOrRlp::Rlp(r) => Keccak256::digest(r.as_ref()).as_slice() == self.as_ref(), + } + } + } + + impl PartialEq for HashOrRlp { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + // if both are hash or rlp, we can skip hashing + (HashOrRlp::Hash(h1), HashOrRlp::Hash(h2)) => h1 == h2, + (HashOrRlp::Rlp(r1), HashOrRlp::Rlp(r2)) => r1 == r2, + // otherwise, one is a hash and the other isn't, so convert both + // to hash and compare + _ => self.as_triehash() == other.as_triehash(), + } + } + } + + impl Eq for HashOrRlp {} + + impl std::hash::Hash for HashOrRlp { + fn hash(&self, state: &mut H) { + // contract on `Hash` and `PartialEq` requires that if `a == b` then `hash(a) == hash(b)` + // and since `PartialEq` may require hashing, we must always convert to `TrieHash` here + // and use it's hash implementation + self.as_triehash().hash(state); + } + } + + impl Serializable for HashOrRlp { + fn write_to(&self, vec: &mut W) { + match self { + HashOrRlp::Hash(h) => { + vec.push(0); + vec.extend_from_slice(h.as_ref()); + } + HashOrRlp::Rlp(r) => { + debug_assert!(!r.is_empty()); + debug_assert!(r.len() < 32); + vec.push(r.len() as u8); + vec.extend_from_slice(r.as_ref()); + } + } + } + + fn from_reader(mut reader: R) -> Result { + let mut bytes = [0; 32]; + reader.read_exact(&mut bytes[0..1])?; + match bytes[0] { + 0 => { + reader.read_exact(&mut bytes)?; + Ok(HashOrRlp::Hash(TrieHash::from(bytes))) + } + len if len < 32 => { + #[expect(clippy::indexing_slicing)] + { + reader.read_exact(&mut bytes[0..len as usize])?; + } + Ok(HashOrRlp::Rlp(SmallVec::from_buf_and_len( + bytes, + len as usize, + ))) + } + _ => Err(std::io::Error::new( + std::io::ErrorKind::InvalidData, + "invalid RLP length", + )), + } + } + } + + impl From for TrieHash { + fn from(val: HashOrRlp) -> Self { + match val { + HashOrRlp::Hash(h) => h, + HashOrRlp::Rlp(r) => Keccak256::digest(&r).into(), + } + } + } + + impl From<&HashOrRlp> for TrieHash { + fn from(val: &HashOrRlp) -> Self { + match val { + HashOrRlp::Hash(h) => h.clone(), + HashOrRlp::Rlp(r) => Keccak256::digest(r).into(), + } + } + } + + impl From for HashOrRlp { + fn from(val: TrieHash) -> Self { + HashOrRlp::Hash(val) + } + } + + impl From<[u8; 32]> for HashOrRlp { + fn from(value: [u8; 32]) -> Self { + HashOrRlp::Hash(TrieHash::into(value.into())) + } + } + + impl TryFrom<&[u8]> for HashOrRlp { + type Error = crate::InvalidTrieHashLength; + + fn try_from(value: &[u8]) -> Result { + value.try_into().map(HashOrRlp::Hash) + } + } + + impl AsRef<[u8]> for HashOrRlp { + fn as_ref(&self) -> &[u8] { + match self { + HashOrRlp::Hash(h) => h.as_ref(), + HashOrRlp::Rlp(r) => r.as_ref(), + } + } + } + + impl std::ops::Deref for HashOrRlp { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + match self { + HashOrRlp::Hash(h) => h.as_slice(), + HashOrRlp::Rlp(r) => r, + } + } + } + + impl Display for HashOrRlp { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + HashOrRlp::Hash(h) => write!(f, "{h}"), + HashOrRlp::Rlp(r) => { + let width = f.precision().unwrap_or(32); + write!(f, "{:.*}", width, hex::encode(r)) + } + } + } + } +} + +#[derive(PartialEq, Eq, Clone)] +/// A branch node +pub struct BranchNode { + /// The partial path for this branch + pub partial_path: Path, + + /// The value of the data for this branch, if any + pub value: Option>, + + /// The children of this branch. + /// Element i is the child at index i, or None if there is no child at that index. + /// Each element is (`child_hash`, `child_address`). + /// `child_address` is None if we don't know the child's hash. + pub children: Children>, +} + +impl Debug for BranchNode { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "[BranchNode")?; + write!(f, r#" path="{:?}""#, self.partial_path)?; + + for (i, c) in &self.children { + match c { + None => {} + Some(Child::Node(_)) => {} //TODO + Some(Child::AddressWithHash(addr, hash)) => { + write!(f, "({i:?}: address={addr:?} hash={hash})")?; + } + Some(Child::MaybePersisted(maybe_persisted, hash)) => { + // For MaybePersisted, show the address if persisted, otherwise show as unpersisted + match maybe_persisted.as_linear_address() { + Some(addr) => write!(f, "({i:?}: address={addr:?} hash={hash})")?, + None => write!(f, "({i:?}: unpersisted hash={hash})")?, + } + } + } + } + + let value: &dyn std::fmt::Display = match self.value.as_deref() { + Some(v) => &super::DisplayTruncatedHex(v), + None => &"nil", + }; + write!(f, "v={value}]") + } +} + +impl BranchNode { + /// The maximum number of children a branch node can have. + pub const MAX_CHILDREN: usize = PathComponent::LEN; + + /// Returns a set of persistence information (address and hash) for each child that + /// is persisted. + /// + /// This will skip any child that is a [`Child::Node`] variant (not yet hashed) + /// or a [`Child::MaybePersisted`] variant that does not have an address (not + /// yet persisted). + #[must_use] + pub fn persist_info(&self) -> Children> { + self.children + .each_ref() + .map(|_, c| c.as_ref().and_then(Child::persist_info)) + } + + /// Returns a set of hashes for each child that has a hash set. + /// + /// The index of the hash in the returned array corresponds to the index of the child + /// in the branch node. + /// + /// Note: This function will skip any child is a [`Child::Node`] variant + /// as it is still mutable and has not been hashed yet. + /// + /// This is an unintentional side effect of the current implementation. Future + /// changes will have this check implemented structurally to prevent such cases. + #[must_use] + pub fn children_hashes(&self) -> Children> { + self.children + .each_ref() + .map(|_, c| c.as_ref().and_then(Child::hash).cloned()) + } + + /// Returns a set of addresses for each child that has an address set. + /// + /// The index of the address in the returned array corresponds to the index of the child + /// in the branch node. + /// + /// Note: This function will skip: + /// - Any child is a [`Child::Node`] variant as it does not have an address. + /// - Any child is a [`Child::MaybePersisted`] variant that is not yet + /// persisted, as we do not yet know its address. + /// + /// This is an unintentional side effect of the current implementation. Future + /// changes will have this check implemented structurally to prevent such cases. + #[must_use] + pub fn children_addresses(&self) -> Children> { + self.children + .each_ref() + .map(|_, c| c.as_ref().and_then(Child::persisted_address)) + } +} + +impl From<&LeafNode> for BranchNode { + fn from(leaf: &LeafNode) -> Self { + BranchNode { + partial_path: leaf.partial_path.clone(), + value: Some(Box::from(&leaf.value[..])), + children: Children::new(), + } + } +} diff --git a/firewood/storage/src/node/children.rs b/firewood/storage/src/node/children.rs new file mode 100644 index 000000000000..5e3f27dc00db --- /dev/null +++ b/firewood/storage/src/node/children.rs @@ -0,0 +1,236 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::PathComponent; + +const MAX_CHILDREN: usize = PathComponent::LEN; + +/// Type alias for an iterator over the slots of a branch node's children +/// with its corresponding [`PathComponent`]. +pub type ChildrenSlots = std::iter::Zip< + std::array::IntoIter, + std::array::IntoIter, +>; + +/// The type of iterator returned by [`Children::iter_present`]. +pub type IterPresentRef<'a, T> = std::iter::FilterMap< + ChildrenSlots<&'a Option>, + fn((PathComponent, &'a Option)) -> Option<(PathComponent, &'a T)>, +>; + +/// The type of iterator returned by [`Children::iter_present`]. +pub type IterPresentMut<'a, T> = std::iter::FilterMap< + ChildrenSlots<&'a mut Option>, + fn((PathComponent, &'a mut Option)) -> Option<(PathComponent, &'a mut T)>, +>; + +/// Type alias for a collection of children in a branch node. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Children([T; MAX_CHILDREN]); + +impl std::fmt::Debug for Children { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_map() + .entries(self.iter().map(|(pc, child)| (pc.as_u8(), child))) + .finish() + } +} + +impl Children { + /// Creates a new [`Children`] by calling `f` for each possible + /// [`PathComponent`]. + #[must_use] + pub fn from_fn(f: impl FnMut(PathComponent) -> T) -> Self { + Self(PathComponent::ALL.map(f)) + } + + /// Borrows each element and returns a [`Children`] wrapping the references. + #[must_use] + pub const fn each_ref(&self) -> Children<&T> { + Children(self.0.each_ref()) + } + + /// Borrows each element mutably and returns a [`Children`] wrapping the + /// mutable references. + #[must_use] + pub const fn each_mut(&mut self) -> Children<&mut T> { + Children(self.0.each_mut()) + } + + /// Returns a reference to the element at `index`. + /// + /// This is infallible because `index` is guaranteed to be in-bounds. + #[must_use] + pub const fn get(&self, index: PathComponent) -> &T { + #![expect(clippy::indexing_slicing)] + &self.0[index.as_usize()] + } + + /// Returns a mutable reference to the element at `index`. + /// + /// This is infallible because `index` is guaranteed to be in-bounds. + #[must_use] + pub const fn get_mut(&mut self, index: PathComponent) -> &mut T { + #![expect(clippy::indexing_slicing)] + &mut self.0[index.as_usize()] + } + + /// Replaces the element at `index` with `value`, returning the previous + /// value. + /// + /// This is infallible because `index` is guaranteed to be in-bounds. + pub const fn replace(&mut self, index: PathComponent, value: T) -> T { + #![expect(clippy::indexing_slicing)] + std::mem::replace(&mut self.0[index.as_usize()], value) + } + + /// Maps each element to another value using `f`, returning a new + /// [`Children`] containing the results. + #[must_use] + pub fn map(self, mut f: impl FnMut(PathComponent, T) -> O) -> Children { + let mut pc = const { PathComponent::ALL[0] }; + Children(self.0.map(|child| { + let out = f(pc, child); + pc = pc.wrapping_next(); + out + })) + } + + /// Returns an iterator over each element with its corresponding + /// [`PathComponent`]. + pub fn iter(&self) -> ChildrenSlots<&T> { + self.into_iter() + } + + /// Returns a mutable iterator over each element with its corresponding + /// [`PathComponent`]. + pub fn iter_mut(&mut self) -> ChildrenSlots<&mut T> { + self.into_iter() + } + + /// Merges this collection of children with another collection of children + /// using the given function. + /// + /// If the function returns an error, the merge is aborted and the error is + /// returned. Because this method takes `self` and `other` by value, they + /// will be dropped if the merge fails. + pub fn merge( + self, + other: Children, + mut merge: impl FnMut(PathComponent, T, U) -> Result, E>, + ) -> Result>, E> { + let iter = self.0.into_iter().zip(other.0); + let mut output = [const { None }; MAX_CHILDREN]; + for (slot, (pc, (a, b))) in output + .iter_mut() + .zip(PathComponent::ALL.into_iter().zip(iter)) + { + *slot = merge(pc, a, b)?; + } + Ok(Children(output)) + } +} + +impl Children> { + /// Creates a new [`Children`] with all elements set to `None`. + #[must_use] + pub const fn new() -> Self { + Self([const { None }; MAX_CHILDREN]) + } + + /// Returns the number of [`Some`] elements in this collection. + #[must_use] + pub fn count(&self) -> usize { + self.0.iter().filter(|c| c.is_some()).count() + } + + /// Sets the element at `index` to `None`, returning the previous value. + #[must_use] + pub const fn take(&mut self, index: PathComponent) -> Option { + self.replace(index, None) + } + + /// Returns an iterator over each [`Some`] element with its corresponding + /// [`PathComponent`]. + pub fn iter_present(&self) -> IterPresentRef<'_, T> { + self.into_iter() + .filter_map(|(pc, opt)| opt.as_ref().map(|v| (pc, v))) + } +} + +impl Default for Children> { + fn default() -> Self { + Self::new() + } +} + +impl<'a, T> Children<&'a Option> { + /// Returns the number of [`Some`] elements in this collection. + #[must_use] + pub fn count(&self) -> usize { + self.0.iter().filter(|c| c.is_some()).count() + } + + /// Returns an iterator over each [`Some`] element with its corresponding + /// [`PathComponent`]. + pub fn iter_present(self) -> IterPresentRef<'a, T> { + self.into_iter() + .filter_map(|(pc, opt)| opt.as_ref().map(|v| (pc, v))) + } +} + +impl<'a, T> Children<&'a mut Option> { + /// Returns the number of [`Some`] elements in this collection. + #[must_use] + pub fn count(&self) -> usize { + self.0.iter().filter(|c| c.is_some()).count() + } + + /// Returns an iterator over each [`Some`] element with its corresponding + /// [`PathComponent`]. + pub fn iter_present(self) -> IterPresentMut<'a, T> { + self.into_iter() + .filter_map(|(pc, opt)| opt.as_mut().map(|v| (pc, v))) + } +} + +impl std::ops::Index for Children { + type Output = T; + + fn index(&self, index: PathComponent) -> &Self::Output { + self.get(index) + } +} + +impl std::ops::IndexMut for Children { + fn index_mut(&mut self, index: PathComponent) -> &mut Self::Output { + self.get_mut(index) + } +} + +impl IntoIterator for Children { + type Item = (PathComponent, T); + type IntoIter = ChildrenSlots; + + fn into_iter(self) -> Self::IntoIter { + PathComponent::ALL.into_iter().zip(self.0) + } +} + +impl<'a, T: 'a> IntoIterator for &'a Children { + type Item = (PathComponent, &'a T); + type IntoIter = ChildrenSlots<&'a T>; + + fn into_iter(self) -> Self::IntoIter { + self.each_ref().into_iter() + } +} + +impl<'a, T: 'a> IntoIterator for &'a mut Children { + type Item = (PathComponent, &'a mut T); + type IntoIter = ChildrenSlots<&'a mut T>; + + fn into_iter(self) -> Self::IntoIter { + self.each_mut().into_iter() + } +} diff --git a/firewood/storage/src/node/leaf.rs b/firewood/storage/src/node/leaf.rs new file mode 100644 index 000000000000..83170558d2ca --- /dev/null +++ b/firewood/storage/src/node/leaf.rs @@ -0,0 +1,27 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::fmt::{Debug, Error as FmtError, Formatter}; + +use crate::Path; + +/// A leaf node +#[derive(PartialEq, Eq, Clone)] +pub struct LeafNode { + /// The path of this leaf, but only the remaining nibbles + pub partial_path: Path, + + /// The value associated with this leaf + pub value: Box<[u8]>, +} + +impl Debug for LeafNode { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + write!( + f, + "[Leaf {:?} {}]", + self.partial_path, + super::DisplayTruncatedHex(&self.value) + ) + } +} diff --git a/firewood/storage/src/node/mod.rs b/firewood/storage/src/node/mod.rs new file mode 100644 index 000000000000..04d2b99a6629 --- /dev/null +++ b/firewood/storage/src/node/mod.rs @@ -0,0 +1,602 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::items_after_statements, + reason = "Found 2 occurrences after enabling the lint." +)] +#![expect( + clippy::missing_errors_doc, + reason = "Found 1 occurrences after enabling the lint." +)] +#![expect( + clippy::missing_panics_doc, + reason = "Found 1 occurrences after enabling the lint." +)] + +use crate::node::branch::ReadSerializable; +use crate::nodestore::AreaIndex; +use crate::{HashType, LinearAddress, Path, PathBuf, PathComponent, SharedNode}; +use bitfield::bitfield; +use branch::Serializable as _; +pub use branch::{BranchNode, Child}; +pub use children::{Children, ChildrenSlots}; +use enum_as_inner::EnumAsInner; +use integer_encoding::{VarInt, VarIntReader as _}; +pub use leaf::LeafNode; +use std::fmt::Debug; +use std::io::{Error, Read, Write}; + +pub mod branch; +pub mod children; +mod leaf; +pub mod path; +pub mod persist; +/// A node, either a Branch or Leaf + +// TODO: explain why Branch is boxed but Leaf is not +#[derive(PartialEq, Eq, Clone, Debug, EnumAsInner)] +#[repr(C)] +pub enum Node { + /// This node is a [`BranchNode`] + Branch(Box), + /// This node is a [`LeafNode`] + Leaf(LeafNode), +} + +impl Default for Node { + fn default() -> Self { + Node::Leaf(LeafNode { + partial_path: Path::new(), + value: Box::default(), + }) + } +} + +impl From for Node { + fn from(branch: BranchNode) -> Self { + Node::Branch(Box::new(branch)) + } +} + +impl From for Node { + fn from(leaf: LeafNode) -> Self { + Node::Leaf(leaf) + } +} + +#[cfg(not(feature = "branch_factor_256"))] +bitfield! { + struct BranchFirstByte(u8); + impl Debug; + impl new; + u8; + has_value, set_has_value: 1, 1; + number_children, set_number_children: 5, 2; + partial_path_length, set_partial_path_length: 7, 6; +} +#[cfg(not(feature = "branch_factor_256"))] +const BRANCH_PARTIAL_PATH_LEN_OVERFLOW: u8 = (1 << 2) - 1; // 3 nibbles + +#[cfg(feature = "branch_factor_256")] +bitfield! { + struct BranchFirstByte(u8); + impl Debug; + impl new; + u8; + has_value, set_has_value: 1, 1; + partial_path_length, set_partial_path_length: 7, 2; +} +#[cfg(feature = "branch_factor_256")] +const BRANCH_PARTIAL_PATH_LEN_OVERFLOW: u8 = (1 << 6) - 1; // 63 nibbles + +bitfield! { + struct LeafFirstByte(u8); + impl Debug; + impl new; + u8; + is_leaf, set_is_leaf: 0, 0; + partial_path_length, set_partial_path_length: 7, 1; +} + +const LEAF_PARTIAL_PATH_LEN_OVERFLOW: u8 = (1 << 7) - 2; // 126 nibbles (-1 for indicating Free Area (0xff)) + +impl Default for LeafFirstByte { + fn default() -> Self { + LeafFirstByte(1) + } +} + +// TODO: Unstable extend_reserve re-implemented here +// Extend::extend_reserve is unstable so we implement it here +// see https://github.com/rust-lang/rust/issues/72631 +pub trait ExtendableBytes: Write { + fn extend>(&mut self, other: T); + fn reserve(&mut self, reserve: usize) { + let _ = reserve; + } + fn push(&mut self, value: u8); + + fn extend_from_slice(&mut self, other: &[u8]) { + self.extend(other.iter().copied()); + } + + /// Write a variable-length integer to the buffer without allocating an + /// intermediate buffer on the heap. + /// + /// This uses a stack buffer for holding the encoded integer and copies it + /// into the buffer. + #[expect(clippy::indexing_slicing)] + fn extend_var_int(&mut self, int: VI) { + let mut buf = [0u8; 10]; + let len = VarInt::encode_var(int, &mut buf); + self.extend_from_slice(&buf[..len]); + } +} + +impl ExtendableBytes for Vec { + fn extend>(&mut self, other: T) { + std::iter::Extend::extend(self, other); + } + fn reserve(&mut self, reserve: usize) { + self.reserve(reserve); + } + fn push(&mut self, value: u8) { + Vec::push(self, value); + } + fn extend_from_slice(&mut self, other: &[u8]) { + Vec::extend_from_slice(self, other); + } +} + +impl ExtendableBytes for bumpalo::collections::Vec<'_, u8> { + fn extend>(&mut self, other: T) { + std::iter::Extend::extend(self, other); + } + fn reserve(&mut self, reserve: usize) { + bumpalo::collections::Vec::reserve(self, reserve); + } + fn push(&mut self, value: u8) { + bumpalo::collections::Vec::push(self, value); + } + fn extend_from_slice(&mut self, other: &[u8]) { + bumpalo::collections::Vec::extend_from_slice(self, other); + } +} + +impl Node { + /// Returns the partial path of the node. + #[must_use] + pub fn partial_path(&self) -> &Path { + match self { + Node::Branch(b) => &b.partial_path, + Node::Leaf(l) => &l.partial_path, + } + } + + /// Updates the partial path of the node to `partial_path`. + pub fn update_partial_path(&mut self, partial_path: Path) { + match self { + Node::Branch(b) => b.partial_path = partial_path, + Node::Leaf(l) => l.partial_path = partial_path, + } + } + + /// Updates the value of the node to `value`. + pub fn update_value(&mut self, value: Box<[u8]>) { + match self { + Node::Branch(b) => b.value = Some(value), + Node::Leaf(l) => l.value = value, + } + } + + /// Returns Some(value) inside the node, or None if the node is a branch + /// with no value. + #[must_use] + pub fn value(&self) -> Option<&[u8]> { + match self { + Node::Branch(b) => b.value.as_deref(), + Node::Leaf(l) => Some(&l.value), + } + } + + /// Given a [Node], returns a set of bytes to write to storage + /// The format is as follows: + /// + /// For a branch: + /// - Byte 0: + /// - Bit 0: always 0 + /// - Bit 1: indicates if the branch has a value + /// - Bits 2-5: the number of children (unless `branch_factor_256`, which stores it in the next byte) + /// - Bits 6-7: 0: empty `partial_path`, 1: 1 nibble, 2: 2 nibbles, 3: length is encoded in the next byte + /// (for `branch_factor_256`, bits 2-7 are used for `partial_path` length, up to 63 nibbles) + /// + /// The remaining bytes are in the following order: + /// - The partial path, possibly preceeded by the length if it is longer than 3 nibbles (varint encoded) + /// - The number of children, if the branch factor is 256 + /// - The children. If the number of children == [`BranchNode::MAX_CHILDREN`], then the children are just + /// addresses with hashes. Otherwise, they are offset, address, hash tuples. + /// + /// For a leaf: + /// - Byte 0: + /// - Bit 0: always 1 + /// - Bits 1-7: the length of the partial path. If the partial path is longer than 126 nibbles, this is set to + /// 126 and the length is encoded in the next byte. + /// + /// The remaining bytes are in the following order: + /// - The partial path, possibly preceeded by the length if it is longer than 126 nibbles (varint encoded) + /// - The value, always preceeded by the length, varint encoded + /// + /// Note that this means the first byte cannot be 255, which would be a leaf with 127 nibbles. We save this extra + /// value to mark this as a freed area. + /// + /// Note that there is a "prefix" byte which is the size of the area when serializing this object. Since + /// we always have one of those, we include it as a parameter for serialization. + /// + /// TODO: We could pack two bytes of the partial path into one and handle the odd byte length + pub fn as_bytes(&self, prefix: AreaIndex, encoded: &mut T) { + match self { + Node::Branch(b) => { + let child_iter = b.children.iter_present(); + let childcount = child_iter.clone().count(); + + // encode the first byte + let pp_len = match b.partial_path.len() { + // less than 3 or 62 nibbles + len if len < BRANCH_PARTIAL_PATH_LEN_OVERFLOW as usize => len as u8, + _ => BRANCH_PARTIAL_PATH_LEN_OVERFLOW, + }; + + #[cfg(not(feature = "branch_factor_256"))] + let first_byte: BranchFirstByte = BranchFirstByte::new( + u8::from(b.value.is_some()), + (childcount % BranchNode::MAX_CHILDREN) as u8, + pp_len, + ); + #[cfg(feature = "branch_factor_256")] + let first_byte: BranchFirstByte = + BranchFirstByte::new(u8::from(b.value.is_some()), pp_len); + + // create an output stack item, which can overflow to memory for very large branch nodes + const OPTIMIZE_BRANCHES_FOR_SIZE: usize = 1024; + encoded.reserve(OPTIMIZE_BRANCHES_FOR_SIZE); + encoded.push(prefix.get()); + encoded.push(first_byte.0); + #[cfg(feature = "branch_factor_256")] + encoded.push((childcount % BranchNode::MAX_CHILDREN) as u8); + + // encode the partial path, including the length if it didn't fit above + if pp_len == BRANCH_PARTIAL_PATH_LEN_OVERFLOW { + encoded.extend_var_int(b.partial_path.len()); + } + encoded.extend_from_slice(&b.partial_path); + + // encode the value. For tries that have the same length keys, this is always empty + if let Some(v) = &b.value { + encoded.extend_var_int(v.len()); + encoded.extend_from_slice(v); + } + + // encode the children + if childcount == BranchNode::MAX_CHILDREN { + for (_, child) in child_iter { + let (address, hash) = child + .persist_info() + .expect("child must be hashed when serializing"); + encoded.extend_from_slice(&address.get().to_ne_bytes()); + hash.write_to(encoded); + } + } else { + for (position, child) in child_iter { + encoded.extend_var_int(position.as_u8()); + let (address, hash) = child + .persist_info() + .expect("child must be hashed when serializing"); + encoded.extend_from_slice(&address.get().to_ne_bytes()); + hash.write_to(encoded); + } + } + } + Node::Leaf(l) => { + let pp_len = match l.partial_path.len() { + // less than 126 nibbles + len if len < LEAF_PARTIAL_PATH_LEN_OVERFLOW as usize => len as u8, + _ => LEAF_PARTIAL_PATH_LEN_OVERFLOW, + }; + let first_byte: LeafFirstByte = LeafFirstByte::new(1, pp_len); + + const OPTIMIZE_LEAVES_FOR_SIZE: usize = 128; + encoded.reserve(OPTIMIZE_LEAVES_FOR_SIZE); + encoded.push(prefix.get()); + encoded.push(first_byte.0); + + // encode the partial path, including the length if it didn't fit above + if pp_len == LEAF_PARTIAL_PATH_LEN_OVERFLOW { + encoded.extend_var_int(l.partial_path.len()); + } + encoded.extend_from_slice(&l.partial_path); + + // encode the value + encoded.extend_var_int(l.value.len()); + encoded.extend_from_slice(&l.value); + } + } + } + + /// Given a reader, return a [Node] from those bytes + pub fn from_reader(mut serialized: &mut impl Read) -> Result { + match serialized.read_byte()? { + 255 => { + // this is a freed area + Err(Error::other("attempt to read freed area")) + } + first_byte if first_byte & 1 == 1 => { + let partial_path = read_path_with_overflow_length( + &mut serialized, + first_byte >> 1, + LEAF_PARTIAL_PATH_LEN_OVERFLOW, + )?; + let value_len = serialized.read_varint()?; + let value = serialized.read_fixed_len(value_len)?; + Ok(Node::Leaf(LeafNode { + partial_path, + value: value.into(), + })) + } + branch_first_byte => { + let branch_first_byte = BranchFirstByte(branch_first_byte); + + let has_value = branch_first_byte.has_value() == 1; + #[cfg(not(feature = "branch_factor_256"))] + let childcount = branch_first_byte.number_children() as usize; + #[cfg(feature = "branch_factor_256")] + let childcount = serialized.read_byte()? as usize; + + let partial_path = read_path_with_overflow_length( + &mut serialized, + branch_first_byte.partial_path_length(), + BRANCH_PARTIAL_PATH_LEN_OVERFLOW, + )?; + + let value = if has_value { + let value_len = serialized.read_varint()?; + let value = serialized.read_fixed_len(value_len)?; + Some(value.into()) + } else { + None + }; + + let mut children = Children::new(); + if childcount == 0 { + // branch is full of all children + for (_, child) in &mut children { + // TODO: we can read them all at once + let mut address_buf = [0u8; 8]; + serialized.read_exact(&mut address_buf)?; + let address = u64::from_ne_bytes(address_buf); + + let hash = HashType::from_reader(&mut serialized)?; + + *child = Some(Child::AddressWithHash( + LinearAddress::new(address) + .ok_or(Error::other("zero address in child"))?, + hash, + )); + } + } else { + for _ in 0..childcount { + let mut position_buf = [0u8; 1]; + serialized.read_exact(&mut position_buf)?; + let position = + PathComponent::try_new(position_buf[0]).ok_or_else(|| { + Error::other(format!( + "invalid child position {:02x}", + position_buf[0] + )) + })?; + + let mut address_buf = [0u8; 8]; + serialized.read_exact(&mut address_buf)?; + let address = u64::from_ne_bytes(address_buf); + + let hash = HashType::from_reader(&mut serialized)?; + + children[position] = Some(Child::AddressWithHash( + LinearAddress::new(address) + .ok_or(Error::other("zero address in child"))?, + hash, + )); + } + } + + Ok(Node::Branch(Box::new(BranchNode { + partial_path, + value, + children, + }))) + } + } + } + + /// Force the node (which should be a root of a trie) into a branch with no partial path + /// in preparation for a parallel insert. There are two cases to handle depending on whether + /// the node has a partial path. + /// + /// 1. If the node has a partial path, then create a new node with an empty partial path + /// and a None for a value. Push down the previous node as a child and return the + /// branch. + /// 2. If the existing node does not have a partial path, then there is nothing we need + /// to do if it is a branch. If it is a leaf, then convert it into a branch. + /// + /// # Errors + /// + /// Returns an `Error` if it cannot create a `PathComponent` from a u8 index. + pub fn force_branch_for_insert(mut self) -> Result, Error> { + // If the `partial_path` is non-empty, then create a branch that will be the new + // root with the previous root as the child at the index returned from split_first. + if let Some((child_index, child_path)) = self + .partial_path() + .split_first() + .map(|(index, path)| (*index, path.into())) + { + let mut branch = BranchNode { + partial_path: Path::new(), + value: None, + children: Children::default(), + }; + self.update_partial_path(child_path); + let child_path_component = PathComponent::try_new(child_index) + .ok_or_else(|| Error::other("invalid child index"))?; + *branch.children.get_mut(child_path_component) = Some(Child::Node(self)); + Ok(branch.into()) + } else { + Ok(match self { + Node::Leaf(leaf) => { + // Root is a leaf with an empty partial path. Replace it with a branch. + BranchNode { + partial_path: Path::new(), + value: Some(leaf.value), + children: Children::default(), + } + .into() + } + Node::Branch(branch) => branch, + }) + } + } +} + +/// A path iterator item, which has the key nibbles up to this point, +/// a node, the address of the node, and the nibble that points to the +/// next child down the list +#[derive(Debug)] +pub struct PathIterItem { + /// The key of the node at `address` as nibbles. + pub key_nibbles: PathBuf, + /// A reference to the node + pub node: SharedNode, + /// The next item returned by the iterator is a child of `node`. + /// Specifically, it's the child at index `next_nibble` in `node`'s + /// children array. + /// None if `node` is the last node in the path. + pub next_nibble: Option, +} + +fn read_path_with_overflow_length( + reader: &mut impl Read, + value: u8, + overflow: u8, +) -> std::io::Result { + if value < overflow { + // the value is less than the overflow, so we can read it directly + read_path_with_provided_length(reader, value as usize) + } else { + read_path_with_prefix_length(reader) + } +} + +#[cold] +#[inline(never)] +fn read_path_with_prefix_length(reader: &mut impl Read) -> std::io::Result { + let len = reader.read_varint()?; + read_path_with_provided_length(reader, len) +} + +#[inline] +fn read_path_with_provided_length(reader: &mut impl Read, len: usize) -> std::io::Result { + reader.read_fixed_len(len).map(Path::from) +} + +struct DisplayTruncatedHex<'a>(&'a [u8]); + +impl std::fmt::Display for DisplayTruncatedHex<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(truncated) = self.0.get(0..256) + && truncated.len() < self.0.len() + { + write!(f, "0x{}... (len={})", hex::encode(truncated), self.0.len()) + } else { + write!(f, "0x{}", hex::encode(self.0)) + } + } +} + +#[cfg(test)] +mod test { + #![expect(clippy::unwrap_used)] + + use crate::node::{BranchNode, LeafNode, Node}; + use crate::nodestore::AreaIndex; + use crate::{Child, Children, LinearAddress, NibblesIterator, Path}; + use test_case::test_case; + + #[test_case( + Node::Leaf(LeafNode { + partial_path: Path::from(vec![0, 1, 2, 3]), + value: vec![4, 5, 6, 7].into() + }), 11; "leaf node with value")] + #[test_case( + Node::Leaf(LeafNode { + partial_path: Path::from_nibbles_iterator(NibblesIterator::new(b"this is a really long partial path, like so long it's more than 63 nibbles long which triggers #1056.")), + value: vec![4, 5, 6, 7].into() + }), 211; "leaf node obnoxiously long partial path")] + #[test_case(Node::Branch(Box::new(BranchNode { + partial_path: Path::from(vec![0, 1]), + value: None, + children: Children::from_fn(|i| { + if i.as_u8() == 15 { + Some(Child::AddressWithHash(LinearAddress::new(1).unwrap(), std::array::from_fn::(|i| i as u8).into())) + } else { + None + } + })})), 45; "one child branch node with short partial path and no value" + )] + #[test_case(Node::Branch(Box::new(BranchNode { + partial_path: Path::from(vec![0, 1, 2, 3]), + value: Some(vec![4, 5, 6, 7].into()), + children: Children::from_fn(|_| + Some(Child::AddressWithHash(LinearAddress::new(1).unwrap(), std::array::from_fn::(|i| i as u8).into())) + )})), 652; "full branch node with long partial path and value" + )] + #[test_case(Node::Branch(Box::new(BranchNode { + partial_path: Path::from_nibbles_iterator(NibblesIterator::new(b"this is a really long partial path, like so long it's more than 63 nibbles long which triggers #1056.")), + value: Some(vec![4, 5, 6, 7].into()), + children: Children::from_fn(|_| + Some(Child::AddressWithHash(LinearAddress::new(1).unwrap(), std::array::from_fn::(|i| i as u8).into())) + )})), 851; "full branch node with obnoxiously long partial path" + )] + #[test_case(Node::Branch(Box::new(BranchNode { + partial_path: Path::from_nibbles_iterator(NibblesIterator::new(b"this is a really long partial path, like so long it's more than 63 nibbles long which triggers #1056.")), + value: Some((*br" +We also need to test values that have a length longer than 255 bytes so that we +verify that we decode the entire value every time. previously, we would only read +the first byte for the value length, which is incorrect if the length is greater +than 126 bytes as the length would be encoded in multiple bytes. + ").into()), + children: Children::from_fn(|_| + Some(Child::AddressWithHash(LinearAddress::new(1).unwrap(), std::array::from_fn::(|i| i as u8).into())) + )})), 1165; "full branch node with obnoxiously long partial path and long value" + )] + // When ethhash is enabled, we don't actually check the `expected_length` + fn test_serialize_deserialize( + node: Node, + #[cfg_attr( + any(feature = "branch_factor_256", feature = "ethhash"), + expect(unused_variables) + )] + expected_length: usize, + ) { + use crate::node::Node; + use std::io::Cursor; + + let mut serialized = Vec::new(); + node.as_bytes(AreaIndex::MIN, &mut serialized); + #[cfg(not(any(feature = "branch_factor_256", feature = "ethhash")))] + assert_eq!(serialized.len(), expected_length); + let mut cursor = Cursor::new(&serialized); + cursor.set_position(1); + let deserialized = Node::from_reader(&mut cursor).unwrap(); + + assert_eq!(node, deserialized); + } +} diff --git a/firewood/storage/src/node/path.rs b/firewood/storage/src/node/path.rs new file mode 100644 index 000000000000..7fcfc44ef141 --- /dev/null +++ b/firewood/storage/src/node/path.rs @@ -0,0 +1,376 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 8 occurrences after enabling the lint." +)] +#![expect( + clippy::from_iter_instead_of_collect, + reason = "Found 1 occurrences after enabling the lint." +)] +#![expect( + clippy::inline_always, + reason = "Found 1 occurrences after enabling the lint." +)] + +// TODO: remove bitflags, we only use one bit +use bitflags::bitflags; +use smallvec::SmallVec; +use std::fmt::{self, Debug, LowerHex}; +use std::iter::{FusedIterator, once}; +use std::ops::Add; + +use crate::{PathComponent, TriePathFromUnpackedBytes}; + +static NIBBLES: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + +/// Path is part or all of a node's path in the trie. +/// Each element is a nibble. +#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Default)] +pub struct Path(pub SmallVec<[u8; 64]>); + +impl Debug for Path { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + for nib in &self.0 { + if *nib > 0xf { + write!(f, "[invalid {:02x}] ", *nib)?; + } else { + write!(f, "{:x} ", *nib)?; + } + } + Ok(()) + } +} + +impl LowerHex for Path { + // TODO: handle fill / alignment / etc + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + if self.0.is_empty() { + write!(f, "[]") + } else { + if f.alternate() { + write!(f, "0x")?; + } + for nib in &self.0 { + write!(f, "{:x}", *nib)?; + } + Ok(()) + } + } +} + +impl std::ops::Deref for Path { + type Target = [u8]; + fn deref(&self) -> &[u8] { + &self.0 + } +} + +impl> From for Path { + fn from(value: T) -> Self { + Self(SmallVec::from_slice(value.as_ref())) + } +} + +bitflags! { + // should only ever be the size of a nibble + struct Flags: u8 { + const ODD_LEN = 0b0001; + } +} + +impl Path { + /// Return an iterator over the encoded bytes + pub fn iter_encoded(&self) -> impl Iterator { + let mut flags = Flags::empty(); + + let has_odd_len = self.0.len() & 1 == 1; + + let extra_byte = if has_odd_len { + flags.insert(Flags::ODD_LEN); + + None + } else { + Some(0) + }; + + once(flags.bits()) + .chain(extra_byte) + .chain(self.0.iter().copied()) + } + + /// Creates a Path from a [Iterator] or other iterator that returns + /// nibbles + pub fn from_nibbles_iterator>(nibbles_iter: T) -> Self { + Path(SmallVec::from_iter(nibbles_iter)) + } + + /// Creates an empty Path + #[must_use] + pub fn new() -> Self { + Path(SmallVec::new()) + } + + /// Read from an iterator that returns nibbles with a prefix + /// The prefix is one optional byte -- if not present, the Path is empty + /// If there is one byte, and the byte contains a [`Flags::ODD_LEN`] (0x1) + /// then there is another discarded byte after that. + #[cfg(test)] + pub fn from_encoded_iter>(mut iter: Iter) -> Self { + let flags = Flags::from_bits_retain(iter.next().unwrap_or_default()); + + if !flags.contains(Flags::ODD_LEN) { + let _ = iter.next(); + } + + Self(iter.collect()) + } + + /// Add nibbles to the end of a path + pub fn extend>(&mut self, iter: T) { + self.0.extend(iter); + } + + /// Create an iterator that returns the bytes from the underlying nibbles + /// If there is an odd nibble at the end, it is dropped + #[must_use] + pub fn bytes_iter(&self) -> BytesIterator<'_> { + BytesIterator { + nibbles_iter: self.iter(), + } + } + + /// Casts the path to a slice of its components. + #[must_use] + pub fn as_components(&self) -> &[PathComponent] { + TriePathFromUnpackedBytes::path_from_unpacked_bytes(&self.0) + .expect("path should contain only nibbles") + } +} + +/// Returns the nibbles in `nibbles_iter` as compressed bytes. +/// That is, each two nibbles are combined into a single byte. +#[derive(Debug)] +pub struct BytesIterator<'a> { + nibbles_iter: std::slice::Iter<'a, u8>, +} + +impl Add for Path { + type Output = Path; + fn add(self, other: Path) -> Self::Output { + let mut new = self.clone(); + new.extend(other.iter().copied()); + new + } +} + +impl Iterator for BytesIterator<'_> { + type Item = u8; + fn next(&mut self) -> Option { + if let Some(&hi) = self.nibbles_iter.next() + && let Some(&lo) = self.nibbles_iter.next() + { + return Some(hi * 16 + lo); + } + None + } + + // this helps make the collection into a box faster + fn size_hint(&self) -> (usize, Option) { + ( + self.nibbles_iter.size_hint().0 / 2, + self.nibbles_iter.size_hint().1.map(|max| max / 2), + ) + } +} + +/// Iterates over the nibbles in `data`. +/// That is, each byte in `data` is converted to two nibbles. +#[derive(Clone, Debug)] +pub struct NibblesIterator<'a> { + data: &'a [u8], + head: usize, + tail: usize, +} + +impl FusedIterator for NibblesIterator<'_> {} + +impl Iterator for NibblesIterator<'_> { + type Item = u8; + + #[cfg(feature = "branch_factor_256")] + fn next(&mut self) -> Option { + #![expect(clippy::indexing_slicing)] + if self.is_empty() { + return None; + } + let result = self.data[self.head]; + self.head += 1; + Some(result) + } + + #[cfg(not(feature = "branch_factor_256"))] + fn next(&mut self) -> Option { + if self.is_empty() { + return None; + } + let result = if self.head.is_multiple_of(2) { + #[expect(clippy::indexing_slicing)] + NIBBLES[(self.data[self.head / 2] >> 4) as usize] + } else { + #[expect(clippy::indexing_slicing)] + NIBBLES[(self.data[self.head / 2] & 0xf) as usize] + }; + self.head += 1; + Some(result) + } + + fn size_hint(&self) -> (usize, Option) { + let remaining = self.tail - self.head; + (remaining, Some(remaining)) + } + + fn nth(&mut self, n: usize) -> Option { + self.head += std::cmp::min(n, self.tail - self.head); + self.next() + } +} + +impl<'a> NibblesIterator<'a> { + #[cfg(not(feature = "branch_factor_256"))] + const BYTES_PER_NIBBLE: usize = 2; + #[cfg(feature = "branch_factor_256")] + const BYTES_PER_NIBBLE: usize = 1; + + #[inline(always)] + const fn is_empty(&self) -> bool { + self.head == self.tail + } + + /// Returns a new `NibblesIterator` over the given `data`. + /// Each byte in `data` is converted to two nibbles. + #[must_use] + pub const fn new(data: &'a [u8]) -> Self { + NibblesIterator { + data, + head: 0, + tail: Self::BYTES_PER_NIBBLE * data.len(), + } + } +} + +impl DoubleEndedIterator for NibblesIterator<'_> { + fn next_back(&mut self) -> Option { + if self.is_empty() { + return None; + } + + let result = if self.tail.is_multiple_of(2) { + #[expect(clippy::indexing_slicing)] + NIBBLES[(self.data[self.tail / 2 - 1] & 0xf) as usize] + } else { + #[expect(clippy::indexing_slicing)] + NIBBLES[(self.data[self.tail / 2] >> 4) as usize] + }; + self.tail -= 1; + + Some(result) + } + + fn nth_back(&mut self, n: usize) -> Option { + self.tail -= std::cmp::min(n, self.tail - self.head); + self.next_back() + } +} + +#[cfg(test)] +mod test { + use super::*; + use std::fmt::Debug; + use test_case::test_case; + + #[cfg(not(feature = "branch_factor_256"))] + static TEST_BYTES: [u8; 4] = [0xde, 0xad, 0xbe, 0xef]; + + #[test] + #[cfg(not(feature = "branch_factor_256"))] + fn happy_regular_nibbles() { + let iter = NibblesIterator::new(&TEST_BYTES); + let expected = [0xd, 0xe, 0xa, 0xd, 0xb, 0xe, 0xe, 0xf]; + + assert!(iter.eq(expected)); + } + + #[test] + #[cfg(not(feature = "branch_factor_256"))] + fn size_hint() { + let mut iter = NibblesIterator::new(&TEST_BYTES); + assert_eq!((8, Some(8)), iter.size_hint()); + let _ = iter.next(); + assert_eq!((7, Some(7)), iter.size_hint()); + } + + #[test] + #[cfg(not(feature = "branch_factor_256"))] + fn backwards() { + let iter = NibblesIterator::new(&TEST_BYTES).rev(); + let expected = [0xf, 0xe, 0xe, 0xb, 0xd, 0xa, 0xe, 0xd]; + assert!(iter.eq(expected)); + } + + #[test] + #[cfg(not(feature = "branch_factor_256"))] + fn nth_back() { + let mut iter = NibblesIterator::new(&TEST_BYTES); + assert_eq!(iter.nth_back(0), Some(0xf)); + assert_eq!(iter.nth_back(0), Some(0xe)); + assert_eq!(iter.nth_back(1), Some(0xb)); + assert_eq!(iter.nth_back(2), Some(0xe)); + assert_eq!(iter.nth_back(0), Some(0xd)); + assert_eq!(iter.nth_back(0), None); + } + + #[test] + fn empty() { + let nib = NibblesIterator::new(&[]); + assert!(nib.is_empty()); + let it = nib.into_iter(); + assert!(it.is_empty()); + assert_eq!(it.size_hint().0, 0); + } + + #[test] + #[cfg(not(feature = "branch_factor_256"))] + fn not_empty_because_of_data() { + let mut iter = NibblesIterator::new(&[1]); + assert!(!iter.is_empty()); + assert!(!iter.is_empty()); + assert_eq!(iter.size_hint(), (2, Some(2))); + assert_eq!(iter.next(), Some(0)); + assert!(!iter.is_empty()); + assert_eq!(iter.size_hint(), (1, Some(1))); + assert_eq!(iter.next(), Some(1)); + assert!(iter.is_empty()); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + #[test_case([0, 0, 2, 3], [2, 3])] + #[test_case([1, 2, 3, 4], [2, 3, 4])] + fn encode_decode + PartialEq + Debug, U: AsRef<[u8]>>(encode: T, expected: U) { + let from_encoded = Path::from_encoded_iter(encode.as_ref().iter().copied()); + assert_eq!( + from_encoded.0, + SmallVec::<[u8; 32]>::from_slice(expected.as_ref()) + ); + let to_encoded = from_encoded.iter_encoded().collect::>(); + assert_eq!(encode.as_ref(), to_encoded.as_ref()); + } + + #[test_case(Path::new(), "[]", "[]")] + #[test_case(Path::from([0x12, 0x34, 0x56, 0x78]), "12345678", "0x12345678")] + fn test_fmt_lower_hex(path: Path, expected: &str, expected_with_prefix: &str) { + assert_eq!(format!("{path:x}"), expected); + assert_eq!(format!("{path:#x}"), expected_with_prefix); + } +} diff --git a/firewood/storage/src/node/persist.rs b/firewood/storage/src/node/persist.rs new file mode 100644 index 000000000000..60f91344da38 --- /dev/null +++ b/firewood/storage/src/node/persist.rs @@ -0,0 +1,323 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use parking_lot::Mutex; +use std::{fmt::Display, sync::Arc}; + +use crate::{FileIoError, LinearAddress, NodeReader, SharedNode}; + +/// A node that is either in memory or on disk. +/// +/// In-memory nodes that can be moved to disk. This structure allows that to happen +/// atomically. +/// +/// `MaybePersistedNode` owns a reference-counted pointer to a mutex-protected +/// enum representing either an un-persisted (or allocating) node or the +/// linear address of a persisted node. +/// +/// This type is complicated, so here is a breakdown of the types involved: +/// +/// | Item | Description | +/// |------------------------|--------------------------------------------------------| +/// | [`MaybePersistedNode`] | Newtype wrapper around the remaining items. | +/// | [Arc] | Reference counted pointer to a mutexed enum | +/// | `Mutex` | Protects the inner enum during updates | +/// | `MaybePersisted` | Enum of either `Unpersisted` or `Persisted` | +/// | variant `Unpersisted` | The shared node, in memory, for unpersisted nodes | +/// | -> [`SharedNode`] | A `triomphe::Arc` of a [Node](`crate::Node`) | +/// | variant `Persisted` | The address of a persisted node. | +/// | -> [`LinearAddress`] | A 64-bit address for a persisted node on disk. | +/// +/// Traversing these pointers does incur a runtime penalty. +/// +/// When an `Unpersisted` node is `Persisted` using [`MaybePersistedNode::persist_at`], +/// the enum value inside the mutex is replaced under the lock. Subsequent accesses +/// to any instance of it, including any clones, will see the `Persisted` node address. +#[derive(Debug, Clone)] +pub struct MaybePersistedNode(Arc>); + +impl PartialEq for MaybePersistedNode { + fn eq(&self, other: &MaybePersistedNode) -> bool { + // if underlying mutex is same, this is necessary to avoid deadlock + if Arc::ptr_eq(&self.0, &other.0) { + return true; + } + *self.0.lock() == *other.0.lock() + } +} + +impl Eq for MaybePersistedNode {} + +impl From for MaybePersistedNode { + fn from(node: SharedNode) -> Self { + MaybePersistedNode(Arc::new(Mutex::new(MaybePersisted::Unpersisted(node)))) + } +} + +impl From for MaybePersistedNode { + fn from(address: LinearAddress) -> Self { + MaybePersistedNode(Arc::new(Mutex::new(MaybePersisted::Persisted(address)))) + } +} + +impl From<&MaybePersistedNode> for Option { + fn from(node: &MaybePersistedNode) -> Option { + match &*node.0.lock() { + MaybePersisted::Unpersisted(_) => None, + MaybePersisted::Allocated(address, _) | MaybePersisted::Persisted(address) => { + Some(*address) + } + } + } +} + +impl MaybePersistedNode { + /// Converts this `MaybePersistedNode` to a `SharedNode` by reading from the appropriate source. + /// + /// If the node is in memory, it returns a clone of the in-memory node. + /// If the node is on disk, it reads the node from storage using the provided `NodeReader`. + /// + /// # Arguments + /// + /// * `storage` - A reference to a `NodeReader` implementation that can read nodes from storage + /// + /// # Returns + /// + /// Returns a `Result` where: + /// - `Ok(SharedNode)` contains the node if successfully retrieved + /// - `Err(FileIoError)` if there was an error reading from storage + pub fn as_shared_node(&self, storage: &S) -> Result { + match &*self.0.lock() { + MaybePersisted::Allocated(_, node) | MaybePersisted::Unpersisted(node) => { + Ok(node.clone()) + } + MaybePersisted::Persisted(address) => storage.read_node(*address), + } + } + + /// Returns the linear address of the node if it is persisted on disk. + /// + /// # Returns + /// + /// Returns `Some(LinearAddress)` if the node is persisted on disk, otherwise `None`. + #[must_use] + pub fn as_linear_address(&self) -> Option { + match &*self.0.lock() { + MaybePersisted::Unpersisted(_) => None, + MaybePersisted::Allocated(address, _) | MaybePersisted::Persisted(address) => { + Some(*address) + } + } + } + + /// Returns a reference to the unpersisted node if it is unpersisted. + /// + /// # Returns + /// + /// Returns `Some(&Self)` if the node is unpersisted, otherwise `None`. + #[must_use] + pub fn unpersisted(&self) -> Option<&Self> { + match &*self.0.lock() { + MaybePersisted::Allocated(_, _) | MaybePersisted::Unpersisted(_) => Some(self), + MaybePersisted::Persisted(_) => None, + } + } + + /// Updates the internal state to indicate this node is persisted at the specified disk address. + /// + /// This method changes the internal state of the `MaybePersistedNode` from `Mem` to `Disk`, + /// indicating that the node has been written to the specified disk location. + /// + /// This is done under a `Mutex` lock. + /// + /// # Arguments + /// + /// * `addr` - The `LinearAddress` where the node has been persisted on disk + pub fn persist_at(&self, addr: LinearAddress) { + *self.0.lock() = MaybePersisted::Persisted(addr); + } + + /// Updates the internal state to indicate this node is allocated at the specified disk address. + /// + /// This method changes the internal state of the `MaybePersistedNode` to `Allocated`, + /// indicating that the node has been allocated on disk but is still in memory. + /// + /// This is done under a `Mutex` lock. + /// + /// # Arguments + /// + /// * `addr` - The `LinearAddress` where the node has been allocated on disk + pub fn allocate_at(&self, addr: LinearAddress) { + let mut guard = self.0.lock(); + let node = { + match &*guard { + MaybePersisted::Unpersisted(node) | MaybePersisted::Allocated(_, node) => { + node.clone() + } + MaybePersisted::Persisted(_) => { + unreachable!("Cannot allocate a node that is already persisted on disk"); + } + } + }; + *guard = MaybePersisted::Allocated(addr, node); + } + + /// Returns the address and shared node if this node is in the Allocated state. + /// + /// # Returns + /// + /// Returns `Some((LinearAddress, SharedNode))` if the node is in the Allocated state, + /// otherwise `None`. + #[must_use] + pub fn allocated_info(&self) -> Option<(LinearAddress, SharedNode)> { + match &*self.0.lock() { + MaybePersisted::Allocated(addr, node) => Some((*addr, node.clone())), + _ => None, + } + } +} + +/// Display the `MaybePersistedNode` as a string. +/// +/// This is used in the dump utility. +/// +/// We render these: +/// For disk addresses, just the address +/// For shared nodes, the address of the [`SharedNode`] object, prefixed with a 'M' +/// +/// If instead you want the node itself, use [`MaybePersistedNode::as_shared_node`] first. +impl Display for MaybePersistedNode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self.0.try_lock() { + Some(guard) => match &*guard { + MaybePersisted::Unpersisted(node) => write!(f, "M{:p}", (*node).as_ptr()), + MaybePersisted::Allocated(addr, node) => { + write!(f, "A{:p}@{addr}", (*node).as_ptr()) + } + MaybePersisted::Persisted(addr) => write!(f, "{addr}"), + }, + None => write!(f, ""), + } + } +} + +/// The internal state of a `MaybePersistedNode`. +/// +/// This enum represents the three possible states of a `MaybePersisted`: +/// - `Unpersisted(SharedNode)`: The node is currently in memory +/// - `Allocated(LinearAddress, SharedNode)`: The node is allocated on disk but being flushed to disk +/// - `Persisted(LinearAddress)`: The node is currently on disk at the specified address +#[derive(Debug, PartialEq, Eq)] +enum MaybePersisted { + Unpersisted(SharedNode), + Allocated(LinearAddress, SharedNode), + Persisted(LinearAddress), +} + +#[cfg(test)] +#[expect(clippy::unwrap_used)] +mod test { + use nonzero_ext::nonzero; + + use crate::{LeafNode, MemStore, Node, NodeStore, Path}; + + use super::*; + + #[test] + fn test_maybe_persisted_node() -> Result<(), FileIoError> { + let mem_store = MemStore::new(vec![]).into(); + let store = NodeStore::new_empty_committed(mem_store); + let node = SharedNode::new(Node::Leaf(LeafNode { + partial_path: Path::new(), + value: vec![0].into(), + })); + // create as unpersisted + let maybe_persisted_node = MaybePersistedNode::from(node.clone()); + let addr = nonzero!(2048u64); + assert_eq!(maybe_persisted_node.as_shared_node(&store).unwrap(), node); + assert_eq!( + Option::::None, + Option::from(&maybe_persisted_node) + ); + + let addr = LinearAddress::new(addr.get()).unwrap(); + maybe_persisted_node.persist_at(addr); + assert!(maybe_persisted_node.as_shared_node(&store).is_err()); + assert_eq!(Some(addr), Option::from(&maybe_persisted_node)); + Ok(()) + } + + #[test] + fn test_from_linear_address() { + let addr: LinearAddress = nonzero!(1024u64).into(); + let maybe_persisted_node = MaybePersistedNode::from(addr); + assert_eq!(Some(addr), Option::from(&maybe_persisted_node)); + } + + #[test] + fn test_clone_shares_underlying_shared_node() -> Result<(), FileIoError> { + let mem_store = MemStore::new(vec![]).into(); + let store = NodeStore::new_empty_committed(mem_store); + let node = SharedNode::new(Node::Leaf(LeafNode { + partial_path: Path::new(), + value: vec![42].into(), + })); + + let original = MaybePersistedNode::from(node.clone()); + let cloned = original.clone(); + + // Both should be unpersisted initially + assert_eq!(original.as_shared_node(&store).unwrap(), node); + assert_eq!(cloned.as_shared_node(&store).unwrap(), node); + assert_eq!(Option::::None, Option::from(&original)); + assert_eq!(Option::::None, Option::from(&cloned)); + + // First reference is 'node', second is shared by original and cloned + assert_eq!(triomphe::Arc::strong_count(&node), 2); + + // Persist the original + let addr = nonzero!(1024u64).into(); + original.persist_at(addr); + + // Both original and clone should now be persisted since they share the same + // mutex-protected pointer + assert!(original.as_shared_node(&store).is_err()); + assert!(cloned.as_shared_node(&store).is_err()); + assert_eq!(Some(addr), Option::from(&original)); + assert_eq!(Some(addr), Option::from(&cloned)); + + // 'node' is no longer referenced by anyone but our local copy, + // so the count should be 1 + assert_eq!(triomphe::Arc::strong_count(&node), 1); + + Ok(()) + } + + #[test] + fn test_allocated_info() { + let node = SharedNode::new(Node::Leaf(LeafNode { + partial_path: Path::new(), + value: vec![123].into(), + })); + + let maybe_persisted = MaybePersistedNode::from(node.clone()); + + // Initially unpersisted, so allocated_info should return None + assert!(maybe_persisted.allocated_info().is_none()); + + // Allocate the node + let addr = LinearAddress::new(2048).unwrap(); + maybe_persisted.allocate_at(addr); + + // Now allocated_info should return Some + let (retrieved_addr, retrieved_node) = maybe_persisted.allocated_info().unwrap(); + assert_eq!(retrieved_addr, addr); + assert_eq!(retrieved_node, node); + + // Persist the node + maybe_persisted.persist_at(addr); + + // After persisting, allocated_info should return None again + assert!(maybe_persisted.allocated_info().is_none()); + } +} diff --git a/firewood/storage/src/nodestore/alloc.rs b/firewood/storage/src/nodestore/alloc.rs new file mode 100644 index 000000000000..b506f496f4dc --- /dev/null +++ b/firewood/storage/src/nodestore/alloc.rs @@ -0,0 +1,977 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! # Allocation Module +//! +//! This module handles memory allocation and space management for nodes in the nodestore's +//! linear storage, implementing a malloc-like free space management system. +//! +//! ### Area Sizes +//! Storage is divided into 23 predefined area sizes from 16 bytes to 16MB: +//! - Small sizes (16, 32, 64, 96, 128, 256, 512, 768, 1024 bytes) for common nodes +//! - Power-of-two larger sizes (2KB, 4KB, 8KB, ..., 16MB) for larger data +//! +//! ### Storage Format +//! Each stored area follows this layout: +//! ```text +//! [AreaIndex:1][AreaType:1][NodeData:n] +//! ``` +//! - **`AreaIndex`** - Index into `AREA_SIZES` array (1 byte) +//! - **`AreaType`** - 0xFF for free areas, otherwise node type data (1 byte) +//! - **`NodeData`** - Serialized node content + +use super::area_index_and_size; +use super::primitives::{AreaIndex, LinearAddress, index_name}; +use crate::linear::FileIoError; +use crate::logger::trace; +use crate::node::branch::{ReadSerializable, Serializable}; +use crate::nodestore::NodeStoreHeader; +use integer_encoding::VarIntReader; + +use std::io::{Error, ErrorKind, Read}; +use std::iter::FusedIterator; + +use crate::node::ExtendableBytes; +use crate::{ + FreeListParent, MaybePersistedNode, ReadableStorage, WritableStorage, firewood_counter, +}; + +/// Returns the maximum size needed to encode a `VarInt`. +const fn var_int_max_size() -> usize { + const { (size_of::() * 8 + 7) / 7 } +} + +/// `FreeLists` is an array of `Option` for each area size. +pub type FreeLists = [Option; AreaIndex::NUM_AREA_SIZES]; + +/// A [`FreeArea`] is stored at the start of the area that contained a node that +/// has been freed. +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct FreeArea { + next_free_block: Option, +} + +impl Serializable for FreeArea { + fn write_to(&self, vec: &mut W) { + vec.push(0xff); // 0xff indicates a free area + vec.extend_var_int(self.next_free_block.map_or(0, LinearAddress::get)); + } + + /// Parse a [`FreeArea`]. + /// + /// The old serde generate code that unintentionally encoded [`FreeArea`]s + /// incorrectly. Integers were encoded as variable length integers, but + /// expanded to fixed-length below: + /// + /// ```text + /// [ + /// 0x01, // LE u32 begin -- field index of the old `StoredArea` struct (#1) + /// 0x00, + /// 0x00, + /// 0x00, // LE u32 end + /// 0x01, // `Option` discriminant, 1 Indicates `Some(_)` from `Option` + /// // because serde does not handle the niche optimization of + /// // `Option>` + /// 0x2a, // LinearAddress(LE u64) start + /// 0x00, + /// 0x00, + /// 0x00, + /// 0x00, + /// 0x00, + /// 0x00, + /// 0x00, // LE u64 end + /// ] + /// ``` + /// + /// Our manual encoding format is (with variable int, but expanded below): + /// + /// ```text + /// [ + /// 0xff, // FreeArea marker + /// 0x2a, // LinearAddress(LE u64) start + /// 0x00, + /// 0x00, + /// 0x00, + /// 0x00, + /// 0x00, + /// 0x00, + /// 0x00, // LE u64 end + /// ] + /// ``` + fn from_reader(mut reader: R) -> std::io::Result { + match reader.read_byte()? { + 0x01 => { + // might be old format, look for option discriminant + match reader.read_byte()? { + 0x00 => { + // serde encoded `Option::None` as 0 with no following data + Ok(Self { + next_free_block: None, + }) + } + 0x01 => { + // encoded `Some(_)` as 1 with the data following + let addr = LinearAddress::new(read_bincode_varint_u64_le(&mut reader)?) + .ok_or_else(|| { + Error::new( + ErrorKind::InvalidData, + "Option:: was Some(0) which is invalid", + ) + })?; + Ok(Self { + next_free_block: Some(addr), + }) + } + option_discriminant => Err(Error::new( + ErrorKind::InvalidData, + format!("Invalid Option discriminant: {option_discriminant}"), + )), + } + } + 0xFF => { + // new format: read the address directly (zero is allowed here to indicate None) + Ok(Self { + next_free_block: LinearAddress::new(reader.read_varint()?), + }) + } + first_byte => Err(Error::new( + ErrorKind::InvalidData, + format!( + "Invalid FreeArea marker, expected 0xFF (or 0x01 for old format), found {first_byte:#04x}" + ), + )), + } + } +} + +impl FreeArea { + /// Create a new `FreeArea` + pub const fn new(next_free_block: Option) -> Self { + Self { next_free_block } + } + + /// Get the next free block address + pub const fn next_free_block(self) -> Option { + self.next_free_block + } + + pub fn from_storage( + storage: &S, + address: LinearAddress, + ) -> Result<(Self, AreaIndex), FileIoError> { + let free_area_addr = address.get(); + let stored_area_stream = storage.stream_from(free_area_addr)?; + Self::from_storage_reader(stored_area_stream).map_err(|e| { + storage.file_io_error( + e, + free_area_addr, + Some("FreeArea::from_storage".to_string()), + ) + }) + } + + pub fn as_bytes(self, area_index: AreaIndex, encoded: &mut T) { + const RESERVE_SIZE: usize = size_of::() + var_int_max_size::(); + + encoded.reserve(RESERVE_SIZE); + encoded.push(area_index.get()); + self.write_to(encoded); + } + + fn from_storage_reader(mut reader: impl Read) -> std::io::Result<(Self, AreaIndex)> { + let area_index = AreaIndex::try_from(reader.read_byte()?)?; + let free_area = reader.next_value()?; + Ok((free_area, area_index)) + } +} + +// Re-export the NodeStore types we need +use super::NodeStore; + +/// Writable allocator for allocating and deleting nodes +#[derive(Debug)] +pub struct NodeAllocator<'a, S> { + storage: &'a S, + header: &'a mut NodeStoreHeader, +} + +impl<'a, S: ReadableStorage> NodeAllocator<'a, S> { + pub const fn new(storage: &'a S, header: &'a mut NodeStoreHeader) -> Self { + Self { storage, header } + } + + /// Returns (index, `area_size`) for the stored area at `addr`. + /// `index` is the index of `area_size` in the array of valid block sizes. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the area cannot be read. + pub fn area_index_and_size( + &self, + addr: LinearAddress, + ) -> Result<(AreaIndex, u64), FileIoError> { + area_index_and_size(self.storage, addr) + } + + /// Attempts to allocate from the free lists for `index`. + /// + /// If successful returns the address of the newly allocated area; + /// otherwise, returns None. + fn allocate_from_freed( + &mut self, + index: AreaIndex, + ) -> Result, FileIoError> { + let free_stored_area_addr = self + .header + .free_lists_mut() + .get_mut(index.as_usize()) + .expect("index is less than AreaIndex::NUM_AREA_SIZES"); + if let Some(address) = free_stored_area_addr { + let address = *address; + if let Some(free_head) = self.storage.free_list_cache(address) { + trace!("free_head@{address}(cached): {free_head:?} size:{index}"); + *free_stored_area_addr = free_head; + } else { + let (free_head, read_index) = FreeArea::from_storage(self.storage, address)?; + debug_assert_eq!(read_index, index); + + // Update the free list to point to the next free block. + *free_stored_area_addr = free_head.next_free_block; + } + + firewood_counter!( + "firewood.space.reused", + "Bytes reused from free list by index", + "index" => index_name(index) + ) + .increment(index.size()); + + // Return the address of the newly allocated block. + trace!("Allocating from free list: addr: {address:?}, size: {index}"); + return Ok(Some(address)); + } + + trace!("No free blocks of sufficient size {index} found"); + firewood_counter!( + "firewood.space.from_end", + "Space allocated from end of nodestore", + "index" => index_name(index) + ) + .increment(index.size()); + Ok(None) + } + + fn allocate_from_end(&mut self, index: AreaIndex) -> Result { + let area_size = index.size(); + let addr = LinearAddress::new(self.header.size()).expect("node store size can't be 0"); + self.header + .set_size(self.header.size().saturating_add(area_size)); + debug_assert!(addr.is_aligned()); + trace!("Allocating from end: addr: {addr:?}, size: {index}"); + Ok(addr) + } + + /// Returns an address that can be used to store the given `node` and updates + /// `self.header` to reflect the allocation. Doesn't actually write the node to storage. + /// Also returns the index of the free list the node was allocated from. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the node cannot be allocated. + pub fn allocate_node( + &mut self, + node: &[u8], + ) -> Result<(LinearAddress, AreaIndex), FileIoError> { + let stored_area_size = node.len() as u64; + let area_index = AreaIndex::from_size(stored_area_size).map_err(|e| { + self.storage + .file_io_error(e, 0, Some("allocate_node".to_owned())) + })?; + + // Attempt to allocate from a free list. + // If we can't allocate from a free list, allocate past the existing + // of the ReadableStorage. + let addr = match self.allocate_from_freed(area_index)? { + Some(addr) => addr, + None => self.allocate_from_end(area_index)?, + }; + + Ok((addr, area_index)) + } +} + +impl NodeAllocator<'_, S> { + /// Deletes the `Node` and updates the header of the allocator. + /// Nodes that are not persisted are just dropped. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the area cannot be read or written. + #[expect(clippy::indexing_slicing)] + pub fn delete_node(&mut self, node: MaybePersistedNode) -> Result<(), FileIoError> { + let Some(addr) = node.as_linear_address() else { + return Ok(()); + }; + debug_assert!(addr.is_aligned()); + + let (area_size_index, _) = self.area_index_and_size(addr)?; + trace!("Deleting node at {addr:?} of size {area_size_index}"); + firewood_counter!( + "firewood.delete_node", + "Nodes deleted", + "index" => index_name(area_size_index) + ) + .increment(1); + firewood_counter!( + "firewood.space.freed", + "Bytes freed in nodestore", + "index" => index_name(area_size_index) + ) + .increment(area_size_index.size()); + + // The area that contained the node is now free. + let mut stored_area_bytes = Vec::new(); + FreeArea::new(self.header.free_lists()[area_size_index.as_usize()]) + .as_bytes(area_size_index, &mut stored_area_bytes); + + self.storage.write(addr.into(), &stored_area_bytes)?; + + self.storage + .add_to_free_list_cache(addr, self.header.free_lists()[area_size_index.as_usize()]); + + // The newly freed block is now the head of the free list. + self.header.free_lists_mut()[area_size_index.as_usize()] = Some(addr); + + Ok(()) + } + + pub fn flush_freelist(&mut self) -> Result<(), FileIoError> { + let free_list_bytes = bytemuck::bytes_of(self.header.free_lists()); + let free_list_offset = NodeStoreHeader::free_lists_offset(); + self.storage.write(free_list_offset, free_list_bytes)?; + Ok(()) + } +} + +/// Iterator over free lists in the nodestore +struct FreeListIterator<'a, S: ReadableStorage> { + storage: &'a S, + id: AreaIndex, + next_addr: Option, + parent: FreeListParent, +} + +impl<'a, S: ReadableStorage> FreeListIterator<'a, S> { + const fn new( + storage: &'a S, + free_list_id: AreaIndex, + next_addr: Option, + src_ptr: FreeListParent, + ) -> Self { + Self { + storage, + id: free_list_id, + next_addr, + parent: src_ptr, + } + } + + fn next_with_metadata( + &mut self, + ) -> Option<(Result, FreeListParent)> { + let parent = self.parent; + let next_addr = self.next()?; + let next_with_metadata = next_addr.map(|(addr, area_index)| FreeAreaWithMetadata { + addr, + area_index, + free_list_id: self.id, + }); + Some((next_with_metadata, parent)) + } +} + +impl Iterator for FreeListIterator<'_, S> { + type Item = Result<(LinearAddress, AreaIndex), FileIoError>; + + fn next(&mut self) -> Option { + let next_addr = self.next_addr?; + + // read the free area, propagate any IO error if it occurs + let (free_area, stored_area_index) = match FreeArea::from_storage(self.storage, next_addr) { + Ok(free_area) => free_area, + Err(e) => { + // if the read fails, we cannot proceed with the current freelist + self.next_addr = None; + return Some(Err(e)); + } + }; + + // update the next address to the next free block + self.parent = FreeListParent::PrevFreeArea { + area_size_idx: stored_area_index, + parent_addr: next_addr, + }; + self.next_addr = free_area.next_free_block(); + Some(Ok((next_addr, stored_area_index))) + } +} + +impl FusedIterator for FreeListIterator<'_, S> {} + +#[derive(Debug, PartialEq, Eq)] +pub(crate) struct FreeAreaWithMetadata { + pub addr: LinearAddress, + pub area_index: AreaIndex, + pub free_list_id: AreaIndex, +} + +pub(crate) struct FreeListsIterator<'a, S: ReadableStorage> { + storage: &'a S, + free_lists_iter: std::iter::Skip< + std::iter::Enumerate>>, + >, + current_free_list: Option<(AreaIndex, FreeListIterator<'a, S>)>, +} + +impl<'a, S: ReadableStorage> FreeListsIterator<'a, S> { + pub(crate) fn new( + storage: &'a S, + free_lists: &'a FreeLists, + start_area_index: AreaIndex, + ) -> Self { + let mut free_lists_iter = free_lists + .iter() + .enumerate() + .skip(start_area_index.as_usize()); + let current_free_list = free_lists_iter.next().map(|(id, head)| { + let free_list_id = + AreaIndex::try_from(id).expect("id is less than AreaIndex::NUM_AREA_SIZES"); + let free_list_iter = FreeListIterator::new( + storage, + free_list_id, + *head, + FreeListParent::FreeListHead(free_list_id), + ); + (free_list_id, free_list_iter) + }); + Self { + storage, + free_lists_iter, + current_free_list, + } + } + + pub(crate) fn next_with_metadata( + &mut self, + ) -> Option<(Result, FreeListParent)> { + self.next_inner(FreeListIterator::next_with_metadata) + } + + fn next_inner) -> Option>( + &mut self, + mut next_fn: F, + ) -> Option { + loop { + let Some((_, free_list_iter)) = &mut self.current_free_list else { + return None; + }; + if let Some(next) = next_fn(free_list_iter) { + // the current free list is not exhausted, return the next free area + return Some(next); + } + + self.move_to_next_free_list(); + } + } + + pub(crate) fn move_to_next_free_list(&mut self) { + let Some((next_free_list_id, next_free_list_head)) = self.free_lists_iter.next() else { + self.current_free_list = None; + return; + }; + let next_free_list_id = AreaIndex::try_from(next_free_list_id) + .expect("next_free_list_id is less than AreaIndex::NUM_AREA_SIZES"); + let next_free_list_iter = FreeListIterator::new( + self.storage, + next_free_list_id, + *next_free_list_head, + FreeListParent::FreeListHead(next_free_list_id), + ); + self.current_free_list = Some((next_free_list_id, next_free_list_iter)); + } +} + +impl Iterator for FreeListsIterator<'_, S> { + type Item = Result<(LinearAddress, AreaIndex), FileIoError>; + + fn next(&mut self) -> Option { + self.next_inner(FreeListIterator::next) + } +} + +/// Extension methods for `NodeStore` to provide free list iteration capabilities +impl NodeStore { + // Returns an iterator over the free lists of size no smaller than the size corresponding to `start_area_index`. + // The iterator returns a tuple of the address and the area index of the free area. + // Since this is a low-level iterator, we avoid safe conversion to AreaIndex for performance + pub(crate) fn free_list_iter(&self, start_area_index: AreaIndex) -> FreeListsIterator<'_, S> { + FreeListsIterator::new(self.storage.as_ref(), self.freelists(), start_area_index) + } +} + +// Functionalities use by the checker +impl NodeStore { + pub(crate) fn truncate_free_list( + &mut self, + free_list_parent: FreeListParent, + ) -> Result<(), FileIoError> { + match free_list_parent { + FreeListParent::FreeListHead(area_size_index) => { + *self + .freelists_mut() + .get_mut(area_size_index.as_usize()) + .expect("area_size_index is less than AreaIndex::NUM_AREA_SIZES") = None; + Ok(()) + } + FreeListParent::PrevFreeArea { + area_size_idx, + parent_addr, + } => { + let free_area = FreeArea::new(None); + let mut stored_area_bytes = Vec::new(); + free_area.as_bytes(area_size_idx, &mut stored_area_bytes); + self.storage.write(parent_addr.into(), &stored_area_bytes)?; + Ok(()) + } + } + } +} + +fn read_bincode_varint_u64_le(reader: &mut impl Read) -> std::io::Result { + // See https://github.com/ava-labs/firewood/issues/1146 for full details. + // emulate this behavior: https://github.com/bincode-org/bincode/blob/c44b5e364e7084cdbabf9f94b63a3c7f32b8fb68/src/config/int.rs#L241-L258 + + const SINGLE_BYTE_MAX: u8 = 250; + const U16_BYTE: u8 = 251; + const U32_BYTE: u8 = 252; + const U64_BYTE: u8 = 253; + + match reader.read_byte()? { + byte @ 0..=SINGLE_BYTE_MAX => Ok(u64::from(byte)), + U16_BYTE => { + let mut buf = [0u8; 2]; + reader.read_exact(&mut buf)?; + Ok(u64::from(u16::from_le_bytes(buf))) + } + U32_BYTE => { + let mut buf = [0u8; 4]; + reader.read_exact(&mut buf)?; + Ok(u64::from(u32::from_le_bytes(buf))) + } + U64_BYTE => { + let mut buf = [0u8; 8]; + reader.read_exact(&mut buf)?; + Ok(u64::from_le_bytes(buf)) + } + byte => Err(Error::new( + ErrorKind::InvalidData, + format!( + "Invalid bincode varint byte, expected 0-250, 251, 252, or 253, found {byte:#04x}" + ), + )), + } +} + +#[cfg(test)] +#[expect(clippy::unwrap_used)] +pub mod test_utils { + use super::*; + + use crate::node::Node; + use crate::nodestore::{Committed, NodeStore, NodeStoreHeader}; + + // Helper function to wrap the node in a StoredArea and write it to the given offset. Returns the size of the area on success. + pub fn test_write_new_node( + nodestore: &NodeStore, + node: &Node, + offset: u64, + ) -> (u64, u64) { + let mut encoded_node = Vec::new(); + node.as_bytes(AreaIndex::MIN, &mut encoded_node); + let encoded_node_len = encoded_node.len() as u64; + let area_size_index = AreaIndex::from_size(encoded_node_len).unwrap(); + let mut stored_area_bytes = Vec::new(); + node.as_bytes(area_size_index, &mut stored_area_bytes); + let bytes_written = stored_area_bytes.len() as u64; + nodestore + .storage + .write(offset, stored_area_bytes.as_slice()) + .unwrap(); + (bytes_written, area_size_index.size()) + } + + // Helper function to write a free area to the given offset. + pub fn test_write_free_area( + nodestore: &NodeStore, + next_free_block: Option, + area_size_index: AreaIndex, + offset: u64, + ) { + let mut stored_area_bytes = Vec::new(); + FreeArea::new(next_free_block).as_bytes(area_size_index, &mut stored_area_bytes); + nodestore.storage.write(offset, &stored_area_bytes).unwrap(); + } + + // Helper function to write the NodeStoreHeader + pub fn test_write_header( + nodestore: &mut NodeStore, + size: u64, + root_addr: Option, + free_lists: FreeLists, + ) { + let mut header = NodeStoreHeader::new(); + header.set_size(size); + header.set_root_address(root_addr); + *header.free_lists_mut() = free_lists; + let header_bytes = bytemuck::bytes_of(&header); + nodestore.header = header; + nodestore.storage.write(0, header_bytes).unwrap(); + } + + // Helper function to write a random stored area to the given offset. + pub(crate) fn test_write_zeroed_area( + nodestore: &NodeStore, + size: u64, + offset: u64, + ) { + let area_content = vec![0u8; size as usize]; + nodestore.storage.write(offset, &area_content).unwrap(); + } +} + +#[cfg(test)] +#[expect(clippy::unwrap_used, clippy::indexing_slicing)] +mod tests { + use super::*; + use crate::area_index; + use crate::linear::memory::MemStore; + use rand::seq::IteratorRandom; + use test_case::test_case; + use test_utils::{test_write_free_area, test_write_header}; + + #[test_case(&[0x01, 0x01, 0x01, 0x2a], Some((area_index!(1), 42)); "old format")] + // StoredArea::new(12, Area::::Free(FreeArea::new(None))); + #[test_case(&[0x02, 0x01, 0x00], Some((area_index!(2), 0)); "none")] + #[test_case(&[0x03, 0xff, 0x2b], Some((area_index!(3), 43)); "new format")] + #[test_case(&[0x03, 0x44, 0x55], None; "garbage")] + #[test_case( + &[0x03, 0x01, 0x01, 0xfd, 0xe0, 0xa2, 0x6d, 0x27, 0x6e, 0x00, 0x00, 0x00, 0x0d, 0x09, 0x03, 0x00], + Some((area_index!(3), 0x6e_276d_a2e0)); + "old format with u64 address (issue #1146)" + )] + fn test_free_list_format(reader: &[u8], expected: Option<(AreaIndex, u64)>) { + let expected = + expected.map(|(index, addr)| (FreeArea::new(LinearAddress::new(addr)), index)); + let result = FreeArea::from_storage_reader(reader).ok(); + assert_eq!(result, expected, "Failed to parse FreeArea from {reader:?}"); + } + + #[test] + // Create a random free list and test that `FreeListIterator` is able to traverse all the free areas + fn free_list_iterator() { + let mut rng = crate::SeededRng::from_env_or_random(); + let memstore = MemStore::new(vec![]); + let nodestore = NodeStore::new_empty_committed(memstore.into()); + + let area_index = rng.random_range(0..AreaIndex::NUM_AREA_SIZES as u8); + let area_index_type = AreaIndex::try_from(area_index).unwrap(); + let area_size = area_index_type.size(); + + // create a random free list scattered across the storage + let offsets = (1..100u64) + .map(|i| i * area_size) + .choose_multiple(&mut rng, 10); + for (cur, next) in offsets.iter().zip(offsets.iter().skip(1)) { + test_utils::test_write_free_area( + &nodestore, + Some(LinearAddress::new(*next).unwrap()), + area_index_type, + *cur, + ); + } + test_utils::test_write_free_area( + &nodestore, + None, + area_index_type, + *offsets.last().unwrap(), + ); + + // test iterator from a random starting point + let skip = rng.random_range(0..offsets.len()); + let mut iterator = offsets.into_iter().skip(skip); + let start = iterator.next().unwrap(); + let mut free_list_iter = FreeListIterator::new( + nodestore.storage.as_ref(), + area_index_type, + LinearAddress::new(start), + FreeListParent::FreeListHead(area_index_type), + ); + assert_eq!( + free_list_iter.next().unwrap().unwrap(), + (LinearAddress::new(start).unwrap(), area_index_type) + ); + + for offset in iterator { + assert_eq!( + free_list_iter.next().unwrap().unwrap(), + (LinearAddress::new(offset).unwrap(), area_index_type) + ); + } + + assert!(free_list_iter.next().is_none()); + } + + // Create two free lists and check that `free_list_iter_with_metadata` correctly returns the free areas and their parents + #[test] + fn free_list_iter_with_metadata() { + let rng = crate::SeededRng::from_env_or_random(); + let memstore = MemStore::new(vec![]); + let mut nodestore = NodeStore::new_empty_committed(memstore.into()); + + let mut free_lists = FreeLists::default(); + let mut offset = NodeStoreHeader::SIZE; + + // first free list + let area_index1 = + AreaIndex::try_from(rng.random_range(0..AreaIndex::NUM_AREA_SIZES as u8)).unwrap(); + let area_size1 = area_index1.size(); + let mut next_free_block1 = None; + + test_write_free_area(&nodestore, next_free_block1, area_index1, offset); + let free_list1_area2 = LinearAddress::new(offset).unwrap(); + next_free_block1 = Some(free_list1_area2); + offset += area_size1; + + test_write_free_area(&nodestore, next_free_block1, area_index1, offset); + let free_list1_area1 = LinearAddress::new(offset).unwrap(); + next_free_block1 = Some(free_list1_area1); + offset += area_size1; + + free_lists[area_index1.as_usize()] = next_free_block1; + + // second free list + let area_index2 = AreaIndex::new( + (area_index1.get() + rng.random_range(1..AreaIndex::NUM_AREA_SIZES as u8)) + % AreaIndex::NUM_AREA_SIZES as u8, + ) + .unwrap(); // make sure the second free list is different from the first + assert_ne!(area_index1, area_index2); + let area_size2 = area_index2.size(); + let mut next_free_block2 = None; + + test_write_free_area(&nodestore, next_free_block2, area_index2, offset); + let free_list2_area2 = LinearAddress::new(offset).unwrap(); + next_free_block2 = Some(free_list2_area2); + offset += area_size2; + + test_write_free_area(&nodestore, next_free_block2, area_index2, offset); + let free_list2_area1 = LinearAddress::new(offset).unwrap(); + next_free_block2 = Some(free_list2_area1); + offset += area_size2; + + free_lists[area_index2.as_usize()] = next_free_block2; + + // write header + test_write_header(&mut nodestore, offset, None, free_lists); + + // test iterator + let mut free_list_iter = nodestore.free_list_iter(AreaIndex::MIN); + + // expected + let expected_free_list1 = vec![ + ( + FreeAreaWithMetadata { + addr: free_list1_area1, + area_index: area_index1, + free_list_id: area_index1, + }, + FreeListParent::FreeListHead(area_index1), + ), + ( + FreeAreaWithMetadata { + addr: free_list1_area2, + area_index: area_index1, + free_list_id: area_index1, + }, + FreeListParent::PrevFreeArea { + area_size_idx: area_index1, + parent_addr: free_list1_area1, + }, + ), + ]; + + let expected_free_list2 = vec![ + ( + FreeAreaWithMetadata { + addr: free_list2_area1, + area_index: area_index2, + free_list_id: area_index2, + }, + FreeListParent::FreeListHead(area_index2), + ), + ( + FreeAreaWithMetadata { + addr: free_list2_area2, + area_index: area_index2, + free_list_id: area_index2, + }, + FreeListParent::PrevFreeArea { + area_size_idx: area_index2, + parent_addr: free_list2_area1, + }, + ), + ]; + + let mut expected_iterator = if area_index1 < area_index2 { + expected_free_list1.into_iter().chain(expected_free_list2) + } else { + expected_free_list2.into_iter().chain(expected_free_list1) + }; + + loop { + let next = free_list_iter.next_with_metadata(); + let Some((expected, expected_parent)) = expected_iterator.next() else { + assert!(next.is_none()); + break; + }; + + let (next, next_parent) = next.unwrap(); + assert_eq!(next.unwrap(), expected); + assert_eq!(next_parent, expected_parent); + } + } + + #[test] + #[expect(clippy::arithmetic_side_effects)] + fn free_lists_iter_skip_to_next_free_list() { + use test_utils::{test_write_free_area, test_write_header}; + + const AREA_INDEX1: AreaIndex = area_index!(3); + const AREA_INDEX1_PLUS_1: AreaIndex = area_index!(4); + const AREA_INDEX2: AreaIndex = area_index!(5); + const AREA_INDEX2_PLUS_1: AreaIndex = area_index!(6); + + let memstore = MemStore::new(vec![]); + let mut nodestore = NodeStore::new_empty_committed(memstore.into()); + + let mut free_lists = FreeLists::default(); + let mut offset = NodeStoreHeader::SIZE; + + // first free list + let area_size1 = AREA_INDEX1.size(); + let mut next_free_block1 = None; + + test_write_free_area(&nodestore, next_free_block1, AREA_INDEX1, offset); + let free_list1_area2 = LinearAddress::new(offset).unwrap(); + next_free_block1 = Some(free_list1_area2); + offset += area_size1; + + test_write_free_area(&nodestore, next_free_block1, AREA_INDEX1, offset); + let free_list1_area1 = LinearAddress::new(offset).unwrap(); + next_free_block1 = Some(free_list1_area1); + offset += area_size1; + + free_lists[AREA_INDEX1.as_usize()] = next_free_block1; + + // second free list + assert_ne!(AREA_INDEX1, AREA_INDEX2); + let area_size2 = AREA_INDEX2.size(); + let mut next_free_block2 = None; + + test_write_free_area(&nodestore, next_free_block2, AREA_INDEX2, offset); + let free_list2_area2 = LinearAddress::new(offset).unwrap(); + next_free_block2 = Some(free_list2_area2); + offset += area_size2; + + test_write_free_area(&nodestore, next_free_block2, AREA_INDEX2, offset); + let free_list2_area1 = LinearAddress::new(offset).unwrap(); + next_free_block2 = Some(free_list2_area1); + offset += area_size2; + + free_lists[AREA_INDEX2.as_usize()] = next_free_block2; + + // write header + test_write_header(&mut nodestore, offset, None, free_lists); + + // test iterator + let mut free_list_iter = nodestore.free_list_iter(AreaIndex::MIN); + + // start at the first free list + assert_eq!( + free_list_iter.current_free_list.as_ref().unwrap().0, + AreaIndex::MIN + ); + let (next, next_parent) = free_list_iter.next_with_metadata().unwrap(); + assert_eq!( + next.unwrap(), + FreeAreaWithMetadata { + addr: free_list1_area1, + area_index: AREA_INDEX1, + free_list_id: AREA_INDEX1, + }, + ); + assert_eq!(next_parent, FreeListParent::FreeListHead(AREA_INDEX1)); + // `next_with_metadata` moves the iterator to the first free list that is not empty + assert_eq!( + free_list_iter.current_free_list.as_ref().unwrap().0, + AREA_INDEX1 + ); + free_list_iter.move_to_next_free_list(); + // `move_to_next_free_list` moves the iterator to the next free list + assert_eq!( + free_list_iter.current_free_list.as_ref().unwrap().0, + AREA_INDEX1_PLUS_1 + ); + let (next, next_parent) = free_list_iter.next_with_metadata().unwrap(); + assert_eq!( + next.unwrap(), + FreeAreaWithMetadata { + addr: free_list2_area1, + area_index: AREA_INDEX2, + free_list_id: AREA_INDEX2, + }, + ); + assert_eq!(next_parent, FreeListParent::FreeListHead(AREA_INDEX2)); + // `next_with_metadata` moves the iterator to the first free list that is not empty + assert_eq!( + free_list_iter.current_free_list.as_ref().unwrap().0, + AREA_INDEX2 + ); + free_list_iter.move_to_next_free_list(); + // `move_to_next_free_list` moves the iterator to the next free list + assert_eq!( + free_list_iter.current_free_list.as_ref().unwrap().0, + AREA_INDEX2_PLUS_1 + ); + assert!(free_list_iter.next_with_metadata().is_none()); + // since no more non-empty free lists, `move_to_next_free_list` moves the iterator to the end + assert!(free_list_iter.current_free_list.is_none()); + free_list_iter.move_to_next_free_list(); + // `move_to_next_free_list` will do nothing since we are already at the end + assert!(free_list_iter.current_free_list.is_none()); + assert!(free_list_iter.next_with_metadata().is_none()); + } + + #[test] + const fn la_const_expr_tests() { + // these are const expr + let _ = const { LinearAddress::new(0) }; + let _ = const { LinearAddress::new(1).unwrap().advance(1u64) }; + } + + #[test] + const fn ai_const_expr_tests() { + let _ = const { AreaIndex::new(1) }; + let _ = const { area_index!(1) }; + } +} diff --git a/firewood/storage/src/nodestore/hash.rs b/firewood/storage/src/nodestore/hash.rs new file mode 100644 index 000000000000..c7187168be74 --- /dev/null +++ b/firewood/storage/src/nodestore/hash.rs @@ -0,0 +1,285 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! # Hash Module +//! +//! This module contains all node hashing functionality for the nodestore, including +//! specialized support for Ethereum-compatible hash processing. + +use crate::hashednode::hash_node; +use crate::linear::FileIoError; +use crate::logger::trace; +use crate::node::Node; +use crate::{Child, HashType, MaybePersistedNode, NodeStore, Path, ReadableStorage, SharedNode}; +#[cfg(feature = "ethhash")] +use crate::{Children, PathComponent}; + +use super::NodeReader; + +use std::ops::{Deref, DerefMut}; + +/// Wrapper around a path that makes sure we truncate what gets extended to the path after it goes out of scope +/// This allows the same memory space to be reused for different path prefixes +#[derive(Debug)] +struct PathGuard<'a> { + path: &'a mut Path, + original_length: usize, +} + +impl<'a> PathGuard<'a> { + fn new(path: &'a mut PathGuard<'_>) -> Self { + Self { + original_length: path.0.len(), + path: &mut path.path, + } + } + + fn from_path(path: &'a mut Path) -> Self { + Self { + original_length: path.0.len(), + path, + } + } +} + +impl Drop for PathGuard<'_> { + fn drop(&mut self) { + self.path.0.truncate(self.original_length); + } +} + +impl Deref for PathGuard<'_> { + type Target = Path; + fn deref(&self) -> &Self::Target { + self.path + } +} + +impl DerefMut for PathGuard<'_> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.path + } +} + +/// Classified children for ethereum hash processing +#[cfg(feature = "ethhash")] +pub(super) struct ClassifiedChildren<'a> { + pub(super) unhashed: Vec<(PathComponent, Node)>, + pub(super) hashed: Vec<(PathComponent, (MaybePersistedNode, &'a mut HashType))>, +} + +impl NodeStore +where + NodeStore: NodeReader, +{ + /// Helper function to classify children for ethereum hash processing + /// We have some special cases based on the number of children + /// and whether they are hashed or unhashed, so we need to classify them. + #[cfg(feature = "ethhash")] + pub(super) fn ethhash_classify_children<'a>( + &self, + children: &'a mut Children>, + ) -> ClassifiedChildren<'a> { + children.into_iter().fold( + ClassifiedChildren { + unhashed: Vec::new(), + hashed: Vec::new(), + }, + |mut acc, (idx, child)| { + match child { + None => {} + Some(Child::AddressWithHash(a, h)) => { + // Convert address to MaybePersistedNode + let maybe_persisted_node = MaybePersistedNode::from(*a); + acc.hashed.push((idx, (maybe_persisted_node, h))); + } + Some(Child::Node(node)) => acc.unhashed.push((idx, node.clone())), + Some(Child::MaybePersisted(maybe_persisted, h)) => { + // For MaybePersisted, we need to get the address if it's persisted + if let Some(addr) = maybe_persisted.as_linear_address() { + let maybe_persisted_node = MaybePersistedNode::from(addr); + acc.hashed.push((idx, (maybe_persisted_node, h))); + } else { + // If not persisted, we need to get the node to hash it + let node = maybe_persisted + .as_shared_node(&self) + .expect("will never fail for unpersisted nodes"); + acc.unhashed.push((idx, node.deref().clone())); + } + } + } + acc + }, + ) + } + + /// Hashes the given `node` and the subtree rooted at it. The `root_path` should be empty + /// if this is called from the root, or it should include the partial path if this is called + /// on a subtrie. Returns the hashed node and its hash. + /// + /// # Errors + /// + /// Can return a `FileIoError` if it is unable to read a node that it is hashing. + pub fn hash_helper( + #[cfg(feature = "ethhash")] &self, + node: Node, + mut root_path: Path, + ) -> Result<(MaybePersistedNode, HashType), FileIoError> { + #[cfg(not(feature = "ethhash"))] + let res = Self::hash_helper_inner(node, PathGuard::from_path(&mut root_path))?; + #[cfg(feature = "ethhash")] + let res = self.hash_helper_inner(node, PathGuard::from_path(&mut root_path), None)?; + Ok(res) + } + + /// Recursive helper that hashes the given `node` and the subtree rooted at it. + /// This function takes a mut `node` to update the hash in place. + /// The `path_prefix` is also mut because we will extend it to the path of the child we are hashing in recursive calls - it will be restored after the recursive call returns. + /// The `num_siblings` is the number of children of the parent node, which includes this node. + fn hash_helper_inner( + #[cfg(feature = "ethhash")] &self, + mut node: Node, + mut path_prefix: PathGuard<'_>, + #[cfg(feature = "ethhash")] fake_root_extra_nibble: Option, + ) -> Result<(MaybePersistedNode, HashType), FileIoError> { + // If this is a branch, find all unhashed children and recursively hash them. + trace!("hashing {node:?} at {path_prefix:?}"); + if let Node::Branch(ref mut b) = node { + // special case code for ethereum hashes at the account level + #[cfg(feature = "ethhash")] + let make_fake_root = if path_prefix.0.len().saturating_add(b.partial_path.0.len()) == 64 + { + // looks like we're at an account branch + // tally up how many hashes we need to deal with + let ClassifiedChildren { + unhashed, + mut hashed, + } = self.ethhash_classify_children(&mut b.children); + trace!("hashed {hashed:?} unhashed {unhashed:?}"); + // we were left with one hashed node that must be rehashed + if let [(child_idx, (child_node, child_hash))] = &mut hashed[..] { + // Extract the address from the MaybePersistedNode + let addr: crate::LinearAddress = child_node + .as_linear_address() + .expect("hashed node should be persisted"); + let mut hashable_node = self.read_node(addr)?.deref().clone(); + let hash = { + let mut path_guard = PathGuard::new(&mut path_prefix); + path_guard.0.extend(b.partial_path.0.iter().copied()); + if unhashed.is_empty() { + hashable_node.update_partial_path(Path::from_nibbles_iterator( + std::iter::once(child_idx.as_u8()) + .chain(hashable_node.partial_path().0.iter().copied()), + )); + } else { + path_guard.0.push(child_idx.as_u8()); + } + hash_node(&hashable_node, &path_guard) + }; + **child_hash = hash; + } + // handle the single-child case for an account special below + if hashed.is_empty() && unhashed.len() == 1 { + Some(unhashed.last().expect("only one").0.as_u8()) + } else { + None + } + } else { + // not a single child + None + }; + + // branch children cases: + // 1. 1 child, already hashed + // 2. >1 child, already hashed, + // 3. 1 hashed child, 1 unhashed child + // 4. 0 hashed, 1 unhashed <-- handle child special + // 5. 1 hashed, >0 unhashed <-- rehash case + // 6. everything already hashed + + for (nibble, child) in &mut b.children { + // If this is empty or already hashed, we're done + // Empty matches None, and non-Node types match Some(None) here, so we want + // Some(Some(node)) + let Some(child_node) = child.as_mut().and_then(|child| child.as_mut_node()) else { + continue; + }; + + // remove the child from the children array, we will replace it with a hashed variant + let child_node = std::mem::take(child_node); + + // Hash this child and update + let (child_node, child_hash) = { + // we extend and truncate path_prefix to reduce memory allocations] + let mut child_path_prefix = PathGuard::new(&mut path_prefix); + child_path_prefix.0.extend(b.partial_path.0.iter().copied()); + #[cfg(feature = "ethhash")] + if make_fake_root.is_none() { + // we don't push the nibble there is only one unhashed child and + // we're on an account + child_path_prefix.0.push(nibble.as_u8()); + } + #[cfg(not(feature = "ethhash"))] + child_path_prefix.0.push(nibble.as_u8()); + #[cfg(feature = "ethhash")] + let (child_node, child_hash) = + self.hash_helper_inner(child_node, child_path_prefix, make_fake_root)?; + #[cfg(not(feature = "ethhash"))] + let (child_node, child_hash) = + Self::hash_helper_inner(child_node, child_path_prefix)?; + + (child_node, child_hash) + }; + + *child = Some(Child::MaybePersisted(child_node, child_hash)); + trace!("child now {child:?}"); + } + } + // At this point, we either have a leaf or a branch with all children hashed. + // if the encoded child hash <32 bytes then we use that RLP + + #[cfg(feature = "ethhash")] + // if we have a child that is the only child of an account branch, we will hash this child as if it + // is a root node. This means we have to take the nibble from the parent and prefix it to the partial path + let hash = if let Some(nibble) = fake_root_extra_nibble { + let mut fake_root = node.clone(); + trace!("old node: {fake_root:?}"); + fake_root.update_partial_path(Path::from_nibbles_iterator( + std::iter::once(nibble).chain(fake_root.partial_path().0.iter().copied()), + )); + trace!("new node: {fake_root:?}"); + hash_node(&fake_root, &path_prefix) + } else { + hash_node(&node, &path_prefix) + }; + + #[cfg(not(feature = "ethhash"))] + let hash = hash_node(&node, &path_prefix); + + Ok((SharedNode::new(node).into(), hash)) + } + + #[cfg(feature = "ethhash")] + pub(crate) fn compute_node_ethhash( + node: &Node, + path_prefix: &Path, + have_peers: bool, + ) -> HashType { + if path_prefix.0.len() == 65 && !have_peers { + // This is the special case when this node is the only child of an account + // - 64 nibbles for account + 1 nibble for its position in account branch node + let mut fake_root = node.clone(); + fake_root.update_partial_path(Path::from_nibbles_iterator( + path_prefix + .0 + .last() + .into_iter() + .chain(fake_root.partial_path().0.iter()) + .copied(), + )); + hash_node(&fake_root, path_prefix) + } else { + hash_node(node, path_prefix) + } + } +} diff --git a/firewood/storage/src/nodestore/header.rs b/firewood/storage/src/nodestore/header.rs new file mode 100644 index 000000000000..8364ca9e573a --- /dev/null +++ b/firewood/storage/src/nodestore/header.rs @@ -0,0 +1,349 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! # Header Module +//! +//! This module defines the nodestore header structure and validation logic for ensuring +//! database compatibility across different versions and configurations. +//! +//! ## Header Structure +//! +//! The `NodeStoreHeader` is stored at the beginning of every nodestore file and contains: +//! +//! - **Version String** - Human-readable firewood version (e.g., "firewood 0.1.0") +//! - **Endianness Test** - Detects byte order mismatches between platforms +//! - **Root Address** - Points to the merkle trie root node (if any) +//! - **Storage Size** - Total allocated storage space +//! - **Free Lists** - Array of free space linked list heads for each area size +//! +//! ## Storage Layout +//! +//! The header occupies the first 2048 bytes of storage: +//! - Fixed size for alignment with disk block boundaries +//! - Zero-padded to full size for consistent layout +//! - Uses C-compatible representation for cross-language access +//! + +use bytemuck_derive::{Pod, Zeroable}; +use std::io::{Error, ErrorKind}; + +use super::alloc::FreeLists; +use super::primitives::{LinearAddress, area_size_hash}; +use crate::logger::{debug, trace}; + +/// Can be used by filesystem tooling such as "file" to identify +/// the version of firewood used to create this `NodeStore` file. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Zeroable, Pod)] +#[repr(transparent)] +pub struct Version { + bytes: [u8; 16], +} + +impl Version { + const SIZE: usize = size_of::(); + + /// Version >= 0.0.4 + /// + /// Increase as needed to set the minimum required version of `firewood-storage` for + /// compatibility checks. + /// + /// We may want to add migrations if we need to add a breaking change. + const BASE_VERSION: semver::Comparator = semver::Comparator { + op: semver::Op::GreaterEq, + major: 0, + minor: Some(0), + patch: Some(4), + pre: semver::Prerelease::EMPTY, + }; + + /// Validates that the version identifier is valid and compatible with the current + /// build of firewood. + /// + /// # Errors + /// + /// - If the token contains invalid utf-8 bytes (nul is allowed). + /// - If the token does not start with "firewood ". + /// - If the version is not parsable by [`semver::Version`]. + /// - If the version is not compatible with the current build of firewood. + /// - Currently, the minimum required version is 0.0.4. + pub fn validate(&self) -> Result<(), Error> { + let version = std::str::from_utf8(&self.bytes).map_err(|e| { + Error::new( + ErrorKind::InvalidData, + format!( + "Invalid database version: invalid utf-8: {e} (original: [{:032x}])", + u128::from_be_bytes(self.bytes) + ), + ) + })?; + + // strip trailling nuls as they're only for padding + let version = version.trim_end_matches('\0'); + + // strip magic prefix or error + let version = version.strip_prefix("firewood ").ok_or_else(|| { + Error::new( + ErrorKind::InvalidData, + format!( + "Invalid database version: does not start with magic 'firewood ': {version}", + ), + ) + })?; + + // Version strings from CARGO_PKG_VERSION are guaranteed to be parsable by + // semver (cargo uses the same library). + let version = semver::Version::parse(version).map_err(|e| { + Error::new( + ErrorKind::InvalidData, + format!( + "Invalid version string: unable to parse `{version}` as a semver string: {e}" + ), + ) + })?; + + // verify base compatibility version + if !Self::BASE_VERSION.matches(&version) { + return Err(Error::new( + ErrorKind::InvalidData, + format!( + "Database was created with firewood version {version}; however, this build of firewood requires version {}", + Self::BASE_VERSION, + ), + )); + } + + debug!( + "Database version is valid: {version} {}", + Self::BASE_VERSION + ); + Ok(()) + } + + /// Construct a [`Version`] instance for the current build of firewood. + pub fn new() -> Self { + // Note that with this magic token of 9 bytes, we can store a version string of + // up to 7 bytes. If we always include the major, minor, and patch versions, + // then no more than two of three can be 2 digits long. + const VERSION_STR: &str = concat!("firewood ", env!("CARGO_PKG_VERSION")); + const { + assert!( + VERSION_STR.len() <= Version::SIZE, + concat!( + "Database version string `firewood ", + env!("CARGO_PKG_VERSION"), + "` is too long for the Version struct! Update Cargo.toml or modify this code.", + ), + ); + } + + // pad with nul bytes + let mut bytes = [0u8; Version::SIZE]; + bytes + .get_mut(..VERSION_STR.len()) + .expect("must fit") + .copy_from_slice(VERSION_STR.as_bytes()); + + Self { bytes } + } +} + +/// Persisted metadata for a `NodeStore`. +/// The [`NodeStoreHeader`] is at the start of the `ReadableStorage`. +#[derive(Copy, Debug, PartialEq, Eq, Clone, Zeroable, Pod)] +#[repr(C)] +pub struct NodeStoreHeader { + /// Identifies the version of firewood used to create this `NodeStore`. + version: Version, + /// always "1"; verifies endianness + endian_test: u64, + size: u64, + /// Element i is the pointer to the first free block of size `BLOCK_SIZES[i]`. + free_lists: FreeLists, + root_address: Option, + /// The hash of the area sizes used in this database to prevent someone from changing the + /// area sizes and trying to read old databases with the wrong area sizes. + area_size_hash: [u8; 32], + /// Whether ethhash was enabled when this database was created. + ethhash: u64, +} + +impl Default for NodeStoreHeader { + fn default() -> Self { + Self::new() + } +} + +impl NodeStoreHeader { + /// The first SIZE bytes of the `ReadableStorage` are reserved for the + /// [`NodeStoreHeader`]. + /// We also want it aligned to a disk block + pub const SIZE: u64 = 2048; + + // Compile-time assertion that SIZE is large enough for the header + const _ASSERT_SIZE: () = assert!(Self::SIZE as usize >= std::mem::size_of::()); + + /// Deserialize a `NodeStoreHeader` from bytes using bytemuck + pub fn from_bytes(bytes: &[u8]) -> &Self { + bytemuck::from_bytes(bytes) + } + + pub fn new() -> Self { + Self::with_root(None) + } + + pub fn with_root(root_address: Option) -> Self { + Self { + // The store just contains the header at this point + size: Self::SIZE, + endian_test: 1, + root_address, + version: Version::new(), + free_lists: Default::default(), + area_size_hash: area_size_hash() + .as_slice() + .try_into() + .expect("sizes should match"), + #[cfg(feature = "ethhash")] + ethhash: 1, + #[cfg(not(feature = "ethhash"))] + ethhash: 0, + } + } + + pub fn validate(&self) -> Result<(), Error> { + trace!("Checking version..."); + self.version.validate()?; + + trace!("Checking endianness..."); + self.validate_endian_test()?; + + trace!("Checking area size hash..."); + self.validate_area_size_hash()?; + + trace!("Checking if db ethhash flag matches build feature..."); + self.validate_ethhash()?; + + Ok(()) + } + + /// Get the size of the nodestore + pub const fn size(&self) -> u64 { + self.size + } + + /// Set the size of the nodestore + pub const fn set_size(&mut self, size: u64) { + self.size = size; + } + + /// Get the free lists + pub const fn free_lists(&self) -> &FreeLists { + &self.free_lists + } + + /// Get mutable access to the free lists + pub const fn free_lists_mut(&mut self) -> &mut FreeLists { + &mut self.free_lists + } + + /// Get the root address + pub const fn root_address(&self) -> Option { + self.root_address + } + + /// Set the root address + pub const fn set_root_address(&mut self, root_address: Option) { + self.root_address = root_address; + } + + /// Get the offset of the `free_lists` field for use with `offset_of`! + pub const fn free_lists_offset() -> u64 { + std::mem::offset_of!(NodeStoreHeader, free_lists) as u64 + } + + fn validate_endian_test(&self) -> Result<(), Error> { + if self.endian_test == 1 { + Ok(()) + } else { + Err(Error::new( + ErrorKind::InvalidData, + "Database cannot be opened due to difference in endianness", + )) + } + } + + fn validate_area_size_hash(&self) -> Result<(), Error> { + if self.area_size_hash == area_size_hash().as_slice() { + Ok(()) + } else { + Err(Error::new( + ErrorKind::InvalidData, + "Database cannot be opened due to difference in area size hash", + )) + } + } + + #[cfg(not(feature = "ethhash"))] + fn validate_ethhash(&self) -> Result<(), Error> { + if self.ethhash == 0 { + Ok(()) + } else { + Err(Error::new( + ErrorKind::InvalidData, + "Database cannot be opened as it was created with ethhash enabled", + )) + } + } + + #[cfg(feature = "ethhash")] + fn validate_ethhash(&self) -> Result<(), Error> { + if self.ethhash == 1 { + Ok(()) + } else { + Err(Error::new( + ErrorKind::InvalidData, + "Database cannot be opened as it was created without ethhash enabled", + )) + } + } +} + +#[cfg(test)] +#[expect(clippy::unwrap_used)] +mod tests { + use super::*; + use crate::linear::ReadableStorage; + use crate::linear::memory::MemStore; + use crate::nodestore::NodeStore; + use std::io::Read; + use test_case::test_case; + + #[test] + fn test_version_new_is_valid() { + Version::new() + .validate() + .expect("Version::new() should always be valid"); + } + + #[test_case(*b"invalid\0\0\0\0\0\0\0\0\0")] + #[test_case(*b"avalanche 0.1.0\0")] + #[test_case(*b"firewood 0.0.1\0\0")] + fn test_invalid_version_strings(bytes: [u8; 16]) { + assert!(Version { bytes }.validate().is_err()); + } + + #[test] + fn test_node_store_new() { + let memstore = MemStore::new(vec![]); + let node_store = NodeStore::new_empty_proposal(memstore.into()); + + // Check the empty header is written at the start of the ReadableStorage. + let mut header_stream = node_store.storage.stream_from(0).unwrap(); + let mut header_bytes = vec![0u8; std::mem::size_of::()]; + header_stream.read_exact(&mut header_bytes).unwrap(); + let header = NodeStoreHeader::from_bytes(&header_bytes); + assert_eq!(header.version, Version::new()); + let empty_free_list: FreeLists = Default::default(); + assert_eq!(*header.free_lists(), empty_free_list); + } +} diff --git a/firewood/storage/src/nodestore/mod.rs b/firewood/storage/src/nodestore/mod.rs new file mode 100644 index 000000000000..c2972ca05422 --- /dev/null +++ b/firewood/storage/src/nodestore/mod.rs @@ -0,0 +1,1079 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! # `NodeStore` Module +//! +//! The main module for nodestore functionality, containing core types, traits, and operations +//! for managing merkle trie data in Firewood. +//! +//! ## Module Structure +//! +//! The nodestore module is organized into several specialized submodules: +//! +//! - [`alloc`] - Memory allocation and area management for nodes in the linear store +//! - [`hash`] - Node hashing functionality, including specialized ethereum hash processing +//! - [`header`] - `NodeStore` header structure and validation logic +//! - [`persist`] - Persistence operations for writing nodes and metadata to storage +//! +//! ## Types +//! +//! This module defines the primary types for nodestore operations: +//! +//! - [`NodeStore`] - The main nodestore container parameterized by state type and storage +//! +//! `T` is one of the following state types: +//! - [`Committed`] - For a committed revision with no in-memory changes +//! - [`MutableProposal`] - For a proposal being actively modified with in-memory nodes +//! - [`ImmutableProposal`] - For a proposal that has been hashed and assigned addresses +//! +//! The nodestore follows a lifecycle pattern: +//! ```text +//! Committed -> MutableProposal -> ImmutableProposal -> Committed +//! ``` +//! +//! ## Traits +//! +//! - **`NodeReader`** - Interface for reading nodes by address +//! - **`RootReader`** - Interface for accessing the root node +//! - **`HashedNodeReader`** - Interface for immutable merkle trie access +//! - **`Parentable`** - Trait for nodestores that can have children + +pub(crate) mod alloc; +pub(crate) mod hash; +pub(crate) mod header; +pub(crate) mod persist; +#[cfg(feature = "io-uring")] +pub(crate) mod persist_io_uring; +pub(crate) mod primitives; + +use crate::linear::OffsetReader; +use crate::logger::trace; +use crate::node::branch::ReadSerializable as _; +use smallvec::SmallVec; +use std::fmt::Debug; +use std::io::{Error, ErrorKind, Read}; + +// Re-export types from alloc module +pub use alloc::NodeAllocator; +pub use primitives::{AreaIndex, LinearAddress}; + +// Re-export types from header module +pub use header::NodeStoreHeader; + +/// The [`NodeStore`] handles the serialization of nodes and +/// free space management of nodes in the page store. It lays out the format +/// of the [`PageStore`]. More specifically, it places a [`FileIdentifyingMagic`] +/// and a [`FreeSpaceHeader`] at the beginning +/// +/// Nodestores represent a revision of the trie. There are three types of nodestores: +/// - Committed: A committed revision of the trie. It has no in-memory changes. +/// - `MutableProposal`: A proposal that is still being modified. It has some nodes in memory. +/// - `ImmutableProposal`: A proposal that has been hashed and assigned addresses. It has no in-memory changes. +/// +/// The general lifecycle of nodestores is as follows: +/// ```mermaid +/// flowchart TD +/// subgraph subgraph["Committed Revisions"] +/// L("Latest Nodestore<Committed, S>") --- |...|O("Oldest NodeStore<Committed, S>") +/// end +/// O --> E("Expire") +/// L --> |start propose|M("NodeStore<ProposedMutable, S>") +/// M --> |finish propose + hash|I("NodeStore<ProposedImmutable, S>") +/// I --> |commit|N("New commit NodeStore<Committed, S>") +/// style E color:#FFFFFF, fill:#AA00FF, stroke:#AA00FF +/// ``` +use std::mem::take; +use std::ops::Deref; +use std::sync::Arc; + +use crate::hashednode::hash_node; +use crate::node::Node; +use crate::node::persist::MaybePersistedNode; +use crate::{ + CacheReadStrategy, Child, FileIoError, HashType, Path, ReadableStorage, SharedNode, TrieHash, +}; + +use super::linear::WritableStorage; + +/// Initial size for the bump allocator used in node serialization batches. +/// Set to the maximum area size to minimize allocations for large nodes. +const INITIAL_BUMP_SIZE: usize = AreaIndex::MAX_AREA_SIZE as usize; + +impl NodeStore { + /// Open an existing [`NodeStore`] + /// Assumes the header is written in the [`ReadableStorage`]. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the header cannot be read or validated. + pub fn open(storage: Arc) -> Result { + let mut stream = storage.stream_from(0)?; + let mut header_bytes = vec![0u8; std::mem::size_of::()]; + if let Err(e) = stream.read_exact(&mut header_bytes) { + if e.kind() == std::io::ErrorKind::UnexpectedEof { + return Ok(Self::new_empty_committed(storage.clone())); + } + return Err(storage.file_io_error(e, 0, Some("header read".to_string()))); + } + + drop(stream); + + let header = *NodeStoreHeader::from_bytes(&header_bytes); + header + .validate() + .map_err(|e| storage.file_io_error(e, 0, Some("header read".to_string())))?; + + let mut nodestore = Self { + header, + kind: Committed { + deleted: Box::default(), + root: None, + }, + storage, + }; + + if let Some(root_address) = header.root_address() { + let node = nodestore.read_node_from_disk(root_address, "open"); + let root_hash = node.map(|n| hash_node(&n, &Path(SmallVec::default())))?; + nodestore.kind.root = Some(Child::AddressWithHash(root_address, root_hash)); + } + + Ok(nodestore) + } + + /// Create a new, empty, Committed [`NodeStore`] and clobber + /// the underlying store with an empty freelist and no root node + pub fn new_empty_committed(storage: Arc) -> Self { + let header = NodeStoreHeader::new(); + + Self { + header, + storage, + kind: Committed { + deleted: Box::default(), + root: None, + }, + } + } + + /// Create a new Committed [`NodeStore`] with a specified root node. + /// + /// This constructor is used when you have an existing root node at a known + /// address and hash, typically when reconstructing a [`NodeStore`] from + /// a committed state. The `latest_nodestore` provides access to the underlying + /// storage backend containing the persisted trie data. + /// + /// ## Panics + /// + /// Panics in debug builds if the hash of the node at `root_address` does + /// not equal `root_hash`. + #[must_use] + pub fn with_root( + root_hash: HashType, + root_address: LinearAddress, + latest_nodestore: Arc>, + ) -> Self { + let header = NodeStoreHeader::with_root(Some(root_address)); + let storage = latest_nodestore.storage.clone(); + + let nodestore = NodeStore { + header, + kind: Committed { + deleted: Box::default(), + root: Some(Child::AddressWithHash(root_address, root_hash)), + }, + storage, + }; + + debug_assert_eq!( + nodestore + .root_hash() + .expect("Nodestore should have root hash"), + hash_node( + &nodestore + .read_node(root_address) + .expect("Root node read should succeed"), + &Path(SmallVec::default()) + ) + ); + + nodestore + } +} + +/// Some nodestore kinds implement Parentable. +/// +/// This means that the nodestore can have children. +/// Only [`ImmutableProposal`] and [Committed] implement this trait. +/// [`MutableProposal`] does not implement this trait because it is not a valid parent. +/// TODO: Maybe this can be renamed to `ImmutableNodestore` +pub trait Parentable { + /// Returns the parent of this nodestore. + fn as_nodestore_parent(&self) -> NodeStoreParent; + /// Returns the root hash of this nodestore. This works because all parentable nodestores have a hash + fn root_hash(&self) -> Option; + /// Returns the root node + fn root(&self) -> Option; +} + +impl Parentable for Arc { + fn as_nodestore_parent(&self) -> NodeStoreParent { + NodeStoreParent::Proposed(Arc::clone(self)) + } + fn root_hash(&self) -> Option { + self.root + .as_ref() + .and_then(|root| root.hash().cloned().map(HashType::into_triehash)) + } + fn root(&self) -> Option { + self.root.as_ref().map(Child::as_maybe_persisted_node) + } +} + +impl NodeStore, S> { + /// When an immutable proposal commits, we need to reparent any proposal that + /// has the committed proposal as it's parent + pub fn commit_reparent(&self, other: &NodeStore, S>) { + other.kind.commit_reparent(&self.kind); + } +} + +impl Parentable for Committed { + fn as_nodestore_parent(&self) -> NodeStoreParent { + NodeStoreParent::Committed( + self.root + .as_ref() + .and_then(|root| root.hash().cloned().map(HashType::into_triehash)), + ) + } + fn root_hash(&self) -> Option { + self.root + .as_ref() + .and_then(|root| root.hash().cloned().map(HashType::into_triehash)) + } + fn root(&self) -> Option { + self.root.as_ref().map(Child::as_maybe_persisted_node) + } +} + +impl NodeStore { + /// Create a new `MutableProposal` [`NodeStore`] from a parent [`NodeStore`] + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the parent root cannot be read. + pub fn new(parent: &NodeStore) -> Result { + let mut deleted = Vec::default(); + let root = if let Some(ref root) = parent.kind.root() { + deleted.push(root.clone()); + let root = root.as_shared_node(parent)?.deref().clone(); + Some(root) + } else { + None + }; + let kind = MutableProposal { + root, + deleted, + parent: parent.kind.as_nodestore_parent(), + }; + Ok(NodeStore { + header: parent.header, + kind, + storage: parent.storage.clone(), + }) + } + + /// Marks the node at `addr` as deleted in this proposal. + pub fn delete_node(&mut self, node: MaybePersistedNode) { + trace!("Pending delete at {node:?}"); + self.kind.deleted.push(node); + } + + /// Take the nodes that have been marked as deleted in this proposal. + pub fn take_deleted_nodes(&mut self) -> Vec { + take(&mut self.kind.deleted) + } + + /// Adds to the nodes deleted in this proposal. + pub fn delete_nodes(&mut self, nodes: &[MaybePersistedNode]) { + self.kind.deleted.extend_from_slice(nodes); + } + + /// Reads a node for update, marking it as deleted in this proposal. + /// We get an arc from cache (reading it from disk if necessary) then + /// copy/clone the node and return it. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the node cannot be read. + pub fn read_for_update(&mut self, node: MaybePersistedNode) -> Result { + let arc_wrapped_node = node.as_shared_node(self)?; + self.delete_node(node); + Ok((*arc_wrapped_node).clone()) + } + + /// Returns the root of this proposal. + pub const fn root_mut(&mut self) -> &mut Option { + &mut self.kind.root + } +} + +impl NodeStore { + /// Creates a new [`NodeStore`] from a root node. + #[must_use] + pub fn from_root(parent: &NodeStore, root: Option) -> Self { + NodeStore { + header: parent.header, + kind: MutableProposal { + root, + deleted: Vec::default(), + parent: parent.kind.parent.clone(), + }, + storage: parent.storage.clone(), + } + } + + /// Consumes the `NodeStore` and returns the root of the trie + #[must_use] + pub fn into_root(self) -> Option { + self.kind.root + } +} + +impl NodeStore { + /// Creates a new, empty, [`NodeStore`] and clobbers the underlying `storage` with an empty header. + /// This is used during testing and during the creation of an in-memory merkle for proofs + /// + /// # Panics + /// + /// Panics if the header cannot be written. + #[cfg(any(test, feature = "test_utils"))] + pub fn new_empty_proposal(storage: Arc) -> Self { + let header = NodeStoreHeader::new(); + let header_bytes = bytemuck::bytes_of(&header); + storage + .write(0, header_bytes) + .expect("failed to write header"); + NodeStore { + header, + kind: MutableProposal { + root: None, + deleted: Vec::default(), + parent: NodeStoreParent::Committed(None), + }, + storage, + } + } +} + +/// Reads from an immutable (i.e. already hashed) merkle trie. +pub trait HashedNodeReader: TrieReader { + /// Gets the address of the root node of an immutable merkle trie. + fn root_address(&self) -> Option; + + /// Gets the hash of the root node of an immutable merkle trie. + fn root_hash(&self) -> Option; +} + +/// Reads nodes and the root address from a merkle trie. +pub trait TrieReader: NodeReader + RootReader {} +impl TrieReader for T where T: NodeReader + RootReader {} + +/// Reads nodes from a merkle trie. +pub trait NodeReader { + /// Returns the node at `addr`. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the node cannot be read. + fn read_node(&self, addr: LinearAddress) -> Result; +} + +impl NodeReader for T +where + T: Deref, + T::Target: NodeReader, +{ + fn read_node(&self, addr: LinearAddress) -> Result { + self.deref().read_node(addr) + } +} + +impl RootReader for T +where + T: Deref, + T::Target: RootReader, +{ + fn root_node(&self) -> Option { + self.deref().root_node() + } + fn root_as_maybe_persisted_node(&self) -> Option { + self.deref().root_as_maybe_persisted_node() + } +} + +/// Reads the root of a merkle trie. +/// +/// The root may be None if the trie is empty. +pub trait RootReader { + /// Returns the root of the trie. + /// Callers that just need the node at the root should use this function. + fn root_node(&self) -> Option; + + /// Returns the root of the trie as a `MaybePersistedNode`. + /// Callers that might want to modify the root or know how it is stored + /// should use this function. + fn root_as_maybe_persisted_node(&self) -> Option; +} + +/// A committed revision of a merkle trie. +#[derive(Debug, Clone)] +pub struct Committed { + deleted: Box<[MaybePersistedNode]>, + root: Option, +} + +#[derive(Clone, Debug)] +pub enum NodeStoreParent { + Proposed(Arc), + Committed(Option), +} + +impl PartialEq for NodeStoreParent { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (NodeStoreParent::Proposed(a), NodeStoreParent::Proposed(b)) => Arc::ptr_eq(a, b), + (NodeStoreParent::Committed(a), NodeStoreParent::Committed(b)) => a == b, + _ => false, + } + } +} + +impl Eq for NodeStoreParent {} + +#[derive(Debug)] +/// Contains state for a proposed revision of the trie. +pub struct ImmutableProposal { + /// Nodes that have been deleted in this proposal. + deleted: Box<[MaybePersistedNode]>, + /// The parent of this proposal. + parent: Arc>, + /// The root of the trie in this proposal. + root: Option, +} + +impl ImmutableProposal { + /// Returns true if the parent of this proposal is committed and has the given hash. + #[must_use] + fn parent_hash_is(&self, hash: Option) -> bool { + match &*self.parent.lock() { + NodeStoreParent::Committed(root_hash) => *root_hash == hash, + NodeStoreParent::Proposed(_) => false, + } + } + + fn commit_reparent(self: &Arc, committing: &Arc) { + let mut guard = self.parent.lock(); + if let NodeStoreParent::Proposed(ref parent) = *guard + && Arc::ptr_eq(parent, committing) + { + *guard = NodeStoreParent::Committed(committing.root_hash()); + } + } +} + +/// Contains the state of a revision of a merkle trie. +/// +/// The first generic parameter is the type of the revision, which supports reading nodes from parent proposals. +/// The second generic parameter is the type of the storage used, either +/// in-memory or on-disk. +/// +/// The lifecycle of a [`NodeStore`] is as follows: +/// 1. Create a new, empty, [Committed] [`NodeStore`] using [`NodeStore::new_empty_committed`]. +/// 2. Create a [`NodeStore`] from disk using [`NodeStore::open`]. +/// 3. Create a new mutable proposal from either a [Committed] or [`ImmutableProposal`] [`NodeStore`] using [`NodeStore::new`]. +/// 4. Convert a mutable proposal to an immutable proposal using [`std::convert::TryInto`], which hashes the nodes and assigns addresses +/// 5. Convert an immutable proposal to a committed revision using [`std::convert::TryInto`], which writes the nodes to disk. + +#[derive(Debug)] +pub struct NodeStore { + // Metadata for this revision. + header: NodeStoreHeader, + /// This is one of [Committed], [`ImmutableProposal`], or [`MutableProposal`]. + kind: T, + /// Persisted storage to read nodes from. + storage: Arc, +} + +impl NodeStore { + pub(crate) const fn freelists(&self) -> &alloc::FreeLists { + self.header.free_lists() + } + + pub(crate) const fn freelists_mut(&mut self) -> &mut alloc::FreeLists { + self.header.free_lists_mut() + } +} + +/// Contains the state of a proposal that is still being modified. +#[derive(Debug)] +pub struct MutableProposal { + /// The root of the trie in this proposal. + root: Option, + /// Nodes that have been deleted in this proposal. + deleted: Vec, + parent: NodeStoreParent, +} + +impl, S: ReadableStorage> From> + for NodeStore +{ + fn from(val: NodeStore) -> Self { + NodeStore { + header: val.header, + kind: MutableProposal { + root: None, + deleted: Vec::default(), + parent: val.kind.into(), + }, + storage: val.storage, + } + } +} + +/// Commit a proposal to a new revision of the trie +impl From> for NodeStore { + fn from(val: NodeStore) -> Self { + NodeStore { + header: val.header, + kind: Committed { + deleted: val.kind.deleted.clone(), + root: val.kind.root.clone(), + }, + storage: val.storage, + } + } +} + +impl NodeStore, S> { + /// Re-export the `parent_hash_is` function of [`ImmutableProposal`]. + #[must_use] + pub fn parent_hash_is(&self, hash: Option) -> bool { + self.kind.parent_hash_is(hash) + } +} + +impl NodeStore, S> { + /// Return a Committed version of this proposal, which doesn't have any modified nodes. + /// This function is used during commit. + #[must_use] + pub fn as_committed( + &self, + current_revision: &NodeStore, + ) -> NodeStore { + NodeStore { + header: current_revision.header, + kind: Committed { + deleted: self.kind.deleted.clone(), + root: self.kind.root.clone(), + }, + storage: self.storage.clone(), + } + } +} + +impl TryFrom> + for NodeStore, S> +{ + type Error = FileIoError; + + fn try_from(val: NodeStore) -> Result { + let NodeStore { + header, + kind, + storage, + } = val; + + let mut nodestore = NodeStore { + header, + kind: Arc::new(ImmutableProposal { + deleted: kind.deleted.into(), + parent: Arc::new(parking_lot::Mutex::new(kind.parent)), + root: None, + }), + storage, + }; + + let Some(root) = kind.root else { + // This trie is now empty. + nodestore.header.set_root_address(None); + return Ok(nodestore); + }; + + // Hashes the trie with an empty path and returns the address of the new root. + #[cfg(feature = "ethhash")] + let (root, root_hash) = nodestore.hash_helper(root, Path::new())?; + #[cfg(not(feature = "ethhash"))] + let (root, root_hash) = NodeStore::::hash_helper(root, Path::new())?; + + let immutable_proposal = + Arc::into_inner(nodestore.kind).expect("no other references to the proposal"); + nodestore.kind = Arc::new(ImmutableProposal { + deleted: immutable_proposal.deleted.clone(), + parent: immutable_proposal.parent.clone(), + root: Some(Child::MaybePersisted(root, root_hash)), + }); + + Ok(nodestore) + } +} + +impl NodeReader for NodeStore { + fn read_node(&self, addr: LinearAddress) -> Result { + self.read_node_from_disk(addr, "write") + } +} + +impl NodeReader for NodeStore { + fn read_node(&self, addr: LinearAddress) -> Result { + self.read_node_from_disk(addr, "read") + } +} + +impl RootReader for NodeStore { + fn root_node(&self) -> Option { + self.kind.root.as_ref().map(|node| node.clone().into()) + } + fn root_as_maybe_persisted_node(&self) -> Option { + self.kind + .root + .as_ref() + .map(|node| SharedNode::new(node.clone()).into()) + } +} + +impl RootReader for NodeStore { + fn root_node(&self) -> Option { + // TODO: If the read_node fails, we just say there is no root; this is incorrect + self.kind + .root + .as_ref() + .map(Child::as_maybe_persisted_node) + .and_then(|node| node.as_shared_node(self).ok()) + } + fn root_as_maybe_persisted_node(&self) -> Option { + self.kind.root.as_ref().map(Child::as_maybe_persisted_node) + } +} + +impl RootReader for NodeStore, S> { + fn root_node(&self) -> Option { + // Use the MaybePersistedNode's as_shared_node method to get the root + self.kind + .root + .as_ref() + .map(Child::as_maybe_persisted_node) + .and_then(|node| node.as_shared_node(self).ok()) + } + fn root_as_maybe_persisted_node(&self) -> Option { + self.kind.root.as_ref().map(Child::as_maybe_persisted_node) + } +} + +impl HashedNodeReader for NodeStore +where + NodeStore: TrieReader, + T: Parentable, + S: ReadableStorage, +{ + fn root_address(&self) -> Option { + self.header.root_address() + } + + fn root_hash(&self) -> Option { + self.kind.root_hash() + } +} + +// TODO: return only the index since we can easily get the size from the index +fn area_index_and_size( + storage: &S, + addr: LinearAddress, +) -> Result<(AreaIndex, u64), FileIoError> { + let mut area_stream = storage.stream_from(addr.get())?; + + let index: AreaIndex = AreaIndex::new(area_stream.read_byte().map_err(|e| { + storage.file_io_error( + Error::new(ErrorKind::InvalidData, e), + addr.get(), + Some("area_index_and_size".to_string()), + ) + })?) + .ok_or_else(|| { + storage.file_io_error( + Error::new(ErrorKind::InvalidData, "invalid area index"), + addr.get(), + Some("area_index_and_size".to_string()), + ) + })?; + + let size = index.size(); + + Ok((index, size)) +} + +impl NodeStore { + /// Read a [Node] from the provided [`LinearAddress`]. + /// `addr` is the address of a `StoredArea` in the `ReadableStorage`. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the node cannot be read. + pub fn read_node_from_disk( + &self, + addr: LinearAddress, + mode: &'static str, + ) -> Result { + if let Some(node) = self.storage.read_cached_node(addr, mode) { + return Ok(node); + } + + let (node, _) = self.read_node_with_num_bytes_from_disk(addr)?; + + match self.storage.cache_read_strategy() { + CacheReadStrategy::All => { + self.storage.cache_node(addr, node.clone()); + } + CacheReadStrategy::BranchReads => { + if !node.is_leaf() { + self.storage.cache_node(addr, node.clone()); + } + } + CacheReadStrategy::WritesOnly => {} + } + + Ok(node) + } + + pub(crate) fn read_node_with_num_bytes_from_disk( + &self, + addr: LinearAddress, + ) -> Result<(SharedNode, u64), FileIoError> { + debug_assert!(addr.is_aligned()); + + // saturating because there is no way we can be reading at u64::MAX + // and this will fail very soon afterwards + let actual_addr = addr.get().saturating_add(1); // skip the length byte + + let _span = fastrace::local::LocalSpan::enter_with_local_parent("read_and_deserialize"); + + let mut area_stream = self.storage.stream_from(actual_addr)?; + let offset_before = area_stream.offset(); + let node: SharedNode = Node::from_reader(&mut area_stream) + .map_err(|e| { + self.storage + .file_io_error(e, actual_addr, Some("read_node_from_disk".to_string())) + })? + .into(); + let length = area_stream + .offset() + .checked_sub(offset_before) + .ok_or_else(|| { + self.storage.file_io_error( + Error::other("Reader offset went backwards"), + actual_addr, + Some("read_node_with_num_bytes_from_disk".to_string()), + ) + })?; + Ok((node, length.saturating_add(1))) // add 1 for the area size index byte + } + + /// Returns (index, `area_size`) for the stored area at `addr`. + /// `index` is the index of `area_size` in the array of valid block sizes. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the area cannot be read. + pub fn area_index_and_size( + &self, + addr: LinearAddress, + ) -> Result<(AreaIndex, u64), FileIoError> { + area_index_and_size(self.storage.as_ref(), addr) + } +} + +impl HashedNodeReader for Arc +where + N: HashedNodeReader, +{ + fn root_address(&self) -> Option { + self.as_ref().root_address() + } + + fn root_hash(&self) -> Option { + self.as_ref().root_hash() + } +} + +impl NodeStore { + /// adjust the freelist of this proposal to reflect the freed nodes in the oldest proposal + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if a node cannot be deleted. + pub fn reap_deleted( + mut self, + proposal: &mut NodeStore, + ) -> Result<(), FileIoError> { + self.storage + .invalidate_cached_nodes(self.kind.deleted.iter()); + trace!("There are {} nodes to reap", self.kind.deleted.len()); + let mut allocator = NodeAllocator::new(self.storage.as_ref(), &mut proposal.header); + for node in take(&mut self.kind.deleted) { + allocator.delete_node(node)?; + } + Ok(()) + } +} + +// Helper functions for the checker +impl NodeStore +where + NodeStore: NodeReader, +{ + pub(crate) const fn size(&self) -> u64 { + self.header.size() + } + + // Find the area index and size of the stored area at the given address if the area is valid. + // TODO: there should be a way to read stored area directly instead of try reading as a free area then as a node + pub(crate) fn read_leaked_area( + &self, + address: LinearAddress, + ) -> Result<(AreaIndex, u64), FileIoError> { + if alloc::FreeArea::from_storage(self.storage.as_ref(), address).is_err() { + self.read_node(address)?; + } + + let area_index_and_size = self.area_index_and_size(address)?; + Ok(area_index_and_size) + } +} + +#[cfg(test)] +#[expect(clippy::unwrap_used)] +#[expect(clippy::cast_possible_truncation)] +mod tests { + + use crate::BranchNode; + use crate::Children; + use crate::FileBacked; + use crate::LeafNode; + use crate::NibblesIterator; + use crate::PathComponent; + use crate::linear::memory::MemStore; + + use super::*; + use nonzero_ext::nonzero; + use primitives::area_size_iter; + use std::error::Error; + + #[test] + fn area_sizes_aligned() { + for (_, area_size) in area_size_iter() { + assert_eq!(area_size % AreaIndex::MIN_AREA_SIZE, 0); + } + } + + #[test] + fn test_area_size_to_index() { + // TODO: rustify using: for size in AREA_SIZES + for (i, area_size) in area_size_iter() { + // area size is at top of range + assert_eq!(AreaIndex::from_size(area_size).unwrap(), i); + + if i > AreaIndex::MIN { + // 1 less than top of range stays in range + assert_eq!(AreaIndex::from_size(area_size - 1).unwrap(), i); + } + + if i < AreaIndex::MAX { + // 1 more than top of range goes to next range + assert_eq!( + AreaIndex::from_size(area_size + 1).unwrap(), + AreaIndex::try_from(i.as_usize() + 1).unwrap() + ); + } + } + + for i in 0..=AreaIndex::MIN_AREA_SIZE { + assert_eq!(AreaIndex::from_size(i).unwrap(), AreaIndex::MIN); + } + + assert!(AreaIndex::from_size(AreaIndex::MAX_AREA_SIZE + 1).is_err()); + } + + #[test] + fn test_reparent() { + // create an empty base revision + let memstore = MemStore::new(vec![]); + let base = NodeStore::new_empty_committed(memstore.into()); + + // create an empty r1, check that it's parent is the empty committed version + let r1 = NodeStore::new(&base).unwrap(); + let r1: NodeStore, _> = r1.try_into().unwrap(); + { + let parent = r1.kind.parent.lock(); + assert!(matches!(*parent, NodeStoreParent::Committed(None))); + } + + // create an empty r2, check that it's parent is the proposed version r1 + let r2: NodeStore = NodeStore::new(&r1).unwrap(); + let r2: NodeStore, _> = r2.try_into().unwrap(); + { + let parent = r2.kind.parent.lock(); + assert!(matches!(*parent, NodeStoreParent::Proposed(_))); + } + + // reparent r2 + r1.commit_reparent(&r2); + + // now check r2's parent, should match the hash of r1 (which is still None) + let parent = r2.kind.parent.lock(); + if let NodeStoreParent::Committed(hash) = &*parent { + assert_eq!(*hash, r1.root_hash()); + assert_eq!(*hash, None); + } else { + panic!("expected committed parent"); + } + } + + #[test] + fn giant_node() { + let memstore = Arc::new(MemStore::new(vec![])); + let empty_root = NodeStore::new_empty_committed(Arc::clone(&memstore)); + + let mut node_store = NodeStore::new(&empty_root).unwrap(); + + let huge_value = vec![0u8; AreaIndex::MAX_AREA_SIZE as usize]; + + let giant_leaf = Node::Leaf(LeafNode { + partial_path: Path::from([0, 1, 2]), + value: huge_value.into_boxed_slice(), + }); + + node_store.root_mut().replace(giant_leaf); + + let node_store = NodeStore::, _>::try_from(node_store).unwrap(); + + let mut node_store = node_store.as_committed(&empty_root); + + let err = node_store.persist().unwrap_err(); + let err_ctx = err.context(); + assert!(err_ctx == Some("allocate_node")); + + let io_err = err + .source() + .unwrap() + .downcast_ref::() + .unwrap(); + assert_eq!(io_err.kind(), std::io::ErrorKind::OutOfMemory); + + let io_err_source = io_err + .get_ref() + .unwrap() + .downcast_ref::() + .unwrap(); + assert_eq!(io_err_source.0, 16_777_225); + } + + /// Test that persisting a branch node with children succeeds. + /// + /// This test verifies the fix for issue #1488 where the panic + /// "child must be hashed when serializing" occurred during persist. + /// + /// The bug was caused by batching nodes before writing but only calling + /// `allocate_at` after writing. This meant when serializing a parent node, + /// its children didn't have addresses yet (children are serialized first + /// in depth-first order, but without `allocate_at()` being called before + /// batching, the parent couldn't get the child's address during serialization). + /// + /// The fix calls `allocate_at` immediately after allocating storage for a node + /// but before adding it to the batch, ensuring children have addresses when + /// their parents are serialized. + #[test] + fn persist_branch_with_children() -> Result<(), Box> { + let tmpdir = tempfile::tempdir()?; + let dbfile = tmpdir.path().join("nodestore_branch_persist_test.db"); + + let nodestore = NodeStore::open(Arc::new(FileBacked::new( + dbfile, + nonzero!(10usize), + nonzero!(10usize), + false, + true, + CacheReadStrategy::WritesOnly, + )?))?; + + let mut proposal = NodeStore::new(&nodestore)?; + + { + let root = proposal.root_mut(); + assert!(root.is_none()); + + let mut children = Children::new(); + children[PathComponent::ALL[0x0]] = Some(Child::Node(Node::Leaf(LeafNode { + partial_path: Path::from_nibbles_iterator(NibblesIterator::new(b"123")), + value: b"\x00123".to_vec().into_boxed_slice(), + }))); + children[PathComponent::ALL[0xF]] = Some(Child::Node(Node::Leaf(LeafNode { + partial_path: Path::from_nibbles_iterator(NibblesIterator::new(b"abc")), + value: b"\x0Fabc".to_vec().into_boxed_slice(), + }))); + let branch1 = Node::Branch(Box::new(BranchNode { + partial_path: Path::new(), + value: None, + children, + })); + + let mut children = Children::new(); + children[PathComponent::ALL[0x0]] = Some(Child::Node(Node::Leaf(LeafNode { + partial_path: Path::from_nibbles_iterator(NibblesIterator::new(b"123")), + value: b"\xF0123".to_vec().into_boxed_slice(), + }))); + children[PathComponent::ALL[0xF]] = Some(Child::Node(Node::Leaf(LeafNode { + partial_path: Path::from_nibbles_iterator(NibblesIterator::new(b"abc")), + value: b"\xFFabc".to_vec().into_boxed_slice(), + }))); + let branch2 = Node::Branch(Box::new(BranchNode { + partial_path: Path::new(), + value: None, + children, + })); + + let mut children = Children::new(); + children[PathComponent::ALL[0x0]] = Some(Child::Node(branch1)); + children[PathComponent::ALL[0xF]] = Some(Child::Node(branch2)); + + *root = Some(Node::Branch(Box::new(BranchNode { + partial_path: Path::new(), + value: None, + children, + }))); + } + + let proposal = NodeStore::, _>::try_from(proposal)?; + + let mut nodestore = proposal.as_committed(&nodestore); + nodestore.persist()?; + + let mut proposal = NodeStore::new(&nodestore)?; + + { + let root = proposal.root_mut(); + assert!(root.is_some()); + } + + Ok(()) + } +} diff --git a/firewood/storage/src/nodestore/persist.rs b/firewood/storage/src/nodestore/persist.rs new file mode 100644 index 000000000000..112bfc7b7d4a --- /dev/null +++ b/firewood/storage/src/nodestore/persist.rs @@ -0,0 +1,675 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! # Persist Module +//! +//! This module handles all persistence operations for the nodestore, including writing +//! headers, nodes, and metadata to storage with support for different I/O backends. +//! +//! ## I/O Backend Support +//! +//! This module supports multiple I/O backends through conditional compilation: +//! +//! - **Standard I/O** - `#[cfg(not(feature = "io-uring"))]` - Uses standard file operations +//! - **io-uring** - `#[cfg(feature = "io-uring")]` - Uses Linux io-uring for async I/O +//! +//! This feature flag is automatically enabled when running on Linux, and disabled for all other platforms. +//! +//! The io-uring implementation provides: +//! - Asynchronous batch operations +//! - Reduced system call overhead +//! - Better performance for high-throughput workloads +//! +//! ## Performance Considerations +//! +//! - Nodes are written in batches to minimize I/O overhead +//! - Metrics are collected for flush operation timing +//! - Memory-efficient serialization with pre-allocated buffers +//! - Ring buffer management for io-uring operations + +use std::iter::FusedIterator; + +use crate::linear::FileIoError; +use crate::nodestore::AreaIndex; +use crate::{Child, firewood_counter}; +use coarsetime::Instant; + +use crate::{MaybePersistedNode, NodeReader, WritableStorage}; + +#[cfg(test)] +use crate::RootReader; + +use super::alloc::NodeAllocator; +use super::header::NodeStoreHeader; +use super::{Committed, NodeStore}; + +#[cfg(not(test))] +use super::RootReader; + +impl NodeStore { + /// Persist the header from this proposal to storage. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the header cannot be written. + pub fn flush_header(&self) -> Result<(), FileIoError> { + let header_bytes = bytemuck::bytes_of(&self.header); + self.storage.write(0, header_bytes)?; + Ok(()) + } + + /// Persist the header, including all the padding + /// This is only done the first time we write the header + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the header cannot be written. + pub fn flush_header_with_padding(&self) -> Result<(), FileIoError> { + let mut header_bytes = bytemuck::bytes_of(&self.header).to_vec(); + header_bytes.resize(NodeStoreHeader::SIZE as usize, 0); + debug_assert_eq!(header_bytes.len(), NodeStoreHeader::SIZE as usize); + + self.storage.write(0, &header_bytes)?; + Ok(()) + } + + /// Persist the freelist from this proposal to storage. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the free list cannot be written to storage. + pub fn flush_freelist(&self) -> Result<(), FileIoError> { + self.flush_freelist_from(&self.header) + } + + /// Persist the freelist from the given header to storage + /// + /// This function is used to ensure that the freelist is advanced after allocating + /// nodes for writing. This allows the database to be recovered from an I/O error while + /// persisting a revision to disk. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if the free list cannot be written to storage. + #[fastrace::trace(name = "firewood.flush_freelist")] + pub(crate) fn flush_freelist_from(&self, header: &NodeStoreHeader) -> Result<(), FileIoError> { + let free_list_bytes = bytemuck::bytes_of(header.free_lists()); + let free_list_offset = NodeStoreHeader::free_lists_offset(); + self.storage.write(free_list_offset, free_list_bytes)?; + Ok(()) + } +} + +/// Iterator that returns unpersisted nodes in depth first order. +/// +/// This iterator assumes the root node is unpersisted and will return it as the +/// last item. It looks at each node and traverses the children in depth first order. +/// A stack of child iterators is maintained to properly handle nested branches. +struct UnPersistedNodeIterator<'a, N> { + store: &'a N, + stack: Vec, + child_iter_stack: Vec + 'a>>, +} + +impl FusedIterator for UnPersistedNodeIterator<'_, N> {} + +impl<'a, N: NodeReader + RootReader> UnPersistedNodeIterator<'a, N> { + /// Creates a new iterator over unpersisted nodes in depth-first order. + fn new(store: &'a N) -> Self { + let root = store.root_as_maybe_persisted_node(); + + // we must have an unpersisted root node to use this iterator + // It's hard to tell at compile time if this is the case, so we assert it here + // TODO: can we use another trait or generic to enforce this? + debug_assert!(root.as_ref().is_none_or(|r| r.unpersisted().is_some())); + let (child_iter_stack, stack) = if let Some(root) = root { + if let Some(branch) = root + .as_shared_node(store) + .expect("in memory, so no io") + .as_branch() + { + // Create an iterator over unpersisted children + let unpersisted_children: Vec = branch + .children + .iter_present() + .filter_map(|(_, child)| child.unpersisted().cloned()) + .collect(); + + ( + vec![Box::new(unpersisted_children.into_iter()) + as Box + 'a>], + vec![root], + ) + } else { + // root is a leaf + (vec![], vec![root]) + } + } else { + (vec![], vec![]) + }; + + Self { + store, + stack, + child_iter_stack, + } + } +} + +impl Iterator for UnPersistedNodeIterator<'_, N> { + type Item = MaybePersistedNode; + + fn next(&mut self) -> Option { + // Try to get the next child from the current child iterator + while let Some(current_iter) = self.child_iter_stack.last_mut() { + if let Some(next_child) = current_iter.next() { + let shared_node = next_child + .as_shared_node(self.store) + .expect("in memory, so IO is impossible"); + + // It's a branch, so we need to get its children + if let Some(branch) = shared_node.as_branch() { + // Create an iterator over unpersisted children + let unpersisted_children: Vec = branch + .children + .iter_present() + .filter_map(|(_, child)| child.unpersisted().cloned()) + .collect(); + + // Push new child iterator to the stack + if !unpersisted_children.is_empty() { + self.child_iter_stack + .push(Box::new(unpersisted_children.into_iter())); + } + self.stack.push(next_child); // visit this node after the children + } else { + // leaf + return Some(next_child); + } + } else { + // Current iterator is exhausted, remove it + self.child_iter_stack.pop(); + } + } + + // No more children to process, pop the next node from the stack + self.stack.pop() + } +} + +/// Helper function to serialize a node into a bump allocator and allocate storage for it +/// +/// # Errors +/// +/// Returns a [`FileIoError`] if the node cannot be allocated in storage. +fn serialize_node_to_bump<'a>( + bump: &'a bumpalo::Bump, + shared_node: &crate::SharedNode, + node_allocator: &mut NodeAllocator<'_, impl WritableStorage>, +) -> Result<(&'a [u8], crate::LinearAddress, usize), FileIoError> { + let mut bytes = bumpalo::collections::Vec::new_in(bump); + shared_node.as_bytes(AreaIndex::MIN, &mut bytes); + let (persisted_address, area_size_index) = node_allocator.allocate_node(bytes.as_slice())?; + *bytes.get_mut(0).expect("byte was reserved") = area_size_index.get(); + bytes.shrink_to_fit(); + let slice = bytes.into_bump_slice(); + Ok((slice, persisted_address, area_size_index.size() as usize)) +} + +/// Helper function to process unpersisted nodes with batching and overflow detection +/// +/// This function iterates through all unpersisted nodes, serializes them into a bump allocator, +/// and flushes them in batches when the bump allocator is about to overflow. +/// +/// # Errors +/// +/// Returns a [`FileIoError`] if any node cannot be serialized, allocated, or written to storage. +pub(super) fn process_unpersisted_nodes( + bump: &mut bumpalo::Bump, + node_allocator: &mut NodeAllocator<'_, S>, + node_store: &N, + bump_size_limit: usize, + mut write_fn: F, +) -> Result<(), FileIoError> +where + N: NodeReader + RootReader, + S: WritableStorage, + F: FnMut(Vec<(&[u8], crate::LinearAddress, MaybePersistedNode)>) -> Result<(), FileIoError>, +{ + let mut allocated_objects = Vec::new(); + let mut allocated_len = 0_usize; + + // Process each unpersisted node directly from the iterator + for node in UnPersistedNodeIterator::new(node_store) { + let shared_node = node + .as_shared_node(node_store) + .expect("in memory, so no IO"); + + // Serialize the node into the bump allocator + let (slice, persisted_address, idx_size) = + serialize_node_to_bump(bump, &shared_node, node_allocator)?; + + // NOTE(#1488): we need to set the address so that the parent node can + // reference it when they are serialized within the same batch. + node.allocate_at(persisted_address); + allocated_len = allocated_len.saturating_add(idx_size); + allocated_objects.push((slice, persisted_address, node)); + + // we pause if we can't allocate another node of the same size as the last one + // This isn't a guarantee that we won't exceed bump_size_limit + // but it's a good enough approximation + let might_overflow = allocated_len > bump_size_limit.saturating_sub(idx_size); + if might_overflow { + // must persist freelist before writing anything + node_allocator.flush_freelist()?; + write_fn(allocated_objects)?; + allocated_objects = Vec::new(); + bump.reset(); + allocated_len = 0; + } + } + if !allocated_objects.is_empty() { + // Flush the freelist using the node_allocator before the final write + node_allocator.flush_freelist()?; + write_fn(allocated_objects)?; + } + + Ok(()) +} + +impl NodeStore { + /// Persist all the nodes of a proposal to storage. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if any node cannot be written to storage. + #[fastrace::trace(short_name = true)] + pub fn flush_nodes(&mut self) -> Result { + let flush_start = Instant::now(); + + let header = { + #[cfg(feature = "io-uring")] + { + use crate::FileBacked; + // Try to use io-uring if available and storage type supports it + let this = self as &mut dyn std::any::Any; + if let Some(file_backed) = this.downcast_mut::>() { + file_backed.flush_nodes_io_uring()? + } else { + self.flush_nodes_generic()? + } + } + #[cfg(not(feature = "io-uring"))] + { + self.flush_nodes_generic()? + } + }; + + let flush_time = flush_start.elapsed().as_millis(); + firewood_counter!("firewood.flush_nodes", "amount flushed nodes").increment(flush_time); + + Ok(header) + } + + /// Persist all the nodes of a proposal to storage. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if any node cannot be written to storage. + fn flush_nodes_generic(&self) -> Result { + use bumpalo::Bump; + + let mut header = self.header; + let mut node_allocator = NodeAllocator::new(self.storage.as_ref(), &mut header); + let mut bump = Bump::with_capacity(super::INITIAL_BUMP_SIZE); + + process_unpersisted_nodes( + &mut bump, + &mut node_allocator, + self, + super::INITIAL_BUMP_SIZE, + |allocated_objects| self.write_nodes_generic(allocated_objects), + )?; + + Ok(header) + } + + /// Write a batch of serialized nodes to storage + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if any node cannot be written to storage. + fn write_nodes_generic( + &self, + allocated_objects: Vec<(&[u8], crate::LinearAddress, MaybePersistedNode)>, + ) -> Result<(), FileIoError> { + // Collect addresses and nodes for caching + let mut cached_nodes = Vec::new(); + + for (serialized, persisted_address, node) in allocated_objects { + self.storage.write(persisted_address.get(), serialized)?; + + // I/O completed successfully - enqueue node for caching at the end + cached_nodes.push(node); + } + + self.storage.write_cached_nodes(cached_nodes)?; + + Ok(()) + } +} + +impl NodeStore { + /// Persist the entire nodestore to storage. + /// + /// This method performs a complete persistence operation by: + /// 1. Flushing all nodes to storage + /// 2. Setting the root address in the header + /// 3. Flushing the header to storage + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if any of the persistence operations fail. + #[fastrace::trace(short_name = true)] + pub fn persist(&mut self) -> Result<(), FileIoError> { + // First persist all the nodes + self.header = self.flush_nodes()?; + + // Set the root address in the header based on the persisted root + let root_address = self.kind.root.as_ref().and_then(Child::persisted_address); + self.header.set_root_address(root_address); + + // Finally persist the header + self.flush_header()?; + + Ok(()) + } +} + +#[cfg(test)] +#[expect(clippy::unwrap_used, clippy::indexing_slicing)] +mod tests { + use super::*; + use crate::{ + Child, Children, HashType, ImmutableProposal, LinearAddress, NodeStore, Path, + PathComponent, SharedNode, + linear::memory::MemStore, + node::{BranchNode, LeafNode, Node}, + nodestore::MutableProposal, + }; + use std::sync::Arc; + + fn into_committed( + ns: NodeStore, MemStore>, + parent: &NodeStore, + ) -> NodeStore { + ns.flush_freelist().unwrap(); + ns.flush_header().unwrap(); + let mut ns = ns.as_committed(parent); + ns.flush_nodes().unwrap(); + ns + } + + /// Helper to create a test node store with a specific root + fn create_test_store_with_root(root: Node) -> NodeStore { + let mem_store = MemStore::new(vec![]).into(); + let mut store = NodeStore::new_empty_proposal(mem_store); + store.root_mut().replace(root); + store + } + + /// Helper to create a leaf node + fn create_leaf(path: &[u8], value: &[u8]) -> Node { + Node::Leaf(LeafNode { + partial_path: Path::from(path), + value: value.to_vec().into_boxed_slice(), + }) + } + + /// Helper to create a branch node with children + fn create_branch( + path: &[u8], + value: Option<&[u8]>, + children: Vec<(PathComponent, Node)>, + ) -> Node { + let mut branch = BranchNode { + partial_path: Path::from(path), + value: value.map(|v| v.to_vec().into_boxed_slice()), + children: Children::new(), + }; + + for (index, child) in children { + let shared_child = SharedNode::new(child); + let maybe_persisted = MaybePersistedNode::from(shared_child); + let hash = HashType::empty(); + branch.children[index] = Some(Child::MaybePersisted(maybe_persisted, hash)); + } + + Node::Branch(Box::new(branch)) + } + + #[test] + fn test_empty_nodestore() { + let mem_store = MemStore::new(vec![]).into(); + let store = NodeStore::new_empty_proposal(mem_store); + let mut iter = UnPersistedNodeIterator::new(&store); + + assert!(iter.next().is_none()); + } + + #[test] + fn test_single_leaf_node() { + let leaf = create_leaf(&[1, 2, 3], &[4, 5, 6]); + let store = create_test_store_with_root(leaf.clone()); + let mut iter = + UnPersistedNodeIterator::new(&store).map(|node| node.as_shared_node(&store).unwrap()); + + // Should return the leaf node + let node = iter.next().unwrap(); + assert_eq!(*node, leaf); + + // Should be exhausted + assert!(iter.next().is_none()); + } + + #[test] + fn test_branch_with_single_child() { + let leaf = create_leaf(&[7, 8], &[9, 10]); + let branch = create_branch( + &[1, 2], + Some(&[3, 4]), + vec![(PathComponent::ALL[5], leaf.clone())], + ); + let store = create_test_store_with_root(branch.clone()); + let mut iter = + UnPersistedNodeIterator::new(&store).map(|node| node.as_shared_node(&store).unwrap()); + + // Should return child first (depth-first) + let node = iter.next().unwrap(); + assert_eq!(*node, leaf); + + // Then the branch + let node = iter.next().unwrap(); + assert_eq!(&*node, &branch); + + assert!(iter.next().is_none()); + + // verify iterator is fused + assert!(iter.next().is_none()); + } + + #[test] + fn test_branch_with_multiple_children() { + let leaves = [ + create_leaf(&[1], &[10]), + create_leaf(&[2], &[20]), + create_leaf(&[3], &[30]), + ]; + let branch = create_branch( + &[0], + None, + vec![ + (PathComponent::ALL[1], leaves[0].clone()), + (PathComponent::ALL[5], leaves[1].clone()), + (PathComponent::ALL[10], leaves[2].clone()), + ], + ); + let store = create_test_store_with_root(branch.clone()); + + // Collect all nodes + let nodes: Vec<_> = UnPersistedNodeIterator::new(&store) + .map(|node| node.as_shared_node(&store).unwrap()) + .collect(); + + // Should have 4 nodes total (3 leaves + 1 branch) + assert_eq!(nodes.len(), 4); + + // The branch should be last (depth-first) + assert_eq!(&*nodes[3], &branch); + + // Children should come first - verify all expected leaf nodes are present + let children_nodes = &nodes[0..3]; + assert!(children_nodes.iter().any(|n| **n == leaves[0])); + assert!(children_nodes.iter().any(|n| **n == leaves[1])); + assert!(children_nodes.iter().any(|n| **n == leaves[2])); + } + + #[test] + fn test_nested_branches() { + let leaves = [ + create_leaf(&[1], &[100]), + create_leaf(&[2], &[200]), + create_leaf(&[3], &[255]), + ]; + + // Create a nested structure: root -> branch1 -> leaf[0] + // -> leaf[1] + // -> branch2 -> leaf[2] + let inner_branch = create_branch( + &[10], + Some(&[50]), + vec![(PathComponent::ALL[0], leaves[2].clone())], + ); + + let mut children = Children::new(); + for (value, (_, slot)) in [ + // unpersisted leaves + Child::MaybePersisted( + MaybePersistedNode::from(SharedNode::new(leaves[0].clone())), + HashType::empty(), + ), + Child::MaybePersisted( + MaybePersistedNode::from(SharedNode::new(leaves[1].clone())), + HashType::empty(), + ), + // unpersisted branch + Child::MaybePersisted( + MaybePersistedNode::from(SharedNode::new(inner_branch.clone())), + HashType::empty(), + ), + // persisted branch + Child::MaybePersisted( + MaybePersistedNode::from(LinearAddress::new(42).unwrap()), + HashType::empty(), + ), + ] + .into_iter() + .zip(children.iter_mut()) + { + slot.replace(value); + } + + let root_branch: Node = BranchNode { + partial_path: Path::new(), + value: None, + children, + } + .into(); + + let store = create_test_store_with_root(root_branch.clone()); + + // Collect all nodes + let nodes: Vec<_> = UnPersistedNodeIterator::new(&store) + .map(|node| node.as_shared_node(&store).unwrap()) + .collect(); + + // Should have 5 nodes total (3 leaves + 2 branches) + assert_eq!(nodes.len(), 5); + + // The root branch should be last (depth-first) + assert_eq!(**nodes.last().unwrap(), root_branch); + + // Find positions of some nodes + let root_pos = nodes.iter().position(|n| **n == root_branch).unwrap(); + let inner_branch_pos = nodes.iter().position(|n| **n == inner_branch).unwrap(); + let leaf3_pos = nodes.iter().position(|n| **n == leaves[2]).unwrap(); + + // Verify depth-first ordering: leaf3 should come before inner_branch, + // inner_branch should come before root_branch + assert!(leaf3_pos < inner_branch_pos); + assert!(inner_branch_pos < root_pos); + } + + #[test] + fn test_into_committed_with_generic_storage() { + // Create a base committed store with MemStore + let mem_store = MemStore::new(vec![]); + let base_committed = NodeStore::new_empty_committed(mem_store.into()); + + // Create a mutable proposal from the base + let mut mutable_store = NodeStore::new(&base_committed).unwrap(); + + // Add some nodes to the mutable store + let leaf1 = create_leaf(&[1, 2, 3], b"value1"); + let leaf2 = create_leaf(&[4, 5, 6], b"value2"); + let branch = create_branch( + &[0], + Some(b"branch_value"), + vec![ + (PathComponent::ALL[1], leaf1.clone()), + (PathComponent::ALL[2], leaf2.clone()), + ], + ); + + mutable_store.root_mut().replace(branch.clone()); + + // Convert to immutable proposal + let immutable_store: NodeStore, _> = + mutable_store.try_into().unwrap(); + + // Commit the immutable store + let committed_store = into_committed(immutable_store, &base_committed); + + // Verify the committed store has the expected values + let root = committed_store.kind.root.as_ref().unwrap(); + let root_maybe_persisted = root.as_maybe_persisted_node(); + let root_node = root_maybe_persisted + .as_shared_node(&committed_store) + .unwrap(); + assert_eq!(*root_node.partial_path(), Path::from(&[0])); + assert_eq!(root_node.value(), Some(&b"branch_value"[..])); + assert!(root_node.is_branch()); + let root_branch = root_node.as_branch().unwrap(); + assert_eq!(root_branch.children.count(), 2); + + let child1 = root_branch.children[PathComponent::ALL[1]] + .as_ref() + .unwrap(); + let child1_maybe_persisted = child1.as_maybe_persisted_node(); + let child1_node = child1_maybe_persisted + .as_shared_node(&committed_store) + .unwrap(); + assert_eq!(*child1_node.partial_path(), Path::from(&[1, 2, 3])); + assert_eq!(child1_node.value(), Some(&b"value1"[..])); + + let child2 = root_branch.children[PathComponent::ALL[2]] + .as_ref() + .unwrap(); + let child2_maybe_persisted = child2.as_maybe_persisted_node(); + let child2_node = child2_maybe_persisted + .as_shared_node(&committed_store) + .unwrap(); + assert_eq!(*child2_node.partial_path(), Path::from(&[4, 5, 6])); + assert_eq!(child2_node.value(), Some(&b"value2"[..])); + } +} diff --git a/firewood/storage/src/nodestore/persist_io_uring.rs b/firewood/storage/src/nodestore/persist_io_uring.rs new file mode 100644 index 000000000000..b44361196536 --- /dev/null +++ b/firewood/storage/src/nodestore/persist_io_uring.rs @@ -0,0 +1,214 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! # io-uring Persistence Module +//! +//! This module contains io-uring-specific implementations for batch node persistence. +//! It is only compiled when the `io-uring` feature is enabled. + +use super::alloc::NodeAllocator; +use super::header::NodeStoreHeader; +use super::persist::process_unpersisted_nodes; +use super::{Committed, NodeStore}; +use crate::LinearAddress; +use crate::linear::{FileIoError, ReadableStorage, WritableStorage}; +use crate::logger::trace; +use crate::{FileBacked, MaybePersistedNode, firewood_counter}; + +/// Entry in the pinned buffer array tracking in-flight io-uring operations +#[derive(Clone, Debug)] +struct BufferEntry<'a> { + buffer: &'a [u8], + address: LinearAddress, + node: MaybePersistedNode, +} + +/// Helper function to retry `submit_and_wait` on EINTR +fn submit_and_wait_with_retry( + ring: &mut io_uring::IoUring, + wait_nr: u32, + storage: &FileBacked, + operation_name: &str, +) -> Result<(), FileIoError> { + use std::io::ErrorKind::Interrupted; + + loop { + match ring.submit_and_wait(wait_nr as usize) { + Ok(_) => return Ok(()), + Err(e) => { + // Retry if the error is an interrupted system call + if e.kind() == Interrupted { + continue; + } + // For other errors, return the error + return Err(storage.file_io_error( + e, + 0, + Some(format!("io-uring {operation_name}")), + )); + } + } + } +} + +/// Helper function to handle completion queue entries and check for errors +fn handle_completion_queue( + storage: &FileBacked, + completion_queue: io_uring::cqueue::CompletionQueue<'_>, + saved_pinned_buffers: &mut [Option>], + cached_nodes: &mut Vec, +) -> Result<(), FileIoError> { + for entry in completion_queue { + // user data contains the index of the entry in the saved_pinned_buffers array + let item = entry.user_data() as usize; + let pbe_entry = saved_pinned_buffers + .get_mut(item) + .expect("completed item user_data should point to an entry") + .take() + .expect("completed items are always in use"); + + let expected_len: i32 = pbe_entry + .buffer + .len() + .try_into() + .expect("buffer length will fit into an i32"); + if entry.result() != expected_len { + let error = if entry.result() >= 0 { + std::io::Error::other("Partial write") + } else { + std::io::Error::from_raw_os_error(0 - entry.result()) + }; + return Err(storage.file_io_error( + error, + pbe_entry.address.get(), + Some("write failure".to_string()), + )); + } + // I/O completed successfully - enqueue node for caching at the end + cached_nodes.push(pbe_entry.node); + } + Ok(()) +} + +impl NodeStore { + /// Persist all the nodes of a proposal to storage using io-uring. + /// + /// # Errors + /// + /// Returns a [`FileIoError`] if any node cannot be written to storage. + #[fastrace::trace(short_name = true)] + pub(super) fn flush_nodes_io_uring(&mut self) -> Result { + use bumpalo::Bump; + + let mut header = self.header; + let mut node_allocator = NodeAllocator::new(self.storage.as_ref(), &mut header); + let mut bump = Bump::with_capacity(super::INITIAL_BUMP_SIZE); + + process_unpersisted_nodes( + &mut bump, + &mut node_allocator, + self, + super::INITIAL_BUMP_SIZE, + |allocated_objects| self.ring_writes(allocated_objects), + )?; + + Ok(header) + } + + fn ring_writes( + &self, + allocated_objects: Vec<(&[u8], LinearAddress, MaybePersistedNode)>, + ) -> Result<(), FileIoError> { + let mut ring = self.storage.ring.lock(); + + let mut saved_pinned_buffers = + vec![Option::>::None; FileBacked::RINGSIZE as usize]; + + // Collect addresses and nodes for caching + let mut cached_nodes = Vec::new(); + + for (serialized, persisted_address, node) in allocated_objects { + loop { + // Find the first available write buffer, enumerate to get the position for marking it completed + if let Some((pos, pbe)) = saved_pinned_buffers + .iter_mut() + .enumerate() + .find(|(_, pbe)| pbe.is_none()) + { + *pbe = Some(BufferEntry { + buffer: serialized, + address: persisted_address, + node: node.clone(), + }); + + let submission_queue_entry = self + .storage + .make_op(serialized) + .offset(persisted_address.get()) + .build() + .user_data(pos as u64); + + #[expect(unsafe_code)] + // SAFETY: the submission_queue_entry's found buffer must not move or go out of scope + // until the operation has been completed. This is ensured by having a Some(offset) + // and not marking it None until the kernel has said it's done below. + while unsafe { ring.submission().push(&submission_queue_entry) }.is_err() { + ring.submitter().squeue_wait().map_err(|e| { + self.storage.file_io_error( + e, + persisted_address.get(), + Some("io-uring squeue_wait".to_string()), + ) + })?; + trace!("submission queue is full"); + firewood_counter!("ring.full", "amount of full ring").increment(1); + } + break; + } + // if we get here, that means we couldn't find a place to queue the request, so wait for at least one operation + // to complete, then handle the completion queue + firewood_counter!("ring.full", "amount of full ring").increment(1); + submit_and_wait_with_retry(&mut ring, 1, &self.storage, "submit_and_wait")?; + let completion_queue = ring.completion(); + trace!("competion queue length: {}", completion_queue.len()); + handle_completion_queue( + &self.storage, + completion_queue, + &mut saved_pinned_buffers, + &mut cached_nodes, + )?; + } + } + let pending = saved_pinned_buffers + .iter() + .filter(|pbe| pbe.is_some()) + .count(); + submit_and_wait_with_retry( + &mut ring, + pending as u32, + &self.storage, + "final submit_and_wait", + )?; + + handle_completion_queue( + &self.storage, + ring.completion(), + &mut saved_pinned_buffers, + &mut cached_nodes, + )?; + + debug_assert!( + !saved_pinned_buffers + .iter() + .any(std::option::Option::is_some), + "Found entry with node still set: {:?}", + saved_pinned_buffers.iter().find(|pbe| pbe.is_some()) + ); + + self.storage.write_cached_nodes(cached_nodes)?; + debug_assert!(ring.completion().is_empty()); + + // All references to batch.bump are now dropped, caller can reset it + Ok(()) + } +} diff --git a/firewood/storage/src/nodestore/primitives.rs b/firewood/storage/src/nodestore/primitives.rs new file mode 100644 index 000000000000..8d0fcf994850 --- /dev/null +++ b/firewood/storage/src/nodestore/primitives.rs @@ -0,0 +1,351 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +//! # Primitives Module +//! +//! This module contains the primitives for the nodestore, including a list of valid +//! area sizes, `AreaIndex` that uniquely identifies a valid area size, and +//! `LinearAddress` that points to a specific location in the linear storage space. + +use crate::TrieHash; + +use sha2::{Digest, Sha256}; +use std::fmt; +use std::io::{Error, ErrorKind}; +use std::num::NonZeroU64; + +/// [`super::NodeStore`] divides the linear store into blocks of different sizes. +/// [`AREA_SIZES`] is every valid block size. +const AREA_SIZES: [u64; 23] = [ + 16, // Min block size + 32, + 64, + 96, + 128, + 256, + 512, + 768, + 1024, + 1024 << 1, + 1024 << 2, + 1024 << 3, + 1024 << 4, + 1024 << 5, + 1024 << 6, + 1024 << 7, + 1024 << 8, + 1024 << 9, + 1024 << 10, + 1024 << 11, + 1024 << 12, + 1024 << 13, + 1024 << 14, +]; + +/// Returns an iterator over all valid area sizes. +// TODO: return a named iterator +pub fn area_size_iter() -> impl DoubleEndedIterator { + AREA_SIZES + .iter() + .enumerate() + .map(|(i, &size)| (AreaIndex(i as u8), size)) +} + +pub fn area_size_hash() -> TrieHash { + let mut hasher = Sha256::new(); + for size in AREA_SIZES { + hasher.update(size.to_ne_bytes()); + } + hasher.finalize().into() +} + +// TODO: automate this, must stay in sync with above +pub const fn index_name(index: AreaIndex) -> &'static str { + match index.get() { + 0 => "16", + 1 => "32", + 2 => "64", + 3 => "96", + 4 => "128", + 5 => "256", + 6 => "512", + 7 => "768", + 8 => "1024", + 9 => "2048", + 10 => "4096", + 11 => "8192", + 12 => "16384", + 13 => "32768", + 14 => "65536", + 15 => "131072", + 16 => "262144", + 17 => "524288", + 18 => "1048576", + 19 => "2097152", + 20 => "4194304", + 21 => "8388608", + 22 => "16777216", + _ => "unknown", + } +} + +/// The type that uniquely identifies a valid area size. +/// This is not usize because we store this as a single byte +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct AreaIndex(u8); + +impl AreaIndex { + /// The number of different area sizes available. + pub const NUM_AREA_SIZES: usize = AREA_SIZES.len(); + + /// The minimum area index (0). + pub const MIN: AreaIndex = AreaIndex(0); + + /// The maximum area index (22). + pub const MAX: AreaIndex = AreaIndex(Self::NUM_AREA_SIZES as u8 - 1); + + /// The minimum area size available for allocation. + pub const MIN_AREA_SIZE: u64 = AREA_SIZES[0]; + + /// The maximum area size available for allocation. + pub const MAX_AREA_SIZE: u64 = AREA_SIZES[Self::NUM_AREA_SIZES - 1]; + + /// Create a new `AreaIndex` from a u8 value, returns None if value is out of range. + #[inline] + #[must_use] + pub const fn new(index: u8) -> Option { + if index < Self::NUM_AREA_SIZES as u8 { + Some(AreaIndex(index)) + } else { + None + } + } + + /// Create an `AreaIndex` from a size in bytes. + /// Returns the index of the smallest area size >= `n`. + /// + /// # Errors + /// + /// Returns an error if the size is too large. + pub fn from_size(n: u64) -> Result { + if n > Self::MAX_AREA_SIZE { + return Err(Error::new(ErrorKind::OutOfMemory, AreaSizeError(n))); + } + + if n <= Self::MIN_AREA_SIZE { + return Ok(AreaIndex(0)); + } + + AREA_SIZES + .iter() + .position(|&size| size >= n) + .map(|index| AreaIndex(index as u8)) + .ok_or_else(|| Error::new(ErrorKind::OutOfMemory, AreaSizeError(n))) + } + + /// Get the underlying index as u8. + #[inline] + #[must_use] + pub const fn get(self) -> u8 { + self.0 + } + + /// Get the underlying index as usize. + #[inline] + #[must_use] + pub const fn as_usize(self) -> usize { + self.0 as usize + } + + /// Returns the number of different area sizes available. + #[inline] + #[must_use] + pub const fn num_area_sizes() -> usize { + Self::NUM_AREA_SIZES + } + + /// Create an `AreaIndex` from a u8 value without bounds checking. + #[inline] + #[must_use] + #[cfg(test)] + pub const fn from_u8_unchecked(index: u8) -> Self { + AreaIndex(index) + } + + /// Get the size of an area index (used by the checker) + /// + /// # Panics + /// + /// Panics if `index` is out of bounds for the `AREA_SIZES` array. + #[must_use] + pub const fn size(self) -> u64 { + #[expect(clippy::indexing_slicing)] + AREA_SIZES[self.as_usize()] + } +} + +impl TryFrom for AreaIndex { + type Error = Error; + + fn try_from(index: u8) -> Result { + AreaIndex::new(index).ok_or_else(|| { + Error::new( + ErrorKind::InvalidData, + format!("Area index out of bounds: {index}"), + ) + }) + } +} + +impl From for u8 { + fn from(area_index: AreaIndex) -> Self { + area_index.get() + } +} + +impl TryFrom for AreaIndex { + type Error = Error; + + fn try_from(index: usize) -> Result { + let index_u8: Result = index.try_into(); + index_u8.map(AreaIndex).map_err(|_| { + Error::new( + ErrorKind::InvalidData, + format!("Area index out of bounds: {index}"), + ) + }) + } +} + +impl From for usize { + fn from(area_index: AreaIndex) -> Self { + area_index.as_usize() + } +} + +impl fmt::Display for AreaIndex { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + std::fmt::Display::fmt(&self.get(), f) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)] +#[error("Node size {_0} is too large")] +pub(super) struct AreaSizeError(pub(super) u64); + +/// A linear address in the nodestore storage. +/// +/// This represents a non-zero address in the linear storage space. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct LinearAddress(NonZeroU64); + +#[expect(unsafe_code)] +// SAFETY: `LinearAddress` is a wrapper around `NonZeroU64` which is also `ZeroableInOption`. +unsafe impl bytemuck::ZeroableInOption for LinearAddress {} +#[expect(unsafe_code)] +// SAFETY: `LinearAddress` is a wrapper around `NonZeroU64` which is also `PodInOption`. +unsafe impl bytemuck::PodInOption for LinearAddress {} + +impl LinearAddress { + /// Create a new `LinearAddress`, returns None if value is zero. + #[inline] + #[must_use] + pub const fn new(addr: u64) -> Option { + match NonZeroU64::new(addr) { + Some(addr) => Some(LinearAddress(addr)), + None => None, + } + } + + /// Get the underlying address as u64. + #[inline] + #[must_use] + pub const fn get(self) -> u64 { + self.0.get() + } + + /// Check if the address is 8-byte aligned. + #[inline] + #[must_use] + pub const fn is_aligned(self) -> bool { + self.0.get().is_multiple_of(Self::MIN_AREA_SIZE) + } + + /// The maximum area size available for allocation. + pub const MAX_AREA_SIZE: u64 = *AREA_SIZES.last().unwrap(); + + /// The minimum area size available for allocation. + pub const MIN_AREA_SIZE: u64 = *AREA_SIZES.first().unwrap(); + + /// Returns the number of different area sizes available. + #[inline] + #[must_use] + pub const fn num_area_sizes() -> usize { + const { AREA_SIZES.len() } + } + + /// Returns the inner `NonZeroU64` + #[inline] + #[must_use] + pub const fn into_nonzero(self) -> NonZeroU64 { + self.0 + } + + /// Advances a `LinearAddress` by `n` bytes. + /// + /// Returns `None` if the result overflows a u64 + /// Some(LinearAddress) otherwise + /// + #[inline] + #[must_use] + pub const fn advance(self, n: u64) -> Option { + match self.0.checked_add(n) { + // overflowed + None => None, + + // It is impossible to add a non-zero positive number to a u64 and get 0 without + // overflowing, so we don't check for that here, and panic instead. + Some(sum) => Some(LinearAddress(sum)), + } + } + + /// Returns the number of bytes between `other` and `self` if `other` is less than or equal to `self`. + /// Otherwise, returns `None`. + #[inline] + #[must_use] + pub const fn distance_from(self, other: Self) -> Option { + self.0.get().checked_sub(other.0.get()) + } +} + +impl std::ops::Deref for LinearAddress { + type Target = NonZeroU64; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl fmt::Display for LinearAddress { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + std::fmt::Display::fmt(&self.get(), f) + } +} + +impl fmt::LowerHex for LinearAddress { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + std::fmt::LowerHex::fmt(&self.get(), f) + } +} +impl From for u64 { + fn from(addr: LinearAddress) -> Self { + addr.get() + } +} + +impl From for LinearAddress { + fn from(addr: NonZeroU64) -> Self { + LinearAddress(addr) + } +} diff --git a/firewood/storage/src/path/buf.rs b/firewood/storage/src/path/buf.rs new file mode 100644 index 000000000000..64293fc004d1 --- /dev/null +++ b/firewood/storage/src/path/buf.rs @@ -0,0 +1,206 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::{ComponentIter, IntoSplitPath, PathComponent, TriePath}; + +/// An owned buffer of path components. +pub type PathBuf = smallvec::SmallVec<[PathComponent; 32]>; + +/// A trie path represented as a slice of path components, either borrowed or owned. +pub enum PartialPath<'a> { + /// A borrowed slice of path components. + Borrowed(&'a [PathComponent]), + + /// An owned buffer of path components. + Owned(PathBuf), +} + +impl std::fmt::Debug for PartialPath<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.display().fmt(f) + } +} + +impl std::fmt::Display for PartialPath<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.display().fmt(f) + } +} + +impl PartialPath<'_> { + /// Returns the path as a slice of path components. + #[inline] + #[must_use] + pub fn as_slice(&self) -> &[PathComponent] { + match self { + PartialPath::Borrowed(slice) => slice, + PartialPath::Owned(buf) => buf.as_slice(), + } + } + + /// Converts this partial path into an owned path buffer. + /// + /// If the path is already owned, this is a no-op. + /// If the path is borrowed, this allocates a new buffer and copies the + /// components into it. + #[inline] + #[must_use] + pub fn into_owned(self) -> PathBuf { + match self { + PartialPath::Borrowed(slice) => slice.into(), + PartialPath::Owned(buf) => buf, + } + } + + /// Returns true if this partial path is a borrowed slice. + #[inline] + #[must_use] + pub const fn is_borrowed(&self) -> bool { + matches!(self, PartialPath::Borrowed(_)) + } + + /// Returns true if this partial path is an owned buffer. + #[inline] + #[must_use] + pub const fn is_owned(&self) -> bool { + matches!(self, PartialPath::Owned(_)) + } + + /// Acquires a mutable reference to the owned path buffer, converting + /// the path to an owned buffer if it is currently a borrowed slice. + pub fn to_mut(&mut self) -> &mut PathBuf { + if let Self::Borrowed(buf) = self { + *self = Self::Owned((*buf).into()); + } + + if let Self::Owned(buf) = self { + buf + } else { + unreachable!() + } + } +} + +impl std::ops::Deref for PartialPath<'_> { + type Target = [PathComponent]; + + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl std::borrow::Borrow<[PathComponent]> for PartialPath<'_> { + fn borrow(&self) -> &[PathComponent] { + self.as_slice() + } +} + +impl AsRef<[PathComponent]> for PartialPath<'_> { + fn as_ref(&self) -> &[PathComponent] { + self.as_slice() + } +} + +impl TriePath for PartialPath<'_> { + type Components<'a> + = ComponentIter<'a> + where + Self: 'a; + + fn len(&self) -> usize { + self.as_slice().len() + } + + fn components(&self) -> Self::Components<'_> { + self.as_slice().iter().copied() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + PartialPath::Borrowed(self.as_slice()) + } +} + +impl<'a> IntoSplitPath for &'a PartialPath<'_> { + type Path = &'a [PathComponent]; + + #[inline] + fn into_split_path(self) -> Self::Path { + self + } +} + +/// A RAII guard that resets a path buffer to its original length when dropped. +/// +/// The guard exposes append-only methods to add components to the path buffer +/// but not remove them without dropping the guard. This ensures that the guard +/// will always restore the path buffer to its original state when dropped. +#[must_use] +pub struct PathGuard<'a> { + buf: &'a mut PathBuf, + len: usize, +} + +impl std::fmt::Debug for PathGuard<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.buf.display().fmt(f) + } +} + +impl Drop for PathGuard<'_> { + fn drop(&mut self) { + self.buf.truncate(self.len); + } +} + +impl<'a> PathGuard<'a> { + /// Creates a new guard that will reset the provided buffer to its current + /// length when dropped. + pub fn new(buf: &'a mut PathBuf) -> Self { + Self { + len: buf.len(), + buf, + } + } + + /// Creates a new guard that will reset this guard's buffer to its current + /// length when dropped. + /// + /// This allows for nested guards that can be used in recursive algorithms. + pub fn fork(&mut self) -> PathGuard<'_> { + PathGuard::new(self.buf) + } + + /// Fork this guard and append the given segment to the path buffer. + /// + /// This is a convenience method that combines `fork` then `extend` in a + /// single operation for ergonomic one-liners. + /// + /// The returned guard will reset the path buffer to its original length, + /// before appending the given segment, when dropped. + pub fn fork_append(&mut self, path: impl TriePath) -> PathGuard<'_> { + let mut fork = self.fork(); + fork.extend(path.components()); + fork + } + + /// Appends the given component to the path buffer. + /// + /// This component will be removed when the guard is dropped. + pub fn push(&mut self, component: PathComponent) { + self.buf.push(component); + } +} + +impl std::ops::Deref for PathGuard<'_> { + type Target = PathBuf; + + fn deref(&self) -> &Self::Target { + self.buf + } +} + +impl Extend for PathGuard<'_> { + fn extend>(&mut self, iter: T) { + self.buf.extend(iter); + } +} diff --git a/firewood/storage/src/path/component.rs b/firewood/storage/src/path/component.rs new file mode 100644 index 000000000000..13e7e17a24d7 --- /dev/null +++ b/firewood/storage/src/path/component.rs @@ -0,0 +1,588 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use smallvec::SmallVec; + +use super::{PartialPath, TriePath, TriePathFromUnpackedBytes}; + +#[cfg(not(feature = "branch_factor_256"))] +/// A path component in a hexary trie; which is only 4 bits (aka a nibble). +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PathComponent(pub crate::u4::U4); + +#[cfg(feature = "branch_factor_256")] +/// A path component in a 256-ary trie; which is 8 bits (aka a byte). +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PathComponent(pub u8); + +/// An iterator over path components. +pub type ComponentIter<'a> = std::iter::Copied>; + +/// Extension methods for slices of path components. +pub trait PathComponentSliceExt { + /// Casts this slice of path components to a byte slice. + fn as_byte_slice(&self) -> &[u8]; +} + +impl PathComponent { + /// All possible path components. + /// + /// This makes it easy to iterate over all possible children of a branch + /// in a type-safe way. It is preferrable to do: + /// + /// ```ignore + /// for (idx, slot) in PathComponent::ALL.into_iter().zip(branch.children.each_ref()) { + /// /// use idx and slot + /// } + /// ``` + /// + /// instead of using a raw range like (`0..16`) or [`Iterator::enumerate`], + /// which does not give a type-safe path component. + #[cfg(not(feature = "branch_factor_256"))] + pub const ALL: [Self; Self::LEN] = [ + Self(crate::u4::U4::new_masked(0x0)), + Self(crate::u4::U4::new_masked(0x1)), + Self(crate::u4::U4::new_masked(0x2)), + Self(crate::u4::U4::new_masked(0x3)), + Self(crate::u4::U4::new_masked(0x4)), + Self(crate::u4::U4::new_masked(0x5)), + Self(crate::u4::U4::new_masked(0x6)), + Self(crate::u4::U4::new_masked(0x7)), + Self(crate::u4::U4::new_masked(0x8)), + Self(crate::u4::U4::new_masked(0x9)), + Self(crate::u4::U4::new_masked(0xA)), + Self(crate::u4::U4::new_masked(0xB)), + Self(crate::u4::U4::new_masked(0xC)), + Self(crate::u4::U4::new_masked(0xD)), + Self(crate::u4::U4::new_masked(0xE)), + Self(crate::u4::U4::new_masked(0xF)), + ]; + + /// All possible path components. + /// + /// This makes it easy to iterate over all possible children of a branch + /// in a type-safe way. It is preferrable to do: + /// + /// ```ignore + /// for (idx, slot) in PathComponent::ALL.into_iter().zip(branch.children.each_ref()) { + /// /// use idx and slot + /// } + /// ``` + /// + /// instead of using a raw range like (`0..256`) or [`Iterator::enumerate`], + /// which does not give a type-safe path component. + #[cfg(feature = "branch_factor_256")] + pub const ALL: [Self; Self::LEN] = { + let mut all = [Self(0); 256]; + let mut i = 0; + #[expect(clippy::indexing_slicing)] + while i < 256 { + all[i] = Self(i as u8); + i += 1; + } + all + }; + + /// The number of possible path components. + pub const LEN: usize = if cfg!(feature = "branch_factor_256") { + 256 + } else { + 16 + }; +} + +impl PathComponent { + /// Returns the path component as a [`u8`]. + #[must_use] + pub const fn as_u8(self) -> u8 { + #[cfg(not(feature = "branch_factor_256"))] + { + self.0.as_u8() + } + #[cfg(feature = "branch_factor_256")] + { + self.0 + } + } + + /// Returns the path component as a [`usize`]. + #[must_use] + pub const fn as_usize(self) -> usize { + self.as_u8() as usize + } + + /// Tries to create a path component from the given [`u8`]. + /// + /// For hexary tries, the input must be in the range 0x00 to 0x0F inclusive. + /// Any value outside this range will result in [`None`]. + /// + /// For 256-ary tries, any value is valid. + #[must_use] + pub const fn try_new(value: u8) -> Option { + #[cfg(not(feature = "branch_factor_256"))] + { + match crate::u4::U4::try_new(value) { + Some(u4) => Some(Self(u4)), + None => None, + } + } + #[cfg(feature = "branch_factor_256")] + { + Some(Self(value)) + } + } + + /// Creates a pair of path components from a single byte where the + /// upper 4 bits are the first component and the lower 4 bits are the + /// second component. + #[cfg(not(feature = "branch_factor_256"))] + #[must_use] + pub const fn new_pair(v: u8) -> (Self, Self) { + let (upper, lower) = crate::u4::U4::new_pair(v); + (Self(upper), Self(lower)) + } + + /// Joins this [`PathComponent`] with another to create a single [`u8`] where + /// this component is the upper 4 bits and the provided component is the + /// lower 4 bits. + #[cfg(not(feature = "branch_factor_256"))] + #[must_use] + pub const fn join(self, other: Self) -> u8 { + self.0.join(other.0) + } + + pub(crate) const fn wrapping_next(self) -> Self { + #[cfg(not(feature = "branch_factor_256"))] + { + match crate::u4::U4::try_new(self.0.as_u8().wrapping_add(1)) { + Some(next) => Self(next), + None => Self(crate::u4::U4::MIN), + } + } + #[cfg(feature = "branch_factor_256")] + { + Self(self.0.wrapping_add(1)) + } + } +} + +impl std::fmt::Display for PathComponent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + #[cfg(not(feature = "branch_factor_256"))] + { + write!(f, "{self:X}") + } + #[cfg(feature = "branch_factor_256")] + { + write!(f, "{self:02X}") + } + } +} + +impl std::fmt::Binary for PathComponent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Binary::fmt(&self.0, f) + } +} + +impl std::fmt::LowerHex for PathComponent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::LowerHex::fmt(&self.0, f) + } +} + +impl std::fmt::UpperHex for PathComponent { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::UpperHex::fmt(&self.0, f) + } +} + +impl TriePath for PathComponent { + type Components<'a> + = std::option::IntoIter + where + Self: 'a; + + fn len(&self) -> usize { + 1 + } + + fn components(&self) -> Self::Components<'_> { + Some(*self).into_iter() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + PartialPath::Borrowed(std::slice::from_ref(self)) + } +} + +impl TriePath for Option { + type Components<'a> + = std::option::IntoIter + where + Self: 'a; + + fn len(&self) -> usize { + usize::from(self.is_some()) + } + + fn components(&self) -> Self::Components<'_> { + (*self).into_iter() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + PartialPath::Borrowed(self.as_slice()) + } +} + +impl TriePath for [PathComponent] { + type Components<'a> + = ComponentIter<'a> + where + Self: 'a; + + fn len(&self) -> usize { + self.len() + } + + fn components(&self) -> Self::Components<'_> { + self.iter().copied() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + PartialPath::Borrowed(self) + } +} + +impl TriePath for [PathComponent; N] { + type Components<'a> + = ComponentIter<'a> + where + Self: 'a; + + fn len(&self) -> usize { + N + } + + fn components(&self) -> Self::Components<'_> { + self.iter().copied() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + PartialPath::Borrowed(self) + } +} + +impl TriePath for Vec { + type Components<'a> + = ComponentIter<'a> + where + Self: 'a; + + fn len(&self) -> usize { + self.len() + } + + fn components(&self) -> Self::Components<'_> { + self.iter().copied() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + PartialPath::Borrowed(self.as_slice()) + } +} + +impl> TriePath for SmallVec { + type Components<'a> + = ComponentIter<'a> + where + Self: 'a; + + fn len(&self) -> usize { + self.len() + } + + fn components(&self) -> Self::Components<'_> { + self.iter().copied() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + PartialPath::Borrowed(self.as_slice()) + } +} + +#[cfg(not(feature = "branch_factor_256"))] +impl<'input> TriePathFromUnpackedBytes<'input> for &'input [PathComponent] { + type Error = crate::u4::TryFromIntError; + + fn path_from_unpacked_bytes(bytes: &'input [u8]) -> Result { + if bytes.iter().all(|&b| b <= 0x0F) { + #[expect(unsafe_code)] + // SAFETY: we have verified that all bytes are in the valid range for + // `U4` (0x00 to 0x0F inclusive); therefore, it is now safe for us + // to reinterpret a &[u8] as a &[PathComponent]. + Ok(unsafe { byte_slice_as_path_components_unchecked(bytes) }) + } else { + Err(crate::u4::TryFromIntError) + } + } +} + +#[cfg(not(feature = "branch_factor_256"))] +impl TriePathFromUnpackedBytes<'_> for Vec { + type Error = crate::u4::TryFromIntError; + + fn path_from_unpacked_bytes(bytes: &[u8]) -> Result { + try_from_maybe_u4(bytes.iter().copied()) + } +} + +#[cfg(not(feature = "branch_factor_256"))] +impl> TriePathFromUnpackedBytes<'_> for SmallVec { + type Error = crate::u4::TryFromIntError; + + fn path_from_unpacked_bytes(bytes: &[u8]) -> Result { + try_from_maybe_u4(bytes.iter().copied()) + } +} + +#[cfg(not(feature = "branch_factor_256"))] +impl super::TriePathFromPackedBytes<'_> for Vec { + fn path_from_packed_bytes(bytes: &'_ [u8]) -> Self { + let path = super::PackedPathRef::path_from_packed_bytes(bytes); + let mut this = Vec::new(); + // reserve_exact is used because we trust that `TriePath::len` returns the exact + // length but `Vec::extend` won't trust `Iterator::size_hint` and may + // over/under-allocate. + this.reserve_exact(path.len()); + this.extend(path.components()); + this + } +} + +#[cfg(not(feature = "branch_factor_256"))] +impl> super::TriePathFromPackedBytes<'_> for SmallVec { + fn path_from_packed_bytes(bytes: &'_ [u8]) -> Self { + let path = super::PackedPathRef::path_from_packed_bytes(bytes); + let mut this = SmallVec::::new(); + // reserve_exact is used because we trust that `TriePath::len` returns the exact + // length but `SmallVec::extend` won't trust `Iterator::size_hint` and may + // over/under-allocate. + this.reserve_exact(path.len()); + this.extend(path.components()); + this + } +} + +#[cfg(feature = "branch_factor_256")] +impl<'input> TriePathFromUnpackedBytes<'input> for &'input [PathComponent] { + type Error = std::convert::Infallible; + + fn path_from_unpacked_bytes(bytes: &'input [u8]) -> Result { + #[expect(unsafe_code)] + // SAFETY: u8 is always valid for PathComponent in 256-ary tries. + Ok(unsafe { byte_slice_as_path_components_unchecked(bytes) }) + } +} + +#[cfg(feature = "branch_factor_256")] +impl TriePathFromUnpackedBytes<'_> for Vec { + type Error = std::convert::Infallible; + + fn path_from_unpacked_bytes(bytes: &[u8]) -> Result { + Ok(bytes.iter().copied().map(PathComponent).collect()) + } +} + +#[cfg(feature = "branch_factor_256")] +impl> TriePathFromUnpackedBytes<'_> for SmallVec { + type Error = std::convert::Infallible; + + fn path_from_unpacked_bytes(bytes: &[u8]) -> Result { + Ok(bytes.iter().copied().map(PathComponent).collect()) + } +} + +impl<'input> TriePathFromUnpackedBytes<'input> for Box<[PathComponent]> { + type Error = as TriePathFromUnpackedBytes<'input>>::Error; + + fn path_from_unpacked_bytes(bytes: &'input [u8]) -> Result { + Vec::::path_from_unpacked_bytes(bytes).map(Into::into) + } +} + +impl<'input> TriePathFromUnpackedBytes<'input> for std::rc::Rc<[PathComponent]> { + type Error = as TriePathFromUnpackedBytes<'input>>::Error; + + fn path_from_unpacked_bytes(bytes: &'input [u8]) -> Result { + Vec::::path_from_unpacked_bytes(bytes).map(Into::into) + } +} + +impl<'input> TriePathFromUnpackedBytes<'input> for std::sync::Arc<[PathComponent]> { + type Error = as TriePathFromUnpackedBytes<'input>>::Error; + + fn path_from_unpacked_bytes(bytes: &'input [u8]) -> Result { + Vec::::path_from_unpacked_bytes(bytes).map(Into::into) + } +} + +// these must also only be included when `branch_factor_256` is not enabled otherwise +// they would conflict with the blanket impl of TriePathFromPackedBytes over +// TriePathFromUnpackedBytes + +#[cfg(not(feature = "branch_factor_256"))] +impl super::TriePathFromPackedBytes<'_> for Box<[PathComponent]> { + fn path_from_packed_bytes(bytes: &[u8]) -> Self { + Vec::::path_from_packed_bytes(bytes).into() + } +} + +#[cfg(not(feature = "branch_factor_256"))] +impl super::TriePathFromPackedBytes<'_> for std::rc::Rc<[PathComponent]> { + fn path_from_packed_bytes(bytes: &[u8]) -> Self { + Vec::::path_from_packed_bytes(bytes).into() + } +} + +#[cfg(not(feature = "branch_factor_256"))] +impl super::TriePathFromPackedBytes<'_> for std::sync::Arc<[PathComponent]> { + fn path_from_packed_bytes(bytes: &[u8]) -> Self { + Vec::::path_from_packed_bytes(bytes).into() + } +} + +impl PathComponentSliceExt for [PathComponent] { + fn as_byte_slice(&self) -> &[u8] { + path_components_as_byte_slice(self) + } +} + +impl> PathComponentSliceExt for T { + fn as_byte_slice(&self) -> &[u8] { + path_components_as_byte_slice(self) + } +} + +#[inline] +const unsafe fn byte_slice_as_path_components_unchecked(bytes: &[u8]) -> &[PathComponent] { + #![expect(unsafe_code)] + + // SAFETY: The caller must ensure that all bytes are valid for `PathComponent`, + // which is trivially true for 256-ary tries. For hexary tries, the caller must + // ensure that each byte is in the range 0x00 to 0x0F inclusive. + // + // We also rely on the fact that `PathComponent` is a single element type + // over `u8` (or `u4` which looks like a `u8` for this purpose). + // + // borrow rules ensure that the pointer for `bytes` is not null and + // `bytes.len()` is always valid. The returned reference will have the same + // lifetime as `bytes` so it cannot outlive the original slice. + unsafe { + &*(std::ptr::slice_from_raw_parts(bytes.as_ptr().cast::(), bytes.len())) + } +} + +#[inline] +const fn path_components_as_byte_slice(components: &[PathComponent]) -> &[u8] { + #![expect(unsafe_code)] + + // SAFETY: We rely on the fact that `PathComponent` is a single element type + // over `u8` (or `u4` which looks like a `u8` for this purpose). + // + // borrow rules ensure that the pointer for `components` is not null and + // `components.len()` is always valid. The returned reference will have the same + // lifetime as `components` so it cannot outlive the original slice. + unsafe { + &*(std::ptr::slice_from_raw_parts(components.as_ptr().cast::(), components.len())) + } +} + +#[inline] +#[cfg(not(feature = "branch_factor_256"))] +fn try_from_maybe_u4>( + bytes: impl IntoIterator, +) -> Result { + bytes + .into_iter() + .map(PathComponent::try_new) + .collect::>() + .ok_or(crate::u4::TryFromIntError) +} + +#[cfg(test)] +mod tests { + use std::marker::PhantomData; + + use test_case::test_case; + + use super::*; + + #[cfg_attr(not(feature = "branch_factor_256"), test_case(PhantomData::<&[PathComponent]>; "slice"))] + #[cfg_attr(not(feature = "branch_factor_256"), test_case(PhantomData::>; "boxed slice"))] + #[cfg_attr(not(feature = "branch_factor_256"), test_case(PhantomData::>; "vec"))] + #[cfg_attr(not(feature = "branch_factor_256"), test_case(PhantomData::>; "smallvec"))] + #[cfg_attr(feature = "branch_factor_256", test_case(PhantomData::<&[PathComponent]>; "slice"))] + #[cfg_attr(feature = "branch_factor_256", test_case(PhantomData::>; "boxed slice"))] + #[cfg_attr(feature = "branch_factor_256", test_case(PhantomData::>; "vec"))] + #[cfg_attr(feature = "branch_factor_256", test_case(PhantomData::>; "smallvec"))] + fn test_path_from_unpacked_bytes_hexary(_: PhantomData) + where + T: TriePathFromUnpackedBytes<'static, Error: std::fmt::Debug>, + { + let input: &[u8; _] = &[0x00, 0x01, 0x0A, 0x0F]; + let output = ::path_from_unpacked_bytes(input).expect("valid input"); + + assert_eq!(output.len(), input.len()); + assert_eq!( + output + .components() + .map(PathComponent::as_u8) + .zip(input.iter().copied()) + .take_while(|&(pc, b)| pc == b) + .count(), + input.len(), + ); + } + + #[cfg(not(feature = "branch_factor_256"))] + #[test_case(PhantomData::<&[PathComponent]>; "slice")] + #[test_case(PhantomData::>; "boxed slice")] + #[test_case(PhantomData::>; "vec")] + #[test_case(PhantomData::>; "smallvec")] + fn test_path_from_unpacked_bytes_hexary_invalid(_: PhantomData) + where + T: TriePathFromUnpackedBytes<'static> + std::fmt::Debug, + { + let input: &[u8; _] = &[0x00, 0x10, 0x0A, 0x0F]; + let _ = ::path_from_unpacked_bytes(input).expect_err("invalid input"); + } + + #[test] + fn test_joined_path() { + let path = <&[PathComponent] as TriePathFromUnpackedBytes>::path_from_unpacked_bytes(&[ + 0x0A, 0x0B, 0x0C, + ]) + .expect("valid input"); + + let with_suffix = path.append(PathComponent::try_new(0x0D).expect("valid")); + assert_eq!(with_suffix.len(), 4); + assert_eq!( + with_suffix + .components() + .map(PathComponent::as_u8) + .collect::>(), + vec![0x0A, 0x0B, 0x0C, 0x0D], + ); + + let with_prefix = with_suffix.prepend(PathComponent::try_new(0x09).expect("valid")); + assert_eq!(with_prefix.len(), 5); + assert_eq!( + with_prefix + .components() + .map(PathComponent::as_u8) + .collect::>(), + vec![0x09, 0x0A, 0x0B, 0x0C, 0x0D], + ); + } +} diff --git a/firewood/storage/src/path/joined.rs b/firewood/storage/src/path/joined.rs new file mode 100644 index 000000000000..13369454dece --- /dev/null +++ b/firewood/storage/src/path/joined.rs @@ -0,0 +1,111 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::iter::Chain; + +use super::{SplitPath, TriePath}; + +/// Joins two path segments into a single path, retaining the original segments +/// without needing to allocate a new contiguous array. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +pub struct JoinedPath { + /// The prefix segment of the path. + pub prefix: P, + + /// The suffix segment of the path. + pub suffix: S, +} + +impl JoinedPath { + /// Creates a new joined path from the given prefix and suffix. + /// + /// This does not allocate and takes ownership of the input segments. + pub const fn new(prefix: P, suffix: S) -> Self { + Self { prefix, suffix } + } +} + +impl TriePath for JoinedPath { + type Components<'a> + = Chain, S::Components<'a>> + where + Self: 'a; + + fn len(&self) -> usize { + self.prefix + .len() + .checked_add(self.suffix.len()) + .expect("joined path length overflowed usize") + } + + fn is_empty(&self) -> bool { + self.prefix.is_empty() && self.suffix.is_empty() + } + + fn components(&self) -> Self::Components<'_> { + self.prefix.components().chain(self.suffix.components()) + } + + fn as_component_slice(&self) -> super::PartialPath<'_> { + if self.prefix.is_empty() { + self.suffix.as_component_slice() + } else if self.suffix.is_empty() { + self.prefix.as_component_slice() + } else { + let mut buf = super::PathBuf::with_capacity(self.len()); + buf.extend(self.prefix.components()); + buf.extend(self.suffix.components()); + super::PartialPath::Owned(buf) + } + } +} + +impl SplitPath for JoinedPath { + fn split_at(self, mid: usize) -> (Self, Self) { + if let Some(mid) = mid.checked_sub(self.prefix.len()) { + let (a_suffix, b_suffix) = self.suffix.split_at(mid); + let prefix: Self = Self { + prefix: self.prefix, + suffix: a_suffix, + }; + let suffix = Self { + prefix: P::default(), + suffix: b_suffix, + }; + (prefix, suffix) + } else { + let (a_prefix, b_prefix) = self.prefix.split_at(mid); + let prefix = Self { + prefix: a_prefix, + suffix: S::default(), + }; + let suffix: Self = Self { + prefix: b_prefix, + suffix: self.suffix, + }; + (prefix, suffix) + } + } + + fn split_first(self) -> Option<(super::PathComponent, Self)> { + if let Some((first, prefix)) = self.prefix.split_first() { + Some(( + first, + Self { + prefix, + suffix: self.suffix, + }, + )) + } else if let Some((first, suffix)) = self.suffix.split_first() { + Some(( + first, + Self { + prefix: P::default(), + suffix, + }, + )) + } else { + None + } + } +} diff --git a/firewood/storage/src/path/mod.rs b/firewood/storage/src/path/mod.rs new file mode 100644 index 000000000000..54aad8145a7b --- /dev/null +++ b/firewood/storage/src/path/mod.rs @@ -0,0 +1,302 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +mod buf; +mod component; +mod joined; +#[cfg(not(feature = "branch_factor_256"))] +mod packed; +mod split; + +pub use self::buf::{PartialPath, PathBuf, PathGuard}; +pub use self::component::{ComponentIter, PathComponent, PathComponentSliceExt}; +pub use self::joined::JoinedPath; +#[cfg(not(feature = "branch_factor_256"))] +pub use self::packed::{PackedBytes, PackedPathComponents, PackedPathRef}; +pub use self::split::{IntoSplitPath, PathCommonPrefix, SplitPath}; + +/// A trie path of components with different underlying representations. +/// +/// The underlying representation does not need to be a contiguous array of +/// [`PathComponent`], but it must be possible to iterate over them in order +/// as well as have a known length. +pub trait TriePath { + /// The iterator returned by [`TriePath::components`]. + type Components<'a>: Iterator + Clone + 'a + where + Self: 'a; + + /// The length, in path components, of this path. + fn len(&self) -> usize; + + /// Returns true if this path is empty (i.e. has length 0). + fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns an iterator over the components of this path. + fn components(&self) -> Self::Components<'_>; + + /// Returns a contiguous view of this path's components. + /// + /// If the underlying representation is already contiguous, this should be a + /// cheap operation (i.e. no allocations or copies). If not, this may allocate + /// and copy the components into a contiguous buffer. + fn as_component_slice(&self) -> PartialPath<'_>; + + /// Appends the provided path segment to this path, returning a new joined + /// path that represents the concatenation of the two paths. + /// + /// The returned path is a view over the two input paths and does not + /// allocate. The input paths are consumed and ownership is taken. + fn append(self, suffix: S) -> JoinedPath + where + Self: Sized, + S: TriePath, + { + JoinedPath::new(self, suffix) + } + + /// Prepends the provided path segment to this path, returning a new joined + /// path that represents the concatenation of the two paths. + /// + /// The inverse of [`TriePath::append`]. + /// + /// The returned path is a view over the two input paths and does not + /// allocate. The input paths are consumed and ownership is taken. + fn prepend

(self, prefix: P) -> JoinedPath + where + Self: Sized, + P: TriePath, + { + prefix.append(self) + } + + /// Compares this path against another path for equality using path component + /// equality. + /// + /// This is analogous to [`Iterator::eq`] and is different than [`PartialEq`] + /// which may have different semantics depending on the underlying type and + /// representation as well as may not be implemented for the cross-type + /// comparisons. + fn path_eq(&self, other: &T) -> bool { + self.len() == other.len() && self.components().eq(other.components()) + } + + /// Compares this path against another path using path-component lexicographic + /// ordering. Strict prefixes are less than their longer counterparts. + /// + /// This is analogous to [`Iterator::cmp`] and is different than [`Ord`] + /// which may have different semantics depending on the underlying type and + /// representation as well as may not be implemented for the cross-type + /// comparisons. + fn path_cmp(&self, other: &T) -> std::cmp::Ordering { + self.components().cmp(other.components()) + } + + /// Returns a wrapper type that implements [`std::fmt::Display`] and + /// [`std::fmt::Debug`] for this path. + fn display(&self) -> DisplayPath<'_, Self> { + DisplayPath { path: self } + } +} + +/// Constructor for a trie path from a set of unpacked bytes; where each byte +/// is a whole path component regardless of the normal width of a path component. +/// +/// For 256-ary tries, this is the bytes as-is. +/// +/// For hexary tries, each byte must occupy only the lower 4 bits. Any byte with +/// a bit set in the upper 4 bits will result in an error. +pub trait TriePathFromUnpackedBytes<'input>: TriePath + Sized { + /// The error type returned if the bytes are invalid. + type Error; + + /// Constructs a path from the given unpacked bytes. + /// + /// For hexary tries, each byte must be in the range 0x00 to 0x0F inclusive. + /// Any byte outside this range will result in an error. + /// + /// # Errors + /// + /// - The input is invalid. + fn path_from_unpacked_bytes(bytes: &'input [u8]) -> Result; +} + +/// Constructor for a trie path from a set of packed bytes; where each byte contains +/// as many path components as possible. +/// +/// For 256-ary tries, this is just the bytes as-is. +/// +/// For hexary tries, each byte contains two path components; one in the upper 4 +/// bits and one in the lower 4 bits, in big-endian order. The resulting path +/// will always have an even length (`bytes.len() * 2`). +/// +/// For future compatibility, this trait only supports paths where the width of +/// a path component is a factor of 8 (i.e. 1, 2, 4, or 8 bits). +pub trait TriePathFromPackedBytes<'input>: Sized { + /// Constructs a path from the given packed bytes. + fn path_from_packed_bytes(bytes: &'input [u8]) -> Self; +} + +/// Converts this path to an iterator over its packed bytes. +pub trait TriePathAsPackedBytes { + /// The iterator type returned by [`TriePathAsPackedBytes::as_packed_bytes`]. + type PackedBytesIter<'a>: Iterator + where + Self: 'a; + + /// Returns an iterator over the packed bytes of this path. + /// + /// If the final path component does not fill a whole byte, it is padded with zero. + fn as_packed_bytes(&self) -> Self::PackedBytesIter<'_>; +} + +/// Blanket implementation of [`TriePathFromPackedBytes`] for 256-ary tries +/// because packed bytes and unpacked bytes are identical. +#[cfg(feature = "branch_factor_256")] +impl<'input, T> TriePathFromPackedBytes<'input> for T +where + T: TriePathFromUnpackedBytes<'input, Error = std::convert::Infallible>, +{ + fn path_from_packed_bytes(bytes: &'input [u8]) -> Self { + match Self::path_from_unpacked_bytes(bytes) { + Ok(p) => p, + // no Err(_) branch because Infallible is an uninhabited type and + // cannot be represented, therefore a match on is impossible + } + } +} + +#[cfg(feature = "branch_factor_256")] +impl TriePathAsPackedBytes for T { + type PackedBytesIter<'a> + = std::iter::Map, fn(PathComponent) -> u8> + where + Self: 'a; + + fn as_packed_bytes(&self) -> Self::PackedBytesIter<'_> { + self.components().map(PathComponent::as_u8) + } +} + +#[inline] +fn display_path( + f: &mut std::fmt::Formatter<'_>, + mut comp: impl Iterator, +) -> std::fmt::Result { + comp.try_for_each(|c| write!(f, "{c}")) +} + +/// A wrapper type that implements [`Display`](std::fmt::Display) and +/// [`Debug`](std::fmt::Debug) for any type that implements [`TriePath`]. +pub struct DisplayPath<'a, P: TriePath + ?Sized> { + path: &'a P, +} + +impl std::fmt::Debug for DisplayPath<'_, P> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + display_path(f, self.path.components()) + } +} + +impl std::fmt::Display for DisplayPath<'_, P> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + display_path(f, self.path.components()) + } +} + +impl TriePath for &T { + type Components<'a> + = T::Components<'a> + where + Self: 'a; + + fn len(&self) -> usize { + (**self).len() + } + + fn components(&self) -> Self::Components<'_> { + (**self).components() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + (**self).as_component_slice() + } +} + +impl TriePath for &mut T { + type Components<'a> + = T::Components<'a> + where + Self: 'a; + + fn len(&self) -> usize { + (**self).len() + } + + fn components(&self) -> Self::Components<'_> { + (**self).components() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + (**self).as_component_slice() + } +} + +impl TriePath for Box { + type Components<'a> + = T::Components<'a> + where + Self: 'a; + + fn len(&self) -> usize { + (**self).len() + } + + fn components(&self) -> Self::Components<'_> { + (**self).components() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + (**self).as_component_slice() + } +} + +impl TriePath for std::rc::Rc { + type Components<'a> + = T::Components<'a> + where + Self: 'a; + + fn len(&self) -> usize { + (**self).len() + } + + fn components(&self) -> Self::Components<'_> { + (**self).components() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + (**self).as_component_slice() + } +} + +impl TriePath for std::sync::Arc { + type Components<'a> + = T::Components<'a> + where + Self: 'a; + + fn len(&self) -> usize { + (**self).len() + } + + fn components(&self) -> Self::Components<'_> { + (**self).components() + } + + fn as_component_slice(&self) -> PartialPath<'_> { + (**self).as_component_slice() + } +} diff --git a/firewood/storage/src/path/packed.rs b/firewood/storage/src/path/packed.rs new file mode 100644 index 000000000000..d53e7f5d3eb2 --- /dev/null +++ b/firewood/storage/src/path/packed.rs @@ -0,0 +1,461 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::TriePathAsPackedBytes; + +use super::{PathComponent, SplitPath, TriePath, TriePathFromPackedBytes}; + +/// A packed representation of a trie path where each byte encodes two path components. +/// +/// This is borrowed over the underlying byte slice and does not allocate. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub struct PackedPathRef<'a> { + prefix: Option, + middle: &'a [u8], + suffix: Option, +} + +/// An iterator over the components of a [`PackedPathRef`]. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct PackedPathComponents<'a> { + path: PackedPathRef<'a>, +} + +/// An iterator over the components of a path that yields them packed into bytes. +/// +/// If there is a trailing component without a pair, it is padded with zero. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct PackedBytes { + iter: I, +} + +impl> PackedBytes { + /// Creates a new iterator over the packed bytes of the given component iterator. + pub const fn new(iter: I) -> Self { + Self { iter } + } +} + +impl TriePath for PackedPathRef<'_> { + type Components<'a> + = PackedPathComponents<'a> + where + Self: 'a; + + fn len(&self) -> usize { + self.middle + .len() + .wrapping_mul(2) + .wrapping_add(usize::from(self.prefix.is_some())) + .wrapping_add(usize::from(self.suffix.is_some())) + } + + fn components(&self) -> Self::Components<'_> { + PackedPathComponents { path: *self } + } + + fn as_component_slice(&self) -> super::PartialPath<'_> { + if self.is_empty() { + super::PartialPath::Borrowed(&[]) + } else { + let mut buf = super::PathBuf::with_capacity(self.len()); + if let Some(prefix) = self.prefix { + buf.push(prefix); + } + for &byte in self.middle { + let (upper, lower) = PathComponent::new_pair(byte); + buf.push(upper); + buf.push(lower); + } + if let Some(suffix) = self.suffix { + buf.push(suffix); + } + super::PartialPath::Owned(buf) + } + } +} + +impl SplitPath for PackedPathRef<'_> { + fn split_at(self, mid: usize) -> (Self, Self) { + assert!(mid <= self.len(), "mid > self.len()"); + + if let Some(mid) = mid.checked_sub(usize::from(self.prefix.is_some())) { + // the mid consumed the prefix, if it existed + if mid.is_multiple_of(2) { + // middle is split cleanly + let (a_middle, b_middle) = self.middle.split_at(mid / 2); + let prefix = Self { + prefix: self.prefix, + middle: a_middle, + suffix: None, + }; + let suffix = Self { + prefix: None, + middle: b_middle, + suffix: self.suffix, + }; + (prefix, suffix) + } else { + // mid splits a middle component into the suffix of `prefix` and the + // prefix of `suffix` + let (a_middle, b_middle) = self.middle.split_at(mid / 2); + let Some((&middle_byte, b_middle)) = b_middle.split_first() else { + // `mid` is oob of `b_middle`, which happens if self.suffix is Some, + // and `mid` is self.len() + return (self, Self::default()); + }; + + let (upper, lower) = PathComponent::new_pair(middle_byte); + let prefix = Self { + prefix: self.prefix, + middle: a_middle, + suffix: Some(upper), + }; + let suffix = Self { + prefix: Some(lower), + middle: b_middle, + suffix: self.suffix, + }; + (prefix, suffix) + } + } else { + // `prefix` is some and `mid` is zero + (Self::default(), self) + } + } + + fn split_first(self) -> Option<(PathComponent, Self)> { + let mut iter = self.into_iter(); + let first = iter.next()?; + Some((first, iter.path)) + } +} + +impl<'input> TriePathFromPackedBytes<'input> for PackedPathRef<'input> { + fn path_from_packed_bytes(bytes: &'input [u8]) -> Self { + Self { + prefix: None, + middle: bytes, + suffix: None, + } + } +} + +impl<'a> IntoIterator for PackedPathRef<'a> { + type Item = PathComponent; + + type IntoIter = PackedPathComponents<'a>; + + fn into_iter(self) -> Self::IntoIter { + PackedPathComponents { path: self } + } +} + +impl Iterator for PackedPathComponents<'_> { + type Item = PathComponent; + + fn next(&mut self) -> Option { + if let Some(next) = self.path.prefix.take() { + return Some(next); + } + + if let Some((&next, rest)) = self.path.middle.split_first() { + let (upper, lower) = PathComponent::new_pair(next); + self.path.prefix = Some(lower); + self.path.middle = rest; + return Some(upper); + } + + self.path.suffix.take() + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.path.len(); + (len, Some(len)) + } +} + +impl DoubleEndedIterator for PackedPathComponents<'_> { + fn next_back(&mut self) -> Option { + if let Some(next) = self.path.suffix.take() { + return Some(next); + } + + if let Some((&last, rest)) = self.path.middle.split_last() { + let (upper, lower) = PathComponent::new_pair(last); + self.path.suffix = Some(upper); + self.path.middle = rest; + return Some(lower); + } + + self.path.prefix.take() + } +} + +impl ExactSizeIterator for PackedPathComponents<'_> {} + +impl std::iter::FusedIterator for PackedPathComponents<'_> {} + +impl> Iterator for PackedBytes { + type Item = u8; + + fn next(&mut self) -> Option { + let hi = self.iter.next()?; + let lo = self.iter.next().unwrap_or(const { PathComponent::ALL[0] }); + Some(hi.join(lo)) + } + + fn size_hint(&self) -> (usize, Option) { + let (lower, upper) = self.iter.size_hint(); + let lower = lower.div_ceil(2); + let upper = upper.map(|u| u.div_ceil(2)); + (lower, upper) + } +} + +impl> DoubleEndedIterator for PackedBytes { + fn next_back(&mut self) -> Option { + let lo = self.iter.next_back()?; + let hi = self + .iter + .next_back() + .unwrap_or(const { PathComponent::ALL[0] }); + Some(hi.join(lo)) + } +} + +impl> ExactSizeIterator for PackedBytes {} + +impl> std::iter::FusedIterator + for PackedBytes +{ +} + +impl TriePathAsPackedBytes for T { + type PackedBytesIter<'a> + = PackedBytes> + where + Self: 'a; + + fn as_packed_bytes(&self) -> Self::PackedBytesIter<'_> { + PackedBytes::new(self.components()) + } +} + +#[cfg(test)] +mod tests { + #![expect(clippy::unwrap_used)] + + // NB: tests do not need to worry about 256-ary tries because this module is + // only compiled when the "branch_factor_256" feature is not enabled. + + use test_case::test_case; + + use super::*; + + /// Yields a [`PathComponent`] failing to compile if the given expression is + /// not a valid path component. + macro_rules! pc { + ($elem:expr) => { + const { PathComponent::ALL[$elem] } + }; + } + + /// Yields an array of [`PathComponent`]s failing to compile if any of the + /// given expressions are not valid path components. + /// + /// The expression yields an array, not a slice, and a reference must be taken + /// to convert it to a slice. + macro_rules! path { + ($($elem:expr),* $(,)?) => { + [ $( pc!($elem), )* ] + }; + } + + struct FromPackedBytesTest<'a> { + bytes: &'a [u8], + components: &'a [PathComponent], + } + + #[test_case( + FromPackedBytesTest{ + bytes: &[], + components: &path![], + }; + "empty path" + )] + #[test_case( + FromPackedBytesTest{ + bytes: b"a", + components: &path![6, 1], + }; + "single byte path" + )] + #[test_case( + FromPackedBytesTest{ + bytes: b"abc", + components: &path![6, 1, 6, 2, 6, 3], + }; + "multi-byte path" + )] + fn test_from_packed_bytes(case: FromPackedBytesTest<'_>) { + let path = PackedPathRef::path_from_packed_bytes(case.bytes); + assert_eq!(path.len(), case.components.len()); + + assert!(path.components().eq(case.components.iter().copied())); + assert!( + path.components() + .rev() + .eq(case.components.iter().copied().rev()) + ); + + assert!(path.as_packed_bytes().eq(case.bytes.iter().copied())); + assert!( + path.as_packed_bytes() + .rev() + .eq(case.bytes.iter().copied().rev()) + ); + + assert!(TriePath::path_eq(&path, &case.components)); + assert!(TriePath::path_cmp(&path, &case.components).is_eq()); + } + + struct SplitAtTest<'a> { + path: PackedPathRef<'a>, + mid: usize, + a: &'a [PathComponent], + b: &'a [PathComponent], + } + + #[test_case( + SplitAtTest{ + path: PackedPathRef::path_from_packed_bytes(b""), + mid: 0, + a: &path![], + b: &path![], + }; + "empty path" + )] + #[test_case( + SplitAtTest{ + path: PackedPathRef::path_from_packed_bytes(b"a"), + mid: 0, + a: &path![], + b: &path![6, 1], + }; + "single byte path, split at 0" + )] + #[test_case( + SplitAtTest{ + path: PackedPathRef::path_from_packed_bytes(b"a"), + mid: 1, + a: &path![6], + b: &path![1], + }; + "single byte path, split at 1" + )] + #[test_case( + SplitAtTest{ + path: PackedPathRef::path_from_packed_bytes(b"a"), + mid: 2, + a: &path![6, 1], + b: &path![], + }; + "single byte path, split at len" + )] + #[test_case( + SplitAtTest{ + path: PackedPathRef::path_from_packed_bytes(b"abc"), + mid: 2, + a: &path![6, 1], + b: &path![6, 2, 6, 3], + }; + "multi byte path, split at 2" + )] + fn test_split_at(case: SplitAtTest<'_>) { + let (a, b) = case.path.split_at(case.mid); + assert_eq!(a.len(), case.mid); + assert_eq!(a.len().wrapping_add(b.len()), case.path.len()); + assert!(a.path_eq(&case.a)); + assert!(b.path_eq(&case.b)); + assert!(a.append(b).path_eq(&case.path)); + if let Some(mid) = case.mid.checked_sub(1) { + let (_, path) = dbg!(case.path.split_first()).unwrap(); + let (_, b) = dbg!(path.split_at(mid)); + assert!( + b.path_eq(&case.b), + "{} != {} ({}) (mid = {mid})", + b.display(), + case.b.display(), + path.display(), + ); + } + if let Some(len) = case.path.len().checked_sub(1) + && len >= case.mid + { + let (path, _) = dbg!(case.path.split_at(len)); + let (a, _) = dbg!(path.split_at(case.mid)); + assert!( + a.path_eq(&case.a), + "{} != {} ({}) (len = {len})", + a.display(), + case.a.display(), + path.display(), + ); + } + } + + struct AsPackedBytesTest<'a, T> { + path: T, + expected: &'a [u8], + } + + #[test_case( + AsPackedBytesTest { + path: PackedPathRef::path_from_packed_bytes(&[]), + expected: &[], + }; + "empty packed path" + )] + #[test_case( + AsPackedBytesTest::<&[PathComponent]> { + path: &[], + expected: &[], + }; + "empty unpacked path" + )] + #[test_case( + AsPackedBytesTest { + path: PackedPathRef::path_from_packed_bytes(b"abc"), + expected: b"abc", + }; + "multi-byte packed path" + )] + #[test_case( + AsPackedBytesTest::<&[PathComponent]> { + path: &[PathComponent::ALL[6]], + expected: &[0x60], + }; + "odd-lengthed unpacked path" + )] + #[test_case( + AsPackedBytesTest::<&[PathComponent]> { + path: &[PathComponent::ALL[6], PathComponent::ALL[1]], + expected: &[0x61], + }; + "even-lengthed unpacked path" + )] + #[test_case( + AsPackedBytesTest::<&[PathComponent]> { + path: &[PathComponent::ALL[6], PathComponent::ALL[1], PathComponent::ALL[2]], + expected: &[0x61, 0x20], + }; + "three-length unpacked path" + )] + fn test_as_packed_bytes(case: AsPackedBytesTest<'_, T>) { + let as_packed = case.path.as_packed_bytes().collect::>(); + assert_eq!(*as_packed, *case.expected); + } +} diff --git a/firewood/storage/src/path/split.rs b/firewood/storage/src/path/split.rs new file mode 100644 index 000000000000..b37590f93fec --- /dev/null +++ b/firewood/storage/src/path/split.rs @@ -0,0 +1,263 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use smallvec::SmallVec; + +use super::{PathComponent, TriePath}; + +/// A trie path that can be (cheaply) split into two sub-paths. +/// +/// Implementations are expected to be cheap to split (i.e. no allocations). +pub trait SplitPath: TriePath + Default + Copy { + /// Splits the path at the given index within the path. + /// + /// The returned tuple contains the two sub-paths `(prefix, suffix)`. + /// + /// # Panics + /// + /// - If `mid > self.len()`. + fn split_at(self, mid: usize) -> (Self, Self); + + /// Splits the first path component off of this path, returning it along with + /// the remaining path. + /// + /// Returns [`None`] if the path is empty. + fn split_first(self) -> Option<(PathComponent, Self)>; + + /// Computes the longest common prefix of this path and another path, along + /// with their respective suffixes. + fn longest_common_prefix(self, other: T) -> PathCommonPrefix { + PathCommonPrefix::new(self, other) + } +} + +/// A type that can be converted into a splittable path. +/// +/// This trait is analogous to [`IntoIterator`] for [`Iterator`] but for trie +/// paths instead of iterators. +/// +/// Like `IntoIterator`, a blanket implementation is provided for all types that +/// already implement [`SplitPath`]. +pub trait IntoSplitPath: TriePath { + /// The splittable path type derived from this type. + type Path: SplitPath; + + /// Converts this type into a splittable path. + #[must_use] + fn into_split_path(self) -> Self::Path; +} + +impl IntoSplitPath for T { + type Path = T; + + #[inline] + fn into_split_path(self) -> Self::Path { + self + } +} + +/// The common prefix of two paths, along with their respective suffixes. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct PathCommonPrefix { + /// The common prefix of the two paths. + pub common: C, + /// The suffix of the first path after the common prefix. + pub a_suffix: A, + /// The suffix of the second path after the common prefix. + pub b_suffix: B, +} + +impl PathCommonPrefix { + /// Computes the common prefix of the two given paths, along with their suffixes. + pub fn new(a: A, b: B) -> Self { + let mid = a + .components() + .zip(b.components()) + .take_while(|&(a, b)| a == b) + .count(); + let (common, a_suffix) = a.split_at(mid); + let (_, b_suffix) = b.split_at(mid); + Self { + common, + a_suffix, + b_suffix, + } + } +} + +impl PathCommonPrefix { + /// Converts this into its constituent parts, where the suffixes are + /// optionally empty. + #[expect(clippy::type_complexity)] + pub fn split_first_parts(self) -> (Option<(PathComponent, A)>, Option<(PathComponent, B)>, C) { + ( + self.a_suffix.split_first(), + self.b_suffix.split_first(), + self.common, + ) + } +} + +impl SplitPath for &[PathComponent] { + fn split_at(self, mid: usize) -> (Self, Self) { + self.split_at(mid) + } + + fn split_first(self) -> Option<(PathComponent, Self)> { + match self.split_first() { + Some((&first, rest)) => Some((first, rest)), + None => None, + } + } +} + +impl<'a, const N: usize> IntoSplitPath for &'a [PathComponent; N] { + type Path = &'a [PathComponent]; + + fn into_split_path(self) -> Self::Path { + self + } +} + +impl<'a> IntoSplitPath for &'a Vec { + type Path = &'a [PathComponent]; + + fn into_split_path(self) -> Self::Path { + self + } +} + +impl<'a, A: smallvec::Array> IntoSplitPath for &'a SmallVec { + type Path = &'a [PathComponent]; + + fn into_split_path(self) -> Self::Path { + self + } +} + +#[cfg(test)] +mod tests { + use test_case::test_case; + + use super::*; + + /// Yields a [`PathComponent`] failing to compile if the given expression is + /// not a valid path component. + macro_rules! pc { + ($elem:expr) => { + const { PathComponent::ALL[$elem] } + }; + } + + /// Yields an array of [`PathComponent`]s failing to compile if any of the + /// given expressions are not valid path components. + /// + /// The expression yields an array, not a slice, and a reference must be taken + /// to convert it to a slice. + macro_rules! path { + ($($elem:expr),* $(,)?) => { + [ $( pc!($elem), )* ] + }; + } + + struct LcpTest<'a> { + a: &'a [PathComponent], + b: &'a [PathComponent], + expected_common: &'a [PathComponent], + expected_a_suffix: &'a [PathComponent], + expected_b_suffix: &'a [PathComponent], + } + + #[test_case( + LcpTest { + a: &path![1, 2, 3], + b: &path![1, 2, 3], + expected_common: &path![1, 2, 3], + expected_a_suffix: &path![], + expected_b_suffix: &path![], + }; + "identical paths" + )] + #[test_case( + LcpTest { + a: &path![1, 2, 3], + b: &path![1, 2, 4], + expected_common: &path![1, 2], + expected_a_suffix: &path![3], + expected_b_suffix: &path![4], + }; + "diverging paths" + )] + #[test_case( + LcpTest { + a: &path![1, 2, 3], + b: &path![1, 2, 3, 4, 5], + expected_common: &path![1, 2, 3], + expected_a_suffix: &path![], + expected_b_suffix: &path![4, 5], + }; + "a is a strict prefix of b" + )] + #[test_case( + LcpTest { + a: &path![1, 2, 3, 4, 5], + b: &path![1, 2, 3], + expected_common: &path![1, 2, 3], + expected_a_suffix: &path![4, 5], + expected_b_suffix: &path![], + }; + "b is a strict prefix of a" + )] + #[test_case( + LcpTest { + a: &path![1, 2, 3], + b: &path![4, 5, 6], + expected_common: &path![], + expected_a_suffix: &path![1, 2, 3], + expected_b_suffix: &path![4, 5, 6], + }; + "no common prefix" + )] + fn test_longest_common_prefix(case: LcpTest<'_>) { + let PathCommonPrefix { + common, + a_suffix, + b_suffix, + } = SplitPath::longest_common_prefix(case.a, case.b); + + assert_eq!(common, case.expected_common); + assert_eq!(a_suffix, case.expected_a_suffix); + assert_eq!(b_suffix, case.expected_b_suffix); + } + + struct SplitFirstTest<'a> { + path: &'a [PathComponent], + expected: Option<(PathComponent, &'a [PathComponent])>, + } + + #[test_case( + SplitFirstTest { + path: &path![], + expected: None, + }; + "empty path" + )] + #[test_case( + SplitFirstTest{ + path: &path![1], + expected: Some((pc!(1), &path![])), + }; + "single element path" + )] + #[test_case( + SplitFirstTest{ + path: &path![1, 2, 3], + expected: Some((pc!(1), &path![2, 3])), + }; + "path with multiple elements" + )] + fn test_split_first(case: SplitFirstTest<'_>) { + let result = SplitPath::split_first(case.path); + assert_eq!(result, case.expected); + } +} diff --git a/firewood/storage/src/test_utils.rs b/firewood/storage/src/test_utils.rs new file mode 100644 index 000000000000..c9baefb050dd --- /dev/null +++ b/firewood/storage/src/test_utils.rs @@ -0,0 +1,168 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use std::cell::RefCell; +use std::rc::Rc; + +#[expect( + clippy::disallowed_types, + reason = "we are implementing the alternative" +)] +use rand::rngs::StdRng; +#[expect( + clippy::disallowed_types, + reason = "we are implementing the alternative" +)] +use rand::{RngCore, SeedableRng, TryRngCore}; + +#[derive(Debug, Clone)] +#[must_use] +/// A seeded random number generator for testing purposes. +#[expect( + clippy::disallowed_types, + reason = "we are implementing the alternative" +)] +pub struct SeededRng(Rc>); + +const ENV: &str = "FIREWOOD_TEST_SEED"; +// `concat!` does not work with constants, only literals and certain special expressions, +const EXPECT: &str = "FIREWOOD_TEST_SEED, when present, must contain a valid u64 value"; + +impl SeededRng { + /// Creates a new `SeededRng` with the given seed. + pub fn new(seed: u64) -> Self { + #![expect( + clippy::disallowed_types, + reason = "we are implementing the alternative" + )] + // we do not log here so that we don't log if `from_option` was used with + // a `Some` value (the seed did not come from the environment) + Self(Rc::new(RefCell::new(StdRng::seed_from_u64(seed)))) + } + + /// Creates a new `SeededRng` from an `Option`. + /// + /// If the provided value is `None`, [`SeededRng::from_env_or_random`] will + /// be used to check the environment variable or otherwise generate a random seed. + pub fn from_option(seed: Option) -> Self { + seed.map_or_else(Self::from_env_or_random, Self::new) + } + + /// Creates a new `SeededRng` from an environment variable set seed. + /// + /// # Returns + /// + /// None if the environment variable is not set, otherwise a [`SeededRng`] + /// with the seed initialized. + /// + /// # Panics + /// + /// Panics if the environment variable is present but is not a valid `u64`. + #[track_caller] + #[must_use] + pub fn from_env() -> Option { + let seed = std::env::var_os(ENV)? + .into_string() + .ok() + .and_then(|s| s.parse().ok()) + .expect(EXPECT); + eprintln!("Seed {seed}: to rerun with this data, export {ENV}={seed}"); + Some(Self::new(seed)) + } + + /// Creates a new `SeededRng` with a random seed generated by the OS. + #[track_caller] + pub fn from_random() -> Self { + let seed = rand::rngs::OsRng.unwrap_err().next_u64(); + eprintln!("Seed {seed}: to rerun with this data, export {ENV}={seed}"); + Self::new(seed) + } + + /// Creates a new `SeededRng` from an environment variable (if set), otherwise + /// a random seed. + #[track_caller] + pub fn from_env_or_random() -> Self { + Self::from_env().unwrap_or_else(Self::from_random) + } + + /// Creates a new `SeededRng` seeded by this Rng. + pub fn seeded_fork(&self) -> Self { + Self::new(self.next_u64()) + } + + /// Convenience method to generate a new u32 from the Rng with a reference + /// and not a mutable reference. + #[must_use] + pub fn next_u32(&self) -> u32 { + self.0.borrow_mut().next_u32() + } + + /// Convenience method to generate a new u64 from the Rng with a reference + /// and not a mutable reference. + #[must_use] + pub fn next_u64(&self) -> u64 { + self.0.borrow_mut().next_u64() + } + + /// Convenience method to fill a byte slice with random bytes from the Rng + /// with a reference and not a mutable reference. + pub fn fill_bytes(&self, dst: &mut [u8]) { + self.0.borrow_mut().fill_bytes(dst); + } + + /// Convenience method for [`rand::Rng::random`] but with a reference and + /// instead of a mutable reference. + #[must_use] + #[inline] + pub fn random(&self) -> T + where + rand::distr::StandardUniform: rand::distr::Distribution, + { + rand::Rng::random(&mut &*self) + } + + /// Convenience method for [`rand::Rng::random_range`] but with a reference + /// and instead of a mutable reference. + #[track_caller] + pub fn random_range(&self, range: R) -> T + where + T: rand::distr::uniform::SampleUniform, + R: rand::distr::uniform::SampleRange, + { + rand::Rng::random_range(&mut &*self, range) + } +} + +impl rand::RngCore for SeededRng { + #[inline] + fn next_u32(&mut self) -> u32 { + SeededRng::next_u32(self) + } + + #[inline] + fn next_u64(&mut self) -> u64 { + SeededRng::next_u64(self) + } + + #[inline] + fn fill_bytes(&mut self, dst: &mut [u8]) { + SeededRng::fill_bytes(self, dst); + } +} + +impl rand::RngCore for &SeededRng { + #[inline] + fn next_u32(&mut self) -> u32 { + SeededRng::next_u32(self) + } + + #[inline] + fn next_u64(&mut self) -> u64 { + SeededRng::next_u64(self) + } + + #[inline] + fn fill_bytes(&mut self, dst: &mut [u8]) { + SeededRng::fill_bytes(self, dst); + } +} diff --git a/firewood/storage/src/trie_hash.rs b/firewood/storage/src/trie_hash.rs new file mode 100644 index 000000000000..b5916edce2ce --- /dev/null +++ b/firewood/storage/src/trie_hash.rs @@ -0,0 +1,126 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::node::ExtendableBytes; +use crate::node::branch::Serializable; +use sha2::digest::generic_array::GenericArray; +use sha2::digest::typenum; +use std::fmt::{self, Debug, Display, Formatter}; + +/// An error that occurs when trying to convert a slice to a `TrieHash` +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, thiserror::Error)] +#[error("could not convert a slice of {0} bytes to TrieHash (an array of 32 bytes)")] +#[non_exhaustive] +pub struct InvalidTrieHashLength(pub usize); + +/// A hash value inside a merkle trie +/// We use the same type as returned by sha2 here to avoid copies +#[derive(PartialEq, Eq, Clone, Hash)] +pub struct TrieHash([u8; 32]); + +/// Intentionally, there is no [`Default`] implementation for [`TrieHash`] to force +/// the user to explicitly decide between an empty RLP hash or a hash of all zeros. +/// +/// These unfortunately cannot be `const` because the [`GenericArray`] type does +/// provide a const constructor. +impl TrieHash { + /// Creates a new `TrieHash` from the default value, which is the all zeros. + /// + /// ``` + /// assert_eq!( + /// firewood_storage::TrieHash::empty(), + /// firewood_storage::TrieHash::from([0; 32]), + /// ) + /// ``` + #[must_use] + pub const fn empty() -> Self { + TrieHash([0; TRIE_HASH_LEN]) + } +} + +impl std::ops::Deref for TrieHash { + type Target = [u8; 32]; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl AsRef<[u8]> for TrieHash { + fn as_ref(&self) -> &[u8] { + &self.0 + } +} + +impl Debug for TrieHash { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + let width = f.precision().unwrap_or(64); + write!(f, "{:.*}", width, hex::encode(self.0)) + } +} +impl Display for TrieHash { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { + let width = f.precision().unwrap_or(64); + write!(f, "{:.*}", width, hex::encode(self.0)) + } +} + +const TRIE_HASH_LEN: usize = std::mem::size_of::(); + +impl From<[u8; TRIE_HASH_LEN]> for TrieHash { + fn from(value: [u8; TRIE_HASH_LEN]) -> Self { + TrieHash(value) + } +} + +impl From for [u8; TRIE_HASH_LEN] { + fn from(value: TrieHash) -> Self { + value.0 + } +} + +impl TryFrom<&[u8]> for TrieHash { + type Error = InvalidTrieHashLength; + + fn try_from(value: &[u8]) -> Result { + match value.try_into() { + Ok(array) => Ok(Self::from_bytes(array)), + Err(_) => Err(InvalidTrieHashLength(value.len())), + } + } +} + +impl From> for TrieHash { + fn from(value: GenericArray) -> Self { + TrieHash(value.into()) + } +} + +impl TrieHash { + /// Some code needs a `TrieHash` even though it only has a `HashType`. + /// This function is a no-op, as `HashType` is a `TrieHash` in this context. + #[must_use] + pub const fn into_triehash(self) -> Self { + self + } + + /// Creates a new `TrieHash` from an array of bytes. + #[must_use] + pub fn from_bytes(bytes: [u8; TRIE_HASH_LEN]) -> Self { + bytes.into() + } +} + +impl Serializable for TrieHash { + fn write_to(&self, vec: &mut W) { + vec.extend_from_slice(&self.0); + } + + fn from_reader(mut reader: R) -> Result + where + Self: Sized, + { + let mut buf = [0u8; 32]; + reader.read_exact(&mut buf)?; + Ok(TrieHash::from(buf)) + } +} diff --git a/firewood/storage/src/tries/iter.rs b/firewood/storage/src/tries/iter.rs new file mode 100644 index 000000000000..a874d9edcacb --- /dev/null +++ b/firewood/storage/src/tries/iter.rs @@ -0,0 +1,267 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +use crate::{HashType, PathBuf, PathComponent, TrieNode, TriePath, tries::TrieEdgeState}; + +/// A marker type for [`TrieEdgeIter`] that indicates that the iterator traverses +/// the trie in ascending order. +#[derive(Debug)] +pub struct IterAscending; + +/// A marker type for [`TrieEdgeIter`] that indicates that the iterator traverses +/// the trie in descending order. +#[derive(Debug)] +pub struct IterDescending; + +/// An iterator over the edges in a key-value trie in a specified order. +/// +/// Use [`TrieNode::iter_edges`] or [`TrieNode::iter_edges_desc`] to +/// create an instance of this iterator in ascending or descending order, +/// respectively. +#[derive(Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct TrieEdgeIter<'a, N: ?Sized, V: ?Sized, D> { + leading_path: PathBuf, + stack: Vec>, + marker: std::marker::PhantomData, +} + +/// An iterator over the key-value pairs in a key-value trie. +#[derive(Debug)] +#[must_use = "iterators are lazy and do nothing unless consumed"] +pub struct TrieValueIter<'a, N: ?Sized, V: ?Sized, D> { + edges: TrieEdgeIter<'a, N, V, D>, +} + +#[derive(Debug)] +struct Frame<'a, N: ?Sized, V: ?Sized> { + node: &'a N, + hash: Option<&'a HashType>, + leading_path_len: usize, + children: Option>, + marker: std::marker::PhantomData, +} + +impl<'a, N, V, D> TrieEdgeIter<'a, N, V, D> +where + N: TrieNode + ?Sized, + V: AsRef<[u8]> + ?Sized, +{ + /// Creates a new iterator over the given key-value trie. + pub fn new(root: &'a N, root_hash: Option<&'a HashType>) -> Self { + let mut this = Self { + leading_path: PathBuf::new_const(), + stack: Vec::new(), + marker: std::marker::PhantomData, + }; + this.push_frame(None, root, root_hash); + this + } + + /// Transforms this iterator into an iterator over the key-value pairs in + /// the trie. + pub const fn node_values(self) -> TrieValueIter<'a, N, V, D> { + TrieValueIter { edges: self } + } + + fn push_frame( + &mut self, + leading_component: Option, + node: &'a N, + hash: Option<&'a HashType>, + ) { + let frame = Frame { + node, + hash, + leading_path_len: self.leading_path.len(), + children: None, + marker: std::marker::PhantomData, + }; + self.stack.push(frame); + self.leading_path.extend(leading_component); + self.leading_path.extend(node.partial_path().components()); + } +} + +/// Both iterators share this logic to descend into a node's children. +/// +/// The passed in `children_iter` should be an iterator over the indices into +/// the children array in the desired order (e.g. ascending or descending). +macro_rules! descend { + ( + $self:expr, + $node:expr, + $children_iter:expr + ) => { + if let Some((pc, state)) = + $children_iter.find_map(|pc| $node.child_state(pc).map(|state| (pc, state))) + { + match state { + TrieEdgeState::LocalChild { node, hash } => { + $self.push_frame(Some(pc), node, Some(hash)); + } + TrieEdgeState::RemoteChild { hash } => { + let mut path = $self.leading_path.clone(); + path.push(pc); + return Some((path, TrieEdgeState::RemoteChild { hash })); + } + TrieEdgeState::UnhashedChild { node } => { + $self.push_frame(Some(pc), node, None); + } + } + + continue; + } + }; +} + +impl<'a, N, V> Iterator for TrieEdgeIter<'a, N, V, IterAscending> +where + N: TrieNode + ?Sized, + V: AsRef<[u8]> + ?Sized, +{ + type Item = (PathBuf, TrieEdgeState<'a, N>); + + fn next(&mut self) -> Option { + while let Some(&mut Frame { + node, + hash, + leading_path_len, + ref mut children, + marker: _, + }) = self.stack.last_mut() + { + // ascending iterator yields the node before iterating its children + let mut do_yield = false; + + let children = children.get_or_insert_with(|| { + do_yield = true; + PathComponent::ALL.into_iter() + }); + + if do_yield { + return Some(( + self.leading_path.clone(), + TrieEdgeState::from_node(node, hash), + )); + } + + descend!(self, node, children); + + // we've exhausted this node's children, so pop its frame + self.stack.pop(); + self.leading_path.truncate(leading_path_len); + } + + None + } +} + +impl<'a, N, V> Iterator for TrieEdgeIter<'a, N, V, IterDescending> +where + N: TrieNode + ?Sized, + V: AsRef<[u8]> + ?Sized, +{ + type Item = (PathBuf, TrieEdgeState<'a, N>); + + fn next(&mut self) -> Option { + while let Some(&mut Frame { + node, + hash, + leading_path_len, + ref mut children, + marker: _, + }) = self.stack.last_mut() + { + // descending iterator yields the node after iterating its children + let children = children.get_or_insert_with(|| PathComponent::ALL.into_iter()); + + descend!(self, node, children.rev()); + + // clone the path before we pop the frame + let leading_path = self.leading_path.clone(); + + // we've exhausted this node's children, so pop its frame and yield the node + self.stack.pop(); + self.leading_path.truncate(leading_path_len); + + return Some((leading_path, TrieEdgeState::from_node(node, hash))); + } + + None + } +} + +impl<'a, N, V> Iterator for TrieValueIter<'a, N, V, IterAscending> +where + N: TrieNode + ?Sized, + V: AsRef<[u8]> + ?Sized + 'a, +{ + type Item = (PathBuf, &'a V); + + fn next(&mut self) -> Option { + self.edges + .find_map(|(path, node)| node.value().map(|v| (path, v))) + } +} + +impl<'a, N, V> Iterator for TrieValueIter<'a, N, V, IterDescending> +where + N: TrieNode + ?Sized, + V: AsRef<[u8]> + ?Sized + 'a, +{ + type Item = (PathBuf, &'a V); + + fn next(&mut self) -> Option { + self.edges + .find_map(|(path, node)| node.value().map(|v| (path, v))) + } +} + +// auto-derived implementations would require N: Clone, V: Clone which is too much + +impl Clone for TrieEdgeIter<'_, N, V, D> { + fn clone(&self) -> Self { + Self { + leading_path: self.leading_path.clone(), + stack: self.stack.clone(), + marker: std::marker::PhantomData, + } + } + + fn clone_from(&mut self, source: &Self) { + self.leading_path.clone_from(&source.leading_path); + self.stack.clone_from(&source.stack); + } +} + +impl Clone for TrieValueIter<'_, N, V, D> { + fn clone(&self) -> Self { + Self { + edges: self.edges.clone(), + } + } + + fn clone_from(&mut self, source: &Self) { + self.edges.clone_from(&source.edges); + } +} + +impl Clone for Frame<'_, N, V> { + fn clone(&self) -> Self { + Self { + node: self.node, + hash: self.hash, + leading_path_len: self.leading_path_len, + children: self.children.clone(), + marker: std::marker::PhantomData, + } + } + + fn clone_from(&mut self, source: &Self) { + self.node = source.node; + self.hash = source.hash; + self.leading_path_len = source.leading_path_len; + self.children.clone_from(&source.children); + } +} diff --git a/firewood/storage/src/tries/kvp.rs b/firewood/storage/src/tries/kvp.rs new file mode 100644 index 000000000000..192b316faf94 --- /dev/null +++ b/firewood/storage/src/tries/kvp.rs @@ -0,0 +1,706 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +#[cfg(not(feature = "branch_factor_256"))] +use crate::PackedPathRef; +use crate::{ + Children, HashType, Hashable, HashableShunt, HashedTrieNode, JoinedPath, PathBuf, + PathComponent, PathGuard, SplitPath, TrieNode, TriePath, TriePathFromPackedBytes, ValueDigest, +}; + +#[cfg(feature = "branch_factor_256")] +type PackedPathRef<'a> = &'a [PathComponent]; + +/// A duplicate key error when merging two key-value tries. +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)] +#[error("duplicate keys found at path {}", path.display())] +pub struct DuplicateKeyError { + /// The path at which the duplicate keys were found. + pub path: PathBuf, +} + +/// The root of a key-value trie. +/// +/// The trie maps byte string keys to values of type `T`. +/// +/// The trie is a compressed prefix tree, where each node contains: +/// - A partial path (a sequence of path components) representing the path from +/// its parent to itself. +/// - An optional value of type `T` if the path to this node corresponds to a +/// key in the trie. +/// - A set of children nodes, each corresponding to a different path component +/// extending the current node's path. +pub struct KeyValueTrieRoot<'a, T: ?Sized> { + /// The partial path from this node's parent to itself. + pub partial_path: PackedPathRef<'a>, + /// The value associated with the path to this node, if any. + /// + /// If [`None`], this node does not correspond to a key in the trie and is + /// expected to have two or more children. If [`Some`], this node may have + /// zero or more children. + pub value: Option<&'a T>, + /// The children of this node, indexed by their leading path component. + pub children: Children>>, +} + +/// The root of a hashed key-value trie. +/// +/// This is similar to [`KeyValueTrieRoot`], but includes the computed hash of +/// the node as well as its leading path components. Consequently, the hashed +/// trie is formed by hashing the un-hashed trie. +pub struct HashedKeyValueTrieRoot<'a, T: ?Sized> { + computed: HashType, + leading_path: PathBuf, + partial_path: PackedPathRef<'a>, + value: Option<&'a T>, + children: Children>>, +} + +impl + ?Sized> std::fmt::Debug for KeyValueTrieRoot<'_, T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("KeyValueTrieRoot") + .field("partial_path", &self.partial_path.display()) + .field("value", &DebugValue::new(self.value)) + .field("children", &DebugChildren::new(&self.children)) + .finish() + } +} + +impl + ?Sized> std::fmt::Debug for HashedKeyValueTrieRoot<'_, T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HashedKeyValueTrieRoot") + .field("computed", &self.computed) + .field("leading_path", &self.leading_path.display()) + .field("partial_path", &self.partial_path.display()) + .field("value", &DebugValue::new(self.value)) + .field("children", &DebugChildren::new(&self.children)) + .finish() + } +} + +impl<'a, T: AsRef<[u8]> + ?Sized> KeyValueTrieRoot<'a, T> { + /// Constructs a new leaf node with the given path and value. + #[must_use] + pub fn new_leaf(path: &'a [u8], value: &'a T) -> Box { + Box::new(Self { + partial_path: PackedPathRef::path_from_packed_bytes(path), + value: Some(value), + children: Children::new(), + }) + } + + /// Constructs a new key-value trie from the given slice of key-value pairs. + /// + /// For efficiency, the slice should be sorted by key; however, this is not + /// explicitly required. + /// + /// # Errors + /// + /// If duplicate keys are found, a [`DuplicateKeyError`] is returned. + pub fn from_slice(slice: &'a [(K, V)]) -> Result>, DuplicateKeyError> + where + K: AsRef<[u8]>, + V: AsRef, + { + match slice { + [] => Ok(None), + [(k, v)] => Ok(Some(Self::new_leaf(k.as_ref(), v.as_ref()))), + _ => { + let mid = slice.len() / 2; + let (lhs, rhs) = slice.split_at(mid); + let lhs = Self::from_slice(lhs)?; + let rhs = Self::from_slice(rhs)?; + Self::merge_root(PathGuard::new(&mut PathBuf::new_const()), lhs, rhs) + } + } + } + + /// Constructs a new internal node with the given two children. + /// + /// The two children must have different leading path components. + #[must_use] + fn new_siblings( + path: PackedPathRef<'a>, + lhs_path: PathComponent, + lhs: Box, + rhs_path: PathComponent, + rhs: Box, + ) -> Box { + debug_assert_ne!(lhs_path, rhs_path); + let mut children = Children::new(); + children[lhs_path] = Some(lhs); + children[rhs_path] = Some(rhs); + Box::new(Self { + partial_path: path, + value: None, + children, + }) + } + + /// Returns a new node with the same contents as `self` but with its path + /// replaced by the given path. + #[must_use] + fn with_path(mut self: Box, path: PackedPathRef<'a>) -> Box { + self.partial_path = path; + self + } + + /// Deeply merges two key-value tries, returning the merged trie. + fn merge_root( + leading_path: PathGuard<'_>, + lhs: Option>, + rhs: Option>, + ) -> Result>, DuplicateKeyError> { + match (lhs, rhs) { + (Some(l), Some(r)) => Self::merge(leading_path, l, r).map(Some), + (Some(node), None) | (None, Some(node)) => Ok(Some(node)), + (None, None) => Ok(None), + } + } + + /// Merges two disjoint tries, returning the merged trie. + fn merge( + leading_path: PathGuard<'_>, + lhs: Box, + rhs: Box, + ) -> Result, DuplicateKeyError> { + match lhs + .partial_path + .longest_common_prefix(rhs.partial_path) + .split_first_parts() + { + (None, None, _) => { + // both paths are identical, perform a deep merge of each child slot + Self::deep_merge(leading_path, lhs, rhs) + } + (Some((l, l_rest)), Some((r, r_rest)), path) => { + // the paths diverge at this component, create a new parent node + // with the two nodes as children + Ok(Self::new_siblings( + path, + l, + lhs.with_path(l_rest), + r, + rhs.with_path(r_rest), + )) + } + (Some((l, l_rest)), None, _) => { + // rhs is a prefix of lhs, so rhs becomes the parent of lhs + rhs.merge_child(leading_path, l, lhs.with_path(l_rest)) + } + (None, Some((r, r_rest)), _) => { + // lhs is a prefix of rhs, so lhs becomes the parent of rhs + lhs.merge_child(leading_path, r, rhs.with_path(r_rest)) + } + } + } + + /// Deeply merges two kvp nodes that have identical paths. + fn deep_merge( + mut leading_path: PathGuard<'_>, + mut lhs: Box, + #[expect(clippy::boxed_local)] mut rhs: Box, + ) -> Result, DuplicateKeyError> { + leading_path.extend(lhs.partial_path.components()); + + lhs.value = match (lhs.value.take(), rhs.value.take()) { + (Some(v), None) | (None, Some(v)) => Some(v), + (Some(_), Some(_)) => { + return Err(DuplicateKeyError { + path: leading_path.as_slice().into(), + }); + } + (None, None) => None, + }; + + lhs.children = lhs.children.merge(rhs.children, |pc, lhs, rhs| { + Self::merge_root(leading_path.fork_append(pc), lhs, rhs) + })?; + + Ok(lhs) + } + + /// Merges the given child into this node at the given prefix. + /// + /// If there is already a child at the given prefix, the two children + /// are recursively merged. + fn merge_child( + mut self: Box, + mut leading_path: PathGuard<'_>, + prefix: PathComponent, + child: Box, + ) -> Result, DuplicateKeyError> { + leading_path.extend(self.partial_path.components()); + leading_path.push(prefix); + + self.children[prefix] = Some(match self.children.take(prefix) { + Some(existing) => Self::merge(leading_path, existing, child)?, + None => child, + }); + + Ok(self) + } + + /// Hashes this trie, returning a hashed trie. + #[must_use] + pub fn into_hashed_trie(self: Box) -> Box> { + HashedKeyValueTrieRoot::new(PathGuard::new(&mut PathBuf::new_const()), self) + } +} + +impl<'a, T: AsRef<[u8]> + ?Sized> HashedKeyValueTrieRoot<'a, T> { + /// Constructs a new hashed key-value trie node from the given un-hashed + /// node. + #[must_use] + pub fn new( + mut leading_path: PathGuard<'_>, + #[expect(clippy::boxed_local)] node: Box>, + ) -> Box { + let children = node + .children + .map(|pc, child| child.map(|child| Self::new(leading_path.fork_append(pc), child))); + + Box::new(Self { + computed: HashableShunt::new( + leading_path.as_slice(), + node.partial_path, + node.value.map(|v| ValueDigest::Value(v.as_ref())), + children + .each_ref() + .map(|_, c| c.as_deref().map(|c| c.computed.clone())), + ) + .to_hash(), + leading_path: leading_path.as_slice().into(), + partial_path: node.partial_path, + value: node.value, + children, + }) + } +} + +impl + ?Sized> TrieNode for KeyValueTrieRoot<'_, T> { + type PartialPath<'a> + = PackedPathRef<'a> + where + Self: 'a; + + fn partial_path(&self) -> Self::PartialPath<'_> { + self.partial_path + } + + fn value(&self) -> Option<&T> { + self.value + } + + fn child_hash(&self, pc: PathComponent) -> Option<&HashType> { + let _ = pc; + None + } + + fn child_node(&self, pc: PathComponent) -> Option<&Self> { + self.children[pc].as_deref() + } + + fn child_state(&self, pc: PathComponent) -> Option> { + self.children[pc] + .as_deref() + .map(|node| super::TrieEdgeState::UnhashedChild { node }) + } +} + +impl + ?Sized> TrieNode for HashedKeyValueTrieRoot<'_, T> { + type PartialPath<'a> + = PackedPathRef<'a> + where + Self: 'a; + + fn partial_path(&self) -> Self::PartialPath<'_> { + self.partial_path + } + + fn value(&self) -> Option<&T> { + self.value + } + + fn child_hash(&self, pc: PathComponent) -> Option<&HashType> { + self.children[pc].as_deref().map(|c| &c.computed) + } + + fn child_node(&self, pc: PathComponent) -> Option<&Self> { + self.children[pc].as_deref() + } + + fn child_state(&self, pc: PathComponent) -> Option> { + self.children[pc] + .as_deref() + .map(|node| super::TrieEdgeState::from_node(node, Some(&node.computed))) + } +} + +impl + ?Sized> HashedTrieNode for HashedKeyValueTrieRoot<'_, T> { + fn computed(&self) -> &HashType { + &self.computed + } +} + +impl<'a, T: AsRef<[u8]> + ?Sized> Hashable for HashedKeyValueTrieRoot<'a, T> { + type LeadingPath<'b> + = &'b [PathComponent] + where + Self: 'b; + + type PartialPath<'b> + = PackedPathRef<'a> + where + Self: 'b; + + type FullPath<'b> + = JoinedPath<&'b [PathComponent], PackedPathRef<'a>> + where + Self: 'b; + + fn parent_prefix_path(&self) -> Self::LeadingPath<'_> { + &self.leading_path + } + + fn partial_path(&self) -> Self::PartialPath<'_> { + self.partial_path + } + + fn full_path(&self) -> Self::FullPath<'_> { + self.parent_prefix_path().append(self.partial_path) + } + + fn value_digest(&self) -> Option> { + self.value.map(|v| ValueDigest::Value(v.as_ref())) + } + + fn children(&self) -> Children> { + self.children + .each_ref() + .map(|_, c| c.as_deref().map(|c| c.computed.clone())) + } +} + +struct DebugValue<'a, T: ?Sized> { + value: Option<&'a T>, +} + +impl<'a, T: AsRef<[u8]> + ?Sized> DebugValue<'a, T> { + const fn new(value: Option<&'a T>) -> Self { + Self { value } + } +} + +impl + ?Sized> std::fmt::Debug for DebugValue<'_, T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + #![expect(clippy::indexing_slicing)] + + const MAX_BYTES: usize = 32; + + let Some(value) = self.value else { + return write!(f, "None"); + }; + + let value = value.as_ref(); + let truncated = &value[..value.len().min(MAX_BYTES)]; + + let mut hex_buf = [0u8; MAX_BYTES * 2]; + let hex_buf = &mut hex_buf[..truncated.len().wrapping_mul(2)]; + hex::encode_to_slice(truncated, hex_buf).expect("exact fit"); + let s = str::from_utf8(hex_buf).expect("valid hex"); + + if truncated.len() < value.len() { + write!(f, "0x{s}... (len {})", value.len()) + } else { + write!(f, "0x{s}") + } + } +} + +struct DebugChildren<'a, T> { + children: &'a Children>, +} + +impl<'a, T: std::fmt::Debug> DebugChildren<'a, T> { + const fn new(children: &'a Children>) -> Self { + Self { children } + } +} + +impl std::fmt::Debug for DebugChildren<'_, T> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if f.alternate() { + // if alternate, debug children as-is (which is pretty and recursive) + self.children.fmt(f) + } else { + // otherwise, replace each child with a continuation marker + self.children + .each_ref() + .map( + |_, child| { + if child.is_some() { "Some(...)" } else { "None" } + }, + ) + .fmt(f) + } + } +} + +#[cfg(test)] +mod tests { + #![expect(clippy::unwrap_used)] + + use test_case::test_case; + + use super::*; + + /// In constant context, convert an ASCII hex string to a byte array. + /// + /// `FROM` must be exactly twice `TO`. This is workaround because generic + /// parameters cannot be used in constant expressions yet (see [upstream]). + /// + /// The [`expected_hash`] macro is able to work around this limitation by + /// evaluating the length at macro expansion time which provides a constant + /// value for both generic parameters at compile time. + /// + /// # Panics + /// + /// Panics if the input is not valid hex. Because this panic occurs in constant + /// context, this will result in an "erroneous constant error" during compilation. + /// + /// [upstream]: https://github.com/rust-lang/rust/issues/76560 + const fn from_ascii(hex: &[u8; FROM]) -> [u8; TO] { + #![expect(clippy::arithmetic_side_effects, clippy::indexing_slicing)] + + const fn from_hex_char(c: u8) -> u8 { + match c { + b'0'..=b'9' => c - b'0', + b'a'..=b'f' => c - b'a' + 10, + b'A'..=b'F' => c - b'A' + 10, + _ => panic!("invalid hex character"), + } + } + + const { + assert!(FROM == TO.wrapping_mul(2)); + } + + let mut bytes = [0u8; TO]; + let mut i = 0_usize; + while i < TO { + let off = i.wrapping_mul(2); + let hi = hex[off]; + let off = off.wrapping_add(1); + let lo = hex[off]; + bytes[i] = (from_hex_char(hi) << 4) | from_hex_char(lo); + i += 1; + } + + bytes + } + + /// A macro to select the expected hash based on the enabled cargo features. + /// + /// For both merkledb hash types, only a 64-character hex string (32 bytes) + /// is expected. For the ethereum hash type, either a 64-character hex string + /// or an RLP-encoded byte string of arbitrary length can be provided, if + /// wrapped in `rlp(...)`. + /// + /// # Example + /// + /// ```ignore + /// expected_hash!{ + /// merkledb16: b"749390713e51d3e4e50ba492a669c1644a6d9cb7e48b2a14d556e7f953da92fc", + /// merkledb256: b"30dbf15b59c97d2997f4fbed1ae86d1eab8e7aa2dd84337029fe898f47aeb8e6", + /// ethereum: b"2e636399fae96dc07abaf21167a34b8a5514d6594e777635987e319c76f28a75", + /// } + /// ``` + /// + /// or with RLP: + /// + /// ```ignore + /// expected_hash!{ + /// merkledb16: b"1ffe11ce995a9c07021d6f8a8c5b1817e6375dd0ea27296b91a8d48db2858bc9", + /// merkledb256: b"831a115e52af616bd2df8cd7a0993e21e544d7d201e151a7f61dcdd1a6bd557c", + /// ethereum: rlp(b"c482206131"), + /// } + /// ``` + macro_rules! expected_hash { + ( + merkledb16: $hex16:expr, + merkledb256: $hex256:expr, + ethereum: rlp($hexeth:expr), + ) => { + match () { + #[cfg(all(not(feature = "branch_factor_256"), not(feature = "ethhash")))] + () => $crate::HashType::from(from_ascii($hex16)), + #[cfg(all(feature = "branch_factor_256", not(feature = "ethhash")))] + () => $crate::HashType::from(from_ascii($hex256)), + #[cfg(all(not(feature = "branch_factor_256"), feature = "ethhash"))] + () => $crate::HashType::Rlp(smallvec::SmallVec::from( + &from_ascii::<{ $hexeth.len() }, { $hexeth.len() / 2 }>($hexeth)[..], + )), + #[cfg(all(feature = "branch_factor_256", feature = "ethhash"))] + () => compile_error!("branch_factor_256 and ethhash cannot both be enabled"), + } + }; + ( + merkledb16: $hex16:expr, + merkledb256: $hex256:expr, + ethereum: $hexeth:expr, + ) => { + $crate::HashType::from(from_ascii(match () { + #[cfg(all(not(feature = "branch_factor_256"), not(feature = "ethhash")))] + () => $hex16, + #[cfg(all(feature = "branch_factor_256", not(feature = "ethhash")))] + () => $hex256, + #[cfg(all(not(feature = "branch_factor_256"), feature = "ethhash"))] + () => $hexeth, + #[cfg(all(feature = "branch_factor_256", feature = "ethhash"))] + () => compile_error!("branch_factor_256 and ethhash cannot both be enabled"), + })) + }; + } + + #[test_case(&[])] + #[test_case(&[("a", "1")])] + #[test_case(&[("a", "1"), ("b", "2")])] + #[test_case(&[("a", "1"), ("ab", "2")])] + #[test_case(&[("a", "1"), ("b", "2"), ("c", "3")])] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3")])] + #[test_case(&[("a", "1"), ("b", "2"), ("ba", "3")])] + #[test_case(&[("a", "1"), ("ab", "2"), ("abc", "3")])] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3"), ("b", "4")])] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3"), ("b", "4"), ("ba", "5")])] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3"), ("b", "4"), ("ba", "5"), ("bb", "6")])] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3"), ("b", "4"), ("ba", "5"), ("bb", "6"), ("c", "7")])] + fn test_trie_from_slice(slice: &[(&str, &str)]) { + let root = KeyValueTrieRoot::::from_slice(slice).unwrap(); + if slice.is_empty() { + if let Some(root) = root { + panic!("expected None, got {root:#?}"); + } + } else { + let root = root.unwrap(); + eprintln!("trie: {root:#?}"); + for ((kvp_path, kvp_value), &(slice_key, slice_value)) in root + .iter_values() + .zip(slice) + .chain(root.iter_values_desc().zip(slice.iter().rev())) + { + let slice_key = PackedPathRef::path_from_packed_bytes(slice_key.as_bytes()); + assert!( + kvp_path.path_eq(&slice_key), + "expected path {} got {}", + slice_key.display(), + kvp_path.display(), + ); + assert_eq!(kvp_value, slice_value); + } + } + } + + #[test] + fn test_trie_from_slice_duplicate_keys() { + let slice = [("a", "1"), ("ab", "2"), ("a", "3")]; + let err = KeyValueTrieRoot::::from_slice(&slice).unwrap_err(); + assert_eq!( + err, + DuplicateKeyError { + path: PathBuf::path_from_packed_bytes(b"a") + } + ); + } + + #[test] + fn test_trie_from_unsorted_slice() { + let slice = [("b", "2"), ("a", "1"), ("ab", "3")]; + let expected = [("a", "1"), ("ab", "3"), ("b", "2")]; + let root = KeyValueTrieRoot::::from_slice(&slice) + .unwrap() + .unwrap(); + eprintln!("trie: {root:#?}"); + + for ((kvp_path, kvp_value), &(slice_key, slice_value)) in root + .iter_values() + .zip(&expected) + .chain(root.iter_values_desc().zip(expected.iter().rev())) + { + let slice_key = PackedPathRef::path_from_packed_bytes(slice_key.as_bytes()); + assert!( + kvp_path.path_eq(&slice_key), + "expected path {} got {}", + slice_key.display(), + kvp_path.display(), + ); + assert_eq!(kvp_value, slice_value); + } + } + + #[test_case(&[("a", "1")], expected_hash!{ + merkledb16: b"1ffe11ce995a9c07021d6f8a8c5b1817e6375dd0ea27296b91a8d48db2858bc9", + merkledb256: b"831a115e52af616bd2df8cd7a0993e21e544d7d201e151a7f61dcdd1a6bd557c", + ethereum: rlp(b"c482206131"), + }; "single key")] + #[test_case(&[("a", "1"), ("b", "2")], expected_hash!{ + merkledb16: b"ff783ce73f7a5fa641991d76d626eefd7840a839590db4269e1e92359ae60593", + merkledb256: b"301e9035ef0fe1b50788f9b5bca3a2c19bce9c798bdb1dda09fc71dd22564ce4", + ethereum: rlp(b"d81696d580c22031c220328080808080808080808080808080"), + }; "two disjoint keys")] + #[test_case(&[("a", "1"), ("ab", "2")], expected_hash!{ + merkledb16: b"c5def8c64a2f3b8647283251732b68a2fb185f8bf92c0103f31d5ec69bb9a90c", + merkledb256: b"2453f6f0b38fd36bcb66b145aff0f7ae3a6b96121fa1187d13afcffa7641b156", + ethereum: rlp(b"d882006194d3808080808080c2323280808080808080808031"), + }; "two nested keys")] + #[test_case(&[("a", "1"), ("b", "2"), ("c", "3")], expected_hash!{ + merkledb16: b"95618fd79a0ca2d7612bf9fd60663b81f632c9a65e76bb5bc3ed5f3045cf1404", + merkledb256: b"f5c185a96ed86da8da052a52f6c2e7368c90d342c272dd0e6c9e72c0071cdb0c", + ethereum: rlp(b"da1698d780c22031c22032c2203380808080808080808080808080"), + }; "three disjoint keys")] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3")], expected_hash!{ + merkledb16: b"ee8a7a1409935f58ab6ce40a1e05ee2a587bdc06c201dbec7006ee1192e71f70", + merkledb256: b"40c9cee60ac59e7926109137fbaa5d68642d4770863b150f98bd8ac00aedbff3", + ethereum: b"6ffab67bf7096a9608b312b9b2459c17ec9429286b283a3b3cdaa64860182699", + }; "two children of same parent")] + #[test_case(&[("a", "1"), ("b", "2"), ("ba", "3")], expected_hash!{ + merkledb16: b"d3efab83a1a4dd193c8ae51dfe638bba3494d8b1917e7a9185d20301ff1c528b", + merkledb256: b"e6f711e762064ffcc7276e9c6149fc8f1050e009a21e436e7b78a4a60079e3ba", + ethereum: b"21a118e1765c556e505a8752a0fd5bbb4ea78fb21077f8488d42862ebabf0130", + }; "nested sibling")] + #[test_case(&[("a", "1"), ("ab", "2"), ("abc", "3")], expected_hash!{ + merkledb16: b"af11454e2f920fb49041c9890c318455952d651b7d835f5731218dbc4bde4805", + merkledb256: b"5dc43e88b3019050e741be52ed4afff621e1ac93cd2c68d37f82947d1d16cff5", + ethereum: b"eabecb5e4efb9b5824cd926fac6350bdcb4a599508b16538afde303d72571169", + }; "linear nested keys")] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3"), ("b", "4")], expected_hash!{ + merkledb16: b"749390713e51d3e4e50ba492a669c1644a6d9cb7e48b2a14d556e7f953da92fc", + merkledb256: b"30dbf15b59c97d2997f4fbed1ae86d1eab8e7aa2dd84337029fe898f47aeb8e6", + ethereum: b"2e636399fae96dc07abaf21167a34b8a5514d6594e777635987e319c76f28a75", + }; "four keys")] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3"), ("b", "4"), ("ba", "5")], expected_hash!{ + merkledb16: b"1c043978de0cd65fe2e75a74eaa98878b753f4ec20f6fbbb7232a39f02e88c6f", + merkledb256: b"02bb75b5d5b81ba4c64464a5e39547de4e0d858c04da4a4aae9e63fc8385279d", + ethereum: b"df930bafb34edb6d758eb5f4dd9461fc259c8c13abf38da8a0f63f289e107ecd", + }; "five keys")] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3"), ("b", "4"), ("ba", "5"), ("bb", "6")], expected_hash!{ + merkledb16: b"c2c13c095f7f07ce9ef92401f73951b4846a19e2b092b8a527fe96fa82f55cfd", + merkledb256: b"56d69386ad494d6be42bbdd78b3ad00c07c12e631338767efa1539d6720ce7a6", + ethereum: b"8ca7c3b09aa0a8877122d67fd795051bd1e6ff169932e3b7a1158ed3d66fbedf", + }; "six keys")] + #[test_case(&[("a", "1"), ("ab", "2"), ("ac", "3"), ("b", "4"), ("ba", "5"), ("bb", "6"), ("c", "7")], expected_hash!{ + merkledb16: b"697e767d6f4af8236090bc95131220c1c94cadba3e66e0a8011c9beef7b255a5", + merkledb256: b"2f083246b86da1e6e135f771ae712f271c1162c23ebfaa16178ea57f0317bf06", + ethereum: b"3fa832b90f7f1a053a48a4528d1e446cc679fbcf376d0ef8703748d64030e19d", + }; "seven keys")] + fn test_hashed_trie(slice: &[(&str, &str)], root_hash: crate::HashType) { + let root = KeyValueTrieRoot::::from_slice(slice) + .unwrap() + .unwrap() + .into_hashed_trie(); + + assert_eq!(*root.computed(), root_hash); + assert_eq!(*root.computed(), crate::Preimage::to_hash(&*root)); + } +} diff --git a/firewood/storage/src/tries/mod.rs b/firewood/storage/src/tries/mod.rs new file mode 100644 index 000000000000..ce19101964ae --- /dev/null +++ b/firewood/storage/src/tries/mod.rs @@ -0,0 +1,196 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +mod iter; +mod kvp; + +use crate::{HashType, IntoSplitPath, PathComponent}; + +pub use self::iter::{IterAscending, IterDescending, TrieEdgeIter, TrieValueIter}; +pub use self::kvp::{DuplicateKeyError, HashedKeyValueTrieRoot, KeyValueTrieRoot}; + +/// The state of an edge from a parent node to a child node in a trie. +#[derive(Debug, PartialEq, Eq, Hash)] +pub enum TrieEdgeState<'a, N: ?Sized> { + /// A child node that is fully known locally, along with its hash. + LocalChild { + /// The child node at this edge. + node: &'a N, + /// The hash of the child at this edge, as known to the parent. A locally + /// hashed child implements [`HashedTrieNode`]. It is possible for the + /// child's computed hash to differ from this hash if the local node has + /// incomplete information. + hash: &'a HashType, + }, + /// A child node that is not known locally, but whose hash is known to the + /// parent. + RemoteChild { + /// The hash of the remote child at this edge, as known to the parent. + hash: &'a HashType, + }, + /// A child node that is known locally, but whose hash is not known to the + /// parent. + UnhashedChild { + /// The child node at this edge. + node: &'a N, + }, +} + +/// A node in a fixed-arity radix trie. +pub trait TrieNode + ?Sized> { + /// The type of path from this node's parent to this node. + type PartialPath<'a>: IntoSplitPath + 'a + where + Self: 'a; + + /// The path from this node's parent to this node. + fn partial_path(&self) -> Self::PartialPath<'_>; + + /// The value stored at this node, if any. + fn value(&self) -> Option<&V>; + + /// The node-local hash of the child at the given path component, if any. + /// + /// This *may* be different from the child's computed hash the child has + /// missing information. + /// + /// A trie node may also have a child node without knowing its hash, in which + /// case this returns [`None`], but [`child_node`] will return [`Some`]. + /// + /// A trie node may also know the hash of a child without having a reference + /// to the child's node. In this case, this will return [`Some`], but + /// [`child_node`] return [`None`]. For example, this occurs in the proof + /// trie where a proof follows a linear path down the trie and only includes + /// the hashes of sibling nodes that branch off the path. + /// + /// [`child_node`]: TrieNode::child_node + fn child_hash(&self, pc: PathComponent) -> Option<&HashType>; + + /// The child node at the given path component, if any. + /// + /// See the documentation for [`child_hash`] for more details on the + /// relationship between these two methods. + /// + /// [`child_hash`]: TrieNode::child_hash + fn child_node(&self, pc: PathComponent) -> Option<&Self>; + + /// A combined view of the child node and its hash at the given path + /// component, if any. + /// + /// This is a combination of [`child_node`] and [`child_hash`], returning + /// a [`TrieEdgeState`] that describes which of the child node and + /// hash are known. + /// + /// [`child_node`]: TrieNode::child_node + /// [`child_hash`]: TrieNode::child_hash + fn child_state(&self, pc: PathComponent) -> Option> { + match (self.child_node(pc), self.child_hash(pc)) { + (Some(node), Some(hash)) => Some(TrieEdgeState::LocalChild { node, hash }), + (Some(node), None) => Some(TrieEdgeState::UnhashedChild { node }), + (None, Some(hash)) => Some(TrieEdgeState::RemoteChild { hash }), + (None, None) => None, + } + } + + /// Returns a breadth-first iterator over the edges in this trie in ascending + /// order. + /// + /// The returned iterator performs a pre-order traversal of the trie, yielding + /// each edge from parent to child before descending into the child node. The + /// children of each node are yielded in ascending order by path component. + fn iter_edges(&self) -> TrieEdgeIter<'_, Self, V, IterAscending> { + TrieEdgeIter::new(self, None) + } + + /// Returns a depth-first iterator over the edges in this trie in descending + /// order. + /// + /// The returned iterator performs a post-order traversal of the trie, yielding + /// each edge from parent to child after ascending back from the child node. + /// The children of each node are yielded in descending order by path component. + fn iter_edges_desc(&self) -> TrieEdgeIter<'_, Self, V, IterDescending> { + TrieEdgeIter::new(self, None) + } + + /// Returns an iterator over each key-value pair in this trie in ascending order. + fn iter_values(&self) -> TrieValueIter<'_, Self, V, IterAscending> { + self.iter_edges().node_values() + } + + /// Returns an iterator over each key-value pair in this trie in descending order. + fn iter_values_desc(&self) -> TrieValueIter<'_, Self, V, IterDescending> { + self.iter_edges_desc().node_values() + } +} + +/// A merkleized node in a fixed-arity radix trie. +pub trait HashedTrieNode + ?Sized>: TrieNode { + /// The computed hash of this node. + fn computed(&self) -> &HashType; +} + +impl<'a, N: ?Sized> TrieEdgeState<'a, N> { + const fn from_node(node: &'a N, hash: Option<&'a HashType>) -> Self { + match hash { + Some(hash) => TrieEdgeState::LocalChild { node, hash }, + None => TrieEdgeState::UnhashedChild { node }, + } + } + + fn value + ?Sized>(self) -> Option<&'a V> + where + N: TrieNode, + { + self.node().and_then(|n| n.value()) + } + + /// Returns `true` if this edge state represents a local child node with a known hash. + #[must_use] + pub const fn is_local(self) -> bool { + matches!(self, TrieEdgeState::LocalChild { .. }) + } + + /// Returns `true` if this edge state represents a remote child node with only a known hash. + #[must_use] + pub const fn is_remote(self) -> bool { + matches!(self, TrieEdgeState::RemoteChild { .. }) + } + + /// Returns `true` if this edge state represents a local child node without a known hash. + #[must_use] + pub const fn is_unhashed(self) -> bool { + matches!(self, TrieEdgeState::UnhashedChild { .. }) + } + + /// Returns the child node if it is known locally. + #[must_use] + pub const fn node(self) -> Option<&'a N> { + match self { + TrieEdgeState::LocalChild { node, .. } | TrieEdgeState::UnhashedChild { node } => { + Some(node) + } + TrieEdgeState::RemoteChild { .. } => None, + } + } + + /// Returns the hash of the child node if it is known. + #[must_use] + pub const fn hash(self) -> Option<&'a HashType> { + match self { + TrieEdgeState::LocalChild { hash, .. } | TrieEdgeState::RemoteChild { hash } => { + Some(hash) + } + TrieEdgeState::UnhashedChild { .. } => None, + } + } +} + +// auto-derived implementations would require N: Clone + Copy which is too much + +impl Clone for TrieEdgeState<'_, N> { + fn clone(&self) -> Self { + *self + } +} + +impl Copy for TrieEdgeState<'_, N> {} diff --git a/firewood/storage/src/u4.rs b/firewood/storage/src/u4.rs new file mode 100644 index 000000000000..0220e54d1259 --- /dev/null +++ b/firewood/storage/src/u4.rs @@ -0,0 +1,343 @@ +// Copyright (C) 2025, Ava Labs, Inc. All rights reserved. +// See the file LICENSE.md for licensing terms. + +/// An error similar to [`std::num::TryFromIntError`] but able to be created +/// within our crate. +/// +/// The std error does not have a public constructor, and neither does ours. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)] +#[non_exhaustive] +#[error("out of range integral type conversion attempted")] +pub struct TryFromIntError; + +/// A 4-bit unsigned integer representing a hexary digit (0-15, inclusive) used +/// as a path component in hexary tries. +/// +/// The internal representation is a `u8` where only the lower 4 bits are used. +/// +/// Niche optimizations are enabled through the inner representation to enable +/// memory efficiency when used in data structures like [`Option`] as well as +/// allowing for faster indexing into [`Children`](crate::node::Children) arrays +/// by enabling the compiler to optimize away bounds checks. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct U4(Repr); + +impl U4 { + /// The number of bits required to represent a single u4. + pub const BITS: u32 = 4; + + /// The minimum value of a [`U4`], representing zero and the leftmost child + /// in a node's children array. + pub const MIN: Self = Self(Repr::Ox0); + + /// The maximum value of a [`U4`], representing fifteen and the rightmost child + /// in a node's children array. + pub const MAX: Self = Self(Repr::OxF); + + /// Fallibly converts a `u8` to a [`U4`], returning [`None`] if the + /// value is out of range. + #[inline] + #[must_use] + pub const fn try_new(v: u8) -> Option { + // FIXME(rust-lang/rust#143874): Option::map is not yet const + match Repr::try_new(v) { + Some(repr) => Some(Self(repr)), + None => None, + } + } + + /// Creates a new [`U4`] without checking that the provided value + /// is valid. + /// + /// # Safety + /// + /// The caller must ensure that the value is between 0 and 15 (inclusive). + /// Providing a value outside of this range results in immediate undefined + /// behavior. + #[inline] + #[must_use] + pub const unsafe fn new_unchecked(v: u8) -> Self { + #![expect(unsafe_code)] + + debug_assert!(v <= 0xF); + // SAFETY: the caller must ensure that `v` is a valid value (0 to 15). + unsafe { Self(Repr::new_unchecked(v)) } + } + + /// Creates a new [`U4`] using only the lower 4 bits of the input value and + /// ignoring the upper 4 bits. + #[inline] + #[must_use] + pub const fn new_masked(v: u8) -> Self { + #[expect(unsafe_code)] + // SAFETY: the value is masked to be between 0 and 15. + unsafe { + Self::new_unchecked(v & 0xF) + } + } + + /// Creates a new [`U4`] using only the upper 4 bits of the input value and + /// ignoring the lower 4 bits. + #[inline] + #[must_use] + pub const fn new_shifted(v: u8) -> Self { + #[expect(unsafe_code)] + // SAFETY: the value is shifted to be between 0 and 15. The extra mask is + // redundant but added for extra clarity. + unsafe { + Self::new_unchecked((v >> 4) & 0xF) + } + } + + /// Creates a pair of [`U4`]s from a single `u8`, where the first element + /// is created from the upper 4 bits and the second element is created from + /// the lower 4 bits. + #[inline] + #[must_use] + pub const fn new_pair(v: u8) -> (Self, Self) { + (Self::new_shifted(v), Self::new_masked(v)) + } + + /// Casts the [`U4`] to a `u8`. + #[inline] + #[must_use] + pub const fn as_u8(self) -> u8 { + self.0 as u8 + } + + /// Casts the [`U4`] to a `usize`. + #[inline] + #[must_use] + pub const fn as_usize(self) -> usize { + self.0 as usize + } + + /// Joins this [`U4`] with another [`U4`] to create a single `u8` where + /// this component is the upper 4 bits and the provided component is the + /// lower 4 bits. + #[inline] + #[must_use] + pub const fn join(self, lower: U4) -> u8 { + (self.as_u8() << 4) | lower.as_u8() + } +} + +impl TryFrom for U4 { + type Error = TryFromIntError; + + fn try_from(value: u8) -> Result { + Self::try_new(value).ok_or(TryFromIntError) + } +} + +/// The internal representation of a [`U4`]. +/// +/// This enum explicitly represents each of the 16 possible values (0b0000 to 0b1111) +/// of a 4-bit unsigned integer. It is used to optimize memory usage and performance +/// in scenarios where many instances of `U4` are stored, such as in a hexary trie, +/// +/// For example, when using [`Option`], the resulting size is still 1 byte +/// due to Rust's niche optimization, where [`Option::None`] can be represented by +/// any of the unused bit patterns of the inner [`Repr`] enum. +/// +/// Additionally, when using [`U4`] as an index into a fixed-size array of 16 elements, +/// like the [`Children`](crate::Children) array in the hexary trie, the compiler can +/// optimize away bounds checks and remove possible panic points. This is because the +/// compiler knows that the value of [`U4`] can only be one of the 16 valid indices. +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +enum Repr { + Ox0, + Ox1, + Ox2, + Ox3, + Ox4, + Ox5, + Ox6, + Ox7, + Ox8, + Ox9, + OxA, + OxB, + OxC, + OxD, + OxE, + OxF, +} + +impl Repr { + #[inline] + #[must_use] + const unsafe fn new_unchecked(v: u8) -> Self { + #![expect(unsafe_code)] + // SAFETY: the caller must ensure that `v` is a valid value (0 to 15). + unsafe { Self::try_new(v).unwrap_unchecked() } + } + + #[inline] + #[must_use] + const fn try_new(v: u8) -> Option { + // this could have been a transmute but then dead code detection would + // annoyingly complain about each variant going unused. the final code + // is the same regardless: https://rust.godbolt.org/z/6v6sddf6d + match v { + 0x0 => Some(Self::Ox0), + 0x1 => Some(Self::Ox1), + 0x2 => Some(Self::Ox2), + 0x3 => Some(Self::Ox3), + 0x4 => Some(Self::Ox4), + 0x5 => Some(Self::Ox5), + 0x6 => Some(Self::Ox6), + 0x7 => Some(Self::Ox7), + 0x8 => Some(Self::Ox8), + 0x9 => Some(Self::Ox9), + 0xA => Some(Self::OxA), + 0xB => Some(Self::OxB), + 0xC => Some(Self::OxC), + 0xD => Some(Self::OxD), + 0xE => Some(Self::OxE), + 0xF => Some(Self::OxF), + _ => None, + } + } +} + +impl std::fmt::Debug for U4 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Debug::fmt(&self.as_u8(), f) + } +} + +impl std::fmt::Display for U4 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Display::fmt(&self.as_u8(), f) + } +} + +impl std::fmt::LowerHex for U4 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::LowerHex::fmt(&self.as_u8(), f) + } +} + +impl std::fmt::UpperHex for U4 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::UpperHex::fmt(&self.as_u8(), f) + } +} + +impl std::fmt::Binary for U4 { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Binary::fmt(&self.as_u8(), f) + } +} + +#[cfg(test)] +mod tests { + use test_case::test_case; + + use super::*; + + #[test_case(0x00, Some(U4(Repr::Ox0)); "0x00 -> 0")] + #[test_case(0x01, Some(U4(Repr::Ox1)); "0x01 -> 1")] + #[test_case(0x02, Some(U4(Repr::Ox2)); "0x02 -> 2")] + #[test_case(0x03, Some(U4(Repr::Ox3)); "0x03 -> 3")] + #[test_case(0x04, Some(U4(Repr::Ox4)); "0x04 -> 4")] + #[test_case(0x05, Some(U4(Repr::Ox5)); "0x05 -> 5")] + #[test_case(0x06, Some(U4(Repr::Ox6)); "0x06 -> 6")] + #[test_case(0x07, Some(U4(Repr::Ox7)); "0x07 -> 7")] + #[test_case(0x08, Some(U4(Repr::Ox8)); "0x08 -> 8")] + #[test_case(0x09, Some(U4(Repr::Ox9)); "0x09 -> 9")] + #[test_case(0x0A, Some(U4(Repr::OxA)); "0x0A -> 10")] + #[test_case(0x0B, Some(U4(Repr::OxB)); "0x0B -> 11")] + #[test_case(0x0C, Some(U4(Repr::OxC)); "0x0C -> 12")] + #[test_case(0x0D, Some(U4(Repr::OxD)); "0x0D -> 13")] + #[test_case(0x0E, Some(U4(Repr::OxE)); "0x0E -> 14")] + #[test_case(0x0F, Some(U4(Repr::OxF)); "0x0F -> 15")] + #[test_case(0x10, None; "0x10 -> None")] + #[test_case(0xFF, None; "0xFF -> None")] + fn test_try_new(input: u8, expected: Option) { + assert_eq!(U4::try_new(input), expected); + } + + #[test_case(0x00, U4(Repr::Ox0); "0x00 -> 0")] + #[test_case(0x01, U4(Repr::Ox1); "0x01 -> 1")] + #[test_case(0x02, U4(Repr::Ox2); "0x02 -> 2")] + #[test_case(0x03, U4(Repr::Ox3); "0x03 -> 3")] + #[test_case(0x04, U4(Repr::Ox4); "0x04 -> 4")] + #[test_case(0x05, U4(Repr::Ox5); "0x05 -> 5")] + #[test_case(0x06, U4(Repr::Ox6); "0x06 -> 6")] + #[test_case(0x07, U4(Repr::Ox7); "0x07 -> 7")] + #[test_case(0x08, U4(Repr::Ox8); "0x08 -> 8")] + #[test_case(0x09, U4(Repr::Ox9); "0x09 -> 9")] + #[test_case(0x0A, U4(Repr::OxA); "0x0A -> 10")] + #[test_case(0x0B, U4(Repr::OxB); "0x0B -> 11")] + #[test_case(0x0C, U4(Repr::OxC); "0x0C -> 12")] + #[test_case(0x0D, U4(Repr::OxD); "0x0D -> 13")] + #[test_case(0x0E, U4(Repr::OxE); "0x0E -> 14")] + #[test_case(0x0F, U4(Repr::OxF); "0x0F -> 15")] + #[test_case(0x10, U4(Repr::Ox0); "0x10 -> 0")] + #[test_case(0x20, U4(Repr::Ox0); "0x20 -> 0")] + #[test_case(0x30, U4(Repr::Ox0); "0x30 -> 0")] + #[test_case(0x40, U4(Repr::Ox0); "0x40 -> 0")] + #[test_case(0x50, U4(Repr::Ox0); "0x50 -> 0")] + #[test_case(0x60, U4(Repr::Ox0); "0x60 -> 0")] + #[test_case(0x70, U4(Repr::Ox0); "0x70 -> 0")] + #[test_case(0x80, U4(Repr::Ox0); "0x80 -> 0")] + #[test_case(0x90, U4(Repr::Ox0); "0x90 -> 0")] + #[test_case(0xA0, U4(Repr::Ox0); "0xA0 -> 0")] + #[test_case(0xB0, U4(Repr::Ox0); "0xB0 -> 0")] + #[test_case(0xC0, U4(Repr::Ox0); "0xC0 -> 0")] + #[test_case(0xD0, U4(Repr::Ox0); "0xD0 -> 0")] + #[test_case(0xE0, U4(Repr::Ox0); "0xE0 -> 0")] + #[test_case(0xF0, U4(Repr::Ox0); "0xF0 -> 0")] + #[test_case(0xFF, U4(Repr::OxF); "0xFF -> 15")] + fn test_new_masked(input: u8, expected: U4) { + assert_eq!(U4::new_masked(input), expected); + } + + #[test_case(0x00, U4(Repr::Ox0); "0x00 -> 0")] + #[test_case(0x01, U4(Repr::Ox0); "0x01 -> 0")] + #[test_case(0x02, U4(Repr::Ox0); "0x02 -> 0")] + #[test_case(0x03, U4(Repr::Ox0); "0x03 -> 0")] + #[test_case(0x04, U4(Repr::Ox0); "0x04 -> 0")] + #[test_case(0x05, U4(Repr::Ox0); "0x05 -> 0")] + #[test_case(0x06, U4(Repr::Ox0); "0x06 -> 0")] + #[test_case(0x07, U4(Repr::Ox0); "0x07 -> 0")] + #[test_case(0x08, U4(Repr::Ox0); "0x08 -> 0")] + #[test_case(0x09, U4(Repr::Ox0); "0x09 -> 0")] + #[test_case(0x0A, U4(Repr::Ox0); "0x0A -> 0")] + #[test_case(0x0B, U4(Repr::Ox0); "0x0B -> 0")] + #[test_case(0x0C, U4(Repr::Ox0); "0x0C -> 0")] + #[test_case(0x0D, U4(Repr::Ox0); "0x0D -> 0")] + #[test_case(0x0E, U4(Repr::Ox0); "0x0E -> 0")] + #[test_case(0x0F, U4(Repr::Ox0); "0x0F -> 0")] + #[test_case(0x10, U4(Repr::Ox1); "0x10 -> 1")] + #[test_case(0x20, U4(Repr::Ox2); "0x20 -> 2")] + #[test_case(0x30, U4(Repr::Ox3); "0x30 -> 3")] + #[test_case(0x40, U4(Repr::Ox4); "0x40 -> 4")] + #[test_case(0x50, U4(Repr::Ox5); "0x50 -> 5")] + #[test_case(0x60, U4(Repr::Ox6); "0x60 -> 6")] + #[test_case(0x70, U4(Repr::Ox7); "0x70 -> 7")] + #[test_case(0x80, U4(Repr::Ox8); "0x80 -> 8")] + #[test_case(0x90, U4(Repr::Ox9); "0x90 -> 9")] + #[test_case(0xA0, U4(Repr::OxA); "0xA0 -> 10")] + #[test_case(0xB0, U4(Repr::OxB); "0xB0 -> 11")] + #[test_case(0xC0, U4(Repr::OxC); "0xC0 -> 12")] + #[test_case(0xD0, U4(Repr::OxD); "0xD0 -> 13")] + #[test_case(0xE0, U4(Repr::OxE); "0xE0 -> 14")] + #[test_case(0xF0, U4(Repr::OxF); "0xF0 -> 15")] + #[test_case(0xFF, U4(Repr::OxF); "0xFF -> 15")] + fn test_new_shifted(input: u8, expected: U4) { + assert_eq!(U4::new_shifted(input), expected); + } + + #[test_case(0x00, (U4(Repr::Ox0), U4(Repr::Ox0)); "0x00 -> (0, 0)")] + #[test_case(0x0F, (U4(Repr::Ox0), U4(Repr::OxF)); "0x0F -> (0, 15)")] + #[test_case(0xF0, (U4(Repr::OxF), U4(Repr::Ox0)); "0xF0 -> (15, 0)")] + #[test_case(0xFF, (U4(Repr::OxF), U4(Repr::OxF)); "0xFF -> (15, 15)")] + fn test_new_pair_then_join(input: u8, expected: (U4, U4)) { + let (upper, lower) = U4::new_pair(input); + assert_eq!((upper, lower), expected); + assert_eq!(upper.join(lower), input); + } +} diff --git a/firewood/triehash/BUILD.bazel b/firewood/triehash/BUILD.bazel new file mode 100644 index 000000000000..14ef8e046b94 --- /dev/null +++ b/firewood/triehash/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_rust//rust:defs.bzl", "rust_library") + +exports_files(["Cargo.toml"]) + +rust_library( + name = "firewood-triehash", + srcs = glob(["src/**/*.rs"]), + crate_root = "src/lib.rs", + edition = "2024", + visibility = ["//firewood:__subpackages__"], + deps = [ + "@firewood_crates//:hash-db", + "@firewood_crates//:rlp", + ], +) diff --git a/firewood/triehash/CHANGELOG.md b/firewood/triehash/CHANGELOG.md new file mode 100644 index 000000000000..22dac3ccae80 --- /dev/null +++ b/firewood/triehash/CHANGELOG.md @@ -0,0 +1,40 @@ +# Changelog + +This changelog is deprecatated. Please see the changelog at the top +level. + +The format is based on [Keep a Changelog]. + +[Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ + +## [Unreleased] + +## [0.8.5] - 2025-03-26 + +- Updated `hash-db` to 0.16.0 +- Updated `rlp` to 0.6 +- Updated `criterion` to 0.5.1 +- Updated `keccak-hasher` to 0.16.0 +- Updated `ethereum-types` to 0.15.1 +- Updated `trie-standardmap` to 0.16.0 +- Updated `hex-literal` to 1.0.0 + +## [0.8.4] - 2020-01-08 + +- Updated `rlp` to 0.5. [#463](https://github.com/paritytech/parity-common/pull/463) + +## [0.8.3] - 2020-03-16 + +- License changed from GPL3 to dual MIT/Apache2. [#342](https://github.com/paritytech/parity-common/pull/342) + +## [0.8.2] - 2019-12-15 + +- Added no-std support. [#280](https://github.com/paritytech/parity-common/pull/280) + +## [0.8.1] - 2019-10-24 + +- Migrated to 2018 edition. [#214](https://github.com/paritytech/parity-common/pull/214) + +### Dependencies + +- Updated dependencies. [#239](https://github.com/paritytech/parity-common/pull/239) diff --git a/firewood/triehash/Cargo.toml b/firewood/triehash/Cargo.toml new file mode 100644 index 000000000000..d39eac3f2194 --- /dev/null +++ b/firewood/triehash/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "firewood-triehash" +version.workspace = true +authors = ["Parity Technologies ", "Ron Kuris "] +description = "In-memory patricia trie operations" +repository.workspace = true +license = "MIT OR Apache-2.0" +edition.workspace = true +rust-version.workspace = true + +[dependencies] +# Regular dependencies +hash-db = "0.16.0" +rlp = "0.6" + +[dev-dependencies] +# Workspace dependencies +criterion.workspace = true +ethereum-types.workspace = true +hex-literal.workspace = true +# Regular dependencies +keccak-hasher = "0.16.0" +tiny-keccak = { version = "2.0", features = ["keccak"] } +trie-standardmap = "0.16.0" + +[[bench]] +name = "triehash" +path = "benches/triehash.rs" +harness = false + +[lints] +workspace = true diff --git a/firewood/triehash/README.md b/firewood/triehash/README.md new file mode 100644 index 000000000000..06b705982da3 --- /dev/null +++ b/firewood/triehash/README.md @@ -0,0 +1,4 @@ +# triehash + +This crate provides utility functions to validate and initialize tries using flexible input. +It is used extensively in `parity-ethereum` to validate blocks (mostly transactions and receipt roots). diff --git a/firewood/triehash/benches/triehash.rs b/firewood/triehash/benches/triehash.rs new file mode 100644 index 000000000000..0ed8ef989588 --- /dev/null +++ b/firewood/triehash/benches/triehash.rs @@ -0,0 +1,133 @@ +// Copyright 2020 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 5 occurrences after enabling the lint." +)] +#![expect( + clippy::indexing_slicing, + reason = "Found 1 occurrences after enabling the lint." +)] + +use criterion::{Criterion, criterion_group, criterion_main}; +use ethereum_types::H256; +use firewood_triehash::trie_root; +use keccak_hasher::KeccakHasher; +use tiny_keccak::{Hasher, Keccak}; +use trie_standardmap::{Alphabet, StandardMap, ValueMode}; + +fn keccak256(input: &[u8]) -> [u8; 32] { + let mut keccak256 = Keccak::v256(); + let mut out = [0u8; 32]; + keccak256.update(input); + keccak256.finalize(&mut out); + out +} + +fn random_word(alphabet: &[u8], min_count: usize, diff_count: usize, seed: &mut H256) -> Vec { + assert!(min_count + diff_count <= 32); + *seed = H256(keccak256(seed.as_bytes())); + let r = min_count + (seed[31] as usize % (diff_count + 1)); + let mut ret: Vec = Vec::with_capacity(r); + for i in 0..r { + ret.push(alphabet[seed[i] as usize % alphabet.len()]); + } + ret +} + +fn random_bytes(min_count: usize, diff_count: usize, seed: &mut H256) -> Vec { + assert!(min_count + diff_count <= 32); + *seed = H256(keccak256(seed.as_bytes())); + let r = min_count + (seed[31] as usize % (diff_count + 1)); + seed[0..r].to_vec() +} + +fn random_value(seed: &mut H256) -> Vec { + *seed = H256(keccak256(seed.as_bytes())); + match seed[0] % 2 { + 1 => vec![seed[31]; 1], + _ => seed.as_bytes().to_vec(), + } +} + +fn bench_insertions(c: &mut Criterion) { + c.bench_function("32_mir_1k", |b| { + let st = StandardMap { + alphabet: Alphabet::All, + min_key: 32, + journal_key: 0, + value_mode: ValueMode::Mirror, + count: 1000, + }; + let d = st.make(); + b.iter(|| trie_root::(d.clone())); + }); + + c.bench_function("32_ran_1k", |b| { + let st = StandardMap { + alphabet: Alphabet::All, + min_key: 32, + journal_key: 0, + value_mode: ValueMode::Random, + count: 1000, + }; + let d = st.make(); + b.iter(|| trie_root::(d.clone())); + }); + + c.bench_function("six_high", |b| { + let mut d: Vec<(Vec, Vec)> = Vec::new(); + let mut seed = H256::default(); + for _ in 0..1000 { + let k = random_bytes(6, 0, &mut seed); + let v = random_value(&mut seed); + d.push((k, v)); + } + b.iter(|| trie_root::(d.clone())); + }); + + c.bench_function("six_mid", |b| { + let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; + let mut d: Vec<(Vec, Vec)> = Vec::new(); + let mut seed = H256::default(); + for _ in 0..1000 { + let k = random_word(alphabet, 6, 0, &mut seed); + let v = random_value(&mut seed); + d.push((k, v)); + } + b.iter(|| trie_root::(d.clone())); + }); + + c.bench_function("random_mid", |b| { + let alphabet = b"@QWERTYUIOPASDFGHJKLZXCVBNM[/]^_"; + let mut d: Vec<(Vec, Vec)> = Vec::new(); + let mut seed = H256::default(); + for _ in 0..1000 { + let k = random_word(alphabet, 1, 5, &mut seed); + let v = random_value(&mut seed); + d.push((k, v)); + } + b.iter(|| trie_root::(d.clone())); + }); + + c.bench_function("six_low", |b| { + let alphabet = b"abcdef"; + let mut d: Vec<(Vec, Vec)> = Vec::new(); + let mut seed = H256::default(); + for _ in 0..1000 { + let k = random_word(alphabet, 6, 0, &mut seed); + let v = random_value(&mut seed); + d.push((k, v)); + } + b.iter(|| trie_root::(d.clone())); + }); +} + +criterion_group!(benches, bench_insertions); +criterion_main!(benches); diff --git a/firewood/triehash/src/lib.rs b/firewood/triehash/src/lib.rs new file mode 100644 index 000000000000..9ac11c3bd4c5 --- /dev/null +++ b/firewood/triehash/src/lib.rs @@ -0,0 +1,371 @@ +// Copyright 2020 Parity Technologies +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Generetes trie root. +//! +//! This module should be used to generate trie root hash. + +#![expect( + clippy::arithmetic_side_effects, + reason = "Found 7 occurrences after enabling the lint." +)] +#![expect( + clippy::bool_to_int_with_if, + reason = "Found 1 occurrences after enabling the lint." +)] +#![expect( + clippy::indexing_slicing, + reason = "Found 13 occurrences after enabling the lint." +)] + +use std::cmp; +use std::collections::BTreeMap; +use std::iter::once; + +use hash_db::Hasher; +use rlp::RlpStream; + +fn shared_prefix_len(first: &[T], second: &[T]) -> usize { + first + .iter() + .zip(second.iter()) + .position(|(f, s)| f != s) + .unwrap_or_else(|| cmp::min(first.len(), second.len())) +} + +/// Generates a trie root hash for a vector of values +/// +/// ``` +/// use hex_literal::hex; +/// use ethereum_types::H256; +/// use firewood_triehash::ordered_trie_root; +/// use keccak_hasher::KeccakHasher; +/// +/// let v = &["doe", "reindeer"]; +/// let root = H256::from(hex!("e766d5d51b89dc39d981b41bda63248d7abce4f0225eefd023792a540bcffee3")); +/// assert_eq!(ordered_trie_root::(v), root.as_ref()); +/// ``` +pub fn ordered_trie_root(input: I) -> H::Out +where + I: IntoIterator, + I::Item: AsRef<[u8]>, + H: Hasher, + ::Out: cmp::Ord, +{ + trie_root::( + input + .into_iter() + .enumerate() + .map(|(i, v)| (rlp::encode(&i), v)), + ) +} + +/// Generates a trie root hash for a vector of key-value tuples +/// +/// ``` +/// use hex_literal::hex; +/// use firewood_triehash::trie_root; +/// use ethereum_types::H256; +/// use keccak_hasher::KeccakHasher; +/// +/// let v = vec![ +/// ("doe", "reindeer"), +/// ("dog", "puppy"), +/// ("dogglesworth", "cat"), +/// ]; +/// +/// let root = H256::from(hex!("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3")); +/// assert_eq!(trie_root::(v), root.as_ref()); +/// ``` +pub fn trie_root(input: I) -> H::Out +where + I: IntoIterator, + A: AsRef<[u8]> + Ord, + B: AsRef<[u8]>, + H: Hasher, + ::Out: cmp::Ord, +{ + // first put elements into btree to sort them and to remove duplicates + let input = input.into_iter().collect::>(); + + let mut nibbles = Vec::with_capacity(input.keys().map(|k| k.as_ref().len()).sum::() * 2); + let mut lens = Vec::with_capacity(input.len() + 1); + lens.push(0); + for k in input.keys() { + for &b in k.as_ref() { + nibbles.push(b >> 4); + nibbles.push(b & 0x0F); + } + lens.push(nibbles.len()); + } + + // then move them to a vector + let input = input + .into_iter() + .zip(lens.windows(2)) + .map(|((_, v), w)| (&nibbles[w[0]..w[1]], v)) + .collect::>(); + + let mut stream = RlpStream::new(); + hash256rlp::(&input, 0, &mut stream); + H::hash(&stream.out()) +} + +/// Generates a key-hashed (secure) trie root hash for a vector of key-value tuples. +/// +/// ``` +/// use hex_literal::hex; +/// use ethereum_types::H256; +/// use firewood_triehash::sec_trie_root; +/// use keccak_hasher::KeccakHasher; +/// +/// let v = vec![ +/// ("doe", "reindeer"), +/// ("dog", "puppy"), +/// ("dogglesworth", "cat"), +/// ]; +/// +/// let root = H256::from(hex!("d4cd937e4a4368d7931a9cf51686b7e10abb3dce38a39000fd7902a092b64585")); +/// assert_eq!(sec_trie_root::(v), root.as_ref()); +/// ``` +pub fn sec_trie_root(input: I) -> H::Out +where + I: IntoIterator, + A: AsRef<[u8]>, + B: AsRef<[u8]>, + H: Hasher, + ::Out: cmp::Ord, +{ + trie_root::(input.into_iter().map(|(k, v)| (H::hash(k.as_ref()), v))) +} + +/// Hex-prefix Notation. First nibble has flags: oddness = 2^0 & termination = 2^1. +/// +/// The "termination marker" and "leaf-node" specifier are completely equivalent. +/// +/// Input values are in range `[0, 0xf]`. +/// +/// ```markdown +/// [0,0,1,2,3,4,5] 0x10012345 // 7 > 4 +/// [0,1,2,3,4,5] 0x00012345 // 6 > 4 +/// [1,2,3,4,5] 0x112345 // 5 > 3 +/// [0,0,1,2,3,4] 0x00001234 // 6 > 3 +/// [0,1,2,3,4] 0x101234 // 5 > 3 +/// [1,2,3,4] 0x001234 // 4 > 3 +/// [0,0,1,2,3,4,5,T] 0x30012345 // 7 > 4 +/// [0,0,1,2,3,4,T] 0x20001234 // 6 > 4 +/// [0,1,2,3,4,5,T] 0x20012345 // 6 > 4 +/// [1,2,3,4,5,T] 0x312345 // 5 > 3 +/// [1,2,3,4,T] 0x201234 // 4 > 3 +/// ``` +fn hex_prefix_encode(nibbles: &[u8], leaf: bool) -> impl Iterator + '_ { + let inlen = nibbles.len(); + let oddness_factor = inlen % 2; + + let first_byte = { + let mut bits = ((inlen as u8 & 1) + (2 * u8::from(leaf))) << 4; + if oddness_factor == 1 { + bits += nibbles[0]; + } + bits + }; + once(first_byte).chain( + nibbles[oddness_factor..] + .chunks(2) + .map(|ch| (ch[0] << 4) | ch[1]), + ) +} + +fn hash256rlp(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream) +where + A: AsRef<[u8]>, + B: AsRef<[u8]>, + H: Hasher, +{ + let inlen = input.len(); + + // in case of empty slice, just append empty data + if inlen == 0 { + stream.append_empty_data(); + return; + } + + // take slices + let key: &[u8] = input[0].0.as_ref(); + let value: &[u8] = input[0].1.as_ref(); + + // if the slice contains just one item, append the suffix of the key + // and then append value + if inlen == 1 { + stream.begin_list(2); + stream.append_iter(hex_prefix_encode(&key[pre_len..], true)); + stream.append(&value); + return; + } + + // get length of the longest shared prefix in slice keys + let shared_prefix = input + .iter() + // skip first tuple + .skip(1) + // get minimum number of shared nibbles between first and each successive + .fold(key.len(), |acc, (k, _)| { + cmp::min(shared_prefix_len(key, k.as_ref()), acc) + }); + + // if shared prefix is higher than current prefix append its + // new part of the key to the stream + // then recursively append suffixes of all items who had this key + if shared_prefix > pre_len { + stream.begin_list(2); + stream.append_iter(hex_prefix_encode(&key[pre_len..shared_prefix], false)); + hash256aux::(input, shared_prefix, stream); + return; + } + + // an item for every possible nibble/suffix + // + 1 for data + stream.begin_list(17); + + // if first key len is equal to prefix_len, move to next element + let mut begin = if pre_len == key.len() { 1 } else { 0 }; + + // iterate over all possible nibbles + for i in 0..16 { + // count how many successive elements have same next nibble + let len = input + .iter() + .skip(begin) + .take_while(|pair| pair.0.as_ref()[pre_len] == i) + .count(); + + // if at least 1 successive element has the same nibble + // append their suffixes + match len { + 0 => { + stream.append_empty_data(); + } + _ => hash256aux::(&input[begin..(begin + len)], pre_len + 1, stream), + } + begin += len; + } + + // if fist key len is equal prefix, append its value + if pre_len == key.len() { + stream.append(&value); + } else { + stream.append_empty_data(); + } +} + +fn hash256aux(input: &[(A, B)], pre_len: usize, stream: &mut RlpStream) +where + A: AsRef<[u8]>, + B: AsRef<[u8]>, + H: Hasher, +{ + let mut s = RlpStream::new(); + hash256rlp::(input, pre_len, &mut s); + let out = s.out(); + match out.len() { + 0..=31 => stream.append_raw(&out, 1), + _ => stream.append(&H::hash(&out).as_ref()), + }; +} + +#[cfg(test)] +mod tests { + use super::{hex_prefix_encode, shared_prefix_len, trie_root}; + use ethereum_types::H256; + use hex_literal::hex; + use keccak_hasher::KeccakHasher; + + #[test] + fn test_hex_prefix_encode() { + let v = vec![0, 0, 1, 2, 3, 4, 5]; + let e = vec![0x10, 0x01, 0x23, 0x45]; + let h = hex_prefix_encode(&v, false).collect::>(); + assert_eq!(h, e); + + let v = vec![0, 1, 2, 3, 4, 5]; + let e = vec![0x00, 0x01, 0x23, 0x45]; + let h = hex_prefix_encode(&v, false).collect::>(); + assert_eq!(h, e); + + let v = vec![0, 1, 2, 3, 4, 5]; + let e = vec![0x20, 0x01, 0x23, 0x45]; + let h = hex_prefix_encode(&v, true).collect::>(); + assert_eq!(h, e); + + let v = vec![1, 2, 3, 4, 5]; + let e = vec![0x31, 0x23, 0x45]; + let h = hex_prefix_encode(&v, true).collect::>(); + assert_eq!(h, e); + + let v = vec![1, 2, 3, 4]; + let e = vec![0x00, 0x12, 0x34]; + let h = hex_prefix_encode(&v, false).collect::>(); + assert_eq!(h, e); + + let v = vec![4, 1]; + let e = vec![0x20, 0x41]; + let h = hex_prefix_encode(&v, true).collect::>(); + assert_eq!(h, e); + } + + #[test] + fn simple_test() { + assert_eq!( + trie_root::(vec![( + b"A", + b"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" as &[u8] + )]), + H256::from(hex!( + "d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab" + )) + .as_ref(), + ); + } + + #[test] + fn test_triehash_out_of_order() { + assert_eq!( + trie_root::(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), + (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), + ]), + trie_root::(vec![ + (vec![0x01u8, 0x23], vec![0x01u8, 0x23]), + (vec![0xf1u8, 0x23], vec![0xf1u8, 0x23]), // last two tuples are swapped + (vec![0x81u8, 0x23], vec![0x81u8, 0x23]), + ]), + ); + } + + #[test] + fn test_shared_prefix() { + let a = vec![1, 2, 3, 4, 5, 6]; + let b = vec![4, 2, 3, 4, 5, 6]; + assert_eq!(shared_prefix_len(&a, &b), 0); + } + + #[test] + fn test_shared_prefix2() { + let a = vec![1, 2, 3, 3, 5]; + let b = vec![1, 2, 3]; + assert_eq!(shared_prefix_len(&a, &b), 3); + } + + #[test] + fn test_shared_prefix3() { + let a = vec![1, 2, 3, 4, 5, 6]; + let b = vec![1, 2, 3, 4, 5, 6]; + assert_eq!(shared_prefix_len(&a, &b), 6); + } +} diff --git a/flake.nix b/flake.nix index 8c5443159c75..a561d7b150bc 100644 --- a/flake.nix +++ b/flake.nix @@ -41,6 +41,10 @@ # Task runner go-task + # Bazel build system + bazel_7 + buildifier + # Local Go package from nested flake go-flake.packages.${pkgs.system}.default diff --git a/genesis/BUILD.bazel b/genesis/BUILD.bazel new file mode 100644 index 000000000000..247282ab6e56 --- /dev/null +++ b/genesis/BUILD.bazel @@ -0,0 +1,77 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "genesis", + srcs = [ + "aliases.go", + "bootstrappers.go", + "checkpoints.go", + "config.go", + "genesis.go", + "genesis_fuji.go", + "genesis_local.go", + "genesis_mainnet.go", + "params.go", + "unparsed_config.go", + "validators.go", + ], + embedsrcs = [ + "bootstrappers.json", + "checkpoints.json", + "genesis_fuji.json", + "genesis_local.json", + "genesis_mainnet.json", + "validators.json", + ], + importpath = "github.com/ava-labs/avalanchego/genesis", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils", + "//utils/cb58", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/formatting/address", + "//utils/math", + "//utils/sampler", + "//utils/set", + "//utils/units", + "//utils/wrappers", + "//vms/avm", + "//vms/avm/fxs", + "//vms/avm/txs", + "//vms/components/gas", + "//vms/nftfx", + "//vms/platformvm/genesis", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/txs", + "//vms/platformvm/validators/fee", + "//vms/propertyfx", + "//vms/secp256k1fx", + ], +) + +go_test( + name = "genesis_test", + srcs = [ + "bootstrappers_test.go", + "config_test.go", + "genesis_test.go", + ], + embed = [":genesis"], + embedsrcs = [ + "genesis_test.json", + "genesis_test_invalid_allocations.json", + ], + deps = [ + "//ids", + "//upgrade", + "//utils/constants", + "//utils/hashing", + "//utils/perms", + "//vms/platformvm/genesis", + "@com_github_ava_labs_libevm//core", + "@com_github_stretchr_testify//require", + ], +) diff --git a/genesis/generate/checkpoints/BUILD.bazel b/genesis/generate/checkpoints/BUILD.bazel new file mode 100644 index 000000000000..9d6ce1c24fcc --- /dev/null +++ b/genesis/generate/checkpoints/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "checkpoints_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/genesis/generate/checkpoints", + visibility = ["//visibility:private"], + deps = [ + "//ids", + "//indexer", + "//utils/constants", + "//utils/perms", + "//utils/set", + ], +) + +go_binary( + name = "checkpoints", + embed = [":checkpoints_lib"], + visibility = ["//visibility:public"], +) diff --git a/genesis/generate/validators/BUILD.bazel b/genesis/generate/validators/BUILD.bazel new file mode 100644 index 000000000000..578e3e6192c1 --- /dev/null +++ b/genesis/generate/validators/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "validators_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/genesis/generate/validators", + visibility = ["//visibility:private"], + deps = [ + "//ids", + "//utils/constants", + "//utils/perms", + "//utils/set", + "//vms/platformvm", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "validators", + embed = [":validators_lib"], + visibility = ["//visibility:public"], +) diff --git a/graft/BUILD.bazel b/graft/BUILD.bazel new file mode 100644 index 000000000000..a01e5d0050b4 --- /dev/null +++ b/graft/BUILD.bazel @@ -0,0 +1,2 @@ +# graft directory BUILD file +# Marker to make this directory a Bazel package diff --git a/graft/coreth/BUILD.bazel b/graft/coreth/BUILD.bazel new file mode 100644 index 000000000000..abd7b60fecd2 --- /dev/null +++ b/graft/coreth/BUILD.bazel @@ -0,0 +1,7 @@ +# Gazelle configuration for coreth submodule +# gazelle:prefix github.com/ava-labs/avalanchego/graft/coreth + +exports_files([ + "go.mod", + "go.sum", +]) diff --git a/graft/coreth/accounts/abi/BUILD.bazel b/graft/coreth/accounts/abi/BUILD.bazel new file mode 100644 index 000000000000..4e978c0d55f3 --- /dev/null +++ b/graft/coreth/accounts/abi/BUILD.bazel @@ -0,0 +1,52 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "abi", + srcs = [ + "abi.go", + "argument.go", + "doc.go", + "error.go", + "error_handling.go", + "event.go", + "method.go", + "pack.go", + "reflect.go", + "topics.go", + "type.go", + "unpack.go", + "utils.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/accounts/abi", + visibility = ["//visibility:public"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//crypto", + ], +) + +go_test( + name = "abi_test", + srcs = [ + "abi_extra_test.go", + "abi_test.go", + "event_test.go", + "method_test.go", + "pack_test.go", + "packing_test.go", + "reflect_test.go", + "topics_test.go", + "type_test.go", + "unpack_test.go", + ], + embed = [":abi"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//crypto", + "@com_github_davecgh_go_spew//spew", + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/accounts/abi/bind/BUILD.bazel b/graft/coreth/accounts/abi/bind/BUILD.bazel new file mode 100644 index 000000000000..81a8c20a5a08 --- /dev/null +++ b/graft/coreth/accounts/abi/bind/BUILD.bazel @@ -0,0 +1,59 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bind", + srcs = [ + "auth.go", + "backend.go", + "base.go", + "bind.go", + "template.go", + "util.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/accounts/abi/bind", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/accounts/abi", + "//graft/coreth/nativeasset", + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//accounts", + "@com_github_ava_labs_libevm//accounts/external", + "@com_github_ava_labs_libevm//accounts/keystore", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + ], +) + +go_test( + name = "bind_test", + srcs = [ + "base_test.go", + "bind_extra_test.go", + "bind_test.go", + "util_test.go", + ], + embed = [":bind"], + deps = [ + "//graft/coreth/accounts/abi", + "//graft/coreth/accounts/abi/bind/backends", + "//graft/coreth/core", + "//graft/coreth/eth/ethconfig", + "//graft/coreth/ethclient/simulated", + "//graft/coreth/nativeasset", + "//graft/coreth/node", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//rlp", + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/accounts/abi/bind/backends/BUILD.bazel b/graft/coreth/accounts/abi/bind/backends/BUILD.bazel new file mode 100644 index 000000000000..b21ac9dba526 --- /dev/null +++ b/graft/coreth/accounts/abi/bind/backends/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "backends", + srcs = ["simulated.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/accounts/abi/bind/backends", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/accounts/abi/bind", + "//graft/coreth/ethclient/simulated", + "//graft/coreth/interfaces", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + ], +) diff --git a/graft/coreth/cmd/simulator/config/BUILD.bazel b/graft/coreth/cmd/simulator/config/BUILD.bazel new file mode 100644 index 000000000000..2bbb0f2c4fcc --- /dev/null +++ b/graft/coreth/cmd/simulator/config/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "config", + srcs = ["flags.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/cmd/simulator/config", + visibility = ["//visibility:public"], + deps = [ + "@com_github_spf13_pflag//:pflag", + "@com_github_spf13_viper//:viper", + ], +) diff --git a/graft/coreth/cmd/simulator/key/BUILD.bazel b/graft/coreth/cmd/simulator/key/BUILD.bazel new file mode 100644 index 000000000000..365224f8416c --- /dev/null +++ b/graft/coreth/cmd/simulator/key/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "key", + srcs = ["key.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/cmd/simulator/key", + visibility = ["//visibility:public"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//crypto", + ], +) diff --git a/graft/coreth/cmd/simulator/load/BUILD.bazel b/graft/coreth/cmd/simulator/load/BUILD.bazel new file mode 100644 index 000000000000..d9bd698b4573 --- /dev/null +++ b/graft/coreth/cmd/simulator/load/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "load", + srcs = [ + "funder.go", + "loader.go", + "worker.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/cmd/simulator/load", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/cmd/simulator/config", + "//graft/coreth/cmd/simulator/key", + "//graft/coreth/cmd/simulator/metrics", + "//graft/coreth/cmd/simulator/txs", + "//graft/coreth/ethclient", + "//graft/coreth/params", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + "@org_golang_x_sync//errgroup", + ], +) diff --git a/graft/coreth/cmd/simulator/main/BUILD.bazel b/graft/coreth/cmd/simulator/main/BUILD.bazel new file mode 100644 index 000000000000..9a14e77cf359 --- /dev/null +++ b/graft/coreth/cmd/simulator/main/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "main_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/cmd/simulator/main", + visibility = ["//visibility:private"], + deps = [ + "//graft/coreth/cmd/simulator/config", + "//graft/coreth/cmd/simulator/load", + "//graft/coreth/log", + "@com_github_ava_labs_libevm//log", + "@com_github_spf13_pflag//:pflag", + ], +) + +go_binary( + name = "main", + embed = [":main_lib"], + visibility = ["//visibility:public"], +) diff --git a/graft/coreth/cmd/simulator/metrics/BUILD.bazel b/graft/coreth/cmd/simulator/metrics/BUILD.bazel new file mode 100644 index 000000000000..2d14a7ee6b59 --- /dev/null +++ b/graft/coreth/cmd/simulator/metrics/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "metrics", + srcs = ["metrics.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/cmd/simulator/metrics", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//log", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/promhttp", + ], +) diff --git a/graft/coreth/cmd/simulator/txs/BUILD.bazel b/graft/coreth/cmd/simulator/txs/BUILD.bazel new file mode 100644 index 000000000000..0fb1fce64edb --- /dev/null +++ b/graft/coreth/cmd/simulator/txs/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "txs", + srcs = [ + "agent.go", + "tx_generator.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/cmd/simulator/txs", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/cmd/simulator/metrics", + "//graft/coreth/ethclient", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//log", + ], +) diff --git a/graft/coreth/consensus/BUILD.bazel b/graft/coreth/consensus/BUILD.bazel new file mode 100644 index 000000000000..2a94a348ad59 --- /dev/null +++ b/graft/coreth/consensus/BUILD.bazel @@ -0,0 +1,17 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "consensus", + srcs = [ + "consensus.go", + "errors.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/consensus", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/params", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + ], +) diff --git a/graft/coreth/consensus/dummy/BUILD.bazel b/graft/coreth/consensus/dummy/BUILD.bazel new file mode 100644 index 000000000000..d79301db55c2 --- /dev/null +++ b/graft/coreth/consensus/dummy/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "dummy", + srcs = ["consensus.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/consensus/dummy", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/consensus", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/utils", + "//vms/components/gas", + "//vms/evm/acp226", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//trie", + ], +) diff --git a/graft/coreth/constants/BUILD.bazel b/graft/coreth/constants/BUILD.bazel new file mode 100644 index 000000000000..7cdada1557ff --- /dev/null +++ b/graft/coreth/constants/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "constants", + srcs = ["constants.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/constants", + visibility = ["//visibility:public"], + deps = ["@com_github_ava_labs_libevm//common"], +) diff --git a/graft/coreth/core/BUILD.bazel b/graft/coreth/core/BUILD.bazel new file mode 100644 index 000000000000..779b12baa387 --- /dev/null +++ b/graft/coreth/core/BUILD.bazel @@ -0,0 +1,161 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "core", + srcs = [ + "block_validator.go", + "blockchain.go", + "blockchain_ext.go", + "blockchain_iterator.go", + "blockchain_reader.go", + "bloom_indexer.go", + "bounded_buffer.go", + "chain_indexer.go", + "chain_makers.go", + "error.go", + "events.go", + "evm.go", + "fifo_cache.go", + "gaspool.go", + "gen_genesis.go", + "genesis.go", + "headerchain.go", + "predicate_check.go", + "sender_cacher.go", + "state_manager.go", + "state_processor.go", + "state_processor_ext.go", + "state_transition.go", + "txindexer.go", + "types.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core", + visibility = ["//visibility:public"], + deps = [ + "//firewood/ffi", + "//graft/coreth/consensus", + "//graft/coreth/core/extstate", + "//graft/coreth/core/state/snapshot", + "//graft/coreth/internal/version", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap3", + "//graft/coreth/precompile/contract", + "//graft/coreth/precompile/modules", + "//graft/coreth/precompile/precompileconfig", + "//graft/coreth/triedb/firewood", + "//graft/coreth/triedb/hashdb", + "//graft/coreth/triedb/pathdb", + "//utils/set", + "//vms/evm/acp176", + "//vms/evm/acp226", + "//vms/evm/predicate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/bitutil", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//common/lru", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//consensus/misc/eip4844", + "@com_github_ava_labs_libevm//core", + "@com_github_ava_labs_libevm//core/bloombits", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//crypto/kzg4844", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//libevm", + "@com_github_ava_labs_libevm//libevm/stateconf", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "core_test", + srcs = [ + "bench_test.go", + "block_validator_test.go", + "blockchain_ext_test.go", + "blockchain_log_test.go", + "blockchain_repair_test.go", + "blockchain_sethead_test.go", + "blockchain_snapshot_test.go", + "blockchain_test.go", + "chain_indexer_test.go", + "chain_makers_test.go", + "genesis_extra_test.go", + "genesis_test.go", + "headerchain_test.go", + "main_test.go", + "predicate_check_test.go", + "rlp_test.go", + "state_manager_test.go", + "state_processor_test.go", + "state_transition_test.go", + "txindexer_test.go", + ], + embed = [":core"], + deps = [ + "//graft/coreth/accounts/abi", + "//graft/coreth/consensus", + "//graft/coreth/consensus/dummy", + "//graft/coreth/core/coretest", + "//graft/coreth/core/extstate", + "//graft/coreth/core/state/pruner", + "//graft/coreth/nativeasset", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/params/paramstest", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap1", + "//graft/coreth/plugin/evm/upgrade/ap3", + "//graft/coreth/plugin/evm/upgrade/ap4", + "//graft/coreth/plugin/evm/upgrade/cortina", + "//graft/coreth/precompile/contracts/warp", + "//graft/coreth/precompile/precompileconfig", + "//graft/coreth/triedb/firewood", + "//graft/coreth/triedb/pathdb", + "//graft/coreth/utils", + "//snow/engine/snowman/block", + "//upgrade", + "//upgrade/upgradetest", + "//utils/set", + "//vms/evm/acp176", + "//vms/evm/predicate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//consensus/misc/eip4844", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//eth/tracers/logger", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_davecgh_go_spew//spew", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + "@org_golang_x_crypto//sha3", + "@org_uber_go_goleak//:goleak", + "@org_uber_go_mock//gomock", + ], +) diff --git a/graft/coreth/core/coretest/BUILD.bazel b/graft/coreth/core/coretest/BUILD.bazel new file mode 100644 index 000000000000..d661f118f7b5 --- /dev/null +++ b/graft/coreth/core/coretest/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "coretest", + srcs = ["test_indices.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core/coretest", + visibility = ["//visibility:public"], + deps = [ + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/core/extstate/BUILD.bazel b/graft/coreth/core/extstate/BUILD.bazel new file mode 100644 index 000000000000..f31a5414923c --- /dev/null +++ b/graft/coreth/core/extstate/BUILD.bazel @@ -0,0 +1,54 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "extstate", + srcs = [ + "database.go", + "firewood_database.go", + "options.go", + "statedb.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core/extstate", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/triedb/firewood", + "//graft/coreth/utils", + "//vms/evm/predicate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//libevm", + "@com_github_ava_labs_libevm//libevm/stateconf", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "extstate_test", + srcs = [ + "database_test.go", + "state_object_test.go", + "statedb_multicoin_test.go", + ], + embed = [":extstate"], + deps = [ + "//graft/coreth/core/state/snapshot", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/triedb/firewood", + "//graft/coreth/triedb/hashdb", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//libevm/stateconf", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/core/state/pruner/BUILD.bazel b/graft/coreth/core/state/pruner/BUILD.bazel new file mode 100644 index 000000000000..ed27050999f6 --- /dev/null +++ b/graft/coreth/core/state/pruner/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "pruner", + srcs = [ + "bloom.go", + "pruner.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core/state/pruner", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core/state/snapshot", + "//graft/coreth/plugin/evm/customrawdb", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_bloomfilter_v2//:bloomfilter", + ], +) diff --git a/graft/coreth/core/state/snapshot/BUILD.bazel b/graft/coreth/core/state/snapshot/BUILD.bazel new file mode 100644 index 000000000000..3ce480a674fe --- /dev/null +++ b/graft/coreth/core/state/snapshot/BUILD.bazel @@ -0,0 +1,73 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "snapshot", + srcs = [ + "context.go", + "conversion.go", + "difflayer.go", + "disklayer.go", + "generate.go", + "iterator.go", + "iterator_binary.go", + "iterator_fast.go", + "journal.go", + "snapshot.go", + "snapshot_ext.go", + "utils.go", + "wipe.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core/state/snapshot", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/utils", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state/snapshot", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//libevm/stateconf", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_bloomfilter_v2//:bloomfilter", + "@org_golang_x_exp//slices", + "@org_golang_x_exp//slog", + ], +) + +go_test( + name = "snapshot_test", + srcs = [ + "difflayer_test.go", + "disklayer_test.go", + "generate_test.go", + "iterator_test.go", + "snapshot_test.go", + "wipe_test.go", + ], + embed = [":snapshot"], + deps = [ + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/triedb/hashdb", + "//graft/coreth/triedb/pathdb", + "//graft/coreth/utils", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//ethdb/memorydb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_uint256//:uint256", + "@org_golang_x_crypto//sha3", + ], +) diff --git a/graft/coreth/core/txpool/BUILD.bazel b/graft/coreth/core/txpool/BUILD.bazel new file mode 100644 index 000000000000..f25d23f659cc --- /dev/null +++ b/graft/coreth/core/txpool/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "txpool", + srcs = [ + "errors.go", + "subpool.go", + "txpool.go", + "validation.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core/txpool", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/params", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto/kzg4844", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//params", + "@com_github_holiman_uint256//:uint256", + ], +) diff --git a/graft/coreth/core/txpool/blobpool/BUILD.bazel b/graft/coreth/core/txpool/blobpool/BUILD.bazel new file mode 100644 index 000000000000..226cc64c383a --- /dev/null +++ b/graft/coreth/core/txpool/blobpool/BUILD.bazel @@ -0,0 +1,67 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "blobpool", + srcs = [ + "blobpool.go", + "config.go", + "evictheap.go", + "interface.go", + "limbo.go", + "metrics.go", + "priority.go", + "slotter.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core/txpool/blobpool", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/core/txpool", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customheader", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//consensus/misc/eip4844", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/txpool/blobpool", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + "@com_github_holiman_billy//:billy", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "blobpool_test", + srcs = [ + "blobpool_test.go", + "evictheap_test.go", + "priority_test.go", + "slotter_test.go", + ], + embed = [":blobpool"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/core/txpool", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/upgrade/ap3", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//consensus/misc/eip4844", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//crypto/kzg4844", + "@com_github_ava_labs_libevm//ethdb/memorydb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + "@com_github_holiman_billy//:billy", + "@com_github_holiman_uint256//:uint256", + ], +) diff --git a/graft/coreth/core/txpool/legacypool/BUILD.bazel b/graft/coreth/core/txpool/legacypool/BUILD.bazel new file mode 100644 index 000000000000..95af342e261c --- /dev/null +++ b/graft/coreth/core/txpool/legacypool/BUILD.bazel @@ -0,0 +1,55 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "legacypool", + srcs = [ + "journal.go", + "legacypool.go", + "list.go", + "noncer.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core/txpool/legacypool", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/core/txpool", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/utils", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/prque", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/txpool/legacypool", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//rlp", + "@com_github_holiman_uint256//:uint256", + "@org_golang_x_exp//slices", + ], +) + +go_test( + name = "legacypool_test", + srcs = [ + "legacypool2_test.go", + "legacypool_test.go", + "list_test.go", + ], + embed = [":legacypool"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/core/txpool", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//trie", + "@com_github_holiman_uint256//:uint256", + ], +) diff --git a/graft/coreth/core/vm/runtime/BUILD.bazel b/graft/coreth/core/vm/runtime/BUILD.bazel new file mode 100644 index 000000000000..64cd33ac152a --- /dev/null +++ b/graft/coreth/core/vm/runtime/BUILD.bazel @@ -0,0 +1,51 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "runtime", + srcs = [ + "doc.go", + "env.go", + "runtime.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/core/vm/runtime", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/upgrade/ap3", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//params", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "runtime_test", + srcs = [ + "runtime_example_test.go", + "runtime_test.go", + ], + embed = [":runtime"], + deps = [ + "//graft/coreth/accounts/abi", + "//graft/coreth/consensus", + "//graft/coreth/core", + "//graft/coreth/eth/tracers", + "//graft/coreth/params", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/asm", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//eth/tracers/js", + "@com_github_ava_labs_libevm//eth/tracers/logger", + "@com_github_holiman_uint256//:uint256", + ], +) diff --git a/graft/coreth/eth/BUILD.bazel b/graft/coreth/eth/BUILD.bazel new file mode 100644 index 000000000000..5149b008a40d --- /dev/null +++ b/graft/coreth/eth/BUILD.bazel @@ -0,0 +1,77 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "eth", + srcs = [ + "api.go", + "api_admin.go", + "api_backend.go", + "api_debug.go", + "backend.go", + "bloombits.go", + "chain_with_final_block.go", + "state_accessor.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/eth", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/consensus", + "//graft/coreth/core", + "//graft/coreth/core/extstate", + "//graft/coreth/core/state/pruner", + "//graft/coreth/core/txpool", + "//graft/coreth/core/txpool/legacypool", + "//graft/coreth/eth/ethconfig", + "//graft/coreth/eth/filters", + "//graft/coreth/eth/gasprice", + "//graft/coreth/eth/tracers", + "//graft/coreth/internal/ethapi", + "//graft/coreth/internal/shutdowncheck", + "//graft/coreth/miner", + "//graft/coreth/node", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/rpc", + "//utils/timer/mockable", + "@com_github_ava_labs_libevm//accounts", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/bitutil", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/bloombits", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + ], +) + +go_test( + name = "eth_test", + srcs = [ + "api_backend_test.go", + "api_debug_test.go", + ], + embed = [":eth"], + deps = [ + "//graft/coreth/core/extstate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//triedb", + "@com_github_davecgh_go_spew//spew", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//assert", + "@com_github_stretchr_testify//require", + "@org_golang_x_exp//slices", + ], +) diff --git a/graft/coreth/eth/ethconfig/BUILD.bazel b/graft/coreth/eth/ethconfig/BUILD.bazel new file mode 100644 index 000000000000..5abbba08f7c9 --- /dev/null +++ b/graft/coreth/eth/ethconfig/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "ethconfig", + srcs = [ + "config.go", + "gen_config.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/eth/ethconfig", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/core/txpool/blobpool", + "//graft/coreth/core/txpool/legacypool", + "//graft/coreth/eth/gasprice", + "//graft/coreth/internal/ethapi", + "//graft/coreth/miner", + "//graft/coreth/params", + "@com_github_ava_labs_libevm//common", + ], +) diff --git a/graft/coreth/eth/filters/BUILD.bazel b/graft/coreth/eth/filters/BUILD.bazel new file mode 100644 index 000000000000..e3ee372afc67 --- /dev/null +++ b/graft/coreth/eth/filters/BUILD.bazel @@ -0,0 +1,59 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "filters", + srcs = [ + "api.go", + "filter.go", + "filter_system.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/eth/filters", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/internal/ethapi", + "//graft/coreth/params", + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/bloombits", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + ], +) + +go_test( + name = "filters_test", + srcs = [ + "api_test.go", + "bench_test.go", + "filter_system_test.go", + "filter_test.go", + ], + embed = [":filters"], + deps = [ + "//graft/coreth/accounts/abi", + "//graft/coreth/consensus/dummy", + "//graft/coreth/core", + "//graft/coreth/internal/ethapi", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/bitutil", + "@com_github_ava_labs_libevm//core/bloombits", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//triedb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/eth/gasestimator/BUILD.bazel b/graft/coreth/eth/gasestimator/BUILD.bazel new file mode 100644 index 000000000000..df77be73dba9 --- /dev/null +++ b/graft/coreth/eth/gasestimator/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "gasestimator", + srcs = ["gasestimator.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/eth/gasestimator", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/params", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + ], +) diff --git a/graft/coreth/eth/gasprice/BUILD.bazel b/graft/coreth/eth/gasprice/BUILD.bazel new file mode 100644 index 000000000000..18ccbe1cce9e --- /dev/null +++ b/graft/coreth/eth/gasprice/BUILD.bazel @@ -0,0 +1,53 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "gasprice", + srcs = [ + "fee_info_provider.go", + "feehistory.go", + "gasprice.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/eth/gasprice", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/rpc", + "//utils/timer/mockable", + "//vms/evm/acp176", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/lru", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + "@com_github_hashicorp_golang_lru//:golang-lru", + "@org_golang_x_exp//slices", + ], +) + +go_test( + name = "gasprice_test", + srcs = [ + "fee_info_provider_test.go", + "feehistory_test.go", + "gasprice_test.go", + ], + embed = [":gasprice"], + deps = [ + "//graft/coreth/consensus/dummy", + "//graft/coreth/core", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/upgrade/ap4", + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//params", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/eth/tracers/BUILD.bazel b/graft/coreth/eth/tracers/BUILD.bazel new file mode 100644 index 000000000000..06d8ab9fb638 --- /dev/null +++ b/graft/coreth/eth/tracers/BUILD.bazel @@ -0,0 +1,61 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "tracers", + srcs = [ + "api.go", + "tracers.go", + "tracker.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/eth/tracers", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/consensus", + "//graft/coreth/core", + "//graft/coreth/internal/ethapi", + "//graft/coreth/params", + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//eth/tracers", + "@com_github_ava_labs_libevm//eth/tracers/logger", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//rlp", + ], +) + +go_test( + name = "tracers_test", + srcs = [ + "api_test.go", + "tracers_test.go", + "tracker_test.go", + ], + embed = [":tracers"], + deps = [ + "//graft/coreth/consensus", + "//graft/coreth/consensus/dummy", + "//graft/coreth/core", + "//graft/coreth/internal/ethapi", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/rpc", + "//graft/coreth/tests", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//eth/tracers/logger", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//params", + "@org_golang_x_exp//slices", + ], +) diff --git a/graft/coreth/ethclient/BUILD.bazel b/graft/coreth/ethclient/BUILD.bazel new file mode 100644 index 000000000000..f14842da31ba --- /dev/null +++ b/graft/coreth/ethclient/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "ethclient", + srcs = [ + "ethclient.go", + "ethclient_ext.go", + "signer.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/ethclient", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/accounts/abi/bind", + "//graft/coreth/interfaces", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/precompile/registry", + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/types", + ], +) diff --git a/graft/coreth/ethclient/corethclient/BUILD.bazel b/graft/coreth/ethclient/corethclient/BUILD.bazel new file mode 100644 index 000000000000..a1e9345a6fc5 --- /dev/null +++ b/graft/coreth/ethclient/corethclient/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "corethclient", + srcs = ["corethclient.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/ethclient/corethclient", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/ethclient", + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/types", + ], +) diff --git a/graft/coreth/ethclient/simulated/BUILD.bazel b/graft/coreth/ethclient/simulated/BUILD.bazel new file mode 100644 index 000000000000..4fcf40ddc3ac --- /dev/null +++ b/graft/coreth/ethclient/simulated/BUILD.bazel @@ -0,0 +1,51 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "simulated", + srcs = [ + "backend.go", + "options.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/ethclient/simulated", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/consensus/dummy", + "//graft/coreth/constants", + "//graft/coreth/core", + "//graft/coreth/eth", + "//graft/coreth/eth/ethconfig", + "//graft/coreth/ethclient", + "//graft/coreth/interfaces", + "//graft/coreth/node", + "//graft/coreth/params", + "//graft/coreth/rpc", + "//utils/timer/mockable", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + ], +) + +go_test( + name = "simulated_test", + srcs = [ + "backend_test.go", + "options_test.go", + ], + embed = [":simulated"], + deps = [ + "//graft/coreth/accounts/abi/bind", + "//graft/coreth/core", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/rpc", + "//vms/evm/acp176", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//params", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/go.mod b/graft/coreth/go.mod index 8ed6774b6dc6..db89c72a6a40 100644 --- a/graft/coreth/go.mod +++ b/graft/coreth/go.mod @@ -190,3 +190,5 @@ tool ( ) replace github.com/ava-labs/avalanchego => ../../ + +replace github.com/ava-labs/firewood-go-ethhash/ffi => ../../firewood/ffi diff --git a/graft/coreth/interfaces/BUILD.bazel b/graft/coreth/interfaces/BUILD.bazel new file mode 100644 index 000000000000..db8e5d4b8222 --- /dev/null +++ b/graft/coreth/interfaces/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "interfaces", + srcs = ["interfaces.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/interfaces", + visibility = ["//visibility:public"], + deps = [ + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + ], +) diff --git a/graft/coreth/internal/blocktest/BUILD.bazel b/graft/coreth/internal/blocktest/BUILD.bazel new file mode 100644 index 000000000000..ae09a57ab10d --- /dev/null +++ b/graft/coreth/internal/blocktest/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "blocktest", + srcs = ["test_hash.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/internal/blocktest", + visibility = ["//graft/coreth:__subpackages__"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@org_golang_x_crypto//sha3", + ], +) diff --git a/graft/coreth/internal/debug/BUILD.bazel b/graft/coreth/internal/debug/BUILD.bazel new file mode 100644 index 000000000000..1daa99857c82 --- /dev/null +++ b/graft/coreth/internal/debug/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "debug", + srcs = [ + "api.go", + "flags.go", + "loudpanic.go", + "trace.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/internal/debug", + visibility = ["//graft/coreth:__subpackages__"], + deps = [ + "//graft/coreth/internal/flags", + "@com_github_ava_labs_libevm//log", + "@com_github_hashicorp_go_bexpr//:go-bexpr", + "@com_github_mattn_go_colorable//:go-colorable", + "@com_github_mattn_go_isatty//:go-isatty", + "@com_github_urfave_cli_v2//:cli", + "@in_gopkg_natefinch_lumberjack_v2//:lumberjack_v2", + "@org_golang_x_exp//slog", + ], +) diff --git a/graft/coreth/internal/ethapi/BUILD.bazel b/graft/coreth/internal/ethapi/BUILD.bazel new file mode 100644 index 000000000000..8c171f255270 --- /dev/null +++ b/graft/coreth/internal/ethapi/BUILD.bazel @@ -0,0 +1,93 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "ethapi", + srcs = [ + "addrlock.go", + "api.coreth.go", + "api.go", + "api_extra.go", + "backend.go", + "errors.go", + "transaction_args.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/internal/ethapi", + visibility = ["//graft/coreth:__subpackages__"], + deps = [ + "//graft/coreth/accounts/abi", + "//graft/coreth/consensus", + "//graft/coreth/core", + "//graft/coreth/eth/gasestimator", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/rpc", + "//graft/coreth/triedb/firewood", + "@com_github_ava_labs_libevm//accounts", + "@com_github_ava_labs_libevm//accounts/keystore", + "@com_github_ava_labs_libevm//accounts/scwallet", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//consensus/misc/eip4844", + "@com_github_ava_labs_libevm//core/bloombits", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//crypto/kzg4844", + "@com_github_ava_labs_libevm//eth/tracers/logger", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_davecgh_go_spew//spew", + "@com_github_holiman_uint256//:uint256", + "@com_github_tyler_smith_go_bip39//:go-bip39", + ], +) + +go_test( + name = "ethapi_test", + srcs = [ + "api.coreth_test.go", + "api_extra_test.go", + "api_test.go", + "mocks_generate_test.go", + "mocks_test.go", + "transaction_args_test.go", + ], + data = glob(["testdata/**"]), + embed = [":ethapi"], + deps = [ + "//graft/coreth/consensus", + "//graft/coreth/consensus/dummy", + "//graft/coreth/core", + "//graft/coreth/internal/blocktest", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/upgrade/ap3", + "//graft/coreth/rpc", + "//graft/coreth/utils", + "//vms/evm/acp176", + "@com_github_ava_labs_libevm//accounts", + "@com_github_ava_labs_libevm//accounts/keystore", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/bloombits", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//crypto/kzg4844", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//params", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + "@org_golang_x_exp//slices", + "@org_uber_go_mock//gomock", + ], +) diff --git a/graft/coreth/internal/flags/BUILD.bazel b/graft/coreth/internal/flags/BUILD.bazel new file mode 100644 index 000000000000..36326a4a6435 --- /dev/null +++ b/graft/coreth/internal/flags/BUILD.bazel @@ -0,0 +1,17 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "flags", + srcs = [ + "categories.go", + "helpers.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/internal/flags", + visibility = ["//graft/coreth:__subpackages__"], + deps = [ + "//graft/coreth/internal/version", + "//graft/coreth/params", + "@com_github_mattn_go_isatty//:go-isatty", + "@com_github_urfave_cli_v2//:cli", + ], +) diff --git a/graft/coreth/internal/shutdowncheck/BUILD.bazel b/graft/coreth/internal/shutdowncheck/BUILD.bazel new file mode 100644 index 000000000000..287e5dd6791d --- /dev/null +++ b/graft/coreth/internal/shutdowncheck/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "shutdowncheck", + srcs = ["shutdown_tracker.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/internal/shutdowncheck", + visibility = ["//graft/coreth:__subpackages__"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + ], +) diff --git a/graft/coreth/internal/version/BUILD.bazel b/graft/coreth/internal/version/BUILD.bazel new file mode 100644 index 000000000000..08c55c5b733d --- /dev/null +++ b/graft/coreth/internal/version/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "version", + srcs = [ + "vcs.go", + "version.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/internal/version", + visibility = ["//graft/coreth:__subpackages__"], + deps = ["//graft/coreth/params"], +) diff --git a/graft/coreth/log/BUILD.bazel b/graft/coreth/log/BUILD.bazel new file mode 100644 index 000000000000..2a792252d620 --- /dev/null +++ b/graft/coreth/log/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "log", + srcs = [ + "format.go", + "handler.go", + "logger.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/log", + visibility = ["//visibility:public"], + deps = [ + "@com_github_holiman_uint256//:uint256", + "@org_golang_x_exp//slog", + ], +) diff --git a/graft/coreth/miner/BUILD.bazel b/graft/coreth/miner/BUILD.bazel new file mode 100644 index 000000000000..a85829d20afc --- /dev/null +++ b/graft/coreth/miner/BUILD.bazel @@ -0,0 +1,49 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "miner", + srcs = [ + "miner.go", + "ordering.go", + "worker.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/miner", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/consensus", + "//graft/coreth/core", + "//graft/coreth/core/extstate", + "//graft/coreth/core/txpool", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/upgrade/cortina", + "//graft/coreth/precompile/precompileconfig", + "//utils/timer/mockable", + "//utils/units", + "//vms/evm/acp176", + "//vms/evm/predicate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//consensus/misc/eip4844", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//event", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "miner_test", + srcs = ["ordering_test.go"], + embed = [":miner"], + deps = [ + "//graft/coreth/core/txpool", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_holiman_uint256//:uint256", + ], +) diff --git a/graft/coreth/nativeasset/BUILD.bazel b/graft/coreth/nativeasset/BUILD.bazel new file mode 100644 index 000000000000..aeb60d47dbd9 --- /dev/null +++ b/graft/coreth/nativeasset/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "nativeasset", + srcs = ["contract.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/nativeasset", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/precompile/contract", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//log", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "nativeasset_test", + srcs = ["contract_test.go"], + deps = [ + ":nativeasset", + "//graft/coreth/core", + "//graft/coreth/core/extstate", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//params", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/network/BUILD.bazel b/graft/coreth/network/BUILD.bazel new file mode 100644 index 000000000000..17cba0780d9a --- /dev/null +++ b/graft/coreth/network/BUILD.bazel @@ -0,0 +1,55 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "network", + srcs = [ + "network.go", + "peer_tracker.go", + "waiting_handler.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/network", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//graft/coreth/network/stats", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/utils/rand", + "//ids", + "//network/p2p", + "//snow", + "//snow/engine/common", + "//snow/validators", + "//utils", + "//utils/math", + "//utils/set", + "//version", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_x_sync//semaphore", + ], +) + +go_test( + name = "network_test", + srcs = [ + "network_test.go", + "peer_tracker_test.go", + ], + embed = [":network"], + deps = [ + "//codec", + "//codec/linearcodec", + "//graft/coreth/plugin/evm/message", + "//ids", + "//network/p2p", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/snowtest", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_x_sync//errgroup", + ], +) diff --git a/graft/coreth/network/stats/BUILD.bazel b/graft/coreth/network/stats/BUILD.bazel new file mode 100644 index 000000000000..aeac77f7b87c --- /dev/null +++ b/graft/coreth/network/stats/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "stats", + srcs = ["stats.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/network/stats", + visibility = ["//visibility:public"], + deps = ["@com_github_ava_labs_libevm//metrics"], +) diff --git a/graft/coreth/node/BUILD.bazel b/graft/coreth/node/BUILD.bazel new file mode 100644 index 000000000000..4bf0bfd42cc4 --- /dev/null +++ b/graft/coreth/node/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "node", + srcs = [ + "api.go", + "config.go", + "defaults.go", + "errors.go", + "node.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/node", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/internal/debug", + "//graft/coreth/rpc", + "@com_github_ava_labs_libevm//accounts", + "@com_github_ava_labs_libevm//accounts/external", + "@com_github_ava_labs_libevm//accounts/keystore", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//log", + ], +) diff --git a/graft/coreth/params/BUILD.bazel b/graft/coreth/params/BUILD.bazel new file mode 100644 index 000000000000..7fb670e9ee0c --- /dev/null +++ b/graft/coreth/params/BUILD.bazel @@ -0,0 +1,53 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "params", + srcs = [ + "config.go", + "config_extra.go", + "config_libevm.go", + "denomination.go", + "hooks_libevm.go", + "network_params.go", + "protocol_params_ext.go", + "version.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/params", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/nativeasset", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/precompile/contract", + "//graft/coreth/precompile/modules", + "//graft/coreth/precompile/precompileconfig", + "//graft/coreth/utils", + "//snow", + "//upgrade", + "//utils/set", + "//vms/evm/predicate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//libevm", + "@com_github_ava_labs_libevm//libevm/legacy", + "@com_github_ava_labs_libevm//params", + ], +) + +go_test( + name = "params_test", + srcs = [ + "config_extra_test.go", + "config_test.go", + "protocol_params_test.go", + ], + embed = [":params"], + deps = [ + "//graft/coreth/params/extras", + "//graft/coreth/utils", + "//upgrade/upgradetest", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//params", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/params/extras/BUILD.bazel b/graft/coreth/params/extras/BUILD.bazel new file mode 100644 index 000000000000..8764358d4838 --- /dev/null +++ b/graft/coreth/params/extras/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "extras", + srcs = [ + "config.go", + "network_upgrades.go", + "precompile_upgrade.go", + "precompiles.go", + "rules.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/params/extras", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/precompile/modules", + "//graft/coreth/precompile/precompileconfig", + "//graft/coreth/utils", + "//snow", + "//upgrade", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//params", + ], +) + +go_test( + name = "extras_test", + srcs = ["config_extra_test.go"], + embed = [":extras"], + deps = [ + "//graft/coreth/utils", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/params/extras/extrastest/BUILD.bazel b/graft/coreth/params/extras/extrastest/BUILD.bazel new file mode 100644 index 000000000000..feec2906d567 --- /dev/null +++ b/graft/coreth/params/extras/extrastest/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "extrastest", + srcs = ["test_rules.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/params/extras/extrastest", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/params/paramstest", + "//upgrade", + "//upgrade/upgradetest", + "@com_github_ava_labs_libevm//common", + ], +) diff --git a/graft/coreth/params/paramstest/BUILD.bazel b/graft/coreth/params/paramstest/BUILD.bazel new file mode 100644 index 000000000000..c03f411e2b54 --- /dev/null +++ b/graft/coreth/params/paramstest/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "paramstest", + srcs = ["forks.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/params/paramstest", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/params", + "//upgrade/upgradetest", + ], +) diff --git a/graft/coreth/plugin/BUILD.bazel b/graft/coreth/plugin/BUILD.bazel new file mode 100644 index 000000000000..a3d1efa7ef36 --- /dev/null +++ b/graft/coreth/plugin/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "plugin_lib", + srcs = [ + "keys.go", + "main.go", + "params.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin", + visibility = ["//visibility:private"], + deps = [ + "//graft/coreth/plugin/evm", + "//graft/coreth/plugin/factory", + "//utils/logging", + "//utils/ulimit", + "//vms/rpcchainvm", + "@com_github_spf13_pflag//:pflag", + "@com_github_spf13_viper//:viper", + ], +) + +go_binary( + name = "plugin", + embed = [":plugin_lib"], + visibility = ["//visibility:public"], +) diff --git a/graft/coreth/plugin/evm/BUILD.bazel b/graft/coreth/plugin/evm/BUILD.bazel new file mode 100644 index 000000000000..66034994ab4f --- /dev/null +++ b/graft/coreth/plugin/evm/BUILD.bazel @@ -0,0 +1,196 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "evm", + srcs = [ + "admin.go", + "block_builder.go", + "eth_gossiper.go", + "health.go", + "libevm.go", + "network_handler.go", + "version.go", + "vm.go", + "vm_database.go", + "vm_extensible.go", + "wrapped_block.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm", + visibility = ["//visibility:public"], + deps = [ + "//api", + "//cache/lru", + "//cache/metercacher", + "//codec", + "//database", + "//database/prefixdb", + "//database/versiondb", + "//firewood/ffi", + "//graft/coreth/consensus/dummy", + "//graft/coreth/constants", + "//graft/coreth/core", + "//graft/coreth/core/extstate", + "//graft/coreth/core/txpool", + "//graft/coreth/eth", + "//graft/coreth/eth/ethconfig", + "//graft/coreth/miner", + "//graft/coreth/network", + "//graft/coreth/node", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/client", + "//graft/coreth/plugin/evm/config", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/extension", + "//graft/coreth/plugin/evm/gossip", + "//graft/coreth/plugin/evm/log", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap1", + "//graft/coreth/plugin/evm/vmerrors", + "//graft/coreth/plugin/evm/vmsync", + "//graft/coreth/precompile/contracts/warp", + "//graft/coreth/precompile/precompileconfig", + "//graft/coreth/precompile/registry", + "//graft/coreth/rpc", + "//graft/coreth/sync/client", + "//graft/coreth/sync/client/stats", + "//graft/coreth/sync/handlers", + "//graft/coreth/sync/handlers/stats", + "//graft/coreth/triedb/hashdb", + "//graft/coreth/utils/rpc", + "//graft/coreth/warp", + "//ids", + "//network/p2p", + "//network/p2p/acp118", + "//network/p2p/gossip", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils", + "//utils/lock", + "//utils/math", + "//utils/perms", + "//utils/profiler", + "//utils/timer/mockable", + "//utils/units", + "//vms/components/chain", + "//vms/components/gas", + "//vms/evm/acp176", + "//vms/evm/acp226", + "//vms/evm/database", + "//vms/evm/metrics/prometheus", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//eth/tracers/js", + "@com_github_ava_labs_libevm//eth/tracers/native", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//libevm", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_uint256//:uint256", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "evm_test", + srcs = [ + "block_builder_test.go", + "gossip_test.go", + "imports_test.go", + "prestate_tracer_test.go", + "syncervm_test.go", + "tx_gossip_test.go", + "vm_test.go", + "vm_warp_test.go", + ], + data = glob(["testdata/**"]), + embed = [":evm"], + embedsrcs = [ + "ExampleWarp.abi", + "ExampleWarp.bin", + ], + deps = [ + "//database", + "//database/memdb", + "//graft/coreth/consensus/dummy", + "//graft/coreth/constants", + "//graft/coreth/core", + "//graft/coreth/core/txpool", + "//graft/coreth/core/txpool/legacypool", + "//graft/coreth/eth", + "//graft/coreth/eth/tracers", + "//graft/coreth/miner", + "//graft/coreth/node", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/params/paramstest", + "//graft/coreth/plugin/evm/config", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/extension", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap1", + "//graft/coreth/plugin/evm/vmtest", + "//graft/coreth/precompile/contract", + "//graft/coreth/precompile/contracts/warp", + "//graft/coreth/rpc", + "//graft/coreth/tests", + "//graft/coreth/utils", + "//graft/coreth/utils/utilstest", + "//graft/coreth/warp", + "//ids", + "//network/p2p", + "//network/p2p/acp118", + "//network/p2p/gossip", + "//proto/pb/sdk", + "//snow", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/snowtest", + "//snow/validators", + "//snow/validators/validatorstest", + "//upgrade", + "//upgrade/upgradetest", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/logging", + "//utils/set", + "//utils/timer/mockable", + "//vms/components/chain", + "//vms/evm/acp176", + "//vms/evm/acp226", + "//vms/evm/predicate", + "//vms/platformvm/warp", + "//vms/platformvm/warp/payload", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//trie", + "@com_github_holiman_uint256//:uint256", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + ], +) diff --git a/graft/coreth/plugin/evm/atomic/BUILD.bazel b/graft/coreth/plugin/evm/atomic/BUILD.bazel new file mode 100644 index 000000000000..ea57eec11251 --- /dev/null +++ b/graft/coreth/plugin/evm/atomic/BUILD.bazel @@ -0,0 +1,63 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "atomic", + srcs = [ + "codec.go", + "export_tx.go", + "gossip.go", + "import_tx.go", + "metadata.go", + "params.go", + "status.go", + "tx.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//codec", + "//codec/linearcodec", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap5", + "//ids", + "//network/p2p/gossip", + "//snow", + "//utils", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/hashing", + "//utils/math", + "//utils/set", + "//utils/units", + "//utils/wrappers", + "//vms/components/avax", + "//vms/components/verify", + "//vms/secp256k1fx", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//log", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "atomic_test", + srcs = [ + "gossip_test.go", + "tx_test.go", + ], + embed = [":atomic"], + deps = [ + "//graft/coreth/plugin/evm/upgrade/ap5", + "//ids", + "//utils/crypto/secp256k1", + "//utils/math", + "//utils/units", + "//vms/components/avax", + "//vms/components/verify", + "//vms/secp256k1fx", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/atomic/atomictest/BUILD.bazel b/graft/coreth/plugin/evm/atomic/atomictest/BUILD.bazel new file mode 100644 index 000000000000..170cb50ec5b3 --- /dev/null +++ b/graft/coreth/plugin/evm/atomic/atomictest/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "atomictest", + srcs = [ + "ops.go", + "shared_memories.go", + "tx.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic/atomictest", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//codec", + "//codec/linearcodec", + "//database", + "//database/memdb", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/atomic", + "//ids", + "//snow", + "//snow/snowtest", + "//utils", + "//utils/set", + "//utils/wrappers", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/atomic/state/BUILD.bazel b/graft/coreth/plugin/evm/atomic/state/BUILD.bazel new file mode 100644 index 000000000000..a29b8f09891d --- /dev/null +++ b/graft/coreth/plugin/evm/atomic/state/BUILD.bazel @@ -0,0 +1,69 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "state", + srcs = [ + "atomic_backend.go", + "atomic_repository.go", + "atomic_state.go", + "atomic_trie.go", + "atomic_trie_iterator.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic/state", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//codec", + "//database", + "//database/prefixdb", + "//database/versiondb", + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/triedb/hashdb", + "//ids", + "//utils", + "//utils/units", + "//utils/wrappers", + "//vms/evm/database", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//triedb", + ], +) + +go_test( + name = "state_test", + srcs = [ + "atomic_repository_test.go", + "atomic_trie_iterator_test.go", + "atomic_trie_test.go", + ], + embed = [":state"], + deps = [ + "//chains/atomic", + "//codec", + "//database", + "//database/leveldb", + "//database/memdb", + "//database/prefixdb", + "//database/versiondb", + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/plugin/evm/atomic/atomictest", + "//ids", + "//snow/snowtest", + "//utils", + "//utils/logging", + "//utils/set", + "//utils/wrappers", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/atomic/sync/BUILD.bazel b/graft/coreth/plugin/evm/atomic/sync/BUILD.bazel new file mode 100644 index 000000000000..2fda215f39bf --- /dev/null +++ b/graft/coreth/plugin/evm/atomic/sync/BUILD.bazel @@ -0,0 +1,63 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "sync", + srcs = [ + "extender.go", + "leaf_handler.go", + "summary.go", + "summary_parser.go", + "summary_provider.go", + "syncer.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic/sync", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//database/versiondb", + "//graft/coreth/plugin/evm/atomic/state", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync", + "//graft/coreth/sync/client", + "//graft/coreth/sync/handlers", + "//graft/coreth/sync/handlers/stats", + "//ids", + "//snow/engine/snowman/block", + "//utils/wrappers", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//libevm/options", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + ], +) + +go_test( + name = "sync_test", + srcs = [ + "summary_test.go", + "syncer_test.go", + ], + embed = [":sync"], + deps = [ + "//database", + "//database/memdb", + "//database/versiondb", + "//graft/coreth/plugin/evm/atomic/atomictest", + "//graft/coreth/plugin/evm/atomic/state", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync/client", + "//graft/coreth/sync/handlers", + "//graft/coreth/sync/handlers/stats", + "//graft/coreth/sync/statesync/statesynctest", + "//ids", + "//snow/engine/snowman/block", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/atomic/txpool/BUILD.bazel b/graft/coreth/plugin/evm/atomic/txpool/BUILD.bazel new file mode 100644 index 000000000000..2b67b8016381 --- /dev/null +++ b/graft/coreth/plugin/evm/atomic/txpool/BUILD.bazel @@ -0,0 +1,44 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "txpool", + srcs = [ + "mempool.go", + "metrics.go", + "tx_heap.go", + "txs.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic/txpool", + visibility = ["//visibility:public"], + deps = [ + "//cache/lru", + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/plugin/evm/config", + "//ids", + "//network/p2p/gossip", + "//snow", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_holiman_uint256//:uint256", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "txpool_test", + srcs = [ + "mempool_test.go", + "tx_heap_test.go", + ], + embed = [":txpool"], + deps = [ + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/plugin/evm/atomic/atomictest", + "//graft/coreth/plugin/evm/config", + "//snow/snowtest", + "//utils/bloom", + "@com_github_holiman_uint256//:uint256", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/atomic/vm/BUILD.bazel b/graft/coreth/plugin/evm/atomic/vm/BUILD.bazel new file mode 100644 index 000000000000..8051f9a00823 --- /dev/null +++ b/graft/coreth/plugin/evm/atomic/vm/BUILD.bazel @@ -0,0 +1,135 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "vm", + srcs = [ + "api.go", + "block_extension.go", + "bonus_blocks.go", + "ext_data_hashes.go", + "formatting.go", + "tx_semantic_verifier.go", + "vm.go", + ], + embedsrcs = [ + "fuji_ext_data_hashes.json", + "mainnet_ext_data_hashes.json", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/atomic/vm", + visibility = ["//visibility:public"], + deps = [ + "//api", + "//codec", + "//codec/linearcodec", + "//database", + "//graft/coreth/consensus/dummy", + "//graft/coreth/core/extstate", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/plugin/evm/atomic/state", + "//graft/coreth/plugin/evm/atomic/sync", + "//graft/coreth/plugin/evm/atomic/txpool", + "//graft/coreth/plugin/evm/client", + "//graft/coreth/plugin/evm/config", + "//graft/coreth/plugin/evm/customheader", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/extension", + "//graft/coreth/plugin/evm/gossip", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap5", + "//graft/coreth/plugin/evm/vmerrors", + "//graft/coreth/utils", + "//graft/coreth/utils/rpc", + "//ids", + "//network/p2p", + "//network/p2p/gossip", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/formatting", + "//utils/formatting/address", + "//utils/json", + "//utils/logging", + "//utils/math", + "//utils/set", + "//utils/timer/mockable", + "//utils/units", + "//vms/components/avax", + "//vms/secp256k1fx", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//log", + ], +) + +go_test( + name = "vm_test", + srcs = [ + "export_tx_test.go", + "import_tx_test.go", + "syncervm_test.go", + "tx_gossip_test.go", + "tx_test.go", + "vm_test.go", + ], + embed = [":vm"], + deps = [ + "//chains/atomic", + "//database/memdb", + "//graft/coreth/consensus/dummy", + "//graft/coreth/core", + "//graft/coreth/core/extstate", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/params/extras/extrastest", + "//graft/coreth/plugin/evm", + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/plugin/evm/atomic/atomictest", + "//graft/coreth/plugin/evm/atomic/txpool", + "//graft/coreth/plugin/evm/config", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/extension", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap1", + "//graft/coreth/plugin/evm/vmtest", + "//graft/coreth/utils", + "//graft/coreth/utils/utilstest", + "//ids", + "//network/p2p", + "//network/p2p/gossip", + "//proto/pb/sdk", + "//snow", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/snowtest", + "//snow/validators", + "//upgrade/upgradetest", + "//utils", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/hashing", + "//utils/logging", + "//utils/set", + "//utils/units", + "//vms/components/avax", + "//vms/components/chain", + "//vms/evm/predicate", + "//vms/secp256k1fx", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_holiman_uint256//:uint256", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + ], +) diff --git a/graft/coreth/plugin/evm/client/BUILD.bazel b/graft/coreth/plugin/evm/client/BUILD.bazel new file mode 100644 index 000000000000..3fe3cbce9903 --- /dev/null +++ b/graft/coreth/plugin/evm/client/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "client", + srcs = [ + "client.go", + "utils.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/client", + visibility = ["//visibility:public"], + deps = [ + "//api", + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/plugin/evm/config", + "//ids", + "//utils/formatting", + "//utils/formatting/address", + "//utils/json", + "//utils/rpc", + "@com_github_ava_labs_libevm//common", + "@org_golang_x_exp//slog", + ], +) diff --git a/graft/coreth/plugin/evm/config/BUILD.bazel b/graft/coreth/plugin/evm/config/BUILD.bazel new file mode 100644 index 000000000000..611362ed32f8 --- /dev/null +++ b/graft/coreth/plugin/evm/config/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "config", + srcs = [ + "config.go", + "constants.go", + "default_config.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/config", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/utils", + "//utils/constants", + "//utils/units", + "//vms/components/gas", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_spf13_cast//:cast", + ], +) + +go_test( + name = "config_test", + srcs = ["config_test.go"], + embed = [":config"], + deps = [ + "//utils/constants", + "@com_github_ava_labs_libevm//common", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/customheader/BUILD.bazel b/graft/coreth/plugin/evm/customheader/BUILD.bazel new file mode 100644 index 000000000000..2649e537d6ff --- /dev/null +++ b/graft/coreth/plugin/evm/customheader/BUILD.bazel @@ -0,0 +1,69 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "customheader", + srcs = [ + "base_fee.go", + "block_gas_cost.go", + "dynamic_fee_state.go", + "dynamic_fee_windower.go", + "extra.go", + "gas_limit.go", + "min_delay_excess.go", + "time.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/customheader", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap1", + "//graft/coreth/plugin/evm/upgrade/ap3", + "//graft/coreth/plugin/evm/upgrade/ap4", + "//graft/coreth/plugin/evm/upgrade/ap5", + "//graft/coreth/plugin/evm/upgrade/cortina", + "//graft/coreth/plugin/evm/upgrade/etna", + "//utils/math", + "//vms/components/gas", + "//vms/evm/acp176", + "//vms/evm/acp226", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//core/types", + ], +) + +go_test( + name = "customheader_test", + srcs = [ + "base_fee_test.go", + "block_gas_cost_test.go", + "dynamic_fee_windower_test.go", + "extra_test.go", + "gas_limit_test.go", + "min_delay_excess_test.go", + "time_test.go", + ], + embed = [":customheader"], + deps = [ + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/upgrade/ap0", + "//graft/coreth/plugin/evm/upgrade/ap1", + "//graft/coreth/plugin/evm/upgrade/ap3", + "//graft/coreth/plugin/evm/upgrade/ap4", + "//graft/coreth/plugin/evm/upgrade/ap5", + "//graft/coreth/plugin/evm/upgrade/cortina", + "//graft/coreth/plugin/evm/upgrade/etna", + "//graft/coreth/utils", + "//graft/coreth/utils/utilstest", + "//utils/math", + "//vms/components/gas", + "//vms/evm/acp176", + "//vms/evm/acp226", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/customrawdb/BUILD.bazel b/graft/coreth/plugin/evm/customrawdb/BUILD.bazel new file mode 100644 index 000000000000..a88adb91534b --- /dev/null +++ b/graft/coreth/plugin/evm/customrawdb/BUILD.bazel @@ -0,0 +1,37 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "customrawdb", + srcs = [ + "accessors_metadata_ext.go", + "accessors_snapshot_ext.go", + "accessors_state_sync.go", + "database_ext.go", + "schema_ext.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/customrawdb", + visibility = ["//visibility:public"], + deps = [ + "//utils/wrappers", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//rlp", + ], +) + +go_test( + name = "customrawdb_test", + srcs = [ + "accessors_state_sync_test.go", + "database_ext_test.go", + ], + embed = [":customrawdb"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/customtypes/BUILD.bazel b/graft/coreth/plugin/evm/customtypes/BUILD.bazel new file mode 100644 index 000000000000..9739fe6ab96e --- /dev/null +++ b/graft/coreth/plugin/evm/customtypes/BUILD.bazel @@ -0,0 +1,59 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "customtypes", + srcs = [ + "block_ext.go", + "gen_header_serializable_json.go", + "gen_header_serializable_rlp.go", + "hashes_ext.go", + "header_ext.go", + "libevm.go", + "state_account_ext.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/customtypes", + visibility = ["//visibility:public"], + deps = [ + "//vms/evm/acp226", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//libevm", + "@com_github_ava_labs_libevm//rlp", + ], +) + +go_test( + name = "customtypes_test", + srcs = [ + "aliases_test.go", + "block_ext_test.go", + "block_test.go", + "hashing_test.go", + "header_ext_test.go", + "rlp_fuzzer_test.go", + "types_test.go", + ], + embed = [":customtypes"], + deps = [ + "//graft/coreth/internal/blocktest", + "//graft/coreth/params", + "//graft/coreth/utils", + "//graft/coreth/utils/utilstest", + "//vms/evm/acp226", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_google_go_cmp//cmp", + "@com_github_google_go_cmp//cmp/cmpopts", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/extension/BUILD.bazel b/graft/coreth/plugin/evm/extension/BUILD.bazel new file mode 100644 index 000000000000..7bb34f84d452 --- /dev/null +++ b/graft/coreth/plugin/evm/extension/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "extension", + srcs = ["config.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/extension", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//database/versiondb", + "//graft/coreth/consensus/dummy", + "//graft/coreth/eth", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/config", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/plugin/evm/vmsync", + "//graft/coreth/sync", + "//graft/coreth/sync/handlers", + "//ids", + "//network/p2p", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils/timer/mockable", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_prometheus_client_golang//prometheus", + ], +) diff --git a/graft/coreth/plugin/evm/gossip/BUILD.bazel b/graft/coreth/plugin/evm/gossip/BUILD.bazel new file mode 100644 index 000000000000..fc5da5e3d20c --- /dev/null +++ b/graft/coreth/plugin/evm/gossip/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "gossip", + srcs = ["handler.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/gossip", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//network/p2p", + "//network/p2p/gossip", + "//snow/engine/common", + "//utils/logging", + "@com_github_prometheus_client_golang//prometheus", + ], +) diff --git a/graft/coreth/plugin/evm/log/BUILD.bazel b/graft/coreth/plugin/evm/log/BUILD.bazel new file mode 100644 index 000000000000..94f37463fb16 --- /dev/null +++ b/graft/coreth/plugin/evm/log/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "log", + srcs = ["log.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/log", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/log", + "@com_github_ava_labs_libevm//log", + "@org_golang_x_exp//slog", + ], +) + +go_test( + name = "log_test", + srcs = ["log_test.go"], + embed = [":log"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/graft/coreth/plugin/evm/message/BUILD.bazel b/graft/coreth/plugin/evm/message/BUILD.bazel new file mode 100644 index 000000000000..7818426752ed --- /dev/null +++ b/graft/coreth/plugin/evm/message/BUILD.bazel @@ -0,0 +1,46 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "message", + srcs = [ + "block_request.go", + "block_sync_summary.go", + "block_sync_summary_parser.go", + "block_sync_summary_provider.go", + "code_request.go", + "codec.go", + "handler.go", + "leafs_request.go", + "request.go", + "syncable.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/message", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//snow/engine/snowman/block", + "//utils/units", + "//utils/wrappers", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + ], +) + +go_test( + name = "message_test", + srcs = [ + "block_request_test.go", + "block_sync_summary_test.go", + "code_request_test.go", + "leafs_request_test.go", + ], + embed = [":message"], + deps = [ + "//snow/engine/snowman/block", + "@com_github_ava_labs_libevm//common", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/tempextrastest/BUILD.bazel b/graft/coreth/plugin/evm/tempextrastest/BUILD.bazel new file mode 100644 index 000000000000..6dea724d2095 --- /dev/null +++ b/graft/coreth/plugin/evm/tempextrastest/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_test") + +go_test( + name = "tempextrastest_test", + srcs = ["tempextras_test.go"], + deps = [ + "//graft/coreth/params", + "//graft/coreth/plugin/evm", + "//graft/coreth/plugin/evm/customtypes", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//params", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/upgrade/ap0/BUILD.bazel b/graft/coreth/plugin/evm/upgrade/ap0/BUILD.bazel new file mode 100644 index 000000000000..614bb82eb4f4 --- /dev/null +++ b/graft/coreth/plugin/evm/upgrade/ap0/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "ap0", + srcs = ["params.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/upgrade/ap0", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/utils", + "//utils/units", + ], +) diff --git a/graft/coreth/plugin/evm/upgrade/ap1/BUILD.bazel b/graft/coreth/plugin/evm/upgrade/ap1/BUILD.bazel new file mode 100644 index 000000000000..4b621393f51b --- /dev/null +++ b/graft/coreth/plugin/evm/upgrade/ap1/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "ap1", + srcs = ["params.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/upgrade/ap1", + visibility = ["//visibility:public"], + deps = ["//graft/coreth/utils"], +) diff --git a/graft/coreth/plugin/evm/upgrade/ap3/BUILD.bazel b/graft/coreth/plugin/evm/upgrade/ap3/BUILD.bazel new file mode 100644 index 000000000000..d3873efec79c --- /dev/null +++ b/graft/coreth/plugin/evm/upgrade/ap3/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "ap3", + srcs = ["window.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/upgrade/ap3", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/utils", + "//utils/wrappers", + "@com_github_ava_labs_libevm//common/math", + ], +) + +go_test( + name = "ap3_test", + srcs = ["window_test.go"], + embed = [":ap3"], + deps = [ + "@com_github_ava_labs_libevm//common/math", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/upgrade/ap4/BUILD.bazel b/graft/coreth/plugin/evm/upgrade/ap4/BUILD.bazel new file mode 100644 index 000000000000..7b8d1ead4ad7 --- /dev/null +++ b/graft/coreth/plugin/evm/upgrade/ap4/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "ap4", + srcs = ["cost.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/upgrade/ap4", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/utils", + "//utils/math", + ], +) + +go_test( + name = "ap4_test", + srcs = ["cost_test.go"], + embed = [":ap4"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/graft/coreth/plugin/evm/upgrade/ap5/BUILD.bazel b/graft/coreth/plugin/evm/upgrade/ap5/BUILD.bazel new file mode 100644 index 000000000000..094132208143 --- /dev/null +++ b/graft/coreth/plugin/evm/upgrade/ap5/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "ap5", + srcs = ["params.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/upgrade/ap5", + visibility = ["//visibility:public"], +) diff --git a/graft/coreth/plugin/evm/upgrade/cortina/BUILD.bazel b/graft/coreth/plugin/evm/upgrade/cortina/BUILD.bazel new file mode 100644 index 000000000000..b6afdb15abf4 --- /dev/null +++ b/graft/coreth/plugin/evm/upgrade/cortina/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "cortina", + srcs = ["params.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/upgrade/cortina", + visibility = ["//visibility:public"], +) diff --git a/graft/coreth/plugin/evm/upgrade/etna/BUILD.bazel b/graft/coreth/plugin/evm/upgrade/etna/BUILD.bazel new file mode 100644 index 000000000000..e66673cc4b6b --- /dev/null +++ b/graft/coreth/plugin/evm/upgrade/etna/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "etna", + srcs = ["params.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/upgrade/etna", + visibility = ["//visibility:public"], + deps = ["//graft/coreth/utils"], +) diff --git a/graft/coreth/plugin/evm/vmerrors/BUILD.bazel b/graft/coreth/plugin/evm/vmerrors/BUILD.bazel new file mode 100644 index 000000000000..02c934381a25 --- /dev/null +++ b/graft/coreth/plugin/evm/vmerrors/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "vmerrors", + srcs = ["errors.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/vmerrors", + visibility = ["//visibility:public"], +) diff --git a/graft/coreth/plugin/evm/vmsync/BUILD.bazel b/graft/coreth/plugin/evm/vmsync/BUILD.bazel new file mode 100644 index 000000000000..1ffc95ffd741 --- /dev/null +++ b/graft/coreth/plugin/evm/vmsync/BUILD.bazel @@ -0,0 +1,49 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "vmsync", + srcs = [ + "client.go", + "registry.go", + "server.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/vmsync", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//database/versiondb", + "//graft/coreth/core", + "//graft/coreth/core/state/snapshot", + "//graft/coreth/eth", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync", + "//graft/coreth/sync/blocksync", + "//graft/coreth/sync/client", + "//graft/coreth/sync/statesync", + "//ids", + "//snow/engine/snowman/block", + "//vms/components/chain", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + "@org_golang_x_sync//errgroup", + ], +) + +go_test( + name = "vmsync_test", + srcs = [ + "doubles_test.go", + "registry_test.go", + ], + embed = [":vmsync"], + deps = [ + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync", + "//graft/coreth/utils/utilstest", + "@com_github_ava_labs_libevm//common", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/evm/vmtest/BUILD.bazel b/graft/coreth/plugin/evm/vmtest/BUILD.bazel new file mode 100644 index 000000000000..e871adf9a2d4 --- /dev/null +++ b/graft/coreth/plugin/evm/vmtest/BUILD.bazel @@ -0,0 +1,56 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "vmtest", + srcs = [ + "genesis.go", + "test_syncervm.go", + "test_vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/evm/vmtest", + visibility = ["//visibility:public"], + deps = [ + "//api/metrics", + "//chains/atomic", + "//database", + "//database/memdb", + "//database/prefixdb", + "//graft/coreth/consensus/dummy", + "//graft/coreth/constants", + "//graft/coreth/core", + "//graft/coreth/core/coretest", + "//graft/coreth/params", + "//graft/coreth/params/paramstest", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/extension", + "//graft/coreth/plugin/evm/upgrade/ap3", + "//graft/coreth/plugin/evm/vmsync", + "//graft/coreth/sync/client", + "//graft/coreth/sync/statesync/statesynctest", + "//graft/coreth/utils/utilstest", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/snowtest", + "//upgrade", + "//upgrade/upgradetest", + "//utils", + "//utils/crypto/secp256k1", + "//utils/set", + "//vms/components/chain", + "//vms/evm/database", + "//vms/evm/predicate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/plugin/factory/BUILD.bazel b/graft/coreth/plugin/factory/BUILD.bazel new file mode 100644 index 000000000000..06fc22440e83 --- /dev/null +++ b/graft/coreth/plugin/factory/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "factory", + srcs = ["factory.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/plugin/factory", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/plugin/evm", + "//graft/coreth/plugin/evm/atomic/vm", + "//ids", + "//snow/engine/snowman/block", + "//utils/logging", + "//vms", + ], +) diff --git a/graft/coreth/precompile/contract/BUILD.bazel b/graft/coreth/precompile/contract/BUILD.bazel new file mode 100644 index 000000000000..551244e60d92 --- /dev/null +++ b/graft/coreth/precompile/contract/BUILD.bazel @@ -0,0 +1,37 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "contract", + srcs = [ + "contract.go", + "interfaces.go", + "mocks.go", + "utils.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/precompile/contract", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/accounts/abi", + "//graft/coreth/precompile/precompileconfig", + "//snow", + "//utils/set", + "//vms/evm/predicate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//libevm/stateconf", + "@com_github_holiman_uint256//:uint256", + "@org_uber_go_mock//gomock", + ], +) + +go_test( + name = "contract_test", + srcs = [ + "mocks_generate_test.go", + "utils_test.go", + ], + embed = [":contract"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/graft/coreth/precompile/contracts/warp/BUILD.bazel b/graft/coreth/precompile/contracts/warp/BUILD.bazel new file mode 100644 index 000000000000..7ec07435baa2 --- /dev/null +++ b/graft/coreth/precompile/contracts/warp/BUILD.bazel @@ -0,0 +1,67 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "warp", + srcs = [ + "config.go", + "contract.go", + "contract_warp_handler.go", + "module.go", + ], + embedsrcs = ["contract.abi"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/precompile/contracts/warp", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/accounts/abi", + "//graft/coreth/precompile/contract", + "//graft/coreth/precompile/modules", + "//graft/coreth/precompile/precompileconfig", + "//utils/constants", + "//vms/evm/predicate", + "//vms/platformvm/warp", + "//vms/platformvm/warp/payload", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_ava_labs_libevm//log", + ], +) + +go_test( + name = "warp_test", + srcs = [ + "config_test.go", + "contract_test.go", + "predicate_test.go", + ], + embed = [":warp"], + deps = [ + "//graft/coreth/params/extras", + "//graft/coreth/params/extras/extrastest", + "//graft/coreth/precompile/contract", + "//graft/coreth/precompile/precompileconfig", + "//graft/coreth/precompile/precompiletest", + "//graft/coreth/utils", + "//ids", + "//snow", + "//snow/engine/snowman/block", + "//snow/snowtest", + "//snow/validators", + "//snow/validators/validatorstest", + "//upgrade/upgradetest", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/math", + "//utils/set", + "//vms/evm/predicate", + "//vms/platformvm/warp", + "//vms/platformvm/warp/payload", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/vm", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/graft/coreth/precompile/modules/BUILD.bazel b/graft/coreth/precompile/modules/BUILD.bazel new file mode 100644 index 000000000000..2ef8b08c1a1e --- /dev/null +++ b/graft/coreth/precompile/modules/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "modules", + srcs = [ + "module.go", + "registerer.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/precompile/modules", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/constants", + "//graft/coreth/precompile/contract", + "//graft/coreth/utils", + "@com_github_ava_labs_libevm//common", + ], +) + +go_test( + name = "modules_test", + srcs = ["registerer_test.go"], + embed = [":modules"], + deps = [ + "//graft/coreth/constants", + "@com_github_ava_labs_libevm//common", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/precompile/precompileconfig/BUILD.bazel b/graft/coreth/precompile/precompileconfig/BUILD.bazel new file mode 100644 index 000000000000..b88d30293b95 --- /dev/null +++ b/graft/coreth/precompile/precompileconfig/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "precompileconfig", + srcs = [ + "config.go", + "mocks.go", + "upgradeable.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/precompile/precompileconfig", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/utils", + "//snow", + "//snow/engine/snowman/block", + "//vms/evm/predicate", + "//vms/platformvm/warp", + "@com_github_ava_labs_libevm//common", + "@org_uber_go_mock//gomock", + ], +) + +go_test( + name = "precompileconfig_test", + srcs = ["mocks_generate_test.go"], + embed = [":precompileconfig"], +) diff --git a/graft/coreth/precompile/precompiletest/BUILD.bazel b/graft/coreth/precompile/precompiletest/BUILD.bazel new file mode 100644 index 000000000000..7e52fac0d51d --- /dev/null +++ b/graft/coreth/precompile/precompiletest/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "precompiletest", + srcs = [ + "test_config.go", + "test_precompile.go", + "test_predicate.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/precompile/precompiletest", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core/extstate", + "//graft/coreth/params/extras", + "//graft/coreth/precompile/contract", + "//graft/coreth/precompile/modules", + "//graft/coreth/precompile/precompileconfig", + "//snow/snowtest", + "//vms/evm/predicate", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/graft/coreth/precompile/registry/BUILD.bazel b/graft/coreth/precompile/registry/BUILD.bazel new file mode 100644 index 000000000000..cc7c439515ea --- /dev/null +++ b/graft/coreth/precompile/registry/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "registry", + srcs = ["registry.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/precompile/registry", + visibility = ["//visibility:public"], + deps = ["//graft/coreth/precompile/contracts/warp"], +) diff --git a/graft/coreth/rpc/BUILD.bazel b/graft/coreth/rpc/BUILD.bazel new file mode 100644 index 000000000000..e25032b8b4bf --- /dev/null +++ b/graft/coreth/rpc/BUILD.bazel @@ -0,0 +1,60 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "rpc", + srcs = [ + "client.go", + "client_opt.go", + "context_headers.go", + "doc.go", + "errors.go", + "handler.go", + "http.go", + "inproc.go", + "json.go", + "metrics.go", + "server.go", + "service.go", + "subscription.go", + "types.go", + "websocket.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/rpc", + visibility = ["//visibility:public"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//rpc", + "@com_github_deckarep_golang_set_v2//:golang-set", + "@com_github_gorilla_websocket//:websocket", + "@org_golang_x_time//rate", + ], +) + +go_test( + name = "rpc_test", + srcs = [ + "client_opt_test.go", + "client_test.go", + "http_test.go", + "main_test.go", + "server_test.go", + "subscription_test.go", + "testservice_test.go", + "types_test.go", + "websocket_test.go", + ], + data = glob(["testdata/**"]), + embed = [":rpc"], + deps = [ + "//graft/coreth/plugin/evm/customtypes", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/math", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//log", + "@com_github_davecgh_go_spew//spew", + "@com_github_gorilla_websocket//:websocket", + ], +) diff --git a/graft/coreth/sync/BUILD.bazel b/graft/coreth/sync/BUILD.bazel new file mode 100644 index 000000000000..ec546e277b41 --- /dev/null +++ b/graft/coreth/sync/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "sync", + srcs = ["types.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync", + visibility = ["//visibility:public"], + deps = [ + "//database/versiondb", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync/client", + "//snow/engine/snowman/block", + "@com_github_ava_labs_libevm//core/types", + ], +) diff --git a/graft/coreth/sync/blocksync/BUILD.bazel b/graft/coreth/sync/blocksync/BUILD.bazel new file mode 100644 index 000000000000..a548ea51b451 --- /dev/null +++ b/graft/coreth/sync/blocksync/BUILD.bazel @@ -0,0 +1,39 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "blocksync", + srcs = ["syncer.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/blocksync", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/sync", + "//graft/coreth/sync/client", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + ], +) + +go_test( + name = "blocksync_test", + srcs = ["syncer_test.go"], + embed = [":blocksync"], + deps = [ + "//graft/coreth/consensus/dummy", + "//graft/coreth/core", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync/client", + "//graft/coreth/sync/handlers", + "//graft/coreth/sync/handlers/stats", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//params", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/sync/client/BUILD.bazel b/graft/coreth/sync/client/BUILD.bazel new file mode 100644 index 000000000000..c869f90cee71 --- /dev/null +++ b/graft/coreth/sync/client/BUILD.bazel @@ -0,0 +1,58 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "client", + srcs = [ + "client.go", + "leaf_syncer.go", + "test_client.go", + "test_network.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/client", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//graft/coreth/network", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync/client/stats", + "//graft/coreth/sync/handlers", + "//graft/coreth/utils", + "//ids", + "//version", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@org_golang_x_sync//errgroup", + ], +) + +go_test( + name = "client_test", + srcs = ["client_test.go"], + embed = [":client"], + deps = [ + "//graft/coreth/consensus/dummy", + "//graft/coreth/core", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync/client/stats", + "//graft/coreth/sync/handlers", + "//graft/coreth/sync/handlers/stats", + "//graft/coreth/sync/statesync/statesynctest", + "//ids", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//triedb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/sync/client/stats/BUILD.bazel b/graft/coreth/sync/client/stats/BUILD.bazel new file mode 100644 index 000000000000..84d7bba70692 --- /dev/null +++ b/graft/coreth/sync/client/stats/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "stats", + srcs = ["stats.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/client/stats", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/plugin/evm/message", + "@com_github_ava_labs_libevm//metrics", + ], +) diff --git a/graft/coreth/sync/handlers/BUILD.bazel b/graft/coreth/sync/handlers/BUILD.bazel new file mode 100644 index 000000000000..8a1b5dcdba18 --- /dev/null +++ b/graft/coreth/sync/handlers/BUILD.bazel @@ -0,0 +1,66 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "handlers", + srcs = [ + "block_request.go", + "code_request.go", + "handler.go", + "leafs_request.go", + "test_providers.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/handlers", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//graft/coreth/core/state/snapshot", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync/handlers/stats", + "//graft/coreth/sync/syncutils", + "//graft/coreth/utils", + "//ids", + "//utils/units", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//ethdb/memorydb", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + ], +) + +go_test( + name = "handlers_test", + srcs = [ + "block_request_test.go", + "code_request_test.go", + "leafs_request_test.go", + ], + embed = [":handlers"], + deps = [ + "//graft/coreth/consensus/dummy", + "//graft/coreth/core", + "//graft/coreth/core/state/snapshot", + "//graft/coreth/params", + "//graft/coreth/plugin/evm/customtypes", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync/handlers/stats", + "//graft/coreth/sync/handlers/stats/statstest", + "//graft/coreth/sync/statesync/statesynctest", + "//ids", + "//utils/units", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//ethdb/memorydb", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/sync/handlers/stats/BUILD.bazel b/graft/coreth/sync/handlers/stats/BUILD.bazel new file mode 100644 index 000000000000..30617e0fd5aa --- /dev/null +++ b/graft/coreth/sync/handlers/stats/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "stats", + srcs = ["stats.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/handlers/stats", + visibility = ["//visibility:public"], + deps = ["@com_github_ava_labs_libevm//metrics"], +) diff --git a/graft/coreth/sync/handlers/stats/statstest/BUILD.bazel b/graft/coreth/sync/handlers/stats/statstest/BUILD.bazel new file mode 100644 index 000000000000..2144c77de828 --- /dev/null +++ b/graft/coreth/sync/handlers/stats/statstest/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "statstest", + srcs = ["test_stats.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/handlers/stats/statstest", + visibility = ["//visibility:public"], + deps = ["//graft/coreth/sync/handlers/stats"], +) diff --git a/graft/coreth/sync/statesync/BUILD.bazel b/graft/coreth/sync/statesync/BUILD.bazel new file mode 100644 index 000000000000..3e42e641fb4c --- /dev/null +++ b/graft/coreth/sync/statesync/BUILD.bazel @@ -0,0 +1,76 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "statesync", + srcs = [ + "code_queue.go", + "code_syncer.go", + "state_syncer.go", + "sync_helpers.go", + "trie_queue.go", + "trie_segments.go", + "trie_sync_stats.go", + "trie_sync_tasks.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/statesync", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core/state/snapshot", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync", + "//graft/coreth/sync/client", + "//graft/coreth/sync/syncutils", + "//graft/coreth/utils", + "//utils/math", + "//utils/timer", + "//utils/wrappers", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//libevm/options", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@org_golang_x_sync//errgroup", + ], +) + +go_test( + name = "statesync_test", + srcs = [ + "code_queue_test.go", + "code_syncer_test.go", + "sync_test.go", + "trie_sync_stats_test.go", + ], + embed = [":statesync"], + deps = [ + "//graft/coreth/core/state/snapshot", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/plugin/evm/message", + "//graft/coreth/sync/client", + "//graft/coreth/sync/handlers", + "//graft/coreth/sync/handlers/stats", + "//graft/coreth/sync/statesync/statesynctest", + "//utils", + "//utils/set", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//ethdb/memorydb", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//triedb", + "@com_github_google_go_cmp//cmp", + "@com_github_stretchr_testify//require", + "@org_golang_x_sync//errgroup", + "@org_uber_go_goleak//:goleak", + ], +) diff --git a/graft/coreth/sync/statesync/statesynctest/BUILD.bazel b/graft/coreth/sync/statesync/statesynctest/BUILD.bazel new file mode 100644 index 000000000000..0a3ce2dea341 --- /dev/null +++ b/graft/coreth/sync/statesync/statesynctest/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "statesynctest", + srcs = [ + "test_sync.go", + "test_trie.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/statesync/statesynctest", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/utils/utilstest", + "//utils/wrappers", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/sync/syncutils/BUILD.bazel b/graft/coreth/sync/syncutils/BUILD.bazel new file mode 100644 index 000000000000..0435a53e709a --- /dev/null +++ b/graft/coreth/sync/syncutils/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "syncutils", + srcs = ["iterators.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/sync/syncutils", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core/state/snapshot", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + ], +) diff --git a/graft/coreth/tests/BUILD.bazel b/graft/coreth/tests/BUILD.bazel new file mode 100644 index 000000000000..dfe1bcf2c275 --- /dev/null +++ b/graft/coreth/tests/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "tests", + srcs = [ + "init.go", + "rlp_test_util.go", + "state_test_util.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/tests", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/core/extstate", + "//graft/coreth/core/state/snapshot", + "//graft/coreth/params", + "//graft/coreth/params/extras", + "//graft/coreth/plugin/evm/customrawdb", + "//graft/coreth/triedb/firewood", + "//graft/coreth/triedb/hashdb", + "//graft/coreth/triedb/pathdb", + "//graft/coreth/utils", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/state", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//libevm", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//triedb", + "@com_github_holiman_uint256//:uint256", + ], +) diff --git a/graft/coreth/tests/utils/BUILD.bazel b/graft/coreth/tests/utils/BUILD.bazel new file mode 100644 index 000000000000..745081923e43 --- /dev/null +++ b/graft/coreth/tests/utils/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "utils", + srcs = [ + "command.go", + "constants.go", + "proposervm.go", + "subnet.go", + "tmpnet.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/tests/utils", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//config", + "//graft/coreth/accounts/abi/bind", + "//graft/coreth/ethclient", + "//graft/coreth/plugin/evm/upgrade/ap1", + "//tests/fixture/tmpnet", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//params", + "@com_github_go_cmd_cmd//:cmd", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/tests/warp/BUILD.bazel b/graft/coreth/tests/warp/BUILD.bazel new file mode 100644 index 000000000000..7c98b820e44e --- /dev/null +++ b/graft/coreth/tests/warp/BUILD.bazel @@ -0,0 +1,34 @@ +load("@rules_go//go:def.bzl", "go_test") + +go_test( + name = "warp_test", + srcs = ["warp_test.go"], + deps = [ + "//api/info", + "//graft/coreth/accounts/abi/bind", + "//graft/coreth/cmd/simulator/key", + "//graft/coreth/cmd/simulator/load", + "//graft/coreth/cmd/simulator/metrics", + "//graft/coreth/cmd/simulator/txs", + "//graft/coreth/ethclient", + "//graft/coreth/params", + "//graft/coreth/precompile/contracts/warp", + "//graft/coreth/tests/utils", + "//graft/coreth/warp", + "//ids", + "//snow/validators", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//utils/constants", + "//vms/evm/predicate", + "//vms/platformvm", + "//vms/platformvm/api", + "//vms/platformvm/warp", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/triedb/firewood/BUILD.bazel b/graft/coreth/triedb/firewood/BUILD.bazel new file mode 100644 index 000000000000..e5ceab92474d --- /dev/null +++ b/graft/coreth/triedb/firewood/BUILD.bazel @@ -0,0 +1,29 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "firewood", + srcs = [ + "account_trie.go", + "database.go", + "storage_trie.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/triedb/firewood", + visibility = ["//visibility:public"], + deps = [ + "//firewood/ffi", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//libevm/stateconf", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//trie/triestate", + "@com_github_ava_labs_libevm//triedb", + "@com_github_ava_labs_libevm//triedb/database", + ], +) diff --git a/graft/coreth/triedb/hashdb/BUILD.bazel b/graft/coreth/triedb/hashdb/BUILD.bazel new file mode 100644 index 000000000000..d4e12bc7decf --- /dev/null +++ b/graft/coreth/triedb/hashdb/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "hashdb", + srcs = ["database.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/triedb/hashdb", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/utils", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//libevm/stateconf", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//trie/triestate", + "@com_github_ava_labs_libevm//triedb", + "@com_github_ava_labs_libevm//triedb/database", + "@com_github_ava_labs_libevm//triedb/hashdb", + ], +) diff --git a/graft/coreth/triedb/pathdb/BUILD.bazel b/graft/coreth/triedb/pathdb/BUILD.bazel new file mode 100644 index 000000000000..88cdc751de9b --- /dev/null +++ b/graft/coreth/triedb/pathdb/BUILD.bazel @@ -0,0 +1,62 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "pathdb", + srcs = [ + "database.go", + "difflayer.go", + "disklayer.go", + "errors.go", + "history.go", + "journal.go", + "layertree.go", + "metrics.go", + "nodebuffer.go", + "testutils.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/triedb/pathdb", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/params", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//libevm/stateconf", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//trie/triestate", + "@com_github_ava_labs_libevm//triedb", + "@com_github_ava_labs_libevm//triedb/database", + "@com_github_ava_labs_libevm//triedb/pathdb", + "@com_github_victoriametrics_fastcache//:fastcache", + "@org_golang_x_crypto//sha3", + "@org_golang_x_exp//slices", + ], +) + +go_test( + name = "pathdb_test", + srcs = [ + "database_test.go", + "difflayer_test.go", + "history_test.go", + ], + embed = [":pathdb"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//rlp", + "@com_github_ava_labs_libevm//trie/testutil", + "@com_github_ava_labs_libevm//trie/trienode", + "@com_github_ava_labs_libevm//trie/triestate", + "@com_github_holiman_uint256//:uint256", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/utils/BUILD.bazel b/graft/coreth/utils/BUILD.bazel new file mode 100644 index 000000000000..47e0abccf497 --- /dev/null +++ b/graft/coreth/utils/BUILD.bazel @@ -0,0 +1,34 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "utils", + srcs = [ + "address_range.go", + "bounded_workers.go", + "bytes.go", + "denomination.go", + "metered_cache.go", + "numbers.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/utils", + visibility = ["//visibility:public"], + deps = [ + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//metrics", + "@com_github_victoriametrics_fastcache//:fastcache", + ], +) + +go_test( + name = "utils_test", + srcs = [ + "bytes_test.go", + "numbers_test.go", + ], + embed = [":utils"], + deps = [ + "//utils", + "@com_github_ava_labs_libevm//common", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/utils/rand/BUILD.bazel b/graft/coreth/utils/rand/BUILD.bazel new file mode 100644 index 000000000000..96909cafc019 --- /dev/null +++ b/graft/coreth/utils/rand/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "rand", + srcs = ["rand.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/utils/rand", + visibility = ["//visibility:public"], +) diff --git a/graft/coreth/utils/rpc/BUILD.bazel b/graft/coreth/utils/rpc/BUILD.bazel new file mode 100644 index 000000000000..fe353dcbfb60 --- /dev/null +++ b/graft/coreth/utils/rpc/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "rpc", + srcs = ["handler.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/utils/rpc", + visibility = ["//visibility:public"], + deps = [ + "//utils/json", + "@com_github_gorilla_rpc//v2:rpc", + ], +) diff --git a/graft/coreth/utils/utilstest/BUILD.bazel b/graft/coreth/utils/utilstest/BUILD.bazel new file mode 100644 index 000000000000..18964272189d --- /dev/null +++ b/graft/coreth/utils/utilstest/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "utilstest", + srcs = [ + "context.go", + "key.go", + "pointer.go", + "snow.go", + "timeout.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/utils/utilstest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/snowtest", + "//snow/validators", + "//snow/validators/validatorstest", + "//utils/constants", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//crypto", + "@com_github_stretchr_testify//require", + ], +) diff --git a/graft/coreth/warp/BUILD.bazel b/graft/coreth/warp/BUILD.bazel new file mode 100644 index 000000000000..90dbc0eee1df --- /dev/null +++ b/graft/coreth/warp/BUILD.bazel @@ -0,0 +1,59 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "warp", + srcs = [ + "backend.go", + "client.go", + "service.go", + "verifier_backend.go", + "verifier_stats.go", + ], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/warp", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//database", + "//graft/coreth/precompile/contracts/warp", + "//graft/coreth/rpc", + "//ids", + "//network/p2p/acp118", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//vms/platformvm/warp", + "//vms/platformvm/warp/payload", + "@com_github_ava_labs_libevm//common/hexutil", + "@com_github_ava_labs_libevm//log", + "@com_github_ava_labs_libevm//metrics", + ], +) + +go_test( + name = "warp_test", + srcs = [ + "backend_test.go", + "verifier_backend_test.go", + ], + embed = [":warp"], + deps = [ + "//cache", + "//cache/lru", + "//database", + "//database/memdb", + "//graft/coreth/warp/warptest", + "//ids", + "//network/p2p/acp118", + "//proto/pb/sdk", + "//snow/engine/common", + "//snow/snowtest", + "//utils", + "//utils/crypto/bls/signer/localsigner", + "//vms/evm/metrics/metricstest", + "//vms/platformvm/warp", + "//vms/platformvm/warp/payload", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + ], +) diff --git a/graft/coreth/warp/warptest/BUILD.bazel b/graft/coreth/warp/warptest/BUILD.bazel new file mode 100644 index 000000000000..e55f86ebc75a --- /dev/null +++ b/graft/coreth/warp/warptest/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "warptest", + srcs = ["block_client.go"], + importpath = "github.com/ava-labs/avalanchego/graft/coreth/warp/warptest", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmantest", + "//snow/snowtest", + ], +) diff --git a/ids/BUILD.bazel b/ids/BUILD.bazel new file mode 100644 index 000000000000..21836bbf5231 --- /dev/null +++ b/ids/BUILD.bazel @@ -0,0 +1,41 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "ids", + srcs = [ + "aliases.go", + "bits.go", + "id.go", + "node_id.go", + "request_id.go", + "short.go", + "test_generator.go", + ], + importpath = "github.com/ava-labs/avalanchego/ids", + visibility = ["//visibility:public"], + deps = [ + "//staking", + "//utils", + "//utils/cb58", + "//utils/hashing", + "//utils/wrappers", + ], +) + +go_test( + name = "ids_test", + srcs = [ + "aliases_test.go", + "bits_test.go", + "id_test.go", + "node_id_test.go", + ], + embed = [":ids"], + deps = [ + "//ids/idstest", + "//utils", + "//utils/cb58", + "//utils/hashing", + "@com_github_stretchr_testify//require", + ], +) diff --git a/ids/galiasreader/BUILD.bazel b/ids/galiasreader/BUILD.bazel new file mode 100644 index 000000000000..f22a25281523 --- /dev/null +++ b/ids/galiasreader/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "galiasreader", + srcs = [ + "alias_reader_client.go", + "alias_reader_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/ids/galiasreader", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//proto/pb/aliasreader", + ], +) + +go_test( + name = "galiasreader_test", + srcs = ["alias_reader_test.go"], + embed = [":galiasreader"], + deps = [ + "//ids", + "//ids/idstest", + "//proto/pb/aliasreader", + "//vms/rpcchainvm/grpcutils", + "@com_github_stretchr_testify//require", + ], +) diff --git a/ids/idstest/BUILD.bazel b/ids/idstest/BUILD.bazel new file mode 100644 index 000000000000..dc6c2b97e1e0 --- /dev/null +++ b/ids/idstest/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "idstest", + srcs = ["aliases.go"], + importpath = "github.com/ava-labs/avalanchego/ids/idstest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/indexer/BUILD.bazel b/indexer/BUILD.bazel new file mode 100644 index 000000000000..874352d0df93 --- /dev/null +++ b/indexer/BUILD.bazel @@ -0,0 +1,67 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "indexer", + srcs = [ + "client.go", + "codec.go", + "container.go", + "index.go", + "indexer.go", + "service.go", + ], + importpath = "github.com/ava-labs/avalanchego/indexer", + visibility = ["//visibility:public"], + deps = [ + "//api/server", + "//chains", + "//codec", + "//codec/linearcodec", + "//database", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//snow", + "//snow/engine/avalanche/vertex", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils/constants", + "//utils/formatting", + "//utils/json", + "//utils/logging", + "//utils/rpc", + "//utils/timer/mockable", + "//utils/wrappers", + "@com_github_gorilla_rpc//v2:rpc", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "indexer_test", + srcs = [ + "client_test.go", + "index_test.go", + "indexer_test.go", + ], + embed = [":indexer"], + deps = [ + "//api/server", + "//database/memdb", + "//database/versiondb", + "//ids", + "//snow", + "//snow/engine/avalanche/vertex/vertexmock", + "//snow/engine/snowman/block/blockmock", + "//snow/snowtest", + "//utils", + "//utils/formatting", + "//utils/json", + "//utils/logging", + "//utils/rpc", + "//utils/set", + "//utils/timer/mockable", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/indexer/examples/p-chain/BUILD.bazel b/indexer/examples/p-chain/BUILD.bazel new file mode 100644 index 000000000000..0e1bb1df0cbc --- /dev/null +++ b/indexer/examples/p-chain/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "p-chain_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/indexer/examples/p-chain", + visibility = ["//visibility:private"], + deps = [ + "//indexer", + "//utils/constants", + "//vms/platformvm/block", + "//vms/proposervm/block", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "p-chain", + embed = [":p-chain_lib"], + visibility = ["//visibility:public"], +) diff --git a/indexer/examples/x-chain-blocks/BUILD.bazel b/indexer/examples/x-chain-blocks/BUILD.bazel new file mode 100644 index 000000000000..4b6499e3be85 --- /dev/null +++ b/indexer/examples/x-chain-blocks/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "x-chain-blocks_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/indexer/examples/x-chain-blocks", + visibility = ["//visibility:private"], + deps = [ + "//ids", + "//indexer", + "//vms/proposervm/block", + "//wallet/chain/x/builder", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "x-chain-blocks", + embed = [":x-chain-blocks_lib"], + visibility = ["//visibility:public"], +) diff --git a/main/BUILD.bazel b/main/BUILD.bazel new file mode 100644 index 000000000000..ffab5909814b --- /dev/null +++ b/main/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "main_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/main", + visibility = ["//visibility:private"], + deps = [ + "//app", + "//config", + "//graft/coreth/plugin/evm", + "//version", + "@com_github_spf13_pflag//:pflag", + "@org_golang_x_term//:term", + ], +) + +go_binary( + name = "avalanchego", + embed = [":main_lib"], + visibility = ["//visibility:public"], + x_defs = { + "github.com/ava-labs/avalanchego/version.GitCommit": "{STABLE_GIT_COMMIT}", + }, +) diff --git a/message/BUILD.bazel b/message/BUILD.bazel new file mode 100644 index 000000000000..ee88f13b928d --- /dev/null +++ b/message/BUILD.bazel @@ -0,0 +1,50 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "message", + srcs = [ + "creator.go", + "fields.go", + "inbound_msg_builder.go", + "internal_msg_builder.go", + "messages.go", + "ops.go", + "outbound_msg_builder.go", + ], + importpath = "github.com/ava-labs/avalanchego/message", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//proto/pb/p2p", + "//utils/compression", + "//utils/constants", + "//utils/ips", + "//utils/set", + "//utils/timer/mockable", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + ], +) + +go_test( + name = "message_test", + srcs = [ + "inbound_msg_builder_test.go", + "messages_benchmark_test.go", + "messages_test.go", + "mocks_generate_test.go", + "outbound_msg_builder_test.go", + ], + embed = [":message"], + deps = [ + "//ids", + "//proto/pb/p2p", + "//staking", + "//utils/compression", + "//utils/timer/mockable", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + ], +) diff --git a/message/messagemock/BUILD.bazel b/message/messagemock/BUILD.bazel new file mode 100644 index 000000000000..5a688c9b3c26 --- /dev/null +++ b/message/messagemock/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "messagemock", + srcs = [ + "outbound_message.go", + "outbound_message_builder.go", + ], + importpath = "github.com/ava-labs/avalanchego/message/messagemock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//proto/pb/p2p", + "//utils/ips", + "@org_uber_go_mock//gomock", + ], +) diff --git a/nat/BUILD.bazel b/nat/BUILD.bazel new file mode 100644 index 000000000000..231b98f98319 --- /dev/null +++ b/nat/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "nat", + srcs = [ + "nat.go", + "no_router.go", + "pmp.go", + "upnp.go", + ], + importpath = "github.com/ava-labs/avalanchego/nat", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/ips", + "//utils/logging", + "@com_github_huin_goupnp//:goupnp", + "@com_github_huin_goupnp//dcps/internetgateway1", + "@com_github_huin_goupnp//dcps/internetgateway2", + "@com_github_jackpal_gateway//:gateway", + "@com_github_jackpal_go_nat_pmp//:go-nat-pmp", + "@org_uber_go_zap//:zap", + ], +) diff --git a/network/BUILD.bazel b/network/BUILD.bazel new file mode 100644 index 000000000000..1f08ac14f9ef --- /dev/null +++ b/network/BUILD.bazel @@ -0,0 +1,102 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "network", + srcs = [ + "config.go", + "ip_tracker.go", + "metrics.go", + "network.go", + "no_ingress_conn_alert.go", + "test_network.go", + "tracked_ip.go", + ], + importpath = "github.com/ava-labs/avalanchego/network", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//genesis", + "//ids", + "//message", + "//network/dialer", + "//network/peer", + "//network/throttling", + "//snow/engine/common", + "//snow/networking/router", + "//snow/networking/sender", + "//snow/networking/tracker", + "//snow/uptime", + "//snow/validators", + "//staking", + "//subnets", + "//upgrade", + "//utils", + "//utils/bloom", + "//utils/compression", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/ips", + "//utils/logging", + "//utils/math", + "//utils/math/meter", + "//utils/resource", + "//utils/sampler", + "//utils/set", + "//utils/units", + "//utils/wrappers", + "//version", + "@com_github_pires_go_proxyproto//:go-proxyproto", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "network_test", + srcs = [ + "conn_test.go", + "dialer_test.go", + "example_test.go", + "handler_test.go", + "ip_tracker_test.go", + "listener_test.go", + "network_test.go", + "no_ingress_conn_alert_test.go", + "tracked_ip_test.go", + ], + embed = [":network"], + deps = [ + "//genesis", + "//ids", + "//message", + "//network/dialer", + "//network/peer", + "//network/throttling", + "//snow/engine/common", + "//snow/networking/router", + "//snow/networking/tracker", + "//snow/uptime", + "//snow/validators", + "//staking", + "//subnets", + "//upgrade", + "//utils", + "//utils/bloom", + "//utils/constants", + "//utils/crypto/bls/signer/localsigner", + "//utils/ips", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/set", + "//utils/timer/mockable", + "//utils/units", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/testutil", + "@com_github_stretchr_testify//require", + "@org_golang_x_sync//errgroup", + "@org_uber_go_zap//:zap", + ], +) diff --git a/network/dialer/BUILD.bazel b/network/dialer/BUILD.bazel new file mode 100644 index 000000000000..4be935bd9bdd --- /dev/null +++ b/network/dialer/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "dialer", + srcs = ["dialer.go"], + importpath = "github.com/ava-labs/avalanchego/network/dialer", + visibility = ["//visibility:public"], + deps = [ + "//network/throttling", + "//utils/logging", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "dialer_test", + srcs = ["dialer_test.go"], + embed = [":dialer"], + deps = [ + "//utils/logging", + "@com_github_stretchr_testify//require", + "@org_golang_x_sync//errgroup", + ], +) diff --git a/network/p2p/BUILD.bazel b/network/p2p/BUILD.bazel new file mode 100644 index 000000000000..7d39bfe1cc06 --- /dev/null +++ b/network/p2p/BUILD.bazel @@ -0,0 +1,63 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "p2p", + srcs = [ + "client.go", + "error.go", + "handler.go", + "network.go", + "node_sampler.go", + "peer_tracker.go", + "router.go", + "throttler.go", + "throttler_handler.go", + "validators.go", + ], + importpath = "github.com/ava-labs/avalanchego/network/p2p", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//snow/engine/common", + "//snow/validators", + "//utils", + "//utils/heap", + "//utils/logging", + "//utils/math", + "//utils/sampler", + "//utils/set", + "//utils/timer/mockable", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "p2p_test", + srcs = [ + "handler_test.go", + "network_test.go", + "peer_tracker_test.go", + "throttler_handler_test.go", + "throttler_test.go", + "validators_test.go", + ], + embed = [":p2p"], + deps = [ + "//ids", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/validators", + "//snow/validators/validatorsmock", + "//snow/validators/validatorstest", + "//utils/logging", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/testutil", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/network/p2p/acp118/BUILD.bazel b/network/p2p/acp118/BUILD.bazel new file mode 100644 index 000000000000..d25967d0d7d0 --- /dev/null +++ b/network/p2p/acp118/BUILD.bazel @@ -0,0 +1,51 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "acp118", + srcs = [ + "aggregator.go", + "handler.go", + ], + importpath = "github.com/ava-labs/avalanchego/network/p2p/acp118", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//ids", + "//network/p2p", + "//proto/pb/sdk", + "//snow/engine/common", + "//snow/validators", + "//utils/crypto/bls", + "//utils/logging", + "//utils/set", + "//vms/platformvm/warp", + "@org_golang_google_protobuf//proto", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "acp118_test", + srcs = [ + "aggregator_test.go", + "handler_test.go", + ], + embed = [":acp118"], + deps = [ + "//cache", + "//cache/lru", + "//ids", + "//network/p2p", + "//network/p2p/p2ptest", + "//proto/pb/sdk", + "//snow/engine/common", + "//snow/validators", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/logging", + "//utils/set", + "//vms/platformvm/warp", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + ], +) diff --git a/network/p2p/gossip/BUILD.bazel b/network/p2p/gossip/BUILD.bazel new file mode 100644 index 000000000000..dac07c2beda6 --- /dev/null +++ b/network/p2p/gossip/BUILD.bazel @@ -0,0 +1,55 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "gossip", + srcs = [ + "bloom.go", + "gossip.go", + "gossipable.go", + "handler.go", + "message.go", + ], + importpath = "github.com/ava-labs/avalanchego/network/p2p/gossip", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//ids", + "//network/p2p", + "//proto/pb/sdk", + "//snow/engine/common", + "//utils/bloom", + "//utils/buffer", + "//utils/logging", + "//utils/set", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "gossip_test", + srcs = [ + "bloom_test.go", + "gossip_test.go", + ], + embed = [":gossip"], + deps = [ + "//ids", + "//network/p2p", + "//proto/pb/sdk", + "//snow/engine/enginetest", + "//snow/validators", + "//snow/validators/validatorstest", + "//utils/bloom", + "//utils/constants", + "//utils/logging", + "//utils/set", + "//utils/units", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/testutil", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + ], +) diff --git a/network/p2p/p2ptest/BUILD.bazel b/network/p2p/p2ptest/BUILD.bazel new file mode 100644 index 000000000000..abcf4a81dd89 --- /dev/null +++ b/network/p2p/p2ptest/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "p2ptest", + srcs = ["client.go"], + importpath = "github.com/ava-labs/avalanchego/network/p2p/p2ptest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//network/p2p", + "//snow/engine/common", + "//snow/engine/enginetest", + "//utils/logging", + "//utils/set", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) + +go_test( + name = "p2ptest_test", + srcs = ["client_test.go"], + embed = [":p2ptest"], + deps = [ + "//ids", + "//network/p2p", + "//snow/engine/common", + "//utils/set", + "@com_github_stretchr_testify//require", + ], +) diff --git a/network/peer/BUILD.bazel b/network/peer/BUILD.bazel new file mode 100644 index 000000000000..3e51d36df798 --- /dev/null +++ b/network/peer/BUILD.bazel @@ -0,0 +1,95 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "peer", + srcs = [ + "config.go", + "info.go", + "ip.go", + "ip_signer.go", + "message_queue.go", + "metrics.go", + "msg_length.go", + "network.go", + "peer.go", + "set.go", + "test_network.go", + "test_peer.go", + "tls_config.go", + "upgrader.go", + ], + importpath = "github.com/ava-labs/avalanchego/network/peer", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//network/throttling", + "//proto/pb/p2p", + "//snow/networking/router", + "//snow/networking/tracker", + "//snow/uptime", + "//snow/validators", + "//staking", + "//upgrade", + "//utils", + "//utils/bloom", + "//utils/buffer", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/hashing", + "//utils/ips", + "//utils/json", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/sampler", + "//utils/set", + "//utils/timer/mockable", + "//utils/wrappers", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "peer_test", + srcs = [ + "example_test.go", + "ip_signer_test.go", + "ip_test.go", + "message_queue_test.go", + "msg_length_test.go", + "peer_test.go", + "set_test.go", + "tls_config_test.go", + "upgrader_test.go", + ], + embed = [":peer"], + embedsrcs = ["8192RSA_test.pem"], + deps = [ + "//ids", + "//message", + "//network/throttling", + "//snow/networking/router", + "//snow/networking/tracker", + "//snow/uptime", + "//snow/validators", + "//staking", + "//upgrade", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_x_crypto//ed25519", + "@org_golang_x_sync//errgroup", + ], +) diff --git a/network/throttling/BUILD.bazel b/network/throttling/BUILD.bazel new file mode 100644 index 000000000000..8bd4fbc4eb33 --- /dev/null +++ b/network/throttling/BUILD.bazel @@ -0,0 +1,68 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "throttling", + srcs = [ + "bandwidth_throttler.go", + "common.go", + "dial_throttler.go", + "inbound_conn_throttler.go", + "inbound_conn_upgrade_throttler.go", + "inbound_msg_buffer_throttler.go", + "inbound_msg_byte_throttler.go", + "inbound_msg_throttler.go", + "inbound_resource_throttler.go", + "no_inbound_msg_throttler.go", + "outbound_msg_throttler.go", + "release_func.go", + ], + importpath = "github.com/ava-labs/avalanchego/network/throttling", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//snow/networking/tracker", + "//snow/validators", + "//utils/constants", + "//utils/linked", + "//utils/logging", + "//utils/metric", + "//utils/set", + "//utils/timer", + "//utils/timer/mockable", + "//utils/wrappers", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_x_time//rate", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "throttling_test", + srcs = [ + "bandwidth_throttler_test.go", + "inbound_conn_throttler_test.go", + "inbound_conn_upgrade_throttler_test.go", + "inbound_msg_buffer_throttler_test.go", + "inbound_msg_byte_throttler_test.go", + "inbound_resource_throttler_test.go", + "outbound_msg_throttler_test.go", + ], + embed = [":throttling"], + deps = [ + "//ids", + "//message", + "//message/messagemock", + "//snow/networking/tracker", + "//snow/networking/tracker/trackermock", + "//snow/validators", + "//utils/constants", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/timer/mockable", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/nix/go/BUILD.bazel b/nix/go/BUILD.bazel new file mode 100644 index 000000000000..7aee75908eee --- /dev/null +++ b/nix/go/BUILD.bazel @@ -0,0 +1,5 @@ +# Make nix files visible to Bazel +exports_files([ + "bazel.nix", + "default.nix", +]) diff --git a/nix/go/bazel.nix b/nix/go/bazel.nix new file mode 100644 index 000000000000..6b7d633227c9 --- /dev/null +++ b/nix/go/bazel.nix @@ -0,0 +1,7 @@ +# Bazel wrapper for Go SDK +# Called by rules_nixpkgs_go to build the Go toolchain +# +# This file re-uses the same Go derivation as nix develop, +# ensuring version consistency between Nix and Bazel environments. +{ pkgs ? import {} }: +import ./default.nix { inherit pkgs; } diff --git a/nix/go/default.nix b/nix/go/default.nix index aa510a23fcc0..e404a05a1341 100644 --- a/nix/go/default.nix +++ b/nix/go/default.nix @@ -53,5 +53,7 @@ pkgs.stdenv.mkDerivation { tar xzf $src -C $out --strip-components=1 --no-same-owner --no-same-permissions # Ensure go binary is executable chmod +x $out/bin/go + # ROOT marker required by rules_go/rules_nixpkgs for SDK identification + touch $out/ROOT ''; } diff --git a/node/BUILD.bazel b/node/BUILD.bazel new file mode 100644 index 000000000000..e032fec10d91 --- /dev/null +++ b/node/BUILD.bazel @@ -0,0 +1,96 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "node", + srcs = [ + "beacon_manager.go", + "insecure_validator_manager.go", + "node.go", + "overridden_manager.go", + ], + importpath = "github.com/ava-labs/avalanchego/node", + visibility = ["//visibility:public"], + deps = [ + "//api/admin", + "//api/health", + "//api/info", + "//api/metrics", + "//api/server", + "//chains", + "//chains/atomic", + "//config/node", + "//database", + "//database/factory", + "//database/leveldb", + "//database/meterdb", + "//database/pebbledb", + "//database/prefixdb", + "//genesis", + "//graft/coreth/plugin/factory", + "//ids", + "//indexer", + "//message", + "//nat", + "//network", + "//network/dialer", + "//network/peer", + "//network/throttling", + "//snow", + "//snow/networking/benchlist", + "//snow/networking/router", + "//snow/networking/timeout", + "//snow/networking/tracker", + "//snow/uptime", + "//snow/validators", + "//staking", + "//trace", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/bls/signer/rpcsigner", + "//utils/dynamicip", + "//utils/filesystem", + "//utils/hashing", + "//utils/ips", + "//utils/logging", + "//utils/math/meter", + "//utils/metric", + "//utils/perms", + "//utils/profiler", + "//utils/resource", + "//utils/set", + "//version", + "//vms", + "//vms/avm", + "//vms/avm/config", + "//vms/platformvm", + "//vms/platformvm/config", + "//vms/platformvm/signer", + "//vms/registry", + "//vms/rpcchainvm/runtime", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/collectors", + "@com_github_prometheus_client_golang//prometheus/promhttp", + "@org_golang_x_exp//maps", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "node_test", + srcs = [ + "beacon_manager_test.go", + "overridden_manager_test.go", + ], + embed = [":node"], + deps = [ + "//ids", + "//snow/networking/router/routermock", + "//snow/validators", + "//utils/constants", + "//version", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/patch1.txt b/patch1.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/patch2.txt b/patch2.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/patches/BUILD.bazel b/patches/BUILD.bazel new file mode 100644 index 000000000000..2f3cf1688bce --- /dev/null +++ b/patches/BUILD.bazel @@ -0,0 +1,6 @@ +# Patch files for external dependencies +exports_files([ + "libevm_secp256k1.patch", + "blst_build.patch", + "firewood_ffi.patch", +]) diff --git a/patches/blst_build.patch b/patches/blst_build.patch new file mode 100644 index 000000000000..e287031c78a4 --- /dev/null +++ b/patches/blst_build.patch @@ -0,0 +1,111 @@ +diff --git a/BUILD.bazel b/BUILD.bazel +new file mode 100644 +index 0000000..1234567 +--- /dev/null ++++ b/BUILD.bazel +@@ -0,0 +1,59 @@ ++# Custom BUILD file for github.com/supranational/blst ++# Based on prysmaticlabs/prysm's third_party/blst/blst.BUILD ++ ++load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") ++ ++cc_library( ++ name = "blst", ++ srcs = [ ++ "bindings/blst.h", ++ "bindings/blst_aux.h", ++ ], ++ hdrs = [ ++ "bindings/blst.h", ++ "bindings/blst_aux.h", ++ ], ++ deps = [ ++ ":src", ++ ":asm", ++ ], ++ strip_include_prefix = "bindings", ++ visibility = ["//visibility:public"], ++) ++ ++cc_library( ++ name = "asm_hdrs", ++ hdrs = glob([ ++ "build/**/*.s", ++ "build/**/*.S", ++ ], exclude = ["build/assembly.s"]), ++) ++ ++cc_library( ++ name = "asm", ++ srcs = ["build/assembly.S"], ++ copts = [ ++ "-O2", ++ "-D__BLST_PORTABLE__", ++ ] + select({ ++ "@io_bazel_rules_go//go/platform:amd64": [ ++ "-mno-avx", ++ "-D__ADX__", ++ ], ++ "//conditions:default": [], ++ }), ++ deps = [":asm_hdrs"], ++ linkstatic = True, ++) ++ ++cc_library( ++ name = "hdrs", ++ hdrs = glob(["src/*.c", "src/*.h"], exclude = ["src/client_*.c"]), ++ strip_include_prefix = "src", ++) ++ ++cc_library( ++ name = "src", ++ srcs = ["src/server.c"], ++ deps = [":hdrs"], ++) +diff --git a/bindings/go/BUILD.bazel b/bindings/go/BUILD.bazel +new file mode 100644 +index 0000000..abcdef0 +--- /dev/null ++++ b/bindings/go/BUILD.bazel +@@ -0,0 +1,40 @@ ++# Go bindings for blst library ++ ++load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") ++ ++go_library( ++ name = "go", ++ srcs = [ ++ "blst.go", ++ "cgo_server.c", ++ ], ++ cgo = True, ++ copts = [ ++ "-D__BLST_CGO__", ++ "-I../..", ++ "-I../../bindings", ++ "-I../../src", ++ "-O2", ++ "-D__BLST_PORTABLE__", ++ ] + select({ ++ "@io_bazel_rules_go//go/platform:amd64": [ ++ "-mno-avx", ++ "-D__ADX__", ++ ], ++ "//conditions:default": [], ++ }), ++ cdeps = ["//:blst"], ++ importpath = "github.com/supranational/blst/bindings/go", ++ visibility = ["//visibility:public"], ++) ++ ++go_test( ++ name = "go_test", ++ srcs = [ ++ "blst_htoc_test.go", ++ "blst_minpk_test.go", ++ "blst_minsig_test.go", ++ ], ++ embed = [":go"], ++ data = glob(["hash_to_curve/*.json"]), ++) diff --git a/patches/firewood_ffi.patch b/patches/firewood_ffi.patch new file mode 100644 index 000000000000..789bc14bf6bc --- /dev/null +++ b/patches/firewood_ffi.patch @@ -0,0 +1,77 @@ +diff --git a/BUILD.bazel b/BUILD.bazel +new file mode 100644 +index 0000000..1234567 +--- /dev/null ++++ b/BUILD.bazel +@@ -0,0 +1,71 @@ ++load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") ++ ++# Pre-built static library for firewood FFI ++cc_import( ++ name = "firewood_ffi_lib", ++ static_library = select({ ++ "@io_bazel_rules_go//go/platform:darwin_amd64": "libs/x86_64-apple-darwin/libfirewood_ffi.a", ++ "@io_bazel_rules_go//go/platform:darwin_arm64": "libs/aarch64-apple-darwin/libfirewood_ffi.a", ++ "@io_bazel_rules_go//go/platform:linux_amd64": "libs/x86_64-unknown-linux-gnu/libfirewood_ffi.a", ++ "@io_bazel_rules_go//go/platform:linux_arm64": "libs/aarch64-unknown-linux-gnu/libfirewood_ffi.a", ++ "@io_bazel_rules_go//go/platform:android_amd64": "libs/x86_64-unknown-linux-gnu/libfirewood_ffi.a", ++ "@io_bazel_rules_go//go/platform:android_arm64": "libs/aarch64-unknown-linux-gnu/libfirewood_ffi.a", ++ "@io_bazel_rules_go//go/platform:ios_amd64": "libs/x86_64-apple-darwin/libfirewood_ffi.a", ++ "@io_bazel_rules_go//go/platform:ios_arm64": "libs/aarch64-apple-darwin/libfirewood_ffi.a", ++ }), ++ visibility = ["//visibility:public"], ++) ++ ++# Wrapper cc_library to use with cdeps ++cc_library( ++ name = "firewood_ffi", ++ hdrs = ["firewood.h"], ++ deps = [":firewood_ffi_lib"], ++ linkopts = ["-lm"], ++ visibility = ["//visibility:public"], ++) ++ ++go_library( ++ name = "ffi", ++ srcs = [ ++ "firewood.go", ++ "firewood.h", ++ "iterator.go", ++ "keepalive.go", ++ "maybe.go", ++ "memory.go", ++ "metrics.go", ++ "proofs.go", ++ "proposal.go", ++ "revision.go", ++ ], ++ cgo = True, ++ cdeps = [":firewood_ffi"], ++ importpath = "github.com/ava-labs/firewood-go-ethhash/ffi", ++ visibility = ["//visibility:public"], ++ deps = [ ++ "@com_github_prometheus_client_golang//prometheus", ++ "@com_github_prometheus_client_model//go", ++ "@com_github_prometheus_common//expfmt", ++ ], ++) ++ ++alias( ++ name = "go_default_library", ++ actual = ":ffi", ++ visibility = ["//visibility:public"], ++) ++ ++go_test( ++ name = "ffi_test", ++ srcs = [ ++ "firewood_test.go", ++ "metrics_test.go", ++ "proofs_test.go", ++ ], ++ embed = [":ffi"], ++ deps = [ ++ "@com_github_prometheus_client_model//go", ++ "@com_github_stretchr_testify//require", ++ ], ++) diff --git a/patches/libevm_secp256k1.patch b/patches/libevm_secp256k1.patch new file mode 100644 index 000000000000..a57d377f4880 --- /dev/null +++ b/patches/libevm_secp256k1.patch @@ -0,0 +1,32 @@ +--- a/crypto/secp256k1/BUILD.bazel ++++ b/crypto/secp256k1/BUILD.bazel +@@ -1,5 +1,16 @@ + load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + ++# The secp256k1 Go package uses cgo and #includes C source files directly. ++# These files must be available as textual headers (not compiled separately). ++cc_library( ++ name = "libsecp256k1_hdrs", ++ textual_hdrs = glob([ ++ "libsecp256k1/**/*.c", ++ "libsecp256k1/**/*.h", ++ ]), ++ visibility = ["//visibility:private"], ++) ++ + go_library( + name = "secp256k1", + srcs = [ +@@ -10,11 +21,8 @@ + "scalar_mult_nocgo.go", + "secp256.go", + ], ++ cdeps = [":libsecp256k1_hdrs"], + cgo = True, +- copts = [ +- "-Icrypto/secp256k1/libsecp256k1", +- "-Icrypto/secp256k1/libsecp256k1/src", +- ], + importpath = "github.com/ava-labs/libevm/crypto/secp256k1", + visibility = ["//visibility:public"], + ) diff --git a/proto/aliasreader/BUILD.bazel b/proto/aliasreader/BUILD.bazel new file mode 100644 index 000000000000..fda4a4880a58 --- /dev/null +++ b/proto/aliasreader/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "aliasreader_proto", + srcs = ["aliasreader.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "aliasreader_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/aliasreader", + proto = ":aliasreader_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "aliasreader", + embed = [":aliasreader_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/aliasreader", + visibility = ["//visibility:public"], +) diff --git a/proto/appsender/BUILD.bazel b/proto/appsender/BUILD.bazel new file mode 100644 index 000000000000..55d2d45b13e5 --- /dev/null +++ b/proto/appsender/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "appsender_proto", + srcs = ["appsender.proto"], + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:empty_proto"], +) + +go_proto_library( + name = "appsender_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/appsender", + proto = ":appsender_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "appsender", + embed = [":appsender_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/appsender", + visibility = ["//visibility:public"], +) diff --git a/proto/http/BUILD.bazel b/proto/http/BUILD.bazel new file mode 100644 index 000000000000..703f8b95b4f2 --- /dev/null +++ b/proto/http/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "http_proto", + srcs = ["http.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "http_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/http", + proto = ":http_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "http", + embed = [":http_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/http", + visibility = ["//visibility:public"], +) diff --git a/proto/http/responsewriter/BUILD.bazel b/proto/http/responsewriter/BUILD.bazel new file mode 100644 index 000000000000..5144f85ed219 --- /dev/null +++ b/proto/http/responsewriter/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "responsewriter_proto", + srcs = ["responsewriter.proto"], + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:empty_proto"], +) + +go_proto_library( + name = "responsewriter_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/http/responsewriter", + proto = ":responsewriter_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "responsewriter", + embed = [":responsewriter_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/http/responsewriter", + visibility = ["//visibility:public"], +) diff --git a/proto/io/reader/BUILD.bazel b/proto/io/reader/BUILD.bazel new file mode 100644 index 000000000000..1be502e4d8e3 --- /dev/null +++ b/proto/io/reader/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "reader_proto", + srcs = ["reader.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "reader_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/io/reader", + proto = ":reader_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "reader", + embed = [":reader_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/io/reader", + visibility = ["//visibility:public"], +) diff --git a/proto/io/writer/BUILD.bazel b/proto/io/writer/BUILD.bazel new file mode 100644 index 000000000000..dfe55d240cfe --- /dev/null +++ b/proto/io/writer/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "writer_proto", + srcs = ["writer.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "writer_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/io/writer", + proto = ":writer_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "writer", + embed = [":writer_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/io/writer", + visibility = ["//visibility:public"], +) diff --git a/proto/net/conn/BUILD.bazel b/proto/net/conn/BUILD.bazel new file mode 100644 index 000000000000..575771d41bde --- /dev/null +++ b/proto/net/conn/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "conn_proto", + srcs = ["conn.proto"], + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:empty_proto"], +) + +go_proto_library( + name = "conn_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/net/conn", + proto = ":conn_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "conn", + embed = [":conn_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/net/conn", + visibility = ["//visibility:public"], +) diff --git a/proto/p2p/BUILD.bazel b/proto/p2p/BUILD.bazel new file mode 100644 index 000000000000..d14fbbdba7cf --- /dev/null +++ b/proto/p2p/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "p2p_proto", + srcs = ["p2p.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "p2p_go_proto", + importpath = "github.com/ava-labs/avalanchego/proto/pb/p2p", + proto = ":p2p_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "p2p", + embed = [":p2p_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/p2p", + visibility = ["//visibility:public"], +) diff --git a/proto/pb/aliasreader/BUILD.bazel b/proto/pb/aliasreader/BUILD.bazel new file mode 100644 index 000000000000..22294b61bf75 --- /dev/null +++ b/proto/pb/aliasreader/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "aliasreader", + srcs = [ + "aliasreader.pb.go", + "aliasreader_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/aliasreader", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/appsender/BUILD.bazel b/proto/pb/appsender/BUILD.bazel new file mode 100644 index 000000000000..60fcd8cf196c --- /dev/null +++ b/proto/pb/appsender/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "appsender", + srcs = [ + "appsender.pb.go", + "appsender_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/appsender", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/proto/pb/http/BUILD.bazel b/proto/pb/http/BUILD.bazel new file mode 100644 index 000000000000..335c16647d38 --- /dev/null +++ b/proto/pb/http/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "http", + srcs = [ + "http.pb.go", + "http_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/http", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/http/responsewriter/BUILD.bazel b/proto/pb/http/responsewriter/BUILD.bazel new file mode 100644 index 000000000000..8863081ed578 --- /dev/null +++ b/proto/pb/http/responsewriter/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "responsewriter", + srcs = [ + "responsewriter.pb.go", + "responsewriter_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/http/responsewriter", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/proto/pb/io/reader/BUILD.bazel b/proto/pb/io/reader/BUILD.bazel new file mode 100644 index 000000000000..e74407b8e023 --- /dev/null +++ b/proto/pb/io/reader/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "reader", + srcs = [ + "reader.pb.go", + "reader_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/io/reader", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/io/writer/BUILD.bazel b/proto/pb/io/writer/BUILD.bazel new file mode 100644 index 000000000000..1fa595973262 --- /dev/null +++ b/proto/pb/io/writer/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "writer", + srcs = [ + "writer.pb.go", + "writer_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/io/writer", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/net/conn/BUILD.bazel b/proto/pb/net/conn/BUILD.bazel new file mode 100644 index 000000000000..c08b95680840 --- /dev/null +++ b/proto/pb/net/conn/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "conn", + srcs = [ + "conn.pb.go", + "conn_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/net/conn", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/proto/pb/p2p/BUILD.bazel b/proto/pb/p2p/BUILD.bazel new file mode 100644 index 000000000000..435c6663121c --- /dev/null +++ b/proto/pb/p2p/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "p2p", + srcs = ["p2p.pb.go"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/p2p", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/platformvm/BUILD.bazel b/proto/pb/platformvm/BUILD.bazel new file mode 100644 index 000000000000..44b0af4d4828 --- /dev/null +++ b/proto/pb/platformvm/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "platformvm", + srcs = ["platformvm.pb.go"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/platformvm", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/rpcdb/BUILD.bazel b/proto/pb/rpcdb/BUILD.bazel new file mode 100644 index 000000000000..b05c475c8ec4 --- /dev/null +++ b/proto/pb/rpcdb/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "rpcdb", + srcs = [ + "rpcdb.pb.go", + "rpcdb_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/rpcdb", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/proto/pb/sdk/BUILD.bazel b/proto/pb/sdk/BUILD.bazel new file mode 100644 index 000000000000..4a2011993817 --- /dev/null +++ b/proto/pb/sdk/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "sdk", + srcs = ["sdk.pb.go"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/sdk", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/sharedmemory/BUILD.bazel b/proto/pb/sharedmemory/BUILD.bazel new file mode 100644 index 000000000000..f4b7c4707fb1 --- /dev/null +++ b/proto/pb/sharedmemory/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "sharedmemory", + srcs = [ + "sharedmemory.pb.go", + "sharedmemory_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/sharedmemory", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/signer/BUILD.bazel b/proto/pb/signer/BUILD.bazel new file mode 100644 index 000000000000..65617f70e380 --- /dev/null +++ b/proto/pb/signer/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "signer", + srcs = [ + "signer.pb.go", + "signer_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/signer", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/sync/BUILD.bazel b/proto/pb/sync/BUILD.bazel new file mode 100644 index 000000000000..012fdb5e0ed6 --- /dev/null +++ b/proto/pb/sync/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "sync", + srcs = ["sync.pb.go"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/sync", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/pb/validatorstate/BUILD.bazel b/proto/pb/validatorstate/BUILD.bazel new file mode 100644 index 000000000000..c1c89e1a35df --- /dev/null +++ b/proto/pb/validatorstate/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "validatorstate", + srcs = [ + "validator_state.pb.go", + "validator_state_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/validatorstate", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/proto/pb/vm/BUILD.bazel b/proto/pb/vm/BUILD.bazel new file mode 100644 index 000000000000..b14227a52ced --- /dev/null +++ b/proto/pb/vm/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "vm", + srcs = [ + "vm.pb.go", + "vm_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/vm", + visibility = ["//visibility:public"], + deps = [ + "@com_github_prometheus_client_model//go", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + "@org_golang_google_protobuf//types/known/durationpb", + "@org_golang_google_protobuf//types/known/emptypb", + "@org_golang_google_protobuf//types/known/timestamppb", + ], +) diff --git a/proto/pb/vm/runtime/BUILD.bazel b/proto/pb/vm/runtime/BUILD.bazel new file mode 100644 index 000000000000..eef8f460f00b --- /dev/null +++ b/proto/pb/vm/runtime/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "runtime", + srcs = [ + "runtime.pb.go", + "runtime_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/vm/runtime", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/proto/pb/warp/BUILD.bazel b/proto/pb/warp/BUILD.bazel new file mode 100644 index 000000000000..56c68c85e317 --- /dev/null +++ b/proto/pb/warp/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "warp", + srcs = [ + "message.pb.go", + "message_grpc.pb.go", + ], + importpath = "github.com/ava-labs/avalanchego/proto/pb/warp", + visibility = ["//visibility:public"], + deps = [ + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//reflect/protoreflect", + "@org_golang_google_protobuf//runtime/protoimpl", + ], +) diff --git a/proto/platformvm/BUILD.bazel b/proto/platformvm/BUILD.bazel new file mode 100644 index 000000000000..835c36a23af6 --- /dev/null +++ b/proto/platformvm/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "platformvm_proto", + srcs = ["platformvm.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "platformvm_go_proto", + importpath = "github.com/ava-labs/avalanchego/proto/pb/platformvm", + proto = ":platformvm_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "platformvm", + embed = [":platformvm_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/platformvm", + visibility = ["//visibility:public"], +) diff --git a/proto/rpcdb/BUILD.bazel b/proto/rpcdb/BUILD.bazel new file mode 100644 index 000000000000..48c5bfb6e2f7 --- /dev/null +++ b/proto/rpcdb/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "rpcdb_proto", + srcs = ["rpcdb.proto"], + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:empty_proto"], +) + +go_proto_library( + name = "rpcdb_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/rpcdb", + proto = ":rpcdb_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "rpcdb", + embed = [":rpcdb_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/rpcdb", + visibility = ["//visibility:public"], +) diff --git a/proto/sdk/BUILD.bazel b/proto/sdk/BUILD.bazel new file mode 100644 index 000000000000..9a2498566ee1 --- /dev/null +++ b/proto/sdk/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "sdk_proto", + srcs = ["sdk.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "sdk_go_proto", + importpath = "github.com/ava-labs/avalanchego/proto/pb/sdk", + proto = ":sdk_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "sdk", + embed = [":sdk_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/sdk", + visibility = ["//visibility:public"], +) diff --git a/proto/sharedmemory/BUILD.bazel b/proto/sharedmemory/BUILD.bazel new file mode 100644 index 000000000000..7dd153f9af96 --- /dev/null +++ b/proto/sharedmemory/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "sharedmemory_proto", + srcs = ["sharedmemory.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "sharedmemory_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/sharedmemory", + proto = ":sharedmemory_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "sharedmemory", + embed = [":sharedmemory_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/sharedmemory", + visibility = ["//visibility:public"], +) diff --git a/proto/signer/BUILD.bazel b/proto/signer/BUILD.bazel new file mode 100644 index 000000000000..ef366fd24c60 --- /dev/null +++ b/proto/signer/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "signer_proto", + srcs = ["signer.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "signer_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/signer", + proto = ":signer_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "signer", + embed = [":signer_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/signer", + visibility = ["//visibility:public"], +) diff --git a/proto/sync/BUILD.bazel b/proto/sync/BUILD.bazel new file mode 100644 index 000000000000..023157b86689 --- /dev/null +++ b/proto/sync/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "sync_proto", + srcs = ["sync.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "sync_go_proto", + importpath = "github.com/ava-labs/avalanchego/proto/pb/sync", + proto = ":sync_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "sync", + embed = [":sync_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/sync", + visibility = ["//visibility:public"], +) diff --git a/proto/validatorstate/BUILD.bazel b/proto/validatorstate/BUILD.bazel new file mode 100644 index 000000000000..c8b0ed9d063b --- /dev/null +++ b/proto/validatorstate/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "validatorstate_proto", + srcs = ["validator_state.proto"], + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:empty_proto"], +) + +go_proto_library( + name = "validatorstate_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/validatorstate", + proto = ":validatorstate_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "validatorstate", + embed = [":validatorstate_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/validatorstate", + visibility = ["//visibility:public"], +) diff --git a/proto/vm/BUILD.bazel b/proto/vm/BUILD.bazel new file mode 100644 index 000000000000..df641e7e9886 --- /dev/null +++ b/proto/vm/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "vm_proto", + srcs = ["vm.proto"], + visibility = ["//visibility:public"], + deps = [ + "//io/prometheus/client:client_proto", + "@com_google_protobuf//:duration_proto", + "@com_google_protobuf//:empty_proto", + "@com_google_protobuf//:timestamp_proto", + ], +) + +go_proto_library( + name = "vm_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/vm", + proto = ":vm_proto", + visibility = ["//visibility:public"], + deps = ["//io/prometheus/client:metrics_proto"], +) + +go_library( + name = "vm", + embed = [":vm_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/vm", + visibility = ["//visibility:public"], +) diff --git a/proto/vm/runtime/BUILD.bazel b/proto/vm/runtime/BUILD.bazel new file mode 100644 index 000000000000..522e387e8511 --- /dev/null +++ b/proto/vm/runtime/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "manager_proto", + srcs = ["runtime.proto"], + visibility = ["//visibility:public"], + deps = ["@com_google_protobuf//:empty_proto"], +) + +go_proto_library( + name = "manager_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/vm/manager", + proto = ":manager_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "manager", + embed = [":manager_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/vm/manager", + visibility = ["//visibility:public"], +) diff --git a/proto/warp/BUILD.bazel b/proto/warp/BUILD.bazel new file mode 100644 index 000000000000..ee8f28cba22b --- /dev/null +++ b/proto/warp/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") +load("@rules_go//proto:def.bzl", "go_proto_library") +load("@rules_proto//proto:defs.bzl", "proto_library") + +proto_library( + name = "warp_proto", + srcs = ["message.proto"], + visibility = ["//visibility:public"], +) + +go_proto_library( + name = "warp_go_proto", + compilers = ["@io_bazel_rules_go//proto:go_grpc_v2"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/warp", + proto = ":warp_proto", + visibility = ["//visibility:public"], +) + +go_library( + name = "warp", + embed = [":warp_go_proto"], + importpath = "github.com/ava-labs/avalanchego/proto/pb/warp", + visibility = ["//visibility:public"], +) diff --git a/result b/result new file mode 120000 index 000000000000..defcc64bc372 --- /dev/null +++ b/result @@ -0,0 +1 @@ +/nix/store/2vjbfwp7hlys3bb54hs7zl8piipkcrry-go-1.24.9 \ No newline at end of file diff --git a/simplex/BUILD.bazel b/simplex/BUILD.bazel new file mode 100644 index 000000000000..6c8bfe93565d --- /dev/null +++ b/simplex/BUILD.bazel @@ -0,0 +1,84 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "simplex", + srcs = [ + "block.canoto.go", + "block.go", + "block_builder.go", + "bls.go", + "codec.go", + "comm.go", + "config.go", + "messages.go", + "qc.canoto.go", + "qc.go", + "storage.canoto.go", + "storage.go", + ], + importpath = "github.com/ava-labs/avalanchego/simplex", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//database", + "//ids", + "//message", + "//proto/pb/p2p", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//snow/networking/sender", + "//snow/validators", + "//subnets", + "//utils", + "//utils/crypto/bls", + "//utils/hashing", + "//utils/logging", + "//utils/set", + "//utils/tree", + "//vms/platformvm/warp", + "@com_github_ava_labs_simplex//:simplex", + "@com_github_stephenbuttolph_canoto//:canoto", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "simplex_test", + srcs = [ + "block_builder_test.go", + "block_test.go", + "bls_test.go", + "comm_test.go", + "qc_test.go", + "storage_test.go", + "util_test.go", + ], + embed = [":simplex"], + deps = [ + "//database", + "//database/memdb", + "//ids", + "//message", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmantest", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/engine/snowman/block/blocktest", + "//snow/networking/sender/sendermock", + "//snow/snowtest", + "//snow/validators", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/logging", + "//utils/set", + "@com_github_ava_labs_simplex//:simplex", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stephenbuttolph_canoto//:canoto", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/BUILD.bazel b/snow/BUILD.bazel new file mode 100644 index 000000000000..0f70888a2219 --- /dev/null +++ b/snow/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "snow", + srcs = [ + "acceptor.go", + "context.go", + "decidable.go", + "state.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow", + visibility = ["//visibility:public"], + deps = [ + "//api/metrics", + "//chains/atomic", + "//ids", + "//proto/pb/p2p", + "//snow/validators", + "//upgrade", + "//utils", + "//utils/crypto/bls", + "//utils/logging", + "//vms/platformvm/warp", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) diff --git a/snow/choices/BUILD.bazel b/snow/choices/BUILD.bazel new file mode 100644 index 000000000000..9066a7833b59 --- /dev/null +++ b/snow/choices/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "choices", + srcs = [ + "decidable.go", + "status.go", + "test_decidable.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/choices", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/wrappers", + ], +) + +go_test( + name = "choices_test", + srcs = ["status_test.go"], + embed = [":choices"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/snow/consensus/avalanche/BUILD.bazel b/snow/consensus/avalanche/BUILD.bazel new file mode 100644 index 000000000000..8806c3557a16 --- /dev/null +++ b/snow/consensus/avalanche/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "avalanche", + srcs = [ + "test_vertex.go", + "vertex.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/consensus/avalanche", + visibility = ["//visibility:public"], + deps = [ + "//snow/choices", + "//snow/consensus/snowstorm", + ], +) diff --git a/snow/consensus/snowball/BUILD.bazel b/snow/consensus/snowball/BUILD.bazel new file mode 100644 index 000000000000..5b41e29a1262 --- /dev/null +++ b/snow/consensus/snowball/BUILD.bazel @@ -0,0 +1,54 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "snowball", + srcs = [ + "binary_slush.go", + "binary_snowball.go", + "binary_snowflake.go", + "consensus.go", + "factory.go", + "flat.go", + "nnary_slush.go", + "nnary_snowball.go", + "nnary_snowflake.go", + "parameters.go", + "tree.go", + "unary_snowball.go", + "unary_snowflake.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/consensus/snowball", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/bag", + ], +) + +go_test( + name = "snowball_test", + srcs = [ + "binary_snowball_test.go", + "binary_snowflake_test.go", + "consensus_performance_test.go", + "consensus_reversibility_test.go", + "consensus_test.go", + "flat_test.go", + "network_test.go", + "nnary_snowball_test.go", + "nnary_snowflake_test.go", + "parameters_test.go", + "snowflake_test.go", + "tree_test.go", + "unary_snowball_test.go", + "unary_snowflake_test.go", + ], + embed = [":snowball"], + deps = [ + "//ids", + "//utils/bag", + "//utils/sampler", + "@com_github_stretchr_testify//require", + "@org_gonum_v1_gonum//mathext/prng", + ], +) diff --git a/snow/consensus/snowman/BUILD.bazel b/snow/consensus/snowman/BUILD.bazel new file mode 100644 index 000000000000..384abecc8c1d --- /dev/null +++ b/snow/consensus/snowman/BUILD.bazel @@ -0,0 +1,58 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "snowman", + srcs = [ + "block.go", + "consensus.go", + "factory.go", + "metrics.go", + "oracle_block.go", + "snowman_block.go", + "topological.go", + "traced_consensus.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/consensus/snowman", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//ids", + "//snow", + "//snow/consensus/snowball", + "//trace", + "//utils/bag", + "//utils/linked", + "//utils/logging", + "//utils/metric", + "//utils/set", + "//utils/wrappers", + "@com_github_prometheus_client_golang//prometheus", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "snowman_test", + srcs = [ + "consensus_test.go", + "mixed_test.go", + "mocks_generate_test.go", + "network_test.go", + "topological_test.go", + ], + embed = [":snowman"], + deps = [ + "//ids", + "//snow/consensus/snowball", + "//snow/consensus/snowman/snowmantest", + "//snow/snowtest", + "//utils", + "//utils/bag", + "//utils/sampler", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_gonum_v1_gonum//mathext/prng", + ], +) diff --git a/snow/consensus/snowman/bootstrapper/BUILD.bazel b/snow/consensus/snowman/bootstrapper/BUILD.bazel new file mode 100644 index 000000000000..ba14cbbc6693 --- /dev/null +++ b/snow/consensus/snowman/bootstrapper/BUILD.bazel @@ -0,0 +1,43 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bootstrapper", + srcs = [ + "majority.go", + "minority.go", + "noop.go", + "poll.go", + "requests.go", + "sampler.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/consensus/snowman/bootstrapper", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/logging", + "//utils/math", + "//utils/sampler", + "//utils/set", + "@org_golang_x_exp//maps", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "bootstrapper_test", + srcs = [ + "majority_test.go", + "minority_test.go", + "noop_test.go", + "poll_test.go", + "sampler_test.go", + ], + embed = [":bootstrapper"], + deps = [ + "//ids", + "//utils/logging", + "//utils/math", + "//utils/set", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/consensus/snowman/poll/BUILD.bazel b/snow/consensus/snowman/poll/BUILD.bazel new file mode 100644 index 000000000000..595f170f4aea --- /dev/null +++ b/snow/consensus/snowman/poll/BUILD.bazel @@ -0,0 +1,42 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "poll", + srcs = [ + "early_term_traversal.go", + "graph.go", + "interfaces.go", + "prefix.go", + "set.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/consensus/snowman/poll", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/bag", + "//utils/formatting", + "//utils/linked", + "//utils/logging", + "//utils/metric", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "poll_test", + srcs = [ + "early_term_traversal_test.go", + "graph_test.go", + "prefix_test.go", + "set_test.go", + ], + embed = [":poll"], + deps = [ + "//ids", + "//utils/bag", + "//utils/logging", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/consensus/snowman/snowmanmock/BUILD.bazel b/snow/consensus/snowman/snowmanmock/BUILD.bazel new file mode 100644 index 000000000000..1fdcdc00d6c4 --- /dev/null +++ b/snow/consensus/snowman/snowmanmock/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "snowmanmock", + srcs = ["block.go"], + importpath = "github.com/ava-labs/avalanchego/snow/consensus/snowman/snowmanmock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/consensus/snowman/snowmantest/BUILD.bazel b/snow/consensus/snowman/snowmantest/BUILD.bazel new file mode 100644 index 000000000000..df2ffb36de3f --- /dev/null +++ b/snow/consensus/snowman/snowmantest/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "snowmantest", + srcs = [ + "block.go", + "engine.go", + "require.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/consensus/snowman/snowmantest", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow/snowtest", + "//upgrade", + "//utils", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/consensus/snowstorm/BUILD.bazel b/snow/consensus/snowstorm/BUILD.bazel new file mode 100644 index 000000000000..264e5b9ee67e --- /dev/null +++ b/snow/consensus/snowstorm/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "snowstorm", + srcs = [ + "test_tx.go", + "tx.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/consensus/snowstorm", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/choices", + "//utils/set", + ], +) diff --git a/snow/engine/avalanche/BUILD.bazel b/snow/engine/avalanche/BUILD.bazel new file mode 100644 index 000000000000..fceae5dcff15 --- /dev/null +++ b/snow/engine/avalanche/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "avalanche", + srcs = ["engine.go"], + importpath = "github.com/ava-labs/avalanchego/snow/engine/avalanche", + visibility = ["//visibility:public"], + deps = [ + "//snow", + "//snow/engine/common", + ], +) diff --git a/snow/engine/avalanche/bootstrap/BUILD.bazel b/snow/engine/avalanche/bootstrap/BUILD.bazel new file mode 100644 index 000000000000..3d16c14fa41d --- /dev/null +++ b/snow/engine/avalanche/bootstrap/BUILD.bazel @@ -0,0 +1,66 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bootstrap", + srcs = [ + "bootstrapper.go", + "config.go", + "metrics.go", + "tx_job.go", + "vertex_job.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/avalanche/bootstrap", + visibility = ["//visibility:public"], + deps = [ + "//cache/lru", + "//ids", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/choices", + "//snow/consensus/avalanche", + "//snow/consensus/snowstorm", + "//snow/engine/avalanche/bootstrap/queue", + "//snow/engine/avalanche/vertex", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//utils/bimap", + "//utils/heap", + "//utils/logging", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "bootstrap_test", + srcs = ["bootstrapper_test.go"], + embed = [":bootstrap"], + deps = [ + "//database/memdb", + "//database/prefixdb", + "//ids", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/choices", + "//snow/consensus/avalanche", + "//snow/consensus/snowstorm", + "//snow/engine/avalanche/bootstrap/queue", + "//snow/engine/avalanche/getter", + "//snow/engine/avalanche/vertex/vertextest", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/enginetest", + "//snow/snowtest", + "//snow/validators", + "//utils/constants", + "//utils/logging", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/avalanche/bootstrap/queue/BUILD.bazel b/snow/engine/avalanche/bootstrap/queue/BUILD.bazel new file mode 100644 index 000000000000..d54571a0432c --- /dev/null +++ b/snow/engine/avalanche/bootstrap/queue/BUILD.bazel @@ -0,0 +1,50 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "queue", + srcs = [ + "job.go", + "jobs.go", + "parser.go", + "state.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/avalanche/bootstrap/queue", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//cache/metercacher", + "//database", + "//database/linkeddb", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//snow", + "//snow/engine/common", + "//utils/metric", + "//utils/set", + "//utils/timer", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "queue_test", + srcs = [ + "job_test.go", + "jobs_test.go", + "parser_test.go", + ], + embed = [":queue"], + deps = [ + "//database", + "//database/memdb", + "//ids", + "//snow/engine/common", + "//snow/snowtest", + "//utils/set", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/avalanche/getter/BUILD.bazel b/snow/engine/avalanche/getter/BUILD.bazel new file mode 100644 index 000000000000..60a8c0ffd0b0 --- /dev/null +++ b/snow/engine/avalanche/getter/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "getter", + srcs = ["getter.go"], + importpath = "github.com/ava-labs/avalanchego/snow/engine/avalanche/getter", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//snow/choices", + "//snow/consensus/avalanche", + "//snow/engine/avalanche/vertex", + "//snow/engine/common", + "//utils/constants", + "//utils/logging", + "//utils/metric", + "//utils/set", + "//utils/wrappers", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) diff --git a/snow/engine/avalanche/state/BUILD.bazel b/snow/engine/avalanche/state/BUILD.bazel new file mode 100644 index 000000000000..467d58f56ee5 --- /dev/null +++ b/snow/engine/avalanche/state/BUILD.bazel @@ -0,0 +1,48 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "state", + srcs = [ + "prefixed_state.go", + "serializer.go", + "state.go", + "unique_vertex.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/avalanche/state", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//database", + "//database/versiondb", + "//ids", + "//snow/choices", + "//snow/consensus/avalanche", + "//snow/consensus/snowstorm", + "//snow/engine/avalanche/vertex", + "//utils/formatting", + "//utils/hashing", + "//utils/logging", + "//utils/math", + "//utils/set", + "//utils/wrappers", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "state_test", + srcs = ["unique_vertex_test.go"], + embed = [":state"], + deps = [ + "//database/memdb", + "//ids", + "//snow/choices", + "//snow/consensus/snowstorm", + "//snow/engine/avalanche/vertex", + "//snow/engine/avalanche/vertex/vertextest", + "//utils/hashing", + "//utils/logging", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/avalanche/vertex/BUILD.bazel b/snow/engine/avalanche/vertex/BUILD.bazel new file mode 100644 index 000000000000..82520429e0b9 --- /dev/null +++ b/snow/engine/avalanche/vertex/BUILD.bazel @@ -0,0 +1,45 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "vertex", + srcs = [ + "builder.go", + "codec.go", + "manager.go", + "parser.go", + "stateless_vertex.go", + "storage.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//codec/reflectcodec", + "//ids", + "//snow/consensus/avalanche", + "//snow/consensus/snowstorm", + "//snow/engine/snowman/block", + "//utils", + "//utils/hashing", + "//utils/units", + "//vms/components/verify", + ], +) + +go_test( + name = "vertex_test", + srcs = [ + "builder_test.go", + "mocks_generate_test.go", + "parser_test.go", + "stateless_vertex_test.go", + ], + embed = [":vertex"], + deps = [ + "//codec", + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/avalanche/vertex/vertexmock/BUILD.bazel b/snow/engine/avalanche/vertex/vertexmock/BUILD.bazel new file mode 100644 index 000000000000..7bcb9058de4d --- /dev/null +++ b/snow/engine/avalanche/vertex/vertexmock/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "vertexmock", + srcs = ["linearizable_vm.go"], + importpath = "github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex/vertexmock", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/consensus/snowstorm", + "//snow/engine/common", + "//version", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/engine/avalanche/vertex/vertextest/BUILD.bazel b/snow/engine/avalanche/vertex/vertextest/BUILD.bazel new file mode 100644 index 000000000000..acbccb0f1feb --- /dev/null +++ b/snow/engine/avalanche/vertex/vertextest/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "vertextest", + srcs = [ + "builder.go", + "manager.go", + "parser.go", + "storage.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/avalanche/vertex/vertextest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/consensus/avalanche", + "//snow/consensus/snowstorm", + "//snow/engine/avalanche/vertex", + "//snow/engine/snowman/block/blocktest", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/common/BUILD.bazel b/snow/engine/common/BUILD.bazel new file mode 100644 index 000000000000..49189c314beb --- /dev/null +++ b/snow/engine/common/BUILD.bazel @@ -0,0 +1,58 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "common", + srcs = [ + "bootstrap_tracker.go", + "bootstrapable.go", + "engine.go", + "error.go", + "fx.go", + "halter.go", + "message.go", + "no_ops_handlers.go", + "notifier.go", + "request.go", + "sender.go", + "state_syncer.go", + "timer.go", + "traced_bootstrapable_engine.go", + "traced_engine.go", + "traced_state_syncer.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/common", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//database", + "//ids", + "//message", + "//snow", + "//snow/validators", + "//trace", + "//utils/logging", + "//utils/set", + "//version", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "common_test", + srcs = [ + "error_test.go", + "mocks_generate_test.go", + "notifier_test.go", + "request_test.go", + "timer_test.go", + ], + embed = [":common"], + deps = [ + "//ids", + "//utils/logging", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/common/appsender/BUILD.bazel b/snow/engine/common/appsender/BUILD.bazel new file mode 100644 index 000000000000..e919d3752c5a --- /dev/null +++ b/snow/engine/common/appsender/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "appsender", + srcs = [ + "appsender_client.go", + "appsender_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/common/appsender", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//proto/pb/appsender", + "//snow/engine/common", + "//utils/set", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/snow/engine/common/commonmock/BUILD.bazel b/snow/engine/common/commonmock/BUILD.bazel new file mode 100644 index 000000000000..2acd91b2dd8e --- /dev/null +++ b/snow/engine/common/commonmock/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "commonmock", + srcs = ["sender.go"], + importpath = "github.com/ava-labs/avalanchego/snow/engine/common/commonmock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/engine/common", + "//utils/set", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/engine/common/tracker/BUILD.bazel b/snow/engine/common/tracker/BUILD.bazel new file mode 100644 index 000000000000..760fe9758795 --- /dev/null +++ b/snow/engine/common/tracker/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "tracker", + srcs = [ + "accepted.go", + "peers.go", + "startup.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/common/tracker", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/validators", + "//utils/crypto/bls", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_x_exp//maps", + ], +) + +go_test( + name = "tracker_test", + srcs = [ + "accepted_test.go", + "peers_test.go", + ], + embed = [":tracker"], + deps = [ + "//ids", + "//version", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/enginetest/BUILD.bazel b/snow/engine/enginetest/BUILD.bazel new file mode 100644 index 000000000000..2dc5150f9cb3 --- /dev/null +++ b/snow/engine/enginetest/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "enginetest", + srcs = [ + "bootstrap_tracker.go", + "bootstrapper.go", + "engine.go", + "sender.go", + "timer.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/enginetest", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/engine/common", + "//utils/set", + "//version", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/snowman/BUILD.bazel b/snow/engine/snowman/BUILD.bazel new file mode 100644 index 000000000000..872caad24f03 --- /dev/null +++ b/snow/engine/snowman/BUILD.bazel @@ -0,0 +1,75 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "snowman", + srcs = [ + "config.go", + "engine.go", + "issuer.go", + "memory_block.go", + "metrics.go", + "voter.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//cache/metercacher", + "//ids", + "//proto/pb/p2p", + "//snow", + "//snow/consensus/snowball", + "//snow/consensus/snowman", + "//snow/consensus/snowman/poll", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/snowman/ancestor", + "//snow/engine/snowman/block", + "//snow/engine/snowman/job", + "//snow/validators", + "//utils/bag", + "//utils/bimap", + "//utils/constants", + "//utils/logging", + "//utils/math", + "//utils/metric", + "//utils/set", + "//utils/units", + "//utils/wrappers", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "snowman_test", + srcs = [ + "config_test.go", + "engine_test.go", + ], + embed = [":snowman"], + deps = [ + "//cache", + "//cache/lru", + "//database", + "//ids", + "//snow", + "//snow/consensus/snowball", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmantest", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/enginetest", + "//snow/engine/snowman/ancestor", + "//snow/engine/snowman/block/blocktest", + "//snow/engine/snowman/getter", + "//snow/snowtest", + "//snow/validators", + "//utils/logging", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/snowman/ancestor/BUILD.bazel b/snow/engine/snowman/ancestor/BUILD.bazel new file mode 100644 index 000000000000..91c69a8a12aa --- /dev/null +++ b/snow/engine/snowman/ancestor/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "ancestor", + srcs = ["tree.go"], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/ancestor", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/set", + ], +) + +go_test( + name = "ancestor_test", + srcs = ["tree_test.go"], + embed = [":ancestor"], + deps = [ + "//ids", + "//utils/set", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/snowman/block/BUILD.bazel b/snow/engine/snowman/block/BUILD.bazel new file mode 100644 index 000000000000..84cf203e94d7 --- /dev/null +++ b/snow/engine/snowman/block/BUILD.bazel @@ -0,0 +1,50 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "block", + srcs = [ + "batched_vm.go", + "block_context_vm.canoto.go", + "block_context_vm.go", + "notifier.go", + "state_summary.go", + "state_sync_mode.go", + "state_syncable_vm.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/block", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//utils/logging", + "//utils/wrappers", + "@com_github_stephenbuttolph_canoto//:canoto", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "block_test", + srcs = [ + "batched_vm_test.go", + "mocks_generate_test.go", + "notifier_test.go", + ], + embed = [":block"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmantest", + "//snow/engine/snowman/block/blockmock", + "//snow/engine/snowman/block/blocktest", + "//utils/logging", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/engine/snowman/block/blockmock/BUILD.bazel b/snow/engine/snowman/block/blockmock/BUILD.bazel new file mode 100644 index 000000000000..0443fc420a60 --- /dev/null +++ b/snow/engine/snowman/block/blockmock/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "blockmock", + srcs = [ + "build_block_with_context_chain_vm.go", + "chain_vm.go", + "full_vm.go", + "state_syncable_vm.go", + "with_verify_context.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/block/blockmock", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//version", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/engine/snowman/block/blocktest/BUILD.bazel b/snow/engine/snowman/block/blocktest/BUILD.bazel new file mode 100644 index 000000000000..1d69385d9cb0 --- /dev/null +++ b/snow/engine/snowman/block/blocktest/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "blocktest", + srcs = [ + "batched_vm.go", + "set_preference_vm.go", + "state_summary.go", + "state_syncable_vm.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/block/blocktest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/consensus/snowman", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/snowman/bootstrap/BUILD.bazel b/snow/engine/snowman/bootstrap/BUILD.bazel new file mode 100644 index 000000000000..328f58efd1ed --- /dev/null +++ b/snow/engine/snowman/bootstrap/BUILD.bazel @@ -0,0 +1,69 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bootstrap", + srcs = [ + "acceptor.go", + "bootstrapper.go", + "config.go", + "metrics.go", + "storage.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//genesis", + "//ids", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/consensus/snowman", + "//snow/consensus/snowman/bootstrapper", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/snowman/block", + "//snow/engine/snowman/bootstrap/interval", + "//snow/validators", + "//utils/bimap", + "//utils/logging", + "//utils/set", + "//utils/timer", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "bootstrap_test", + srcs = [ + "bootstrapper_test.go", + "storage_test.go", + ], + embed = [":bootstrap"], + deps = [ + "//database", + "//database/memdb", + "//ids", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmantest", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/engine/snowman/block/blocktest", + "//snow/engine/snowman/bootstrap/interval", + "//snow/engine/snowman/getter", + "//snow/snowtest", + "//snow/validators", + "//utils/logging", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/snowman/bootstrap/interval/BUILD.bazel b/snow/engine/snowman/bootstrap/interval/BUILD.bazel new file mode 100644 index 000000000000..dcc48d27f7aa --- /dev/null +++ b/snow/engine/snowman/bootstrap/interval/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "interval", + srcs = [ + "blocks.go", + "interval.go", + "state.go", + "tree.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/bootstrap/interval", + visibility = ["//visibility:public"], + deps = [ + "//database", + "@com_github_google_btree//:btree", + ], +) + +go_test( + name = "interval_test", + srcs = [ + "blocks_test.go", + "interval_test.go", + "tree_test.go", + ], + embed = [":interval"], + deps = [ + "//database", + "//database/memdb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/engine/snowman/getter/BUILD.bazel b/snow/engine/snowman/getter/BUILD.bazel new file mode 100644 index 000000000000..9af100dcb891 --- /dev/null +++ b/snow/engine/snowman/getter/BUILD.bazel @@ -0,0 +1,39 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "getter", + srcs = ["getter.go"], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/getter", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils/constants", + "//utils/logging", + "//utils/metric", + "//utils/set", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "getter_test", + srcs = ["getter_test.go"], + embed = [":getter"], + deps = [ + "//ids", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmantest", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/engine/snowman/block/blockmock", + "//snow/engine/snowman/block/blocktest", + "//utils/logging", + "//utils/set", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/engine/snowman/job/BUILD.bazel b/snow/engine/snowman/job/BUILD.bazel new file mode 100644 index 000000000000..84d687c30f01 --- /dev/null +++ b/snow/engine/snowman/job/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "job", + srcs = ["scheduler.go"], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/job", + visibility = ["//visibility:public"], +) + +go_test( + name = "job_test", + srcs = ["scheduler_test.go"], + embed = [":job"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/snow/engine/snowman/syncer/BUILD.bazel b/snow/engine/snowman/syncer/BUILD.bazel new file mode 100644 index 000000000000..0cda727e4854 --- /dev/null +++ b/snow/engine/snowman/syncer/BUILD.bazel @@ -0,0 +1,54 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "syncer", + srcs = [ + "config.go", + "state_syncer.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/engine/snowman/syncer", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//proto/pb/p2p", + "//snow", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/snowman/block", + "//snow/validators", + "//utils/logging", + "//utils/math", + "//utils/set", + "//version", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "syncer_test", + srcs = [ + "state_syncer_test.go", + "utils_test.go", + ], + embed = [":syncer"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/engine/snowman/block/blocktest", + "//snow/engine/snowman/getter", + "//snow/snowtest", + "//snow/validators", + "//utils/hashing", + "//utils/logging", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/networking/benchlist/BUILD.bazel b/snow/networking/benchlist/BUILD.bazel new file mode 100644 index 000000000000..c925cc2a5b50 --- /dev/null +++ b/snow/networking/benchlist/BUILD.bazel @@ -0,0 +1,40 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "benchlist", + srcs = [ + "benchable.go", + "benchlist.go", + "manager.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/networking/benchlist", + visibility = ["//visibility:public"], + deps = [ + "//api/metrics", + "//ids", + "//snow", + "//snow/validators", + "//utils/heap", + "//utils/math", + "//utils/set", + "//utils/timer/mockable", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "benchlist_test", + srcs = [ + "benchable_test.go", + "benchlist_test.go", + ], + embed = [":benchlist"], + deps = [ + "//ids", + "//snow/snowtest", + "//snow/validators", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/networking/handler/BUILD.bazel b/snow/networking/handler/BUILD.bazel new file mode 100644 index 000000000000..71e4c3ad3043 --- /dev/null +++ b/snow/networking/handler/BUILD.bazel @@ -0,0 +1,78 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "handler", + srcs = [ + "engine.go", + "handler.go", + "health.go", + "message_queue.go", + "message_queue_metrics.go", + "metrics.go", + "parser.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/networking/handler", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//ids", + "//message", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/snowman/block", + "//snow/networking/tracker", + "//snow/validators", + "//subnets", + "//utils/buffer", + "//utils/logging", + "//utils/metric", + "//utils/set", + "//utils/timer/mockable", + "@com_github_prometheus_client_golang//prometheus", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + "@org_golang_x_sync//errgroup", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "handler_test", + srcs = [ + "engine_test.go", + "handler_test.go", + "health_test.go", + "message_queue_test.go", + "mocks_generate_test.go", + ], + embed = [":handler"], + deps = [ + "//ids", + "//message", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/consensus/snowball", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/networking/tracker", + "//snow/networking/tracker/trackermock", + "//snow/snowtest", + "//snow/validators", + "//subnets", + "//utils/constants", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/networking/handler/handlermock/BUILD.bazel b/snow/networking/handler/handlermock/BUILD.bazel new file mode 100644 index 000000000000..6a754f940b3c --- /dev/null +++ b/snow/networking/handler/handlermock/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "handlermock", + srcs = ["handler.go"], + importpath = "github.com/ava-labs/avalanchego/snow/networking/handler/handlermock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//snow/networking/handler", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/networking/router/BUILD.bazel b/snow/networking/router/BUILD.bazel new file mode 100644 index 000000000000..3a86fe339506 --- /dev/null +++ b/snow/networking/router/BUILD.bazel @@ -0,0 +1,76 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "router", + srcs = [ + "chain_router.go", + "chain_router_metrics.go", + "health.go", + "inbound_handler.go", + "router.go", + "traced_router.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/networking/router", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//ids", + "//message", + "//proto/pb/p2p", + "//snow/networking/benchlist", + "//snow/networking/handler", + "//snow/networking/timeout", + "//trace", + "//utils", + "//utils/constants", + "//utils/linked", + "//utils/logging", + "//utils/set", + "//utils/timer/mockable", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "router_test", + srcs = [ + "chain_router_test.go", + "main_test.go", + "mocks_generate_test.go", + ], + embed = [":router"], + deps = [ + "//ids", + "//message", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/networking/benchlist", + "//snow/networking/handler", + "//snow/networking/handler/handlermock", + "//snow/networking/timeout", + "//snow/networking/tracker", + "//snow/snowtest", + "//snow/validators", + "//subnets", + "//tests", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/set", + "//utils/timer", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_goleak//:goleak", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/networking/router/routermock/BUILD.bazel b/snow/networking/router/routermock/BUILD.bazel new file mode 100644 index 000000000000..f1a5cf1f8146 --- /dev/null +++ b/snow/networking/router/routermock/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "routermock", + srcs = ["router.go"], + importpath = "github.com/ava-labs/avalanchego/snow/networking/router/routermock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//proto/pb/p2p", + "//snow/networking/handler", + "//snow/networking/router", + "//snow/networking/timeout", + "//utils/logging", + "//utils/set", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/networking/sender/BUILD.bazel b/snow/networking/sender/BUILD.bazel new file mode 100644 index 000000000000..6514a12730cc --- /dev/null +++ b/snow/networking/sender/BUILD.bazel @@ -0,0 +1,72 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "sender", + srcs = [ + "external_sender.go", + "sender.go", + "traced_sender.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/networking/sender", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//proto/pb/p2p", + "//snow", + "//snow/engine/common", + "//snow/networking/router", + "//snow/networking/timeout", + "//subnets", + "//trace", + "//utils/logging", + "//utils/set", + "@com_github_prometheus_client_golang//prometheus", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "sender_test", + srcs = [ + "mocks_generate_test.go", + "sender_test.go", + ], + embed = [":sender"], + deps = [ + "//ids", + "//message", + "//message/messagemock", + "//network/p2p", + "//proto/pb/p2p", + "//snow", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/networking/benchlist", + "//snow/networking/handler", + "//snow/networking/router", + "//snow/networking/router/routermock", + "//snow/networking/sender/sendermock", + "//snow/networking/sender/sendertest", + "//snow/networking/timeout", + "//snow/networking/timeout/timeoutmock", + "//snow/networking/tracker", + "//snow/snowtest", + "//snow/validators", + "//subnets", + "//utils/constants", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/set", + "//utils/timer", + "//version", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/networking/sender/sendermock/BUILD.bazel b/snow/networking/sender/sendermock/BUILD.bazel new file mode 100644 index 000000000000..6d6ac742ea21 --- /dev/null +++ b/snow/networking/sender/sendermock/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "sendermock", + srcs = ["external_sender.go"], + importpath = "github.com/ava-labs/avalanchego/snow/networking/sender/sendermock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//snow/engine/common", + "//subnets", + "//utils/set", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/networking/sender/sendertest/BUILD.bazel b/snow/networking/sender/sendertest/BUILD.bazel new file mode 100644 index 000000000000..9c0ceaf9206c --- /dev/null +++ b/snow/networking/sender/sendertest/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "sendertest", + srcs = ["external.go"], + importpath = "github.com/ava-labs/avalanchego/snow/networking/sender/sendertest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//snow/engine/common", + "//snow/networking/sender", + "//subnets", + "//utils/set", + ], +) diff --git a/snow/networking/timeout/BUILD.bazel b/snow/networking/timeout/BUILD.bazel new file mode 100644 index 000000000000..174da566397e --- /dev/null +++ b/snow/networking/timeout/BUILD.bazel @@ -0,0 +1,37 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "timeout", + srcs = [ + "manager.go", + "metrics.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/networking/timeout", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//snow", + "//snow/networking/benchlist", + "//utils/timer", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "timeout_test", + srcs = [ + "main_test.go", + "manager_test.go", + "mocks_generate_test.go", + ], + embed = [":timeout"], + deps = [ + "//ids", + "//snow/networking/benchlist", + "//utils/timer", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_goleak//:goleak", + ], +) diff --git a/snow/networking/timeout/timeoutmock/BUILD.bazel b/snow/networking/timeout/timeoutmock/BUILD.bazel new file mode 100644 index 000000000000..5c8f86a5aad0 --- /dev/null +++ b/snow/networking/timeout/timeoutmock/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "timeoutmock", + srcs = ["manager.go"], + importpath = "github.com/ava-labs/avalanchego/snow/networking/timeout/timeoutmock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//message", + "//snow", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/networking/tracker/BUILD.bazel b/snow/networking/tracker/BUILD.bazel new file mode 100644 index 000000000000..26f5a5e0eb5b --- /dev/null +++ b/snow/networking/tracker/BUILD.bazel @@ -0,0 +1,45 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "tracker", + srcs = [ + "resource_tracker.go", + "targeter.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/networking/tracker", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/validators", + "//utils/constants", + "//utils/linked", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "tracker_test", + srcs = [ + "mocks_generate_test.go", + "resource_tracker_test.go", + "targeter_test.go", + ], + embed = [":tracker"], + deps = [ + "//ids", + "//snow/networking/tracker/trackermock", + "//snow/validators", + "//utils/constants", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/resource/resourcemock", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/networking/tracker/trackermock/BUILD.bazel b/snow/networking/tracker/trackermock/BUILD.bazel new file mode 100644 index 000000000000..1563af67b4ec --- /dev/null +++ b/snow/networking/tracker/trackermock/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "trackermock", + srcs = [ + "targeter.go", + "tracker.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/networking/tracker/trackermock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/snowtest/BUILD.bazel b/snow/snowtest/BUILD.bazel new file mode 100644 index 000000000000..9e0b6b186a1f --- /dev/null +++ b/snow/snowtest/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "snowtest", + srcs = [ + "context.go", + "decidable.go", + "status.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/snowtest", + visibility = ["//visibility:public"], + deps = [ + "//api/metrics", + "//chains/atomic", + "//database/memdb", + "//ids", + "//snow", + "//snow/validators", + "//snow/validators/validatorstest", + "//upgrade/upgradetest", + "//utils/constants", + "//utils/crypto/bls/signer/localsigner", + "//utils/logging", + "//vms/platformvm/warp", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/uptime/BUILD.bazel b/snow/uptime/BUILD.bazel new file mode 100644 index 000000000000..be6c9c2ea8e9 --- /dev/null +++ b/snow/uptime/BUILD.bazel @@ -0,0 +1,39 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "uptime", + srcs = [ + "locked_calculator.go", + "manager.go", + "no_op_calculator.go", + "state.go", + "test_state.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/uptime", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//utils", + "//utils/timer/mockable", + ], +) + +go_test( + name = "uptime_test", + srcs = [ + "locked_calculator_test.go", + "manager_test.go", + "mocks_generate_test.go", + ], + embed = [":uptime"], + deps = [ + "//database", + "//ids", + "//snow/uptime/uptimemock", + "//utils", + "//utils/timer/mockable", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/uptime/uptimemock/BUILD.bazel b/snow/uptime/uptimemock/BUILD.bazel new file mode 100644 index 000000000000..c5bd0e611f79 --- /dev/null +++ b/snow/uptime/uptimemock/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "uptimemock", + srcs = ["calculator.go"], + importpath = "github.com/ava-labs/avalanchego/snow/uptime/uptimemock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/validators/BUILD.bazel b/snow/validators/BUILD.bazel new file mode 100644 index 000000000000..bb5169d7916d --- /dev/null +++ b/snow/validators/BUILD.bazel @@ -0,0 +1,59 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "validators", + srcs = [ + "connector.go", + "logger.go", + "manager.go", + "set.go", + "state.go", + "traced_state.go", + "validator.go", + "warp.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/validators", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//ids", + "//trace", + "//utils", + "//utils/crypto/bls", + "//utils/formatting", + "//utils/json", + "//utils/logging", + "//utils/math", + "//utils/sampler", + "//utils/set", + "//version", + "//vms/types", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + "@org_golang_x_exp//maps", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "validators_test", + srcs = [ + "manager_test.go", + "mocks_generate_test.go", + "set_test.go", + "state_test.go", + "warp_test.go", + ], + embed = [":validators"], + deps = [ + "//ids", + "//snow/validators/validatorstest", + "//upgrade", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/math", + "//utils/set", + "@com_github_stretchr_testify//require", + ], +) diff --git a/snow/validators/gvalidators/BUILD.bazel b/snow/validators/gvalidators/BUILD.bazel new file mode 100644 index 000000000000..bef58258712a --- /dev/null +++ b/snow/validators/gvalidators/BUILD.bazel @@ -0,0 +1,36 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "gvalidators", + srcs = [ + "validator_state_client.go", + "validator_state_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/validators/gvalidators", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//proto/pb/validatorstate", + "//snow/validators", + "//utils/crypto/bls", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) + +go_test( + name = "gvalidators_test", + srcs = ["validator_state_test.go"], + embed = [":gvalidators"], + deps = [ + "//ids", + "//proto/pb/validatorstate", + "//snow/validators", + "//snow/validators/validatorsmock", + "//snow/validators/validatorstest", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//vms/rpcchainvm/grpcutils", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/validators/validatorsmock/BUILD.bazel b/snow/validators/validatorsmock/BUILD.bazel new file mode 100644 index 000000000000..c983c4bb9131 --- /dev/null +++ b/snow/validators/validatorsmock/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "validatorsmock", + srcs = ["state.go"], + importpath = "github.com/ava-labs/avalanchego/snow/validators/validatorsmock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/validators", + "@org_uber_go_mock//gomock", + ], +) diff --git a/snow/validators/validatorstest/BUILD.bazel b/snow/validators/validatorstest/BUILD.bazel new file mode 100644 index 000000000000..c74d6b85ff65 --- /dev/null +++ b/snow/validators/validatorstest/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "validatorstest", + srcs = [ + "state.go", + "warp.go", + ], + importpath = "github.com/ava-labs/avalanchego/snow/validators/validatorstest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/validators", + "//utils", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "@com_github_stretchr_testify//require", + ], +) diff --git a/staking/BUILD.bazel b/staking/BUILD.bazel new file mode 100644 index 000000000000..5431240f8b31 --- /dev/null +++ b/staking/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "staking", + srcs = [ + "asn1.go", + "certificate.go", + "parse.go", + "tls.go", + "verify.go", + ], + importpath = "github.com/ava-labs/avalanchego/staking", + visibility = ["//visibility:public"], + deps = [ + "//utils/perms", + "//utils/units", + "@org_golang_x_crypto//cryptobyte", + "@org_golang_x_crypto//cryptobyte/asn1", + ], +) + +go_test( + name = "staking_test", + srcs = [ + "parse_test.go", + "tls_test.go", + "verify_test.go", + ], + embed = [":staking"], + embedsrcs = ["large_rsa_key.cert"], + deps = [ + "//utils/hashing", + "@com_github_stretchr_testify//require", + ], +) diff --git a/subnets/BUILD.bazel b/subnets/BUILD.bazel new file mode 100644 index 000000000000..09429f3c0daa --- /dev/null +++ b/subnets/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "subnets", + srcs = [ + "config.go", + "no_op_allower.go", + "subnet.go", + ], + importpath = "github.com/ava-labs/avalanchego/subnets", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/consensus/snowball", + "//snow/engine/common", + "//utils/set", + ], +) + +go_test( + name = "subnets_test", + srcs = [ + "config_test.go", + "subnet_test.go", + ], + embed = [":subnets"], + deps = [ + "//ids", + "//snow/consensus/snowball", + "//utils/set", + "@com_github_stretchr_testify//require", + ], +) diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel new file mode 100644 index 000000000000..b5fc8daec0d6 --- /dev/null +++ b/tests/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "tests", + srcs = [ + "context_helpers.go", + "log.go", + "metrics.go", + "notify_context.go", + "prometheus_server.go", + "simple_test_context.go", + "test_context.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests", + visibility = ["//visibility:public"], + deps = [ + "//api/metrics", + "//utils/logging", + "//wallet/subnet/primary/common", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/promhttp", + "@com_github_prometheus_client_model//go", + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/antithesis/BUILD.bazel b/tests/antithesis/BUILD.bazel new file mode 100644 index 000000000000..7859abb5529d --- /dev/null +++ b/tests/antithesis/BUILD.bazel @@ -0,0 +1,29 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "antithesis", + srcs = [ + "compose.go", + "config.go", + "context.go", + "init_db.go", + "node_health.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests/antithesis", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//config", + "//tests", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//utils/constants", + "//utils/logging", + "//utils/perms", + "@com_github_antithesishq_antithesis_sdk_go//assert", + "@com_github_compose_spec_compose_go//types", + "@com_github_stretchr_testify//require", + "@in_gopkg_yaml_v3//:yaml_v3", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/antithesis/avalanchego/BUILD.bazel b/tests/antithesis/avalanchego/BUILD.bazel new file mode 100644 index 000000000000..70507b41575f --- /dev/null +++ b/tests/antithesis/avalanchego/BUILD.bazel @@ -0,0 +1,44 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "avalanchego_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/tests/antithesis/avalanchego", + visibility = ["//visibility:private"], + deps = [ + "//database", + "//genesis", + "//ids", + "//tests", + "//tests/antithesis", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/logging", + "//utils/set", + "//utils/timer", + "//utils/units", + "//vms/avm", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm", + "//vms/platformvm/txs", + "//vms/propertyfx", + "//vms/secp256k1fx", + "//wallet/chain/x/builder", + "//wallet/subnet/primary", + "//wallet/subnet/primary/common", + "@com_github_antithesishq_antithesis_sdk_go//assert", + "@com_github_antithesishq_antithesis_sdk_go//lifecycle", + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + ], +) + +go_binary( + name = "avalanchego", + embed = [":avalanchego_lib"], + visibility = ["//visibility:public"], +) diff --git a/tests/antithesis/avalanchego/gencomposeconfig/BUILD.bazel b/tests/antithesis/avalanchego/gencomposeconfig/BUILD.bazel new file mode 100644 index 000000000000..f13e2a08da22 --- /dev/null +++ b/tests/antithesis/avalanchego/gencomposeconfig/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "gencomposeconfig_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/tests/antithesis/avalanchego/gencomposeconfig", + visibility = ["//visibility:private"], + deps = [ + "//tests", + "//tests/antithesis", + "//tests/fixture/tmpnet", + "@org_uber_go_zap//:zap", + ], +) + +go_binary( + name = "gencomposeconfig", + embed = [":gencomposeconfig_lib"], + visibility = ["//visibility:public"], +) diff --git a/tests/antithesis/xsvm/BUILD.bazel b/tests/antithesis/xsvm/BUILD.bazel new file mode 100644 index 000000000000..8114bf0a4e5c --- /dev/null +++ b/tests/antithesis/xsvm/BUILD.bazel @@ -0,0 +1,34 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "xsvm_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/tests/antithesis/xsvm", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//tests", + "//tests/antithesis", + "//tests/fixture/subnet", + "//tests/fixture/tmpnet", + "//utils/crypto/secp256k1", + "//utils/logging", + "//utils/set", + "//utils/timer", + "//utils/units", + "//vms/example/xsvm/api", + "//vms/example/xsvm/cmd/issue/status", + "//vms/example/xsvm/cmd/issue/transfer", + "@com_github_antithesishq_antithesis_sdk_go//assert", + "@com_github_antithesishq_antithesis_sdk_go//lifecycle", + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + ], +) + +go_binary( + name = "xsvm", + embed = [":xsvm_lib"], + visibility = ["//visibility:public"], +) diff --git a/tests/antithesis/xsvm/gencomposeconfig/BUILD.bazel b/tests/antithesis/xsvm/gencomposeconfig/BUILD.bazel new file mode 100644 index 000000000000..a74889ed5e30 --- /dev/null +++ b/tests/antithesis/xsvm/gencomposeconfig/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "gencomposeconfig_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/tests/antithesis/xsvm/gencomposeconfig", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//tests", + "//tests/antithesis", + "//tests/fixture/subnet", + "//tests/fixture/tmpnet", + "@org_uber_go_zap//:zap", + ], +) + +go_binary( + name = "gencomposeconfig", + embed = [":gencomposeconfig_lib"], + visibility = ["//visibility:public"], +) diff --git a/tests/e2e/BUILD.bazel b/tests/e2e/BUILD.bazel new file mode 100644 index 000000000000..e846562cfb1d --- /dev/null +++ b/tests/e2e/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "e2e", + srcs = ["ignore.go"], + importpath = "github.com/ava-labs/avalanchego/tests/e2e", + visibility = ["//visibility:public"], +) + +go_test( + name = "e2e_test", + srcs = ["e2e_test.go"], + deps = [ + "//config", + "//graft/coreth/plugin/evm", + "//tests/e2e/banff", + "//tests/e2e/c", + "//tests/e2e/faultinjection", + "//tests/e2e/p", + "//tests/e2e/vms", + "//tests/e2e/x", + "//tests/e2e/x/transfer", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//upgrade/upgradetest", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/e2e/banff/BUILD.bazel b/tests/e2e/banff/BUILD.bazel new file mode 100644 index 000000000000..aaebba669e06 --- /dev/null +++ b/tests/e2e/banff/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "banff", + srcs = ["suites.go"], + importpath = "github.com/ava-labs/avalanchego/tests/e2e/banff", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//tests", + "//tests/fixture/e2e", + "//utils/constants", + "//utils/units", + "//vms/components/avax", + "//vms/components/verify", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + ], +) diff --git a/tests/e2e/c/BUILD.bazel b/tests/e2e/c/BUILD.bazel new file mode 100644 index 000000000000..55bd7cebecd6 --- /dev/null +++ b/tests/e2e/c/BUILD.bazel @@ -0,0 +1,42 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "c", + srcs = [ + "api.go", + "consume_gas.go", + "dynamic_fees.go", + "interchain_workflow.go", + "proposervm_epoch.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests/e2e/c", + visibility = ["//visibility:public"], + deps = [ + "//api/connectclient", + "//api/info", + "//connectproto/pb/proposervm", + "//connectproto/pb/proposervm/proposervmconnect", + "//graft/coreth/ethclient", + "//graft/coreth/plugin/evm/upgrade/cortina", + "//ids", + "//tests", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/set", + "//utils/units", + "//vms/evm/acp176", + "//vms/proposervm", + "//vms/secp256k1fx", + "//wallet/subnet/primary/common", + "@com_connectrpc_connect//:connect", + "@com_github_ava_labs_libevm//accounts/abi", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//params", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/e2e/faultinjection/BUILD.bazel b/tests/e2e/faultinjection/BUILD.bazel new file mode 100644 index 000000000000..d3d4fd90b51f --- /dev/null +++ b/tests/e2e/faultinjection/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "faultinjection", + srcs = ["duplicate_node_id.go"], + importpath = "github.com/ava-labs/avalanchego/tests/e2e/faultinjection", + visibility = ["//visibility:public"], + deps = [ + "//api/info", + "//config", + "//ids", + "//tests", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//utils/set", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + ], +) diff --git a/tests/e2e/p/BUILD.bazel b/tests/e2e/p/BUILD.bazel new file mode 100644 index 000000000000..0c4792c54d52 --- /dev/null +++ b/tests/e2e/p/BUILD.bazel @@ -0,0 +1,61 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "p", + srcs = [ + "interchain_workflow.go", + "l1.go", + "owner_retrieval.go", + "staking_rewards.go", + "validator_sets.go", + "workflow.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests/e2e/p", + visibility = ["//visibility:public"], + deps = [ + "//api/admin", + "//api/info", + "//config", + "//genesis", + "//ids", + "//message", + "//network/p2p", + "//network/peer", + "//proto/pb/p2p", + "//proto/pb/platformvm", + "//proto/pb/sdk", + "//snow/networking/router", + "//snow/validators", + "//tests", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//utils", + "//utils/buffer", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/set", + "//utils/units", + "//vms/components/avax", + "//vms/example/xsvm/genesis", + "//vms/platformvm", + "//vms/platformvm/api", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/txs", + "//vms/platformvm/validators", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/proposervm", + "//vms/secp256k1fx", + "//wallet/subnet/primary/common", + "@com_github_mitchellh_mapstructure//:mapstructure", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/e2e/vms/BUILD.bazel b/tests/e2e/vms/BUILD.bazel new file mode 100644 index 000000000000..ed5ce99c8469 --- /dev/null +++ b/tests/e2e/vms/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "vms", + srcs = ["xsvm.go"], + importpath = "github.com/ava-labs/avalanchego/tests/e2e/vms", + visibility = ["//visibility:public"], + deps = [ + "//api/connectclient", + "//connectproto/pb/xsvm", + "//connectproto/pb/xsvm/xsvmconnect", + "//ids", + "//tests/fixture/e2e", + "//tests/fixture/subnet", + "//tests/fixture/tmpnet", + "//utils/crypto/secp256k1", + "//utils/units", + "//vms/example/xsvm/api", + "//vms/example/xsvm/cmd/issue/export", + "//vms/example/xsvm/cmd/issue/importtx", + "//vms/example/xsvm/cmd/issue/transfer", + "@com_connectrpc_connect//:connect", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + "@org_golang_x_sync//errgroup", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/e2e/x/BUILD.bazel b/tests/e2e/x/BUILD.bazel new file mode 100644 index 000000000000..255a845ad0db --- /dev/null +++ b/tests/e2e/x/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "x", + srcs = ["interchain_workflow.go"], + importpath = "github.com/ava-labs/avalanchego/tests/e2e/x", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//tests/fixture/e2e", + "//utils/constants", + "//utils/set", + "//utils/units", + "//vms/components/avax", + "//vms/secp256k1fx", + "//wallet/subnet/primary/common", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + ], +) diff --git a/tests/e2e/x/transfer/BUILD.bazel b/tests/e2e/x/transfer/BUILD.bazel new file mode 100644 index 000000000000..61423d62f143 --- /dev/null +++ b/tests/e2e/x/transfer/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "transfer", + srcs = ["virtuous.go"], + importpath = "github.com/ava-labs/avalanchego/tests/e2e/x/transfer", + visibility = ["//visibility:public"], + deps = [ + "//chains", + "//ids", + "//tests", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//utils/crypto/secp256k1", + "//utils/set", + "//utils/units", + "//vms/avm", + "//vms/components/avax", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + "//wallet/subnet/primary/common", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/fixture/bootstrapmonitor/BUILD.bazel b/tests/fixture/bootstrapmonitor/BUILD.bazel new file mode 100644 index 000000000000..cc84d53112dd --- /dev/null +++ b/tests/fixture/bootstrapmonitor/BUILD.bazel @@ -0,0 +1,42 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bootstrapmonitor", + srcs = [ + "bootstrap_test_config.go", + "common.go", + "init.go", + "wait.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests/fixture/bootstrapmonitor", + visibility = ["//visibility:public"], + deps = [ + "//chains", + "//config", + "//tests/fixture/tmpnet", + "//tests/fixture/tmpnet/flags", + "//utils/logging", + "//utils/perms", + "//version", + "@com_github_spf13_cast//:cast", + "@io_k8s_api//core/v1:core", + "@io_k8s_apimachinery//pkg/apis/meta/v1:meta", + "@io_k8s_apimachinery//pkg/types", + "@io_k8s_apimachinery//pkg/util/wait", + "@io_k8s_client_go//kubernetes", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "bootstrapmonitor_test", + srcs = ["bootstrap_test_config_test.go"], + embed = [":bootstrapmonitor"], + deps = [ + "//chains", + "//version", + "@com_github_stretchr_testify//require", + "@io_k8s_api//core/v1:core", + "@io_k8s_apimachinery//pkg/apis/meta/v1:meta", + ], +) diff --git a/tests/fixture/bootstrapmonitor/cmd/BUILD.bazel b/tests/fixture/bootstrapmonitor/cmd/BUILD.bazel new file mode 100644 index 000000000000..f939328319de --- /dev/null +++ b/tests/fixture/bootstrapmonitor/cmd/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "cmd_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/tests/fixture/bootstrapmonitor/cmd", + visibility = ["//visibility:private"], + deps = [ + "//tests/fixture/bootstrapmonitor", + "//utils/logging", + "//version", + "@com_github_spf13_cobra//:cobra", + ], +) + +go_binary( + name = "cmd", + embed = [":cmd_lib"], + visibility = ["//visibility:public"], +) diff --git a/tests/fixture/bootstrapmonitor/e2e/BUILD.bazel b/tests/fixture/bootstrapmonitor/e2e/BUILD.bazel new file mode 100644 index 000000000000..3dd09b74d966 --- /dev/null +++ b/tests/fixture/bootstrapmonitor/e2e/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_test") + +go_test( + name = "e2e_test", + srcs = ["e2e_test.go"], + deps = [ + "//config", + "//ids", + "//tests", + "//tests/fixture/bootstrapmonitor", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//tests/fixture/tmpnet/flags", + "//utils/constants", + "//utils/logging", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + "@io_k8s_api//apps/v1:apps", + "@io_k8s_api//core/v1:core", + "@io_k8s_api//rbac/v1:rbac", + "@io_k8s_apimachinery//pkg/api/errors", + "@io_k8s_apimachinery//pkg/apis/meta/v1:meta", + "@io_k8s_client_go//kubernetes", + "@io_k8s_client_go//rest", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/fixture/e2e/BUILD.bazel b/tests/fixture/e2e/BUILD.bazel new file mode 100644 index 000000000000..57a94c266f3a --- /dev/null +++ b/tests/fixture/e2e/BUILD.bazel @@ -0,0 +1,38 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "e2e", + srcs = [ + "apitest.go", + "describe.go", + "env.go", + "flags.go", + "ginkgo_test_context.go", + "helpers.go", + "metrics_link.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests/fixture/e2e", + visibility = ["//visibility:public"], + deps = [ + "//config", + "//graft/coreth/ethclient", + "//ids", + "//tests", + "//tests/fixture/tmpnet", + "//tests/fixture/tmpnet/flags", + "//utils/crypto/secp256k1", + "//utils/logging", + "//vms/platformvm/txs/fee", + "//vms/secp256k1fx", + "//wallet/chain/p/builder", + "//wallet/subnet/primary", + "//wallet/subnet/primary/common", + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//core/types", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_spf13_cast//:cast", + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + "@org_uber_go_zap//zapcore", + ], +) diff --git a/tests/fixture/stacktrace/BUILD.bazel b/tests/fixture/stacktrace/BUILD.bazel new file mode 100644 index 000000000000..dfe90ae162b5 --- /dev/null +++ b/tests/fixture/stacktrace/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "stacktrace", + srcs = ["stacktrace.go"], + importpath = "github.com/ava-labs/avalanchego/tests/fixture/stacktrace", + visibility = ["//visibility:public"], +) diff --git a/tests/fixture/subnet/BUILD.bazel b/tests/fixture/subnet/BUILD.bazel new file mode 100644 index 000000000000..47685e96904d --- /dev/null +++ b/tests/fixture/subnet/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "subnet", + srcs = ["xsvm.go"], + importpath = "github.com/ava-labs/avalanchego/tests/fixture/subnet", + visibility = ["//visibility:public"], + deps = [ + "//tests/fixture/tmpnet", + "//utils/constants", + "//utils/crypto/secp256k1", + "//vms/example/xsvm/genesis", + ], +) diff --git a/tests/fixture/tmpnet/BUILD.bazel b/tests/fixture/tmpnet/BUILD.bazel new file mode 100644 index 000000000000..60aa72a85b64 --- /dev/null +++ b/tests/fixture/tmpnet/BUILD.bazel @@ -0,0 +1,99 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "tmpnet", + srcs = [ + "check_monitoring.go", + "defaults.go", + "detached_process_default.go", + "flagsmap.go", + "genesis.go", + "kube.go", + "kube_runtime.go", + "local_network.go", + "monitor_kube.go", + "monitor_processes.go", + "network.go", + "network_config.go", + "node.go", + "node_config.go", + "process_runtime.go", + "start_kind_cluster.go", + "subnet.go", + "utils.go", + ], + embedsrcs = [ + "yaml/prometheus-agent.yaml", + "yaml/promtail-daemonset.yaml", + "yaml/tmpnet-rbac.yaml", + ], + importpath = "github.com/ava-labs/avalanchego/tests/fixture/tmpnet", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//api/info", + "//chains", + "//config", + "//config/node", + "//genesis", + "//ids", + "//staking", + "//tests/fixture/stacktrace", + "//upgrade", + "//utils/constants", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/formatting/address", + "//utils/logging", + "//utils/perms", + "//utils/rpc", + "//utils/set", + "//utils/units", + "//vms/platformvm", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/txs", + "//vms/platformvm/txs/executor", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + "//wallet/subnet/primary/common", + "@com_github_ava_labs_libevm//core", + "@com_github_ava_labs_libevm//params", + "@com_github_google_uuid//:uuid", + "@com_github_prometheus_client_golang//api", + "@com_github_prometheus_client_golang//api/prometheus/v1:prometheus", + "@com_github_prometheus_common//model", + "@io_k8s_api//apps/v1:apps", + "@io_k8s_api//authentication/v1:authentication", + "@io_k8s_api//core/v1:core", + "@io_k8s_api//networking/v1:networking", + "@io_k8s_apimachinery//pkg/api/errors", + "@io_k8s_apimachinery//pkg/api/resource", + "@io_k8s_apimachinery//pkg/apis/meta/v1:meta", + "@io_k8s_apimachinery//pkg/apis/meta/v1/unstructured", + "@io_k8s_apimachinery//pkg/runtime/schema", + "@io_k8s_apimachinery//pkg/runtime/serializer/yaml", + "@io_k8s_apimachinery//pkg/types", + "@io_k8s_apimachinery//pkg/util/intstr", + "@io_k8s_apimachinery//pkg/util/wait", + "@io_k8s_client_go//dynamic", + "@io_k8s_client_go//kubernetes", + "@io_k8s_client_go//rest", + "@io_k8s_client_go//tools/clientcmd", + "@io_k8s_client_go//tools/clientcmd/api", + "@io_k8s_client_go//tools/portforward", + "@io_k8s_client_go//transport/spdy", + "@io_k8s_utils//ptr", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "tmpnet_test", + srcs = ["network_test.go"], + embed = [":tmpnet"], + deps = [ + "//utils/logging", + "@com_github_stretchr_testify//require", + ], +) diff --git a/tests/fixture/tmpnet/flags/BUILD.bazel b/tests/fixture/tmpnet/flags/BUILD.bazel new file mode 100644 index 000000000000..28761be518f9 --- /dev/null +++ b/tests/fixture/tmpnet/flags/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "flags", + srcs = [ + "collector.go", + "common.go", + "kube_runtime.go", + "kubeconfig.go", + "process_runtime.go", + "runtime.go", + "start_network.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests/fixture/tmpnet/flags", + visibility = ["//visibility:public"], + deps = [ + "//tests/fixture/stacktrace", + "//tests/fixture/tmpnet", + "@com_github_spf13_cast//:cast", + "@com_github_spf13_pflag//:pflag", + ], +) diff --git a/tests/fixture/tmpnet/tmpnetctl/BUILD.bazel b/tests/fixture/tmpnet/tmpnetctl/BUILD.bazel new file mode 100644 index 000000000000..83797e526076 --- /dev/null +++ b/tests/fixture/tmpnet/tmpnetctl/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "tmpnetctl_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/tests/fixture/tmpnet/tmpnetctl", + visibility = ["//visibility:private"], + deps = [ + "//tests", + "//tests/fixture/stacktrace", + "//tests/fixture/tmpnet", + "//tests/fixture/tmpnet/flags", + "//utils/logging", + "//version", + "@com_github_spf13_cobra//:cobra", + "@org_uber_go_zap//:zap", + ], +) + +go_binary( + name = "tmpnetctl", + embed = [":tmpnetctl_lib"], + visibility = ["//visibility:public"], +) diff --git a/tests/load/BUILD.bazel b/tests/load/BUILD.bazel new file mode 100644 index 000000000000..7219a70bd5d6 --- /dev/null +++ b/tests/load/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "load", + srcs = [ + "generator.go", + "metrics.go", + "tests.go", + "wallet.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests/load", + visibility = ["//visibility:public"], + deps = [ + "//tests", + "//tests/load/contracts", + "//utils/logging", + "//utils/sampler", + "@com_github_ava_labs_libevm//accounts/abi/bind", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethclient", + "@com_github_ava_labs_libevm//params", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_x_sync//errgroup", + ], +) diff --git a/tests/load/contracts/BUILD.bazel b/tests/load/contracts/BUILD.bazel new file mode 100644 index 000000000000..38e74c855081 --- /dev/null +++ b/tests/load/contracts/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "contracts", + srcs = [ + "ERC20.bindings.go", + "LoadSimulator.bindings.go", + "TrieStressTest.bindings.go", + "generate.go", + ], + importpath = "github.com/ava-labs/avalanchego/tests/load/contracts", + visibility = ["//visibility:public"], + deps = [ + "@com_github_ava_labs_libevm//:libevm", + "@com_github_ava_labs_libevm//accounts/abi", + "@com_github_ava_labs_libevm//accounts/abi/bind", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//event", + ], +) diff --git a/tests/load/main/BUILD.bazel b/tests/load/main/BUILD.bazel new file mode 100644 index 000000000000..0a5346665ec2 --- /dev/null +++ b/tests/load/main/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "main_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/tests/load/main", + visibility = ["//visibility:private"], + deps = [ + "//tests", + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//tests/load", + "//tests/load/contracts", + "@com_github_ava_labs_libevm//accounts/abi/bind", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_libevm//crypto", + "@com_github_ava_labs_libevm//ethclient", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_x_exp//maps", + ], +) + +go_binary( + name = "main", + embed = [":main_lib"], + visibility = ["//visibility:public"], +) diff --git a/tests/reexecute/c/BUILD.bazel b/tests/reexecute/c/BUILD.bazel new file mode 100644 index 000000000000..1b2664491125 --- /dev/null +++ b/tests/reexecute/c/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_go//go:def.bzl", "go_test") + +go_test( + name = "c_test", + srcs = ["vm_reexecute_test.go"], + deps = [ + "//api/metrics", + "//chains/atomic", + "//database", + "//database/leveldb", + "//database/prefixdb", + "//genesis", + "//graft/coreth/plugin/evm", + "//graft/coreth/plugin/factory", + "//ids", + "//snow", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/validators/validatorstest", + "//tests", + "//tests/fixture/tmpnet", + "//upgrade", + "//utils/constants", + "//utils/crypto/bls/signer/localsigner", + "//utils/logging", + "//utils/timer", + "//utils/units", + "//vms/metervm", + "//vms/platformvm/warp", + "@com_github_google_uuid//:uuid", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + ], +) diff --git a/tests/upgrade/BUILD.bazel b/tests/upgrade/BUILD.bazel new file mode 100644 index 000000000000..93987f0a6e60 --- /dev/null +++ b/tests/upgrade/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_test") + +go_test( + name = "upgrade_test", + srcs = ["upgrade_test.go"], + deps = [ + "//tests/fixture/e2e", + "//tests/fixture/tmpnet", + "//tests/fixture/tmpnet/flags", + "@com_github_onsi_ginkgo_v2//:ginkgo", + "@com_github_stretchr_testify//require", + ], +) diff --git a/tools/bazel/workspace_status.sh b/tools/bazel/workspace_status.sh new file mode 100755 index 000000000000..c32816da11ef --- /dev/null +++ b/tools/bazel/workspace_status.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Workspace status script for Bazel +# Provides build metadata for version injection + +# Stable status (cached, won't trigger rebuilds on change) +echo "STABLE_GIT_COMMIT $(git rev-parse HEAD 2>/dev/null || echo unknown)" +echo "STABLE_GIT_BRANCH $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)" + +# Volatile status (changes trigger rebuilds but only for rules that use them) +echo "BUILD_TIMESTAMP $(date -u +%Y-%m-%dT%H:%M:%SZ)" diff --git a/trace/BUILD.bazel b/trace/BUILD.bazel new file mode 100644 index 000000000000..01fc3e838280 --- /dev/null +++ b/trace/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "trace", + srcs = [ + "exporter.go", + "exporter_type.go", + "noop.go", + "tracer.go", + ], + importpath = "github.com/ava-labs/avalanchego/trace", + visibility = ["//visibility:public"], + deps = [ + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel//semconv/v1.4.0:v1_4_0", + "@io_opentelemetry_go_otel_exporters_otlp_otlptrace//:otlptrace", + "@io_opentelemetry_go_otel_exporters_otlp_otlptrace_otlptracegrpc//:otlptracegrpc", + "@io_opentelemetry_go_otel_exporters_otlp_otlptrace_otlptracehttp//:otlptracehttp", + "@io_opentelemetry_go_otel_sdk//resource", + "@io_opentelemetry_go_otel_sdk//trace", + "@io_opentelemetry_go_otel_trace//:trace", + "@io_opentelemetry_go_otel_trace//noop", + ], +) + +go_test( + name = "trace_test", + srcs = ["exporter_type_test.go"], + embed = [":trace"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/updated-plan.md b/updated-plan.md new file mode 100644 index 000000000000..05a57a1f694c --- /dev/null +++ b/updated-plan.md @@ -0,0 +1,594 @@ +# Bazel Integration Execution Plan for avalanchego + +## Background Context + +### Repository Overview +- **Repository**: avalanchego - Avalanche network node implementation +- **Branch**: maru/bazel +- **Main module**: `github.com/ava-labs/avalanchego` (BSD-3 license) at repository root +- **Coreth module**: `github.com/ava-labs/avalanchego/graft/coreth` (LGPL-3 license) at `graft/coreth/` +- **Go version**: 1.24.9 (security-critical, must be exact) + +### Why Bazel? +The repository is evolving into a multi-language monorepo: +1. Currently: Two Go modules (avalanchego + coreth) with circular dependencies +2. Coming: Another Go module +3. Future: Rust dependency (Firewood) + +Bazel enables: +- Targeted CI/builds (don't rebuild the world for every change) +- Multi-language support (Go now, Rust later) +- Shared toolchain management via rules_nixpkgs + +### Current Build System +- **Nix flake** (`flake.nix`) provides development environment +- **Task runner** (`Taskfile.yml`) orchestrates builds via shell scripts +- **Go SDK** defined in `nix/go/default.nix` with explicit version and SHA256s +- **No existing Bazel** - this plan creates it from scratch + +### Key Files to Reference +- `flake.nix` - Nix development environment (lines 37-77 have package list) +- `nix/go/default.nix` - Custom Go 1.24.9 derivation with SHA256 checksums +- `nix/go/flake.nix` - Flake wrapper for Go derivation +- `go.mod` - Main module definition with replace directive for coreth +- `graft/coreth/go.mod` - Coreth module with reverse replace directive +- `Taskfile.yml` - Task definitions +- `scripts/build.sh` - Current build script (CGO flags, ldflags) + +--- + +## Execution Strategy + +### Approach +- **Minimal first**: Build just avalanchego binary before expanding +- **Incremental**: Validate each step, commit on success +- **Single source of truth**: Go SDK from Nix via rules_nixpkgs (not duplicated) +- **Exclude coreth**: Defer circular dependency handling + +### Go SDK Strategy +Use `rules_nixpkgs_go` to source Go SDK from existing Nix derivation: +- Avoids duplicating Go version/checksums in Bazel config +- Future-proof for Rust (rules_nixpkgs_rust uses same pattern) +- Fallback to explicit SDK registration if rules_nixpkgs proves problematic + +--- + +## Step 1: Add Bazel to Nix Environment + +### Files to Modify +**`flake.nix`** - Add to the packages list (around line 37-77): + +```nix +# After "go-task" line, add: +bazel_7 # Bazel build system +buildifier # Bazel file formatter +``` + +### Full Context +Current packages section looks like: +```nix +packages = with pkgs; [ + git + go-task + # ... (add bazel_7 and buildifier here) +``` + +### Validation Commands +```bash +# Test Bazel is available +nix develop --command bazel version +# Should output: Build label: 7.x.x + +# Test buildifier is available +nix develop --command buildifier --version +# Should output version info +``` + +### Commit +Message: `Add Bazel and buildifier to nix development environment` + +--- + +## Step 2: Modify Nix Go Derivation for rules_go Compatibility + +### Why This Is Needed +`nixpkgs_go_configure` from rules_nixpkgs expects the Go SDK to have a `ROOT` marker file at the package root. This is how rules_go identifies the SDK root directory. + +### Files to Modify +**`nix/go/default.nix`** - Add ROOT marker in installPhase (around line 49-56): + +Current: +```nix +installPhase = '' + mkdir -p $out + tar xzf $src -C $out --strip-components=1 --no-same-owner --no-same-permissions + chmod +x $out/bin/go +''; +``` + +Change to: +```nix +installPhase = '' + mkdir -p $out + tar xzf $src -C $out --strip-components=1 --no-same-owner --no-same-permissions + chmod +x $out/bin/go + # ROOT marker required by rules_go/rules_nixpkgs for SDK identification + touch $out/ROOT +''; +``` + +### Validation Commands +```bash +# Build the Go derivation +nix build ./nix/go + +# Check ROOT file exists +ls $(nix build ./nix/go --print-out-paths 2>/dev/null)/ROOT +# Should show: /nix/store/.../ROOT + +# Verify Go still works +$(nix build ./nix/go --print-out-paths 2>/dev/null)/bin/go version +# Should show: go version go1.24.9 ... +``` + +### Commit +Message: `Add ROOT marker to Go derivation for Bazel compatibility` + +--- + +## Step 3: Initialize Bazel Workspace with bzlmod + rules_nixpkgs + +### Files to Create + +#### **`MODULE.bazel`** (new file at repository root) +```python +"""Bazel module definition for avalanchego.""" + +module( + name = "avalanchego", + version = "0.0.0", +) + +# Core dependencies from Bazel Central Registry +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") +bazel_dep(name = "rules_go", version = "0.50.1") +bazel_dep(name = "gazelle", version = "0.39.1") + +# rules_nixpkgs for Nix integration +# Not in BCR, so we use git_override to fetch from GitHub +bazel_dep(name = "rules_nixpkgs_core", version = "0.13.0") +bazel_dep(name = "rules_nixpkgs_go", version = "0.13.0") + +git_override( + module_name = "rules_nixpkgs_core", + remote = "https://github.com/tweag/rules_nixpkgs.git", + # TODO: Pin to specific commit after initial testing + # Find latest: git ls-remote https://github.com/tweag/rules_nixpkgs.git HEAD + commit = "REPLACE_WITH_ACTUAL_COMMIT_SHA", + strip_prefix = "core", +) + +git_override( + module_name = "rules_nixpkgs_go", + remote = "https://github.com/tweag/rules_nixpkgs.git", + commit = "REPLACE_WITH_ACTUAL_COMMIT_SHA", # Same commit as above + strip_prefix = "toolchains/go", +) + +# Configure Go SDK from Nix derivation +# This ensures Bazel uses the exact same Go version as nix develop +nixpkgs_go = use_extension( + "@rules_nixpkgs_go//:extensions.bzl", + "nixpkgs_go", +) +nixpkgs_go.toolchain( + nix_file = "//nix/go:bazel.nix", + nix_file_deps = ["//nix/go:default.nix"], +) +use_repo(nixpkgs_go, "go_toolchains") + +register_toolchains("@go_toolchains//:all") + +# Go dependencies from go.mod +go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps") +go_deps.from_file(go_mod = "//:go.mod") +use_repo( + go_deps, + # Will be populated by gazelle +) +``` + +**Important**: Before creating this file, get the actual commit SHA: +```bash +git ls-remote https://github.com/tweag/rules_nixpkgs.git HEAD +# Use the commit SHA in both git_override blocks +``` + +#### **`nix/go/bazel.nix`** (new file) +```nix +# Bazel wrapper for Go SDK +# Called by rules_nixpkgs_go to build the Go toolchain +# +# This file re-uses the same Go derivation as nix develop, +# ensuring version consistency between Nix and Bazel environments. +{ pkgs ? import {} }: +import ./default.nix { inherit pkgs; } +``` + +#### **`nix/go/BUILD.bazel`** (new file) +```python +# Make nix files visible to Bazel +exports_files([ + "bazel.nix", + "default.nix", +]) +``` + +#### **`.bazelrc`** (new file at repository root) +``` +# Bazel configuration for avalanchego + +# Enable bzlmod (default in Bazel 7+, explicit for clarity) +common --enable_bzlmod + +# Build settings +build --incompatible_enable_cc_toolchain_resolution + +# CGO flags for BLST cryptography library +# Must match scripts/build.sh: CGO_CFLAGS="-O2 -D__BLST_PORTABLE__" +build --action_env=CGO_CFLAGS=-O2 -D__BLST_PORTABLE__ +build --action_env=CGO_ENABLED=1 + +# Test settings +test --test_output=errors + +# Performance +build --jobs=auto + +# Nix integration - allow network for nix-build +# This may need adjustment based on your Bazel sandbox configuration +build --sandbox_add_mount_pair=/nix + +# Version injection (added in Step 6) +# build --workspace_status_command=tools/bazel/workspace_status.sh +``` + +#### **`.bazelignore`** (new file at repository root) +``` +# Directories to exclude from Bazel's file watching +.git +node_modules +.avalanchego +build +.direnv +result +``` + +### Validation Commands +```bash +# Verify Bazel recognizes the workspace +nix develop --command bazel version +# Should show version without errors about missing workspace + +# Verify module resolution (may take time on first run) +nix develop --command bazel mod deps +# Should show dependency tree including rules_go, gazelle, rules_nixpkgs +``` + +### Commit +Message: `Initialize Bazel workspace with rules_nixpkgs Go integration` + +--- + +## Step 4: Configure Gazelle and Generate Root BUILD + +### Files to Create + +#### **`BUILD.bazel`** (new file at repository root) +```python +load("@gazelle//:def.bzl", "gazelle") + +# Gazelle configuration +# gazelle:prefix github.com/ava-labs/avalanchego +# gazelle:exclude graft/coreth +# gazelle:exclude .git +# gazelle:exclude build +# gazelle:exclude .direnv + +gazelle(name = "gazelle") + +# Target to update external Go dependencies +gazelle( + name = "gazelle-update-repos", + args = [ + "-from_file=go.mod", + "-to_macro=deps.bzl%go_dependencies", + "-prune", + ], + command = "update-repos", +) +``` + +### Why Exclude graft/coreth +The main module and coreth have circular `replace` directives: +- `go.mod`: `replace github.com/ava-labs/avalanchego/graft/coreth => ./graft/coreth` +- `graft/coreth/go.mod`: `replace github.com/ava-labs/avalanchego => ../../` + +Handling this in Bazel requires careful configuration. For the minimal-first approach, we exclude coreth and focus on building avalanchego without coreth dependencies. + +### Validation Commands +```bash +# Run gazelle to generate BUILD files +nix develop --command bazel run //:gazelle + +# Check that BUILD.bazel files were created +find . -name "BUILD.bazel" -not -path "./.git/*" | head -20 +# Should show BUILD.bazel files in various directories + +# Verify no BUILD files in graft/coreth +ls graft/coreth/BUILD.bazel 2>/dev/null +# Should not exist (excluded) +``` + +### Commit +Message: `Add root BUILD.bazel with Gazelle configuration` + +--- + +## Step 5: Generate BUILD Files and Fix Issues + +### Actions +1. Run Gazelle to generate BUILD files throughout the codebase +2. Attempt to build and fix issues iteratively + +### Common Issues and Fixes + +#### Issue: Missing CGO flags for specific packages +Some packages (especially crypto-related) may need explicit CGO configuration. + +Solution: Add to affected BUILD.bazel files: +```python +go_library( + name = "...", + # ... existing config ... + cgo = True, + copts = ["-O2", "-D__BLST_PORTABLE__"], +) +``` + +#### Issue: Replace directives not handled +Bazel doesn't automatically handle go.mod replace directives. + +Solution: For external dependencies, add to MODULE.bazel: +```python +go_deps.module( + path = "github.com/some/dependency", + sum = "h1:...", + version = "v1.2.3", + replace = "github.com/fork/dependency", +) +``` + +#### Issue: Test files with special requirements +Some test files may need to be excluded from the initial build. + +Solution: Add gazelle directives: +```python +# gazelle:exclude *_test.go +``` + +### Validation Commands +```bash +# Attempt build (will likely fail initially) +nix develop --command bazel build //cmd/avalanchego:all + +# If errors, fix and retry iteratively +# Check specific error messages and adjust BUILD files + +# Once individual fixes are applied, regenerate with gazelle +nix develop --command bazel run //:gazelle +``` + +### Commit +Message: `Generate initial BUILD files with Gazelle` + +--- + +## Step 6: Build avalanchego Binary with Version Injection + +### Files to Create/Modify + +#### **`tools/bazel/workspace_status.sh`** (new file) +```bash +#!/bin/bash +# Workspace status script for Bazel +# Provides variables that can be used in x_defs for version injection +# +# Usage: build --workspace_status_command=tools/bazel/workspace_status.sh +# Access in BUILD: x_defs = {"...version.GitCommit": "{STABLE_GIT_COMMIT}"} + +set -euo pipefail + +# Git commit hash - matches scripts/build.sh behavior +echo "STABLE_GIT_COMMIT $(git rev-parse HEAD 2>/dev/null || echo 'unknown')" + +# Optional: Add more status variables as needed +# echo "STABLE_BUILD_TIME $(date -u +%Y-%m-%dT%H:%M:%SZ)" +``` + +Make executable: +```bash +chmod +x tools/bazel/workspace_status.sh +mkdir -p tools/bazel +``` + +#### **`.bazelrc`** - Add workspace status command +Uncomment/add this line: +``` +build --workspace_status_command=tools/bazel/workspace_status.sh +``` + +#### **`cmd/avalanchego/BUILD.bazel`** - Modify generated file +After Gazelle generates this file, modify the `go_binary` target: + +```python +go_binary( + name = "avalanchego", + embed = [":avalanchego_lib"], + visibility = ["//visibility:public"], + # Version injection - matches scripts/build.sh ldflags + x_defs = { + "github.com/ava-labs/avalanchego/version.GitCommit": "{STABLE_GIT_COMMIT}", + }, +) +``` + +### Validation Commands +```bash +# Build the binary +nix develop --command bazel build //cmd/avalanchego + +# Find and run the binary +BINARY=$(nix develop --command bazel cquery --output=files //cmd/avalanchego 2>/dev/null) +$BINARY --version + +# Verify git commit is embedded +$BINARY --version | grep -i commit +# Should show the current git commit hash +``` + +### Commit +Message: `Configure avalanchego binary build with version injection` + +--- + +## Step 7: Add Task Wrapper + +### Files to Modify + +#### **`Taskfile.yml`** - Add Bazel tasks +Add after existing build tasks: + +```yaml + build-bazel: + desc: Builds avalanchego using Bazel + cmds: + - nix develop --command bazel build //cmd/avalanchego + sources: + - "**/*.go" + - "**/*.bazel" + - MODULE.bazel + - .bazelrc + + build-bazel-all: + desc: Builds all Bazel targets + cmds: + - nix develop --command bazel build //... + + gazelle: + desc: Updates BUILD.bazel files using Gazelle + cmds: + - nix develop --command bazel run //:gazelle + + check-gazelle: + desc: Verifies BUILD.bazel files are up-to-date + cmds: + - nix develop --command bazel run //:gazelle + - task: check-clean-branch +``` + +### Validation Commands +```bash +# Test the new task +task build-bazel +# Should build successfully + +# Verify original build still works +task build +# Should build successfully (no regression) + +# Compare binary sizes (should be similar, ±10%) +ls -la build/avalanchego +ls -la $(bazel cquery --output=files //cmd/avalanchego 2>/dev/null) +``` + +### Commit +Message: `Add Bazel build tasks to Taskfile` + +--- + +## Troubleshooting Guide + +### If rules_nixpkgs_go fails + +**Symptom**: Errors about missing extensions or module not found + +**Solution**: Fall back to explicit SDK registration. Replace the nixpkgs_go section in MODULE.bazel with: + +```python +# Fallback: Explicit Go SDK registration +# Uses same SHA256 checksums as nix/go/default.nix for identical binaries +go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk") +go_sdk.download( + name = "go_sdk", + version = "1.24.9", + sdks = { + # SHA256s from nix/go/default.nix lines 24-29 + "linux_amd64": ("go1.24.9.linux-amd64.tar.gz", "5b7899591c2dd6e9da1809fde4a2fad842c45d3f6b9deb235ba82216e31e34a6"), + "linux_arm64": ("go1.24.9.linux-arm64.tar.gz", "9aa1243d51d41e2f93e895c89c0a2daf7166768c4a4c3ac79db81029d295a540"), + "darwin_amd64": ("go1.24.9.darwin-amd64.tar.gz", "961aa2ae2b97e428d6d8991367e7c98cb403bac54276b8259aead42a0081591c"), + "darwin_arm64": ("go1.24.9.darwin-arm64.tar.gz", "af451b40651d7fb36db1bbbd9c66ddbed28b96d7da48abea50a19f82c6e9d1d6"), + }, +) +use_repo(go_sdk, "go_sdk") +``` + +### If Nix sandbox conflicts with Bazel + +**Symptom**: Errors about /nix not being accessible + +**Solution**: Add to `.bazelrc`: +``` +build --sandbox_add_mount_pair=/nix +# Or disable sandbox for specific actions: +build --spawn_strategy=local +``` + +### If circular dependency errors appear + +**Symptom**: Import cycle errors involving graft/coreth + +**Solution**: Ensure `# gazelle:exclude graft/coreth` is in root BUILD.bazel and re-run gazelle. + +--- + +## Success Criteria + +After completing all steps: + +1. ✅ `nix develop --command bazel build //cmd/avalanchego` produces working binary +2. ✅ Binary shows correct git commit in `--version` output +3. ✅ `task build-bazel` succeeds +4. ✅ Original `task build` still works (no regression) +5. ✅ All changes committed to `maru/bazel` branch + +--- + +## What's Deferred (Future Work) + +- **Coreth integration**: Handle circular dependencies with proper Bazel configuration +- **Code generation**: Protobuf, mocks, canoto via Bazel rules +- **Test execution**: `bazel test //...` +- **CI integration**: Remote caching, build event streaming +- **Rust/Firewood**: Add rules_nixpkgs_rust when Firewood is integrated + +--- + +## References + +- [rules_nixpkgs GitHub](https://github.com/tweag/rules_nixpkgs) +- [rules_go bzlmod docs](https://github.com/bazel-contrib/rules_go/blob/master/docs/go/core/bzlmod.md) +- [nix-bazel.build](https://nix-bazel.build/) +- [Bazel Central Registry - rules_nixpkgs_core](https://registry.bazel.build/modules/rules_nixpkgs_core) +- [Bazel git_override documentation](https://bazel.build/rules/lib/globals/module#git_override) diff --git a/upgrade/BUILD.bazel b/upgrade/BUILD.bazel new file mode 100644 index 000000000000..1462edceb914 --- /dev/null +++ b/upgrade/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "upgrade", + srcs = ["upgrade.go"], + importpath = "github.com/ava-labs/avalanchego/upgrade", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/constants", + ], +) + +go_test( + name = "upgrade_test", + srcs = ["upgrade_test.go"], + embed = [":upgrade"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/upgrade/upgradetest/BUILD.bazel b/upgrade/upgradetest/BUILD.bazel new file mode 100644 index 000000000000..02993d86546b --- /dev/null +++ b/upgrade/upgradetest/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "upgradetest", + srcs = [ + "config.go", + "fork.go", + ], + importpath = "github.com/ava-labs/avalanchego/upgrade/upgradetest", + visibility = ["//visibility:public"], + deps = ["//upgrade"], +) diff --git a/utils/BUILD.bazel b/utils/BUILD.bazel new file mode 100644 index 000000000000..08f3f9da3a9c --- /dev/null +++ b/utils/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "utils", + srcs = [ + "atomic.go", + "bytes.go", + "slice.go", + "sorting.go", + "stacktrace.go", + "zero.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils", + visibility = ["//visibility:public"], + deps = ["//utils/hashing"], +) + +go_test( + name = "utils_test", + srcs = [ + "atomic_test.go", + "bytes_test.go", + "slice_test.go", + "sorting_test.go", + ], + embed = [":utils"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/bag/BUILD.bazel b/utils/bag/BUILD.bazel new file mode 100644 index 000000000000..6e07b4522929 --- /dev/null +++ b/utils/bag/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bag", + srcs = [ + "bag.go", + "unique_bag.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/bag", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/set", + "@org_golang_x_exp//maps", + ], +) + +go_test( + name = "bag_test", + srcs = [ + "bag_benchmark_test.go", + "bag_test.go", + "unique_bag_test.go", + ], + embed = [":bag"], + deps = [ + "//utils/set", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/beacon/BUILD.bazel b/utils/beacon/BUILD.bazel new file mode 100644 index 000000000000..40f67abadfae --- /dev/null +++ b/utils/beacon/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "beacon", + srcs = [ + "beacon.go", + "set.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/beacon", + visibility = ["//visibility:public"], + deps = ["//ids"], +) + +go_test( + name = "beacon_test", + srcs = ["set_test.go"], + embed = [":beacon"], + deps = [ + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/bimap/BUILD.bazel b/utils/bimap/BUILD.bazel new file mode 100644 index 000000000000..c8c513848f31 --- /dev/null +++ b/utils/bimap/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bimap", + srcs = ["bimap.go"], + importpath = "github.com/ava-labs/avalanchego/utils/bimap", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "@org_golang_x_exp//maps", + ], +) + +go_test( + name = "bimap_test", + srcs = ["bimap_test.go"], + embed = [":bimap"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/bloom/BUILD.bazel b/utils/bloom/BUILD.bazel new file mode 100644 index 000000000000..19cf8cc61f3d --- /dev/null +++ b/utils/bloom/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bloom", + srcs = [ + "filter.go", + "hasher.go", + "metrics.go", + "optimal.go", + "read_filter.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/bloom", + visibility = ["//visibility:public"], + deps = ["@com_github_prometheus_client_golang//prometheus"], +) + +go_test( + name = "bloom_test", + srcs = [ + "filter_test.go", + "hasher_test.go", + "optimal_test.go", + "read_filter_test.go", + ], + embed = [":bloom"], + deps = [ + "//ids", + "//utils/units", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/buffer/BUILD.bazel b/utils/buffer/BUILD.bazel new file mode 100644 index 000000000000..f5e675a01b0d --- /dev/null +++ b/utils/buffer/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "buffer", + srcs = [ + "bounded_nonblocking_queue.go", + "unbounded_blocking_deque.go", + "unbounded_deque.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/buffer", + visibility = ["//visibility:public"], + deps = ["//utils"], +) + +go_test( + name = "buffer_test", + srcs = [ + "bounded_nonblocking_queue_test.go", + "unbounded_blocking_deque_test.go", + "unbounded_deque_test.go", + ], + embed = [":buffer"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/cb58/BUILD.bazel b/utils/cb58/BUILD.bazel new file mode 100644 index 000000000000..3b210858f2f3 --- /dev/null +++ b/utils/cb58/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "cb58", + srcs = ["cb58.go"], + importpath = "github.com/ava-labs/avalanchego/utils/cb58", + visibility = ["//visibility:public"], + deps = [ + "//utils/hashing", + "@com_github_mr_tron_base58//base58", + ], +) + +go_test( + name = "cb58_test", + srcs = ["cb58_test.go"], + embed = [":cb58"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/compression/BUILD.bazel b/utils/compression/BUILD.bazel new file mode 100644 index 000000000000..03fbb8237e8e --- /dev/null +++ b/utils/compression/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "compression", + srcs = [ + "compressor.go", + "no_compressor.go", + "type.go", + "zstd_compressor.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/compression", + visibility = ["//visibility:public"], + deps = ["@com_github_datadog_zstd//:zstd"], +) + +go_test( + name = "compression_test", + srcs = [ + "compressor_test.go", + "no_compressor_test.go", + "type_test.go", + ], + embed = [":compression"], + embedsrcs = ["zstd_zip_bomb.bin"], + deps = [ + "//utils", + "//utils/units", + "@com_github_datadog_zstd//:zstd", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/constants/BUILD.bazel b/utils/constants/BUILD.bazel new file mode 100644 index 000000000000..87ad75737614 --- /dev/null +++ b/utils/constants/BUILD.bazel @@ -0,0 +1,29 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "constants", + srcs = [ + "acps.go", + "aliases.go", + "application.go", + "memory.go", + "network_ids.go", + "networking.go", + "vm_ids.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/constants", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/compression", + "//utils/set", + "//utils/units", + ], +) + +go_test( + name = "constants_test", + srcs = ["network_ids_test.go"], + embed = [":constants"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/crypto/bls/BUILD.bazel b/utils/crypto/bls/BUILD.bazel new file mode 100644 index 000000000000..8fe7042f0a83 --- /dev/null +++ b/utils/crypto/bls/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "bls", + srcs = [ + "ciphersuite.go", + "public.go", + "signature.go", + "signer.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/crypto/bls", + visibility = ["//visibility:public"], + deps = ["@com_github_supranational_blst//bindings/go"], +) + +go_test( + name = "bls_test", + srcs = [ + "bls_benchmark_test.go", + "bls_test.go", + "public_test.go", + "signature_test.go", + ], + embed = [":bls"], + deps = [ + "//utils", + "//utils/crypto/bls/blstest", + "@com_github_stretchr_testify//require", + "@com_github_supranational_blst//bindings/go", + ], +) diff --git a/utils/crypto/bls/blstest/BUILD.bazel b/utils/crypto/bls/blstest/BUILD.bazel new file mode 100644 index 000000000000..15236a703e26 --- /dev/null +++ b/utils/crypto/bls/blstest/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "blstest", + srcs = ["benchmark.go"], + importpath = "github.com/ava-labs/avalanchego/utils/crypto/bls/blstest", + visibility = ["//visibility:public"], +) diff --git a/utils/crypto/bls/signer/localsigner/BUILD.bazel b/utils/crypto/bls/signer/localsigner/BUILD.bazel new file mode 100644 index 000000000000..822c8535954f --- /dev/null +++ b/utils/crypto/bls/signer/localsigner/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "localsigner", + srcs = ["localsigner.go"], + importpath = "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/localsigner", + visibility = ["//visibility:public"], + deps = [ + "//utils/crypto/bls", + "//utils/perms", + "@com_github_supranational_blst//bindings/go", + ], +) + +go_test( + name = "localsigner_test", + srcs = [ + "benchmark_test.go", + "bls_test.go", + "serialization_test.go", + ], + embed = [":localsigner"], + deps = [ + "//utils", + "//utils/crypto/bls", + "//utils/crypto/bls/blstest", + "@com_github_stretchr_testify//require", + "@com_github_supranational_blst//bindings/go", + ], +) diff --git a/utils/crypto/bls/signer/rpcsigner/BUILD.bazel b/utils/crypto/bls/signer/rpcsigner/BUILD.bazel new file mode 100644 index 000000000000..eac8b96ec7cf --- /dev/null +++ b/utils/crypto/bls/signer/rpcsigner/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "rpcsigner", + srcs = ["client.go"], + importpath = "github.com/ava-labs/avalanchego/utils/crypto/bls/signer/rpcsigner", + visibility = ["//visibility:public"], + deps = [ + "//proto/pb/signer", + "//utils/crypto/bls", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//backoff", + "@org_golang_google_grpc//credentials/insecure", + ], +) + +go_test( + name = "rpcsigner_test", + srcs = ["client_test.go"], + embed = [":rpcsigner"], + deps = [ + "//proto/pb/signer", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "@com_github_stretchr_testify//require", + "@org_golang_google_grpc//:grpc", + ], +) diff --git a/utils/crypto/keychain/BUILD.bazel b/utils/crypto/keychain/BUILD.bazel new file mode 100644 index 000000000000..9b26a0d56977 --- /dev/null +++ b/utils/crypto/keychain/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "keychain", + srcs = ["keychain.go"], + importpath = "github.com/ava-labs/avalanchego/utils/crypto/keychain", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/set", + ], +) diff --git a/utils/crypto/secp256k1/BUILD.bazel b/utils/crypto/secp256k1/BUILD.bazel new file mode 100644 index 000000000000..5c221b016982 --- /dev/null +++ b/utils/crypto/secp256k1/BUILD.bazel @@ -0,0 +1,39 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "secp256k1", + srcs = [ + "secp256k1.go", + "test_keys.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/crypto/secp256k1", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//ids", + "//utils/cb58", + "//utils/hashing", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//crypto", + "@com_github_decred_dcrd_dcrec_secp256k1_v4//:secp256k1", + "@com_github_decred_dcrd_dcrec_secp256k1_v4//ecdsa", + ], +) + +go_test( + name = "secp256k1_test", + srcs = [ + "rfc6979_test.go", + "secp256k1_benchmark_test.go", + "secp256k1_test.go", + ], + embed = [":secp256k1"], + deps = [ + "//utils", + "//utils/cb58", + "//utils/hashing", + "@com_github_decred_dcrd_dcrec_secp256k1_v4//:secp256k1", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/dynamicip/BUILD.bazel b/utils/dynamicip/BUILD.bazel new file mode 100644 index 000000000000..00c31c8196e8 --- /dev/null +++ b/utils/dynamicip/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "dynamicip", + srcs = [ + "ifconfig_resolver.go", + "no_updater.go", + "opendns_resolver.go", + "resolver.go", + "updater.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/dynamicip", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/ips", + "//utils/logging", + "//utils/rpc", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "dynamicip_test", + srcs = [ + "resolver_test.go", + "updater_test.go", + ], + embed = [":dynamicip"], + deps = [ + "//utils", + "//utils/logging", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/filesystem/BUILD.bazel b/utils/filesystem/BUILD.bazel new file mode 100644 index 000000000000..1ca8cf13a2fc --- /dev/null +++ b/utils/filesystem/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "filesystem", + srcs = [ + "io.go", + "mock_file.go", + "rename.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/filesystem", + visibility = ["//visibility:public"], +) + +go_test( + name = "filesystem_test", + srcs = [ + "mocks_generate_test.go", + "rename_test.go", + ], + embed = [":filesystem"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/filesystem/filesystemmock/BUILD.bazel b/utils/filesystem/filesystemmock/BUILD.bazel new file mode 100644 index 000000000000..fb322d8747b5 --- /dev/null +++ b/utils/filesystem/filesystemmock/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "filesystemmock", + srcs = ["reader.go"], + importpath = "github.com/ava-labs/avalanchego/utils/filesystem/filesystemmock", + visibility = ["//visibility:public"], + deps = ["@org_uber_go_mock//gomock"], +) diff --git a/utils/formatting/BUILD.bazel b/utils/formatting/BUILD.bazel new file mode 100644 index 000000000000..0f06a6875f5d --- /dev/null +++ b/utils/formatting/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "formatting", + srcs = [ + "encoding.go", + "int_format.go", + "prefixed_stringer.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/formatting", + visibility = ["//visibility:public"], + deps = ["//utils/hashing"], +) + +go_test( + name = "formatting_test", + srcs = [ + "encoding_benchmark_test.go", + "encoding_test.go", + "int_format_test.go", + ], + embed = [":formatting"], + deps = [ + "//utils/units", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/formatting/address/BUILD.bazel b/utils/formatting/address/BUILD.bazel new file mode 100644 index 000000000000..8f4a1dab5807 --- /dev/null +++ b/utils/formatting/address/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "address", + srcs = [ + "address.go", + "converter.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/formatting/address", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "@com_github_btcsuite_btcd_btcutil//bech32", + ], +) diff --git a/utils/hashing/BUILD.bazel b/utils/hashing/BUILD.bazel new file mode 100644 index 000000000000..f9695379d1a2 --- /dev/null +++ b/utils/hashing/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "hashing", + srcs = [ + "hasher.go", + "hashing.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/hashing", + visibility = ["//visibility:public"], + deps = ["@org_golang_x_crypto//ripemd160"], +) + +go_test( + name = "hashing_test", + srcs = ["mocks_generate_test.go"], + embed = [":hashing"], +) diff --git a/utils/hashing/consistent/BUILD.bazel b/utils/hashing/consistent/BUILD.bazel new file mode 100644 index 000000000000..12d83cf0408d --- /dev/null +++ b/utils/hashing/consistent/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "consistent", + srcs = [ + "hashable.go", + "ring.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/hashing/consistent", + visibility = ["//visibility:public"], + deps = [ + "//utils/hashing", + "@com_github_google_btree//:btree", + ], +) + +go_test( + name = "consistent_test", + srcs = ["ring_test.go"], + embed = [":consistent"], + deps = [ + "//utils/hashing/hashingmock", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/utils/hashing/hashingmock/BUILD.bazel b/utils/hashing/hashingmock/BUILD.bazel new file mode 100644 index 000000000000..c73007b2b853 --- /dev/null +++ b/utils/hashing/hashingmock/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "hashingmock", + srcs = ["hasher.go"], + importpath = "github.com/ava-labs/avalanchego/utils/hashing/hashingmock", + visibility = ["//visibility:public"], + deps = ["@org_uber_go_mock//gomock"], +) diff --git a/utils/heap/BUILD.bazel b/utils/heap/BUILD.bazel new file mode 100644 index 000000000000..f6cf1d720071 --- /dev/null +++ b/utils/heap/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "heap", + srcs = [ + "map.go", + "queue.go", + "set.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/heap", + visibility = ["//visibility:public"], + deps = ["//utils"], +) + +go_test( + name = "heap_test", + srcs = [ + "map_test.go", + "queue_test.go", + "set_test.go", + ], + embed = [":heap"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/ips/BUILD.bazel b/utils/ips/BUILD.bazel new file mode 100644 index 000000000000..98567ead043a --- /dev/null +++ b/utils/ips/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "ips", + srcs = [ + "claimed_ip_port.go", + "ip.go", + "lookup.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/ips", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//staking", + "//utils/hashing", + "//utils/wrappers", + ], +) + +go_test( + name = "ips_test", + srcs = ["lookup_test.go"], + embed = [":ips"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/iterator/BUILD.bazel b/utils/iterator/BUILD.bazel new file mode 100644 index 000000000000..632578075a7f --- /dev/null +++ b/utils/iterator/BUILD.bazel @@ -0,0 +1,38 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "iterator", + srcs = [ + "empty.go", + "filter.go", + "iterator.go", + "merge.go", + "slice.go", + "tree.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/iterator", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/heap", + "//utils/set", + "@com_github_google_btree//:btree", + ], +) + +go_test( + name = "iterator_test", + srcs = [ + "empty_test.go", + "filter_test.go", + "merge_test.go", + "tree_test.go", + ], + embed = [":iterator"], + deps = [ + "//ids", + "//vms/platformvm/state", + "@com_github_google_btree//:btree", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/json/BUILD.bazel b/utils/json/BUILD.bazel new file mode 100644 index 000000000000..d71077a87d8a --- /dev/null +++ b/utils/json/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "json", + srcs = [ + "codec.go", + "float32.go", + "float64.go", + "uint16.go", + "uint32.go", + "uint64.go", + "uint8.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/json", + visibility = ["//visibility:public"], + deps = [ + "@com_github_gorilla_rpc//v2:rpc", + "@com_github_gorilla_rpc//v2/json2", + ], +) + +go_test( + name = "json_test", + srcs = ["float32_test.go"], + embed = [":json"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/linked/BUILD.bazel b/utils/linked/BUILD.bazel new file mode 100644 index 000000000000..9cd33674cf5e --- /dev/null +++ b/utils/linked/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "linked", + srcs = [ + "hashmap.go", + "list.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/linked", + visibility = ["//visibility:public"], + deps = ["//utils"], +) + +go_test( + name = "linked_test", + srcs = [ + "hashmap_test.go", + "list_test.go", + ], + embed = [":linked"], + deps = [ + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/lock/BUILD.bazel b/utils/lock/BUILD.bazel new file mode 100644 index 000000000000..a756399513fd --- /dev/null +++ b/utils/lock/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "lock", + srcs = ["cond.go"], + importpath = "github.com/ava-labs/avalanchego/utils/lock", + visibility = ["//visibility:public"], +) + +go_test( + name = "lock_test", + srcs = ["cond_test.go"], + embed = [":lock"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/logging/BUILD.bazel b/utils/logging/BUILD.bazel new file mode 100644 index 000000000000..6f688c3d3f8b --- /dev/null +++ b/utils/logging/BUILD.bazel @@ -0,0 +1,36 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "logging", + srcs = [ + "color.go", + "config.go", + "factory.go", + "format.go", + "level.go", + "log.go", + "logger.go", + "sanitize.go", + "test_log.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/logging", + visibility = ["//visibility:public"], + deps = [ + "@in_gopkg_natefinch_lumberjack_v2//:lumberjack_v2", + "@org_golang_x_exp//maps", + "@org_golang_x_term//:term", + "@org_uber_go_zap//:zap", + "@org_uber_go_zap//zapcore", + ], +) + +go_test( + name = "logging_test", + srcs = ["log_test.go"], + embed = [":logging"], + deps = [ + "@com_github_stretchr_testify//require", + "@org_uber_go_zap//:zap", + "@org_uber_go_zap//zapcore", + ], +) diff --git a/utils/math/BUILD.bazel b/utils/math/BUILD.bazel new file mode 100644 index 000000000000..1a2c60900e28 --- /dev/null +++ b/utils/math/BUILD.bazel @@ -0,0 +1,34 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "math", + srcs = [ + "averager.go", + "averager_heap.go", + "continuous_averager.go", + "safe_math.go", + "sync_averager.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/math", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/heap", + "@org_golang_x_exp//constraints", + ], +) + +go_test( + name = "math_test", + srcs = [ + "averager_heap_test.go", + "continuous_averager_benchmark_test.go", + "continuous_averager_test.go", + "safe_math_test.go", + ], + embed = [":math"], + deps = [ + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/math/meter/BUILD.bazel b/utils/math/meter/BUILD.bazel new file mode 100644 index 000000000000..185277a5a322 --- /dev/null +++ b/utils/math/meter/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "meter", + srcs = [ + "continuous_meter.go", + "factory.go", + "meter.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/math/meter", + visibility = ["//visibility:public"], +) + +go_test( + name = "meter_test", + srcs = [ + "meter_benchmark_test.go", + "meter_test.go", + ], + embed = [":meter"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/maybe/BUILD.bazel b/utils/maybe/BUILD.bazel new file mode 100644 index 000000000000..8fe2a901c026 --- /dev/null +++ b/utils/maybe/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "maybe", + srcs = ["maybe.go"], + importpath = "github.com/ava-labs/avalanchego/utils/maybe", + visibility = ["//visibility:public"], +) + +go_test( + name = "maybe_test", + srcs = ["maybe_test.go"], + embed = [":maybe"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/metric/BUILD.bazel b/utils/metric/BUILD.bazel new file mode 100644 index 000000000000..e2c9f39e8dee --- /dev/null +++ b/utils/metric/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "metric", + srcs = [ + "api_interceptor.go", + "averager.go", + "namespace.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/metric", + visibility = ["//visibility:public"], + deps = [ + "//utils/wrappers", + "@com_github_gorilla_rpc//v2:rpc", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "metric_test", + srcs = ["namespace_test.go"], + embed = [":metric"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/packages/BUILD.bazel b/utils/packages/BUILD.bazel new file mode 100644 index 000000000000..12c504eabe90 --- /dev/null +++ b/utils/packages/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "packages", + srcs = ["dependencies.go"], + importpath = "github.com/ava-labs/avalanchego/utils/packages", + visibility = ["//visibility:public"], + deps = [ + "//utils/set", + "@org_golang_x_tools//go/packages", + ], +) diff --git a/utils/password/BUILD.bazel b/utils/password/BUILD.bazel new file mode 100644 index 000000000000..7e63e2f8f5bf --- /dev/null +++ b/utils/password/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "password", + srcs = [ + "hash.go", + "password.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/password", + visibility = ["//visibility:public"], + deps = [ + "@com_github_nbutton23_zxcvbn_go//:zxcvbn-go", + "@org_golang_x_crypto//argon2", + ], +) + +go_test( + name = "password_test", + srcs = [ + "hash_test.go", + "password_test.go", + ], + embed = [":password"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/perms/BUILD.bazel b/utils/perms/BUILD.bazel new file mode 100644 index 000000000000..d70ed10d83e4 --- /dev/null +++ b/utils/perms/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "perms", + srcs = [ + "chmod.go", + "create.go", + "perms.go", + "write_file.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/perms", + visibility = ["//visibility:public"], + deps = ["@com_github_google_renameio_v2//maybe"], +) diff --git a/utils/profiler/BUILD.bazel b/utils/profiler/BUILD.bazel new file mode 100644 index 000000000000..8b80bfcf140f --- /dev/null +++ b/utils/profiler/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "profiler", + srcs = [ + "continuous.go", + "profiler.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/profiler", + visibility = ["//visibility:public"], + deps = [ + "//utils/filesystem", + "//utils/perms", + "@org_golang_x_sync//errgroup", + ], +) + +go_test( + name = "profiler_test", + srcs = ["profiler_test.go"], + embed = [":profiler"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/resource/BUILD.bazel b/utils/resource/BUILD.bazel new file mode 100644 index 000000000000..aff50d83702c --- /dev/null +++ b/utils/resource/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "resource", + srcs = [ + "metrics.go", + "no_usage.go", + "usage.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/resource", + visibility = ["//visibility:public"], + deps = [ + "//utils/logging", + "//utils/storage", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_shirou_gopsutil//cpu", + "@com_github_shirou_gopsutil//process", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "resource_test", + srcs = [ + "mocks_generate_test.go", + "usage_test.go", + ], + embed = [":resource"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/resource/resourcemock/BUILD.bazel b/utils/resource/resourcemock/BUILD.bazel new file mode 100644 index 000000000000..3f8984c5c560 --- /dev/null +++ b/utils/resource/resourcemock/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "resourcemock", + srcs = ["user.go"], + importpath = "github.com/ava-labs/avalanchego/utils/resource/resourcemock", + visibility = ["//visibility:public"], + deps = ["@org_uber_go_mock//gomock"], +) diff --git a/utils/rpc/BUILD.bazel b/utils/rpc/BUILD.bazel new file mode 100644 index 000000000000..a387af3d9e05 --- /dev/null +++ b/utils/rpc/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "rpc", + srcs = [ + "json.go", + "options.go", + "requester.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/rpc", + visibility = ["//visibility:public"], + deps = ["@com_github_gorilla_rpc//v2/json2"], +) diff --git a/utils/sampler/BUILD.bazel b/utils/sampler/BUILD.bazel new file mode 100644 index 000000000000..97b5f7cf9c81 --- /dev/null +++ b/utils/sampler/BUILD.bazel @@ -0,0 +1,42 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "sampler", + srcs = [ + "rand.go", + "uniform.go", + "uniform_replacer.go", + "weighted.go", + "weighted_heap.go", + "weighted_without_replacement.go", + "weighted_without_replacement_generic.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/sampler", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/math", + "@org_gonum_v1_gonum//mathext/prng", + ], +) + +go_test( + name = "sampler_test", + srcs = [ + "rand_test.go", + "uniform_benchmark_test.go", + "uniform_test.go", + "weighted_benchmark_test.go", + "weighted_heap_test.go", + "weighted_test.go", + "weighted_without_replacement_benchmark_test.go", + "weighted_without_replacement_test.go", + ], + embed = [":sampler"], + deps = [ + "//utils/math", + "@com_github_stretchr_testify//require", + "@com_github_thepudds_fzgen//fuzzer", + "@org_gonum_v1_gonum//mathext/prng", + ], +) diff --git a/utils/set/BUILD.bazel b/utils/set/BUILD.bazel new file mode 100644 index 000000000000..c6d777d5b709 --- /dev/null +++ b/utils/set/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "set", + srcs = [ + "bits.go", + "bits_64.go", + "sampleable_set.go", + "set.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/set", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/json", + "//utils/sampler", + "//utils/wrappers", + "@org_golang_x_exp//maps", + ], +) + +go_test( + name = "set_test", + srcs = [ + "bits_64_test.go", + "bits_test.go", + "sampleable_set_test.go", + "set_benchmark_test.go", + "set_test.go", + ], + embed = [":set"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/setmap/BUILD.bazel b/utils/setmap/BUILD.bazel new file mode 100644 index 000000000000..9cd7718903e2 --- /dev/null +++ b/utils/setmap/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "setmap", + srcs = ["setmap.go"], + importpath = "github.com/ava-labs/avalanchego/utils/setmap", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/set", + ], +) + +go_test( + name = "setmap_test", + srcs = ["setmap_test.go"], + embed = [":setmap"], + deps = [ + "//utils/set", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/storage/BUILD.bazel b/utils/storage/BUILD.bazel new file mode 100644 index 000000000000..697e1dd82fef --- /dev/null +++ b/utils/storage/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "storage", + srcs = [ + "storage_common.go", + "storage_openbsd.go", + "storage_unix.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/storage", + visibility = ["//visibility:public"], +) diff --git a/utils/timer/BUILD.bazel b/utils/timer/BUILD.bazel new file mode 100644 index 000000000000..817a9a2a8bc6 --- /dev/null +++ b/utils/timer/BUILD.bazel @@ -0,0 +1,36 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "timer", + srcs = [ + "adaptive_timeout_manager.go", + "eta.go", + "meter.go", + "stopped_timer.go", + "timer.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/timer", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/heap", + "//utils/math", + "//utils/timer/mockable", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "timer_test", + srcs = [ + "adaptive_timeout_manager_test.go", + "eta_test.go", + "timer_test.go", + ], + embed = [":timer"], + deps = [ + "//ids", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/timer/mockable/BUILD.bazel b/utils/timer/mockable/BUILD.bazel new file mode 100644 index 000000000000..444d5956a88d --- /dev/null +++ b/utils/timer/mockable/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "mockable", + srcs = ["clock.go"], + importpath = "github.com/ava-labs/avalanchego/utils/timer/mockable", + visibility = ["//visibility:public"], +) + +go_test( + name = "mockable_test", + srcs = ["clock_test.go"], + embed = [":mockable"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/utils/tree/BUILD.bazel b/utils/tree/BUILD.bazel new file mode 100644 index 000000000000..61cd4770e1ae --- /dev/null +++ b/utils/tree/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "tree", + srcs = ["tree.go"], + importpath = "github.com/ava-labs/avalanchego/utils/tree", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/consensus/snowman", + "@org_golang_x_exp//maps", + ], +) + +go_test( + name = "tree_test", + srcs = ["tree_test.go"], + embed = [":tree"], + deps = [ + "//snow/consensus/snowman/snowmantest", + "//snow/snowtest", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/ulimit/BUILD.bazel b/utils/ulimit/BUILD.bazel new file mode 100644 index 000000000000..2bc5fa20ea2c --- /dev/null +++ b/utils/ulimit/BUILD.bazel @@ -0,0 +1,43 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "ulimit", + srcs = [ + "ulimit_bsd.go", + "ulimit_darwin.go", + "ulimit_unix.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/ulimit", + visibility = ["//visibility:public"], + deps = select({ + "@rules_go//go/platform:android": [ + "//utils/logging", + "@org_uber_go_zap//:zap", + ], + "@rules_go//go/platform:darwin": [ + "//utils/logging", + "@org_uber_go_zap//:zap", + ], + "@rules_go//go/platform:freebsd": [ + "//utils/logging", + "@org_uber_go_zap//:zap", + ], + "@rules_go//go/platform:ios": [ + "//utils/logging", + "@org_uber_go_zap//:zap", + ], + "@rules_go//go/platform:linux": [ + "//utils/logging", + "@org_uber_go_zap//:zap", + ], + "@rules_go//go/platform:netbsd": [ + "//utils/logging", + "@org_uber_go_zap//:zap", + ], + "@rules_go//go/platform:openbsd": [ + "//utils/logging", + "@org_uber_go_zap//:zap", + ], + "//conditions:default": [], + }), +) diff --git a/utils/units/BUILD.bazel b/utils/units/BUILD.bazel new file mode 100644 index 000000000000..baeb53849f2b --- /dev/null +++ b/utils/units/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "units", + srcs = [ + "avax.go", + "bytes.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/units", + visibility = ["//visibility:public"], +) diff --git a/utils/window/BUILD.bazel b/utils/window/BUILD.bazel new file mode 100644 index 000000000000..4b49790adc23 --- /dev/null +++ b/utils/window/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "window", + srcs = ["window.go"], + importpath = "github.com/ava-labs/avalanchego/utils/window", + visibility = ["//visibility:public"], + deps = [ + "//utils", + "//utils/buffer", + "//utils/timer/mockable", + ], +) + +go_test( + name = "window_test", + srcs = ["window_test.go"], + embed = [":window"], + deps = [ + "//utils/timer/mockable", + "@com_github_stretchr_testify//require", + ], +) diff --git a/utils/wrappers/BUILD.bazel b/utils/wrappers/BUILD.bazel new file mode 100644 index 000000000000..dc6ffd4abcd9 --- /dev/null +++ b/utils/wrappers/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "wrappers", + srcs = [ + "closers.go", + "errors.go", + "packing.go", + ], + importpath = "github.com/ava-labs/avalanchego/utils/wrappers", + visibility = ["//visibility:public"], +) + +go_test( + name = "wrappers_test", + srcs = ["packing_test.go"], + embed = [":wrappers"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/version/BUILD.bazel b/version/BUILD.bazel new file mode 100644 index 000000000000..3156a58b0e1b --- /dev/null +++ b/version/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "version", + srcs = [ + "application.go", + "compatibility.go", + "constants.go", + "string.go", + ], + embedsrcs = ["compatibility.json"], + importpath = "github.com/ava-labs/avalanchego/version", + visibility = ["//visibility:public"], + deps = ["//utils/timer/mockable"], +) + +go_test( + name = "version_test", + srcs = [ + "application_test.go", + "compatibility_test.go", + "constants_test.go", + "string_test.go", + ], + embed = [":version"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/vms/BUILD.bazel b/vms/BUILD.bazel new file mode 100644 index 000000000000..d0235952c9b5 --- /dev/null +++ b/vms/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "vms", + srcs = ["manager.go"], + importpath = "github.com/ava-labs/avalanchego/vms", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/engine/common", + "//utils/logging", + "@org_golang_x_exp//maps", + ], +) + +go_test( + name = "vms_test", + srcs = ["mocks_generate_test.go"], + embed = [":vms"], +) diff --git a/vms/avm/BUILD.bazel b/vms/avm/BUILD.bazel new file mode 100644 index 000000000000..d46234018187 --- /dev/null +++ b/vms/avm/BUILD.bazel @@ -0,0 +1,124 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "avm", + srcs = [ + "client.go", + "config.go", + "factory.go", + "genesis.go", + "health.go", + "service.go", + "tx.go", + "tx_init.go", + "vm.go", + "wallet_client.go", + "wallet_service.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm", + visibility = ["//visibility:public"], + deps = [ + "//api", + "//api/metrics", + "//codec", + "//database", + "//database/versiondb", + "//ids", + "//snow", + "//snow/choices", + "//snow/consensus/snowman", + "//snow/consensus/snowstorm", + "//snow/engine/avalanche/vertex", + "//snow/engine/common", + "//utils", + "//utils/constants", + "//utils/formatting", + "//utils/formatting/address", + "//utils/json", + "//utils/linked", + "//utils/logging", + "//utils/math", + "//utils/rpc", + "//utils/set", + "//utils/timer/mockable", + "//version", + "//vms", + "//vms/avm/block", + "//vms/avm/block/builder", + "//vms/avm/block/executor", + "//vms/avm/config", + "//vms/avm/fxs", + "//vms/avm/metrics", + "//vms/avm/network", + "//vms/avm/state", + "//vms/avm/txs", + "//vms/avm/txs/executor", + "//vms/avm/txs/mempool", + "//vms/avm/utxo", + "//vms/components/avax", + "//vms/components/verify", + "//vms/nftfx", + "//vms/propertyfx", + "//vms/secp256k1fx", + "//vms/txs/mempool", + "@com_github_gorilla_rpc//v2:rpc", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "avm_test", + srcs = [ + "config_test.go", + "environment_test.go", + "fx_test.go", + "genesis_test.go", + "service_test.go", + "state_test.go", + "vm_benchmark_test.go", + "vm_regression_test.go", + "vm_test.go", + ], + embed = [":avm"], + deps = [ + "//api", + "//chains/atomic", + "//codec", + "//database", + "//database/memdb", + "//database/prefixdb", + "//ids", + "//snow", + "//snow/choices", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/snowtest", + "//upgrade/upgradetest", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/formatting", + "//utils/formatting/address", + "//utils/json", + "//utils/logging", + "//utils/set", + "//utils/units", + "//vms/avm/block", + "//vms/avm/block/executor", + "//vms/avm/block/executor/executormock", + "//vms/avm/config", + "//vms/avm/fxs", + "//vms/avm/network", + "//vms/avm/state/statemock", + "//vms/avm/txs", + "//vms/avm/txs/txstest", + "//vms/components/avax", + "//vms/components/verify", + "//vms/nftfx", + "//vms/propertyfx", + "//vms/secp256k1fx", + "@com_github_btcsuite_btcd_btcutil//bech32", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/block/BUILD.bazel b/vms/avm/block/BUILD.bazel new file mode 100644 index 000000000000..693aa181ca45 --- /dev/null +++ b/vms/avm/block/BUILD.bazel @@ -0,0 +1,44 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "block", + srcs = [ + "block.go", + "mock_block.go", + "parser.go", + "standard_block.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/block", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//ids", + "//snow", + "//utils/hashing", + "//utils/logging", + "//utils/timer/mockable", + "//vms/avm/fxs", + "//vms/avm/txs", + "@org_uber_go_mock//gomock", + ], +) + +go_test( + name = "block_test", + srcs = [ + "block_test.go", + "mocks_generate_test.go", + ], + embed = [":block"], + deps = [ + "//codec", + "//ids", + "//utils/constants", + "//utils/crypto/secp256k1", + "//vms/avm/fxs", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/avm/block/builder/BUILD.bazel b/vms/avm/block/builder/BUILD.bazel new file mode 100644 index 000000000000..94dff743d93b --- /dev/null +++ b/vms/avm/block/builder/BUILD.bazel @@ -0,0 +1,57 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "builder", + srcs = ["builder.go"], + importpath = "github.com/ava-labs/avalanchego/vms/avm/block/builder", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/consensus/snowman", + "//snow/engine/common", + "//utils/set", + "//utils/timer/mockable", + "//utils/units", + "//vms/avm/block", + "//vms/avm/block/executor", + "//vms/avm/state", + "//vms/avm/txs", + "//vms/avm/txs/executor", + "//vms/txs/mempool", + ], +) + +go_test( + name = "builder_test", + srcs = ["builder_test.go"], + embed = [":builder"], + deps = [ + "//codec", + "//codec/codecmock", + "//database/memdb", + "//database/versiondb", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/logging", + "//utils/timer/mockable", + "//vms/avm/block", + "//vms/avm/block/executor", + "//vms/avm/block/executor/executormock", + "//vms/avm/fxs", + "//vms/avm/metrics", + "//vms/avm/state", + "//vms/avm/state/statemock", + "//vms/avm/txs", + "//vms/avm/txs/executor", + "//vms/avm/txs/mempool", + "//vms/avm/txs/txsmock", + "//vms/components/avax", + "//vms/secp256k1fx", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/block/executor/BUILD.bazel b/vms/avm/block/executor/BUILD.bazel new file mode 100644 index 000000000000..88bc7d841e04 --- /dev/null +++ b/vms/avm/block/executor/BUILD.bazel @@ -0,0 +1,57 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "executor", + srcs = [ + "block.go", + "manager.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/block/executor", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//ids", + "//snow/consensus/snowman", + "//utils/set", + "//utils/timer/mockable", + "//vms/avm/block", + "//vms/avm/metrics", + "//vms/avm/state", + "//vms/avm/txs", + "//vms/avm/txs/executor", + "//vms/txs/mempool", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "executor_test", + srcs = [ + "block_test.go", + "manager_test.go", + "mocks_generate_test.go", + ], + embed = [":executor"], + deps = [ + "//chains/atomic", + "//chains/atomic/atomicmock", + "//ids", + "//snow", + "//upgrade/upgradetest", + "//utils", + "//utils/logging", + "//utils/set", + "//utils/timer/mockable", + "//vms/avm/block", + "//vms/avm/config", + "//vms/avm/metrics/metricsmock", + "//vms/avm/state/statemock", + "//vms/avm/txs", + "//vms/avm/txs/executor", + "//vms/avm/txs/mempool", + "//vms/avm/txs/txsmock", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/block/executor/executormock/BUILD.bazel b/vms/avm/block/executor/executormock/BUILD.bazel new file mode 100644 index 000000000000..c11471711caf --- /dev/null +++ b/vms/avm/block/executor/executormock/BUILD.bazel @@ -0,0 +1,17 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "executormock", + srcs = ["manager.go"], + importpath = "github.com/ava-labs/avalanchego/vms/avm/block/executor/executormock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/consensus/snowman", + "//utils/set", + "//vms/avm/block", + "//vms/avm/state", + "//vms/avm/txs", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/config/BUILD.bazel b/vms/avm/config/BUILD.bazel new file mode 100644 index 000000000000..202be3fa693c --- /dev/null +++ b/vms/avm/config/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "config", + srcs = ["config.go"], + importpath = "github.com/ava-labs/avalanchego/vms/avm/config", + visibility = ["//visibility:public"], + deps = ["//upgrade"], +) diff --git a/vms/avm/fxs/BUILD.bazel b/vms/avm/fxs/BUILD.bazel new file mode 100644 index 000000000000..f8518dab59f4 --- /dev/null +++ b/vms/avm/fxs/BUILD.bazel @@ -0,0 +1,17 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "fxs", + srcs = ["fx.go"], + importpath = "github.com/ava-labs/avalanchego/vms/avm/fxs", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//vms/components/avax", + "//vms/components/verify", + "//vms/nftfx", + "//vms/propertyfx", + "//vms/secp256k1fx", + ], +) diff --git a/vms/avm/metrics/BUILD.bazel b/vms/avm/metrics/BUILD.bazel new file mode 100644 index 000000000000..9a13c7896a9a --- /dev/null +++ b/vms/avm/metrics/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "metrics", + srcs = [ + "metrics.go", + "tx_metrics.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/metrics", + visibility = ["//visibility:public"], + deps = [ + "//utils/metric", + "//utils/wrappers", + "//vms/avm/block", + "//vms/avm/txs", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "metrics_test", + srcs = ["mocks_generate_test.go"], + embed = [":metrics"], +) diff --git a/vms/avm/metrics/metricsmock/BUILD.bazel b/vms/avm/metrics/metricsmock/BUILD.bazel new file mode 100644 index 000000000000..e2820f27042f --- /dev/null +++ b/vms/avm/metrics/metricsmock/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "metricsmock", + srcs = ["metrics.go"], + importpath = "github.com/ava-labs/avalanchego/vms/avm/metrics/metricsmock", + visibility = ["//visibility:public"], + deps = [ + "//vms/avm/block", + "//vms/avm/txs", + "@com_github_gorilla_rpc//v2:rpc", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/network/BUILD.bazel b/vms/avm/network/BUILD.bazel new file mode 100644 index 000000000000..d263c3d708d1 --- /dev/null +++ b/vms/avm/network/BUILD.bazel @@ -0,0 +1,56 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "network", + srcs = [ + "atomic.go", + "config.go", + "gossip.go", + "network.go", + "tx_verifier.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/network", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//network/p2p", + "//network/p2p/gossip", + "//snow/engine/common", + "//snow/validators", + "//utils", + "//utils/logging", + "//utils/units", + "//vms/avm/txs", + "//vms/txs/mempool", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "network_test", + srcs = [ + "gossip_test.go", + "network_test.go", + ], + embed = [":network"], + deps = [ + "//ids", + "//snow/engine/common", + "//snow/engine/common/commonmock", + "//snow/validators", + "//snow/validators/validatorstest", + "//utils/logging", + "//vms/avm/block/executor/executormock", + "//vms/avm/fxs", + "//vms/avm/txs", + "//vms/avm/txs/mempool", + "//vms/components/avax", + "//vms/nftfx", + "//vms/propertyfx", + "//vms/secp256k1fx", + "//vms/txs/mempool", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/state/BUILD.bazel b/vms/avm/state/BUILD.bazel new file mode 100644 index 000000000000..0d83b3f26359 --- /dev/null +++ b/vms/avm/state/BUILD.bazel @@ -0,0 +1,48 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "state", + srcs = [ + "diff.go", + "state.go", + "versions.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/state", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//cache/metercacher", + "//database", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//vms/avm/block", + "//vms/avm/txs", + "//vms/components/avax", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "state_test", + srcs = [ + "mocks_generate_test.go", + "state_test.go", + ], + embed = [":state"], + deps = [ + "//database", + "//database/memdb", + "//database/versiondb", + "//ids", + "//upgrade", + "//vms/avm/block", + "//vms/avm/fxs", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/secp256k1fx", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/avm/state/statemock/BUILD.bazel b/vms/avm/state/statemock/BUILD.bazel new file mode 100644 index 000000000000..aa2939c146d7 --- /dev/null +++ b/vms/avm/state/statemock/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "statemock", + srcs = [ + "chain.go", + "diff.go", + "state.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/state/statemock", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//vms/avm/block", + "//vms/avm/state", + "//vms/avm/txs", + "//vms/components/avax", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/txs/BUILD.bazel b/vms/avm/txs/BUILD.bazel new file mode 100644 index 000000000000..9492f1fe3058 --- /dev/null +++ b/vms/avm/txs/BUILD.bazel @@ -0,0 +1,68 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "txs", + srcs = [ + "base_tx.go", + "codec.go", + "create_asset_tx.go", + "export_tx.go", + "import_tx.go", + "initial_state.go", + "operation.go", + "operation_tx.go", + "parser.go", + "tx.go", + "visitor.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/txs", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//network/p2p/gossip", + "//snow", + "//utils", + "//utils/crypto/secp256k1", + "//utils/hashing", + "//utils/logging", + "//utils/set", + "//utils/timer/mockable", + "//utils/wrappers", + "//vms/avm/fxs", + "//vms/components/avax", + "//vms/components/verify", + "//vms/nftfx", + "//vms/propertyfx", + "//vms/secp256k1fx", + ], +) + +go_test( + name = "txs_test", + srcs = [ + "base_tx_test.go", + "create_asset_tx_test.go", + "export_tx_test.go", + "import_tx_test.go", + "initial_state_test.go", + "mocks_generate_test.go", + "operation_test.go", + ], + embed = [":txs"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//snow", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/units", + "//vms/avm/fxs", + "//vms/components/avax", + "//vms/components/verify", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/avm/txs/executor/BUILD.bazel b/vms/avm/txs/executor/BUILD.bazel new file mode 100644 index 000000000000..f18b362baac5 --- /dev/null +++ b/vms/avm/txs/executor/BUILD.bazel @@ -0,0 +1,66 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "executor", + srcs = [ + "backend.go", + "executor.go", + "semantic_verifier.go", + "syntactic_verifier.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/txs/executor", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//codec", + "//ids", + "//snow", + "//utils", + "//utils/set", + "//vms/avm/config", + "//vms/avm/fxs", + "//vms/avm/state", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/components/verify", + ], +) + +go_test( + name = "executor_test", + srcs = [ + "executor_test.go", + "semantic_verifier_test.go", + "syntactic_verifier_test.go", + ], + embed = [":executor"], + deps = [ + "//chains/atomic", + "//database", + "//database/memdb", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//snow/snowtest", + "//snow/validators/validatorsmock", + "//upgrade/upgradetest", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/logging", + "//utils/math", + "//utils/timer/mockable", + "//utils/units", + "//vms/avm/block", + "//vms/avm/config", + "//vms/avm/fxs", + "//vms/avm/state", + "//vms/avm/state/statemock", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/components/verify", + "//vms/secp256k1fx", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/txs/mempool/BUILD.bazel b/vms/avm/txs/mempool/BUILD.bazel new file mode 100644 index 000000000000..3d54995d473f --- /dev/null +++ b/vms/avm/txs/mempool/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "mempool", + srcs = ["mempool.go"], + importpath = "github.com/ava-labs/avalanchego/vms/avm/txs/mempool", + visibility = ["//visibility:public"], + deps = [ + "//vms/avm/txs", + "//vms/txs/mempool", + "@com_github_prometheus_client_golang//prometheus", + ], +) diff --git a/vms/avm/txs/txsmock/BUILD.bazel b/vms/avm/txs/txsmock/BUILD.bazel new file mode 100644 index 000000000000..a2384adcb138 --- /dev/null +++ b/vms/avm/txs/txsmock/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "txsmock", + srcs = ["tx.go"], + importpath = "github.com/ava-labs/avalanchego/vms/avm/txs/txsmock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//utils/set", + "//vms/avm/txs", + "//vms/components/avax", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/avm/txs/txstest/BUILD.bazel b/vms/avm/txs/txstest/BUILD.bazel new file mode 100644 index 000000000000..f4f2f351bce1 --- /dev/null +++ b/vms/avm/txs/txstest/BUILD.bazel @@ -0,0 +1,29 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "txstest", + srcs = [ + "builder.go", + "context.go", + "utxos.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/avm/txs/txstest", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//codec", + "//database", + "//ids", + "//snow", + "//utils/set", + "//vms/avm/config", + "//vms/avm/state", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/components/verify", + "//vms/secp256k1fx", + "//wallet/chain/x/builder", + "//wallet/chain/x/signer", + "//wallet/subnet/primary/common", + ], +) diff --git a/vms/avm/utxo/BUILD.bazel b/vms/avm/utxo/BUILD.bazel new file mode 100644 index 000000000000..8f4f6b901d5f --- /dev/null +++ b/vms/avm/utxo/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "utxo", + srcs = ["spender.go"], + importpath = "github.com/ava-labs/avalanchego/vms/avm/utxo", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//ids", + "//utils/crypto/secp256k1", + "//utils/math", + "//utils/timer/mockable", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/nftfx", + "//vms/secp256k1fx", + ], +) diff --git a/vms/components/avax/BUILD.bazel b/vms/components/avax/BUILD.bazel new file mode 100644 index 000000000000..d52ffa1372e8 --- /dev/null +++ b/vms/components/avax/BUILD.bazel @@ -0,0 +1,69 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "avax", + srcs = [ + "addresses.go", + "asset.go", + "atomic_utxos.go", + "base_tx.go", + "flow_checker.go", + "state.go", + "test_verifiable.go", + "transferables.go", + "utxo.go", + "utxo_fetching.go", + "utxo_handler.go", + "utxo_id.go", + "utxo_state.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/components/avax", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//cache/metercacher", + "//chains/atomic", + "//codec", + "//database", + "//database/linkeddb", + "//database/prefixdb", + "//ids", + "//snow", + "//utils", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/formatting/address", + "//utils/math", + "//utils/set", + "//utils/wrappers", + "//vms/components/verify", + "//vms/types", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "avax_test", + srcs = [ + "asset_test.go", + "mocks_generate_test.go", + "transferables_test.go", + "utxo_fetching_test.go", + "utxo_id_test.go", + "utxo_state_test.go", + "utxo_test.go", + ], + embed = [":avax"], + deps = [ + "//codec", + "//codec/linearcodec", + "//database", + "//database/memdb", + "//ids", + "//utils", + "//utils/set", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/components/avax/avaxmock/BUILD.bazel b/vms/components/avax/avaxmock/BUILD.bazel new file mode 100644 index 000000000000..3968be6eb403 --- /dev/null +++ b/vms/components/avax/avaxmock/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "avaxmock", + srcs = [ + "transferable_in.go", + "transferable_out.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/components/avax/avaxmock", + visibility = ["//visibility:public"], + deps = [ + "//snow", + "//vms/components/verify", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/components/chain/BUILD.bazel b/vms/components/chain/BUILD.bazel new file mode 100644 index 000000000000..7eb63c82e910 --- /dev/null +++ b/vms/components/chain/BUILD.bazel @@ -0,0 +1,38 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "chain", + srcs = [ + "block.go", + "state.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/components/chain", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//cache/metercacher", + "//database", + "//ids", + "//snow/consensus/snowman", + "//snow/engine/snowman/block", + "//utils/constants", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "chain_test", + srcs = ["state_test.go"], + embed = [":chain"], + deps = [ + "//database", + "//ids", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmantest", + "//snow/snowtest", + "//utils/hashing", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/components/gas/BUILD.bazel b/vms/components/gas/BUILD.bazel new file mode 100644 index 000000000000..ba3f1acbe6c0 --- /dev/null +++ b/vms/components/gas/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "gas", + srcs = [ + "config.go", + "dimensions.go", + "gas.go", + "state.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/components/gas", + visibility = ["//visibility:public"], + deps = [ + "//utils/math", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "gas_test", + srcs = [ + "dimensions_test.go", + "gas_test.go", + "state_test.go", + ], + embed = [":gas"], + deps = [ + "//utils/math", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/components/verify/BUILD.bazel b/vms/components/verify/BUILD.bazel new file mode 100644 index 000000000000..f3852e36de87 --- /dev/null +++ b/vms/components/verify/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "verify", + srcs = [ + "subnet.go", + "verification.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/components/verify", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + ], +) + +go_test( + name = "verify_test", + srcs = [ + "mocks_generate_test.go", + "subnet_test.go", + "verification_test.go", + ], + embed = [":verify"], + deps = [ + "//ids", + "//snow", + "//snow/validators/validatorsmock", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/components/verify/verifymock/BUILD.bazel b/vms/components/verify/verifymock/BUILD.bazel new file mode 100644 index 000000000000..093319e18c1e --- /dev/null +++ b/vms/components/verify/verifymock/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "verifymock", + srcs = ["verifiable.go"], + importpath = "github.com/ava-labs/avalanchego/vms/components/verify/verifymock", + visibility = ["//visibility:public"], + deps = ["@org_uber_go_mock//gomock"], +) diff --git a/vms/evm/acp176/BUILD.bazel b/vms/evm/acp176/BUILD.bazel new file mode 100644 index 000000000000..5b6c6b78efed --- /dev/null +++ b/vms/evm/acp176/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "acp176", + srcs = ["acp176.go"], + importpath = "github.com/ava-labs/avalanchego/vms/evm/acp176", + visibility = ["//visibility:public"], + deps = [ + "//utils/math", + "//utils/wrappers", + "//vms/components/gas", + "@com_github_holiman_uint256//:uint256", + ], +) + +go_test( + name = "acp176_test", + srcs = ["acp176_test.go"], + embed = [":acp176"], + deps = [ + "//vms/components/gas", + "@com_github_ava_labs_libevm//common", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/evm/acp226/BUILD.bazel b/vms/evm/acp226/BUILD.bazel new file mode 100644 index 000000000000..9222163ce964 --- /dev/null +++ b/vms/evm/acp226/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "acp226", + srcs = ["acp226.go"], + importpath = "github.com/ava-labs/avalanchego/vms/evm/acp226", + visibility = ["//visibility:public"], + deps = [ + "//utils/math", + "//vms/components/gas", + ], +) + +go_test( + name = "acp226_test", + srcs = ["acp226_test.go"], + embed = [":acp226"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/vms/evm/database/BUILD.bazel b/vms/evm/database/BUILD.bazel new file mode 100644 index 000000000000..f475a84597ab --- /dev/null +++ b/vms/evm/database/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "database", + srcs = ["database.go"], + importpath = "github.com/ava-labs/avalanchego/vms/evm/database", + visibility = ["//visibility:public"], + deps = [ + "//database", + "@com_github_ava_labs_libevm//ethdb", + ], +) + +go_test( + name = "database_test", + srcs = ["database_test.go"], + embed = [":database"], + deps = [ + "//database/memdb", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//ethdb/dbtest", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/evm/emulate/BUILD.bazel b/vms/evm/emulate/BUILD.bazel new file mode 100644 index 000000000000..14d836e9e568 --- /dev/null +++ b/vms/evm/emulate/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "emulate", + srcs = ["emulate.go"], + importpath = "github.com/ava-labs/avalanchego/vms/evm/emulate", + visibility = ["//visibility:public"], + deps = [ + "//graft/coreth/plugin/evm", + "@com_github_ava_labs_subnet_evm//plugin/evm", + ], +) + +go_test( + name = "emulate_test", + srcs = ["emulate_test.go"], + embed = [":emulate"], + deps = [ + "//graft/coreth/plugin/evm/customtypes", + "@com_github_ava_labs_libevm//core/types", + "@com_github_ava_labs_subnet_evm//plugin/evm/customtypes", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/evm/metrics/metricstest/BUILD.bazel b/vms/evm/metrics/metricstest/BUILD.bazel new file mode 100644 index 000000000000..feb6ed384ec1 --- /dev/null +++ b/vms/evm/metrics/metricstest/BUILD.bazel @@ -0,0 +1,9 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "metricstest", + srcs = ["metrics.go"], + importpath = "github.com/ava-labs/avalanchego/vms/evm/metrics/metricstest", + visibility = ["//visibility:public"], + deps = ["@com_github_ava_labs_libevm//metrics"], +) diff --git a/vms/evm/metrics/prometheus/BUILD.bazel b/vms/evm/metrics/prometheus/BUILD.bazel new file mode 100644 index 000000000000..5fd62cc26e12 --- /dev/null +++ b/vms/evm/metrics/prometheus/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "prometheus", + srcs = [ + "interfaces.go", + "prometheus.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/evm/metrics/prometheus", + visibility = ["//visibility:public"], + deps = [ + "@com_github_ava_labs_libevm//metrics", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_model//go", + ], +) + +go_test( + name = "prometheus_test", + srcs = [ + "enabled_test.go", + "prometheus_test.go", + ], + embed = [":prometheus"], + deps = [ + "//vms/evm/metrics/metricstest", + "@com_github_ava_labs_libevm//metrics", + "@com_github_prometheus_client_golang//prometheus/testutil", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/evm/predicate/BUILD.bazel b/vms/evm/predicate/BUILD.bazel new file mode 100644 index 000000000000..8d4cbc3c1445 --- /dev/null +++ b/vms/evm/predicate/BUILD.bazel @@ -0,0 +1,35 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "predicate", + srcs = [ + "predicate.go", + "results.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/evm/predicate", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//utils/set", + "//utils/units", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + ], +) + +go_test( + name = "predicate_test", + srcs = [ + "predicate_test.go", + "results_test.go", + ], + embed = [":predicate"], + deps = [ + "//codec", + "//utils/set", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/types", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/evm/sync/customrawdb/BUILD.bazel b/vms/evm/sync/customrawdb/BUILD.bazel new file mode 100644 index 000000000000..8859fdd4ca03 --- /dev/null +++ b/vms/evm/sync/customrawdb/BUILD.bazel @@ -0,0 +1,40 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "customrawdb", + srcs = [ + "db.go", + "markers.go", + "sync_progress.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/evm/sync/customrawdb", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//utils/wrappers", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//params", + "@com_github_ava_labs_libevm//rlp", + ], +) + +go_test( + name = "customrawdb_test", + srcs = [ + "db_test.go", + "markers_test.go", + "sync_progress_test.go", + ], + embed = [":customrawdb"], + deps = [ + "//database", + "//utils/set", + "@com_github_ava_labs_libevm//common", + "@com_github_ava_labs_libevm//core/rawdb", + "@com_github_ava_labs_libevm//ethdb", + "@com_github_ava_labs_libevm//params", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/evm/uptimetracker/BUILD.bazel b/vms/evm/uptimetracker/BUILD.bazel new file mode 100644 index 000000000000..95ba05c67543 --- /dev/null +++ b/vms/evm/uptimetracker/BUILD.bazel @@ -0,0 +1,36 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "uptimetracker", + srcs = [ + "state.go", + "uptime_tracker.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/evm/uptimetracker", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//database", + "//ids", + "//snow/uptime", + "//snow/validators", + "//utils/set", + "//utils/timer/mockable", + "@org_golang_x_exp//maps", + ], +) + +go_test( + name = "uptimetracker_test", + srcs = ["uptime_tracker_test.go"], + embed = [":uptimetracker"], + deps = [ + "//database/memdb", + "//ids", + "//snow/validators", + "//snow/validators/validatorstest", + "//utils/timer/mockable", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/example/xsvm/BUILD.bazel b/vms/example/xsvm/BUILD.bazel new file mode 100644 index 000000000000..2d9f15e9a6bc --- /dev/null +++ b/vms/example/xsvm/BUILD.bazel @@ -0,0 +1,41 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "xsvm", + srcs = [ + "constants.go", + "factory.go", + "vm.go", + "warp.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm", + visibility = ["//visibility:public"], + deps = [ + "//connectproto/pb/xsvm/xsvmconnect", + "//database", + "//database/versiondb", + "//ids", + "//network/p2p", + "//network/p2p/acp118", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils/constants", + "//utils/json", + "//utils/logging", + "//vms", + "//vms/example/xsvm/api", + "//vms/example/xsvm/block", + "//vms/example/xsvm/builder", + "//vms/example/xsvm/chain", + "//vms/example/xsvm/execute", + "//vms/example/xsvm/genesis", + "//vms/example/xsvm/state", + "//vms/platformvm/warp", + "@com_connectrpc_grpcreflect//:grpcreflect", + "@com_github_gorilla_rpc//v2:rpc", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) diff --git a/vms/example/xsvm/api/BUILD.bazel b/vms/example/xsvm/api/BUILD.bazel new file mode 100644 index 000000000000..fc0b00295f47 --- /dev/null +++ b/vms/example/xsvm/api/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "api", + srcs = [ + "client.go", + "ping.go", + "server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/api", + visibility = ["//visibility:public"], + deps = [ + "//connectproto/pb/xsvm", + "//connectproto/pb/xsvm/xsvmconnect", + "//database", + "//ids", + "//snow", + "//utils/constants", + "//utils/logging", + "//utils/rpc", + "//vms/example/xsvm/block", + "//vms/example/xsvm/builder", + "//vms/example/xsvm/chain", + "//vms/example/xsvm/genesis", + "//vms/example/xsvm/state", + "//vms/example/xsvm/tx", + "//vms/platformvm/warp", + "@com_connectrpc_connect//:connect", + "@org_uber_go_zap//:zap", + ], +) diff --git a/vms/example/xsvm/block/BUILD.bazel b/vms/example/xsvm/block/BUILD.bazel new file mode 100644 index 000000000000..d0150806ef19 --- /dev/null +++ b/vms/example/xsvm/block/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "block", + srcs = [ + "block.go", + "codec.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/block", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/hashing", + "//vms/example/xsvm/tx", + ], +) diff --git a/vms/example/xsvm/builder/BUILD.bazel b/vms/example/xsvm/builder/BUILD.bazel new file mode 100644 index 000000000000..67dad3aff5ca --- /dev/null +++ b/vms/example/xsvm/builder/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "builder", + srcs = ["builder.go"], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/builder", + visibility = ["//visibility:public"], + deps = [ + "//database/versiondb", + "//ids", + "//snow", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils/linked", + "//utils/lock", + "//vms/example/xsvm/block", + "//vms/example/xsvm/chain", + "//vms/example/xsvm/execute", + "//vms/example/xsvm/tx", + ], +) diff --git a/vms/example/xsvm/chain/BUILD.bazel b/vms/example/xsvm/chain/BUILD.bazel new file mode 100644 index 000000000000..c44e8e8b7b6a --- /dev/null +++ b/vms/example/xsvm/chain/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "chain", + srcs = [ + "block.go", + "chain.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/chain", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//database/versiondb", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/snowman/block", + "//utils/set", + "//vms/example/xsvm/block", + "//vms/example/xsvm/execute", + "//vms/example/xsvm/state", + ], +) diff --git a/vms/example/xsvm/cmd/account/BUILD.bazel b/vms/example/xsvm/cmd/account/BUILD.bazel new file mode 100644 index 000000000000..f306c03554a3 --- /dev/null +++ b/vms/example/xsvm/cmd/account/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "account", + srcs = [ + "cmd.go", + "flags.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/account", + visibility = ["//visibility:public"], + deps = [ + "//genesis", + "//ids", + "//vms/example/xsvm/api", + "//wallet/subnet/primary", + "@com_github_spf13_cobra//:cobra", + "@com_github_spf13_pflag//:pflag", + ], +) diff --git a/vms/example/xsvm/cmd/chain/BUILD.bazel b/vms/example/xsvm/cmd/chain/BUILD.bazel new file mode 100644 index 000000000000..9f8ddafd541a --- /dev/null +++ b/vms/example/xsvm/cmd/chain/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "chain", + srcs = ["cmd.go"], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/chain", + visibility = ["//visibility:public"], + deps = [ + "//vms/example/xsvm/cmd/chain/create", + "//vms/example/xsvm/cmd/chain/genesis", + "@com_github_spf13_cobra//:cobra", + ], +) diff --git a/vms/example/xsvm/cmd/chain/create/BUILD.bazel b/vms/example/xsvm/cmd/chain/create/BUILD.bazel new file mode 100644 index 000000000000..ec5df8a6295c --- /dev/null +++ b/vms/example/xsvm/cmd/chain/create/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "create", + srcs = [ + "cmd.go", + "flags.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/chain/create", + visibility = ["//visibility:public"], + deps = [ + "//genesis", + "//ids", + "//utils/constants", + "//utils/crypto/secp256k1", + "//vms/example/xsvm/genesis", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + "//wallet/subnet/primary/common", + "@com_github_spf13_cobra//:cobra", + "@com_github_spf13_pflag//:pflag", + ], +) diff --git a/vms/example/xsvm/cmd/chain/genesis/BUILD.bazel b/vms/example/xsvm/cmd/chain/genesis/BUILD.bazel new file mode 100644 index 000000000000..03573ec119d9 --- /dev/null +++ b/vms/example/xsvm/cmd/chain/genesis/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "genesis", + srcs = [ + "cmd.go", + "flags.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/chain/genesis", + visibility = ["//visibility:public"], + deps = [ + "//genesis", + "//ids", + "//utils/formatting", + "//vms/example/xsvm/genesis", + "@com_github_spf13_cobra//:cobra", + "@com_github_spf13_pflag//:pflag", + ], +) diff --git a/vms/example/xsvm/cmd/issue/BUILD.bazel b/vms/example/xsvm/cmd/issue/BUILD.bazel new file mode 100644 index 000000000000..5f7c57281e90 --- /dev/null +++ b/vms/example/xsvm/cmd/issue/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "issue", + srcs = ["cmd.go"], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/issue", + visibility = ["//visibility:public"], + deps = [ + "//vms/example/xsvm/cmd/issue/export", + "//vms/example/xsvm/cmd/issue/importtx", + "//vms/example/xsvm/cmd/issue/transfer", + "@com_github_spf13_cobra//:cobra", + ], +) diff --git a/vms/example/xsvm/cmd/issue/export/BUILD.bazel b/vms/example/xsvm/cmd/issue/export/BUILD.bazel new file mode 100644 index 000000000000..2aec8c9d44d0 --- /dev/null +++ b/vms/example/xsvm/cmd/issue/export/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "export", + srcs = [ + "cmd.go", + "flags.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/issue/export", + visibility = ["//visibility:public"], + deps = [ + "//genesis", + "//ids", + "//utils/crypto/secp256k1", + "//utils/units", + "//vms/example/xsvm/api", + "//vms/example/xsvm/cmd/issue/status", + "//vms/example/xsvm/tx", + "//wallet/subnet/primary", + "@com_github_spf13_cobra//:cobra", + "@com_github_spf13_pflag//:pflag", + ], +) diff --git a/vms/example/xsvm/cmd/issue/importtx/BUILD.bazel b/vms/example/xsvm/cmd/issue/importtx/BUILD.bazel new file mode 100644 index 000000000000..387dd269850d --- /dev/null +++ b/vms/example/xsvm/cmd/issue/importtx/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "importtx", + srcs = [ + "cmd.go", + "flags.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/issue/importtx", + visibility = ["//visibility:public"], + deps = [ + "//api/info", + "//genesis", + "//ids", + "//utils/crypto/bls", + "//utils/crypto/secp256k1", + "//utils/set", + "//vms/example/xsvm/api", + "//vms/example/xsvm/cmd/issue/status", + "//vms/example/xsvm/tx", + "//vms/platformvm/warp", + "//wallet/subnet/primary", + "@com_github_spf13_cobra//:cobra", + "@com_github_spf13_pflag//:pflag", + ], +) diff --git a/vms/example/xsvm/cmd/issue/status/BUILD.bazel b/vms/example/xsvm/cmd/issue/status/BUILD.bazel new file mode 100644 index 000000000000..4dfe0d4377f1 --- /dev/null +++ b/vms/example/xsvm/cmd/issue/status/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "status", + srcs = ["status.go"], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/issue/status", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//vms/example/xsvm/tx", + ], +) diff --git a/vms/example/xsvm/cmd/issue/transfer/BUILD.bazel b/vms/example/xsvm/cmd/issue/transfer/BUILD.bazel new file mode 100644 index 000000000000..87ad14a54411 --- /dev/null +++ b/vms/example/xsvm/cmd/issue/transfer/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "transfer", + srcs = [ + "cmd.go", + "flags.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/issue/transfer", + visibility = ["//visibility:public"], + deps = [ + "//genesis", + "//ids", + "//utils/crypto/secp256k1", + "//utils/units", + "//vms/example/xsvm/api", + "//vms/example/xsvm/cmd/issue/status", + "//vms/example/xsvm/tx", + "//wallet/subnet/primary", + "@com_github_spf13_cobra//:cobra", + "@com_github_spf13_pflag//:pflag", + ], +) diff --git a/vms/example/xsvm/cmd/run/BUILD.bazel b/vms/example/xsvm/cmd/run/BUILD.bazel new file mode 100644 index 000000000000..a97eb30fc245 --- /dev/null +++ b/vms/example/xsvm/cmd/run/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "run", + srcs = ["cmd.go"], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/run", + visibility = ["//visibility:public"], + deps = [ + "//vms/example/xsvm", + "//vms/rpcchainvm", + "@com_github_spf13_cobra//:cobra", + ], +) diff --git a/vms/example/xsvm/cmd/version/BUILD.bazel b/vms/example/xsvm/cmd/version/BUILD.bazel new file mode 100644 index 000000000000..7a0d310e780d --- /dev/null +++ b/vms/example/xsvm/cmd/version/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "version", + srcs = ["cmd.go"], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/version", + visibility = ["//visibility:public"], + deps = [ + "//utils/constants", + "//version", + "//vms/example/xsvm", + "@com_github_spf13_cobra//:cobra", + ], +) diff --git a/vms/example/xsvm/cmd/versionjson/BUILD.bazel b/vms/example/xsvm/cmd/versionjson/BUILD.bazel new file mode 100644 index 000000000000..6828acf3638c --- /dev/null +++ b/vms/example/xsvm/cmd/versionjson/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "versionjson", + srcs = ["cmd.go"], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/versionjson", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/constants", + "//version", + "//vms/example/xsvm", + "@com_github_spf13_cobra//:cobra", + ], +) diff --git a/vms/example/xsvm/cmd/xsvm/BUILD.bazel b/vms/example/xsvm/cmd/xsvm/BUILD.bazel new file mode 100644 index 000000000000..5330be56bcd7 --- /dev/null +++ b/vms/example/xsvm/cmd/xsvm/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "xsvm_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/xsvm", + visibility = ["//visibility:private"], + deps = [ + "//vms/example/xsvm/cmd/account", + "//vms/example/xsvm/cmd/chain", + "//vms/example/xsvm/cmd/issue", + "//vms/example/xsvm/cmd/run", + "//vms/example/xsvm/cmd/version", + "//vms/example/xsvm/cmd/versionjson", + "@com_github_spf13_cobra//:cobra", + ], +) + +go_binary( + name = "xsvm", + embed = [":xsvm_lib"], + visibility = ["//visibility:public"], +) diff --git a/vms/example/xsvm/execute/BUILD.bazel b/vms/example/xsvm/execute/BUILD.bazel new file mode 100644 index 000000000000..ebeef577c899 --- /dev/null +++ b/vms/example/xsvm/execute/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "execute", + srcs = [ + "block.go", + "expects_context.go", + "genesis.go", + "tx.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/execute", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/engine/snowman/block", + "//utils/hashing", + "//utils/wrappers", + "//vms/example/xsvm/block", + "//vms/example/xsvm/genesis", + "//vms/example/xsvm/state", + "//vms/example/xsvm/tx", + "//vms/platformvm/warp", + ], +) diff --git a/vms/example/xsvm/genesis/BUILD.bazel b/vms/example/xsvm/genesis/BUILD.bazel new file mode 100644 index 000000000000..91db2c82ea3a --- /dev/null +++ b/vms/example/xsvm/genesis/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "genesis", + srcs = [ + "codec.go", + "genesis.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/genesis", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/hashing", + "//vms/example/xsvm/block", + ], +) + +go_test( + name = "genesis_test", + srcs = ["genesis_test.go"], + embed = [":genesis"], + deps = [ + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/example/xsvm/state/BUILD.bazel b/vms/example/xsvm/state/BUILD.bazel new file mode 100644 index 000000000000..87dbcc37fd8c --- /dev/null +++ b/vms/example/xsvm/state/BUILD.bazel @@ -0,0 +1,17 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "state", + srcs = [ + "keys.go", + "storage.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/state", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//utils/math", + "//vms/platformvm/warp", + ], +) diff --git a/vms/example/xsvm/tx/BUILD.bazel b/vms/example/xsvm/tx/BUILD.bazel new file mode 100644 index 000000000000..3ae2a23bdce0 --- /dev/null +++ b/vms/example/xsvm/tx/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "tx", + srcs = [ + "codec.go", + "export.go", + "import.go", + "payload.go", + "transfer.go", + "tx.go", + "unsigned.go", + "visitor.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/example/xsvm/tx", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//utils/crypto/secp256k1", + "//utils/hashing", + ], +) diff --git a/vms/fx/BUILD.bazel b/vms/fx/BUILD.bazel new file mode 100644 index 000000000000..0dfae1973d26 --- /dev/null +++ b/vms/fx/BUILD.bazel @@ -0,0 +1,8 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "fx", + srcs = ["factory.go"], + importpath = "github.com/ava-labs/avalanchego/vms/fx", + visibility = ["//visibility:public"], +) diff --git a/vms/metervm/BUILD.bazel b/vms/metervm/BUILD.bazel new file mode 100644 index 000000000000..1b686ac9d9a8 --- /dev/null +++ b/vms/metervm/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "metervm", + srcs = [ + "batched_vm.go", + "block.go", + "block_metrics.go", + "block_vm.go", + "build_block_with_context_vm.go", + "metrics.go", + "set_preference_with_context_vm.go", + "state_syncable_vm.go", + "vertex_metrics.go", + "vertex_vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/metervm", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/consensus/snowstorm", + "//snow/engine/avalanche/vertex", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils/metric", + "//utils/wrappers", + "@com_github_prometheus_client_golang//prometheus", + ], +) diff --git a/vms/nftfx/BUILD.bazel b/vms/nftfx/BUILD.bazel new file mode 100644 index 000000000000..e18c6a57f5af --- /dev/null +++ b/vms/nftfx/BUILD.bazel @@ -0,0 +1,49 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "nftfx", + srcs = [ + "credential.go", + "factory.go", + "fx.go", + "mint_operation.go", + "mint_output.go", + "transfer_operation.go", + "transfer_output.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/nftfx", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//utils/units", + "//vms/components/verify", + "//vms/fx", + "//vms/secp256k1fx", + "//vms/types", + ], +) + +go_test( + name = "nftfx_test", + srcs = [ + "credential_test.go", + "factory_test.go", + "fx_test.go", + "mint_operation_test.go", + "mint_output_test.go", + "transfer_operation_test.go", + "transfer_output_test.go", + ], + embed = [":nftfx"], + deps = [ + "//codec/linearcodec", + "//ids", + "//utils/crypto/secp256k1", + "//utils/hashing", + "//utils/logging", + "//vms/components/verify", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/BUILD.bazel b/vms/platformvm/BUILD.bazel new file mode 100644 index 000000000000..e6d4d76c06c5 --- /dev/null +++ b/vms/platformvm/BUILD.bazel @@ -0,0 +1,167 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "platformvm", + srcs = [ + "client.go", + "client_permissionless_validator.go", + "factory.go", + "health.go", + "service.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm", + visibility = ["//visibility:public"], + deps = [ + "//api", + "//api/metrics", + "//cache/lru", + "//codec", + "//codec/linearcodec", + "//database", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//snow/uptime", + "//snow/validators", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/formatting", + "//utils/formatting/address", + "//utils/json", + "//utils/logging", + "//utils/math", + "//utils/rpc", + "//utils/set", + "//utils/timer/mockable", + "//version", + "//vms", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/api", + "//vms/platformvm/block", + "//vms/platformvm/block/builder", + "//vms/platformvm/block/executor", + "//vms/platformvm/config", + "//vms/platformvm/fx", + "//vms/platformvm/metrics", + "//vms/platformvm/network", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/stakeable", + "//vms/platformvm/state", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/executor", + "//vms/platformvm/txs/mempool", + "//vms/platformvm/utxo", + "//vms/platformvm/validators", + "//vms/platformvm/validators/fee", + "//vms/platformvm/warp/message", + "//vms/secp256k1fx", + "//vms/txs/mempool", + "//vms/types", + "@com_github_gorilla_rpc//v2:rpc", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "platformvm_test", + srcs = [ + "main_test.go", + "service_test.go", + "validator_set_property_test.go", + "vm_regression_test.go", + "vm_test.go", + ], + embed = [":platformvm"], + deps = [ + "//api", + "//cache/lru", + "//chains", + "//chains/atomic", + "//database", + "//database/memdb", + "//database/prefixdb", + "//ids", + "//message", + "//network/p2p", + "//network/p2p/gossip", + "//proto/pb/p2p", + "//snow", + "//snow/consensus/snowball", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/common/tracker", + "//snow/engine/enginetest", + "//snow/engine/snowman", + "//snow/engine/snowman/block", + "//snow/engine/snowman/bootstrap", + "//snow/engine/snowman/getter", + "//snow/networking/benchlist", + "//snow/networking/handler", + "//snow/networking/router", + "//snow/networking/sender", + "//snow/networking/sender/sendertest", + "//snow/networking/timeout", + "//snow/networking/tracker", + "//snow/snowtest", + "//snow/uptime", + "//snow/validators", + "//subnets", + "//upgrade/upgradetest", + "//utils/bloom", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/formatting", + "//utils/formatting/address", + "//utils/json", + "//utils/logging", + "//utils/math/meter", + "//utils/resource", + "//utils/set", + "//utils/timer", + "//utils/timer/mockable", + "//utils/units", + "//version", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/api", + "//vms/platformvm/block", + "//vms/platformvm/block/builder", + "//vms/platformvm/block/executor", + "//vms/platformvm/block/executor/executormock", + "//vms/platformvm/config", + "//vms/platformvm/genesis/genesistest", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/state", + "//vms/platformvm/state/statetest", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/executor", + "//vms/platformvm/txs/txstest", + "//vms/platformvm/validators/fee", + "//vms/platformvm/warp/message", + "//vms/secp256k1fx", + "//vms/types", + "//wallet/chain/p/builder", + "//wallet/chain/p/wallet", + "//wallet/subnet/primary/common", + "@com_github_leanovate_gopter//:gopter", + "@com_github_leanovate_gopter//gen", + "@com_github_leanovate_gopter//prop", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_x_exp//maps", + "@org_golang_x_sync//errgroup", + "@org_uber_go_goleak//:goleak", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/api/BUILD.bazel b/vms/platformvm/api/BUILD.bazel new file mode 100644 index 000000000000..0ec8df8f7e55 --- /dev/null +++ b/vms/platformvm/api/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "api", + srcs = [ + "height.go", + "validator.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/api", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/json", + "//vms/platformvm/signer", + "//vms/types", + ], +) + +go_test( + name = "api_test", + srcs = ["height_test.go"], + embed = [":api"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/vms/platformvm/block/BUILD.bazel b/vms/platformvm/block/BUILD.bazel new file mode 100644 index 000000000000..41ebfc7ccc6c --- /dev/null +++ b/vms/platformvm/block/BUILD.bazel @@ -0,0 +1,56 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "block", + srcs = [ + "abort_block.go", + "atomic_block.go", + "block.go", + "codec.go", + "commit_block.go", + "common_block.go", + "mock_block.go", + "parse.go", + "proposal_block.go", + "standard_block.go", + "visitor.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/block", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//snow", + "//utils/hashing", + "//utils/wrappers", + "//vms/platformvm/txs", + "@org_uber_go_mock//gomock", + ], +) + +go_test( + name = "block_test", + srcs = [ + "abort_block_test.go", + "atomic_block_test.go", + "commit_block_test.go", + "mocks_generate_test.go", + "parse_test.go", + "proposal_block_test.go", + "serialization_test.go", + "standard_block_test.go", + ], + embed = [":block"], + deps = [ + "//codec", + "//ids", + "//utils/constants", + "//utils/crypto/secp256k1", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/block/builder/BUILD.bazel b/vms/platformvm/block/builder/BUILD.bazel new file mode 100644 index 000000000000..a4beaf38a9dc --- /dev/null +++ b/vms/platformvm/block/builder/BUILD.bazel @@ -0,0 +1,91 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "builder", + srcs = ["builder.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/block/builder", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//utils/set", + "//utils/timer/mockable", + "//utils/units", + "//vms/components/gas", + "//vms/platformvm/block", + "//vms/platformvm/block/executor", + "//vms/platformvm/state", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/executor", + "//vms/platformvm/txs/fee", + "//vms/platformvm/txs/mempool", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "builder_test", + srcs = [ + "builder_test.go", + "helpers_test.go", + "main_test.go", + "standard_block_test.go", + ], + embed = [":builder"], + deps = [ + "//chains", + "//chains/atomic", + "//codec", + "//codec/linearcodec", + "//database/memdb", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/snowtest", + "//snow/uptime", + "//snow/validators", + "//upgrade/upgradetest", + "//utils", + "//utils/constants", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/iterator", + "//utils/logging", + "//utils/timer/mockable", + "//utils/units", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/block", + "//vms/platformvm/block/executor", + "//vms/platformvm/config", + "//vms/platformvm/fx", + "//vms/platformvm/genesis/genesistest", + "//vms/platformvm/metrics", + "//vms/platformvm/network", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/state", + "//vms/platformvm/state/statetest", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/executor", + "//vms/platformvm/txs/mempool", + "//vms/platformvm/txs/txstest", + "//vms/platformvm/utxo", + "//vms/platformvm/validators/validatorstest", + "//vms/secp256k1fx", + "//wallet/chain/p/wallet", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_goleak//:goleak", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/block/executor/BUILD.bazel b/vms/platformvm/block/executor/BUILD.bazel new file mode 100644 index 000000000000..5b56fbfd2857 --- /dev/null +++ b/vms/platformvm/block/executor/BUILD.bazel @@ -0,0 +1,124 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "executor", + srcs = [ + "acceptor.go", + "backend.go", + "block.go", + "block_state.go", + "manager.go", + "options.go", + "rejector.go", + "verifier.go", + "warp_verifier.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/block/executor", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/snowman/block", + "//snow/uptime", + "//snow/validators", + "//utils/constants", + "//utils/logging", + "//utils/math", + "//utils/set", + "//vms/components/gas", + "//vms/platformvm/block", + "//vms/platformvm/config", + "//vms/platformvm/metrics", + "//vms/platformvm/reward", + "//vms/platformvm/state", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/executor", + "//vms/platformvm/txs/fee", + "//vms/platformvm/txs/mempool", + "//vms/platformvm/validators", + "//vms/platformvm/validators/fee", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "executor_test", + srcs = [ + "acceptor_test.go", + "backend_test.go", + "block_test.go", + "helpers_test.go", + "manager_test.go", + "mocks_generate_test.go", + "options_test.go", + "proposal_block_test.go", + "rejector_test.go", + "standard_block_test.go", + "verifier_test.go", + "warp_verifier_test.go", + ], + embed = [":executor"], + deps = [ + "//chains", + "//chains/atomic", + "//chains/atomic/atomicmock", + "//codec", + "//codec/linearcodec", + "//database", + "//database/databasemock", + "//database/memdb", + "//database/prefixdb", + "//database/versiondb", + "//genesis", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/snowman/block", + "//snow/snowtest", + "//snow/uptime", + "//snow/uptime/uptimemock", + "//snow/validators", + "//upgrade", + "//upgrade/upgradetest", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/iterator", + "//utils/logging", + "//utils/set", + "//utils/timer/mockable", + "//utils/units", + "//vms/components/avax", + "//vms/components/gas", + "//vms/components/verify", + "//vms/platformvm/block", + "//vms/platformvm/config", + "//vms/platformvm/fx", + "//vms/platformvm/genesis/genesistest", + "//vms/platformvm/metrics", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/state", + "//vms/platformvm/state/statetest", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/executor", + "//vms/platformvm/txs/fee", + "//vms/platformvm/txs/mempool", + "//vms/platformvm/txs/txstest", + "//vms/platformvm/utxo", + "//vms/platformvm/validators/fee", + "//vms/platformvm/validators/validatorstest", + "//vms/secp256k1fx", + "//wallet/chain/p/wallet", + "//wallet/subnet/primary/common", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/block/executor/executormock/BUILD.bazel b/vms/platformvm/block/executor/executormock/BUILD.bazel new file mode 100644 index 000000000000..41be826ef9db --- /dev/null +++ b/vms/platformvm/block/executor/executormock/BUILD.bazel @@ -0,0 +1,18 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "executormock", + srcs = ["manager.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/block/executor/executormock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/consensus/snowman", + "//snow/engine/snowman/block", + "//utils/set", + "//vms/platformvm/block", + "//vms/platformvm/state", + "//vms/platformvm/txs", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/config/BUILD.bazel b/vms/platformvm/config/BUILD.bazel new file mode 100644 index 000000000000..065d8915292e --- /dev/null +++ b/vms/platformvm/config/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "config", + srcs = [ + "config.go", + "internal.go", + "network.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/config", + visibility = ["//visibility:public"], + deps = [ + "//chains", + "//ids", + "//snow/uptime", + "//snow/validators", + "//upgrade", + "//utils/constants", + "//utils/set", + "//utils/units", + "//vms/components/gas", + "//vms/platformvm/reward", + "//vms/platformvm/txs", + "//vms/platformvm/validators/fee", + ], +) + +go_test( + name = "config_test", + srcs = ["config_test.go"], + embed = [":config"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/vms/platformvm/fx/BUILD.bazel b/vms/platformvm/fx/BUILD.bazel new file mode 100644 index 000000000000..2fb2ecdd00fc --- /dev/null +++ b/vms/platformvm/fx/BUILD.bazel @@ -0,0 +1,19 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "fx", + srcs = ["fx.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/fx", + visibility = ["//visibility:public"], + deps = [ + "//snow", + "//vms/components/verify", + "//vms/secp256k1fx", + ], +) + +go_test( + name = "fx_test", + srcs = ["mocks_generate_test.go"], + embed = [":fx"], +) diff --git a/vms/platformvm/fx/fxmock/BUILD.bazel b/vms/platformvm/fx/fxmock/BUILD.bazel new file mode 100644 index 000000000000..02a7b6fb1ea7 --- /dev/null +++ b/vms/platformvm/fx/fxmock/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "fxmock", + srcs = [ + "fx.go", + "owner.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/fx/fxmock", + visibility = ["//visibility:public"], + deps = [ + "//snow", + "//vms/components/verify", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/genesis/BUILD.bazel b/vms/platformvm/genesis/BUILD.bazel new file mode 100644 index 000000000000..50b913ed1984 --- /dev/null +++ b/vms/platformvm/genesis/BUILD.bazel @@ -0,0 +1,38 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "genesis", + srcs = [ + "codec.go", + "genesis.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/genesis", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils", + "//utils/formatting/address", + "//utils/math", + "//vms/components/avax", + "//vms/platformvm/block", + "//vms/platformvm/signer", + "//vms/platformvm/stakeable", + "//vms/platformvm/txs", + "//vms/platformvm/txs/txheap", + "//vms/secp256k1fx", + ], +) + +go_test( + name = "genesis_test", + srcs = ["genesis_test.go"], + embed = [":genesis"], + deps = [ + "//ids", + "//utils/constants", + "//utils/formatting/address", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/genesis/genesistest/BUILD.bazel b/vms/platformvm/genesis/genesistest/BUILD.bazel new file mode 100644 index 000000000000..4657146f4474 --- /dev/null +++ b/vms/platformvm/genesis/genesistest/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "genesistest", + srcs = ["genesis.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/genesis/genesistest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/snowtest", + "//upgrade", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/units", + "//vms/components/avax", + "//vms/platformvm/genesis", + "//vms/platformvm/reward", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/metrics/BUILD.bazel b/vms/platformvm/metrics/BUILD.bazel new file mode 100644 index 000000000000..6157c6292d1c --- /dev/null +++ b/vms/platformvm/metrics/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "metrics", + srcs = [ + "block_metrics.go", + "metrics.go", + "no_op.go", + "tx_metrics.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/metrics", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/metric", + "//utils/wrappers", + "//vms/components/gas", + "//vms/platformvm/block", + "//vms/platformvm/txs", + "@com_github_gorilla_rpc//v2:rpc", + "@com_github_prometheus_client_golang//prometheus", + ], +) diff --git a/vms/platformvm/network/BUILD.bazel b/vms/platformvm/network/BUILD.bazel new file mode 100644 index 000000000000..05ede186043c --- /dev/null +++ b/vms/platformvm/network/BUILD.bazel @@ -0,0 +1,77 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "network", + srcs = [ + "gossip.go", + "network.go", + "tx_verifier.go", + "warp.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/network", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//network/p2p", + "//network/p2p/acp118", + "//network/p2p/gossip", + "//proto/pb/platformvm", + "//snow/engine/common", + "//snow/validators", + "//utils/logging", + "//vms/platformvm/config", + "//vms/platformvm/state", + "//vms/platformvm/txs", + "//vms/platformvm/txs/mempool", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/txs/mempool", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "network_test", + srcs = [ + "gossip_test.go", + "main_test.go", + "network_test.go", + "warp_test.go", + ], + embed = [":network"], + deps = [ + "//ids", + "//proto/pb/platformvm", + "//snow/engine/common", + "//snow/engine/common/commonmock", + "//snow/snowtest", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/logging", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/config", + "//vms/platformvm/genesis/genesistest", + "//vms/platformvm/state", + "//vms/platformvm/state/statetest", + "//vms/platformvm/txs", + "//vms/platformvm/txs/mempool", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/secp256k1fx", + "//vms/txs/mempool", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + "@org_golang_x_exp//rand", + "@org_uber_go_goleak//:goleak", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/reward/BUILD.bazel b/vms/platformvm/reward/BUILD.bazel new file mode 100644 index 000000000000..1148a01724f0 --- /dev/null +++ b/vms/platformvm/reward/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "reward", + srcs = [ + "calculator.go", + "config.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/reward", + visibility = ["//visibility:public"], + deps = ["//utils/math"], +) + +go_test( + name = "reward_test", + srcs = [ + "calculator_test.go", + "example_test.go", + ], + embed = [":reward"], + deps = [ + "//utils/units", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/signer/BUILD.bazel b/vms/platformvm/signer/BUILD.bazel new file mode 100644 index 000000000000..f1bdcea7d3a3 --- /dev/null +++ b/vms/platformvm/signer/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "signer", + srcs = [ + "empty.go", + "proof_of_possession.go", + "signer.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/signer", + visibility = ["//visibility:public"], + deps = [ + "//utils/crypto/bls", + "//utils/formatting", + "//vms/components/verify", + ], +) + +go_test( + name = "signer_test", + srcs = [ + "empty_test.go", + "mocks_generate_test.go", + "proof_of_possession_test.go", + ], + embed = [":signer"], + deps = [ + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/signer/signermock/BUILD.bazel b/vms/platformvm/signer/signermock/BUILD.bazel new file mode 100644 index 000000000000..84174de7ff34 --- /dev/null +++ b/vms/platformvm/signer/signermock/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "signermock", + srcs = ["signer.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/signer/signermock", + visibility = ["//visibility:public"], + deps = [ + "//utils/crypto/bls", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/stakeable/BUILD.bazel b/vms/platformvm/stakeable/BUILD.bazel new file mode 100644 index 000000000000..abea6475e8be --- /dev/null +++ b/vms/platformvm/stakeable/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "stakeable", + srcs = ["stakeable_lock.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/stakeable", + visibility = ["//visibility:public"], + deps = ["//vms/components/avax"], +) + +go_test( + name = "stakeable_test", + srcs = ["stakeable_lock_test.go"], + embed = [":stakeable"], + deps = [ + "//vms/components/avax", + "//vms/components/avax/avaxmock", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/state/BUILD.bazel b/vms/platformvm/state/BUILD.bazel new file mode 100644 index 000000000000..5567d3d7861f --- /dev/null +++ b/vms/platformvm/state/BUILD.bazel @@ -0,0 +1,139 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "state", + srcs = [ + "chain_time_helpers.go", + "diff.go", + "disk_staker_diff_iterator.go", + "expiry.go", + "l1_validator.go", + "metadata_codec.go", + "metadata_delegator.go", + "metadata_validator.go", + "mock_chain.go", + "mock_diff.go", + "mock_state.go", + "staker.go", + "staker_diff_iterator.go", + "staker_status.go", + "stakers.go", + "state.go", + "subnet_id_node_id.go", + "versions.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/state", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//cache/metercacher", + "//codec", + "//codec/linearcodec", + "//database", + "//database/linkeddb", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//snow", + "//snow/choices", + "//snow/uptime", + "//snow/validators", + "//upgrade", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/hashing", + "//utils/heap", + "//utils/iterator", + "//utils/logging", + "//utils/math", + "//utils/maybe", + "//utils/set", + "//utils/timer", + "//utils/timer/mockable", + "//utils/wrappers", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/block", + "//vms/platformvm/config", + "//vms/platformvm/fx", + "//vms/platformvm/genesis", + "//vms/platformvm/metrics", + "//vms/platformvm/reward", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/fee", + "//vms/platformvm/validators/fee", + "@com_github_google_btree//:btree", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_x_exp//maps", + "@org_uber_go_mock//gomock", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "state_test", + srcs = [ + "chain_time_helpers_test.go", + "diff_test.go", + "disk_staker_diff_iterator_test.go", + "expiry_test.go", + "l1_validator_test.go", + "metadata_delegator_test.go", + "metadata_validator_test.go", + "mocks_generate_test.go", + "staker_diff_iterator_test.go", + "staker_test.go", + "stakers_test.go", + "state_test.go", + "subnet_id_node_id_test.go", + ], + embed = [":state"], + deps = [ + "//cache", + "//cache/lru", + "//codec", + "//database", + "//database/memdb", + "//genesis", + "//ids", + "//snow", + "//snow/choices", + "//snow/validators", + "//upgrade/upgradetest", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/iterator", + "//utils/logging", + "//utils/math", + "//utils/maybe", + "//utils/set", + "//utils/timer/mockable", + "//utils/units", + "//utils/wrappers", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/block", + "//vms/platformvm/config", + "//vms/platformvm/fx/fxmock", + "//vms/platformvm/genesis/genesistest", + "//vms/platformvm/metrics", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/signer/signermock", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/fee", + "//vms/platformvm/validators/fee", + "//vms/secp256k1fx", + "//vms/types", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@com_github_thepudds_fzgen//fuzzer", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/state/statetest/BUILD.bazel b/vms/platformvm/state/statetest/BUILD.bazel new file mode 100644 index 000000000000..1e077bfded5e --- /dev/null +++ b/vms/platformvm/state/statetest/BUILD.bazel @@ -0,0 +1,27 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "statetest", + srcs = ["state.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/state/statetest", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//database/memdb", + "//ids", + "//snow", + "//snow/validators", + "//upgrade", + "//upgrade/upgradetest", + "//utils/constants", + "//utils/logging", + "//utils/units", + "//vms/platformvm/config", + "//vms/platformvm/genesis/genesistest", + "//vms/platformvm/metrics", + "//vms/platformvm/reward", + "//vms/platformvm/state", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/status/BUILD.bazel b/vms/platformvm/status/BUILD.bazel new file mode 100644 index 000000000000..e1baee7bd36f --- /dev/null +++ b/vms/platformvm/status/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "status", + srcs = [ + "blockchain_status.go", + "status.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/status", + visibility = ["//visibility:public"], + deps = ["//vms/components/verify"], +) + +go_test( + name = "status_test", + srcs = [ + "blockchain_status_test.go", + "status_test.go", + ], + embed = [":status"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/vms/platformvm/txs/BUILD.bazel b/vms/platformvm/txs/BUILD.bazel new file mode 100644 index 000000000000..2d0a5ed63e33 --- /dev/null +++ b/vms/platformvm/txs/BUILD.bazel @@ -0,0 +1,122 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "txs", + srcs = [ + "add_delegator_tx.go", + "add_permissionless_delegator_tx.go", + "add_permissionless_validator_tx.go", + "add_subnet_validator_tx.go", + "add_validator_tx.go", + "advance_time_tx.go", + "base_tx.go", + "codec.go", + "convert_subnet_to_l1_tx.go", + "create_chain_tx.go", + "create_subnet_tx.go", + "disable_l1_validator_tx.go", + "export_tx.go", + "import_tx.go", + "increase_l1_validator_balance_tx.go", + "priorities.go", + "register_l1_validator_tx.go", + "remove_subnet_validator_tx.go", + "reward_validator_tx.go", + "set_l1_validator_weight_tx.go", + "staker_tx.go", + "subnet_validator.go", + "transfer_subnet_ownership_tx.go", + "transform_subnet_tx.go", + "tx.go", + "unsigned_tx.go", + "validator.go", + "visitor.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/txs", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//network/p2p/gossip", + "//snow", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/secp256k1", + "//utils/hashing", + "//utils/math", + "//utils/set", + "//utils/units", + "//utils/wrappers", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm/fx", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/stakeable", + "//vms/platformvm/warp/message", + "//vms/secp256k1fx", + "//vms/types", + ], +) + +go_test( + name = "txs_test", + srcs = [ + "add_delegator_test.go", + "add_permissionless_delegator_tx_test.go", + "add_permissionless_validator_tx_test.go", + "add_subnet_validator_test.go", + "add_validator_test.go", + "base_tx_test.go", + "convert_subnet_to_l1_tx_test.go", + "create_chain_test.go", + "disable_l1_validator_tx_test.go", + "increase_l1_validator_balance_tx_test.go", + "priorities_test.go", + "register_l1_validator_tx_test.go", + "remove_subnet_validator_tx_test.go", + "set_l1_validator_weight_tx_test.go", + "subnet_validator_test.go", + "transfer_subnet_ownership_tx_test.go", + "transform_subnet_tx_test.go", + "validator_test.go", + ], + embed = [":txs"], + embedsrcs = [ + "convert_subnet_to_l1_tx_test_complex.json", + "convert_subnet_to_l1_tx_test_simple.json", + "disable_l1_validator_tx_test.json", + "increase_l1_validator_balance_tx_test.json", + "register_l1_validator_tx_test.json", + "set_l1_validator_weight_tx_test.json", + ], + deps = [ + "//ids", + "//snow", + "//snow/snowtest", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/hashing", + "//utils/math", + "//utils/timer/mockable", + "//utils/units", + "//vms/components/avax", + "//vms/components/avax/avaxmock", + "//vms/components/verify", + "//vms/components/verify/verifymock", + "//vms/platformvm/fx/fxmock", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/stakeable", + "//vms/platformvm/warp/message", + "//vms/secp256k1fx", + "//vms/types", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/txs/executor/BUILD.bazel b/vms/platformvm/txs/executor/BUILD.bazel new file mode 100644 index 000000000000..5a442147a798 --- /dev/null +++ b/vms/platformvm/txs/executor/BUILD.bazel @@ -0,0 +1,125 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "executor", + srcs = [ + "atomic_tx_executor.go", + "backend.go", + "proposal_tx_executor.go", + "staker_tx_verification.go", + "staker_tx_verification_helpers.go", + "standard_tx_executor.go", + "state_changes.go", + "subnet_tx_verification.go", + "warp_verifier.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/txs/executor", + visibility = ["//visibility:public"], + deps = [ + "//chains/atomic", + "//database", + "//ids", + "//snow", + "//snow/uptime", + "//snow/validators", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/math", + "//utils/set", + "//utils/timer/mockable", + "//vms/components/avax", + "//vms/components/gas", + "//vms/components/verify", + "//vms/platformvm/config", + "//vms/platformvm/fx", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/state", + "//vms/platformvm/txs", + "//vms/platformvm/txs/fee", + "//vms/platformvm/utxo", + "//vms/platformvm/validators/fee", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/secp256k1fx", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "executor_test", + srcs = [ + "advance_time_test.go", + "create_chain_test.go", + "export_test.go", + "helpers_test.go", + "import_test.go", + "proposal_tx_executor_test.go", + "reward_validator_test.go", + "staker_tx_verification_test.go", + "standard_tx_executor_test.go", + "state_changes_test.go", + "warp_verifier_test.go", + ], + embed = [":executor"], + deps = [ + "//chains", + "//chains/atomic", + "//codec", + "//codec/linearcodec", + "//database", + "//database/memdb", + "//database/prefixdb", + "//database/versiondb", + "//genesis", + "//ids", + "//snow", + "//snow/snowtest", + "//snow/uptime", + "//snow/validators", + "//snow/validators/validatorstest", + "//upgrade/upgradetest", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/hashing", + "//utils/iterator", + "//utils/logging", + "//utils/math", + "//utils/set", + "//utils/timer/mockable", + "//utils/units", + "//vms/components/avax", + "//vms/components/gas", + "//vms/components/verify", + "//vms/platformvm/config", + "//vms/platformvm/fx", + "//vms/platformvm/fx/fxmock", + "//vms/platformvm/genesis/genesistest", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/state", + "//vms/platformvm/state/statetest", + "//vms/platformvm/status", + "//vms/platformvm/txs", + "//vms/platformvm/txs/fee", + "//vms/platformvm/txs/txstest", + "//vms/platformvm/utxo", + "//vms/platformvm/utxo/utxomock", + "//vms/platformvm/validators/fee", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/secp256k1fx", + "//vms/types", + "//wallet/chain/p/builder", + "//wallet/chain/p/wallet", + "//wallet/subnet/primary/common", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/txs/fee/BUILD.bazel b/vms/platformvm/txs/fee/BUILD.bazel new file mode 100644 index 000000000000..8a27e181c268 --- /dev/null +++ b/vms/platformvm/txs/fee/BUILD.bazel @@ -0,0 +1,56 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "fee", + srcs = [ + "calculator.go", + "complexity.go", + "dynamic_calculator.go", + "simple_calculator.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/txs/fee", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//ids", + "//utils/crypto/bls", + "//utils/crypto/secp256k1", + "//utils/math", + "//utils/wrappers", + "//vms/components/avax", + "//vms/components/gas", + "//vms/components/verify", + "//vms/platformvm/fx", + "//vms/platformvm/signer", + "//vms/platformvm/stakeable", + "//vms/platformvm/txs", + "//vms/platformvm/warp", + "//vms/secp256k1fx", + ], +) + +go_test( + name = "fee_test", + srcs = [ + "calculator_test.go", + "complexity_test.go", + "dynamic_calculator_test.go", + ], + embed = [":fee"], + deps = [ + "//codec", + "//ids", + "//utils/crypto/secp256k1", + "//utils/units", + "//vms/components/avax", + "//vms/components/gas", + "//vms/components/verify", + "//vms/platformvm/fx", + "//vms/platformvm/signer", + "//vms/platformvm/stakeable", + "//vms/platformvm/txs", + "//vms/platformvm/warp/message", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/txs/mempool/BUILD.bazel b/vms/platformvm/txs/mempool/BUILD.bazel new file mode 100644 index 000000000000..4c977e5a1cc9 --- /dev/null +++ b/vms/platformvm/txs/mempool/BUILD.bazel @@ -0,0 +1,45 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "mempool", + srcs = ["mempool.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool", + visibility = ["//visibility:public"], + deps = [ + "//cache/lru", + "//ids", + "//snow/engine/common", + "//utils/lock", + "//utils/math", + "//utils/set", + "//utils/setmap", + "//vms/components/gas", + "//vms/platformvm/txs", + "//vms/platformvm/txs/fee", + "//vms/platformvm/utxo", + "//vms/txs/mempool", + "@com_github_google_btree//:btree", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "mempool_test", + srcs = ["mempool_test.go"], + embed = [":mempool"], + deps = [ + "//ids", + "//snow/engine/common", + "//snow/snowtest", + "//utils/set", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/txs", + "//vms/platformvm/utxo", + "//vms/secp256k1fx", + "//vms/txs/mempool", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_x_sync//errgroup", + ], +) diff --git a/vms/platformvm/txs/txheap/BUILD.bazel b/vms/platformvm/txs/txheap/BUILD.bazel new file mode 100644 index 000000000000..6145abae1429 --- /dev/null +++ b/vms/platformvm/txs/txheap/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "txheap", + srcs = [ + "by_end_time.go", + "heap.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/txs/txheap", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/heap", + "//vms/platformvm/txs", + ], +) + +go_test( + name = "txheap_test", + srcs = ["by_end_time_test.go"], + embed = [":txheap"], + deps = [ + "//ids", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/txs/txstest/BUILD.bazel b/vms/platformvm/txs/txstest/BUILD.bazel new file mode 100644 index 000000000000..98344b47ad09 --- /dev/null +++ b/vms/platformvm/txs/txstest/BUILD.bazel @@ -0,0 +1,29 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "txstest", + srcs = [ + "context.go", + "wallet.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/txs/txstest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//utils/constants", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/config", + "//vms/platformvm/fx", + "//vms/platformvm/state", + "//vms/platformvm/txs", + "//vms/platformvm/warp/message", + "//vms/secp256k1fx", + "//wallet/chain/p/builder", + "//wallet/chain/p/signer", + "//wallet/chain/p/wallet", + "//wallet/subnet/primary/common", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/utxo/BUILD.bazel b/vms/platformvm/utxo/BUILD.bazel new file mode 100644 index 000000000000..d41d6f2cb300 --- /dev/null +++ b/vms/platformvm/utxo/BUILD.bazel @@ -0,0 +1,42 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "utxo", + srcs = ["verifier.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/utxo", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//utils/hashing", + "//utils/math", + "//utils/timer/mockable", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm/fx", + "//vms/platformvm/stakeable", + "//vms/platformvm/txs", + ], +) + +go_test( + name = "utxo_test", + srcs = [ + "mocks_generate_test.go", + "verifier_test.go", + ], + embed = [":utxo"], + deps = [ + "//ids", + "//snow/snowtest", + "//utils/crypto/secp256k1", + "//utils/math", + "//utils/timer/mockable", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm/stakeable", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/utxo/utxomock/BUILD.bazel b/vms/platformvm/utxo/utxomock/BUILD.bazel new file mode 100644 index 000000000000..2ae5a68f0e61 --- /dev/null +++ b/vms/platformvm/utxo/utxomock/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "utxomock", + srcs = ["verifier.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/utxo/utxomock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm/txs", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/validators/BUILD.bazel b/vms/platformvm/validators/BUILD.bazel new file mode 100644 index 000000000000..54086700d164 --- /dev/null +++ b/vms/platformvm/validators/BUILD.bazel @@ -0,0 +1,54 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "validators", + srcs = ["manager.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/validators", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//ids", + "//snow/validators", + "//utils/constants", + "//utils/crypto/bls", + "//utils/timer/mockable", + "//utils/window", + "//vms/platformvm/block", + "//vms/platformvm/config", + "//vms/platformvm/metrics", + "//vms/platformvm/state", + "//vms/platformvm/status", + "//vms/platformvm/txs", + ], +) + +go_test( + name = "validators_test", + srcs = [ + "manager_benchmark_test.go", + "manager_test.go", + ], + embed = [":validators"], + deps = [ + "//database/leveldb", + "//ids", + "//snow/validators", + "//upgrade/upgradetest", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/logging", + "//utils/timer/mockable", + "//utils/units", + "//vms/platformvm/block", + "//vms/platformvm/config", + "//vms/platformvm/genesis/genesistest", + "//vms/platformvm/metrics", + "//vms/platformvm/state", + "//vms/platformvm/state/statetest", + "//vms/platformvm/txs", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/validators/fee/BUILD.bazel b/vms/platformvm/validators/fee/BUILD.bazel new file mode 100644 index 000000000000..92caa0edffdd --- /dev/null +++ b/vms/platformvm/validators/fee/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "fee", + srcs = ["fee.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/validators/fee", + visibility = ["//visibility:public"], + deps = [ + "//utils/math", + "//vms/components/gas", + ], +) + +go_test( + name = "fee_test", + srcs = ["fee_test.go"], + embed = [":fee"], + deps = [ + "//utils/math", + "//vms/components/gas", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/validators/validatorstest/BUILD.bazel b/vms/platformvm/validators/validatorstest/BUILD.bazel new file mode 100644 index 000000000000..a9c420b93ae6 --- /dev/null +++ b/vms/platformvm/validators/validatorstest/BUILD.bazel @@ -0,0 +1,13 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "validatorstest", + srcs = ["manager.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/validators/validatorstest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/validators", + "//vms/platformvm/validators", + ], +) diff --git a/vms/platformvm/warp/BUILD.bazel b/vms/platformvm/warp/BUILD.bazel new file mode 100644 index 000000000000..e13bd60496ae --- /dev/null +++ b/vms/platformvm/warp/BUILD.bazel @@ -0,0 +1,53 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "warp", + srcs = [ + "codec.go", + "constants.go", + "message.go", + "signature.go", + "signer.go", + "unsigned_message.go", + "validator.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/warp", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//snow/validators", + "//utils/crypto/bls", + "//utils/hashing", + "//utils/math", + "//utils/set", + ], +) + +go_test( + name = "warp_test", + srcs = [ + "message_test.go", + "signature_test.go", + "signer_test.go", + "unsigned_message_test.go", + "validator_test.go", + ], + embed = [":warp"], + deps = [ + "//codec", + "//ids", + "//snow/validators", + "//snow/validators/validatorsmock", + "//snow/validators/validatorstest", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/set", + "//vms/platformvm/warp/signertest", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/platformvm/warp/gwarp/BUILD.bazel b/vms/platformvm/warp/gwarp/BUILD.bazel new file mode 100644 index 000000000000..d4ce70949ebc --- /dev/null +++ b/vms/platformvm/warp/gwarp/BUILD.bazel @@ -0,0 +1,33 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "gwarp", + srcs = [ + "client.go", + "server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/warp/gwarp", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//proto/pb/warp", + "//vms/platformvm/warp", + ], +) + +go_test( + name = "gwarp_test", + srcs = ["signer_test.go"], + embed = [":gwarp"], + deps = [ + "//ids", + "//proto/pb/warp", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//vms/platformvm/warp", + "//vms/platformvm/warp/signertest", + "//vms/rpcchainvm/grpcutils", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/warp/message/BUILD.bazel b/vms/platformvm/warp/message/BUILD.bazel new file mode 100644 index 000000000000..7e46eedce87d --- /dev/null +++ b/vms/platformvm/warp/message/BUILD.bazel @@ -0,0 +1,48 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "message", + srcs = [ + "codec.go", + "l1_validator_registration.go", + "l1_validator_weight.go", + "payload.go", + "register_l1_validator.go", + "subnet_to_l1_conversion.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/warp/message", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//utils/constants", + "//utils/crypto/bls", + "//utils/hashing", + "//vms/components/verify", + "//vms/secp256k1fx", + "//vms/types", + ], +) + +go_test( + name = "message_test", + srcs = [ + "l1_validator_registration_test.go", + "l1_validator_weight_test.go", + "payload_test.go", + "register_l1_validator_test.go", + "subnet_to_l1_conversion_test.go", + ], + embed = [":message"], + deps = [ + "//codec", + "//ids", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/hashing", + "//vms/types", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/warp/payload/BUILD.bazel b/vms/platformvm/warp/payload/BUILD.bazel new file mode 100644 index 000000000000..97dbfc57ec5d --- /dev/null +++ b/vms/platformvm/warp/payload/BUILD.bazel @@ -0,0 +1,34 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "payload", + srcs = [ + "addressed_call.go", + "codec.go", + "hash.go", + "payload.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/warp/payload", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//utils/units", + ], +) + +go_test( + name = "payload_test", + srcs = [ + "addressed_call_test.go", + "hash_test.go", + "payload_test.go", + ], + embed = [":payload"], + deps = [ + "//codec", + "//ids", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/platformvm/warp/signertest/BUILD.bazel b/vms/platformvm/warp/signertest/BUILD.bazel new file mode 100644 index 000000000000..5241f39e9455 --- /dev/null +++ b/vms/platformvm/warp/signertest/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "signertest", + srcs = ["signertest.go"], + importpath = "github.com/ava-labs/avalanchego/vms/platformvm/warp/signertest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/constants", + "//utils/crypto/bls", + "//vms/platformvm/warp", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/propertyfx/BUILD.bazel b/vms/propertyfx/BUILD.bazel new file mode 100644 index 000000000000..c99f7ab89c31 --- /dev/null +++ b/vms/propertyfx/BUILD.bazel @@ -0,0 +1,47 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "propertyfx", + srcs = [ + "burn_operation.go", + "credential.go", + "factory.go", + "fx.go", + "mint_operation.go", + "mint_output.go", + "owned_output.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/propertyfx", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//vms/components/verify", + "//vms/fx", + "//vms/secp256k1fx", + ], +) + +go_test( + name = "propertyfx_test", + srcs = [ + "burn_operation_test.go", + "credential_test.go", + "factory_test.go", + "fx_test.go", + "mint_operation_test.go", + "mint_output_test.go", + "owned_output_test.go", + ], + embed = [":propertyfx"], + deps = [ + "//codec/linearcodec", + "//ids", + "//utils/crypto/secp256k1", + "//utils/hashing", + "//utils/logging", + "//vms/components/verify", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/proposervm/BUILD.bazel b/vms/proposervm/BUILD.bazel new file mode 100644 index 000000000000..dec634dbcd4e --- /dev/null +++ b/vms/proposervm/BUILD.bazel @@ -0,0 +1,118 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "proposervm", + srcs = [ + "batched_vm.go", + "block.go", + "client_jsonrpc.go", + "config.go", + "height_indexed_vm.go", + "post_fork_block.go", + "post_fork_option.go", + "pre_fork_block.go", + "service.go", + "state_summary.go", + "state_syncable_vm.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/proposervm", + visibility = ["//visibility:public"], + deps = [ + "//api", + "//api/server", + "//cache", + "//cache/lru", + "//cache/metercacher", + "//connectproto/pb/proposervm", + "//connectproto/pb/proposervm/proposervmconnect", + "//database", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//staking", + "//upgrade", + "//utils/constants", + "//utils/json", + "//utils/math", + "//utils/metric", + "//utils/rpc", + "//utils/timer/mockable", + "//utils/tree", + "//utils/units", + "//utils/wrappers", + "//vms/proposervm/acp181", + "//vms/proposervm/block", + "//vms/proposervm/proposer", + "//vms/proposervm/state", + "//vms/proposervm/summary", + "@com_connectrpc_connect//:connect", + "@com_connectrpc_grpcreflect//:grpcreflect", + "@com_github_gorilla_rpc//v2:rpc", + "@com_github_prometheus_client_golang//prometheus", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "proposervm_test", + srcs = [ + "batched_vm_test.go", + "block_test.go", + "main_test.go", + "mocks_generate_test.go", + "mocks_test.go", + "post_fork_block_test.go", + "post_fork_option_test.go", + "pre_fork_block_test.go", + "service_test.go", + "state_syncable_vm_test.go", + "vm_byzantine_test.go", + "vm_test.go", + ], + embed = [":proposervm"], + deps = [ + "//api", + "//api/connectclient", + "//connectproto/pb/proposervm", + "//connectproto/pb/proposervm/proposervmconnect", + "//database", + "//database/memdb", + "//database/prefixdb", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmanmock", + "//snow/consensus/snowman/snowmantest", + "//snow/engine/common", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/engine/snowman/block/blockmock", + "//snow/engine/snowman/block/blocktest", + "//snow/snowtest", + "//snow/validators", + "//snow/validators/validatorsmock", + "//snow/validators/validatorstest", + "//staking", + "//upgrade", + "//upgrade/upgradetest", + "//utils", + "//utils/constants", + "//utils/logging", + "//vms/proposervm/acp181", + "//vms/proposervm/block", + "//vms/proposervm/proposer", + "//vms/proposervm/proposer/proposermock", + "//vms/proposervm/summary", + "@com_connectrpc_connect//:connect", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/testutil", + "@com_github_stretchr_testify//require", + "@org_uber_go_goleak//:goleak", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/proposervm/acp181/BUILD.bazel b/vms/proposervm/acp181/BUILD.bazel new file mode 100644 index 000000000000..cfe79601f02a --- /dev/null +++ b/vms/proposervm/acp181/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "acp181", + srcs = ["epoch.go"], + importpath = "github.com/ava-labs/avalanchego/vms/proposervm/acp181", + visibility = ["//visibility:public"], + deps = [ + "//upgrade", + "//vms/proposervm/block", + ], +) + +go_test( + name = "acp181_test", + srcs = ["epoch_test.go"], + embed = [":acp181"], + deps = [ + "//upgrade", + "//upgrade/upgradetest", + "//vms/proposervm/block", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/proposervm/block/BUILD.bazel b/vms/proposervm/block/BUILD.bazel new file mode 100644 index 000000000000..1a1ffe00d4e2 --- /dev/null +++ b/vms/proposervm/block/BUILD.bazel @@ -0,0 +1,42 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "block", + srcs = [ + "block.go", + "build.go", + "codec.go", + "header.go", + "option.go", + "parse.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/proposervm/block", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//staking", + "//utils/hashing", + "//utils/wrappers", + ], +) + +go_test( + name = "block_test", + srcs = [ + "block_test.go", + "build_test.go", + "header_test.go", + "parse_test.go", + ], + embed = [":block"], + deps = [ + "//codec", + "//ids", + "//staking", + "//utils/units", + "//utils/wrappers", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/proposervm/proposer/BUILD.bazel b/vms/proposervm/proposer/BUILD.bazel new file mode 100644 index 000000000000..21f4ac507940 --- /dev/null +++ b/vms/proposervm/proposer/BUILD.bazel @@ -0,0 +1,37 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "proposer", + srcs = [ + "validators.go", + "windower.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/proposervm/proposer", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow/validators", + "//utils", + "//utils/math", + "//utils/sampler", + "//utils/wrappers", + "@org_gonum_v1_gonum//mathext/prng", + ], +) + +go_test( + name = "proposer_test", + srcs = [ + "mocks_generate_test.go", + "validators_test.go", + "windower_test.go", + ], + embed = [":proposer"], + deps = [ + "//ids", + "//snow/validators", + "//snow/validators/validatorstest", + "//utils/math", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/proposervm/proposer/proposermock/BUILD.bazel b/vms/proposervm/proposer/proposermock/BUILD.bazel new file mode 100644 index 000000000000..22cf1e32ee1c --- /dev/null +++ b/vms/proposervm/proposer/proposermock/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "proposermock", + srcs = ["windower.go"], + importpath = "github.com/ava-labs/avalanchego/vms/proposervm/proposer/proposermock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/proposervm/state/BUILD.bazel b/vms/proposervm/state/BUILD.bazel new file mode 100644 index 000000000000..e97ae869c872 --- /dev/null +++ b/vms/proposervm/state/BUILD.bazel @@ -0,0 +1,52 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "state", + srcs = [ + "block_height_index.go", + "block_state.go", + "chain_state.go", + "codec.go", + "state.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/proposervm/state", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//cache/metercacher", + "//codec", + "//codec/linearcodec", + "//database", + "//database/prefixdb", + "//database/versiondb", + "//ids", + "//snow/choices", + "//utils/constants", + "//utils/metric", + "//utils/units", + "//utils/wrappers", + "//vms/proposervm/block", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "state_test", + srcs = [ + "block_state_test.go", + "chain_state_test.go", + "state_test.go", + ], + embed = [":state"], + deps = [ + "//database", + "//database/memdb", + "//database/versiondb", + "//ids", + "//staking", + "//vms/proposervm/block", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/proposervm/summary/BUILD.bazel b/vms/proposervm/summary/BUILD.bazel new file mode 100644 index 000000000000..9f3a70422236 --- /dev/null +++ b/vms/proposervm/summary/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "summary", + srcs = [ + "build.go", + "codec.go", + "parse.go", + "state_summary.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/proposervm/summary", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//utils/hashing", + ], +) + +go_test( + name = "summary_test", + srcs = [ + "build_test.go", + "parse_test.go", + ], + embed = [":summary"], + deps = [ + "//codec", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/registry/BUILD.bazel b/vms/registry/BUILD.bazel new file mode 100644 index 000000000000..67c784f68fc6 --- /dev/null +++ b/vms/registry/BUILD.bazel @@ -0,0 +1,43 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "registry", + srcs = [ + "vm_getter.go", + "vm_registry.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/registry", + visibility = ["//visibility:public"], + deps = [ + "//api/metrics", + "//ids", + "//utils/filesystem", + "//utils/resource", + "//vms", + "//vms/rpcchainvm", + "//vms/rpcchainvm/runtime", + ], +) + +go_test( + name = "registry_test", + srcs = [ + "mocks_generate_test.go", + "vm_getter_test.go", + "vm_registry_test.go", + ], + embed = [":registry"], + deps = [ + "//ids", + "//utils/filesystem", + "//utils/filesystem/filesystemmock", + "//utils/logging", + "//utils/resource", + "//vms", + "//vms/registry/registrymock", + "//vms/vmsmock", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/registry/registrymock/BUILD.bazel b/vms/registry/registrymock/BUILD.bazel new file mode 100644 index 000000000000..39e481d6d4d8 --- /dev/null +++ b/vms/registry/registrymock/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "registrymock", + srcs = [ + "vm_getter.go", + "vm_registry.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/registry/registrymock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//vms", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/rpcchainvm/BUILD.bazel b/vms/rpcchainvm/BUILD.bazel new file mode 100644 index 000000000000..86a7398fd371 --- /dev/null +++ b/vms/rpcchainvm/BUILD.bazel @@ -0,0 +1,104 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "rpcchainvm", + srcs = [ + "errors.go", + "factory.go", + "vm.go", + "vm_client.go", + "vm_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm", + visibility = ["//visibility:public"], + deps = [ + "//api/metrics", + "//chains/atomic/gsharedmemory", + "//database", + "//database/corruptabledb", + "//database/rpcdb", + "//ids", + "//ids/galiasreader", + "//proto/pb/aliasreader", + "//proto/pb/appsender", + "//proto/pb/http", + "//proto/pb/rpcdb", + "//proto/pb/sharedmemory", + "//proto/pb/validatorstate", + "//proto/pb/vm", + "//proto/pb/vm/runtime", + "//proto/pb/warp", + "//snow", + "//snow/consensus/snowman", + "//snow/engine/common", + "//snow/engine/common/appsender", + "//snow/engine/snowman/block", + "//snow/validators", + "//snow/validators/gvalidators", + "//upgrade", + "//utils", + "//utils/crypto/bls", + "//utils/logging", + "//utils/resource", + "//utils/units", + "//utils/wrappers", + "//version", + "//vms", + "//vms/components/chain", + "//vms/platformvm/warp/gwarp", + "//vms/rpcchainvm/ghttp", + "//vms/rpcchainvm/grpcutils", + "//vms/rpcchainvm/gruntime", + "//vms/rpcchainvm/runtime", + "//vms/rpcchainvm/runtime/subprocess", + "@com_github_grpc_ecosystem_go_grpc_prometheus//:go-grpc-prometheus", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_prometheus_client_golang//prometheus/collectors", + "@com_github_prometheus_client_model//go", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//health", + "@org_golang_google_grpc//health/grpc_health_v1", + "@org_golang_google_protobuf//types/known/durationpb", + "@org_golang_google_protobuf//types/known/emptypb", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "rpcchainvm_test", + srcs = [ + "batched_vm_test.go", + "state_syncable_vm_test.go", + "vm_test.go", + "with_context_vm_test.go", + ], + embed = [":rpcchainvm"], + deps = [ + "//api/metrics", + "//database/memdb", + "//database/prefixdb", + "//ids", + "//proto/pb/vm", + "//snow", + "//snow/consensus/snowman", + "//snow/consensus/snowman/snowmanmock", + "//snow/consensus/snowman/snowmantest", + "//snow/engine/enginetest", + "//snow/engine/snowman/block", + "//snow/engine/snowman/block/blockmock", + "//snow/engine/snowman/block/blocktest", + "//snow/snowtest", + "//upgrade", + "//utils", + "//utils/constants", + "//utils/logging", + "//vms/components/chain", + "//vms/rpcchainvm/grpcutils", + "//vms/rpcchainvm/runtime", + "//vms/rpcchainvm/runtime/subprocess", + "@com_github_stretchr_testify//require", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//test/bufconn", + "@org_uber_go_mock//gomock", + ], +) diff --git a/vms/rpcchainvm/ghttp/BUILD.bazel b/vms/rpcchainvm/ghttp/BUILD.bazel new file mode 100644 index 000000000000..8461ce0c3e1d --- /dev/null +++ b/vms/rpcchainvm/ghttp/BUILD.bazel @@ -0,0 +1,37 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "ghttp", + srcs = [ + "http_client.go", + "http_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/ghttp", + visibility = ["//visibility:public"], + deps = [ + "//proto/pb/http", + "//proto/pb/http/responsewriter", + "//proto/pb/io/reader", + "//utils/logging", + "//vms/rpcchainvm/ghttp/greader", + "//vms/rpcchainvm/ghttp/gresponsewriter", + "//vms/rpcchainvm/grpcutils", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "ghttp_test", + srcs = ["http_test.go"], + embed = [":ghttp"], + deps = [ + "//proto/pb/http", + "//utils/logging", + "//vms/rpcchainvm/grpcutils", + "@com_github_stretchr_testify//require", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//credentials/insecure", + "@org_golang_google_grpc//test/bufconn", + "@org_golang_x_exp//maps", + ], +) diff --git a/vms/rpcchainvm/ghttp/gconn/BUILD.bazel b/vms/rpcchainvm/ghttp/gconn/BUILD.bazel new file mode 100644 index 000000000000..72aa3522e8c9 --- /dev/null +++ b/vms/rpcchainvm/ghttp/gconn/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "gconn", + srcs = [ + "conn_client.go", + "conn_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/ghttp/gconn", + visibility = ["//visibility:public"], + deps = [ + "//proto/pb/net/conn", + "//utils/wrappers", + "//vms/rpcchainvm/grpcutils", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) + +go_test( + name = "gconn_test", + srcs = ["gconn_test.go"], + embed = [":gconn"], + deps = [ + "//proto/pb/net/conn", + "//vms/rpcchainvm/grpcutils", + "@com_github_stretchr_testify//require", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//test/bufconn", + ], +) diff --git a/vms/rpcchainvm/ghttp/greader/BUILD.bazel b/vms/rpcchainvm/ghttp/greader/BUILD.bazel new file mode 100644 index 000000000000..757fdc25e29d --- /dev/null +++ b/vms/rpcchainvm/ghttp/greader/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "greader", + srcs = [ + "reader_client.go", + "reader_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/ghttp/greader", + visibility = ["//visibility:public"], + deps = ["//proto/pb/io/reader"], +) + +go_test( + name = "greader_test", + srcs = ["greader_test.go"], + embed = [":greader"], + deps = [ + "//proto/pb/io/reader", + "@com_github_stretchr_testify//require", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//test/bufconn", + ], +) diff --git a/vms/rpcchainvm/ghttp/gresponsewriter/BUILD.bazel b/vms/rpcchainvm/ghttp/gresponsewriter/BUILD.bazel new file mode 100644 index 000000000000..553d031a1ece --- /dev/null +++ b/vms/rpcchainvm/ghttp/gresponsewriter/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "gresponsewriter", + srcs = [ + "locked_writer.go", + "writer_client.go", + "writer_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/ghttp/gresponsewriter", + visibility = ["//visibility:public"], + deps = [ + "//proto/pb/http/responsewriter", + "//proto/pb/io/reader", + "//proto/pb/io/writer", + "//proto/pb/net/conn", + "//vms/rpcchainvm/ghttp/gconn", + "//vms/rpcchainvm/ghttp/greader", + "//vms/rpcchainvm/ghttp/gwriter", + "//vms/rpcchainvm/grpcutils", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/vms/rpcchainvm/ghttp/gwriter/BUILD.bazel b/vms/rpcchainvm/ghttp/gwriter/BUILD.bazel new file mode 100644 index 000000000000..e0261c58c92f --- /dev/null +++ b/vms/rpcchainvm/ghttp/gwriter/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "gwriter", + srcs = [ + "writer_client.go", + "writer_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/ghttp/gwriter", + visibility = ["//visibility:public"], + deps = ["//proto/pb/io/writer"], +) diff --git a/vms/rpcchainvm/grpcutils/BUILD.bazel b/vms/rpcchainvm/grpcutils/BUILD.bazel new file mode 100644 index 000000000000..ffe1e012979d --- /dev/null +++ b/vms/rpcchainvm/grpcutils/BUILD.bazel @@ -0,0 +1,41 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "grpcutils", + srcs = [ + "client.go", + "server.go", + "server_closer.go", + "util.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/grpcutils", + visibility = ["//visibility:public"], + deps = [ + "//proto/pb/http", + "@org_golang_google_genproto_googleapis_rpc//status", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//credentials/insecure", + "@org_golang_google_grpc//keepalive", + "@org_golang_google_grpc//status", + "@org_golang_google_protobuf//proto", + "@org_golang_google_protobuf//types/known/anypb", + "@org_golang_google_protobuf//types/known/timestamppb", + ], +) + +go_test( + name = "grpcutils_test", + srcs = ["client_test.go"], + embed = [":grpcutils"], + deps = [ + "//database/memdb", + "//database/rpcdb", + "//proto/pb/rpcdb", + "@com_github_grpc_ecosystem_go_grpc_prometheus//:go-grpc-prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_google_grpc//:grpc", + "@org_golang_google_grpc//codes", + "@org_golang_google_grpc//credentials/insecure", + "@org_golang_google_grpc//status", + ], +) diff --git a/vms/rpcchainvm/gruntime/BUILD.bazel b/vms/rpcchainvm/gruntime/BUILD.bazel new file mode 100644 index 000000000000..1cc4529eb08d --- /dev/null +++ b/vms/rpcchainvm/gruntime/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "gruntime", + srcs = [ + "runtime_client.go", + "runtime_server.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/gruntime", + visibility = ["//visibility:public"], + deps = [ + "//proto/pb/vm/runtime", + "//vms/rpcchainvm/runtime", + "@org_golang_google_protobuf//types/known/emptypb", + ], +) diff --git a/vms/rpcchainvm/runtime/BUILD.bazel b/vms/rpcchainvm/runtime/BUILD.bazel new file mode 100644 index 000000000000..4058c5322c52 --- /dev/null +++ b/vms/rpcchainvm/runtime/BUILD.bazel @@ -0,0 +1,11 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "runtime", + srcs = [ + "manager.go", + "runtime.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/runtime", + visibility = ["//visibility:public"], +) diff --git a/vms/rpcchainvm/runtime/subprocess/BUILD.bazel b/vms/rpcchainvm/runtime/subprocess/BUILD.bazel new file mode 100644 index 000000000000..51439993a989 --- /dev/null +++ b/vms/rpcchainvm/runtime/subprocess/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "subprocess", + srcs = [ + "initializer.go", + "linux_stopper.go", + "non_linux_stopper.go", + "runtime.go", + "stopper.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/rpcchainvm/runtime/subprocess", + visibility = ["//visibility:public"], + deps = [ + "//proto/pb/vm/runtime", + "//utils/logging", + "//version", + "//vms/rpcchainvm/grpcutils", + "//vms/rpcchainvm/gruntime", + "//vms/rpcchainvm/runtime", + "@org_uber_go_zap//:zap", + ] + select({ + "@rules_go//go/platform:android": [ + "//utils/wrappers", + ], + "@rules_go//go/platform:linux": [ + "//utils/wrappers", + ], + "//conditions:default": [], + }), +) diff --git a/vms/secp256k1fx/BUILD.bazel b/vms/secp256k1fx/BUILD.bazel new file mode 100644 index 000000000000..75451c7bd784 --- /dev/null +++ b/vms/secp256k1fx/BUILD.bazel @@ -0,0 +1,68 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "secp256k1fx", + srcs = [ + "credential.go", + "factory.go", + "fx.go", + "input.go", + "keychain.go", + "mint_operation.go", + "mint_output.go", + "output_owners.go", + "transfer_input.go", + "transfer_output.go", + "tx.go", + "vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/secp256k1fx", + visibility = ["//visibility:public"], + deps = [ + "//codec", + "//ids", + "//snow", + "//utils", + "//utils/constants", + "//utils/crypto/keychain", + "//utils/crypto/secp256k1", + "//utils/formatting", + "//utils/formatting/address", + "//utils/hashing", + "//utils/logging", + "//utils/math", + "//utils/set", + "//utils/timer/mockable", + "//vms/components/verify", + "//vms/fx", + "@com_github_ava_labs_libevm//common", + ], +) + +go_test( + name = "secp256k1fx_test", + srcs = [ + "credential_test.go", + "factory_test.go", + "fx_test.go", + "input_test.go", + "keychain_test.go", + "mint_operation_test.go", + "mint_output_test.go", + "output_owners_test.go", + "transfer_input_test.go", + "transfer_output_test.go", + ], + embed = [":secp256k1fx"], + deps = [ + "//codec", + "//codec/linearcodec", + "//ids", + "//utils/cb58", + "//utils/crypto/secp256k1", + "//utils/formatting", + "//utils/logging", + "//vms/components/verify", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/tracedvm/BUILD.bazel b/vms/tracedvm/BUILD.bazel new file mode 100644 index 000000000000..383ffbd29632 --- /dev/null +++ b/vms/tracedvm/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "tracedvm", + srcs = [ + "batched_vm.go", + "block.go", + "block_vm.go", + "build_block_with_context_vm.go", + "set_preference_with_context_vm.go", + "state_syncable_vm.go", + "tx.go", + "vertex_vm.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/tracedvm", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//snow", + "//snow/consensus/snowman", + "//snow/consensus/snowstorm", + "//snow/engine/avalanche/vertex", + "//snow/engine/common", + "//snow/engine/snowman/block", + "//trace", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + ], +) diff --git a/vms/txs/mempool/BUILD.bazel b/vms/txs/mempool/BUILD.bazel new file mode 100644 index 000000000000..86cb1c3217ef --- /dev/null +++ b/vms/txs/mempool/BUILD.bazel @@ -0,0 +1,34 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "mempool", + srcs = [ + "mempool.go", + "metrics.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/txs/mempool", + visibility = ["//visibility:public"], + deps = [ + "//cache/lru", + "//ids", + "//snow/engine/common", + "//utils/linked", + "//utils/lock", + "//utils/set", + "//utils/setmap", + "//utils/units", + "@com_github_prometheus_client_golang//prometheus", + ], +) + +go_test( + name = "mempool_test", + srcs = ["mempool_test.go"], + embed = [":mempool"], + deps = [ + "//ids", + "//snow/engine/common", + "//utils/set", + "@com_github_stretchr_testify//require", + ], +) diff --git a/vms/types/BUILD.bazel b/vms/types/BUILD.bazel new file mode 100644 index 000000000000..a94629608dcd --- /dev/null +++ b/vms/types/BUILD.bazel @@ -0,0 +1,16 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "types", + srcs = ["blob_data.go"], + importpath = "github.com/ava-labs/avalanchego/vms/types", + visibility = ["//visibility:public"], + deps = ["//utils/formatting"], +) + +go_test( + name = "types_test", + srcs = ["blob_data_test.go"], + embed = [":types"], + deps = ["@com_github_stretchr_testify//require"], +) diff --git a/vms/vmsmock/BUILD.bazel b/vms/vmsmock/BUILD.bazel new file mode 100644 index 000000000000..e1d4b07e84fb --- /dev/null +++ b/vms/vmsmock/BUILD.bazel @@ -0,0 +1,17 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "vmsmock", + srcs = [ + "factory.go", + "manager.go", + ], + importpath = "github.com/ava-labs/avalanchego/vms/vmsmock", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/logging", + "//vms", + "@org_uber_go_mock//gomock", + ], +) diff --git a/wallet/chain/c/BUILD.bazel b/wallet/chain/c/BUILD.bazel new file mode 100644 index 000000000000..13ac03586602 --- /dev/null +++ b/wallet/chain/c/BUILD.bazel @@ -0,0 +1,39 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "c", + srcs = [ + "backend.go", + "builder.go", + "builder_with_options.go", + "context.go", + "signer.go", + "wallet.go", + "wallet_with_options.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/chain/c", + visibility = ["//visibility:public"], + deps = [ + "//api/info", + "//database", + "//graft/coreth/ethclient", + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/plugin/evm/client", + "//ids", + "//snow", + "//utils", + "//utils/constants", + "//utils/crypto/keychain", + "//utils/crypto/secp256k1", + "//utils/logging", + "//utils/math", + "//utils/rpc", + "//utils/set", + "//vms/avm", + "//vms/components/avax", + "//vms/components/verify", + "//vms/secp256k1fx", + "//wallet/subnet/primary/common", + "@com_github_ava_labs_libevm//common", + ], +) diff --git a/wallet/chain/p/BUILD.bazel b/wallet/chain/p/BUILD.bazel new file mode 100644 index 000000000000..0b6165cc7224 --- /dev/null +++ b/wallet/chain/p/BUILD.bazel @@ -0,0 +1,54 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "p", + srcs = [ + "client.go", + "context.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/chain/p", + visibility = ["//visibility:public"], + deps = [ + "//api/info", + "//utils/constants", + "//vms/platformvm", + "//vms/platformvm/txs", + "//wallet/chain/p/builder", + "//wallet/chain/p/wallet", + "//wallet/subnet/primary/common", + ], +) + +go_test( + name = "p_test", + srcs = ["builder_test.go"], + embed = [":p"], + deps = [ + "//ids", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/crypto/secp256k1", + "//utils/set", + "//utils/units", + "//vms/components/avax", + "//vms/components/gas", + "//vms/platformvm/fx", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/stakeable", + "//vms/platformvm/txs", + "//vms/platformvm/txs/fee", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/secp256k1fx", + "//vms/types", + "//wallet/chain/p/builder", + "//wallet/chain/p/wallet", + "//wallet/subnet/primary/common", + "//wallet/subnet/primary/common/utxotest", + "@com_github_stretchr_testify//require", + ], +) diff --git a/wallet/chain/p/builder/BUILD.bazel b/wallet/chain/p/builder/BUILD.bazel new file mode 100644 index 000000000000..0f91364b9878 --- /dev/null +++ b/wallet/chain/p/builder/BUILD.bazel @@ -0,0 +1,46 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "builder", + srcs = [ + "builder.go", + "context.go", + "with_options.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/chain/p/builder", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//utils", + "//utils/constants", + "//utils/crypto/bls", + "//utils/logging", + "//utils/math", + "//utils/set", + "//vms/components/avax", + "//vms/components/gas", + "//vms/components/verify", + "//vms/platformvm/fx", + "//vms/platformvm/signer", + "//vms/platformvm/stakeable", + "//vms/platformvm/txs", + "//vms/platformvm/txs/fee", + "//vms/secp256k1fx", + "//wallet/subnet/primary/common", + ], +) + +go_test( + name = "builder_test", + srcs = ["builder_test.go"], + embed = [":builder"], + deps = [ + "//ids", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm/stakeable", + "//vms/secp256k1fx", + "@com_github_stretchr_testify//require", + ], +) diff --git a/wallet/chain/p/signer/BUILD.bazel b/wallet/chain/p/signer/BUILD.bazel new file mode 100644 index 000000000000..4fa7fe9b9978 --- /dev/null +++ b/wallet/chain/p/signer/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "signer", + srcs = [ + "signer.go", + "visitor.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/chain/p/signer", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//utils/constants", + "//utils/crypto/keychain", + "//utils/crypto/secp256k1", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm/fx", + "//vms/platformvm/stakeable", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + ], +) diff --git a/wallet/chain/p/wallet/BUILD.bazel b/wallet/chain/p/wallet/BUILD.bazel new file mode 100644 index 000000000000..df0374852440 --- /dev/null +++ b/wallet/chain/p/wallet/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "wallet", + srcs = [ + "backend.go", + "backend_visitor.go", + "wallet.go", + "with_options.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/chain/p/wallet", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//utils/constants", + "//utils/crypto/bls", + "//utils/set", + "//vms/components/avax", + "//vms/platformvm/fx", + "//vms/platformvm/signer", + "//vms/platformvm/txs", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/secp256k1fx", + "//wallet/chain/p/builder", + "//wallet/chain/p/signer", + "//wallet/subnet/primary/common", + ], +) diff --git a/wallet/chain/x/BUILD.bazel b/wallet/chain/x/BUILD.bazel new file mode 100644 index 000000000000..a0095465ba37 --- /dev/null +++ b/wallet/chain/x/BUILD.bazel @@ -0,0 +1,47 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "x", + srcs = [ + "backend.go", + "backend_visitor.go", + "context.go", + "wallet.go", + "wallet_with_options.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/chain/x", + visibility = ["//visibility:public"], + deps = [ + "//api/info", + "//ids", + "//vms/avm", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/components/verify", + "//vms/secp256k1fx", + "//wallet/chain/x/builder", + "//wallet/chain/x/signer", + "//wallet/subnet/primary/common", + ], +) + +go_test( + name = "x_test", + srcs = ["builder_test.go"], + embed = [":x"], + deps = [ + "//ids", + "//utils/constants", + "//utils/crypto/secp256k1", + "//utils/set", + "//utils/units", + "//vms/components/avax", + "//vms/components/verify", + "//vms/nftfx", + "//vms/propertyfx", + "//vms/secp256k1fx", + "//wallet/chain/x/builder", + "//wallet/subnet/primary/common/utxotest", + "@com_github_stretchr_testify//require", + ], +) diff --git a/wallet/chain/x/builder/BUILD.bazel b/wallet/chain/x/builder/BUILD.bazel new file mode 100644 index 000000000000..24ea7cba7314 --- /dev/null +++ b/wallet/chain/x/builder/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "builder", + srcs = [ + "builder.go", + "builder_with_options.go", + "constants.go", + "context.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/chain/x/builder", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//snow", + "//utils", + "//utils/constants", + "//utils/logging", + "//utils/math", + "//utils/set", + "//vms/avm/block", + "//vms/avm/fxs", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/components/verify", + "//vms/nftfx", + "//vms/propertyfx", + "//vms/secp256k1fx", + "//wallet/subnet/primary/common", + ], +) diff --git a/wallet/chain/x/signer/BUILD.bazel b/wallet/chain/x/signer/BUILD.bazel new file mode 100644 index 000000000000..b1a9537e7ceb --- /dev/null +++ b/wallet/chain/x/signer/BUILD.bazel @@ -0,0 +1,25 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "signer", + srcs = [ + "signer.go", + "visitor.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/chain/x/signer", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//utils/crypto/keychain", + "//utils/crypto/secp256k1", + "//vms/avm/fxs", + "//vms/avm/txs", + "//vms/components/avax", + "//vms/components/verify", + "//vms/nftfx", + "//vms/propertyfx", + "//vms/secp256k1fx", + "//wallet/chain/x/builder", + ], +) diff --git a/wallet/subnet/primary/BUILD.bazel b/wallet/subnet/primary/BUILD.bazel new file mode 100644 index 000000000000..b0498c0a06a9 --- /dev/null +++ b/wallet/subnet/primary/BUILD.bazel @@ -0,0 +1,55 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "primary", + srcs = [ + "api.go", + "wallet.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary", + visibility = ["//visibility:public"], + deps = [ + "//api/info", + "//codec", + "//graft/coreth/ethclient", + "//graft/coreth/plugin/evm/atomic", + "//graft/coreth/plugin/evm/client", + "//ids", + "//utils/constants", + "//utils/crypto/keychain", + "//utils/rpc", + "//utils/set", + "//vms/avm", + "//vms/components/avax", + "//vms/platformvm", + "//vms/platformvm/txs", + "//wallet/chain/c", + "//wallet/chain/p", + "//wallet/chain/p/builder", + "//wallet/chain/p/signer", + "//wallet/chain/p/wallet", + "//wallet/chain/x", + "//wallet/chain/x/builder", + "//wallet/chain/x/signer", + "//wallet/subnet/primary/common", + "@com_github_ava_labs_libevm//common", + ], +) + +go_test( + name = "primary_test", + srcs = ["example_test.go"], + embed = [":primary"], + deps = [ + "//genesis", + "//ids", + "//utils/constants", + "//utils/units", + "//vms/components/avax", + "//vms/components/verify", + "//vms/platformvm/reward", + "//vms/platformvm/signer", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + ], +) diff --git a/wallet/subnet/primary/common/BUILD.bazel b/wallet/subnet/primary/common/BUILD.bazel new file mode 100644 index 000000000000..d17d881f0025 --- /dev/null +++ b/wallet/subnet/primary/common/BUILD.bazel @@ -0,0 +1,21 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "common", + srcs = [ + "options.go", + "spend.go", + "utxos.go", + ], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/common", + visibility = ["//visibility:public"], + deps = [ + "//database", + "//ids", + "//utils/set", + "//vms/components/avax", + "//vms/secp256k1fx", + "@com_github_ava_labs_libevm//common", + "@org_golang_x_exp//maps", + ], +) diff --git a/wallet/subnet/primary/common/utxotest/BUILD.bazel b/wallet/subnet/primary/common/utxotest/BUILD.bazel new file mode 100644 index 000000000000..5da3d3222d0a --- /dev/null +++ b/wallet/subnet/primary/common/utxotest/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "utxotest", + srcs = ["utxotest.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/common/utxotest", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//utils/constants", + "//vms/components/avax", + "//wallet/subnet/primary/common", + "@com_github_stretchr_testify//require", + ], +) diff --git a/wallet/subnet/primary/examples/add-permissioned-subnet-validator/BUILD.bazel b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/BUILD.bazel new file mode 100644 index 000000000000..cb81ae27e0d9 --- /dev/null +++ b/wallet/subnet/primary/examples/add-permissioned-subnet-validator/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "add-permissioned-subnet-validator_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/add-permissioned-subnet-validator", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//genesis", + "//ids", + "//utils/units", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "add-permissioned-subnet-validator", + embed = [":add-permissioned-subnet-validator_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/add-primary-validator/BUILD.bazel b/wallet/subnet/primary/examples/add-primary-validator/BUILD.bazel new file mode 100644 index 000000000000..f85640f89f94 --- /dev/null +++ b/wallet/subnet/primary/examples/add-primary-validator/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "add-primary-validator_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/add-primary-validator", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//genesis", + "//ids", + "//utils/units", + "//vms/platformvm/reward", + "//vms/platformvm/txs", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "add-primary-validator", + embed = [":add-primary-validator_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/c-chain-export/BUILD.bazel b/wallet/subnet/primary/examples/c-chain-export/BUILD.bazel new file mode 100644 index 000000000000..96c33cd2a8d4 --- /dev/null +++ b/wallet/subnet/primary/examples/c-chain-export/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "c-chain-export_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/c-chain-export", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//utils/constants", + "//utils/units", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "c-chain-export", + embed = [":c-chain-export_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/c-chain-import/BUILD.bazel b/wallet/subnet/primary/examples/c-chain-import/BUILD.bazel new file mode 100644 index 000000000000..aa6d8d4e4f84 --- /dev/null +++ b/wallet/subnet/primary/examples/c-chain-import/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "c-chain-import_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/c-chain-import", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//utils/constants", + "//utils/units", + "//vms/components/avax", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "c-chain-import", + embed = [":c-chain-import_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/convert-subnet-to-l1/BUILD.bazel b/wallet/subnet/primary/examples/convert-subnet-to-l1/BUILD.bazel new file mode 100644 index 000000000000..ab29aea160dc --- /dev/null +++ b/wallet/subnet/primary/examples/convert-subnet-to-l1/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "convert-subnet-to-l1_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/convert-subnet-to-l1", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//genesis", + "//ids", + "//utils/units", + "//vms/platformvm/txs", + "//vms/platformvm/warp/message", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "convert-subnet-to-l1", + embed = [":convert-subnet-to-l1_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/create-asset/BUILD.bazel b/wallet/subnet/primary/examples/create-asset/BUILD.bazel new file mode 100644 index 000000000000..96d9fb79f836 --- /dev/null +++ b/wallet/subnet/primary/examples/create-asset/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "create-asset_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/create-asset", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//utils/units", + "//vms/components/verify", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "create-asset", + embed = [":create-asset_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/create-chain/BUILD.bazel b/wallet/subnet/primary/examples/create-chain/BUILD.bazel new file mode 100644 index 000000000000..d06807965014 --- /dev/null +++ b/wallet/subnet/primary/examples/create-chain/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "create-chain_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/create-chain", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//utils/constants", + "//vms/example/xsvm/genesis", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "create-chain", + embed = [":create-chain_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/create-locked-stakeable/BUILD.bazel b/wallet/subnet/primary/examples/create-locked-stakeable/BUILD.bazel new file mode 100644 index 000000000000..700410eb5d87 --- /dev/null +++ b/wallet/subnet/primary/examples/create-locked-stakeable/BUILD.bazel @@ -0,0 +1,24 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "create-locked-stakeable_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/create-locked-stakeable", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//utils/formatting/address", + "//utils/units", + "//vms/components/avax", + "//vms/platformvm/stakeable", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "create-locked-stakeable", + embed = [":create-locked-stakeable_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/create-subnet/BUILD.bazel b/wallet/subnet/primary/examples/create-subnet/BUILD.bazel new file mode 100644 index 000000000000..c05152b90d02 --- /dev/null +++ b/wallet/subnet/primary/examples/create-subnet/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "create-subnet_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/create-subnet", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "create-subnet", + embed = [":create-subnet_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/disable-l1-validator/BUILD.bazel b/wallet/subnet/primary/examples/disable-l1-validator/BUILD.bazel new file mode 100644 index 000000000000..516b978ebcad --- /dev/null +++ b/wallet/subnet/primary/examples/disable-l1-validator/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "disable-l1-validator_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/disable-l1-validator", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "disable-l1-validator", + embed = [":disable-l1-validator_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/get-p-chain-balance/BUILD.bazel b/wallet/subnet/primary/examples/get-p-chain-balance/BUILD.bazel new file mode 100644 index 000000000000..c82163134c92 --- /dev/null +++ b/wallet/subnet/primary/examples/get-p-chain-balance/BUILD.bazel @@ -0,0 +1,23 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "get-p-chain-balance_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/get-p-chain-balance", + visibility = ["//visibility:private"], + deps = [ + "//utils/constants", + "//utils/formatting/address", + "//utils/set", + "//wallet/chain/p/builder", + "//wallet/chain/p/wallet", + "//wallet/subnet/primary", + "//wallet/subnet/primary/common", + ], +) + +go_binary( + name = "get-p-chain-balance", + embed = [":get-p-chain-balance_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/get-x-chain-balance/BUILD.bazel b/wallet/subnet/primary/examples/get-x-chain-balance/BUILD.bazel new file mode 100644 index 000000000000..65e98861076a --- /dev/null +++ b/wallet/subnet/primary/examples/get-x-chain-balance/BUILD.bazel @@ -0,0 +1,22 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "get-x-chain-balance_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/get-x-chain-balance", + visibility = ["//visibility:private"], + deps = [ + "//utils/formatting/address", + "//utils/set", + "//wallet/chain/x", + "//wallet/chain/x/builder", + "//wallet/subnet/primary", + "//wallet/subnet/primary/common", + ], +) + +go_binary( + name = "get-x-chain-balance", + embed = [":get-x-chain-balance_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/increase-l1-validator-balance/BUILD.bazel b/wallet/subnet/primary/examples/increase-l1-validator-balance/BUILD.bazel new file mode 100644 index 000000000000..cdc24a15f0b9 --- /dev/null +++ b/wallet/subnet/primary/examples/increase-l1-validator-balance/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "increase-l1-validator-balance_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/increase-l1-validator-balance", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "increase-l1-validator-balance", + embed = [":increase-l1-validator-balance_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/register-l1-validator/BUILD.bazel b/wallet/subnet/primary/examples/register-l1-validator/BUILD.bazel new file mode 100644 index 000000000000..6190312b945c --- /dev/null +++ b/wallet/subnet/primary/examples/register-l1-validator/BUILD.bazel @@ -0,0 +1,28 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "register-l1-validator_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/register-l1-validator", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//genesis", + "//ids", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/set", + "//utils/units", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "register-l1-validator", + embed = [":register-l1-validator_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/remove-subnet-validator/BUILD.bazel b/wallet/subnet/primary/examples/remove-subnet-validator/BUILD.bazel new file mode 100644 index 000000000000..a44a45b71010 --- /dev/null +++ b/wallet/subnet/primary/examples/remove-subnet-validator/BUILD.bazel @@ -0,0 +1,20 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "remove-subnet-validator_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/remove-subnet-validator", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "remove-subnet-validator", + embed = [":remove-subnet-validator_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/set-l1-validator-weight/BUILD.bazel b/wallet/subnet/primary/examples/set-l1-validator-weight/BUILD.bazel new file mode 100644 index 000000000000..e92b1eef78ae --- /dev/null +++ b/wallet/subnet/primary/examples/set-l1-validator-weight/BUILD.bazel @@ -0,0 +1,26 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "set-l1-validator-weight_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/set-l1-validator-weight", + visibility = ["//visibility:private"], + deps = [ + "//genesis", + "//ids", + "//utils/crypto/bls", + "//utils/crypto/bls/signer/localsigner", + "//utils/set", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//vms/secp256k1fx", + "//wallet/subnet/primary", + ], +) + +go_binary( + name = "set-l1-validator-weight", + embed = [":set-l1-validator-weight_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/sign-l1-validator-registration/BUILD.bazel b/wallet/subnet/primary/examples/sign-l1-validator-registration/BUILD.bazel new file mode 100644 index 000000000000..7cf6cb261b84 --- /dev/null +++ b/wallet/subnet/primary/examples/sign-l1-validator-registration/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "sign-l1-validator-registration_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/sign-l1-validator-registration", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//ids", + "//message", + "//network/p2p", + "//network/peer", + "//proto/pb/sdk", + "//snow/networking/router", + "//utils/compression", + "//utils/constants", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//wallet/subnet/primary", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + ], +) + +go_binary( + name = "sign-l1-validator-registration", + embed = [":sign-l1-validator-registration_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/sign-l1-validator-removal-genesis/BUILD.bazel b/wallet/subnet/primary/examples/sign-l1-validator-removal-genesis/BUILD.bazel new file mode 100644 index 000000000000..ad1042f9009b --- /dev/null +++ b/wallet/subnet/primary/examples/sign-l1-validator-removal-genesis/BUILD.bazel @@ -0,0 +1,32 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "sign-l1-validator-removal-genesis_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/sign-l1-validator-removal-genesis", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//ids", + "//message", + "//network/p2p", + "//network/peer", + "//proto/pb/platformvm", + "//proto/pb/sdk", + "//snow/networking/router", + "//utils/compression", + "//utils/constants", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//wallet/subnet/primary", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + ], +) + +go_binary( + name = "sign-l1-validator-removal-genesis", + embed = [":sign-l1-validator-removal-genesis_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/sign-l1-validator-removal-registration/BUILD.bazel b/wallet/subnet/primary/examples/sign-l1-validator-removal-registration/BUILD.bazel new file mode 100644 index 000000000000..c6776b7ddc4a --- /dev/null +++ b/wallet/subnet/primary/examples/sign-l1-validator-removal-registration/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "sign-l1-validator-removal-registration_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/sign-l1-validator-removal-registration", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//message", + "//network/p2p", + "//network/peer", + "//proto/pb/platformvm", + "//proto/pb/sdk", + "//snow/networking/router", + "//utils/compression", + "//utils/constants", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//wallet/subnet/primary", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + ], +) + +go_binary( + name = "sign-l1-validator-removal-registration", + embed = [":sign-l1-validator-removal-registration_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/sign-l1-validator-weight/BUILD.bazel b/wallet/subnet/primary/examples/sign-l1-validator-weight/BUILD.bazel new file mode 100644 index 000000000000..d8ffb8270695 --- /dev/null +++ b/wallet/subnet/primary/examples/sign-l1-validator-weight/BUILD.bazel @@ -0,0 +1,30 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "sign-l1-validator-weight_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/sign-l1-validator-weight", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//message", + "//network/p2p", + "//network/peer", + "//proto/pb/sdk", + "//snow/networking/router", + "//utils/compression", + "//utils/constants", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//wallet/subnet/primary", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + ], +) + +go_binary( + name = "sign-l1-validator-weight", + embed = [":sign-l1-validator-weight_lib"], + visibility = ["//visibility:public"], +) diff --git a/wallet/subnet/primary/examples/sign-subnet-to-l1-conversion/BUILD.bazel b/wallet/subnet/primary/examples/sign-subnet-to-l1-conversion/BUILD.bazel new file mode 100644 index 000000000000..890411dee6ff --- /dev/null +++ b/wallet/subnet/primary/examples/sign-subnet-to-l1-conversion/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_go//go:def.bzl", "go_binary", "go_library") + +go_library( + name = "sign-subnet-to-l1-conversion_lib", + srcs = ["main.go"], + importpath = "github.com/ava-labs/avalanchego/wallet/subnet/primary/examples/sign-subnet-to-l1-conversion", + visibility = ["//visibility:private"], + deps = [ + "//api/info", + "//ids", + "//message", + "//network/p2p", + "//network/peer", + "//proto/pb/sdk", + "//snow/networking/router", + "//utils/compression", + "//utils/constants", + "//vms/platformvm/warp", + "//vms/platformvm/warp/message", + "//vms/platformvm/warp/payload", + "//wallet/subnet/primary", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + ], +) + +go_binary( + name = "sign-subnet-to-l1-conversion", + embed = [":sign-subnet-to-l1-conversion_lib"], + visibility = ["//visibility:public"], +) diff --git a/x/archivedb/BUILD.bazel b/x/archivedb/BUILD.bazel new file mode 100644 index 000000000000..6dc998626134 --- /dev/null +++ b/x/archivedb/BUILD.bazel @@ -0,0 +1,34 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "archivedb", + srcs = [ + "batch.go", + "db.go", + "key.go", + "reader.go", + "value.go", + ], + importpath = "github.com/ava-labs/avalanchego/x/archivedb", + visibility = ["//visibility:public"], + deps = [ + "//api/health", + "//database", + "//utils/wrappers", + ], +) + +go_test( + name = "archivedb_test", + srcs = [ + "db_test.go", + "key_test.go", + "prefix_test.go", + ], + embed = [":archivedb"], + deps = [ + "//database", + "//database/memdb", + "@com_github_stretchr_testify//require", + ], +) diff --git a/x/blockdb/BUILD.bazel b/x/blockdb/BUILD.bazel new file mode 100644 index 000000000000..02d8f4f1154f --- /dev/null +++ b/x/blockdb/BUILD.bazel @@ -0,0 +1,47 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "blockdb", + srcs = [ + "cache_db.go", + "config.go", + "database.go", + "errors.go", + ], + importpath = "github.com/ava-labs/avalanchego/x/blockdb", + visibility = ["//visibility:public"], + deps = [ + "//cache/lru", + "//database", + "//utils/compression", + "//utils/logging", + "//utils/math", + "@com_github_cespare_xxhash_v2//:xxhash", + "@com_github_datadog_zstd//:zstd", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "blockdb_test", + srcs = [ + "cache_db_test.go", + "database_test.go", + "datasplit_test.go", + "helpers_test.go", + "readblock_test.go", + "recovery_test.go", + "writeblock_test.go", + ], + embed = [":blockdb"], + deps = [ + "//cache/lru", + "//database", + "//database/heightindexdb/dbtest", + "//utils/compression", + "//utils/logging", + "//utils/math", + "@com_github_datadog_zstd//:zstd", + "@com_github_stretchr_testify//require", + ], +) diff --git a/x/merkledb/BUILD.bazel b/x/merkledb/BUILD.bazel new file mode 100644 index 000000000000..97715a4c9d78 --- /dev/null +++ b/x/merkledb/BUILD.bazel @@ -0,0 +1,102 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "merkledb", + srcs = [ + "batch.go", + "bytes_pool.go", + "cache.go", + "codec.go", + "db.go", + "hashing.go", + "history.go", + "intermediate_node_db.go", + "key.go", + "metrics.go", + "node.go", + "proof.go", + "tracer.go", + "trie.go", + "value_node_db.go", + "view.go", + "view_iterator.go", + "wait_group.go", + ], + importpath = "github.com/ava-labs/avalanchego/x/merkledb", + visibility = ["//visibility:public"], + deps = [ + "//cache", + "//cache/lru", + "//database", + "//database/memdb", + "//ids", + "//proto/pb/sync", + "//trace", + "//utils", + "//utils/buffer", + "//utils/heap", + "//utils/linked", + "//utils/maybe", + "//utils/metric", + "//utils/set", + "//utils/units", + "//utils/wrappers", + "//x/sync", + "//x/sync/protoutils", + "@com_github_prometheus_client_golang//prometheus", + "@io_opentelemetry_go_otel//attribute", + "@io_opentelemetry_go_otel_trace//:trace", + "@org_golang_google_protobuf//proto", + "@org_golang_x_exp//maps", + ], +) + +go_test( + name = "merkledb_test", + srcs = [ + "bytes_pool_test.go", + "cache_test.go", + "client_test.go", + "codec_test.go", + "db_test.go", + "hashing_test.go", + "helpers_test.go", + "history_test.go", + "intermediate_node_db_test.go", + "key_test.go", + "metrics_test.go", + "network_server_test.go", + "node_test.go", + "proof_test.go", + "sync_test.go", + "trie_test.go", + "value_node_db_test.go", + "view_iterator_test.go", + "view_test.go", + "wait_group_test.go", + ], + embed = [":merkledb"], + deps = [ + "//database", + "//database/dbtest", + "//database/memdb", + "//ids", + "//network/p2p", + "//network/p2p/p2ptest", + "//proto/pb/sync", + "//snow/engine/common", + "//trace", + "//utils", + "//utils/hashing", + "//utils/logging", + "//utils/maybe", + "//utils/set", + "//utils/units", + "//x/sync", + "@com_github_prometheus_client_golang//prometheus", + "@com_github_stretchr_testify//require", + "@org_golang_google_protobuf//proto", + "@org_golang_x_exp//maps", + "@org_golang_x_sync//errgroup", + ], +) diff --git a/x/sync/BUILD.bazel b/x/sync/BUILD.bazel new file mode 100644 index 000000000000..1ddf277f654b --- /dev/null +++ b/x/sync/BUILD.bazel @@ -0,0 +1,46 @@ +load("@rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "sync", + srcs = [ + "db.go", + "manager.go", + "metrics.go", + "network_server.go", + "workheap.go", + ], + importpath = "github.com/ava-labs/avalanchego/x/sync", + visibility = ["//visibility:public"], + deps = [ + "//ids", + "//network/p2p", + "//proto/pb/sync", + "//snow/engine/common", + "//utils/constants", + "//utils/hashing", + "//utils/heap", + "//utils/logging", + "//utils/maybe", + "//utils/set", + "//utils/units", + "//x/sync/protoutils", + "@com_github_google_btree//:btree", + "@com_github_prometheus_client_golang//prometheus", + "@org_golang_google_protobuf//proto", + "@org_uber_go_zap//:zap", + ], +) + +go_test( + name = "sync_test", + srcs = [ + "sync_test.go", + "workheap_test.go", + ], + embed = [":sync"], + deps = [ + "//ids", + "//utils/maybe", + "@com_github_stretchr_testify//require", + ], +) diff --git a/x/sync/protoutils/BUILD.bazel b/x/sync/protoutils/BUILD.bazel new file mode 100644 index 000000000000..8446cf6111ef --- /dev/null +++ b/x/sync/protoutils/BUILD.bazel @@ -0,0 +1,12 @@ +load("@rules_go//go:def.bzl", "go_library") + +go_library( + name = "protoutils", + srcs = ["utils.go"], + importpath = "github.com/ava-labs/avalanchego/x/sync/protoutils", + visibility = ["//visibility:public"], + deps = [ + "//proto/pb/sync", + "//utils/maybe", + ], +)