diff --git a/.cargo/config.toml b/.cargo/config.toml index 4b9b3fef..7ac1f5bb 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,3 +1,3 @@ [env] -NEARCORE_VERSION = "2.6.1" -NEARD_COMMIT = "60bb220fcc9853e68778ba33364b343c8d720b3a" +NEARCORE_VERSION = "2.6.5" +NEARD_COMMIT = "fe3f6de3aea0433310bcb4b61d3b8517e7ba3ffd" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 1bb9e5fe..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Release NearStateIndexer Workflow - -on: - release: - types: [created, published] - -jobs: - build-and-release: - permissions: - contents: write - runs-on: ubuntu-22.04 - if: > - (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')) || - (github.event_name == 'release' && github.event.action == 'created') - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Install Rust toolchain - run: | - rustup update stable - rustup default stable - - - name: Build release binary - run: | - cargo build --release --package near-state-indexer --verbose - strip target/release/near-state-indexer - cp target/release/near-state-indexer near-state-indexer - - - name: Determine UPLOAD_URL - run: | - if [[ "${{ github.event_name }}" == "push" ]]; then - TAG_NAME=${GITHUB_REF#refs/tags/} - RELEASE_RESPONSE=$(curl -s -X GET -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" "https://api.github.com/repos/${{ github.repository }}/releases/tags/$TAG_NAME") - UPLOAD_URL=$(echo "$RELEASE_RESPONSE" | jq -r .upload_url) - echo "UPLOAD_URL=$UPLOAD_URL" >> $GITHUB_ENV - else - echo "UPLOAD_URL=${{ github.event.release.upload_url }}" >> $GITHUB_ENV - fi - - - name: Upload release asset - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ env.UPLOAD_URL }} - asset_path: ./near-state-indexer/near-state-indexer - asset_name: near-state-indexer - asset_content_type: application/octet-stream - diff --git a/CHANGELOG.md b/CHANGELOG.md index 45dadca3..86e2c401 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased](https://github.com/near/read-rpc/compare/main...develop) +## [0.4.0](https://github.com/near/read-rpc/releases/tag/v0.4.0) + +### What's Changed +* Added postgres as a storage for `tx_details_storage` +* Changed database schema for state changes to improve performance +* Added new custom RPC method `emulate_tx` +* Fix lake authorization for fastnear data + +### Supported Nearcore Version +- nearcore v2.7.0 +- rust v1.86.0 + +## [0.3.4](https://github.com/near/read-rpc/releases/tag/v0.3.4) + ### What's Changed * Migrate from lake data to fastnear data * Add metrics to calculate the number of blocks which fetched from the cache and fastnear @@ -19,6 +33,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * `ShardLayout` depends on the `near-chain-configs::GenesisConfig` so now the `configuration` crate is responsible for downloading the genesis config and providing the `ShardLayout` automatically. This process is surrounded by additional logs to help with debugging. * Provide `Option` to `DatabaseConfig` since it's the most common case to care about shard layout in the database context * Refactor the configuration of the `rpc-server` crate to use the `ShardLayout` from the `configuration` crate + * `tx-details-storage` has been updated: + * Now it can work with either PostgreSQL or ScyllaDB + * The actual database interactions have been moved to the `database` crate and traits have been introduced to abstract the database interactions, so we can add more storage engines in the future + * `tx_details_storage_provider` parameter has been added to the `configuration` and defaults to `postgres` storage engine` + * `configuration` does not require `scylla_url` and will panic if the `tx_details_storage_provider` is set to `scylla` without the `scylla_url` parameter. The panic will occur during the initialization of the `tx-details-storage` in the `rpc-server` or `tx-indexer` crates. + * `rpc-server` will instantiate the `tx-details-storage` with the `tx_details_storage_provider` from the configuration + * `rpc-server` doesn't not ignore the `sernder_account_id` parameter when fetching the `TransactionDetails`. With ScyllaDB this parameter is not needed, but required for PostgreSQL to fetch the `TransactionDetails` from the corresponding shard database ### Supported Nearcore Version - nearcore v2.6.3 diff --git a/Cargo.lock b/Cargo.lock index 40258afd..1e4f5493 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,7 +21,7 @@ dependencies = [ "actix-macros", "actix-rt", "actix_derive", - "bitflags 2.9.0", + "bitflags 2.9.2", "bytes", "crossbeam-channel", "futures-core", @@ -30,11 +30,11 @@ dependencies = [ "futures-util", "log", "once_cell", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project-lite", "smallvec", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", ] [[package]] @@ -43,14 +43,14 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.2", "bytes", "futures-core", "futures-sink", "memchr", "pin-project-lite", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "tracing", ] @@ -62,7 +62,7 @@ checksum = "0346d8c1f762b41b458ed3145eea914966bb9ad20b9be0d6d463b20d45586370" dependencies = [ "actix-utils", "actix-web", - "derive_more 0.99.19", + "derive_more 0.99.20", "futures-util", "log", "once_cell", @@ -86,16 +86,16 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa882656b67966045e4152c634051e70346939fced7117d5f0b52146a7c74c9" +checksum = "44dfe5c9e0004c623edc65391dfd51daa201e7e30ebd9c9bedf873048ec32bc2" dependencies = [ "actix-codec", "actix-rt", "actix-service", "actix-utils", "base64 0.22.1", - "bitflags 2.9.0", + "bitflags 2.9.2", "brotli", "bytes", "bytestring", @@ -104,7 +104,7 @@ dependencies = [ "flate2", "foldhash", "futures-core", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "httparse", "httpdate", @@ -114,11 +114,11 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rand 0.9.0", + "rand 0.9.2", "sha1", "smallvec", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "tracing", "zstd", ] @@ -130,7 +130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -140,7 +140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", - "cfg-if 1.0.0", + "cfg-if", "http 0.2.12", "regex", "regex-lite", @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6398974fd4284f4768af07965701efbbb5fdc0616bff20cade1bb14b77675e24" +checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" dependencies = [ "actix-rt", "actix-service", @@ -171,7 +171,7 @@ dependencies = [ "futures-core", "futures-util", "mio", - "socket2", + "socket2 0.5.10", "tokio", "tracing", ] @@ -203,7 +203,7 @@ dependencies = [ "pin-project-lite", "tokio", "tokio-openssl", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "tracing", ] @@ -219,9 +219,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.10.2" +version = "4.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e3b15b3dc6c6ed996e4032389e9849d4ab002b1e92fbfe85b5f307d1479b4d" +checksum = "a597b77b5c6d6a1e1097fddde329a83665e25c5437c696a3a9a4aa514a614dea" dependencies = [ "actix-codec", "actix-http", @@ -234,7 +234,7 @@ dependencies = [ "actix-web-codegen", "bytes", "bytestring", - "cfg-if 1.0.0", + "cfg-if", "cookie", "derive_more 2.0.1", "encoding_rs", @@ -254,7 +254,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", - "socket2", + "socket2 0.5.10", "time", "tracing", "url", @@ -269,7 +269,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -280,7 +280,7 @@ checksum = "b6ac1e58cded18cb28ddc17143c4dea5345b3ad575e14f32f66e4054a56eb271" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -294,9 +294,9 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "ahash" @@ -304,21 +304,21 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "once_cell", "version_check", ] [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "version_check", - "zerocopy 0.7.35", + "zerocopy", ] [[package]] @@ -368,9 +368,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" dependencies = [ "anstyle", "anstyle-parse", @@ -383,50 +383,50 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "anstyle-parse" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.2" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" dependencies = [ "anstyle", - "once_cell", - "windows-sys 0.59.0", + "once_cell_polyfill", + "windows-sys 0.60.2", ] [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" [[package]] name = "arbitrary" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" dependencies = [ "derive_arbitrary", ] @@ -437,18 +437,6 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - [[package]] name = "assert-json-diff" version = "2.0.2" @@ -495,18 +483,18 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -542,15 +530,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "awc" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caa7cbf905267e0e80a33142717a85e334e73d878be234c62ff116cf48731ddc" +checksum = "e76d68b4f02400c2f9110437f254873e8f265b35ea87352f142bc7c8e878115a" dependencies = [ "actix-codec", "actix-http", @@ -560,12 +548,12 @@ dependencies = [ "actix-utils", "base64 0.22.1", "bytes", - "cfg-if 1.0.0", + "cfg-if", "cookie", "derive_more 2.0.1", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "itoa", "log", @@ -573,7 +561,7 @@ dependencies = [ "openssl", "percent-encoding", "pin-project-lite", - "rand 0.9.0", + "rand 0.9.2", "serde", "serde_json", "serde_urlencoded", @@ -582,9 +570,9 @@ dependencies = [ [[package]] name = "aws-config" -version = "1.6.0" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a84fe2c5e9965fba0fbc2001db252f1d57527d82a905cca85127df227bca748" +checksum = "c478f5b10ce55c9a33f87ca3404ca92768b144fc1bfdede7c0121214a8283a25" dependencies = [ "aws-credential-types", "aws-runtime", @@ -602,7 +590,7 @@ dependencies = [ "fastrand 2.3.0", "hex", "http 1.3.1", - "ring 0.17.14", + "ring", "time", "tokio", "tracing", @@ -612,9 +600,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.2.2" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4471bef4c22a06d2c7a1b6492493d3fdf24a805323109d6874f9c94d5906ac14" +checksum = "1541072f81945fa1251f8795ef6c92c4282d74d59f88498ae7d4bf00f0ebdad9" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -640,9 +628,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.12.6" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01" +checksum = "5c953fe1ba023e6b7730c0d4b031d06f267f23a46167dcbd40316644b10a17ba" dependencies = [ "aws-lc-sys", "zeroize", @@ -650,9 +638,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.27.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77926887776171ced7d662120a75998e444d3750c951abfe07f90da130514b1f" +checksum = "dbfd150b5dbdb988bcc8fb1fe787eb6b7ee6180ca24da683b61ea5405f3d43ff" dependencies = [ "bindgen 0.69.5", "cc", @@ -672,9 +660,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.5.6" +version = "1.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aff45ffe35196e593ea3b9dd65b320e51e2dda95aff4390bc459e461d09c6ad" +checksum = "c034a1bc1d70e16e7f4e4caf7e9f7693e4c9c24cd91cf17c2a0b21abaebc7c8b" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -689,7 +677,6 @@ dependencies = [ "fastrand 2.3.0", "http 0.2.12", "http-body 0.4.6", - "once_cell", "percent-encoding", "pin-project-lite", "tracing", @@ -698,9 +685,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.79.0" +version = "1.103.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f63ba8f5fca32061c7d62d866ef65470edde38d4c5f8a0ebb8ff40a0521e1c" +checksum = "af040a86ae4378b7ed2f62c83b36be1848709bbbf5757ec850d0e08596a26be9" dependencies = [ "aws-credential-types", "aws-runtime", @@ -723,7 +710,6 @@ dependencies = [ "http 1.3.1", "http-body 0.4.6", "lru 0.12.5", - "once_cell", "percent-encoding", "regex-lite", "sha2", @@ -733,9 +719,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.62.0" +version = "1.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d5330ad4e8a1ff49e9f26b738611caa72b105c41d41733801d1a36e8f9de936" +checksum = "79ede098271e3471036c46957cba2ba30888f53bda2515bf04b560614a30a36e" dependencies = [ "aws-credential-types", "aws-runtime", @@ -747,17 +733,17 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", + "fastrand 2.3.0", "http 0.2.12", - "once_cell", "regex-lite", "tracing", ] [[package]] name = "aws-sdk-ssooidc" -version = "1.63.0" +version = "1.82.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7956b1a85d49082347a7d17daa2e32df191f3e23c03d47294b99f95413026a78" +checksum = "43326f724ba2cc957e6f3deac0ca1621a3e5d4146f5970c24c8a108dac33070f" dependencies = [ "aws-credential-types", "aws-runtime", @@ -769,17 +755,17 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", + "fastrand 2.3.0", "http 0.2.12", - "once_cell", "regex-lite", "tracing", ] [[package]] name = "aws-sdk-sts" -version = "1.63.0" +version = "1.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065c533fbe6f84962af33fcf02b0350b7c1f79285baab5924615d2be3b232855" +checksum = "a5468593c47efc31fdbe6c902d1a5fde8d9c82f78a3f8ccfe907b1e9434748cb" dependencies = [ "aws-credential-types", "aws-runtime", @@ -792,17 +778,17 @@ dependencies = [ "aws-smithy-types", "aws-smithy-xml", "aws-types", + "fastrand 2.3.0", "http 0.2.12", - "once_cell", "regex-lite", "tracing", ] [[package]] name = "aws-sigv4" -version = "1.3.0" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d03c3c05ff80d54ff860fe38c726f6f494c639ae975203a101335f223386db" +checksum = "084c34162187d39e3740cb635acd73c4e3a551a36146ad6fe8883c929c9f876c" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -816,10 +802,9 @@ dependencies = [ "hmac", "http 0.2.12", "http 1.3.1", - "once_cell", "p256", "percent-encoding", - "ring 0.17.14", + "ring", "sha2", "subtle", "time", @@ -840,16 +825,14 @@ dependencies = [ [[package]] name = "aws-smithy-checksums" -version = "0.63.1" +version = "0.63.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b65d21e1ba6f2cdec92044f904356a19f5ad86961acf015741106cdfafd747c0" +checksum = "4dbef71cd3cf607deb5c407df52f7e589e6849b296874ee448977efbb6d0832b" dependencies = [ "aws-smithy-http", "aws-smithy-types", "bytes", - "crc32c", - "crc32fast", - "crc64fast-nvme", + "crc-fast", "hex", "http 0.2.12", "http-body 0.4.6", @@ -862,9 +845,9 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.8" +version = "0.60.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c45d3dddac16c5c59d553ece225a88870cf81b7b813c9cc17b78cf4685eac7a" +checksum = "604c7aec361252b8f1c871a7641d5e0ba3a7f5a586e51b66bc9510a5519594d9" dependencies = [ "aws-smithy-types", "bytes", @@ -873,9 +856,9 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.62.0" +version = "0.62.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5949124d11e538ca21142d1fba61ab0a2a2c1bc3ed323cdb3e4b878bfb83166" +checksum = "7c4dacf2d38996cf729f55e7a762b30918229917eca115de45dfa8dfb97796c9" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", @@ -886,7 +869,6 @@ dependencies = [ "http 0.2.12", "http 1.3.1", "http-body 0.4.6", - "once_cell", "percent-encoding", "pin-project-lite", "pin-utils", @@ -895,25 +877,26 @@ dependencies = [ [[package]] name = "aws-smithy-http-client" -version = "1.0.0" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0497ef5d53065b7cd6a35e9c1654bd1fefeae5c52900d91d1b188b0af0f29324" +checksum = "f108f1ca850f3feef3009bdcc977be201bca9a91058864d9de0684e64514bee0" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "h2 0.4.8", + "h2 0.3.27", + "h2 0.4.12", "http 0.2.12", "http 1.3.1", "http-body 0.4.6", "hyper 0.14.32", "hyper 1.6.0", "hyper-rustls 0.24.2", - "hyper-rustls 0.27.5", + "hyper-rustls 0.27.7", "hyper-util", "pin-project-lite", "rustls 0.21.12", - "rustls 0.23.25", + "rustls 0.23.31", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", @@ -923,13 +906,22 @@ dependencies = [ [[package]] name = "aws-smithy-json" -version = "0.61.3" +version = "0.61.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92144e45819cae7dc62af23eac5a038a58aa544432d2102609654376a900bd07" +checksum = "a16e040799d29c17412943bdbf488fd75db04112d0c0d4b9290bacf5ae0014b9" dependencies = [ "aws-smithy-types", ] +[[package]] +name = "aws-smithy-observability" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9364d5989ac4dd918e5cc4c4bdcc61c9be17dcd2586ea7f69e348fc7c6cab393" +dependencies = [ + "aws-smithy-runtime-api", +] + [[package]] name = "aws-smithy-query" version = "0.60.7" @@ -942,13 +934,14 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.8.0" +version = "1.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6328865e36c6fd970094ead6b05efd047d3a80ec5fc3be5e743910da9f2ebf8" +checksum = "9e107ce0783019dbff59b3a244aa0c114e4a8c9d93498af9162608cd5474e796" dependencies = [ "aws-smithy-async", "aws-smithy-http", "aws-smithy-http-client", + "aws-smithy-observability", "aws-smithy-runtime-api", "aws-smithy-types", "bytes", @@ -957,7 +950,6 @@ dependencies = [ "http 1.3.1", "http-body 0.4.6", "http-body 1.0.1", - "once_cell", "pin-project-lite", "pin-utils", "tokio", @@ -966,9 +958,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.7.4" +version = "1.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da37cf5d57011cb1753456518ec76e31691f1f474b73934a284eb2a1c76510f" +checksum = "75d52251ed4b9776a3e8487b2a01ac915f73b2da3af8fc1e77e0fce697a550d4" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -983,9 +975,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836155caafba616c0ff9b07944324785de2ab016141c3550bd1c07882f8cee8f" +checksum = "d498595448e43de7f4296b7b7a18a8a02c61ec9349128c80a368f7c3b4ab11a8" dependencies = [ "base64-simd", "bytes", @@ -1004,29 +996,29 @@ dependencies = [ "serde", "time", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", ] [[package]] name = "aws-smithy-xml" -version = "0.60.9" +version = "0.60.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0b0166827aa700d3dc519f72f8b3a91c35d0b8d042dc5d643a91e6f80648fc" +checksum = "3db87b96cb1b16c024980f133968d52882ca0daaee3a086c6decc500f6c99728" dependencies = [ "xmlparser", ] [[package]] name = "aws-types" -version = "1.3.6" +version = "1.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3873f8deed8927ce8d04487630dc9ff73193bab64742a61d050e57a68dec4125" +checksum = "b069d19bf01e46298eaedd7c6f283fe565a59263e53eebec945f3e6398f42390" dependencies = [ "aws-credential-types", "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "rustc_version 0.4.1", + "rustc_version", "tracing", ] @@ -1077,21 +1069,21 @@ dependencies = [ [[package]] name = "backon" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "970d91570c01a8a5959b36ad7dd1c30642df24b6b3068710066f6809f7033bb7" +checksum = "592277618714fbcecda9a02ba7a8781f319d26532a88553bbacc77ba5d2b3a8d" dependencies = [ "fastrand 2.3.0", ] [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object", @@ -1105,12 +1097,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - [[package]] name = "base64" version = "0.13.1" @@ -1141,15 +1127,15 @@ dependencies = [ [[package]] name = "base64ct" -version = "1.7.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" [[package]] name = "bigdecimal" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f31f3af01c5c65a07985c804d3366560e6fa7883d640a122819b14ec327482c" +checksum = "1a22f228ab7a1b23027ccc6c350b72868017af7ea8356fbdf19f8d991c690013" dependencies = [ "autocfg", "libm", @@ -1158,15 +1144,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bindgen" version = "0.65.1" @@ -1185,7 +1162,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -1194,7 +1171,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.2", "cexpr", "clang-sys", "itertools 0.12.1", @@ -1207,7 +1184,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.100", + "syn 2.0.106", "which", ] @@ -1217,7 +1194,7 @@ version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.2", "cexpr", "clang-sys", "itertools 0.13.0", @@ -1226,7 +1203,7 @@ dependencies = [ "regex", "rustc-hash 2.1.1", "shlex", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -1237,9 +1214,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29" dependencies = [ "serde", ] @@ -1285,26 +1262,13 @@ dependencies = [ "digest 0.10.7", ] -[[package]] -name = "blake3" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17679a8d69b6d7fd9cd9801a536cec9fa5e5970b69f9d4747f70b39b031f5e7" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if 1.0.0", - "constant_time_eq", -] - [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.7", + "generic-array", ] [[package]] @@ -1319,9 +1283,9 @@ dependencies = [ [[package]] name = "blst" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c79a94619fade3c0b887670333513a67ac28a6a7e653eb260bf0d4103db38d" +checksum = "4fd49896f12ac9b6dcd7a5998466b9b58263a695a3dd1ecc1aaca2e12a90b080" dependencies = [ "cc", "glob", @@ -1331,9 +1295,9 @@ dependencies = [ [[package]] name = "borsh" -version = "1.5.6" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b74d67a0fc0af8e9823b79fd1c43a0900e5a8f0e0f4cc9210796bf3a820126" +checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" dependencies = [ "borsh-derive", "cfg_aliases", @@ -1341,22 +1305,22 @@ dependencies = [ [[package]] name = "borsh-derive" -version = "1.5.6" +version = "1.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d37ed1b2c9b78421218a0b4f6d8349132d6ec2cfeba1cfb0118b0a8e268df9e" +checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "brotli" -version = "7.0.0" +version = "8.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1365,9 +1329,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "4.0.2" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -1381,47 +1345,25 @@ checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" dependencies = [ "allocator-api2", ] -[[package]] -name = "bytecheck" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" -dependencies = [ - "bytecheck_derive 0.6.12", - "ptr_meta 0.1.4", - "simdutf8", -] - [[package]] name = "bytecheck" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50690fb3370fb9fe3550372746084c46f2ac8c9685c583d2be10eefd89d3d1a3" dependencies = [ - "bytecheck_derive 0.8.1", - "ptr_meta 0.3.0", + "bytecheck_derive", + "ptr_meta", "rancor", "simdutf8", ] -[[package]] -name = "bytecheck_derive" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "bytecheck_derive" version = "0.8.1" @@ -1430,7 +1372,7 @@ checksum = "efb7846e0cb180355c2dec69e721edafa36919850f1a9f52ffba4ebc0393cb71" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -1457,9 +1399,9 @@ dependencies = [ [[package]] name = "bytesize" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2c12f985c78475a6b8d629afd0c360260ef34cfef52efccdcfd31972f81c2e" +checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" dependencies = [ "serde", ] @@ -1495,7 +1437,7 @@ dependencies = [ [[package]] name = "cache-storage" -version = "0.3.3" +version = "0.3.4" dependencies = [ "anyhow", "futures", @@ -1514,9 +1456,9 @@ checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" [[package]] name = "cc" -version = "1.2.17" +version = "1.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f" dependencies = [ "jobserver", "libc", @@ -1534,15 +1476,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "cfg_aliases" @@ -1552,9 +1488,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1571,7 +1507,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" dependencies = [ - "generic-array 0.14.7", + "generic-array", ] [[package]] @@ -1587,9 +1523,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.32" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318" dependencies = [ "clap_builder", "clap_derive", @@ -1597,9 +1533,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.32" +version = "4.5.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8" dependencies = [ "anstream", "anstyle", @@ -1609,53 +1545,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.32" +version = "4.5.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "clap_lex" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" - -[[package]] -name = "cloud-storage" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7602ac4363f68ac757d6b87dd5d850549a14d37489902ae639c06ecec06ad275" -dependencies = [ - "async-trait", - "base64 0.13.1", - "bytes", - "chrono", - "dotenv", - "futures-util", - "hex", - "jsonwebtoken", - "lazy_static", - "openssl", - "percent-encoding", - "reqwest 0.11.27", - "serde", - "serde_json", - "tokio", -] - -[[package]] -name = "cloudabi" -version = "0.0.3" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags 1.3.2", -] +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cmake" @@ -1668,15 +1572,18 @@ dependencies = [ [[package]] name = "cobs" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror 2.0.15", +] [[package]] name = "colorchoice" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" [[package]] name = "combine" @@ -1689,7 +1596,7 @@ dependencies = [ "memchr", "pin-project-lite", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", ] [[package]] @@ -1703,14 +1610,14 @@ dependencies = [ [[package]] name = "configuration" -version = "0.3.3" +version = "0.3.4" dependencies = [ "anyhow", "dotenv", "lazy_static", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-lake-framework", - "near-primitives 2.6.3", + "near-primitives 2.7.0", "openssl", "opentelemetry 0.19.0", "opentelemetry-jaeger", @@ -1735,12 +1642,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - [[package]] name = "convert_case" version = "0.4.0" @@ -1770,9 +1671,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -1843,7 +1744,7 @@ dependencies = [ "cranelift-entity", "cranelift-isle", "gimli", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "log", "pulley-interpreter", "regalloc2", @@ -1921,9 +1822,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.2.1" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" dependencies = [ "crc-catalog", ] @@ -1935,30 +1836,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] -name = "crc32c" -version = "0.6.8" +name = "crc-fast" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" +checksum = "6bf62af4cc77d8fe1c22dde4e721d87f2f54056139d8c412e1366b740305f56f" dependencies = [ - "rustc_version 0.4.1", + "crc", + "digest 0.10.7", + "libc", + "rand 0.9.2", + "regex", ] [[package]] name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "crc64fast-nvme" -version = "1.2.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4955638f00a809894c947f85a024020a20815b65a5eea633798ea7924edab2b3" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "crc", + "cfg-if", ] [[package]] @@ -1976,9 +1872,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.14" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ "crossbeam-utils", ] @@ -2019,9 +1915,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "crypto-bigint" @@ -2029,7 +1925,7 @@ version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ - "generic-array 0.14.7", + "generic-array", "rand_core 0.6.4", "subtle", "zeroize", @@ -2051,7 +1947,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.7", + "generic-array", "typenum", ] @@ -2061,30 +1957,30 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.7", + "generic-array", "subtle", ] [[package]] name = "curl" -version = "0.4.47" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fb4d13a1be2b58f14d60adba57c9834b78c62fd86c3e76a148f732686e9265" +checksum = "79fc3b6dd0b87ba36e565715bf9a2ced221311db47bd18011676f24a6066edbc" dependencies = [ "curl-sys", "libc", "openssl-probe", "openssl-sys", "schannel", - "socket2", - "windows-sys 0.52.0", + "socket2 0.6.0", + "windows-sys 0.59.0", ] [[package]] name = "curl-sys" -version = "0.4.80+curl-8.12.1" +version = "0.4.83+curl-8.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f7df2eac63200c3ab25bde3b2268ef2ee56af3d238e76d61f01c3c49bff734" +checksum = "5830daf304027db10c82632a464879d46a3f7c4ba17a31592657ad16c719b483" dependencies = [ "cc", "libc", @@ -2092,7 +1988,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2101,13 +1997,13 @@ version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", "rand_core 0.6.4", - "rustc_version 0.4.1", + "rustc_version", "subtle", "zeroize", ] @@ -2120,42 +2016,76 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", ] [[package]] name = "darling" -version = "0.20.10" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "08440b3dd222c3d0433e63e097463969485f112baff337dfdaca043a0d760570" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.21.2", + "darling_macro 0.21.2", ] [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.100", + "syn 2.0.106", +] + +[[package]] +name = "darling_core" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25b7912bc28a04ab1b7715a68ea03aaa15662b43a1a4b2c480531fd19f8bf7e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", + "syn 2.0.106", ] [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "ce154b9bea7fb0c8e8326e62d00354000c36e79770ff21b8c84e3aa267d9d531" dependencies = [ - "darling_core", + "darling_core 0.21.2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -2164,16 +2094,16 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "hashbrown 0.14.5", - "lock_api 0.4.12", + "lock_api", "once_cell", - "parking_lot_core 0.9.10", + "parking_lot_core 0.9.11", ] [[package]] name = "database" -version = "0.3.3" +version = "0.3.4" dependencies = [ "anyhow", "async-trait", @@ -2183,12 +2113,17 @@ dependencies = [ "futures", "hex", "lazy_static", - "near-crypto 2.6.3", - "near-primitives 2.6.3", + "near-crypto 2.7.0", + "near-primitives 2.7.0", + "num-bigint 0.3.3", + "num-traits", "prometheus", "readnode-primitives", + "scylla", "serde_json", "sqlx", + "tokio", + "tracing", ] [[package]] @@ -2203,9 +2138,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", @@ -2214,9 +2149,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" dependencies = [ "powerfmt", "serde", @@ -2224,24 +2159,24 @@ dependencies = [ [[package]] name = "derive-where" -version = "1.2.7" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "derive_arbitrary" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -2259,10 +2194,10 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -2272,29 +2207,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "derive_more" -version = "0.99.19" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.1", - "syn 2.0.100", -] - -[[package]] -name = "derive_more" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" -dependencies = [ - "derive_more-impl 1.0.0", + "rustc_version", + "syn 2.0.106", ] [[package]] @@ -2303,18 +2229,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" dependencies = [ - "derive_more-impl 2.0.1", -] - -[[package]] -name = "derive_more-impl" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", + "derive_more-impl", ] [[package]] @@ -2325,26 +2240,17 @@ checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", "unicode-xid", ] -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.14.7", + "generic-array", ] [[package]] @@ -2387,7 +2293,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -2421,19 +2327,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] -name = "dynasm" -version = "1.2.3" +name = "dyn-clone" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add9a102807b524ec050363f09e06f1504214b0e1c7797f64261c891022dce8b" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "lazy_static", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" [[package]] name = "dynasm" @@ -2450,17 +2347,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "dynasmrt" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64fba5a42bd76a17cad4bfa00de168ee1cbfa06a5e8ce992ae880218c05641a9" -dependencies = [ - "byteorder", - "dynasm 1.2.3", - "memmap2", -] - [[package]] name = "dynasmrt" version = "2.0.0" @@ -2468,7 +2354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7dccc31a678058996aef614f6bd418ced384da70f284e83e2b7bf29b27b6a28" dependencies = [ "byteorder", - "dynasm 2.0.0", + "dynasm", "fnv", "memmap2", ] @@ -2502,9 +2388,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" dependencies = [ "curve25519-dalek", "ed25519", @@ -2533,7 +2419,7 @@ dependencies = [ "der 0.6.1", "digest 0.10.7", "ff", - "generic-array 0.14.7", + "generic-array", "group", "pkcs8 0.9.0", "rand_core 0.6.4", @@ -2560,7 +2446,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -2580,28 +2466,28 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "enumset" -version = "1.1.5" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" +checksum = "f50acec76c668b4621fe3694e5ddee53c8fae2a03410026f50947d195eb44dc1" dependencies = [ "enumset_derive", ] [[package]] name = "enumset_derive" -version = "0.10.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" +checksum = "588eaef9dbc5d72c5fa4edf162527e67dab5d14ba61519ef7c8e233d5bdc092c" dependencies = [ - "darling", + "darling 0.21.2", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -2612,33 +2498,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - -[[package]] -name = "errno" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ - "cc", "libc", + "windows-sys 0.60.2", ] [[package]] @@ -2647,7 +2512,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "home", "windows-sys 0.48.0", ] @@ -2660,9 +2525,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "5.4.0" +version = "5.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" dependencies = [ "concurrent-queue", "parking", @@ -2739,9 +2604,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" dependencies = [ "crc32fast", "miniz_oxide", @@ -2755,7 +2620,7 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", ] [[package]] @@ -2865,8 +2730,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" dependencies = [ "futures-core", - "lock_api 0.4.12", - "parking_lot 0.12.3", + "lock_api", + "parking_lot 0.12.4", ] [[package]] @@ -2909,7 +2774,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -2942,15 +2807,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -2967,32 +2823,36 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -3002,15 +2862,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" dependencies = [ "fallible-iterator", - "indexmap 2.8.0", + "indexmap 2.10.0", "stable_deref_trait", ] [[package]] name = "glob" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "group" @@ -3025,9 +2885,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" dependencies = [ "bytes", "fnv", @@ -3035,18 +2895,18 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.8.0", + "indexmap 2.10.0", "slab", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "tracing", ] [[package]] name = "h2" -version = "0.4.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ "atomic-waker", "bytes", @@ -3054,10 +2914,10 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.8.0", + "indexmap 2.10.0", "slab", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "tracing", ] @@ -3076,15 +2936,15 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash 0.8.11", + "ahash 0.8.12", "allocator-api2", ] [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", @@ -3098,7 +2958,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] [[package]] @@ -3124,9 +2984,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.9" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -3254,14 +3114,14 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.10", "tokio", "tower-service", "tracing", @@ -3277,7 +3137,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.8", + "h2 0.4.12", "http 1.3.1", "http-body 1.0.1", "httparse", @@ -3306,15 +3166,14 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.5" +version = "0.27.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ - "futures-util", "http 1.3.1", "hyper 1.6.0", "hyper-util", - "rustls 0.23.25", + "rustls 0.23.31", "rustls-native-certs 0.8.1", "rustls-pki-types", "tokio", @@ -3365,28 +3224,35 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.3.1", "http-body 1.0.1", "hyper 1.6.0", + "ipnet", + "libc", + "percent-encoding", "pin-project-lite", - "socket2", + "socket2 0.6.0", + "system-configuration 0.6.1", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] name = "iana-time-zone" -version = "0.1.62" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3408,21 +3274,22 @@ dependencies = [ [[package]] name = "icu_collections" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" dependencies = [ "displaydoc", - "yoke", + "potential_utf", + "yoke 0.8.0", "zerofrom", "zerovec", ] [[package]] -name = "icu_locid" -version = "1.5.0" +name = "icu_locale_core" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" dependencies = [ "displaydoc", "litemap", @@ -3431,31 +3298,11 @@ dependencies = [ "zerovec", ] -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - [[package]] name = "icu_normalizer" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" dependencies = [ "displaydoc", "icu_collections", @@ -3463,67 +3310,54 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", - "utf16_iter", - "utf8_iter", - "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" [[package]] name = "icu_properties" -version = "1.5.1" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" dependencies = [ "displaydoc", "icu_collections", - "icu_locid_transform", + "icu_locale_core", "icu_properties_data", "icu_provider", - "tinystr", + "potential_utf", + "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" [[package]] name = "icu_provider" -version = "1.5.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" dependencies = [ "displaydoc", - "icu_locid", - "icu_provider_macros", + "icu_locale_core", "stable_deref_trait", "tinystr", "writeable", - "yoke", + "yoke 0.8.0", "zerofrom", + "zerotrie", "zerovec", ] -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -3543,9 +3377,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ "icu_normalizer", "icu_properties", @@ -3584,12 +3418,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "serde", ] @@ -3599,7 +3433,7 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -3608,12 +3442,33 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" +[[package]] +name = "io-uring" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4" +dependencies = [ + "bitflags 2.9.2", + "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.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -3672,6 +3527,15 @@ 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" @@ -3680,10 +3544,11 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jobserver" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" dependencies = [ + "getrandom 0.3.3", "libc", ] @@ -3703,20 +3568,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9dbbfed4e59ba9750e15ba154fdfd9329cee16ff3df539c2666b70f58cc32105" -[[package]] -name = "jsonwebtoken" -version = "7.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afabcc15e437a6484fc4f12d0fd63068fe457bf93f1c148d3d9649c60b103f32" -dependencies = [ - "base64 0.12.3", - "pem", - "ring 0.16.20", - "serde", - "serde_json", - "simple_asn1", -] - [[package]] name = "keccak" version = "0.1.5" @@ -3738,7 +3589,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -3755,31 +3606,31 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.175" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ - "cfg-if 1.0.0", - "windows-targets 0.52.6", + "cfg-if", + "windows-targets 0.53.3", ] [[package]] name = "libm" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libmimalloc-sys" -version = "0.1.40" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d0e07885d6a754b9c7993f2625187ad694ee985d60f23355ff0e7077261502" +checksum = "bf88cd67e9de251c1781dbe2f641a1a3ad66eaae831b8a2c38fbdc5ddae16d4d" dependencies = [ "cc", "libc", @@ -3787,12 +3638,13 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.3" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.2", "libc", + "redox_syscall 0.5.17", ] [[package]] @@ -3842,15 +3694,15 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "litemap" -version = "0.7.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "local-channel" @@ -3871,21 +3723,13 @@ checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" [[package]] name = "lock_api" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "lock_api" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" dependencies = [ "autocfg", "scopeguard", + "serde", ] [[package]] @@ -3896,7 +3740,7 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "logic-state-indexer" -version = "0.3.3" +version = "0.3.4" dependencies = [ "actix-web", "anyhow", @@ -3909,8 +3753,8 @@ dependencies = [ "humantime", "lazy_static", "near-indexer-primitives", - "near-jsonrpc-client 0.17.0", - "near-primitives 2.6.3", + "near-jsonrpc-client 0.18.0", + "near-primitives 2.7.0", "prometheus", "readnode-primitives", "tokio", @@ -3933,9 +3777,15 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.2", + "hashbrown 0.15.5", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lz4-sys" version = "1.11.1+lz4-1.10.0" @@ -3948,18 +3798,18 @@ dependencies = [ [[package]] name = "lz4_flex" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" +checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" dependencies = [ "twox-hash", ] [[package]] name = "mach2" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" dependencies = [ "libc", ] @@ -3987,7 +3837,7 @@ checksum = "5cf92c10c7e361d6b99666ec1c6f9805b0bea2c3bd8c78dc6fe98ac5bd78db11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -3996,7 +3846,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "digest 0.10.7", ] @@ -4008,9 +3858,9 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "memfd" @@ -4021,16 +3871,6 @@ dependencies = [ "rustix 0.38.44", ] -[[package]] -name = "memmap" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6585fd95e7bb50d6cc31e20d4cf9afb4e2ba16c5846fc76793f11218da9c475b" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "memmap2" version = "0.5.10" @@ -4042,9 +3882,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.6.5" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ "autocfg", ] @@ -4060,9 +3900,9 @@ dependencies = [ [[package]] name = "mimalloc" -version = "0.1.44" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99585191385958383e13f6b822e6b6d8d9cf928e7d286ceb092da92b43c87bc1" +checksum = "b1791cbe101e95af5764f06f20f6760521f7158f69dbf9d6baf941ee1bf6bc40" dependencies = [ "libmimalloc-sys", ] @@ -4090,23 +3930,23 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", ] [[package]] @@ -4123,22 +3963,22 @@ checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" [[package]] name = "munge" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0091202c98cf06da46c279fdf50cccb6b1c43b4521abdf6a27b4c7e71d5d9d7" +checksum = "d7feb0b48aa0a25f9fe0899482c6e1379ee7a11b24a53073eacdecb9adb6dc60" dependencies = [ "munge_macro", ] [[package]] name = "munge_macro" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "734799cf91479720b2f970c61a22850940dd91e27d4f02b1c6fc792778df2459" +checksum = "f2e3795a5d2da581a8b252fec6022eee01aea10161a4d1bf237d4cbe47f7e988" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -4166,9 +4006,9 @@ dependencies = [ [[package]] name = "near-account-id" -version = "1.0.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35cbb989542587b47205e608324ddd391f0cee1c22b4b64ae49f458334b95907" +checksum = "8542f031adc257a27ba46ad904c241a88470ee95130663a9e5c08cf8e124f4d4" dependencies = [ "borsh", "serde", @@ -4176,17 +4016,16 @@ dependencies = [ [[package]] name = "near-async" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", - "derive_more 1.0.0", "futures", "near-async-derive", - "near-o11y 2.6.3", + "near-o11y 2.7.0", "near-performance-metrics", "near-time", - "once_cell", + "parking_lot 0.12.4", "serde", "serde_json", "time", @@ -4196,26 +4035,27 @@ dependencies = [ [[package]] name = "near-async-derive" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "near-cache" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "lru 0.12.5", + "parking_lot 0.12.4", ] [[package]] name = "near-chain" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", "anyhow", @@ -4226,37 +4066,34 @@ dependencies = [ "easy-ext", "enum-map", "itertools 0.12.1", - "itoa", "lru 0.12.5", - "more-asserts", "near-async", - "near-cache", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-chain-primitives", "near-client-primitives", - "near-crypto 2.6.3", + "near-crypto 2.7.0", "near-epoch-manager", - "near-mainnet-res", "near-network", - "near-o11y 2.6.3", - "near-parameters 2.6.3", + "near-o11y 2.7.0", + "near-parameters 2.7.0", "near-performance-metrics", "near-performance-metrics-macros", "near-pool", - "near-primitives 2.6.3", + "near-primitives 2.7.0", "near-schema-checker-lib", "near-store", - "near-vm-runner 2.6.3", + "near-vm-runner 2.7.0", "node-runtime", "num-rational", - "once_cell", + "parking_lot 0.12.4", "rand 0.8.5", "rand_chacha 0.3.1", "rayon", + "reed-solomon-erasure 6.0.0", "serde", "strum", "tempfile", - "thiserror 2.0.12", + "thiserror 2.0.15", "time", "tokio", "tracing", @@ -4271,7 +4108,7 @@ dependencies = [ "anyhow", "bytesize", "chrono", - "derive_more 0.99.19", + "derive_more 0.99.20", "near-config-utils 0.20.1", "near-crypto 0.20.1", "near-parameters 0.20.1", @@ -4287,20 +4124,21 @@ dependencies = [ [[package]] name = "near-chain-configs" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "anyhow", "bytesize", "chrono", - "derive_more 1.0.0", - "near-config-utils 2.6.3", - "near-crypto 2.6.3", - "near-o11y 2.6.3", - "near-parameters 2.6.3", - "near-primitives 2.6.3", + "derive_more 2.0.1", + "near-config-utils 2.7.0", + "near-crypto 2.7.0", + "near-o11y 2.7.0", + "near-parameters 2.7.0", + "near-primitives 2.7.0", "near-time", "num-rational", + "parking_lot 0.12.4", "serde", "serde_json", "sha2", @@ -4311,42 +4149,38 @@ dependencies = [ [[package]] name = "near-chain-primitives" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ - "near-crypto 2.6.3", - "near-primitives 2.6.3", + "near-crypto 2.7.0", + "near-primitives 2.7.0", "near-time", - "thiserror 2.0.12", - "time", + "thiserror 2.0.15", "tracing", ] [[package]] name = "near-chunks" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", - "borsh", - "chrono", - "derive_more 1.0.0", - "futures", "itertools 0.12.1", "lru 0.12.5", "near-async", "near-chain", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-chunks-primitives", - "near-crypto 2.6.3", + "near-crypto 2.7.0", "near-epoch-manager", "near-network", - "near-o11y 2.6.3", + "near-o11y 2.7.0", "near-performance-metrics", "near-performance-metrics-macros", "near-pool", - "near-primitives 2.6.3", + "near-primitives 2.7.0", "near-store", + "parking_lot 0.12.4", "rand 0.8.5", "reed-solomon-erasure 6.0.0", "strum", @@ -4356,91 +4190,84 @@ dependencies = [ [[package]] name = "near-chunks-primitives" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "near-chain-primitives", - "near-primitives 2.6.3", + "near-primitives 2.7.0", ] [[package]] name = "near-client" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", "actix-rt", "anyhow", - "async-trait", "borsh", "bytesize", - "chrono", - "cloud-storage", - "derive_more 1.0.0", "futures", "itertools 0.12.1", "lru 0.12.5", "near-async", "near-cache", "near-chain", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-chain-primitives", "near-chunks", "near-client-primitives", - "near-crypto 2.6.3", + "near-crypto 2.7.0", "near-dyn-configs", "near-epoch-manager", "near-network", - "near-o11y 2.6.3", - "near-parameters 2.6.3", + "near-o11y 2.7.0", + "near-parameters 2.7.0", "near-performance-metrics", "near-performance-metrics-macros", "near-pool", - "near-primitives 2.6.3", + "near-primitives 2.7.0", "near-store", "near-telemetry", - "near-vm-runner 2.6.3", + "near-vm-runner 2.7.0", "num-rational", - "once_cell", + "object_store", + "parking_lot 0.12.4", "percent-encoding", "rand 0.8.5", "rayon", "reed-solomon-erasure 6.0.0", "regex", - "reqwest 0.11.27", + "reqwest 0.12.23", "rust-s3", "serde", "serde_json", "strum", "sysinfo", "tempfile", - "thiserror 2.0.12", "time", "tokio", "tokio-stream", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "tracing", "yansi", ] [[package]] name = "near-client-primitives" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", - "chrono", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-chain-primitives", "near-chunks-primitives", - "near-crypto 2.6.3", - "near-primitives 2.6.3", + "near-crypto 2.7.0", + "near-primitives 2.7.0", "near-time", "serde", - "serde_json", "strum", - "thiserror 2.0.12", - "time", + "thiserror 2.0.15", "tracing", ] @@ -4458,12 +4285,12 @@ dependencies = [ [[package]] name = "near-config-utils" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "anyhow", "json_comments", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", ] @@ -4478,7 +4305,7 @@ dependencies = [ "bs58", "c2-chacha", "curve25519-dalek", - "derive_more 0.99.19", + "derive_more 0.99.20", "ed25519-dalek", "hex", "near-account-id", @@ -4496,71 +4323,66 @@ dependencies = [ [[package]] name = "near-crypto" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "blake2 0.10.6", "borsh", "bs58", "curve25519-dalek", - "derive_more 1.0.0", + "derive_more 2.0.1", "ed25519-dalek", "hex", "near-account-id", - "near-config-utils 2.6.3", + "near-config-utils 2.7.0", "near-schema-checker-lib", - "near-stdx 2.6.3", + "near-stdx 2.7.0", "primitive-types", "rand 0.8.5", "secp256k1", "serde", "serde_json", "subtle", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "near-dyn-configs" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "anyhow", - "near-chain-configs 2.6.3", - "near-crypto 2.6.3", - "near-o11y 2.6.3", - "near-primitives 2.6.3", + "near-chain-configs 2.7.0", + "near-o11y 2.7.0", + "near-primitives 2.7.0", "near-time", - "prometheus", - "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", "tokio", - "tracing", ] [[package]] name = "near-epoch-manager" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "borsh", "itertools 0.12.1", "near-cache", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-chain-primitives", - "near-crypto 2.6.3", - "near-o11y 2.6.3", - "near-primitives 2.6.3", + "near-crypto 2.7.0", + "near-o11y 2.7.0", + "near-primitives 2.7.0", "near-schema-checker-lib", "near-store", "num-bigint 0.3.3", "num-rational", + "parking_lot 0.12.4", "primitive-types", "rand 0.8.5", "rand_hc 0.3.2", "serde", - "serde_json", - "smart-default 0.7.1", "tracing", ] @@ -4575,50 +4397,43 @@ dependencies = [ [[package]] name = "near-fmt" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ - "near-primitives-core 2.6.3", + "near-primitives-core 2.7.0", ] [[package]] name = "near-indexer-primitives" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ - "near-primitives 2.6.3", + "near-primitives 2.7.0", "serde", - "serde_json", ] [[package]] name = "near-jsonrpc" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ - "actix", "actix-cors 0.6.5", "actix-web", "bs58", - "derive_more 1.0.0", "easy-ext", - "futures", - "hex", "near-async", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-client", "near-client-primitives", "near-jsonrpc-client-internal", - "near-jsonrpc-primitives 2.6.3", + "near-jsonrpc-primitives 2.7.0", "near-network", - "near-o11y 2.6.3", - "near-primitives 2.6.3", + "near-o11y 2.7.0", + "near-primitives 2.7.0", "serde", "serde_json", - "serde_with", "tokio", "tracing", - "tracing-subscriber", ] [[package]] @@ -4642,32 +4457,31 @@ dependencies = [ [[package]] name = "near-jsonrpc-client" -version = "0.17.0" -source = "git+https://github.com/kobayurii/near-jsonrpc-client-rs.git?branch=fork%2F0.17.1#f2af1d3f098da2a73a442aee93bd221cd96a34a0" +version = "0.18.0" +source = "git+https://github.com/kobayurii/near-jsonrpc-client-rs.git?branch=fork%2F0.18.0#ebb4002da816cf4665c3f8ebae42d4c3258ae304" dependencies = [ "borsh", "lazy_static", "log", - "near-chain-configs 2.6.3", - "near-crypto 2.6.3", - "near-jsonrpc-primitives 2.6.3", - "near-primitives 2.6.3", - "reqwest 0.12.15", + "near-chain-configs 2.7.0", + "near-crypto 2.7.0", + "near-jsonrpc-primitives 2.7.0", + "near-primitives 2.7.0", + "reqwest 0.12.23", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "near-jsonrpc-client-internal" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ - "actix-http", "awc", "futures", - "near-jsonrpc-primitives 2.6.3", - "near-primitives 2.6.3", + "near-jsonrpc-primitives 2.7.0", + "near-primitives 2.7.0", "serde", "serde_json", ] @@ -4690,25 +4504,26 @@ dependencies = [ [[package]] name = "near-jsonrpc-primitives" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "arbitrary", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-client-primitives", - "near-crypto 2.6.3", - "near-primitives 2.6.3", + "near-crypto 2.7.0", + "near-primitives 2.7.0", "near-schema-checker-lib", + "near-time", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", "time", ] [[package]] name = "near-lake-framework" version = "0.0.0" -source = "git+https://github.com/kobayurii/near-lake-framework-rs.git?branch=fork%2F0.7.17#c1919120a4be4d0cae3667024c0638bac693d0fd" +source = "git+https://github.com/kobayurii/near-lake-framework-rs.git?branch=fork%2F0.7.20#b51a540c3ba750909138f9dcbc96d154c4cf6509" dependencies = [ "anyhow", "async-stream", @@ -4721,42 +4536,28 @@ dependencies = [ "derive_builder", "futures", "near-indexer-primitives", - "reqwest 0.12.15", + "reqwest 0.12.23", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", "tokio", "tokio-stream", "tracing", "url", ] -[[package]] -name = "near-mainnet-res" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" -dependencies = [ - "near-account-id", - "near-chain-configs 2.6.3", - "near-primitives 2.6.3", - "serde_json", -] - [[package]] name = "near-network" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", "anyhow", "arc-swap", - "async-trait", "borsh", "bytes", "bytesize", - "chrono", "crossbeam-channel", - "derive_more 1.0.0", "enum-map", "futures", "futures-util", @@ -4764,17 +4565,17 @@ dependencies = [ "itertools 0.12.1", "lru 0.12.5", "near-async", - "near-chain-configs 2.6.3", - "near-crypto 2.6.3", - "near-fmt 2.6.3", - "near-o11y 2.6.3", + "near-chain-configs 2.7.0", + "near-crypto 2.7.0", + "near-fmt 2.7.0", + "near-o11y 2.7.0", "near-performance-metrics", "near-performance-metrics-macros", - "near-primitives 2.6.3", + "near-primitives 2.7.0", "near-schema-checker-lib", "near-store", "opentelemetry 0.22.0", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project", "protobuf 3.7.2", "protobuf-codegen", @@ -4783,14 +4584,11 @@ dependencies = [ "reed-solomon-erasure 6.0.0", "serde", "sha2", - "smart-default 0.7.1", "strum", "stun", - "thiserror 2.0.12", + "thiserror 2.0.15", "time", "tokio", - "tokio-stream", - "tokio-util 0.7.14", "tracing", ] @@ -4824,23 +4622,23 @@ dependencies = [ [[package]] name = "near-o11y" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", "base64 0.21.7", "clap", - "near-crypto 2.6.3", - "near-primitives-core 2.6.3", + "near-crypto 2.7.0", + "near-primitives-core 2.7.0", "opentelemetry 0.22.0", "opentelemetry-otlp 0.15.0", "opentelemetry-semantic-conventions 0.14.0", "opentelemetry_sdk 0.22.1", + "parking_lot 0.12.4", "prometheus", "serde", "serde_json", - "thiserror 2.0.12", - "tokio", + "thiserror 2.0.15", "tracing", "tracing-appender", "tracing-opentelemetry 0.23.0", @@ -4868,55 +4666,52 @@ dependencies = [ [[package]] name = "near-parameters" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "borsh", "enum-map", "near-account-id", - "near-primitives-core 2.6.3", + "near-primitives-core 2.7.0", "near-schema-checker-lib", "num-rational", "serde", "serde_repr", "serde_yaml", "strum", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] name = "near-performance-metrics" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", - "bitflags 1.3.2", - "bytes", "futures", "libc", - "tokio", - "tokio-util 0.7.14", + "parking_lot 0.12.4", "tracing", ] [[package]] name = "near-performance-metrics-macros" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "near-pool" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "borsh", - "near-crypto 2.6.3", - "near-o11y 2.6.3", - "near-primitives 2.6.3", + "near-crypto 2.7.0", + "near-o11y 2.7.0", + "near-primitives 2.7.0", "rand 0.8.5", ] @@ -4930,9 +4725,9 @@ dependencies = [ "base64 0.21.7", "borsh", "bytesize", - "cfg-if 1.0.0", + "cfg-if", "chrono", - "derive_more 0.99.19", + "derive_more 0.99.20", "easy-ext", "enum-map", "hex", @@ -4964,8 +4759,8 @@ dependencies = [ [[package]] name = "near-primitives" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "arbitrary", "base64 0.21.7", @@ -4973,19 +4768,18 @@ dependencies = [ "borsh", "bytes", "bytesize", - "cfg-if 1.0.0", "chrono", - "derive_more 1.0.0", + "derive_more 2.0.1", "easy-ext", "enum-map", "hex", "itertools 0.12.1", - "near-crypto 2.6.3", - "near-fmt 2.6.3", - "near-parameters 2.6.3", - "near-primitives-core 2.6.3", + "near-crypto 2.7.0", + "near-fmt 2.7.0", + "near-parameters 2.7.0", + "near-primitives-core 2.7.0", "near-schema-checker-lib", - "near-stdx 2.6.3", + "near-stdx 2.7.0", "near-time", "num-rational", "ordered-float 4.6.0", @@ -4999,7 +4793,7 @@ dependencies = [ "sha3", "smart-default 0.7.1", "strum", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", "zstd", ] @@ -5014,7 +4808,7 @@ dependencies = [ "base64 0.21.7", "borsh", "bs58", - "derive_more 0.99.19", + "derive_more 0.99.20", "enum-map", "near-account-id", "num-rational", @@ -5028,14 +4822,14 @@ dependencies = [ [[package]] name = "near-primitives-core" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "arbitrary", "base64 0.21.7", "borsh", "bs58", - "derive_more 1.0.0", + "derive_more 2.0.1", "enum-map", "near-account-id", "near-schema-checker-lib", @@ -5043,7 +4837,7 @@ dependencies = [ "serde", "serde_repr", "sha2", - "thiserror 2.0.12", + "thiserror 2.0.15", ] [[package]] @@ -5054,7 +4848,7 @@ checksum = "80fca203c51edd9595ec14db1d13359fb9ede32314990bf296b6c5c4502f6ab7" dependencies = [ "quote", "serde", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -5066,18 +4860,18 @@ dependencies = [ "fs2", "near-rpc-error-core", "serde", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "near-schema-checker-core" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" [[package]] name = "near-schema-checker-lib" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "near-schema-checker-core", "near-schema-checker-macro", @@ -5085,8 +4879,8 @@ dependencies = [ [[package]] name = "near-schema-checker-macro" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" [[package]] name = "near-stdx" @@ -5096,13 +4890,13 @@ checksum = "855fd5540e3b4ff6fedf12aba2db1ee4b371b36f465da1363a6d022b27cb43b8" [[package]] name = "near-stdx" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" [[package]] name = "near-store" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", "actix-rt", @@ -5111,24 +4905,25 @@ dependencies = [ "bytesize", "crossbeam", "derive-where", - "derive_more 1.0.0", + "derive_more 2.0.1", "enum-map", "hex", "itertools 0.12.1", "itoa", "lru 0.12.5", - "near-chain-configs 2.6.3", + "near-chain-configs 2.7.0", "near-chain-primitives", - "near-crypto 2.6.3", - "near-fmt 2.6.3", - "near-o11y 2.6.3", - "near-parameters 2.6.3", - "near-primitives 2.6.3", + "near-crypto 2.7.0", + "near-fmt 2.7.0", + "near-o11y 2.7.0", + "near-parameters 2.7.0", + "near-primitives 2.7.0", "near-schema-checker-lib", - "near-stdx 2.6.3", + "near-stdx 2.7.0", "near-time", - "near-vm-runner 2.6.3", + "near-vm-runner 2.7.0", "num_cpus", + "parking_lot 0.12.4", "rand 0.8.5", "rayon", "reed-solomon-erasure 6.0.0", @@ -5140,26 +4935,23 @@ dependencies = [ "static_assertions", "strum", "tempfile", - "thiserror 2.0.12", - "thread_local", + "thiserror 2.0.15", "tokio", "tracing", ] [[package]] name = "near-telemetry" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "actix", "awc", "futures", "near-async", - "near-o11y 2.6.3", + "near-o11y 2.7.0", "near-performance-metrics", "near-performance-metrics-macros", - "near-time", - "openssl", "serde", "serde_json", "tracing", @@ -5167,9 +4959,10 @@ dependencies = [ [[package]] name = "near-time" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ + "parking_lot 0.12.4", "serde", "time", "tokio", @@ -5177,31 +4970,30 @@ dependencies = [ [[package]] name = "near-vm-compiler" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "enumset", "finite-wasm", "near-vm-types", "near-vm-vm", - "rkyv 0.8.10", + "rkyv", "target-lexicon 0.12.16", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", "wasmparser 0.99.0", ] [[package]] name = "near-vm-compiler-singlepass" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ - "dynasm 2.0.0", - "dynasmrt 2.0.0", + "dynasm", + "dynasmrt", "enumset", "finite-wasm", "memoffset 0.8.0", - "more-asserts", "near-vm-compiler", "near-vm-types", "near-vm-vm", @@ -5213,23 +5005,20 @@ dependencies = [ [[package]] name = "near-vm-engine" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "backtrace", - "cfg-if 1.0.0", - "enumset", "finite-wasm", "more-asserts", "near-vm-compiler", "near-vm-types", "near-vm-vm", - "region", - "rkyv 0.8.10", + "parking_lot 0.12.4", + "rkyv", "rustc-demangle", - "rustix 1.0.3", - "target-lexicon 0.12.16", - "thiserror 2.0.12", + "rustix 1.0.8", + "thiserror 2.0.15", "tracing", ] @@ -5265,8 +5054,8 @@ dependencies = [ [[package]] name = "near-vm-runner" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "anyhow", "blst", @@ -5277,44 +5066,33 @@ dependencies = [ "finite-wasm", "lru 0.12.5", "memoffset 0.8.0", - "near-crypto 2.6.3", - "near-o11y 2.6.3", - "near-parameters 2.6.3", - "near-primitives-core 2.6.3", + "near-crypto 2.7.0", + "near-o11y 2.7.0", + "near-parameters 2.7.0", + "near-primitives-core 2.7.0", "near-schema-checker-lib", - "near-stdx 2.6.3", + "near-stdx 2.7.0", "near-vm-compiler", "near-vm-compiler-singlepass", "near-vm-engine", "near-vm-types", "near-vm-vm", "num-rational", - "parity-wasm 0.41.0", - "parity-wasm 0.42.2", + "parking_lot 0.12.4", "prefix-sum-vec", "prometheus", - "pwasm-utils", "rand 0.8.5", "rayon", "ripemd", - "rustix 1.0.3", + "rustix 1.0.8", "serde", - "serde_repr", "sha2", "sha3", "strum", "tempfile", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", "wasm-encoder 0.224.1", - "wasmer-compiler-near", - "wasmer-compiler-singlepass-near", - "wasmer-engine-near", - "wasmer-engine-universal-near", - "wasmer-runtime-core-near", - "wasmer-runtime-near", - "wasmer-types-near", - "wasmer-vm-near", "wasmparser 0.78.2", "wasmtime", "zeropool-bn", @@ -5322,95 +5100,84 @@ dependencies = [ [[package]] name = "near-vm-types" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.10.0", "num-traits", - "rkyv 0.8.10", - "thiserror 2.0.12", + "rkyv", + "thiserror 2.0.15", ] [[package]] name = "near-vm-vm" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "backtrace", "cc", - "cfg-if 1.0.0", + "cfg-if", "finite-wasm", - "indexmap 2.8.0", "libc", "memoffset 0.8.0", "more-asserts", "near-vm-types", + "parking_lot 0.12.4", "region", - "rkyv 0.8.10", - "thiserror 2.0.12", + "rkyv", + "thiserror 2.0.15", "tracing", "winapi", ] [[package]] name = "near-wallet-contract" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "anyhow", - "near-primitives-core 2.6.3", - "near-vm-runner 2.6.3", -] - -[[package]] -name = "nix" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" -dependencies = [ - "bitflags 1.3.2", - "cc", - "cfg-if 0.1.10", - "libc", - "void", + "near-primitives-core 2.7.0", + "near-vm-runner 2.7.0", ] [[package]] name = "nix" -version = "0.24.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "libc", - "memoffset 0.6.5", + "memoffset 0.7.1", + "pin-utils", ] [[package]] name = "node-runtime" -version = "2.6.3" -source = "git+https://github.com/near/nearcore?rev=680b27eb0105655345535a20623aaeb3b49b82e0#680b27eb0105655345535a20623aaeb3b49b82e0" +version = "2.7.0" +source = "git+https://github.com/kobayurii/nearcore?branch=fork%2F2.7.0#32f674eca813b071ddf7213afca6b12c67570a56" dependencies = [ "borsh", "bytesize", "itertools 0.12.1", - "near-crypto 2.6.3", - "near-o11y 2.6.3", - "near-parameters 2.6.3", - "near-primitives 2.6.3", - "near-primitives-core 2.6.3", + "near-crypto 2.7.0", + "near-o11y 2.7.0", + "near-parameters 2.7.0", + "near-primitives 2.7.0", + "near-primitives-core 2.7.0", "near-store", - "near-vm-runner 2.6.3", + "near-vm-runner 2.7.0", "near-wallet-contract", "num-bigint 0.3.3", "num-traits", + "parking_lot 0.12.4", "rand 0.8.5", "rand_chacha 0.3.1", "rayon", "serde_json", "sha2", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", ] @@ -5443,17 +5210,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-bigint" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.3.3" @@ -5543,9 +5299,9 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -5558,47 +5314,89 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "crc32fast", - "hashbrown 0.15.2", - "indexmap 2.8.0", + "hashbrown 0.15.5", + "indexmap 2.10.0", "memchr", ] [[package]] -name = "once_cell" -version = "1.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" - -[[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" - -[[package]] -name = "openssl" -version = "0.10.71" +name = "object_store" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e14130c6a98cd258fdcb0fb6d744152343ff729cbfcb28c656a9d12b999fbcd" +checksum = "efc4f07659e11cd45a341cd24d71e683e3be65d9ff1f8150061678fe60437496" dependencies = [ - "bitflags 2.9.0", - "cfg-if 1.0.0", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" + "async-trait", + "base64 0.22.1", + "bytes", + "chrono", + "form_urlencoded", + "futures", + "http 1.3.1", + "http-body-util", + "humantime", + "hyper 1.6.0", + "itertools 0.14.0", + "parking_lot 0.12.4", + "percent-encoding", + "quick-xml", + "rand 0.9.2", + "reqwest 0.12.23", + "ring", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "serde_urlencoded", + "thiserror 2.0.15", + "tokio", + "tracing", + "url", + "walkdir", + "wasm-bindgen-futures", + "web-time", +] + +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl" +version = "0.10.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +dependencies = [ + "bitflags 2.9.2", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -5607,24 +5405,14 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" -[[package]] -name = "openssl-src" -version = "300.4.2+3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168ce4e058f975fe43e89d9ccf78ca668601887ae736090aacc23ae353c298e2" -dependencies = [ - "cc", -] - [[package]] name = "openssl-sys" -version = "0.9.106" +version = "0.9.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb61ea9811cc39e3c2069f40b8b8e2e70d8569b361f879786cc7ed48b777cdd" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" dependencies = [ "cc", "libc", - "openssl-src", "pkg-config", "vcpkg", ] @@ -5895,44 +5683,12 @@ dependencies = [ "sha2", ] -[[package]] -name = "page_size" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eebde548fbbf1ea81a99b128872779c437752fb99f217c45245e1a61dcd9edcd" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "parity-wasm" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc878dac00da22f8f61e7af3157988424567ab01d9920b962ef7dcbd7cd865" - -[[package]] -name = "parity-wasm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5e13c266502aadf83426d87d81a0f5d1ef45b8027f5a471c360abfe4bfae92" - [[package]] name = "parking" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" -[[package]] -name = "parking_lot" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" -dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.7.3", -] - [[package]] name = "parking_lot" version = "0.11.2" @@ -5940,32 +5696,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", - "lock_api 0.4.12", + "lock_api", "parking_lot_core 0.8.6", ] [[package]] name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api 0.4.12", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.7.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93f386bb233083c799e6e642a9d73db98c24a5deeb95ffc85bf281255dffc98" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "smallvec", - "winapi", + "lock_api", + "parking_lot_core 0.9.11", ] [[package]] @@ -5974,7 +5716,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall 0.2.16", @@ -5984,13 +5726,13 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "redox_syscall 0.5.10", + "redox_syscall 0.5.17", "smallvec", "windows-targets 0.52.6", ] @@ -6007,17 +5749,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" -[[package]] -name = "pem" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb" -dependencies = [ - "base64 0.13.1", - "once_cell", - "regex", -] - [[package]] name = "pem-rfc7468" version = "0.7.0" @@ -6035,7 +5766,7 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "perf-testing" -version = "0.3.3" +version = "0.3.4" dependencies = [ "anyhow", "chrono", @@ -6059,7 +5790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.8.0", + "indexmap 2.10.0", ] [[package]] @@ -6079,7 +5810,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -6100,7 +5831,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" dependencies = [ - "der 0.7.9", + "der 0.7.10", "pkcs8 0.10.2", "spki 0.7.3", ] @@ -6121,7 +5852,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" dependencies = [ - "der 0.7.9", + "der 0.7.10", "spki 0.7.3", ] @@ -6139,7 +5870,7 @@ checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" dependencies = [ "autocfg", "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "concurrent-queue", "libc", "log", @@ -6147,11 +5878,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + [[package]] name = "postcard" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" dependencies = [ "cobs", "embedded-io 0.4.0", @@ -6159,6 +5896,15 @@ dependencies = [ "serde", ] +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -6171,7 +5917,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.24", + "zerocopy", ] [[package]] @@ -6182,12 +5928,12 @@ checksum = "aa06bd51638b6e76ac9ba9b6afb4164fa647bd2916d722f2623fbb6d1ed8bdba" [[package]] name = "prettyplease" -version = "0.2.31" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" +checksum = "ff24dfcda44452b9816fff4cd4227e1bb73ff5a2f1bc1105aa92fb8565ce44d2" dependencies = [ "proc-macro2", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -6252,14 +5998,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" dependencies = [ "unicode-ident", ] @@ -6270,11 +6016,11 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d33c28a30771f7f96db69893f78b857f7450d7e0237e9c8fc6427a81bae7ed1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fnv", "lazy_static", "memchr", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "protobuf 2.28.0", "thiserror 1.0.69", ] @@ -6342,7 +6088,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -6394,7 +6140,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4aeaa1f2460f1d348eeaeed86aea999ce98c1bded6f089ff8514c9d9dbdc973" dependencies = [ "anyhow", - "indexmap 2.8.0", + "indexmap 2.10.0", "log", "protobuf 3.7.2", "protobuf-support", @@ -6414,40 +6160,20 @@ dependencies = [ [[package]] name = "psm" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" +checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" dependencies = [ "cc", ] -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive 0.1.4", -] - [[package]] name = "ptr_meta" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" dependencies = [ - "ptr_meta_derive 0.3.0", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "ptr_meta_derive", ] [[package]] @@ -6458,7 +6184,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -6473,14 +6199,68 @@ dependencies = [ ] [[package]] -name = "pwasm-utils" -version = "0.12.0" +name = "quick-xml" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f7a12f176deee919f4ba55326ee17491c8b707d0987aed822682c821b660192" +checksum = "9845d9dccf565065824e69f9f235fafba1587031eda353c1f1561cd6a6be78f4" dependencies = [ - "byteorder", - "log", - "parity-wasm 0.41.0", + "memchr", + "serde", +] + +[[package]] +name = "quinn" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls 0.23.31", + "socket2 0.5.10", + "thiserror 2.0.15", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash 2.1.1", + "rustls 0.23.31", + "rustls-pki-types", + "slab", + "thiserror 2.0.15", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.5.10", + "tracing", + "windows-sys 0.59.0", ] [[package]] @@ -6494,9 +6274,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "radium" @@ -6510,7 +6290,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947" dependencies = [ - "ptr_meta 0.3.0", + "ptr_meta", ] [[package]] @@ -6540,13 +6320,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.24", ] [[package]] @@ -6594,7 +6373,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "serde", ] @@ -6604,7 +6383,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", ] [[package]] @@ -6645,9 +6424,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" dependencies = [ "either", "rayon-core", @@ -6655,9 +6434,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -6665,7 +6444,7 @@ dependencies = [ [[package]] name = "read-rpc-server" -version = "0.3.3" +version = "0.3.4" dependencies = [ "actix-cors 0.7.1", "actix-web", @@ -6683,21 +6462,22 @@ dependencies = [ "lru 0.12.5", "mimalloc", "near-async", - "near-chain-configs 2.6.3", - "near-crypto 2.6.3", + "near-chain-configs 2.7.0", + "near-crypto 2.7.0", "near-indexer-primitives", "near-jsonrpc", - "near-jsonrpc-client 0.17.0", + "near-jsonrpc-client 0.18.0", "near-lake-framework", - "near-parameters 2.6.3", - "near-primitives 2.6.3", - "near-vm-runner 2.6.3", + "near-parameters 2.7.0", + "near-primitives 2.7.0", + "near-vm-runner 2.7.0", + "node-runtime", "prometheus", "readnode-primitives", - "rustc_version 0.4.1", + "rustc_version", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.15", "tokio", "tokio-stream", "tracing", @@ -6707,7 +6487,7 @@ dependencies = [ [[package]] name = "readnode-primitives" -version = "0.3.3" +version = "0.3.4" dependencies = [ "anyhow", "borsh", @@ -6737,18 +6517,12 @@ dependencies = [ "pin-project-lite", "ryu", "sha1_smol", - "socket2", + "socket2 0.5.10", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "url", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.16" @@ -6760,11 +6534,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.2", ] [[package]] @@ -6773,7 +6547,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.15", + "getrandom 0.2.16", "libredox", "thiserror 1.0.69", ] @@ -6799,7 +6573,27 @@ dependencies = [ "lru 0.7.8", "parking_lot 0.11.2", "smallvec", - "spin 0.9.8", + "spin", +] + +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", ] [[package]] @@ -6810,7 +6604,7 @@ checksum = "dc06e6b318142614e4a48bc725abbf08ff166694835c43c9dae5a9009704639a" dependencies = [ "allocator-api2", "bumpalo", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "log", "rustc-hash 2.1.1", "smallvec", @@ -6878,22 +6672,13 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "rend" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" -dependencies = [ - "bytecheck 0.6.12", -] - [[package]] name = "rend" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" dependencies = [ - "bytecheck 0.8.1", + "bytecheck", ] [[package]] @@ -6907,7 +6692,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.32", @@ -6928,7 +6713,7 @@ dependencies = [ "system-configuration 0.5.1", "tokio", "tokio-native-tls", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "tower-service", "url", "wasm-bindgen", @@ -6940,46 +6725,50 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ "base64 0.22.1", "bytes", "encoding_rs", + "futures-channel", "futures-core", "futures-util", - "h2 0.4.8", + "h2 0.4.12", "http 1.3.1", "http-body 1.0.1", "http-body-util", "hyper 1.6.0", - "hyper-rustls 0.27.5", + "hyper-rustls 0.27.7", "hyper-tls 0.6.0", "hyper-util", - "ipnet", "js-sys", "log", "mime", "native-tls", - "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.2.0", + "quinn", + "rustls 0.23.31", + "rustls-native-certs 0.8.1", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper 1.0.2", - "system-configuration 0.6.1", "tokio", "tokio-native-tls", + "tokio-rustls 0.26.2", + "tokio-util 0.7.16", "tower 0.5.2", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", - "windows-registry", ] [[package]] @@ -6993,21 +6782,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin 0.5.2", - "untrusted 0.7.1", - "web-sys", - "winapi", -] - [[package]] name = "ring" version = "0.17.14" @@ -7015,10 +6789,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if 1.0.0", - "getrandom 0.2.15", + "cfg-if", + "getrandom 0.2.16", "libc", - "untrusted 0.9.0", + "untrusted", "windows-sys 0.52.0", ] @@ -7033,61 +6807,32 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.7.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" -dependencies = [ - "bitvec", - "bytecheck 0.6.12", - "bytes", - "hashbrown 0.12.3", - "ptr_meta 0.1.4", - "rend 0.4.2", - "rkyv_derive 0.7.45", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65" +checksum = "19f5c3e5da784cd8c69d32cdc84673f3204536ca56e1fa01be31a74b92c932ac" dependencies = [ - "bytecheck 0.8.1", + "bytecheck", "bytes", - "hashbrown 0.15.2", - "indexmap 2.8.0", + "hashbrown 0.15.5", + "indexmap 2.10.0", "munge", - "ptr_meta 0.3.0", + "ptr_meta", "rancor", - "rend 0.5.2", - "rkyv_derive 0.8.10", + "rend", + "rkyv_derive", "tinyvec", "uuid", ] [[package]] name = "rkyv_derive" -version = "0.7.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "rkyv_derive" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" +checksum = "4270433626cffc9c4c1d3707dd681f2a2718d3d7b09ad754bec137acecda8d22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -7135,7 +6880,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "ordered-multimap", ] @@ -7150,7 +6895,7 @@ dependencies = [ "aws-region", "base64 0.13.1", "block_on_proc", - "cfg-if 1.0.0", + "cfg-if", "hex", "hmac", "http 0.2.12", @@ -7173,9 +6918,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" [[package]] name = "rustc-hash" @@ -7195,22 +6940,13 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.26", + "semver", ] [[package]] @@ -7219,8 +6955,8 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.0", - "errno 0.3.10", + "bitflags 2.9.2", + "errno", "libc", "linux-raw-sys 0.4.15", "windows-sys 0.59.0", @@ -7228,15 +6964,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.3" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" dependencies = [ - "bitflags 2.9.0", - "errno 0.3.10", + "bitflags 2.9.2", + "errno", "libc", - "linux-raw-sys 0.9.3", - "windows-sys 0.59.0", + "linux-raw-sys 0.9.4", + "windows-sys 0.60.2", ] [[package]] @@ -7246,23 +6982,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.17.14", + "ring", "rustls-webpki 0.101.7", "sct", ] [[package]] name = "rustls" -version = "0.23.25" +version = "0.23.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" dependencies = [ "aws-lc-rs", "log", "once_cell", - "ring 0.17.14", + "ring", "rustls-pki-types", - "rustls-webpki 0.103.0", + "rustls-webpki 0.103.4", "subtle", "zeroize", ] @@ -7288,7 +7024,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.2.0", + "security-framework 3.3.0", ] [[package]] @@ -7311,9 +7047,13 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] [[package]] name = "rustls-webpki" @@ -7321,27 +7061,27 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] name = "rustls-webpki" -version = "0.103.0" +version = "0.103.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" dependencies = [ "aws-lc-rs", - "ring 0.17.14", + "ring", "rustls-pki-types", - "untrusted 0.9.0", + "untrusted", ] [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rxml" @@ -7366,6 +7106,15 @@ 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 = "schannel" version = "0.1.27" @@ -7375,6 +7124,30 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -7387,8 +7160,8 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.14", - "untrusted 0.9.0", + "ring", + "untrusted", ] [[package]] @@ -7416,8 +7189,8 @@ dependencies = [ "scylla-macros", "smallvec", "snap", - "socket2", - "thiserror 2.0.12", + "socket2 0.5.10", + "thiserror 2.0.15", "tokio", "tokio-openssl", "tracing", @@ -7442,11 +7215,11 @@ dependencies = [ "secrecy", "snap", "stable_deref_trait", - "thiserror 2.0.12", + "thiserror 2.0.15", "time", "tokio", "uuid", - "yoke", + "yoke 0.7.5", ] [[package]] @@ -7455,18 +7228,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e878bfb8a235207864ac3fb0b51d7954c77fd38486e0e4fb4e037935ff7eb46c" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "sec1" version = "0.3.0" @@ -7475,7 +7242,7 @@ checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" dependencies = [ "base16ct", "der 0.6.1", - "generic-array 0.14.7", + "generic-array", "pkcs8 0.9.0", "subtle", "zeroize", @@ -7493,9 +7260,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "4473013577ec77b4ee3668179ef1186df3146e2cf2d927bd200974c6fe60fd99" dependencies = [ "cc", ] @@ -7515,7 +7282,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.2", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -7524,12 +7291,12 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "80fb1d92c5028aa318b4b8bd7302a5bfcf48be96a37fc6fc790f806b0004ee0c" dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", + "bitflags 2.9.2", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -7545,27 +7312,12 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.219" @@ -7575,16 +7327,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-bench" -version = "0.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d733da87e79faaac25616e33d26299a41143fd4cd42746cbb0e91d8feea243fd" -dependencies = [ - "byteorder", - "serde", -] - [[package]] name = "serde-xml-rs" version = "0.5.1" @@ -7597,15 +7339,6 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "serde_bytes" -version = "0.11.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" -dependencies = [ - "serde", -] - [[package]] name = "serde_derive" version = "1.0.219" @@ -7614,14 +7347,14 @@ checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" dependencies = [ "itoa", "memchr", @@ -7637,14 +7370,14 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "serde_spanned" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" dependencies = [ "serde", ] @@ -7663,15 +7396,17 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" dependencies = [ "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.8.0", + "indexmap 2.10.0", + "schemars 0.9.0", + "schemars 1.0.4", "serde", "serde_derive", "serde_json", @@ -7681,14 +7416,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -7697,7 +7432,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.10.0", "itoa", "ryu", "serde", @@ -7710,7 +7445,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -7723,11 +7458,11 @@ checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.10.7", ] @@ -7759,9 +7494,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" dependencies = [ "libc", ] @@ -7792,17 +7527,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" -[[package]] -name = "simple_asn1" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b" -dependencies = [ - "chrono", - "num-bigint 0.2.6", - "num-traits", -] - [[package]] name = "sized-chunks" version = "0.6.5" @@ -7815,12 +7539,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "sluice" @@ -7835,9 +7556,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" dependencies = [ "serde", ] @@ -7861,7 +7582,7 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -7883,19 +7604,23 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", ] [[package]] -name = "spin" -version = "0.5.2" +name = "socket2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] [[package]] name = "spin" @@ -7903,7 +7628,7 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ - "lock_api 0.4.12", + "lock_api", ] [[package]] @@ -7923,7 +7648,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", - "der 0.7.9", + "der 0.7.10", ] [[package]] @@ -7934,9 +7659,9 @@ checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" [[package]] name = "sqlx" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" dependencies = [ "sqlx-core", "sqlx-macros", @@ -7947,23 +7672,24 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" dependencies = [ + "base64 0.22.1", "bigdecimal", "bytes", "crc", "crossbeam-queue", "either", - "event-listener 5.4.0", + "event-listener 5.4.1", "futures-core", "futures-intrusive", "futures-io", "futures-util", - "hashbrown 0.15.2", + "hashbrown 0.15.5", "hashlink", - "indexmap 2.8.0", + "indexmap 2.10.0", "log", "memchr", "native-tls", @@ -7973,7 +7699,7 @@ dependencies = [ "serde_json", "sha2", "smallvec", - "thiserror 2.0.12", + "thiserror 2.0.15", "tokio", "tokio-stream", "tracing", @@ -7982,22 +7708,22 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" dependencies = [ "proc-macro2", "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "sqlx-macros-core" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" dependencies = [ "dotenvy", "either", @@ -8013,22 +7739,21 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.100", - "tempfile", + "syn 2.0.106", "tokio", "url", ] [[package]] name = "sqlx-mysql" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64 0.22.1", "bigdecimal", - "bitflags 2.9.0", + "bitflags 2.9.2", "byteorder", "bytes", "crc", @@ -8039,7 +7764,7 @@ dependencies = [ "futures-core", "futures-io", "futures-util", - "generic-array 0.14.7", + "generic-array", "hex", "hkdf", "hmac", @@ -8057,21 +7782,21 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", "whoami", ] [[package]] name = "sqlx-postgres" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64 0.22.1", "bigdecimal", - "bitflags 2.9.0", + "bitflags 2.9.2", "byteorder", "crc", "dotenvy", @@ -8096,16 +7821,16 @@ dependencies = [ "smallvec", "sqlx-core", "stringprep", - "thiserror 2.0.12", + "thiserror 2.0.15", "tracing", "whoami", ] [[package]] name = "sqlx-sqlite" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" dependencies = [ "atoi", "flume", @@ -8120,6 +7845,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", + "thiserror 2.0.15", "tracing", "url", ] @@ -8132,7 +7858,7 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "state-indexer" -version = "0.3.3" +version = "0.3.4" dependencies = [ "anyhow", "clap", @@ -8140,10 +7866,10 @@ dependencies = [ "database", "futures", "logic-state-indexer", - "near-jsonrpc-client 0.17.0", + "near-jsonrpc-client 0.18.0", "near-lake-framework", "openssl-probe", - "rustc_version 0.4.1", + "rustc_version", "tokio", "tokio-stream", "tracing", @@ -8196,16 +7922,16 @@ dependencies = [ [[package]] name = "stun" -version = "0.4.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7e94b1ec00bad60e6410e058b52f1c66de3dc5fe4d62d09b3e52bb7d3b73e25" +checksum = "ea256fb46a13f9204e9dee9982997b2c3097db175a9fddaa8350310d03c4d5a3" dependencies = [ - "base64 0.13.1", + "base64 0.22.1", "crc", "lazy_static", "md-5", "rand 0.8.5", - "ring 0.16.20", + "ring", "subtle", "thiserror 1.0.69", "tokio", @@ -8232,9 +7958,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.100" +version = "2.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" dependencies = [ "proc-macro2", "quote", @@ -8258,13 +7984,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -8273,7 +7999,7 @@ version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54cb4ebf3d49308b99e6e9dc95e989e2fdbdc210e4f67c39db0bb89ba927001c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "core-foundation-sys", "libc", "ntapi", @@ -8299,7 +8025,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.2", "core-foundation 0.9.4", "system-configuration-sys 0.6.0", ] @@ -8330,12 +8056,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" -[[package]] -name = "target-lexicon" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab0e7238dcc7b40a7be719a25365910f6807bd864f4cce6b2e6b873658e2b19d" - [[package]] name = "target-lexicon" version = "0.12.16" @@ -8350,14 +8070,14 @@ checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a" [[package]] name = "tempfile" -version = "3.19.1" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand 2.3.0", - "getrandom 0.3.2", + "getrandom 0.3.3", "once_cell", - "rustix 1.0.3", + "rustix 1.0.8", "windows-sys 0.59.0", ] @@ -8381,11 +8101,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.15", ] [[package]] @@ -8396,28 +8116,27 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ - "cfg-if 1.0.0", - "once_cell", + "cfg-if", ] [[package]] @@ -8454,9 +8173,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.39" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -8469,15 +8188,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -8485,9 +8204,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.7.6" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" dependencies = [ "displaydoc", "zerovec", @@ -8510,28 +8229,30 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.1" +version = "1.47.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a" +checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", "bytes", + "io-uring", "libc", "mio", - "parking_lot 0.12.3", + "parking_lot 0.12.4", "pin-project-lite", "signal-hook-registry", - "socket2", + "slab", + "socket2 0.6.0", "tokio-macros", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "tokio-io-timeout" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +checksum = "0bd86198d9ee903fedd2f9a2e72014287c0d9167e4ae43b5853007205dda1b76" dependencies = [ "pin-project-lite", "tokio", @@ -8545,7 +8266,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -8596,7 +8317,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.25", + "rustls 0.23.31", "tokio", ] @@ -8627,9 +8348,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.14" +version = "0.7.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9590b93e6fcc1739458317cccd391ad3955e2bde8913edf6f95f9e65a8f034" +checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" dependencies = [ "bytes", "futures-core", @@ -8640,9 +8361,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.20" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ "serde", "serde_spanned", @@ -8652,26 +8373,33 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.24" +version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.10.0", "serde", "serde_spanned", "toml_datetime", + "toml_write", "winnow", ] +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + [[package]] name = "tonic" version = "0.6.2" @@ -8684,7 +8412,7 @@ dependencies = [ "bytes", "futures-core", "futures-util", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.32", @@ -8714,7 +8442,7 @@ dependencies = [ "axum", "base64 0.21.7", "bytes", - "h2 0.3.26", + "h2 0.3.27", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.32", @@ -8756,7 +8484,7 @@ dependencies = [ "rand 0.8.5", "slab", "tokio", - "tokio-util 0.7.14", + "tokio-util 0.7.16", "tower-layer", "tower-service", "tracing", @@ -8777,6 +8505,24 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.2", + "bytes", + "futures-util", + "http 1.3.1", + "http-body 1.0.1", + "iri-string", + "pin-project-lite", + "tower 0.5.2", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" @@ -8803,9 +8549,9 @@ dependencies = [ [[package]] name = "tracing-actix-web" -version = "0.7.16" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332bbdf3bd208d1fe6446f8ffb4e8c2ae66e25da0fb38e0b69545e640ecee6a6" +checksum = "5360edd490ec8dee9fedfc6a9fd83ac2f01b3e1996e3261b9ad18a61971fe064" dependencies = [ "actix-web", "mutually_exclusive_features", @@ -8828,20 +8574,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] name = "tracing-core" -version = "0.1.33" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", "valuable", @@ -8979,20 +8725,20 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "twox-hash" -version = "1.6.3" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if 1.0.0", - "static_assertions", -] +checksum = "8b907da542cbced5261bd3256de1b3a1bf340a3d37f93425a07362a1d687de56" [[package]] name = "tx-details-storage" -version = "0.3.3" +version = "0.3.4" dependencies = [ "anyhow", + "async-trait", + "bigdecimal", + "database", "futures", + "near-primitives 2.7.0", "num-bigint 0.3.3", "num-traits", "readnode-primitives", @@ -9001,13 +8747,14 @@ dependencies = [ [[package]] name = "tx-indexer" -version = "0.3.3" +version = "0.3.4" dependencies = [ "actix-web", "anyhow", "cache-storage", "clap", "configuration", + "database", "futures", "futures-locks", "humantime", @@ -9017,7 +8764,7 @@ dependencies = [ "near-lake-framework", "prometheus", "readnode-primitives", - "rustc_version 0.4.1", + "rustc_version", "tokio", "tokio-retry", "tokio-stream", @@ -9088,12 +8835,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - [[package]] name = "untrusted" version = "0.9.0" @@ -9110,7 +8851,7 @@ dependencies = [ "flate2", "log", "once_cell", - "rustls 0.23.25", + "rustls 0.23.31", "rustls-pki-types", "url", "webpki-roots 0.26.11", @@ -9133,12 +8874,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8_iter" version = "1.0.4" @@ -9153,11 +8888,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.16.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" dependencies = [ - "getrandom 0.3.2", + "getrandom 0.3.3", + "js-sys", + "wasm-bindgen", ] [[package]] @@ -9182,12 +8919,12 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bac855a2ce6f843beb229757e6e570a42e837bcb15e5f449dd48d5747d41bf77" dependencies = [ - "darling", + "darling 0.20.11", "once_cell", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -9208,12 +8945,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "vsimd" version = "0.8.0" @@ -9226,6 +8957,16 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" +[[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" @@ -9243,9 +8984,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" @@ -9268,7 +9009,7 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -9284,7 +9025,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", "wasm-bindgen-shared", ] @@ -9294,7 +9035,7 @@ version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "once_cell", "wasm-bindgen", @@ -9319,7 +9060,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -9365,180 +9106,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmer-compiler-near" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fdae7245128f284476e6db9653ef0a15b011975091bcd7f9d7303132409662" -dependencies = [ - "enumset", - "rkyv 0.7.45", - "smallvec", - "target-lexicon 0.12.16", - "thiserror 1.0.69", - "wasmer-types-near", - "wasmer-vm-near", - "wasmparser 0.78.2", -] - -[[package]] -name = "wasmer-compiler-singlepass-near" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac4af0e438015585eb27b2c6f6869c58c540bfe27408b686b1778470bf301050" -dependencies = [ - "byteorder", - "dynasm 1.2.3", - "dynasmrt 1.2.3", - "lazy_static", - "memoffset 0.6.5", - "more-asserts", - "rayon", - "smallvec", - "wasmer-compiler-near", - "wasmer-types-near", - "wasmer-vm-near", -] - -[[package]] -name = "wasmer-engine-near" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4048411cabb2c94c7d8d11d9d0282cc6b15308b61ebc1e122c40e89865ebb5c5" -dependencies = [ - "backtrace", - "enumset", - "lazy_static", - "memmap2", - "more-asserts", - "rustc-demangle", - "target-lexicon 0.12.16", - "thiserror 1.0.69", - "wasmer-compiler-near", - "wasmer-types-near", - "wasmer-vm-near", -] - -[[package]] -name = "wasmer-engine-universal-near" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f31c3d2850ac7957406d3c9581d9435ea8126a26478709fa7e931b6f562b4d" -dependencies = [ - "cfg-if 1.0.0", - "enumset", - "leb128", - "region", - "rkyv 0.7.45", - "thiserror 1.0.69", - "wasmer-compiler-near", - "wasmer-engine-near", - "wasmer-types-near", - "wasmer-vm-near", - "winapi", -] - -[[package]] -name = "wasmer-runtime-core-near" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af9c54899b847f8bab6d47295487c9827f14cc411bd70b168e87a4ea017ccd7e" -dependencies = [ - "bincode", - "blake3", - "borsh", - "cc", - "digest 0.8.1", - "errno 0.2.8", - "hex", - "indexmap 2.8.0", - "lazy_static", - "libc", - "nix 0.15.0", - "page_size", - "parking_lot 0.10.2", - "rustc_version 0.2.3", - "serde", - "serde-bench", - "serde_bytes", - "serde_derive", - "smallvec", - "target-lexicon 0.10.0", - "wasmparser 0.51.4", - "winapi", -] - -[[package]] -name = "wasmer-runtime-near" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "158e6fff11e5e1ef805af50637374d5bd43d92017beafa18992cdf7f3f7ae3e4" -dependencies = [ - "lazy_static", - "memmap", - "serde", - "serde_derive", - "wasmer-runtime-core-near", - "wasmer-singlepass-backend-near", -] - -[[package]] -name = "wasmer-singlepass-backend-near" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9358673d39c3b4a15374fba0536bfe5e50485e7c826de50d2dbef8c96df07674" -dependencies = [ - "bincode", - "borsh", - "byteorder", - "dynasm 1.2.3", - "dynasmrt 1.2.3", - "lazy_static", - "libc", - "nix 0.15.0", - "serde", - "serde_derive", - "smallvec", - "wasmer-runtime-core-near", -] - -[[package]] -name = "wasmer-types-near" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba154adffb0fbd33f5dabd3788a1744d846b43e6e090d44269c7ee8fa5743e4" -dependencies = [ - "indexmap 1.9.3", - "rkyv 0.7.45", - "thiserror 1.0.69", -] - -[[package]] -name = "wasmer-vm-near" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a5585596f6e9915d606de944aece51626736fb1191aefb5b2ef108c6f7604a" -dependencies = [ - "backtrace", - "cc", - "cfg-if 1.0.0", - "indexmap 1.9.3", - "libc", - "memoffset 0.6.5", - "more-asserts", - "region", - "rkyv 0.7.45", - "thiserror 1.0.69", - "wasmer-types-near", - "winapi", -] - -[[package]] -name = "wasmparser" -version = "0.51.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeb1956b19469d1c5e63e459d29e7b5aa0f558d9f16fcef09736f8a265e6c10a" - [[package]] name = "wasmparser" version = "0.78.2" @@ -9571,10 +9138,10 @@ version = "0.224.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04f17a5917c2ddd3819e84c661fae0d6ba29d7b9c1f0e96c708c65a9c4188e11" dependencies = [ - "bitflags 2.9.0", - "hashbrown 0.15.2", - "indexmap 2.8.0", - "semver 1.0.26", + "bitflags 2.9.2", + "hashbrown 0.15.5", + "indexmap 2.10.0", + "semver", "serde", ] @@ -9607,12 +9174,12 @@ checksum = "809cc8780708f1deed0a7c3fcab46954f0e8c08a6fe0252772481fbc88fcf946" dependencies = [ "addr2line", "anyhow", - "bitflags 2.9.0", + "bitflags 2.9.2", "bumpalo", "cc", - "cfg-if 1.0.0", - "hashbrown 0.15.2", - "indexmap 2.8.0", + "cfg-if", + "hashbrown 0.15.5", + "indexmap 2.10.0", "libc", "log", "mach2", @@ -9647,7 +9214,7 @@ version = "30.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "236964b6b35af0f08879c9c56dbfbc5adc12e8d624672341a0121df31adaa3fa" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -9657,7 +9224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abcc9179097235c91f299a8ff56b358ee921266b61adff7d14d6e48428954dd2" dependencies = [ "anyhow", - "cfg-if 1.0.0", + "cfg-if", "cranelift-codegen", "cranelift-control", "cranelift-entity", @@ -9686,7 +9253,7 @@ dependencies = [ "cranelift-bitset", "cranelift-entity", "gimli", - "indexmap 2.8.0", + "indexmap 2.10.0", "log", "object", "postcard", @@ -9707,7 +9274,7 @@ checksum = "ba5c2ac21f0b39d72d2dac198218a12b3ddeb4ab388a8fa0d2e429855876783c" dependencies = [ "anyhow", "cc", - "cfg-if 1.0.0", + "cfg-if", "rustix 0.38.44", "wasmtime-asm-macros", "wasmtime-versioned-export-macros", @@ -9721,7 +9288,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f180cc0d2745e3a5df5d02231cd3046f49c75512eaa987b8202363b112e125d" dependencies = [ "anyhow", - "cfg-if 1.0.0", + "cfg-if", "libc", "windows-sys 0.59.0", ] @@ -9749,7 +9316,7 @@ checksum = "dd2fe69d04986a12fc759d2e79494100d600adcb3bb79e63dedfc8e6bb2ab03e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -9778,33 +9345,33 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.0", + "webpki-roots 1.0.2", ] [[package]] name = "webpki-roots" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" dependencies = [ "rustls-pki-types", ] [[package]] name = "webrtc-util" -version = "0.7.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f1db1727772c05cf7a2cfece52c3aca8045ca1e176cd517d323489aa3c6d87" +checksum = "1438a8fd0d69c5775afb4a71470af92242dbd04059c61895163aa3c1ef933375" dependencies = [ "async-trait", "bitflags 1.3.2", "bytes", - "cc", "ipnet", "lazy_static", "libc", "log", - "nix 0.24.3", + "nix", + "portable-atomic", "rand 0.8.5", "thiserror 1.0.69", "tokio", @@ -9825,11 +9392,11 @@ dependencies = [ [[package]] name = "whoami" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" dependencies = [ - "redox_syscall 0.5.10", + "libredox", "wasite", ] @@ -9872,44 +9439,70 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.52.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-targets 0.52.6", + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", ] [[package]] name = "windows-link" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-registry" -version = "0.4.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ + "windows-link", "windows-result", "windows-strings", - "windows-targets 0.53.0", ] [[package]] name = "windows-result" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] @@ -9941,6 +9534,15 @@ 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.3", +] + [[package]] name = "windows-targets" version = "0.48.5" @@ -9974,10 +9576,11 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.0" +version = "0.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" dependencies = [ + "windows-link", "windows_aarch64_gnullvm 0.53.0", "windows_aarch64_msvc 0.53.0", "windows_i686_gnu 0.53.0", @@ -10128,9 +9731,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.4" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" dependencies = [ "memchr", ] @@ -10141,7 +9744,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "windows-sys 0.48.0", ] @@ -10151,20 +9754,14 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.9.2", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - [[package]] name = "writeable" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" [[package]] name = "wyz" @@ -10177,9 +9774,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.25" +version = "0.8.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b940ebc25896e71dd073bad2dbaa2abfe97b0a391415e22ad1326d9c54e3c4" +checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" [[package]] name = "xmlparser" @@ -10201,7 +9798,19 @@ checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", - "yoke-derive", + "yoke-derive 0.7.5", + "zerofrom", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive 0.8.0", "zerofrom", ] @@ -10213,48 +9822,40 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", "synstructure", ] [[package]] -name = "zerocopy" -version = "0.7.35" +name = "yoke-derive" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" dependencies = [ - "zerocopy-derive 0.7.35", + "proc-macro2", + "quote", + "syn 2.0.106", + "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" -dependencies = [ - "zerocopy-derive 0.8.24", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.35" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", + "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -10274,7 +9875,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", "synstructure", ] @@ -10295,7 +9896,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] @@ -10311,26 +9912,37 @@ dependencies = [ "rustc-hex", ] +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke 0.8.0", + "zerofrom", +] + [[package]] name = "zerovec" -version = "0.10.4" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" dependencies = [ - "yoke", + "yoke 0.8.0", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" -version = "0.10.3" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.100", + "syn 2.0.106", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1f3767f0..0c74bc61 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [workspace.package] -version = "0.3.3" +version = "0.3.4" authors = ["Near Inc "] edition = "2021" -rust-version = "1.85.0" +rust-version = "1.86.0" repository = "https://github.com/near/read-rpc" license = "MIT OR Apache-2.0" @@ -50,19 +50,18 @@ tx-details-storage = { path = "tx-details-storage" } logic-state-indexer = { path = "logic-state-indexer" } # Please, update the supported nearcore version in .cargo/config.toml file -near-async = { git = "https://github.com/near/nearcore", rev = "680b27eb0105655345535a20623aaeb3b49b82e0" } -near-indexer-primitives = { git = "https://github.com/near/nearcore", rev = "680b27eb0105655345535a20623aaeb3b49b82e0" } -near-primitives = { git = "https://github.com/near/nearcore", rev = "680b27eb0105655345535a20623aaeb3b49b82e0" } -near-chain-configs = { git = "https://github.com/near/nearcore", rev = "680b27eb0105655345535a20623aaeb3b49b82e0" } -near-crypto = { git = "https://github.com/near/nearcore", rev = "680b27eb0105655345535a20623aaeb3b49b82e0" } -near-jsonrpc = { git = "https://github.com/near/nearcore", rev = "680b27eb0105655345535a20623aaeb3b49b82e0" } -near-parameters = { git = "https://github.com/near/nearcore", rev = "680b27eb0105655345535a20623aaeb3b49b82e0" } -near-vm-runner = { git = "https://github.com/near/nearcore", rev = "680b27eb0105655345535a20623aaeb3b49b82e0" , features = [ - "wasmer0_vm", - "wasmer2_vm", +near-async = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" } +near-indexer-primitives = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" } +near-primitives = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" } +near-chain-configs = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" } +near-crypto = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" } +near-jsonrpc = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" } +near-parameters = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" } +node-runtime = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" } +near-vm-runner = { git = "https://github.com/kobayurii/nearcore", branch = "fork/2.7.0" , features = [ "wasmtime_vm", "near_vm", ] } -near-jsonrpc-client = { git = 'https://github.com/kobayurii/near-jsonrpc-client-rs.git', branch = 'fork/0.17.1' } -near-lake-framework = { git = 'https://github.com/kobayurii/near-lake-framework-rs.git', branch = 'fork/0.7.17' } +near-jsonrpc-client = { git = 'https://github.com/kobayurii/near-jsonrpc-client-rs.git', branch = 'fork/0.18.0' } +near-lake-framework = { git = 'https://github.com/kobayurii/near-lake-framework-rs.git', branch = 'fork/0.7.20' } diff --git a/README.md b/README.md index d2729432..e09debc9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,40 @@ This workspace holds the collection of components for the Read RPC. +## Branch Information + +- **main** - Latest released version, stable and production-ready +- **develop** - Development branch containing the latest changes and features under development + +## NEAR Dependencies + +This project relies heavily on NEAR ecosystem crates and uses dependencies directly from Git repositories rather than published crates from crates.io. This approach is necessary because: + +1. **Unpublished Crates**: NEAR doesn't publish all the necessary crates required for Read RPC functionality to public registries +2. **Version Compatibility**: We need specific versions or features that may not be available in published releases +3. **Custom Modifications**: Some dependencies require modifications to work optimally with Read RPC + +### Forked Dependencies + +- **`near-jsonrpc-client`** - Provides JSON RPC client functionality for communicating with NEAR nodes +- **`near-lake-framework`** - Essential for indexing blockchain data from NEAR Lake (AWS S3 data buckets) + +### Fork Maintenance + +These dependencies are maintained as forks to: +- Ensure compatibility with Read RPC's specific requirements +- Include necessary modifications and patches +- Control the update cycle and maintain stability +- Add features or fixes that haven't been merged upstream yet + +### Dependency Management + +When updating NEAR dependencies: +1. Check for upstream changes in the original repositories +2. Test compatibility with existing Read RPC functionality +3. Update fork references in `Cargo.toml` files +4. Ensure all components still build and function correctly + ## Current content ### [rpc-server](rpc-server/README.md) @@ -27,6 +61,46 @@ The indexer built on top of Lake Framework that watches the network and stores t The configuration module is responsible for managing the configuration settings of the NEAR ReadRPC project. +### [database](database/README.md) + +The database module provides database abstractions and implementations for storing and retrieving data. + +### [cache-storage](cache-storage/README.md) + +The cache storage module provides caching functionality for improved performance. + +### [tx-details-storage](tx-details-storage/README.md) + +The transaction details storage module handles storage of detailed transaction information. + +### [logic-state-indexer](logic-state-indexer/README.md) + +The logic state indexer module provides state indexing functionality. + +### [readnode-primitives](readnode-primitives/README.md) + +The readnode primitives module contains common data structures and utilities. + +### [perf-testing](perf-testing/README.md) + +The performance testing module provides tools for testing and benchmarking. + +## Documentation + +### Project Documentation +- [CHANGELOG.md](CHANGELOG.md) - Project changelog and version history +- [Examples](examples/README.md) - Usage examples and sample configurations + +### Technical Documentation +- [RPC Methods](docs/RPC_METHODS.md) - Available RPC methods and their specifications +- [Custom RPC Methods](docs/CUSTOM_RPC_METHODS.md) - Custom RPC methods specific to Read RPC +- [Database Migrations](docs/DATABASE_MIGRATIONS.md) - Database migration procedures and guidelines +- [Tracing](docs/TRACING.md) - Distributed tracing setup and configuration + +### Database Documentation +- [PostgreSQL Setup](database/src/postgres/README.md) - PostgreSQL-specific configuration and setup +- [Database Migrations](docs/DATABASE_MIGRATIONS.md) - Database migration procedures and guidelines + ## Docker compose **Note!** The docker compose is not fully ready yet. It's still in progress. However, you can run the entire project to play around with it. It is still not convenient for development or debugging purposes. We are working on improving it. diff --git a/configuration/src/configs/database.rs b/configuration/src/configs/database.rs index 815bc76d..5034484f 100644 --- a/configuration/src/configs/database.rs +++ b/configuration/src/configs/database.rs @@ -22,9 +22,6 @@ pub struct DatabaseConfig { pub shards_config: std::collections::HashMap, pub max_connections: u32, - // Migrations cannot be applied to read-only replicas - // We should run rpc-server only on read-only replicas - pub read_only: bool, pub shard_layout: Option, } @@ -34,7 +31,6 @@ impl DatabaseConfig { database_url: self.database_url.clone(), shards_config: self.shards_config.clone(), max_connections: self.max_connections, - read_only: true, shard_layout: self.shard_layout.clone(), } } @@ -77,7 +73,6 @@ impl From for DatabaseConfig { max_connections: database_config .max_connections .unwrap_or_else(CommonDatabaseConfig::default_max_connections), - read_only: false, shard_layout: crate::shard_layout().ok(), } } diff --git a/configuration/src/configs/general.rs b/configuration/src/configs/general.rs index a603f9f9..836badf9 100644 --- a/configuration/src/configs/general.rs +++ b/configuration/src/configs/general.rs @@ -29,6 +29,7 @@ pub struct GeneralTxIndexerConfig { pub redis_url: url::Url, pub indexer_id: String, pub metrics_server_port: u16, + pub tx_details_storage_provider: StorageProvider, } #[derive(Debug, Clone)] @@ -67,6 +68,8 @@ pub struct CommonGeneralConfig { pub tx_indexer: CommonGeneralTxIndexerConfig, #[serde(default)] pub state_indexer: CommonGeneralStateIndexerConfig, + #[serde(default)] + pub tx_details_storage_provider: StorageProvider, } #[derive(Deserialize, PartialEq, Debug, Clone, Default)] @@ -93,6 +96,30 @@ impl FromStr for ChainId { } } +/// Represents the storage provider for some parts of the project. +/// Initially created to be able to switch between ScyllaDB and Postgres for transaction details storage. +/// Default is Postgres to simplify the initial setup for a new node operator. +/// It is not recommended to use Postgres transaction details storage for an archival node. +#[derive(Deserialize, PartialEq, Debug, Clone, Default)] +#[serde(rename_all = "lowercase")] +pub enum StorageProvider { + #[default] + Postgres, + ScyllaDb, +} + +impl FromStr for StorageProvider { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + match s { + "postgres" => Ok(StorageProvider::Postgres), + "scylladb" => Ok(StorageProvider::ScyllaDb), + _ => Err(anyhow::anyhow!("Invalid storage provider")), + } + } +} + #[derive(Validate, Deserialize, Debug, Clone)] pub struct CommonGeneralRpcServerConfig { #[serde(deserialize_with = "deserialize_optional_data_or_env", default)] @@ -167,6 +194,8 @@ pub struct CommonGeneralTxIndexerConfig { pub indexer_id: Option, #[serde(deserialize_with = "deserialize_optional_data_or_env", default)] pub metrics_server_port: Option, + #[serde(deserialize_with = "deserialize_optional_data_or_env", default)] + pub tx_details_storage_provider: Option, } impl CommonGeneralTxIndexerConfig { @@ -184,6 +213,7 @@ impl Default for CommonGeneralTxIndexerConfig { Self { indexer_id: Some(Self::default_indexer_id()), metrics_server_port: Some(Self::default_metrics_server_port()), + tx_details_storage_provider: Some(StorageProvider::Postgres), } } } @@ -283,6 +313,7 @@ impl From for GeneralTxIndexerConfig { .tx_indexer .metrics_server_port .unwrap_or_else(CommonGeneralTxIndexerConfig::default_metrics_server_port), + tx_details_storage_provider: common_config.tx_details_storage_provider, } } } diff --git a/configuration/src/configs/lake.rs b/configuration/src/configs/lake.rs index fb5f0b4e..63f15432 100644 --- a/configuration/src/configs/lake.rs +++ b/configuration/src/configs/lake.rs @@ -23,6 +23,7 @@ impl LakeConfig { if let Some(num_threads) = self.num_threads { config_builder = config_builder.num_threads(num_threads); }; + config_builder = config_builder.authorization_token(self.lake_auth_token.clone()); Ok(config_builder .start_block_height(start_block_height) .build()?) diff --git a/configuration/src/configs/mod.rs b/configuration/src/configs/mod.rs index 0467efe2..299fd499 100644 --- a/configuration/src/configs/mod.rs +++ b/configuration/src/configs/mod.rs @@ -120,11 +120,13 @@ pub struct RpcServerConfig { pub lake_config: lake::LakeConfig, pub database: database::DatabaseConfig, pub tx_details_storage: tx_details_storage::TxDetailsStorageConfig, + pub tx_details_storage_provider: general::StorageProvider, } impl Config for RpcServerConfig { fn from_common_config(common_config: CommonConfig) -> Self { Self { + tx_details_storage_provider: common_config.general.tx_details_storage_provider.clone(), general: common_config.general.into(), lake_config: common_config.lake_config.into(), database: database::DatabaseConfig::from(common_config.database).to_read_only(), @@ -142,6 +144,7 @@ pub struct TxIndexerConfig { pub lake_config: lake::LakeConfig, pub database: database::DatabaseConfig, pub tx_details_storage: tx_details_storage::TxDetailsStorageConfig, + pub tx_details_storage_provider: general::StorageProvider, } impl TxIndexerConfig { @@ -156,6 +159,7 @@ impl TxIndexerConfig { impl Config for TxIndexerConfig { fn from_common_config(common_config: CommonConfig) -> Self { Self { + tx_details_storage_provider: common_config.general.tx_details_storage_provider.clone(), general: common_config.general.into(), rightsizing: common_config.rightsizing.into(), lake_config: common_config.lake_config.into(), diff --git a/configuration/src/configs/tx_details_storage.rs b/configuration/src/configs/tx_details_storage.rs index cb6e31d3..64429578 100644 --- a/configuration/src/configs/tx_details_storage.rs +++ b/configuration/src/configs/tx_details_storage.rs @@ -1,10 +1,10 @@ use serde_derive::Deserialize; -use crate::configs::{deserialize_optional_data_or_env, required_value_or_panic}; +use crate::configs::deserialize_optional_data_or_env; #[derive(Debug, Clone)] pub struct TxDetailsStorageConfig { - pub scylla_url: String, + pub scylla_url: Option, pub scylla_user: Option, pub scylla_password: Option, pub scylla_preferred_dc: Option, @@ -26,7 +26,14 @@ impl TxDetailsStorageConfig { Ok(builder.build()) } - pub async fn scylla_client(&self) -> scylla::Session { + pub async fn scylla_client(&self) -> Option { + let scylla_url = match &self.scylla_url { + Some(url) => url.clone(), + None => { + panic!("Scylla URL is not set but scylla_client() was called. This method should only be used when Scylla is configured."); + } + }; + let mut load_balancing_policy_builder = scylla::transport::load_balancing::DefaultPolicy::builder(); @@ -39,14 +46,10 @@ impl TxDetailsStorageConfig { .load_balancing_policy(load_balancing_policy_builder.build()) .build() .into_handle(); - let ssl_context = if let Ok(ssl_context) = self.create_ssl_context().await { - Some(ssl_context) - } else { - None - }; + let ssl_context = (self.create_ssl_context().await).ok(); let mut session: scylla::SessionBuilder = scylla::SessionBuilder::new() - .known_node(self.scylla_url.clone()) + .known_node(scylla_url.clone()) .keepalive_interval(std::time::Duration::from_secs( self.scylla_keepalive_interval, )) @@ -58,10 +61,12 @@ impl TxDetailsStorageConfig { session = session.user(user, password); } } - session - .build() - .await - .expect("Failed to create scylla session") + Some( + session + .build() + .await + .expect("Failed to create scylla session"), + ) } } @@ -88,7 +93,7 @@ impl CommonTxDetailStorageConfig { impl From for TxDetailsStorageConfig { fn from(common_config: CommonTxDetailStorageConfig) -> Self { Self { - scylla_url: required_value_or_panic("scylla_url", common_config.scylla_url), + scylla_url: common_config.scylla_url, scylla_user: common_config.scylla_user, scylla_password: common_config.scylla_password, scylla_preferred_dc: common_config.scylla_preferred_dc, diff --git a/configuration/src/default_env_configs.rs b/configuration/src/default_env_configs.rs index 7788a905..8e514515 100644 --- a/configuration/src/default_env_configs.rs +++ b/configuration/src/default_env_configs.rs @@ -78,6 +78,11 @@ indexer_id = "${TX_INDEXER_ID}" ## By default it 8080 for tx-indexer and 8081 for state-indexer metrics_server_port = "${TX_SERVER_PORT}" +## Transaction details storage provider +## Options: "scylla", "postgres" +## Default value is "postgres" +#tx_details_storage_provider = "${TX_DETAILS_STORAGE_PROVIDER}" + ### State indexer general configuration [general.state_indexer] diff --git a/configuration/src/lib.rs b/configuration/src/lib.rs index e121ac81..ba238a92 100644 --- a/configuration/src/lib.rs +++ b/configuration/src/lib.rs @@ -10,6 +10,7 @@ mod default_env_configs; pub use crate::configs::database::DatabaseConfig; pub use crate::configs::general::ChainId; +pub use crate::configs::general::StorageProvider; pub use crate::configs::{ IndexerConfig, RightsizingConfig, RpcServerConfig, StateIndexerConfig, TxIndexerConfig, }; @@ -168,12 +169,15 @@ fn find_configs_root() -> anyhow::Result { // Helper function to get shard layout for the `SHARD_LAYOUT_PROTOCOL_VERSION` protocol version pub fn shard_layout() -> anyhow::Result { let genesis_config = read_genesis_config_from_root()?; - let default_epoch_config = near_primitives::epoch_manager::EpochConfig::from(&genesis_config); - let all_epoch_config = near_primitives::epoch_manager::AllEpochConfig::new( - true, - genesis_config.protocol_version, - default_epoch_config, + let epoch_config_store = near_primitives::epoch_manager::EpochConfigStore::for_chain_id( &genesis_config.chain_id, + None, + ) + .expect("Failed to create epoch config store"); + let all_epoch_config = near_primitives::epoch_manager::AllEpochConfig::from_epoch_config_store( + &genesis_config.chain_id, + genesis_config.epoch_length, + epoch_config_store, ); let epoch_config = all_epoch_config.for_protocol_version(SHARD_LAYOUT_PROTOCOL_VERSION); Ok(epoch_config.shard_layout) diff --git a/database/Cargo.toml b/database/Cargo.toml index 5e88c08b..7681960c 100644 --- a/database/Cargo.toml +++ b/database/Cargo.toml @@ -23,7 +23,18 @@ sqlx = { version = "0.8.2", features = [ "runtime-tokio-native-tls", "postgres", "migrate", - "bigdecimal"] } + "bigdecimal", +] } +num-bigint = "0.3.3" +num-traits = "0.2.19" +scylla = { version = "0.15.1", features = ["ssl", "full-serialization"] } +tokio = { version = "1.36.0", features = [ + "sync", + "time", + "macros", + "rt-multi-thread", +] } +tracing = "0.1.34" configuration.workspace = true readnode-primitives.workspace = true diff --git a/database/README.md b/database/README.md index c06a0834..f4a6ac08 100644 --- a/database/README.md +++ b/database/README.md @@ -3,3 +3,15 @@ This is a helper crate that provides db manager. ## [Postgres DB](src/postgres/README.md) + +## [Database Migrations with SQLx](../docs/DATABASE_MIGRATIONS.md) + +Comprehensive guide for managing database migrations using SQLx CLI. This covers: +- Setting up and applying migrations for all database types (meta, shard, transaction details) +- Creating new migrations +- Migration best practices and troubleshooting +- Automated migration scripts + +## [Legacy Database Migration Scripts](database_migrations/README.md) + +Scripts for migrating data from existing databases (only needed for upgrading existing deployments). diff --git a/database/database_migrations/README.md b/database/database_migrations/README.md new file mode 100644 index 00000000..4a63b363 --- /dev/null +++ b/database/database_migrations/README.md @@ -0,0 +1,100 @@ +> **Note:** If you are starting the project from scratch (with a new, empty database), you do not need to run the migration scripts in this directory. These scripts are only necessary when migrating data from an existing database or upgrading shards. For new deployments, follow the standard database initialization procedures instead. + +Database Migration Scripts + +This directory contains scripts for migrating database shards and related data. + +## Shard Migration Script + +The `shard_migration.sh` script is the main migration orchestrator that runs multiple migration scripts in parallel. + +### Usage + +The script accepts the following command-line arguments: + +- `--db_name`: Database name +- `--db_user`: Database username +- `--db_password`: Database password +- `--host`: Database host +- `--port`: Database port + +### Examples + +#### Basic Example: +```bash +./shard_migration.sh --db_name my_database --db_user postgres --db_password mypassword --host localhost --port 5432 +``` + +#### Local PostgreSQL Database: +```bash +./shard_migration.sh \ + --db_name read_rpc_db \ + --db_user postgres \ + --db_password secretpassword \ + --host localhost \ + --port 5432 +``` + +#### Remote Database: +```bash +./shard_migration.sh \ + --db_name production_db \ + --db_user readrpc_user \ + --db_password prod_password123 \ + --host db.example.com \ + --port 5432 +``` + +#### Using Environment Variables: +```bash +# Set environment variables first +export DB_NAME="my_database" +export DB_USER="postgres" +export PGPASSWORD="mypassword" +export DB_HOST="localhost" +export DB_PORT="5432" + +# Then run the script (it will use the environment variables) +./shard_migration.sh +``` + +### Prerequisites + +1. **Make the script executable:** + ```bash + chmod +x shard_migration.sh + ``` + +2. **Make all migration scripts executable:** + ```bash + chmod +x migrate_*.sh + ``` + +3. **Ensure all required migration scripts exist:** + - `migrate_access_keys.sh` + - `migrate_accounts.sh` + - `migrate_contracts.sh` + - `migrate_state_changes.sh` + +### How it Works + +The `shard_migration.sh` script: + +1. Parses command-line arguments and sets environment variables +2. Creates a log file named `migration_${DB_NAME}.log` +3. Runs four migration scripts in parallel using the `&` operator +4. Waits for all migrations to complete using the `wait` command +5. Logs start and completion times + +### Output + +- Migration progress and results are logged to `migration_${DB_NAME}.log` +- Console output shows start and completion timestamps +- Each individual migration script may produce its own output + +### Notes + +- All arguments are required for the script to function properly +- The script runs migrations in parallel to improve performance +- Make sure you have proper database permissions before running the migration +- Review the individual migration scripts to understand what data will be migrated diff --git a/database/database_migrations/migrate_access_keys.sh b/database/database_migrations/migrate_access_keys.sh new file mode 100644 index 00000000..e0312fa4 --- /dev/null +++ b/database/database_migrations/migrate_access_keys.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# Function to migrate a single partition +migrate_partition() { + local partition=$1 + # shellcheck disable=SC2155 + local start_time=$(date +"%T") + + echo "[INFO] Starting migration for partition state_changes_access_key_$partition at $start_time" + echo "[INFO] Starting migration for partition state_changes_access_key_$partition at $start_time" >> "$LOG_FILE" + + psql -U "$DB_USER" -d "$DB_NAME" -h "$DB_HOST" -p "$DB_PORT" -c " + WITH ordered_data AS ( + SELECT + account_id, + data_key, + data_value, + block_height AS block_height_from, + LAG(block_height) OVER (PARTITION BY account_id, data_key ORDER BY block_height DESC) AS block_height_to + FROM state_changes_access_key_$partition + ) + INSERT INTO state_changes_access_key_compact_$partition (account_id, data_key, data_value, block_height_from, block_height_to) + SELECT + account_id, + data_key, + data_value, + block_height_from::bigint, + block_height_to::bigint + FROM ordered_data + WHERE data_value IS NOT NULL + ON CONFLICT (account_id, data_key, block_height_from) DO NOTHING; + " 2>&1 | tee -a "$LOG_FILE" + + # shellcheck disable=SC2155 + local end_time=$(date +"%T") + echo "[INFO] Finished migration for partition state_changes_access_key_$partition at $end_time" + echo "[INFO] Finished migration for partition state_changes_access_key_$partition at $end_time" >> "$LOG_FILE" +} + +# Run migrations in parallel for partitions 0 to 99 +for i in $(seq 0 99); do + migrate_partition "$i" & +done + +# Wait for all background jobs to finish +wait diff --git a/database/database_migrations/migrate_accounts.sh b/database/database_migrations/migrate_accounts.sh new file mode 100644 index 00000000..74da3785 --- /dev/null +++ b/database/database_migrations/migrate_accounts.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Function to migrate a single partition +migrate_partition() { + local partition=$1 + # shellcheck disable=SC2155 + local start_time=$(date +"%T") + + echo "[INFO] Starting migration for partition state_changes_account_$partition at $start_time" + echo "[INFO] Starting migration for partition state_changes_account_$partition at $start_time" >> "$LOG_FILE" + + psql -U "$DB_USER" -d "$DB_NAME" -h "$DB_HOST" -p "$DB_PORT" -c " + WITH ordered_data AS ( + SELECT + account_id, + data_value, + block_height AS block_height_from, + LAG(block_height) OVER (PARTITION BY account_id ORDER BY block_height DESC) AS block_height_to + FROM state_changes_account_$partition + ) + INSERT INTO state_changes_account_compact_$partition (account_id, data_value, block_height_from, block_height_to) + SELECT + account_id, + data_value, + block_height_from::bigint, + block_height_to::bigint + FROM ordered_data + WHERE data_value IS NOT NULL + ON CONFLICT (account_id, block_height_from) DO NOTHING; + " 2>&1 | tee -a "$LOG_FILE" + + # shellcheck disable=SC2155 + local end_time=$(date +"%T") + echo "[INFO] Finished migration for partition state_changes_account_$partition at $end_time" + echo "[INFO] Finished migration for partition state_changes_account_$partition at $end_time" >> "$LOG_FILE" +} + +# Run migrations in parallel for partitions 0 to 99 +for i in $(seq 0 99); do + migrate_partition "$i" & +done + +# Wait for all background jobs to finish +wait diff --git a/database/database_migrations/migrate_contracts.sh b/database/database_migrations/migrate_contracts.sh new file mode 100644 index 00000000..be04e782 --- /dev/null +++ b/database/database_migrations/migrate_contracts.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Function to migrate a single partition +migrate_partition() { + local partition=$1 + # shellcheck disable=SC2155 + local start_time=$(date +"%T") + + echo "[INFO] Starting migration for partition state_changes_contract_$partition at $start_time" + echo "[INFO] Starting migration for partition state_changes_contract_$partition at $start_time" >> "$LOG_FILE" + + psql -U "$DB_USER" -d "$DB_NAME" -h "$DB_HOST" -p "$DB_PORT" -c " + WITH ordered_data AS ( + SELECT + account_id, + data_value, + block_height AS block_height_from, + LAG(block_height) OVER (PARTITION BY account_id ORDER BY block_height DESC) AS block_height_to + FROM state_changes_contract_$partition + ) + INSERT INTO state_changes_contract_compact_$partition (account_id, data_value, block_height_from, block_height_to) + SELECT + account_id, + data_value, + block_height_from::bigint, + block_height_to::bigint + FROM ordered_data + WHERE data_value IS NOT NULL + ON CONFLICT (account_id, block_height_from) DO NOTHING; + " 2>&1 | tee -a "$LOG_FILE" + + # shellcheck disable=SC2155 + local end_time=$(date +"%T") + echo "[INFO] Finished migration for partition state_changes_contract_$partition at $end_time" + echo "[INFO] Finished migration for partition state_changes_contract_$partition at $end_time" >> "$LOG_FILE" +} + +# Run migrations in parallel for partitions 0 to 99 +for i in $(seq 0 99); do + migrate_partition "$i" & +done + +# Wait for all background jobs to finish +wait diff --git a/database/database_migrations/migrate_state_changes.sh b/database/database_migrations/migrate_state_changes.sh new file mode 100644 index 00000000..0129d143 --- /dev/null +++ b/database/database_migrations/migrate_state_changes.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# Function to migrate a single partition +migrate_partition() { + local partition=$1 + # shellcheck disable=SC2155 + local start_time=$(date +"%T") + + echo "[INFO] Starting migration for partition state_changes_data_$partition at $start_time" + echo "[INFO] Starting migration for partition state_changes_data_$partition at $start_time" >> "$LOG_FILE" + + psql -U "$DB_USER" -d "$DB_NAME" -h "$DB_HOST" -p "$DB_PORT" -c " + WITH ordered_data AS ( + SELECT + account_id, + data_key, + data_value, + block_height AS block_height_from, + LAG(block_height) OVER (PARTITION BY account_id, data_key ORDER BY block_height DESC) AS block_height_to + FROM state_changes_data_$partition + ) + INSERT INTO state_changes_data_compact_$partition (account_id, data_key, data_value, block_height_from, block_height_to) + SELECT + account_id, + data_key, + data_value, + block_height_from::bigint, + block_height_to::bigint + FROM ordered_data + WHERE data_value IS NOT NULL + ON CONFLICT (account_id, data_key, block_height_from) DO NOTHING; + " 2>&1 | tee -a "$LOG_FILE" + + # shellcheck disable=SC2155 + local end_time=$(date +"%T") + echo "[INFO] Finished migration for partition state_changes_data_$partition at $end_time" + echo "[INFO] Finished migration for partition state_changes_data_$partition at $end_time" >> "$LOG_FILE" +} + +# Run migrations in parallel for partitions 0 to 99 +for i in $(seq 0 99); do + migrate_partition "$i" & +done + +# Wait for all background jobs to finish +wait diff --git a/database/database_migrations/shard_migration.sh b/database/database_migrations/shard_migration.sh new file mode 100644 index 00000000..1ca0a17b --- /dev/null +++ b/database/database_migrations/shard_migration.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +# Parse arguments or use environment variables +while [[ $# -gt 0 ]]; do + key="$1" + case $key in + --db_name) + export DB_NAME="$2" + shift 2 + ;; + --db_user) + export DB_USER="$2" + shift 2 + ;; + --db_password) + export PGPASSWORD="$2" + shift 2 + ;; + --host) + export DB_HOST="$2" + shift 2 + ;; + --port) + export DB_PORT="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +# Set defaults from environment if not set by args +: "${DB_NAME:=${DB_NAME}}" +: "${DB_USER:=${DB_USER}}" +: "${PGPASSWORD:=${PGPASSWORD}}" +: "${DB_HOST:=${DB_HOST}}" +: "${DB_PORT:=${DB_PORT}}" + +# Check required variables +if [[ -z "$DB_NAME" || -z "$DB_USER" || -z "$PGPASSWORD" || -z "$DB_HOST" || -z "$DB_PORT" ]]; then + echo "All arguments are required: --db_name, --db_user, --db_password, --host, --port (or set corresponding env vars)" + exit 1 +fi + + +# Set log file +export LOG_FILE="migration_${DB_NAME}.log" +# Remove old log file if it exists +rm -f "$LOG_FILE" +touch "$LOG_FILE" + +echo "Starting migration at $(date)" | tee -a "$LOG_FILE" + +./migrate_access_keys.sh & +./migrate_accounts.sh & +./migrate_contracts.sh & +./migrate_state_changes.sh & + +wait + +echo "Migration completed at $(date)" | tee -a "$LOG_FILE" diff --git a/database/src/base/mod.rs b/database/src/base/mod.rs index f29232ed..f7a98524 100644 --- a/database/src/base/mod.rs +++ b/database/src/base/mod.rs @@ -1,7 +1,10 @@ -mod rpc_server; pub use crate::base::rpc_server::ReaderDbManager; -pub mod state_indexer; pub use crate::base::state_indexer::StateIndexerDbManager; +pub use crate::base::tx_indexer::TxIndexerDbManager; + +mod rpc_server; +pub mod state_indexer; +pub mod tx_indexer; pub type PageToken = Option; diff --git a/database/src/base/rpc_server.rs b/database/src/base/rpc_server.rs index 18990a92..12ffc06a 100644 --- a/database/src/base/rpc_server.rs +++ b/database/src/base/rpc_server.rs @@ -130,4 +130,10 @@ pub trait ReaderDbManager { block_height: near_primitives::types::BlockHeight, method_name: &str, ) -> anyhow::Result; + + /// Converts an account ID to a shard ID + fn get_shard_id_by_account_id( + &self, + account_id: &near_primitives::types::AccountId, + ) -> near_primitives::types::ShardId; } diff --git a/database/src/base/state_indexer.rs b/database/src/base/state_indexer.rs index 73048fc7..85ab5b37 100644 --- a/database/src/base/state_indexer.rs +++ b/database/src/base/state_indexer.rs @@ -59,7 +59,26 @@ pub trait StateIndexerDbManager { shard_id: near_primitives::types::ShardId, state_changes: Vec, block_height: u64, - block_hash: near_primitives::hash::CryptoHash, + ) -> anyhow::Result<()> { + self.update_state_changes_data(shard_id, state_changes.clone(), block_height) + .await?; + self.insert_state_changes_data(shard_id, state_changes, block_height) + .await?; + Ok(()) + } + + async fn insert_state_changes_data( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()>; + + async fn update_state_changes_data( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, ) -> anyhow::Result<()>; async fn save_state_changes_access_key( @@ -67,7 +86,26 @@ pub trait StateIndexerDbManager { shard_id: near_primitives::types::ShardId, state_changes: Vec, block_height: u64, - block_hash: near_primitives::hash::CryptoHash, + ) -> anyhow::Result<()> { + self.update_state_changes_access_key(shard_id, state_changes.clone(), block_height) + .await?; + self.insert_state_changes_access_key(shard_id, state_changes, block_height) + .await?; + Ok(()) + } + + async fn insert_state_changes_access_key( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()>; + + async fn update_state_changes_access_key( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, ) -> anyhow::Result<()>; async fn save_state_changes_contract( @@ -75,7 +113,26 @@ pub trait StateIndexerDbManager { shard_id: near_primitives::types::ShardId, state_changes: Vec, block_height: u64, - block_hash: near_primitives::hash::CryptoHash, + ) -> anyhow::Result<()> { + self.update_state_changes_contract(shard_id, state_changes.clone(), block_height) + .await?; + self.insert_state_changes_contract(shard_id, state_changes, block_height) + .await?; + Ok(()) + } + + async fn insert_state_changes_contract( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()>; + + async fn update_state_changes_contract( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, ) -> anyhow::Result<()>; async fn save_state_changes_account( @@ -83,6 +140,25 @@ pub trait StateIndexerDbManager { shard_id: near_primitives::types::ShardId, state_changes: Vec, block_height: u64, - block_hash: near_primitives::hash::CryptoHash, + ) -> anyhow::Result<()> { + self.update_state_changes_account(shard_id, state_changes.clone(), block_height) + .await?; + self.insert_state_changes_account(shard_id, state_changes, block_height) + .await?; + Ok(()) + } + + async fn insert_state_changes_account( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()>; + + async fn update_state_changes_account( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, ) -> anyhow::Result<()>; } diff --git a/database/src/base/tx_indexer.rs b/database/src/base/tx_indexer.rs new file mode 100644 index 00000000..d60f7347 --- /dev/null +++ b/database/src/base/tx_indexer.rs @@ -0,0 +1,44 @@ +use anyhow::Result; + +#[async_trait::async_trait] +pub trait TxIndexerDbManager { + async fn create_tx_tables(&self) -> Result<()>; + + async fn save_transaction( + &self, + sender_id: &near_primitives::types::AccountId, + key: &str, + data: Vec, + block_height: u64, + ) -> Result<()>; + + async fn retrieve_transaction( + &self, + key: &str, + shard_id: &near_primitives::types::ShardId, + ) -> Result>; + + async fn save_receipts(&self, receipts: Vec) -> Result<()>; + + async fn get_receipt_by_id( + &self, + receipt_id: &str, + ) -> Result; + + async fn save_outcomes(&self, outcomes: Vec) -> Result<()>; + + async fn get_outcome_by_id( + &self, + outcome_id: &str, + ) -> Result; + + async fn update_meta(&self, indexer_id: &str, last_processed_block_height: u64) -> Result<()>; + + async fn get_last_processed_block_height(&self, indexer_id: &str) -> Result; + + async fn save_outcomes_and_receipts( + &self, + receipts: Vec, + outcomes: Vec, + ) -> Result<()>; +} diff --git a/database/src/lib.rs b/database/src/lib.rs index c7f3b58a..c037e693 100644 --- a/database/src/lib.rs +++ b/database/src/lib.rs @@ -7,10 +7,12 @@ use crate::base::BaseDbManager; pub use crate::base::PageToken; pub use crate::base::ReaderDbManager; pub use crate::base::StateIndexerDbManager; +pub use crate::base::TxIndexerDbManager; mod metrics; mod postgres; pub mod primitives; +pub mod scylla; pub use crate::postgres::PostgresDBManager; diff --git a/database/src/metrics.rs b/database/src/metrics.rs index 7ba79cb9..8d52a731 100644 --- a/database/src/metrics.rs +++ b/database/src/metrics.rs @@ -38,4 +38,32 @@ lazy_static! { &["method_name", "table_name"] ) .unwrap(); + + pub(crate) static ref SHARD_DATABASE_WRITE_ELAPSED_TIME: IntCounterVec = register_int_counter_vec( + "shard_database_write_elapsed_time", + "Total elapsed time of shard database write query by shard_id, operation_name, time_elapsed", + &["shard_id", "operation_name", "time_elapsed"] + ) + .unwrap(); + + pub(crate) static ref AFFECTED_ACCOUNTS_COUNT: IntCounterVec = register_int_counter_vec( + "affected_accounts_count", + "Total number of affected accounts by shard_id, operation_name and accounts_number", + &["shard_id", "operation_name", "accounts_number"] + ) + .unwrap(); + + pub(crate) static ref PARTITIONS_TOUCHED_COUNT: IntCounterVec = register_int_counter_vec( + "partitions_touched_count", + "Total number of partitions touched by shard_id, operation_name and partitions_number", + &["shard_id", "operation_name", "partitions_number"] + ) + .unwrap(); + + pub(crate) static ref PARTITION_MAP_TIME_ELAPSED: IntCounterVec = register_int_counter_vec( + "partition_map_time_elapsed", + "Total elapsed time of partition map by shard_id and time_elapsed", + &["shard_id", "time_elapsed"] + ) + .unwrap(); } diff --git a/database/src/postgres/README.md b/database/src/postgres/README.md index d583769f..84d4de90 100644 --- a/database/src/postgres/README.md +++ b/database/src/postgres/README.md @@ -42,3 +42,10 @@ SHARD_3_DATABASE_URL=postgres://postgres:password@localhost:5433/near_data SHARD_4_DATABASE_URL=postgres://postgres:password@localhost:5434/near_data SHARD_5_DATABASE_URL=postgres://postgres:password@localhost:5435/near_data ``` + +### Transaction details storage + +When the `tx_details_storage_provider` is set to `postgres`, the `tx-details-storage` library will use the Postgres database to store and retrieve `TransactionDetails`. Only in this case the migrations from `src/postgres/migrations/tx_details` will be applied to the database. This will create: + +* `transactions` tables on each of the shard databases +* `receipts` and `outcomes` tables on the metadata database \ No newline at end of file diff --git a/database/src/postgres/migrations/shard_db/20250218132509_create_state_changes_compact.down.sql b/database/src/postgres/migrations/shard_db/20250218132509_create_state_changes_compact.down.sql new file mode 100644 index 00000000..097c6490 --- /dev/null +++ b/database/src/postgres/migrations/shard_db/20250218132509_create_state_changes_compact.down.sql @@ -0,0 +1,4 @@ +DROP TABLE IF EXISTS state_changes_data_compact CASCADE; +DROP TABLE IF EXISTS state_changes_access_key_compact CASCADE; +DROP TABLE IF EXISTS state_changes_contract_compact CASCADE; +DROP TABLE IF EXISTS state_changes_account_compact CASCADE; diff --git a/database/src/postgres/migrations/shard_db/20250218132509_create_state_changes_compact.up.sql b/database/src/postgres/migrations/shard_db/20250218132509_create_state_changes_compact.up.sql new file mode 100644 index 00000000..6c19baad --- /dev/null +++ b/database/src/postgres/migrations/shard_db/20250218132509_create_state_changes_compact.up.sql @@ -0,0 +1,83 @@ +CREATE TABLE IF NOT EXISTS state_changes_data_compact ( + account_id text NOT NULL, + data_key text NOT NULL, + data_value bytea NOT NULL, + block_height_from bigint NOT NULL, + block_height_to bigint NULL, + PRIMARY KEY (account_id, data_key, block_height_from) +) PARTITION BY HASH (account_id); + +-- Create state_changes_data partitions +DO $$ +DECLARE + i INT; +BEGIN + FOR i IN 0..99 LOOP + EXECUTE format('CREATE TABLE IF NOT EXISTS state_changes_data_compact_%s PARTITION OF state_changes_data_compact FOR VALUES WITH (MODULUS 100, REMAINDER %s)', i, i); + -- Indexes for state_changes_data_compact partitions + EXECUTE format('CREATE INDEX IF NOT EXISTS idx_data_%s_keys ON state_changes_data_compact_%s (account_id, data_key) WHERE block_height_to IS NULL;', i, i); + END LOOP; +END $$; + + +CREATE TABLE IF NOT EXISTS state_changes_access_key_compact ( + account_id text NOT NULL, + data_key text NOT NULL, + data_value bytea NOT NULL, + block_height_from bigint NOT NULL, + block_height_to bigint NULL, + PRIMARY KEY (account_id, data_key, block_height_from) +) PARTITION BY HASH (account_id); + +-- Create state_changes_access_key partitions +DO $$ +DECLARE + i INT; +BEGIN + FOR i IN 0..99 LOOP + EXECUTE format('CREATE TABLE IF NOT EXISTS state_changes_access_key_compact_%s PARTITION OF state_changes_access_key_compact FOR VALUES WITH (MODULUS 100, REMAINDER %s)', i, i); + -- Indexes for state_changes_access_key_compact partitions + EXECUTE format('CREATE INDEX IF NOT EXISTS idx_access_key_%s_keys ON state_changes_access_key_compact_%s (account_id, data_key) WHERE block_height_to IS NULL;', i, i); + END LOOP; +END $$; + + +CREATE TABLE IF NOT EXISTS state_changes_contract_compact ( + account_id text NOT NULL, + data_value bytea NOT NULL, + block_height_from bigint NOT NULL, + block_height_to bigint NULL, + PRIMARY KEY (account_id, block_height_from) +) PARTITION BY HASH (account_id); + +-- Create state_changes_contract partitions +DO $$ +DECLARE + i INT; +BEGIN + FOR i IN 0..99 LOOP + EXECUTE format('CREATE TABLE IF NOT EXISTS state_changes_contract_compact_%s PARTITION OF state_changes_contract_compact FOR VALUES WITH (MODULUS 100, REMAINDER %s)', i, i); + -- Indexes for state_changes_contract_compact partitions + EXECUTE format('CREATE INDEX IF NOT EXISTS idx_contract_%s_acc ON state_changes_contract_compact_%s (account_id) WHERE block_height_to IS NULL;', i, i); + END LOOP; +END $$; + +CREATE TABLE IF NOT EXISTS state_changes_account_compact ( + account_id text NOT NULL, + data_value bytea NULL, + block_height_from bigint NOT NULL, + block_height_to bigint NULL, + PRIMARY KEY (account_id, block_height_from) +) PARTITION BY HASH (account_id); + +-- Create state_changes_account partitions +DO $$ +DECLARE + i INT; +BEGIN + FOR i IN 0..99 LOOP + EXECUTE format('CREATE TABLE IF NOT EXISTS state_changes_account_compact_%s PARTITION OF state_changes_account_compact FOR VALUES WITH (MODULUS 100, REMAINDER %s)', i, i); + -- Indexes for state_changes_account_compact partitions + EXECUTE format('CREATE INDEX IF NOT EXISTS idx_account_%s_acc ON state_changes_account_compact_%s (account_id) WHERE block_height_to IS NULL;', i, i); + END LOOP; +END $$; diff --git a/database/src/postgres/migrations/shard_db/20250218132510_create_get_text_partition_function.down.sql b/database/src/postgres/migrations/shard_db/20250218132510_create_get_text_partition_function.down.sql new file mode 100644 index 00000000..0bb39c5e --- /dev/null +++ b/database/src/postgres/migrations/shard_db/20250218132510_create_get_text_partition_function.down.sql @@ -0,0 +1 @@ +DROP FUNCTION IF EXISTS get_text_partition(TEXT, INT); diff --git a/database/src/postgres/migrations/shard_db/20250218132510_create_get_text_partition_function.up.sql b/database/src/postgres/migrations/shard_db/20250218132510_create_get_text_partition_function.up.sql new file mode 100644 index 00000000..2a0790b5 --- /dev/null +++ b/database/src/postgres/migrations/shard_db/20250218132510_create_get_text_partition_function.up.sql @@ -0,0 +1,16 @@ +CREATE OR REPLACE FUNCTION get_text_partition(value TEXT, partitions INT) +RETURNS INT AS $$ +DECLARE + hash_val numeric; +BEGIN + hash_val := ( + ( + hashtextextended(value, 8816678312871386365)::numeric + + 5305509591434766563 + + 18446744073709551616 + ) % 18446744073709551616 + ); + + RETURN (hash_val % partitions)::int; +END; +$$ LANGUAGE plpgsql IMMUTABLE; diff --git a/database/src/postgres/migrations/tx_details/receipts_and_outcomes/20250528103158_receipts_and_outcomes.down.sql b/database/src/postgres/migrations/tx_details/receipts_and_outcomes/20250528103158_receipts_and_outcomes.down.sql new file mode 100644 index 00000000..f41bb865 --- /dev/null +++ b/database/src/postgres/migrations/tx_details/receipts_and_outcomes/20250528103158_receipts_and_outcomes.down.sql @@ -0,0 +1,3 @@ +-- Add down migration script here +DROP TABLE IF EXISTS receipts; +DROP TABLE IF EXISTS outcomes; \ No newline at end of file diff --git a/database/src/postgres/migrations/tx_details/receipts_and_outcomes/20250528103158_receipts_and_outcomes.up.sql b/database/src/postgres/migrations/tx_details/receipts_and_outcomes/20250528103158_receipts_and_outcomes.up.sql new file mode 100644 index 00000000..1f9acc49 --- /dev/null +++ b/database/src/postgres/migrations/tx_details/receipts_and_outcomes/20250528103158_receipts_and_outcomes.up.sql @@ -0,0 +1,51 @@ +-- Add up migration script here + +-- Create receipts table +CREATE TABLE IF NOT EXISTS receipts ( + receipt_id VARCHAR PRIMARY KEY, + parent_transaction_hash VARCHAR NOT NULL, + receiver_id VARCHAR NOT NULL, + block_height NUMERIC(20,0) NOT NULL, + block_hash VARCHAR NOT NULL, + shard_id BIGINT NOT NULL +) PARTITION BY HASH (receipt_id); + +-- Create receipts partitions +DO $$ +DECLARE + i INT; +BEGIN + FOR i IN 0..99 LOOP + EXECUTE format( + 'CREATE TABLE IF NOT EXISTS receipts_%s PARTITION OF receipts FOR VALUES WITH (MODULUS 100, REMAINDER %s)', i, i + ); + END LOOP; +END $$; + +-- Create outcomes table +CREATE TABLE IF NOT EXISTS outcomes ( + outcome_id VARCHAR PRIMARY KEY, + parent_transaction_hash VARCHAR NOT NULL, + receiver_id VARCHAR NOT NULL, + block_height NUMERIC(20,0) NOT NULL, + block_hash VARCHAR NOT NULL, + shard_id BIGINT NOT NULL +) PARTITION BY HASH (outcome_id); + +-- Create outcomes partitions +DO $$ +DECLARE + i INT; +BEGIN + FOR i IN 0..99 LOOP + EXECUTE format( + 'CREATE TABLE IF NOT EXISTS outcomes_%s PARTITION OF outcomes FOR VALUES WITH (MODULUS 100, REMAINDER %s)', i, i + ); + END LOOP; +END $$; + +-- Create meta table if not exists +CREATE TABLE IF NOT EXISTS meta ( + indexer_id VARCHAR PRIMARY KEY, + last_processed_block_height NUMERIC(20,0) NOT NULL +); \ No newline at end of file diff --git a/database/src/postgres/migrations/tx_details/transactions/20250528103139_transactions.down.sql b/database/src/postgres/migrations/tx_details/transactions/20250528103139_transactions.down.sql new file mode 100644 index 00000000..18c7808c --- /dev/null +++ b/database/src/postgres/migrations/tx_details/transactions/20250528103139_transactions.down.sql @@ -0,0 +1,2 @@ +-- Add down migration script here +DROP TABLE IF EXISTS transactions; \ No newline at end of file diff --git a/database/src/postgres/migrations/tx_details/transactions/20250528103139_transactions.up.sql b/database/src/postgres/migrations/tx_details/transactions/20250528103139_transactions.up.sql new file mode 100644 index 00000000..288a9d2e --- /dev/null +++ b/database/src/postgres/migrations/tx_details/transactions/20250528103139_transactions.up.sql @@ -0,0 +1,22 @@ +-- Add up migration script here + +-- Create transactions table +CREATE TABLE IF NOT EXISTS transactions ( + transaction_hash text NOT NULL, + sender_account_id text NOT NULL, + block_height numeric(20,0) NOT NULL, + transaction_details bytea NOT NULL, + PRIMARY KEY (transaction_hash) + ) PARTITION BY HASH (transaction_hash); + +-- Create transactions partitions +DO $$ +DECLARE + i INT; +BEGIN + FOR i IN 0..99 LOOP + EXECUTE format( + 'CREATE TABLE IF NOT EXISTS transactions_%s PARTITION OF transactions FOR VALUES WITH (MODULUS 100, REMAINDER %s)', i, i + ); + END LOOP; +END $$; \ No newline at end of file diff --git a/database/src/postgres/mod.rs b/database/src/postgres/mod.rs index c7b58b87..059d720c 100644 --- a/database/src/postgres/mod.rs +++ b/database/src/postgres/mod.rs @@ -1,10 +1,6 @@ mod rpc_server; mod state_indexer; - -static META_DB_MIGRATOR: sqlx::migrate::Migrator = - sqlx::migrate!("src/postgres/migrations/meta_db"); -static SHARD_DB_MIGRATOR: sqlx::migrate::Migrator = - sqlx::migrate!("src/postgres/migrations/shard_db"); +mod tx_indexer; #[derive(borsh::BorshSerialize, borsh::BorshDeserialize, Clone, Debug)] struct PageState { @@ -33,6 +29,7 @@ pub struct ShardIdPool<'a> { pool: &'a sqlx::Pool, } +#[derive(Clone)] pub struct PostgresDBManager { shard_layout: near_primitives::shard_layout::ShardLayout, shards_pool: @@ -43,31 +40,23 @@ pub struct PostgresDBManager { impl PostgresDBManager { async fn create_meta_db_pool( database_url: &str, - read_only: bool, max_connections: u32, ) -> anyhow::Result> { let pool = sqlx::postgres::PgPoolOptions::new() .max_connections(max_connections) .connect(database_url) .await?; - if !read_only { - Self::run_migrations(&META_DB_MIGRATOR, &pool).await?; - } Ok(pool) } async fn create_shard_db_pool( database_url: &str, - read_only: bool, max_connections: u32, ) -> anyhow::Result> { let pool = sqlx::postgres::PgPoolOptions::new() .max_connections(max_connections) .connect(database_url) .await?; - if !read_only { - Self::run_migrations(&SHARD_DB_MIGRATOR, &pool).await?; - } Ok(pool) } @@ -85,24 +74,25 @@ impl PostgresDBManager { }) } - async fn run_migrations( - migrator: &sqlx::migrate::Migrator, - pool: &sqlx::Pool, - ) -> anyhow::Result<()> { - migrator.run(pool).await?; - Ok(()) + async fn get_shard_connection_by_id( + &self, + shard_id: &near_primitives::types::ShardId, + ) -> anyhow::Result { + Ok(ShardIdPool { + shard_id: *shard_id, + pool: self.shards_pool.get(shard_id).ok_or(anyhow::anyhow!( + "Database connection for shard_{} not found", + shard_id + ))?, + }) } } #[async_trait::async_trait] impl crate::BaseDbManager for PostgresDBManager { async fn new(config: &configuration::DatabaseConfig) -> anyhow::Result> { - let meta_db_pool = Self::create_meta_db_pool( - &config.database_url, - config.read_only, - config.max_connections, - ) - .await?; + let meta_db_pool = + Self::create_meta_db_pool(&config.database_url, config.max_connections).await?; let mut shards_pool = std::collections::HashMap::new(); let shard_layout = config .shard_layout @@ -113,9 +103,7 @@ impl crate::BaseDbManager for PostgresDBManager { .shards_config .get(&shard_id) .unwrap_or_else(|| panic!("Shard_{shard_id} - database config not found")); - let pool = - Self::create_shard_db_pool(database_url, config.read_only, config.max_connections) - .await?; + let pool = Self::create_shard_db_pool(database_url, config.max_connections).await?; shards_pool.insert(shard_id, pool); } Ok(Box::new(Self { diff --git a/database/src/postgres/rpc_server.rs b/database/src/postgres/rpc_server.rs index 66bcddc1..a4d32b98 100644 --- a/database/src/postgres/rpc_server.rs +++ b/database/src/postgres/rpc_server.rs @@ -74,46 +74,43 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { } else { crate::postgres::PageState::new(1000) }; - let mut stream = sqlx::query_as::<_, (String, Vec)>( - " - WITH latest_blocks AS ( - SELECT - data_key, - MAX(block_height) AS max_block_height - FROM - state_changes_data - WHERE - account_id = $1 - AND block_height <= $2 - GROUP BY - data_key - ) - SELECT - sc.data_key, - sc.data_value - FROM - state_changes_data sc - INNER JOIN latest_blocks lb - ON - sc.data_key = lb.data_key - AND sc.block_height = lb.max_block_height - WHERE - sc.account_id = $1 - AND sc.data_value IS NOT NULL - AND ( - $3 IS NULL OR - sc.data_key > $3 - ) - ORDER BY - sc.data_key ASC + let mut stream = if let Some(last_data_key) = &page_state.last_data_key { + sqlx::query_as::<_, (String, Vec)>( + " + SELECT data_key, data_value + FROM state_changes_data_compact + WHERE account_id = $1 + AND block_height_from <= $2 + AND (block_height_to IS NULL OR block_height_to > $2) + AND data_key > $3 + ORDER BY + data_key ASC LIMIT $4; ", - ) - .bind(account_id.to_string()) - .bind(bigdecimal::BigDecimal::from(block_height)) - .bind(page_state.last_data_key.clone()) - .bind(page_state.page_size) - .fetch(shard_id_pool.pool); + ) + .bind(account_id.to_string()) + .bind(block_height as i64) // Convert to i64 for database compatibility + .bind(last_data_key.clone()) + .bind(page_state.page_size) + .fetch(shard_id_pool.pool) + } else { + sqlx::query_as::<_, (String, Vec)>( + " + SELECT data_key, data_value + FROM state_changes_data_compact + WHERE account_id = $1 + AND block_height_from <= $2 + AND (block_height_to IS NULL OR block_height_to > $2) + ORDER BY + data_key ASC + LIMIT $3; + ", + ) + .bind(account_id.to_string()) + .bind(block_height as i64) // Convert to i64 for database compatibility + .bind(page_state.page_size) + .fetch(shard_id_pool.pool) + }; let mut items = std::collections::HashMap::new(); let mut last_data_key = String::new(); while let Some(row) = stream.next().await { @@ -153,36 +150,17 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { let mut items = std::collections::HashMap::new(); let mut stream = sqlx::query_as::<_, (String, Vec)>( " - WITH latest_blocks AS ( - SELECT - data_key, - MAX(block_height) AS max_block_height - FROM - state_changes_data - WHERE - account_id = $1 - AND data_key LIKE $2 - AND block_height <= $3 - GROUP BY - data_key - ) - SELECT - sc.data_key, - sc.data_value - FROM - state_changes_data sc - INNER JOIN latest_blocks lb - ON - sc.data_key = lb.data_key - AND sc.block_height = lb.max_block_height - WHERE - sc.account_id = $1 - AND sc.data_value IS NOT NULL; + SELECT data_key, data_value + FROM state_changes_data_compact + WHERE account_id = $1 + AND data_key LIKE $2 + AND block_height_from <= $3 + AND (block_height_to IS NULL OR block_height_to > $3); ", ) .bind(account_id.to_string()) .bind(format!("{}%", hex::encode(prefix))) - .bind(bigdecimal::BigDecimal::from(block_height)) + .bind(block_height as i64) // Convert to i64 for database compatibility .fetch(shard_id_pool.pool); while let Some(row) = stream.next().await { let (key, value): (String, Vec) = row?; @@ -210,34 +188,15 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { let mut items = std::collections::HashMap::new(); let mut stream = sqlx::query_as::<_, (String, Vec)>( " - WITH latest_blocks AS ( - SELECT - data_key, - MAX(block_height) AS max_block_height - FROM - state_changes_data - WHERE - account_id = $1 - AND block_height <= $2 - GROUP BY - data_key - ) - SELECT - sc.data_key, - sc.data_value - FROM - state_changes_data sc - INNER JOIN latest_blocks lb - ON - sc.data_key = lb.data_key - AND sc.block_height = lb.max_block_height - WHERE - sc.account_id = $1 - AND sc.data_value IS NOT NULL; + SELECT data_key, data_value + FROM state_changes_data_compact + WHERE account_id = $1 + AND block_height_from <= $2 + AND (block_height_to IS NULL OR block_height_to > $2); ", ) .bind(account_id.to_string()) - .bind(bigdecimal::BigDecimal::from(block_height)) + .bind(block_height as i64) // Convert to i64 for database compatibility .fetch(shard_id_pool.pool); while let Some(row) = stream.next().await { let (key, value): (String, Vec) = row?; @@ -266,18 +225,19 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { .inc(); let (data_value,): (Vec,) = sqlx::query_as( " - SELECT data_value - FROM state_changes_data - WHERE account_id = $1 - AND data_key = $2 - AND block_height <= $3 - ORDER BY block_height DESC + SELECT data_key, data_value + FROM state_changes_data_compact + WHERE account_id = $1 + AND data_key = $2 + AND block_height_from <= $3 + AND (block_height_to IS NULL OR block_height_to > $3) + ORDER BY block_height_from DESC LIMIT 1; ", ) .bind(account_id.to_string()) .bind(hex::encode(&key_data).to_string()) - .bind(bigdecimal::BigDecimal::from(block_height)) + .bind(block_height as i64) // Convert to i64 for database compatibility .fetch_one(shard_id_pool.pool) .await?; Ok((key_data, data_value)) @@ -290,6 +250,12 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { method_name: &str, ) -> anyhow::Result> { let shard_id_pool = self.get_shard_connection(account_id).await?; + tracing::debug!( + "Getting account data for {} at block height {} from shard {}", + account_id, + request_block_height, + shard_id_pool.shard_id + ); crate::metrics::SHARD_DATABASE_READ_QUERIES .with_label_values(&[ &shard_id_pool.shard_id.to_string(), @@ -297,27 +263,28 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { "state_changes_account", ]) .inc(); - let (block_height, block_hash, data_value): (bigdecimal::BigDecimal, String, Vec) = - sqlx::query_as( - " - SELECT block_height, block_hash, data_value - FROM state_changes_account - WHERE account_id = $1 - AND block_height <= $2 - ORDER BY block_height DESC + let result: (Vec, i64) = sqlx::query_as( + " + SELECT data_value, block_height_from + FROM state_changes_account_compact + WHERE account_id = $1 + AND block_height_from <= $2 + AND (block_height_to IS NULL OR block_height_to > $2) + ORDER BY block_height_from DESC LIMIT 1; ", - ) - .bind(account_id.to_string()) - .bind(bigdecimal::BigDecimal::from(request_block_height)) - .fetch_one(shard_id_pool.pool) - .await?; - let block = readnode_primitives::BlockRecord::try_from((block_hash, block_height))?; - readnode_primitives::QueryData::::try_from(( - data_value, - block.height, - block.hash, - )) + ) + .bind(account_id.to_string()) + .bind(request_block_height as i64) // Convert to i64 for database compatibility + .fetch_one(shard_id_pool.pool) + .await?; + tracing::debug!( + "Fetched account data for {} at block height {}: {:?}", + account_id, + request_block_height, + result + ); + readnode_primitives::QueryData::::try_from(result) } async fn get_contract_code( @@ -334,27 +301,23 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { "state_changes_contract", ]) .inc(); - let (block_height, block_hash, contract_code): (bigdecimal::BigDecimal, String, Vec) = - sqlx::query_as( - " - SELECT block_height, block_hash, data_value - FROM state_changes_contract - WHERE account_id = $1 - AND block_height <= $2 - ORDER BY block_height DESC + let result: (Vec, i64) = sqlx::query_as( + " + SELECT data_value, block_height_from + FROM state_changes_contract_compact + WHERE account_id = $1 + AND block_height_from <= $2 + AND (block_height_to IS NULL OR block_height_to > $2) + ORDER BY block_height_from DESC LIMIT 1; ", - ) - .bind(account_id.to_string()) - .bind(bigdecimal::BigDecimal::from(request_block_height)) - .fetch_one(shard_id_pool.pool) - .await?; - let block = readnode_primitives::BlockRecord::try_from((block_hash, block_height))?; - Ok(readnode_primitives::QueryData { - data: contract_code, - block_height: block.height, - block_hash: block.hash, - }) + ) + .bind(account_id.to_string()) + .bind(request_block_height as i64) // Convert to i64 for database compatibility + .fetch_one(shard_id_pool.pool) + .await?; + + readnode_primitives::QueryData::>::try_from(result) } async fn get_access_key( @@ -373,29 +336,24 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { ]) .inc(); let key_data = borsh::to_vec(&public_key)?; - let (block_height, block_hash, data_value): (bigdecimal::BigDecimal, String, Vec) = - sqlx::query_as( - " - SELECT block_height, block_hash, data_value - FROM state_changes_access_key - WHERE account_id = $1 - AND data_key = $2 - AND block_height <= $3 - ORDER BY block_height DESC + let result: (Vec, i64) = sqlx::query_as( + " + SELECT data_value, block_height_from + FROM state_changes_access_key_compact + WHERE account_id = $1 + AND data_key = $2 + AND block_height_from <= $3 + AND (block_height_to IS NULL OR block_height_to > $3) + ORDER BY block_height_from DESC LIMIT 1; ", - ) - .bind(account_id.to_string()) - .bind(hex::encode(&key_data).to_string()) - .bind(bigdecimal::BigDecimal::from(request_block_height)) - .fetch_one(shard_id_pool.pool) - .await?; - let block = readnode_primitives::BlockRecord::try_from((block_hash, block_height))?; - readnode_primitives::QueryData::::try_from(( - data_value, - block.height, - block.hash, - )) + ) + .bind(account_id.to_string()) + .bind(hex::encode(&key_data).to_string()) + .bind(request_block_height as i64) // Convert to i64 for database compatibility + .fetch_one(shard_id_pool.pool) + .await?; + readnode_primitives::QueryData::::try_from(result) } async fn get_account_access_keys( @@ -413,42 +371,20 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { ]) .inc(); let mut access_keys = vec![]; - let mut stream = sqlx::query_as::<_, (String, Vec, bigdecimal::BigDecimal)>( + let mut stream = sqlx::query_as::<_, (String, Vec)>( " - WITH latest_blocks AS ( - SELECT - data_key, - account_id, - MAX(block_height) as max_block_height - FROM - state_changes_access_key - WHERE - account_id = $1 - AND block_height <= $2 - GROUP BY - data_key, - account_id - ) - SELECT - sc.data_key, - sc.data_value, - sc.block_height - FROM - state_changes_access_key sc - INNER JOIN latest_blocks lb - ON - sc.data_key = lb.data_key - AND sc.block_height = lb.max_block_height - AND sc.account_id = lb.account_id - WHERE - sc.data_value IS NOT NULL; + SELECT data_key, data_value + FROM state_changes_access_key_compact + WHERE account_id = $1 + AND block_height_from <= $2 + AND (block_height_to IS NULL OR block_height_to > $2); ", ) .bind(account_id.to_string()) - .bind(bigdecimal::BigDecimal::from(block_height)) + .bind(block_height as i64) // Convert to i64 for database compatibility .fetch(shard_id_pool.pool); while let Some(row) = stream.next().await { - let (public_key_hex, access_key, _): (String, Vec, _) = row?; + let (public_key_hex, access_key): (String, Vec) = row?; let access_key_view = near_primitives::views::AccessKeyInfoView { public_key: borsh::from_slice::(&hex::decode( public_key_hex, @@ -478,7 +414,7 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { " SELECT included_in_block_height, shard_id FROM chunks_duplicate - WHERE block_height = $1 + WHERE block_height = $1 AND shard_id = $2 LIMIT 1; ", @@ -558,4 +494,11 @@ impl crate::ReaderDbManager for crate::PostgresDBManager { validators_info, }) } + + fn get_shard_id_by_account_id( + &self, + account_id: &near_primitives::types::AccountId, + ) -> near_primitives::types::ShardId { + self.shard_layout.account_id_to_shard_id(account_id) + } } diff --git a/database/src/postgres/state_indexer.rs b/database/src/postgres/state_indexer.rs deleted file mode 100644 index 3f3b11f9..00000000 --- a/database/src/postgres/state_indexer.rs +++ /dev/null @@ -1,441 +0,0 @@ -use bigdecimal::ToPrimitive; -use futures::FutureExt; - -impl crate::PostgresDBManager { - async fn save_chunks_unique( - &self, - block_height: u64, - chunks: Vec<( - crate::primitives::ChunkHash, - crate::primitives::ShardId, - crate::primitives::HeightIncluded, - )>, - ) -> anyhow::Result<()> { - let unique_chunks = chunks - .iter() - .filter(|(_chunk_hash, _shard_id, height_included)| height_included == &block_height) - .collect::>(); - - if !unique_chunks.is_empty() { - crate::metrics::META_DATABASE_WRITE_QUERIES - .with_label_values(&["save_chunks", "chunks"]) - .inc(); - let mut query_builder: sqlx::QueryBuilder = - sqlx::QueryBuilder::new("INSERT INTO chunks (chunk_hash, block_height, shard_id) "); - - query_builder.push_values( - unique_chunks.iter(), - |mut values, (chunk_hash, shard_id, height_included)| { - values - .push_bind(chunk_hash.to_string()) - .push_bind(bigdecimal::BigDecimal::from(*height_included)) - .push_bind(bigdecimal::BigDecimal::from(*shard_id)); - }, - ); - query_builder.push(" ON CONFLICT DO NOTHING;"); - query_builder.build().execute(&self.meta_db_pool).await?; - } - Ok(()) - } - - async fn save_chunks_duplicate( - &self, - block_height: u64, - chunks: Vec<( - crate::primitives::ChunkHash, - crate::primitives::ShardId, - crate::primitives::HeightIncluded, - )>, - ) -> anyhow::Result<()> { - let chunks_duplicate = chunks - .iter() - .filter(|(_chunk_hash, _shard_id, height_included)| height_included != &block_height) - .collect::>(); - if !chunks_duplicate.is_empty() { - crate::metrics::META_DATABASE_WRITE_QUERIES - .with_label_values(&["save_chunks", "chunks_duplicate"]) - .inc(); - let mut query_builder: sqlx::QueryBuilder = - sqlx::QueryBuilder::new("INSERT INTO chunks_duplicate (chunk_hash, block_height, shard_id, included_in_block_height) "); - - query_builder.push_values( - chunks.iter(), - |mut values, (chunk_hash, shard_id, height_included)| { - values - .push_bind(chunk_hash.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(bigdecimal::BigDecimal::from(*shard_id)) - .push_bind(bigdecimal::BigDecimal::from(*height_included)); - }, - ); - query_builder.push(" ON CONFLICT DO NOTHING;"); - query_builder.build().execute(&self.meta_db_pool).await?; - } - Ok(()) - } -} -#[async_trait::async_trait] -impl crate::StateIndexerDbManager for crate::PostgresDBManager { - async fn save_block( - &self, - block_height: u64, - block_hash: near_primitives::hash::CryptoHash, - ) -> anyhow::Result<()> { - crate::metrics::META_DATABASE_WRITE_QUERIES - .with_label_values(&["save_block", "blocks"]) - .inc(); - sqlx::query( - " - INSERT INTO blocks (block_height, block_hash) - VALUES ($1, $2) ON CONFLICT DO NOTHING; - ", - ) - .bind(bigdecimal::BigDecimal::from(block_height)) - .bind(block_hash.to_string()) - .execute(&self.meta_db_pool) - .await?; - Ok(()) - } - - async fn save_chunks( - &self, - block_height: u64, - chunks: Vec<( - crate::primitives::ChunkHash, - crate::primitives::ShardId, - crate::primitives::HeightIncluded, - )>, - ) -> anyhow::Result<()> { - let save_chunks_unique_future = self.save_chunks_unique(block_height, chunks.clone()); - let save_chunks_duplicate_future = self.save_chunks_duplicate(block_height, chunks); - - futures::future::join_all([ - save_chunks_unique_future.boxed(), - save_chunks_duplicate_future.boxed(), - ]) - .await - .into_iter() - .collect::>() - } - - async fn get_block_height_by_hash( - &self, - block_hash: near_primitives::hash::CryptoHash, - method_name: &str, - ) -> anyhow::Result { - crate::metrics::META_DATABASE_READ_QUERIES - .with_label_values(&[method_name, "blocks"]) - .inc(); - let (block_height,): (bigdecimal::BigDecimal,) = sqlx::query_as( - " - SELECT block_height - FROM blocks - WHERE block_hash = $1 - LIMIT 1; - ", - ) - .bind(block_hash.to_string()) - .fetch_one(&self.meta_db_pool) - .await?; - block_height - .to_u64() - .ok_or_else(|| anyhow::anyhow!("Failed to parse `block_height` to u64")) - } - - async fn update_meta(&self, indexer_id: &str, block_height: u64) -> anyhow::Result<()> { - crate::metrics::META_DATABASE_WRITE_QUERIES - .with_label_values(&["update_meta", "meta"]) - .inc(); - sqlx::query( - " - INSERT INTO meta (indexer_id, last_processed_block_height) - VALUES ($1, $2) - ON CONFLICT (indexer_id) - DO UPDATE SET last_processed_block_height = $2; - ", - ) - .bind(indexer_id) - .bind(bigdecimal::BigDecimal::from(block_height)) - .execute(&self.meta_db_pool) - .await?; - Ok(()) - } - - async fn get_last_processed_block_height(&self, indexer_id: &str) -> anyhow::Result { - crate::metrics::META_DATABASE_READ_QUERIES - .with_label_values(&["get_last_processed_block_height", "meta"]) - .inc(); - let (last_processed_block_height,): (bigdecimal::BigDecimal,) = sqlx::query_as( - " - SELECT last_processed_block_height - FROM meta - WHERE indexer_id = $1 - LIMIT 1; - ", - ) - .bind(indexer_id) - .fetch_one(&self.meta_db_pool) - .await?; - last_processed_block_height - .to_u64() - .ok_or_else(|| anyhow::anyhow!("Failed to parse `last_processed_block_height` to u64")) - } - - async fn save_validators( - &self, - epoch_id: near_primitives::hash::CryptoHash, - epoch_height: u64, - epoch_start_height: u64, - validators_info: &near_primitives::views::EpochValidatorInfo, - epoch_end_block_hash: near_primitives::hash::CryptoHash, - ) -> anyhow::Result<()> { - crate::metrics::META_DATABASE_WRITE_QUERIES - .with_label_values(&["add_validators", "validators"]) - .inc(); - let epoch_end_block_height = self - .get_block_height_by_hash(epoch_end_block_hash, "add_validators") - .await?; - sqlx::query( - " - INSERT INTO validators (epoch_id, epoch_height, epoch_start_height, epoch_end_height, validators_info) - VALUES ($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING; - " - ) - .bind(epoch_id.to_string()) - .bind(bigdecimal::BigDecimal::from(epoch_height)) - .bind(bigdecimal::BigDecimal::from(epoch_start_height)) - .bind(bigdecimal::BigDecimal::from(epoch_end_block_height)) - .bind(&serde_json::to_value(validators_info)?) - .execute(&self.meta_db_pool) - .await?; - Ok(()) - } - - async fn save_state_changes_data( - &self, - shard_id: near_primitives::types::ShardId, - state_changes: Vec, - block_height: u64, - block_hash: near_primitives::hash::CryptoHash, - ) -> anyhow::Result<()> { - crate::metrics::SHARD_DATABASE_WRITE_QUERIES - .with_label_values(&[ - &shard_id.to_string(), - "save_state_changes_data", - "state_changes_data", - ]) - .inc(); - let mut query_builder: sqlx::QueryBuilder = sqlx::QueryBuilder::new( - "INSERT INTO state_changes_data (account_id, block_height, block_hash, data_key, data_value) ", - ); - query_builder.push_values(state_changes.iter(), |mut values, state_change| { - match &state_change.value { - near_primitives::views::StateChangeValueView::DataUpdate { - account_id, - key, - value, - } => { - let data_key: &[u8] = key.as_ref(); - let data_value: &[u8] = value.as_ref(); - values - .push_bind(account_id.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(block_hash.to_string()) - .push_bind(hex::encode(data_key).to_string()) - .push_bind(data_value); - } - near_primitives::views::StateChangeValueView::DataDeletion { account_id, key } => { - let data_key: &[u8] = key.as_ref(); - let data_value: Option<&[u8]> = None; - values - .push_bind(account_id.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(block_hash.to_string()) - .push_bind(hex::encode(data_key).to_string()) - .push_bind(data_value); - } - _ => {} - } - }); - query_builder.push(" ON CONFLICT DO NOTHING;"); - query_builder - .build() - .execute(self.shards_pool.get(&shard_id).ok_or(anyhow::anyhow!( - "Database connection for Shard_{} not found", - shard_id - ))?) - .await?; - Ok(()) - } - - async fn save_state_changes_access_key( - &self, - shard_id: near_primitives::types::ShardId, - state_changes: Vec, - block_height: u64, - block_hash: near_primitives::hash::CryptoHash, - ) -> anyhow::Result<()> { - crate::metrics::SHARD_DATABASE_WRITE_QUERIES - .with_label_values(&[ - &shard_id.to_string(), - "save_state_changes_access_key", - "state_changes_access_key", - ]) - .inc(); - let mut query_builder: sqlx::QueryBuilder = sqlx::QueryBuilder::new( - "INSERT INTO state_changes_access_key (account_id, block_height, block_hash, data_key, data_value) ", - ); - query_builder.push_values(state_changes.iter(), |mut values, state_change| { - match &state_change.value { - near_primitives::views::StateChangeValueView::AccessKeyUpdate { - account_id, - public_key, - access_key, - } => { - let data_key = - borsh::to_vec(public_key).expect("Failed to borsh serialize public key"); - let data_value = - borsh::to_vec(access_key).expect("Failed to borsh serialize access key"); - values - .push_bind(account_id.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(block_hash.to_string()) - .push_bind(hex::encode(data_key).to_string()) - .push_bind(data_value); - } - near_primitives::views::StateChangeValueView::AccessKeyDeletion { - account_id, - public_key, - } => { - let data_key = - borsh::to_vec(public_key).expect("Failed to borsh serialize public key"); - let data_value: Option<&[u8]> = None; - values - .push_bind(account_id.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(block_hash.to_string()) - .push_bind(hex::encode(data_key).to_string()) - .push_bind(data_value); - } - _ => {} - } - }); - query_builder.push(" ON CONFLICT DO NOTHING;"); - query_builder - .build() - .execute(self.shards_pool.get(&shard_id).ok_or(anyhow::anyhow!( - "Database connection for Shard_{} not found", - shard_id - ))?) - .await?; - Ok(()) - } - - async fn save_state_changes_contract( - &self, - shard_id: near_primitives::types::ShardId, - state_changes: Vec, - block_height: u64, - block_hash: near_primitives::hash::CryptoHash, - ) -> anyhow::Result<()> { - crate::metrics::SHARD_DATABASE_WRITE_QUERIES - .with_label_values(&[ - &shard_id.to_string(), - "save_state_changes_contract", - "state_changes_contract", - ]) - .inc(); - let mut query_builder: sqlx::QueryBuilder = sqlx::QueryBuilder::new( - "INSERT INTO state_changes_contract (account_id, block_height, block_hash, data_value) ", - ); - query_builder.push_values(state_changes.iter(), |mut values, state_change| { - match &state_change.value { - near_primitives::views::StateChangeValueView::ContractCodeUpdate { - account_id, - code, - } => { - let data_value: &[u8] = code.as_ref(); - values - .push_bind(account_id.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(block_hash.to_string()) - .push_bind(data_value); - } - near_primitives::views::StateChangeValueView::ContractCodeDeletion { - account_id, - } => { - let data_value: Option<&[u8]> = None; - values - .push_bind(account_id.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(block_hash.to_string()) - .push_bind(data_value); - } - _ => {} - } - }); - query_builder.push(" ON CONFLICT DO NOTHING;"); - query_builder - .build() - .execute(self.shards_pool.get(&shard_id).ok_or(anyhow::anyhow!( - "Database connection for Shard_{} not found", - shard_id - ))?) - .await?; - Ok(()) - } - - async fn save_state_changes_account( - &self, - shard_id: near_primitives::types::ShardId, - state_changes: Vec, - block_height: u64, - block_hash: near_primitives::hash::CryptoHash, - ) -> anyhow::Result<()> { - crate::metrics::SHARD_DATABASE_WRITE_QUERIES - .with_label_values(&[ - &shard_id.to_string(), - "save_state_changes_account", - "state_changes_account", - ]) - .inc(); - let mut query_builder: sqlx::QueryBuilder = sqlx::QueryBuilder::new( - "INSERT INTO state_changes_account (account_id, block_height, block_hash, data_value) ", - ); - query_builder.push_values(state_changes.iter(), |mut values, state_change| { - match &state_change.value { - near_primitives::views::StateChangeValueView::AccountUpdate { - account_id, - account, - } => { - let data_value = - borsh::to_vec(&near_primitives::account::Account::from(account)) - .expect("Failed to borsh serialize account"); - values - .push_bind(account_id.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(block_hash.to_string()) - .push_bind(data_value); - } - near_primitives::views::StateChangeValueView::AccountDeletion { account_id } => { - let data_value: Option<&[u8]> = None; - values - .push_bind(account_id.to_string()) - .push_bind(bigdecimal::BigDecimal::from(block_height)) - .push_bind(block_hash.to_string()) - .push_bind(data_value); - } - _ => {} - } - }); - query_builder.push(" ON CONFLICT DO NOTHING;"); - query_builder - .build() - .execute(self.shards_pool.get(&shard_id).ok_or(anyhow::anyhow!( - "Database connection for Shard_{} not found", - shard_id - ))?) - .await?; - Ok(()) - } -} diff --git a/database/src/postgres/state_indexer/helpers.rs b/database/src/postgres/state_indexer/helpers.rs new file mode 100644 index 00000000..dc71a7b7 --- /dev/null +++ b/database/src/postgres/state_indexer/helpers.rs @@ -0,0 +1,616 @@ +use std::collections::HashMap; +use std::time::Instant; + +use futures::future::try_join_all; +use sqlx::Row; + +type StateChangeKeyDataAtBlockHeight = ( + String, // account_id + String, // data_key + Vec, // data_value + i64, // block_height_from +); + +/// PostgreSQL State Indexer Implementation +/// +/// ARCHITECTURAL OVERVIEW: +/// This module implements efficient batch processing for NEAR Protocol state changes +/// across partitioned PostgreSQL tables. The design focuses on: +/// +/// 1. **Partitioned Tables**: All state tables are horizontally partitioned by account_id +/// using PostgreSQL's hashtext() function for consistent distribution +/// +/// 2. **Batch Processing**: Operations are grouped by partition and executed in parallel +/// to maximize throughput while respecting connection pool limits +/// +/// 3. **Helper Function Strategy**: Four specialized helpers handle different data patterns: +/// - execute_partitioned_account_update: Account-only updates (UNNEST pattern) +/// - execute_partitioned_key_update: Composite key updates (CTE pattern) +/// - execute_partitioned_standard_insert: 4-column inserts with data_key +/// - execute_partitioned_keyless_insert: 3-column inserts without data_key +/// +/// 4. **SQL Pattern Selection**: Different update patterns optimize for different scenarios: +/// - UNNEST: Efficient for uniform operations (same block_height, simple matching) +/// - CTE: Required for variable data operations (different block_heights, complex conditions) +/// +/// 5. **Concurrency Control**: Semaphores limit parallel operations to prevent database +/// connection pool exhaustion while maximizing throughput +/// +/// SPECIAL CASES: +/// - update_state_changes_access_key: Uses in-place UNNEST pattern instead of CTE helper +/// due to uniform block_height and simpler matching requirements (see method comments) +/// +impl crate::PostgresDBManager { + /// Helper function for partitioned update operations using account-only updates + /// + /// This helper is used for tables that only have account_id as the primary key component + /// (like account and contract tables), where we need to update block_height_to for all + /// rows matching specific account_ids. + /// + /// SQL Pattern: Uses UNNEST with a single array for account_ids + /// ```sql + /// UPDATE table_partition AS t + /// SET block_height_to = $2 + /// FROM (SELECT unnest($1::text[]) AS account_id) AS u + /// WHERE t.account_id = u.account_id AND t.block_height_to IS NULL; + /// ``` + /// + /// Used by: update_state_changes_account, update_state_changes_contract + pub(crate) async fn execute_partitioned_account_update( + &self, + shard_id: near_primitives::types::ShardId, + table_prefix: String, + operation_name: String, + account_ids: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + if account_ids.is_empty() { + return Ok(()); + } + + // Get database connection pool for this shard + let pool = self.get_shard_pool(shard_id)?; + + // Compute partition assignments for all account_ids using PostgreSQL's hashtext() function + // This ensures consistent partition distribution matching the table partitioning scheme + let partition_map = self.partition_map(&shard_id, pool, &account_ids).await?; + + // Group account_ids by their target partition for batch processing + // This reduces the number of database queries by updating entire partitions at once + let mut accounts_per_partition: HashMap> = HashMap::new(); + for account_id in account_ids { + if let Some(&partition) = partition_map.get(&account_id) { + accounts_per_partition + .entry(partition) + .or_default() + .push(account_id); + } else { + tracing::warn!("Partition not found for account_id: {}", account_id); + } + } + crate::metrics::PARTITIONS_TOUCHED_COUNT + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &accounts_per_partition.len().to_string(), + ]) + .inc(); + + // Execute updates in parallel across partitions with concurrency control + // Each partition can be updated independently, improving throughput + let semaphore = + std::sync::Arc::new(tokio::sync::Semaphore::new(super::MAX_CONCURRENT_QUERIES)); + let mut tasks = Vec::new(); + + for (partition_id, partition_accounts) in accounts_per_partition { + let pool = pool.clone(); + let semaphore = semaphore.clone(); + let operation_name = operation_name.clone(); + let table_prefix = table_prefix.clone(); + let block_height_bd = bigdecimal::BigDecimal::from(block_height); + + let task = tokio::spawn(async move { + // Acquire semaphore permit to limit concurrent database operations + let _permit = semaphore.acquire_owned().await.unwrap(); + let start = Instant::now(); + + // Build UPDATE query using UNNEST to batch-process multiple account_ids + // UNNEST converts the array parameter into rows for efficient JOIN operations + let query = format!( + r#" + UPDATE {table_prefix}_{partition_id} AS t + SET block_height_to = $2 + FROM (SELECT unnest($1::text[]) AS account_id) AS u + WHERE t.account_id = u.account_id + AND t.block_height_to IS NULL; + "#, + table_prefix = table_prefix, + partition_id = partition_id + ); + + sqlx::query(&query) + .bind(&partition_accounts) + .bind(&block_height_bd) + .execute(&pool) + .await?; + + crate::metrics::SHARD_DATABASE_WRITE_ELAPSED_TIME + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &start.elapsed().as_millis().to_string(), + ]) + .inc(); + tracing::debug!( + target: "database::postgres::state_indexer", + "Update done operation={} partition={} elapsed={:?} rows={}", + operation_name, + partition_id, + start.elapsed(), + partition_accounts.len() + ); + + Ok::<(), anyhow::Error>(()) + }); + + tasks.push(task); + } + + try_join_all(tasks).await?; + Ok(()) + } + + /// Helper function for partitioned updates with composite key (account_id + data_key) + /// + /// This helper now uses `UNNEST()` instead of CTE for performance: + /// - `UNNEST()` is much faster for large batches compared to VALUES in CTE. + /// - Allows PostgreSQL to stream and avoid heavy planning overhead. + /// + /// Uses: `update_state_changes_data` + pub(crate) async fn execute_partitioned_key_update( + &self, + shard_id: near_primitives::types::ShardId, + table_prefix: String, + operation_name: String, + updates: Vec<(String, String, i64)>, // (account_id, data_key, block_height) + ) -> anyhow::Result<()> { + if updates.is_empty() { + return Ok(()); + } + + let pool = self.get_shard_pool(shard_id)?; + let account_ids: Vec = updates.iter().map(|(id, _, _)| id.clone()).collect(); + + // Metrics for accounts affected + crate::metrics::AFFECTED_ACCOUNTS_COUNT + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &account_ids.len().to_string(), + ]) + .inc(); + + let partition_map = self.partition_map(&shard_id, pool, &account_ids).await?; + + // Group updates per partition + let mut updates_per_partition: HashMap> = HashMap::new(); + for (account_id, data_key, block_height) in updates { + if let Some(&partition) = partition_map.get(&account_id) { + updates_per_partition.entry(partition).or_default().push(( + account_id, + data_key, + block_height, + )); + } + } + + // Track partitions touched + crate::metrics::PARTITIONS_TOUCHED_COUNT + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &updates_per_partition.len().to_string(), + ]) + .inc(); + + let semaphore = + std::sync::Arc::new(tokio::sync::Semaphore::new(super::MAX_CONCURRENT_QUERIES)); + let mut tasks = Vec::new(); + + for (partition_id, rows) in updates_per_partition { + let pool = pool.clone(); + let semaphore = semaphore.clone(); + let table_name = format!("{}_{}", table_prefix, partition_id); + let operation_name = operation_name.clone(); + + let task = tokio::spawn(async move { + let _permit = semaphore.acquire_owned().await.unwrap(); + let start = Instant::now(); + + // Use unzip_n_vec to split tuples into separate Vecs for UNNEST + let (account_ids, data_keys, block_heights): (Vec<_>, Vec<_>, Vec<_>) = + unzip_n_vec(rows); + + let query = format!( + r#" + UPDATE {table_name} AS old + SET block_height_to = new_data.block_height + FROM ( + SELECT UNNEST($1::text[]) AS account_id, + UNNEST($2::text[]) AS data_key, + UNNEST($3::numeric[]) AS block_height + ) AS new_data + WHERE old.account_id = new_data.account_id + AND old.data_key = new_data.data_key + AND old.block_height_from < new_data.block_height + AND old.block_height_to IS NULL; + "#, + ); + + let result = sqlx::query(&query) + .bind(&account_ids) + .bind(&data_keys) + .bind(&block_heights) + .execute(&pool) + .await + .map_err(anyhow::Error::from); + + crate::metrics::SHARD_DATABASE_WRITE_ELAPSED_TIME + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &start.elapsed().as_millis().to_string(), + ]) + .inc(); + + tracing::debug!( + target: "database::postgres::state_indexer", + "Update done operation={} partition={} elapsed={:?} rows={}", + operation_name, + partition_id, + start.elapsed(), + account_ids.len() + ); + + result + }); + + tasks.push(task); + } + + try_join_all(tasks).await?; + Ok(()) + } + + /// Helper function for standard 4-column inserts with data_key + /// + /// This helper handles inserts into tables with composite keys that include both + /// account_id and data_key (like state_changes_data and state_changes_access_key). + /// + /// Table Schema: (account_id, data_key, data_value, block_height_from, block_height_to) + /// - account_id: partition key for data distribution + /// - data_key: secondary key component (hex-encoded for data, borsh-serialized for access keys) + /// - data_value: the actual state data (raw bytes) + /// - block_height_from: when this version became active + /// - block_height_to: when this version was superseded (NULL for current) + /// + /// Used by: insert_state_changes_data, insert_state_changes_access_key + pub(crate) async fn execute_partitioned_standard_insert( + &self, + shard_id: near_primitives::types::ShardId, + table_prefix: String, + operation_name: String, + inserts: Vec<(String, String, Vec, i64)>, // (account_id, data_key, data_value, block_height) + ) -> anyhow::Result<()> { + if inserts.is_empty() { + return Ok(()); + } + + let pool = self.get_shard_pool(shard_id)?; + let account_ids: Vec = inserts.iter().map(|(id, _, _, _)| id.clone()).collect(); + crate::metrics::AFFECTED_ACCOUNTS_COUNT + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &account_ids.len().to_string(), + ]) + .inc(); + + let partition_map = self.partition_map(&shard_id, pool, &account_ids).await?; + + // Group inserts by partition for efficient batch processing + let mut inserts_per_partition: HashMap> = + HashMap::new(); + for (account_id, data_key, data_value, block_height) in inserts { + if let Some(&partition) = partition_map.get(&account_id) { + inserts_per_partition.entry(partition).or_default().push(( + account_id, + data_key, + data_value, + block_height, + )); + } else { + tracing::warn!("Partition not found for account_id: {}", account_id); + } + } + crate::metrics::PARTITIONS_TOUCHED_COUNT + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &inserts_per_partition.len().to_string(), + ]) + .inc(); + + let semaphore = + std::sync::Arc::new(tokio::sync::Semaphore::new(super::MAX_CONCURRENT_QUERIES)); + let mut tasks = Vec::new(); + + for (partition_id, rows) in inserts_per_partition { + let pool = pool.clone(); + let semaphore = semaphore.clone(); + let table_name = format!("{}_{}", table_prefix, partition_id); + let operation_name = operation_name.clone(); + + let task = tokio::spawn(async move { + let start = Instant::now(); + let _permit = semaphore.acquire_owned().await.unwrap(); + + // Build batch INSERT using sqlx QueryBuilder for type safety and performance + let mut qb = sqlx::QueryBuilder::new(format!( + "INSERT INTO {} (account_id, data_key, data_value, block_height_from, block_height_to) ", + table_name, + )); + + qb.push_values( + rows.iter(), + |mut row, (account_id, data_key, data_value, block_height)| { + row.push_bind(account_id) + .push_bind(data_key) + .push_bind(data_value) + .push_bind(block_height) + .push_bind(None::>); // block_height_to starts as NULL (active) + }, + ); + + // Use ON CONFLICT DO NOTHING to handle duplicate inserts gracefully + // This is important for idempotency during indexer restarts or replays + qb.push(" ON CONFLICT DO NOTHING"); + + let result = qb.build().execute(&pool).await.map_err(anyhow::Error::from); + + crate::metrics::SHARD_DATABASE_WRITE_ELAPSED_TIME + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &start.elapsed().as_millis().to_string(), + ]) + .inc(); + tracing::debug!( + target: "database::postgres::state_indexer", + "Insert done operation={} partition={} elapsed={:?} rows={}", + operation_name, + partition_id, + start.elapsed(), + rows.len() + ); + + result + }); + + tasks.push(task); + } + + try_join_all(tasks).await?; + Ok(()) + } + + /// Helper function for keyless 3-column inserts without data_key + /// + /// This helper handles inserts into tables that only use account_id as the key + /// (like state_changes_account and state_changes_contract), where the data_value + /// represents the entire state of the account or contract. + /// + /// Table Schema: (account_id, data_value, block_height_from, block_height_to) + /// - account_id: primary partition key + /// - data_value: complete state data (borsh-serialized account or contract code) + /// - block_height_from: when this version became active + /// - block_height_to: when this version was superseded (NULL for current) + /// + /// The absence of data_key means each account/contract has exactly one active + /// record at any given block height, representing its complete state. + /// + /// Used by: insert_state_changes_account, insert_state_changes_contract + pub(crate) async fn execute_partitioned_keyless_insert( + &self, + shard_id: near_primitives::types::ShardId, + table_prefix: String, + operation_name: String, + inserts: Vec<(String, Vec, i64)>, // (account_id, data_value, block_height) + ) -> anyhow::Result<()> { + if inserts.is_empty() { + return Ok(()); + } + + let pool = self.get_shard_pool(shard_id)?; + let account_ids: Vec = inserts.iter().map(|(id, _, _)| id.clone()).collect(); + crate::metrics::AFFECTED_ACCOUNTS_COUNT + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &account_ids.len().to_string(), + ]) + .inc(); + let partition_map = self.partition_map(&shard_id, pool, &account_ids).await?; + + // Group inserts per partition + let mut inserts_per_partition: HashMap, i64)>> = HashMap::new(); + for (account_id, data_value, block_height) in inserts { + if let Some(&partition) = partition_map.get(&account_id) { + inserts_per_partition.entry(partition).or_default().push(( + account_id, + data_value, + block_height, + )); + } else { + tracing::warn!("Partition not found for account_id: {}", account_id); + } + } + crate::metrics::PARTITIONS_TOUCHED_COUNT + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &inserts_per_partition.len().to_string(), + ]) + .inc(); + + let semaphore = + std::sync::Arc::new(tokio::sync::Semaphore::new(super::MAX_CONCURRENT_QUERIES)); + let mut tasks = Vec::new(); + + for (partition_id, rows) in inserts_per_partition { + let pool = pool.clone(); + let semaphore = semaphore.clone(); + let table_name = format!("{}_{}", table_prefix, partition_id); + let operation_name = operation_name.clone(); + + let task = tokio::spawn(async move { + let start = Instant::now(); + let _permit = semaphore.acquire_owned().await.unwrap(); + // Build batch INSERT for keyless tables (no data_key column) + let mut qb = sqlx::QueryBuilder::new(format!( + "INSERT INTO {} (account_id, data_value, block_height_from, block_height_to) ", + table_name, + )); + + qb.push_values( + rows.iter(), + |mut row, (account_id, data_value, block_height)| { + row.push_bind(account_id) + .push_bind(data_value) + .push_bind(block_height) + .push_bind(None::>); // block_height_to starts as NULL + }, + ); + + qb.push(" ON CONFLICT DO NOTHING"); + + let result = qb.build().execute(&pool).await.map_err(anyhow::Error::from); + + crate::metrics::SHARD_DATABASE_WRITE_ELAPSED_TIME + .with_label_values(&[ + &shard_id.to_string(), + &operation_name, + &start.elapsed().as_millis().to_string(), + ]) + .inc(); + tracing::debug!( + target: "database::postgres::state_indexer", + "Insert done operation={} partition={} elapsed={:?} rows={}", + operation_name, + partition_id, + start.elapsed(), + rows.len() + ); + + result + }); + + tasks.push(task); + } + + try_join_all(tasks).await?; + Ok(()) + } + + /// Helper function to record metrics consistently across all database operations + /// + /// Increments the SHARD_DATABASE_WRITE_QUERIES metric with standardized labels + /// for monitoring and observability of database write patterns. + pub(crate) fn record_shard_write_metric( + &self, + shard_id: near_primitives::types::ShardId, + operation: &str, + table: &str, + ) { + crate::metrics::SHARD_DATABASE_WRITE_QUERIES + .with_label_values(&[&shard_id.to_string(), operation, table]) + .inc(); + } + + /// Helper function to get database pool with consistent error handling + /// + /// Centralizes the pool retrieval logic and provides meaningful error messages + /// when a shard's database connection is not available. + pub(crate) fn get_shard_pool( + &self, + shard_id: near_primitives::types::ShardId, + ) -> anyhow::Result<&sqlx::PgPool> { + self.shards_pool + .get(&shard_id) + .ok_or_else(|| anyhow::anyhow!("Database connection for Shard_{} not found", shard_id)) + } + + /// Compute partition assignments for account_ids using PostgreSQL's hashtext() function + /// + /// This function is critical for maintaining consistency with the database partitioning scheme. + /// It uses the same hash function (hashtext) and modulo operation that PostgreSQL uses + /// for automatic partition routing, ensuring our manual partition targeting matches + /// the database's internal partition selection. + /// + /// The computation is done in PostgreSQL rather than Rust to guarantee identical + /// hash results regardless of client-side hash implementations or endianness differences. + pub(crate) async fn partition_map( + &self, + shard_id: &near_primitives::types::ShardId, + pool: &sqlx::PgPool, + account_ids: &Vec, + ) -> anyhow::Result> { + let now = std::time::Instant::now(); + + // Execute partition calculation in PostgreSQL to ensure consistency + // This MUST use the same hash function and modulo as the partitioned table definitions + let partition_rows = sqlx::query( + "SELECT account_id, get_text_partition(account_id, $2) AS partition + FROM unnest($1::text[]) AS account_id", + ) + .bind(account_ids) + .bind(super::PARTITIONS) + .fetch_all(pool) + .await?; + + let partition_map: HashMap = partition_rows + .into_iter() + .map(|row| { + let account_id: String = row.try_get("account_id").unwrap(); + let partition: i32 = row.try_get("partition").unwrap(); + (account_id, partition) + }) + .collect(); + crate::metrics::PARTITION_MAP_TIME_ELAPSED + .with_label_values(&[ + &shard_id.to_string(), + &now.elapsed().as_millis().to_string(), + ]) + .inc(); + tracing::debug!( + target: "database::postgres::state_indexer", + "Partition map computed in {:?} for {} accounts", + now.elapsed(), + account_ids.len() + ); + Ok(partition_map) + } +} + +/// Utility to unzip Vec of 3-tuples into 3 separate Vecs +fn unzip_n_vec(input: Vec<(T1, T2, T3)>) -> (Vec, Vec, Vec) { + let mut v1 = Vec::with_capacity(input.len()); + let mut v2 = Vec::with_capacity(input.len()); + let mut v3 = Vec::with_capacity(input.len()); + for (a, b, c) in input { + v1.push(a); + v2.push(b); + v3.push(c); + } + (v1, v2, v3) +} diff --git a/database/src/postgres/state_indexer/mod.rs b/database/src/postgres/state_indexer/mod.rs new file mode 100644 index 00000000..21eb095e --- /dev/null +++ b/database/src/postgres/state_indexer/mod.rs @@ -0,0 +1,629 @@ +use std::time::Instant; + +use bigdecimal::ToPrimitive; +use futures::FutureExt; + +mod helpers; + +// Database configuration constants +pub(crate) const PARTITIONS: i32 = 100; // Number of partitions for sharded tables (consistent with hashtext() mod) +pub(crate) const MAX_CONCURRENT_QUERIES: usize = 16; // Limit parallel database operations to prevent connection pool exhaustion + +impl crate::PostgresDBManager { + async fn save_chunks_unique( + &self, + block_height: u64, + chunks: Vec<( + crate::primitives::ChunkHash, + crate::primitives::ShardId, + crate::primitives::HeightIncluded, + )>, + ) -> anyhow::Result<()> { + let unique_chunks = chunks + .iter() + .filter(|(_chunk_hash, _shard_id, height_included)| height_included == &block_height) + .collect::>(); + + if !unique_chunks.is_empty() { + crate::metrics::META_DATABASE_WRITE_QUERIES + .with_label_values(&["save_chunks", "chunks"]) + .inc(); + let mut query_builder: sqlx::QueryBuilder = + sqlx::QueryBuilder::new("INSERT INTO chunks (chunk_hash, block_height, shard_id) "); + + query_builder.push_values( + unique_chunks.iter(), + |mut values, (chunk_hash, shard_id, height_included)| { + values + .push_bind(chunk_hash.to_string()) + .push_bind(bigdecimal::BigDecimal::from(*height_included)) + .push_bind(bigdecimal::BigDecimal::from(*shard_id)); + }, + ); + query_builder.push(" ON CONFLICT DO NOTHING;"); + query_builder.build().execute(&self.meta_db_pool).await?; + } + Ok(()) + } + + async fn save_chunks_duplicate( + &self, + block_height: u64, + chunks: Vec<( + crate::primitives::ChunkHash, + crate::primitives::ShardId, + crate::primitives::HeightIncluded, + )>, + ) -> anyhow::Result<()> { + let chunks_duplicate = chunks + .iter() + .filter(|(_chunk_hash, _shard_id, height_included)| height_included != &block_height) + .collect::>(); + if !chunks_duplicate.is_empty() { + crate::metrics::META_DATABASE_WRITE_QUERIES + .with_label_values(&["save_chunks", "chunks_duplicate"]) + .inc(); + let mut query_builder: sqlx::QueryBuilder = + sqlx::QueryBuilder::new("INSERT INTO chunks_duplicate (chunk_hash, block_height, shard_id, included_in_block_height) "); + + query_builder.push_values( + chunks.iter(), + |mut values, (chunk_hash, shard_id, height_included)| { + values + .push_bind(chunk_hash.to_string()) + .push_bind(bigdecimal::BigDecimal::from(block_height)) + .push_bind(bigdecimal::BigDecimal::from(*shard_id)) + .push_bind(bigdecimal::BigDecimal::from(*height_included)); + }, + ); + query_builder.push(" ON CONFLICT DO NOTHING;"); + query_builder.build().execute(&self.meta_db_pool).await?; + } + Ok(()) + } +} +#[async_trait::async_trait] +impl crate::StateIndexerDbManager for crate::PostgresDBManager { + async fn save_block( + &self, + block_height: u64, + block_hash: near_primitives::hash::CryptoHash, + ) -> anyhow::Result<()> { + crate::metrics::META_DATABASE_WRITE_QUERIES + .with_label_values(&["save_block", "blocks"]) + .inc(); + sqlx::query( + " + INSERT INTO blocks (block_height, block_hash) + VALUES ($1, $2) ON CONFLICT DO NOTHING; + ", + ) + .bind(bigdecimal::BigDecimal::from(block_height)) + .bind(block_hash.to_string()) + .execute(&self.meta_db_pool) + .await?; + Ok(()) + } + + async fn save_chunks( + &self, + block_height: u64, + chunks: Vec<( + crate::primitives::ChunkHash, + crate::primitives::ShardId, + crate::primitives::HeightIncluded, + )>, + ) -> anyhow::Result<()> { + let save_chunks_unique_future = self.save_chunks_unique(block_height, chunks.clone()); + let save_chunks_duplicate_future = self.save_chunks_duplicate(block_height, chunks); + + futures::future::join_all([ + save_chunks_unique_future.boxed(), + save_chunks_duplicate_future.boxed(), + ]) + .await + .into_iter() + .collect::>() + } + + async fn get_block_height_by_hash( + &self, + block_hash: near_primitives::hash::CryptoHash, + method_name: &str, + ) -> anyhow::Result { + crate::metrics::META_DATABASE_READ_QUERIES + .with_label_values(&[method_name, "blocks"]) + .inc(); + let (block_height,): (bigdecimal::BigDecimal,) = sqlx::query_as( + " + SELECT block_height + FROM blocks + WHERE block_hash = $1 + LIMIT 1; + ", + ) + .bind(block_hash.to_string()) + .fetch_one(&self.meta_db_pool) + .await?; + block_height + .to_u64() + .ok_or_else(|| anyhow::anyhow!("Failed to parse `block_height` to u64")) + } + + async fn update_meta(&self, indexer_id: &str, block_height: u64) -> anyhow::Result<()> { + crate::metrics::META_DATABASE_WRITE_QUERIES + .with_label_values(&["update_meta", "meta"]) + .inc(); + sqlx::query( + " + INSERT INTO meta (indexer_id, last_processed_block_height) + VALUES ($1, $2) + ON CONFLICT (indexer_id) + DO UPDATE SET last_processed_block_height = $2; + ", + ) + .bind(indexer_id) + .bind(bigdecimal::BigDecimal::from(block_height)) + .execute(&self.meta_db_pool) + .await?; + Ok(()) + } + + async fn get_last_processed_block_height(&self, indexer_id: &str) -> anyhow::Result { + crate::metrics::META_DATABASE_READ_QUERIES + .with_label_values(&["get_last_processed_block_height", "meta"]) + .inc(); + let (last_processed_block_height,): (bigdecimal::BigDecimal,) = sqlx::query_as( + " + SELECT last_processed_block_height + FROM meta + WHERE indexer_id = $1 + LIMIT 1; + ", + ) + .bind(indexer_id) + .fetch_one(&self.meta_db_pool) + .await?; + last_processed_block_height + .to_u64() + .ok_or_else(|| anyhow::anyhow!("Failed to parse `last_processed_block_height` to u64")) + } + + async fn save_validators( + &self, + epoch_id: near_primitives::hash::CryptoHash, + epoch_height: u64, + epoch_start_height: u64, + validators_info: &near_primitives::views::EpochValidatorInfo, + epoch_end_block_hash: near_primitives::hash::CryptoHash, + ) -> anyhow::Result<()> { + crate::metrics::META_DATABASE_WRITE_QUERIES + .with_label_values(&["add_validators", "validators"]) + .inc(); + let epoch_end_block_height = self + .get_block_height_by_hash(epoch_end_block_hash, "add_validators") + .await?; + sqlx::query( + " + INSERT INTO validators (epoch_id, epoch_height, epoch_start_height, epoch_end_height, validators_info) + VALUES ($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING; + " + ) + .bind(epoch_id.to_string()) + .bind(bigdecimal::BigDecimal::from(epoch_height)) + .bind(bigdecimal::BigDecimal::from(epoch_start_height)) + .bind(bigdecimal::BigDecimal::from(epoch_end_block_height)) + .bind(&serde_json::to_value(validators_info)?) + .execute(&self.meta_db_pool) + .await?; + Ok(()) + } + + async fn insert_state_changes_data( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + self.record_shard_write_metric(shard_id, "save_state_changes_data", "state_changes_data"); + + // Extract relevant data + let inserts: Vec<(String, String, Vec, i64)> = state_changes + .iter() + .filter_map(|change| { + if let near_primitives::views::StateChangeValueView::DataUpdate { + account_id, + key, + value, + } = &change.value + { + let data_key: String = hex::encode(key.as_slice()); + Some(( + account_id.to_string(), + data_key, + value.clone().to_vec(), + block_height as i64, // Convert to i64 for database compatibility + )) + } else { + None + } + }) + .collect(); + + // Use the standard insert helper + self.execute_partitioned_standard_insert( + shard_id, + "state_changes_data_compact".to_string(), + "insert_state_changes_data".to_string(), + inserts, + ) + .await + } + + async fn update_state_changes_data( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + self.record_shard_write_metric(shard_id, "save_state_changes_data", "state_changes_data"); + + let updates: Vec<(String, String, i64)> = + state_changes + .iter() + .filter_map(|change| match &change.value { + near_primitives::views::StateChangeValueView::DataUpdate { + account_id, + key, + .. + } + | near_primitives::views::StateChangeValueView::DataDeletion { + account_id, + key, + } => { + let data_key: &[u8] = key.as_ref(); + let data_key = hex::encode(data_key).to_string(); + Some(( + account_id.to_string(), + data_key, + block_height as i64, // Convert to i64 for database compatibility + )) + } + _ => None, + }) + .collect(); + + // Use the key-based update helper that preserves all complex AND conditions + // This uses CTE pattern because data updates can have varying block heights + // and need the full 4-condition WHERE clause for data integrity + self.execute_partitioned_key_update( + shard_id, + "state_changes_data_compact".to_string(), + "update_state_changes_data".to_string(), + updates, + ) + .await + } + + async fn insert_state_changes_access_key( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + let overall_start = Instant::now(); + self.record_shard_write_metric( + shard_id, + "save_state_changes_access_key", + "state_changes_access_key", + ); + + // Extract relevant updates + let inserts: Vec<(String, String, Vec, i64)> = state_changes + .iter() + .filter_map(|change| { + if let near_primitives::views::StateChangeValueView::AccessKeyUpdate { + account_id, + public_key, + access_key, + } = &change.value + { + let data_key = hex::encode( + borsh::to_vec(public_key).expect("Failed to borsh serialize public key"), + ); + let data_value = + borsh::to_vec(access_key).expect("Failed to borsh serialize access key"); + Some(( + account_id.to_string(), + data_key, + data_value, + block_height as i64, // Convert to i64 for database compatibility + )) + } else { + None + } + }) + .collect(); + + // Use the standard insert helper + self.execute_partitioned_standard_insert( + shard_id, + "state_changes_access_key_compact".to_string(), + "insert_access_key".to_string(), + inserts, + ) + .await?; + + tracing::debug!( + target: "database::postgres::state_indexer", + "Total insert_state_changes_access_key duration shard={} elapsed={:?}", + shard_id, + overall_start.elapsed() + ); + + Ok(()) + } + + // TODO: provide docstring + async fn update_state_changes_access_key( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + self.record_shard_write_metric( + shard_id, + "save_state_changes_access_key", + "state_changes_access_key", + ); + + // Collect updates as triples (account_id, data_key, block_height) + let block_height_bd = block_height as i64; // Convert to i64 for database compatibility + let updates: Vec<(String, String, i64)> = state_changes + .iter() + .filter_map(|c| match &c.value { + near_primitives::views::StateChangeValueView::AccessKeyUpdate { + account_id, + public_key, + .. + } + | near_primitives::views::StateChangeValueView::AccessKeyDeletion { + account_id, + public_key, + } => Some(( + account_id.to_string(), + hex::encode(public_key.key_data()), + block_height_bd, // same height for all rows + )), + _ => None, + }) + .collect(); + + if updates.is_empty() { + return Ok(()); + } + + // Delegate to the same partitioned update helper + self.execute_partitioned_key_update( + shard_id, + "state_changes_access_key_compact".to_string(), + "update_state_changes_access_key".to_string(), + updates, + ) + .await + } + + async fn insert_state_changes_contract( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + let overall_start = Instant::now(); + self.record_shard_write_metric( + shard_id, + "save_state_changes_contract", + "state_changes_contract", + ); + + // Extract only ContractCodeUpdate + let inserts: Vec<(String, Vec, i64)> = state_changes + .into_iter() + .filter_map(|change| { + if let near_primitives::views::StateChangeValueView::ContractCodeUpdate { + account_id, + code, + } = change.value + { + Some((account_id.to_string(), code.to_vec(), block_height as i64)) + } else { + None + } + }) + .collect(); + + // Use the keyless insert helper (3-column) + self.execute_partitioned_keyless_insert( + shard_id, + "state_changes_contract_compact".to_string(), + "insert_contract".to_string(), + inserts, + ) + .await?; + + tracing::debug!( + target: "database::postgres::state_indexer", + "Total insert_state_changes_contract duration shard={} elapsed={:?}", + shard_id, + overall_start.elapsed() + ); + + Ok(()) + } + + /// Update contract state changes with partitions under semaphore + async fn update_state_changes_contract( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + let overall_start = Instant::now(); + self.record_shard_write_metric( + shard_id, + "save_state_changes_contract", + "state_changes_contract", + ); + + // Collect account_ids for updates + let accounts: Vec = state_changes + .into_iter() + .filter_map(|change| match change.value { + near_primitives::views::StateChangeValueView::ContractCodeUpdate { + account_id, + .. + } + | near_primitives::views::StateChangeValueView::ContractCodeDeletion { + account_id, + } => Some(account_id.to_string()), + _ => None, + }) + .collect(); + crate::metrics::AFFECTED_ACCOUNTS_COUNT + .with_label_values(&[ + &shard_id.to_string(), + "update_state_changes_contract", + &accounts.len().to_string(), + ]) + .inc(); + + // Use the account-only update helper + self.execute_partitioned_account_update( + shard_id, + "state_changes_contract_compact".to_string(), + "update_contract".to_string(), + accounts, + block_height, + ) + .await?; + + tracing::debug!( + target: "database::postgres::state_indexer", + "Total update_state_changes_contract duration shard={} elapsed={:?}", + shard_id, + overall_start.elapsed() + ); + + Ok(()) + } + + async fn insert_state_changes_account( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + let overall_start = Instant::now(); + self.record_shard_write_metric( + shard_id, + "save_state_changes_account", + "state_changes_account", + ); + + // Extract account updates + let inserts: Vec<(String, Vec, i64)> = state_changes + .into_iter() + .filter_map(|change| { + if let near_primitives::views::StateChangeValueView::AccountUpdate { + account_id, + account, + } = change.value + { + let data_value = + borsh::to_vec(&near_primitives::account::Account::from(&account)) + .expect("Failed to borsh serialize account"); + Some(( + account_id.to_string(), + data_value, + block_height as i64, // Convert to i64 for database compatibility + )) + } else { + None + } + }) + .collect(); + + // Use the keyless insert helper (3-column) + self.execute_partitioned_keyless_insert( + shard_id, + "state_changes_account_compact".to_string(), + "insert_account".to_string(), + inserts, + ) + .await?; + + tracing::debug!( + target: "database::postgres::state_indexer", + "Total insert_state_changes_account duration shard={} elapsed={:?}", + shard_id, + overall_start.elapsed() + ); + + Ok(()) + } + + /// Update Account state changes using partitions + concurrency limit + async fn update_state_changes_account( + &self, + shard_id: near_primitives::types::ShardId, + state_changes: Vec, + block_height: u64, + ) -> anyhow::Result<()> { + let overall_start = Instant::now(); + self.record_shard_write_metric( + shard_id, + "save_state_changes_account", + "state_changes_account", + ); + + // Collect accounts for update + let accounts: Vec = state_changes + .into_iter() + .filter_map(|change| match change.value { + near_primitives::views::StateChangeValueView::AccountUpdate { + account_id, .. + } + | near_primitives::views::StateChangeValueView::AccountDeletion { account_id } => { + Some(account_id.to_string()) + } + _ => None, + }) + .collect(); + crate::metrics::AFFECTED_ACCOUNTS_COUNT + .with_label_values(&[ + &shard_id.to_string(), + "update_state_changes_account", + &accounts.len().to_string(), + ]) + .inc(); + + // Use the account-only update helper + self.execute_partitioned_account_update( + shard_id, + "state_changes_account_compact".to_string(), + "update_account".to_string(), + accounts, + block_height, + ) + .await?; + + tracing::debug!( + target: "database::postgres::state_indexer", + "Total update_state_changes_account duration shard={} elapsed={:?}", + shard_id, + overall_start.elapsed() + ); + + Ok(()) + } +} diff --git a/database/src/postgres/tx_indexer.rs b/database/src/postgres/tx_indexer.rs new file mode 100644 index 00000000..2597a04b --- /dev/null +++ b/database/src/postgres/tx_indexer.rs @@ -0,0 +1,187 @@ +use anyhow::Result; +use async_trait::async_trait; +use bigdecimal::num_traits::ToPrimitive; +use bigdecimal::BigDecimal; +use sqlx::QueryBuilder; + +#[async_trait] +impl crate::base::tx_indexer::TxIndexerDbManager for crate::postgres::PostgresDBManager { + async fn create_tx_tables(&self) -> Result<()> { + // For POstgres please read the `README.md` in the `database/src/postgres` directory. + // The tables are created by the migrations, so this method is not needed. + Ok(()) + } + + async fn save_transaction( + &self, + sender_id: &near_primitives::types::AccountId, + key: &str, + data: Vec, + block_height: u64, + ) -> Result<()> { + let shard_conn = self.get_shard_connection(sender_id).await?; + sqlx::query( + " + INSERT INTO transactions (transaction_hash, sender_account_id, block_height, transaction_details) + VALUES ($1, $2, $3, $4) + ON CONFLICT (transaction_hash) DO NOTHING; + ", + ) + .bind(key) + .bind(sender_id.as_str()) + .bind(BigDecimal::from(block_height)) + .bind(data) + .execute(shard_conn.pool) + .await?; + Ok(()) + } + + async fn retrieve_transaction( + &self, + key: &str, + shard_id: &near_primitives::types::ShardId, + ) -> Result> { + let shard_connection = self.get_shard_connection_by_id(shard_id).await?; + let (data,): (Vec,) = sqlx::query_as( + " + SELECT transaction_details + FROM transactions + WHERE transaction_hash = $1 + LIMIT 1; + ", + ) + .bind(key) + .fetch_one(shard_connection.pool) + .await?; + + Ok(data) + } + + async fn save_receipts(&self, receipts: Vec) -> Result<()> { + if receipts.is_empty() { + return Ok(()); + } + + let mut builder = QueryBuilder::new( + "INSERT INTO receipts (receipt_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id) " + ); + builder.push_values(receipts.iter(), |mut b, receipt| { + let shard_id: u64 = receipt.shard_id.into(); + b.push_bind(receipt.receipt_id.to_string()) + .push_bind(receipt.parent_transaction_hash.to_string()) + .push_bind(receipt.receiver_id.to_string()) + .push_bind(BigDecimal::from(receipt.block_height)) + .push_bind(receipt.block_hash.to_string()) + .push_bind(BigDecimal::from(shard_id)); + }); + builder.push(" ON CONFLICT DO NOTHING"); + + builder.build().execute(&self.meta_db_pool).await?; + Ok(()) + } + + async fn get_receipt_by_id( + &self, + receipt_id: &str, + ) -> Result { + let row: (String, String, String, BigDecimal, String, BigDecimal) = sqlx::query_as( + " + SELECT receipt_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id + FROM receipts + WHERE receipt_id = $1 + LIMIT 1; + ", + ) + .bind(receipt_id) + .fetch_one(&self.meta_db_pool) + .await?; + + readnode_primitives::ReceiptRecord::try_from(row) + } + + async fn save_outcomes(&self, outcomes: Vec) -> Result<()> { + if outcomes.is_empty() { + return Ok(()); + } + + let mut builder = QueryBuilder::new( + "INSERT INTO outcomes (outcome_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id) " + ); + builder.push_values(outcomes.iter(), |mut b, outcome| { + let shard_id: u64 = outcome.shard_id.into(); + b.push_bind(outcome.outcome_id.to_string()) + .push_bind(outcome.parent_transaction_hash.to_string()) + .push_bind(outcome.receiver_id.to_string()) + .push_bind(BigDecimal::from(outcome.block_height)) + .push_bind(outcome.block_hash.to_string()) + .push_bind(BigDecimal::from(shard_id)); + }); + builder.push(" ON CONFLICT (outcome_id) DO NOTHING;"); + + builder.build().execute(&self.meta_db_pool).await?; + Ok(()) + } + + async fn get_outcome_by_id( + &self, + outcome_id: &str, + ) -> Result { + let row: (String, String, String, BigDecimal, String, BigDecimal) = sqlx::query_as( + " + SELECT outcome_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id + FROM outcomes + WHERE outcome_id = $1 + LIMIT 1; + ", + ) + .bind(outcome_id) + .fetch_one(&self.meta_db_pool) + .await?; + + readnode_primitives::OutcomeRecord::try_from(row) + } + + async fn update_meta(&self, indexer_id: &str, last_processed_block_height: u64) -> Result<()> { + sqlx::query( + " + INSERT INTO meta (indexer_id, last_processed_block_height) + VALUES ($1, $2) + ON CONFLICT (indexer_id) + DO UPDATE SET last_processed_block_height = $2; + ", + ) + .bind(indexer_id) + .bind(BigDecimal::from(last_processed_block_height)) + .execute(&self.meta_db_pool) + .await?; + Ok(()) + } + + async fn get_last_processed_block_height(&self, indexer_id: &str) -> Result { + let (height,): (BigDecimal,) = sqlx::query_as( + " + SELECT last_processed_block_height + FROM meta + WHERE indexer_id = $1 + LIMIT 1; + ", + ) + .bind(indexer_id) + .fetch_one(&self.meta_db_pool) + .await?; + + height + .to_u64() + .ok_or_else(|| anyhow::anyhow!("Failed to convert last_processed_block_height to u64")) + } + + async fn save_outcomes_and_receipts( + &self, + receipts: Vec, + outcomes: Vec, + ) -> Result<()> { + self.save_receipts(receipts).await?; + self.save_outcomes(outcomes).await?; + Ok(()) + } +} diff --git a/database/src/scylla/mod.rs b/database/src/scylla/mod.rs new file mode 100644 index 00000000..b0b9bcdb --- /dev/null +++ b/database/src/scylla/mod.rs @@ -0,0 +1 @@ +pub mod tx_indexer; diff --git a/database/src/scylla/tx_indexer.rs b/database/src/scylla/tx_indexer.rs new file mode 100644 index 00000000..cc60fb6c --- /dev/null +++ b/database/src/scylla/tx_indexer.rs @@ -0,0 +1,307 @@ +// ScyllaDB manager for transaction, receipt, and outcome storage +// All ScyllaDB-specific logic will be implemented here + +use crate::base::tx_indexer::TxIndexerDbManager; +use anyhow::Result; +use async_trait::async_trait; +use futures::FutureExt; +use num_traits::cast::ToPrimitive; + +pub struct ScyllaDBManager { + add_transaction: scylla::prepared_statement::PreparedStatement, + get_transaction: scylla::prepared_statement::PreparedStatement, + add_receipt: scylla::prepared_statement::PreparedStatement, + get_receipt: scylla::prepared_statement::PreparedStatement, + add_outcome: scylla::prepared_statement::PreparedStatement, + get_outcome: scylla::prepared_statement::PreparedStatement, + update_meta: scylla::prepared_statement::PreparedStatement, + last_processed_block_height: scylla::prepared_statement::PreparedStatement, + scylla_session: scylla::Session, +} + +impl ScyllaDBManager { + pub async fn new(scylla_session: scylla::Session) -> anyhow::Result { + Self::create_keyspace(&scylla_session).await?; + Self::create_table(&scylla_session).await?; + Ok(Self { + add_transaction: Self::prepare_query( + &scylla_session, + "INSERT INTO tx_details.transactions + (transaction_hash, transaction_details) + VALUES(?, ?)", + scylla::frame::types::Consistency::LocalQuorum, + ).await?, + get_transaction: Self::prepare_query( + &scylla_session, + "SELECT transaction_details FROM tx_details.transactions WHERE transaction_hash = ? LIMIT 1", + scylla::frame::types::Consistency::LocalOne, + ).await?, + add_receipt: Self::prepare_query( + &scylla_session, + "INSERT INTO tx_details.receipts_map + (receipt_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id) + VALUES(?, ?, ?, ?, ?, ?)", + scylla::frame::types::Consistency::LocalQuorum, + ).await?, + get_receipt: Self::prepare_query( + &scylla_session, + "SELECT receipt_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id FROM tx_details.receipts_map WHERE receipt_id = ? LIMIT 1", + scylla::frame::types::Consistency::LocalOne, + ).await?, + add_outcome: Self::prepare_query( + &scylla_session, + "INSERT INTO tx_details.outcomes_map + (outcome_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id) + VALUES(?, ?, ?, ?, ?, ?)", + scylla::frame::types::Consistency::LocalQuorum, + ).await?, + get_outcome: Self::prepare_query( + &scylla_session, + "SELECT outcome_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id FROM tx_details.outcomes_map WHERE outcome_id = ? LIMIT 1", + scylla::frame::types::Consistency::LocalOne, + ).await?, + update_meta: Self::prepare_query( + &scylla_session, + "INSERT INTO tx_details.meta + (indexer_id, last_processed_block_height) + VALUES (?, ?)", + scylla::frame::types::Consistency::LocalQuorum, + ).await?, + last_processed_block_height: Self::prepare_query( + &scylla_session, + "SELECT last_processed_block_height FROM tx_details.meta WHERE indexer_id = ? LIMIT 1", + scylla::frame::types::Consistency::LocalOne, + ).await?, + scylla_session, + }) + } + + async fn prepare_query( + scylla_db_session: &scylla::Session, + query_text: &str, + consistency: scylla::frame::types::Consistency, + ) -> anyhow::Result { + let mut query = scylla::statement::query::Query::new(query_text); + query.set_consistency(consistency); + Ok(scylla_db_session.prepare(query).await?) + } + + pub async fn create_keyspace(scylla_session: &scylla::Session) -> anyhow::Result<()> { + scylla_session + .query_unpaged( + "CREATE KEYSPACE IF NOT EXISTS tx_details + WITH REPLICATION = { + 'class': 'NetworkTopologyStrategy', + 'replication_factor': 3 + }", + &[], + ) + .await?; + Ok(()) + } + + pub async fn create_table(scylla_session: &scylla::Session) -> anyhow::Result<()> { + scylla_session + .query_unpaged( + "CREATE TABLE IF NOT EXISTS tx_details.transactions ( + transaction_hash varchar PRIMARY KEY, + transaction_details BLOB + )", + &[], + ) + .await?; + scylla_session + .query_unpaged( + "CREATE TABLE IF NOT EXISTS tx_details.receipts_map ( + receipt_id varchar PRIMARY KEY, + parent_transaction_hash varchar, + receiver_id varchar, + block_height varint, + block_hash varchar, + shard_id varint + )", + &[], + ) + .await?; + scylla_session + .query_unpaged( + "CREATE TABLE IF NOT EXISTS tx_details.outcomes_map ( + outcome_id varchar PRIMARY KEY, + parent_transaction_hash varchar, + receiver_id varchar, + block_height varint, + block_hash varchar, + shard_id varint + )", + &[], + ) + .await?; + scylla_session + .query_unpaged( + "CREATE TABLE IF NOT EXISTS tx_details.meta ( + indexer_id varchar PRIMARY KEY, + last_processed_block_height varint + )", + &[], + ) + .await?; + Ok(()) + } +} + +#[async_trait] +impl TxIndexerDbManager for ScyllaDBManager { + async fn create_tx_tables(&self) -> Result<()> { + Self::create_keyspace(&self.scylla_session).await?; + Self::create_table(&self.scylla_session).await + } + + async fn save_transaction( + &self, + _sender_id: &near_primitives::types::AccountId, + key: &str, + data: Vec, + _block_height: u64, + ) -> Result<()> { + self.scylla_session + .execute_unpaged(&self.add_transaction, (key, data)) + .await?; + Ok(()) + } + + async fn retrieve_transaction( + &self, + key: &str, + _shard_id: &near_primitives::types::ShardId, + ) -> Result> { + let (data,) = self + .scylla_session + .execute_unpaged(&self.get_transaction, (key.to_string(),)) + .await? + .into_rows_result()? + .single_row::<(Vec,)>()?; + Ok(data) + } + + async fn save_receipts(&self, receipts: Vec) -> Result<()> { + if receipts.is_empty() { + return Ok(()); + } + let mut batch: scylla::batch::Batch = Default::default(); + let mut batch_values = Vec::new(); + for receipt in receipts { + batch.append_statement(self.add_receipt.clone()); + let shard_id: u64 = receipt.shard_id.into(); + batch_values.push(( + receipt.receipt_id.to_string(), + receipt.parent_transaction_hash.to_string(), + receipt.receiver_id.to_string(), + num_bigint::BigInt::from(receipt.block_height), + receipt.block_hash.to_string(), + num_bigint::BigInt::from(shard_id), + )); + } + self.scylla_session.batch(&batch, batch_values).await?; + Ok(()) + } + + async fn get_receipt_by_id( + &self, + receipt_id: &str, + ) -> Result { + readnode_primitives::ReceiptRecord::try_from( + self.scylla_session + .execute_unpaged(&self.get_receipt, (receipt_id.to_string(),)) + .await? + .into_rows_result()? + .single_row::<( + String, + String, + String, + num_bigint::BigInt, + String, + num_bigint::BigInt, + )>()?, + ) + } + + async fn save_outcomes(&self, outcomes: Vec) -> Result<()> { + if outcomes.is_empty() { + return Ok(()); + } + let mut batch: scylla::batch::Batch = Default::default(); + let mut batch_values = Vec::new(); + for outcome in outcomes { + batch.append_statement(self.add_outcome.clone()); + let shard_id: u64 = outcome.shard_id.into(); + batch_values.push(( + outcome.outcome_id.to_string(), + outcome.parent_transaction_hash.to_string(), + outcome.receiver_id.to_string(), + num_bigint::BigInt::from(outcome.block_height), + outcome.block_hash.to_string(), + num_bigint::BigInt::from(shard_id), + )); + } + self.scylla_session.batch(&batch, batch_values).await?; + Ok(()) + } + + async fn get_outcome_by_id( + &self, + outcome_id: &str, + ) -> Result { + readnode_primitives::OutcomeRecord::try_from( + self.scylla_session + .execute_unpaged(&self.get_outcome, (outcome_id.to_string(),)) + .await? + .into_rows_result()? + .single_row::<( + String, + String, + String, + num_bigint::BigInt, + String, + num_bigint::BigInt, + )>()?, + ) + } + + async fn update_meta(&self, indexer_id: &str, last_processed_block_height: u64) -> Result<()> { + self.scylla_session + .execute_unpaged( + &self.update_meta, + ( + indexer_id.to_string(), + num_bigint::BigInt::from(last_processed_block_height), + ), + ) + .await?; + Ok(()) + } + + async fn get_last_processed_block_height(&self, indexer_id: &str) -> Result { + let (last_processed_block_height,) = self + .scylla_session + .execute_unpaged(&self.last_processed_block_height, (indexer_id.to_string(),)) + .await? + .into_rows_result()? + .single_row::<(num_bigint::BigInt,)>()?; + last_processed_block_height.to_u64().ok_or(anyhow::anyhow!( + "Failed to convert last_processed_block_height to u64" + )) + } + + async fn save_outcomes_and_receipts( + &self, + receipts: Vec, + outcomes: Vec, + ) -> anyhow::Result<()> { + let save_outcome_future = self.save_outcomes(outcomes); + let save_receipt_future = self.save_receipts(receipts); + futures::future::join_all([save_outcome_future.boxed(), save_receipt_future.boxed()]) + .await + .into_iter() + .collect::>() + } +} diff --git a/docs/CUSTOM_RPC_METHODS.md b/docs/CUSTOM_RPC_METHODS.md index 33927ed9..de66fe1b 100644 --- a/docs/CUSTOM_RPC_METHODS.md +++ b/docs/CUSTOM_RPC_METHODS.md @@ -116,3 +116,51 @@ Response: } } ``` + +# emulate_tx + +The `emulate_tx` method is a custom method that allows you to estimate transaction costs and simulate its execution without actually sending it to the network. For now simulation supports only `FunctionCall` action, for other actions it will return only estimate fee. + +## How to use it +### Example + +Request: +```json +{ + "jsonrpc": "2.0", + "id": "dontcare", + "method": "emulate_tx", + "params": { + "signed_tx_base64": "DgAAAHNlbmRlci50ZXN0bmV0AOrmAai64SZOv9e/naX4W15pJx0GAap35wTT1T/DwcbbDwAAAAAAAAAQAAAAcmVjZWl2ZXIudGVzdG5ldNMnL7URB1cxPOu3G8jTqlEwlcasagIbKlAJlF5ywVFLAQAAAAMAAACh7czOG8LTAAAAAAAAAGQcOG03xVSFQFjoagOb4NBBqWhERnnz45LY4+52JgZhm1iQKz7qAdPByrGFDQhQ2Mfga8RlbysuQ8D8LlA6bQE=", + "wait_until": "INCLUDED_FINAL" + } +} +``` +or +```json +{ + "jsonrpc": "2.0", + "id": "dontcare", + "method": "emulate_tx", + "params": [ "DgAAAHNlbmRlci50ZXN0bmV0AOrmAai64SZOv9e/naX4W15pJx0GAap35wTT1T/DwcbbDwAAAAAAAAAQAAAAcmVjZWl2ZXIudGVzdG5ldNMnL7URB1cxPOu3G8jTqlEwlcasagIbKlAJlF5ywVFLAQAAAAMAAACh7czOG8LTAAAAAAAAAGQcOG03xVSFQFjoagOb4NBBqWhERnnz45LY4+52JgZhm1iQKz7qAdPByrGFDQhQ2Mfga8RlbysuQ8D8LlA6bQE=" + ] +} +``` +Response: +```json +{ + "jsonrpc": "2.0", + "result": { + "block_height": 156743532, + "gas_price": 100000000, + "results": [ + { + "Transfer": { + "fee": 115123062500 + } + } + ] + }, + "id": "dontcare" +} +``` diff --git a/docs/DATABASE_MIGRATIONS.md b/docs/DATABASE_MIGRATIONS.md new file mode 100644 index 00000000..24858ea1 --- /dev/null +++ b/docs/DATABASE_MIGRATIONS.md @@ -0,0 +1,388 @@ +# Database Migrations with SQLx + +This document provides a comprehensive guide for managing database migrations in the NEAR Read RPC project using SQLx. + +## Overview + +The NEAR Read RPC project uses PostgreSQL databases with SQLx for migration management. The project has three distinct database types: + +1. **Meta Database** - Stores blocks, chunks, validator metadata, and receipts/outcomes +2. **Shard Databases** - Stores state changes, partition-specific data, and transactions +3. **Transaction Details** - Split between meta database (receipts/outcomes) and shard databases (transactions) + +## Database Structure + +``` +database/src/postgres/migrations/ +├── meta_db/ # Meta database migrations (blocks, chunks, validators, receipts/outcomes) +├── shard_db/ # Shard database migrations (state changes, transactions) +└── tx_details/ # Transaction details database migrations + ├── receipts_and_outcomes/ # Applied to meta database + └── transactions/ # Applied to shard databases +``` + +## Prerequisites + +### Install SQLx CLI + +```bash +cargo install sqlx-cli --no-default-features --features native-tls,postgres +``` + +### Environment Variables + +Set up the required database connection URLs: + +```bash +# Meta database +export META_DATABASE_URL="postgresql://username:password@localhost:5432/meta_db" + +# Shard databases (one per shard) +export SHARD_0_DATABASE_URL="postgresql://username:password@localhost:5432/shard_0_db" +export SHARD_1_DATABASE_URL="postgresql://username:password@localhost:5432/shard_1_db" +# ... additional shards as needed +``` + +## Migration Management + +### Creating New Migrations + +#### 1. Meta Database Migrations + +```bash +# Navigate to meta database migrations directory +cd database/src/postgres/migrations/meta_db + +# Create a new migration +sqlx migrate add -r +``` + +Example: +```bash +sqlx migrate add -r add_new_index_to_blocks +``` + +#### 2. Shard Database Migrations + +```bash +# Navigate to shard database migrations directory +cd database/src/postgres/migrations/shard_db + +# Create a new migration +sqlx migrate add -r +``` + +Example: +```bash +sqlx migrate add -r optimize_state_changes_table +``` + +#### 3. Transaction Details Migrations + +Transaction details are split between different databases: + +**For Receipts and Outcomes (Meta Database):** +```bash +# Navigate to receipts and outcomes migrations directory +cd database/src/postgres/migrations/tx_details/receipts_and_outcomes + +# Create a new migration for receipts and outcomes +sqlx migrate add -r +``` + +**For Transactions (Shard Databases):** +```bash +# Navigate to transactions migrations directory +cd database/src/postgres/migrations/tx_details/transactions + +# Create a new migration for transactions +sqlx migrate add -r +``` + +### Applying Migrations + +#### 1. Meta Database + +```bash +# Set the database URL +export DATABASE_URL=$META_DATABASE_URL + +# Run migrations +cd database/src/postgres/migrations/meta_db +sqlx migrate run +``` + +#### 2. Shard Databases + +Apply migrations to each shard database: + +```bash +# For each shard +export DATABASE_URL=$SHARD_0_DATABASE_URL +cd database/src/postgres/migrations/shard_db +sqlx migrate run + +export DATABASE_URL=$SHARD_1_DATABASE_URL +sqlx migrate run + +# Repeat for all shards... +``` + +#### 3. Transaction Details Migrations + +Transaction details migrations are applied to different databases: + +```bash +# Receipts and outcomes migrations (applied to META database) +export DATABASE_URL=$META_DATABASE_URL +cd database/src/postgres/migrations/tx_details/receipts_and_outcomes +sqlx migrate run + +# Transactions migrations (applied to SHARD databases) +export DATABASE_URL=$SHARD_0_DATABASE_URL +cd ../transactions +sqlx migrate run + +export DATABASE_URL=$SHARD_1_DATABASE_URL +sqlx migrate run + +# Repeat for all shards... +``` + +### Migration Scripts for Automation + +Create convenience scripts to manage all databases at once: + +#### Apply All Migrations Script + +```bash +#!/bin/bash +# save as: scripts/apply_all_migrations.sh + +set -e + +echo "Applying migrations to Meta Database..." +export DATABASE_URL=$META_DATABASE_URL +cd database/src/postgres/migrations/meta_db +sqlx migrate run + +# Apply receipts and outcomes migrations to Meta Database +echo "Applying receipts and outcomes migrations to Meta Database..." +cd ../tx_details/receipts_and_outcomes +sqlx migrate run + +echo "Applying migrations to Shard Databases..." +for shard_url in $SHARD_0_DATABASE_URL $SHARD_1_DATABASE_URL $SHARD_2_DATABASE_URL $SHARD_3_DATABASE_URL $SHARD_4_DATABASE_URL $SHARD_5_DATABASE_URL; do + if [ ! -z "$shard_url" ]; then + echo "Migrating shard: $shard_url" + export DATABASE_URL=$shard_url + + # Apply shard database migrations + cd ../../shard_db + sqlx migrate run + + # Apply transactions migrations to each shard + cd ../tx_details/transactions + sqlx migrate run + fi +done + +echo "All migrations applied successfully!" +``` + +### Checking Migration Status + +#### View Applied Migrations + +```bash +# Set appropriate DATABASE_URL for the target database +export DATABASE_URL=$META_DATABASE_URL + +# Navigate to migrations directory +cd database/src/postgres/migrations/meta_db + +# Check migration status +sqlx migrate info +``` + +#### View Migration History + +```bash +# Show detailed migration history +sqlx migrate info --verbose +``` + +### Rolling Back Migrations + +#### Revert Last Migration + +```bash +# Set appropriate DATABASE_URL +export DATABASE_URL=$META_DATABASE_URL + +# Navigate to migrations directory +cd database/src/postgres/migrations/meta_db + +# Revert the last migration +sqlx migrate revert +``` + +#### Revert to Specific Version + +```bash +# Revert to a specific migration version +sqlx migrate revert --target-version +``` + +## Database Setup from Scratch + +### 1. Create Databases + +```sql +-- Connect to PostgreSQL as superuser +CREATE DATABASE meta_db; +CREATE DATABASE shard_0_db; +CREATE DATABASE shard_1_db; +-- ... create additional shard databases as needed +``` + +### 2. Apply All Migrations + +```bash +# Use the apply_all_migrations.sh script +chmod +x scripts/apply_all_migrations.sh +./scripts/apply_all_migrations.sh +``` + +## Migration Best Practices + +### 1. Migration File Naming + +SQLx uses timestamp-based naming: +``` +YYYYMMDDHHMMSS_migration_name.up.sql +YYYYMMDDHHMMSS_migration_name.down.sql +``` + +### 2. Writing Safe Migrations + +- Always test migrations on a copy of production data +- Use `IF EXISTS` and `IF NOT EXISTS` clauses where appropriate +- Make migrations atomic and reversible +- Include proper indexes for performance + +Example migration: +```sql +-- up.sql +CREATE TABLE IF NOT EXISTS new_table ( + id BIGSERIAL PRIMARY KEY, + data JSONB NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_new_table_created_at ON new_table(created_at); + +-- down.sql +DROP INDEX IF EXISTS idx_new_table_created_at; +DROP TABLE IF EXISTS new_table; +``` + +### 3. Large Table Migrations + +For large tables, consider: +- Creating new tables and migrating data in batches +- Using `CONCURRENTLY` for index creation +- Planning for downtime if necessary + +### 4. Data Migrations + +When migrating data, use transactions and include rollback logic: + +```sql +-- up.sql +BEGIN; + +-- Migration logic here +UPDATE existing_table SET new_column = 'default_value' WHERE new_column IS NULL; + +COMMIT; +``` + +## Troubleshooting + +### Common Issues + +1. **Migration fails midway** + ```bash + # Check current state + sqlx migrate info + + # Fix the issue and retry + sqlx migrate run + ``` + +2. **Database connection issues** + ```bash + # Test connection + psql $DATABASE_URL -c "SELECT version();" + ``` + +3. **Migration version conflicts** + ```bash + # Reset migrations (DANGEROUS - only for development) + sqlx migrate reset + ``` + +### Recovery Procedures + +1. **Partial migration failure** + - Review the error logs + - Manually fix any partial changes + - Re-run the migration + +2. **Rollback when down migration fails** + - Manually revert changes using SQL + - Update the `_sqlx_migrations` table if necessary + +## Integration with Application + +The project's database module automatically handles connections. Ensure migrations are applied before starting the application: + +```bash +# In your deployment script +./scripts/apply_all_migrations.sh + +# Then start the application +cargo run --bin rpc-server +``` + +## Development Workflow + +1. Create feature branch +2. Add necessary migrations using `sqlx migrate add` +3. Test migrations on development database +4. Commit migration files with your changes +5. Include migration instructions in PR description +6. Apply migrations to staging/production after deployment + +## Environment-Specific Considerations + +### Development +- Use local PostgreSQL instance +- Apply migrations manually or via script + +### Production +- Always backup databases before migration +- Test migrations on staging first +- Plan for minimal downtime +- Have rollback plan ready + +### Docker Compose +The project includes Docker Compose setup. Migrations should be applied after containers are up: + +```bash +docker-compose up -d postgres +# Wait for PostgreSQL to be ready +./scripts/apply_all_migrations.sh +docker-compose up +``` diff --git a/docs/RPC_METHODS.md b/docs/RPC_METHODS.md index a610206e..36ec314c 100644 --- a/docs/RPC_METHODS.md +++ b/docs/RPC_METHODS.md @@ -1,7 +1,8 @@ | **Method** | **status** | **Note** | |-----------------------------------|---------------|-----------------------------------------------------------------------------| | view_state_paginated | Included | Custom method. See details [here](../docs/CUSTOM_RPC_METHODS.md) | -| view_receipt_record | Included | Custom method. See details [here](../docs/CUSTOM_RPC_METHODS.md) | +| view_state_paginated | Included | Custom method. See details [here](../docs/CUSTOM_RPC_METHODS.md) | +| emulate_tx | Included | Custom method. See details [here](../docs/CUSTOM_RPC_METHODS.md) | | query.view_account | Included | | | query.view_code | Included | | | query.view_state | Included | | diff --git a/logic-state-indexer/src/configs.rs b/logic-state-indexer/src/configs.rs index b90da712..96b81445 100644 --- a/logic-state-indexer/src/configs.rs +++ b/logic-state-indexer/src/configs.rs @@ -41,7 +41,7 @@ pub async fn get_start_block_height( } StartOptions::FromLatest => final_block_height(near_client).await?, }; - Ok(start_block_height - 100) // Start just a bit earlier to overlap indexed blocks to ensure we don't miss anything in-between + Ok(start_block_height) } pub(crate) async fn final_block_height( diff --git a/logic-state-indexer/src/lib.rs b/logic-state-indexer/src/lib.rs index e41c3a04..684f6e4a 100644 --- a/logic-state-indexer/src/lib.rs +++ b/logic-state-indexer/src/lib.rs @@ -50,7 +50,6 @@ impl StateChangesToStore { &self, db_manager: &(impl database::StateIndexerDbManager + Sync + Send + 'static), block_height: u64, - block_hash: CryptoHash, ) -> anyhow::Result<()> { if !self.data.is_empty() { let futures = self.data.iter().map(|(shard_id, state_changes)| { @@ -58,7 +57,6 @@ impl StateChangesToStore { *shard_id, state_changes.values().cloned().collect(), block_height, - block_hash, ) }); futures::future::join_all(futures) @@ -75,7 +73,6 @@ impl StateChangesToStore { &self, db_manager: &(impl database::StateIndexerDbManager + Sync + Send + 'static), block_height: u64, - block_hash: CryptoHash, ) -> anyhow::Result<()> { if !self.access_key.is_empty() { let futures = self.access_key.iter().map(|(shard_id, state_changes)| { @@ -83,7 +80,6 @@ impl StateChangesToStore { *shard_id, state_changes.values().cloned().collect(), block_height, - block_hash, ) }); futures::future::join_all(futures) @@ -100,7 +96,6 @@ impl StateChangesToStore { &self, db_manager: &(impl database::StateIndexerDbManager + Sync + Send + 'static), block_height: u64, - block_hash: CryptoHash, ) -> anyhow::Result<()> { if !self.contract.is_empty() { let futures = self.contract.iter().map(|(shard_id, state_changes)| { @@ -108,7 +103,6 @@ impl StateChangesToStore { *shard_id, state_changes.values().cloned().collect(), block_height, - block_hash, ) }); futures::future::join_all(futures) @@ -125,7 +119,6 @@ impl StateChangesToStore { &self, db_manager: &(impl database::StateIndexerDbManager + Sync + Send + 'static), block_height: u64, - block_hash: CryptoHash, ) -> anyhow::Result<()> { if !self.account.is_empty() { let futures = self.account.iter().map(|(shard_id, state_changes)| { @@ -133,7 +126,6 @@ impl StateChangesToStore { *shard_id, state_changes.values().cloned().collect(), block_height, - block_hash, ) }); futures::future::join_all(futures) @@ -148,12 +140,11 @@ impl StateChangesToStore { &self, db_manager: &(impl database::StateIndexerDbManager + Sync + Send + 'static), block_height: u64, - block_hash: CryptoHash, ) -> anyhow::Result<()> { - let save_data_future = self.save_data(db_manager, block_height, block_hash); - let save_access_key_future = self.save_access_key(db_manager, block_height, block_hash); - let save_contract_future = self.save_contract(db_manager, block_height, block_hash); - let save_account_future = self.save_account(db_manager, block_height, block_hash); + let save_data_future = self.save_data(db_manager, block_height); + let save_access_key_future = self.save_access_key(db_manager, block_height); + let save_contract_future = self.save_contract(db_manager, block_height); + let save_account_future = self.save_account(db_manager, block_height); futures::future::join_all([ save_data_future.boxed(), @@ -244,7 +235,6 @@ pub async fn handle_streamer_message( &streamer_message, db_manager, block_height, - block_hash, &indexer_config, shard_layout, ) @@ -339,7 +329,6 @@ async fn handle_state_changes( streamer_message: &near_indexer_primitives::StreamerMessage, db_manager: &(impl database::StateIndexerDbManager + Sync + Send + 'static), block_height: u64, - block_hash: CryptoHash, indexer_config: &(impl configuration::RightsizingConfig + std::fmt::Debug), shard_layout: &near_primitives::shard_layout::ShardLayout, ) -> anyhow::Result<()> { @@ -432,6 +421,6 @@ async fn handle_state_changes( } state_changes_to_store - .save_state_changes(db_manager, block_height, block_hash) + .save_state_changes(db_manager, block_height) .await } diff --git a/readnode-primitives/src/lib.rs b/readnode-primitives/src/lib.rs index 35c3ce5c..481ef49e 100644 --- a/readnode-primitives/src/lib.rs +++ b/readnode-primitives/src/lib.rs @@ -220,12 +220,11 @@ pub type StateValue = Vec; pub struct BlockHeightShardId(pub u64, pub u64); pub struct QueryData { pub data: T, - // block_height and block_hash we return here represents the moment + // block_height we return here represents the moment // when the data was last updated in the database // We used to return it in the `QueryResponse` but it was replaced with // the logic that corresponds the logic of the `nearcore` RPC API pub block_height: near_indexer_primitives::types::BlockHeight, - pub block_hash: CryptoHash, } #[derive(Debug, Clone)] @@ -300,31 +299,17 @@ where } } -impl - TryFrom<( - Vec, - near_indexer_primitives::types::BlockHeight, - CryptoHash, - )> for QueryData +impl TryFrom<(Vec, i64)> for QueryData where T: borsh::BorshDeserialize, { type Error = anyhow::Error; - fn try_from( - value: ( - Vec, - near_indexer_primitives::types::BlockHeight, - CryptoHash, - ), - ) -> Result { + fn try_from(value: (Vec, i64)) -> Result { let data = T::try_from_slice(&value.0)?; - - Ok(Self { - data, - block_height: value.1, - block_hash: value.2, - }) + let block_height = u64::try_from(value.1) + .map_err(|_| anyhow::anyhow!("Failed to cast `block_height` from i64 to u64"))?; + Ok(Self { data, block_height }) } } @@ -415,22 +400,3 @@ where }) } } - -impl TryFrom<(String, T)> for BlockRecord -where - T: ToPrimitive, -{ - type Error = anyhow::Error; - - fn try_from(value: (String, T)) -> Result { - let height = value - .1 - .to_u64() - .ok_or_else(|| anyhow::anyhow!("Failed to parse `block_height` to u64"))?; - let hash = CryptoHash::from_str(&value.0).map_err(|err| { - anyhow::anyhow!("Failed to parse `block_hash` to CryptoHash: {}", err) - })?; - - Ok(BlockRecord { height, hash }) - } -} diff --git a/rpc-server/Cargo.toml b/rpc-server/Cargo.toml index c1624bf9..02d2f877 100644 --- a/rpc-server/Cargo.toml +++ b/rpc-server/Cargo.toml @@ -46,6 +46,7 @@ near-jsonrpc.workspace = true near-jsonrpc-client.workspace = true near-indexer-primitives.workspace = true near-lake-framework.workspace = true +node-runtime.workspace = true near-primitives.workspace = true near-parameters.workspace = true near-vm-runner.workspace = true diff --git a/rpc-server/Dockerfile b/rpc-server/Dockerfile index ffba4d3a..e315c38e 100644 --- a/rpc-server/Dockerfile +++ b/rpc-server/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.85 AS builder +FROM rust:1.86 AS builder ARG features="default" ARG profile="release" WORKDIR /tmp/ diff --git a/rpc-server/src/config.rs b/rpc-server/src/config.rs index 5aa95d97..a16fd025 100644 --- a/rpc-server/src/config.rs +++ b/rpc-server/src/config.rs @@ -40,7 +40,7 @@ pub struct ServerContext { /// Database manager pub db_manager: std::sync::Arc>, /// TransactionDetails storage - pub tx_details_storage: std::sync::Arc, + pub tx_details_storage: std::sync::Arc, /// Connection to cache storage with transactions in process pub tx_cache_storage: Option, /// Genesis info include genesis_config and genesis_block @@ -135,11 +135,37 @@ impl ServerContext { BlocksInfoByFinality::new(&near_rpc_client, &fastnear_client).await, ); - let tx_details_storage = tx_details_storage::TxDetailsStorage::new( - rpc_server_config.tx_details_storage.scylla_client().await, + let db_manager = database::prepare_db_manager::( + &rpc_server_config.database, ) .await?; + let tx_details_storage: std::sync::Arc = + match rpc_server_config.tx_details_storage_provider { + configuration::StorageProvider::ScyllaDb => { + let scylla_session = rpc_server_config + .tx_details_storage + .scylla_client() + .await + .expect("Failed to create ScyllaDB client"); + let scylla_db_manager = + database::scylla::tx_indexer::ScyllaDBManager::new(scylla_session).await?; + // Use ScyllaDBManager directly for tx_details_storage, since it does not implement ReaderDbManager + std::sync::Arc::new( + tx_details_storage::ScyllaDbTxDetailsStorage::new(std::sync::Arc::new( + scylla_db_manager, + )) + .await?, + ) + } + configuration::StorageProvider::Postgres => std::sync::Arc::new( + tx_details_storage::PostgresTxDetailsStorage::new(std::sync::Arc::new( + db_manager.clone(), + )) + .await?, + ), + }; + let tx_cache_storage = cache_storage::TxIndexerCache::new(rpc_server_config.general.redis_url.to_string()) .await @@ -150,11 +176,6 @@ impl ServerContext { let genesis_info = GenesisInfo::get(&fastnear_client).await; - let db_manager = database::prepare_db_manager::( - &rpc_server_config.database, - ) - .await?; - crate::metrics::CARGO_PKG_VERSION .with_label_values(&[NEARD_VERSION]) .inc(); @@ -162,7 +183,7 @@ impl ServerContext { Ok(Self { fastnear_client, db_manager: std::sync::Arc::new(Box::new(db_manager)), - tx_details_storage: std::sync::Arc::new(tx_details_storage), + tx_details_storage, tx_cache_storage, genesis_info, near_rpc_client, diff --git a/rpc-server/src/main.rs b/rpc-server/src/main.rs index f256b6f2..71e5da41 100644 --- a/rpc-server/src/main.rs +++ b/rpc-server/src/main.rs @@ -78,6 +78,13 @@ async fn rpc_handler( }) .await } + + "emulate_tx" => { + process_method_call(request, |params| { + modules::transactions::methods::emulate_tx(data, params) + }) + .await + } // request methods "query" => { process_method_call(request, |params| { diff --git a/rpc-server/src/modules/network/methods.rs b/rpc-server/src/modules/network/methods.rs index 707f5786..0003c2fb 100644 --- a/rpc-server/src/modules/network/methods.rs +++ b/rpc-server/src/modules/network/methods.rs @@ -1,5 +1,4 @@ use actix_web::web::Data; -use near_primitives::epoch_manager::{AllEpochConfig, EpochConfig}; use crate::config::ServerContext; use crate::modules::blocks::utils::fetch_block_from_cache_or_get; @@ -45,7 +44,6 @@ pub async fn status( .iter() .map(|validator| near_primitives::views::ValidatorInfo { account_id: validator.account_id.clone(), - is_slashed: validator.is_slashed, }) .collect(); @@ -400,15 +398,18 @@ pub async fn protocol_config_call( let runtime_config = store.get_config(protocol_version); // get default epoch config for genesis config - let default_epoch_config = EpochConfig::from(&data.genesis_info.genesis_config); + let epoch_config_store = near_primitives::epoch_manager::EpochConfigStore::for_chain_id( + &data.genesis_info.genesis_config.chain_id, + None, + ) + .expect("Failed to create epoch config store"); // AllEpochConfig manages protocol configs that might be changing throughout epochs (hence EpochConfig). // The main function in AllEpochConfig is ::for_protocol_version which takes a protocol version // and returns the EpochConfig that should be used for this protocol version. - let all_epoch_config = AllEpochConfig::new( - true, - data.genesis_info.genesis_config.protocol_version, - default_epoch_config, + let all_epoch_config = near_primitives::epoch_manager::AllEpochConfig::from_epoch_config_store( &data.genesis_info.genesis_config.chain_id, + data.genesis_info.genesis_config.epoch_length, + epoch_config_store, ); let epoch_config = all_epoch_config.for_protocol_version(protocol_version); diff --git a/rpc-server/src/modules/queries/contract_runner/code_storage.rs b/rpc-server/src/modules/queries/contract_runner/code_storage.rs index f200e4dc..9ef58a23 100644 --- a/rpc-server/src/modules/queries/contract_runner/code_storage.rs +++ b/rpc-server/src/modules/queries/contract_runner/code_storage.rs @@ -21,6 +21,11 @@ pub struct CodeStorage { is_prefetch_state: bool, prefetch_state_data: HashMap, + + tx_actions_collector: Option>, + tx_actions: Vec, + tx_storage: HashMap>, + is_tx_emulator: bool, } pub struct StorageValuePtr { @@ -38,6 +43,7 @@ impl near_vm_runner::logic::ValuePtr for StorageValuePtr { } impl CodeStorage { + #[allow(clippy::too_many_arguments)] pub async fn init( db_manager: std::sync::Arc>, account_id: near_primitives::types::AccountId, @@ -48,6 +54,10 @@ impl CodeStorage { Option, >, prefetch_state: bool, + tx_actions_collector: Option< + std::sync::Arc, + >, + is_tx_emulator: bool, ) -> Self { let prefetch_state_data = if prefetch_state { utils::get_state_from_db( @@ -72,7 +82,18 @@ impl CodeStorage { optimistic_data, is_prefetch_state: !prefetch_state_data.is_empty(), prefetch_state_data, + tx_actions_collector, + tx_actions: vec![], + tx_storage: Default::default(), + is_tx_emulator, + } + } + + fn push_action(&mut self, action: near_vm_runner::logic::mocks::mock_external::MockAction) { + if let Some(collector) = &self.tx_actions_collector { + collector.push_mock_action(action.clone()); } + self.tx_actions.push(action); } fn get_state_key_data(&self, key: &[u8]) -> readnode_primitives::StateValue { @@ -142,14 +163,31 @@ impl near_vm_runner::logic::External for CodeStorage { fn storage_set( &mut self, _access_tracker: &mut dyn StorageAccessTracker, - _key: &[u8], - _value: &[u8], + key: &[u8], + value: &[u8], ) -> Result>> { - Err(near_vm_runner::logic::VMLogicError::HostError( - near_vm_runner::logic::HostError::ProhibitedInView { - method_name: String::from("storage_set"), - }, - )) + if !self.is_tx_emulator { + return Err(near_vm_runner::logic::VMLogicError::HostError( + near_vm_runner::logic::HostError::ProhibitedInView { + method_name: String::from("storage_set"), + }, + )); + }; + let tx_value = self.tx_storage.insert(key.to_vec(), Some(value.to_vec())); + // Returns the previous value for the given key if it exists in the transaction storage, + // otherwise fetches the value from the database. If the database value is not empty, + // returns it as Some; otherwise, returns None. + let result = if let Some(tx_value) = tx_value { + tx_value + } else { + let db_value = self.get_state_key_data(key); + if !db_value.is_empty() { + Some(db_value) + } else { + None + } + }; + Ok(result) } #[cfg_attr( @@ -161,6 +199,18 @@ impl near_vm_runner::logic::External for CodeStorage { _access_tracker: &mut dyn StorageAccessTracker, key: &[u8], ) -> Result>> { + // If we are in transaction emulator mode, we should return the value from the transaction storage + if self.is_tx_emulator { + let val = self.tx_storage.get(key); + if let Some(Some(value)) = val { + return Ok(Some(Box::new(StorageValuePtr { + value: value.clone(), + }) as Box<_>)); + } else if let Some(None) = val { + return Ok(None); + } + } + // If the key is not in the transaction storage, we should return the value from the database if self.is_optimistic { self.optimistic_storage_get(key) } else { @@ -175,13 +225,31 @@ impl near_vm_runner::logic::External for CodeStorage { fn storage_remove( &mut self, _access_tracker: &mut dyn StorageAccessTracker, - _key: &[u8], + key: &[u8], ) -> Result>> { - Err(near_vm_runner::logic::VMLogicError::HostError( - near_vm_runner::logic::HostError::ProhibitedInView { - method_name: String::from("storage_remove"), - }, - )) + if !self.is_tx_emulator { + return Err(near_vm_runner::logic::VMLogicError::HostError( + near_vm_runner::logic::HostError::ProhibitedInView { + method_name: String::from("storage_remove"), + }, + )); + } + // We set the value to None to emulate the removal of the key + let value = self.tx_storage.insert(key.to_vec(), None); + // Returns the previous value for the given key, if it exists. + // If the key was already present in the transaction storage, return its value (which may be Some or None). + // Otherwise, fetch the value from the database. If the database value is not empty, return it as Some; otherwise, return None. + let result = if let Some(value) = value { + value + } else { + let db_val = self.get_state_key_data(key); + if !db_val.is_empty() { + Some(db_val) + } else { + None + } + }; + Ok(result) } #[cfg_attr( @@ -193,6 +261,15 @@ impl near_vm_runner::logic::External for CodeStorage { _access_tracker: &mut dyn StorageAccessTracker, key: &[u8], ) -> Result { + // If we are in transaction emulator mode, we should check the transaction storage + if self.is_tx_emulator { + let val = self.tx_storage.get(key); + if let Some(Some(_)) = val { + return Ok(true); + } else if let Some(None) = val { + return Ok(false); + } + } if self.is_optimistic { self.optimistic_storage_has_key(key) } else { @@ -229,112 +306,265 @@ impl near_vm_runner::logic::External for CodeStorage { fn create_action_receipt( &mut self, - _receipt_indices: Vec, - _receiver_id: near_primitives::types::AccountId, + receipt_indices: Vec, + receiver_id: near_primitives::types::AccountId, ) -> Result { - panic!("Prohibited in view. `create_action_receipt`"); + if !self.is_tx_emulator { + return Err(near_vm_runner::logic::VMLogicError::HostError( + near_vm_runner::logic::HostError::ProhibitedInView { + method_name: String::from("create_action_receipt"), + }, + )); + } + let index = self.tx_actions.len(); + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::CreateReceipt { + receipt_indices, + receiver_id, + }, + ); + Ok(index as u64) } fn create_promise_yield_receipt( &mut self, - _receiver_id: near_primitives::types::AccountId, + receiver_id: near_primitives::types::AccountId, ) -> Result<( near_vm_runner::logic::types::ReceiptIndex, near_indexer_primitives::CryptoHash, )> { - panic!("Prohibited in view. `create_promise_yield_receipt`"); + if !self.is_tx_emulator { + return Err(near_vm_runner::logic::VMLogicError::HostError( + near_vm_runner::logic::HostError::ProhibitedInView { + method_name: String::from("create_promise_yield_receipt"), + }, + )); + } + let index = self.tx_actions.len(); + let data_id = self.generate_data_id(); + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::YieldCreate { + data_id, + receiver_id, + }, + ); + Ok((index as u64, data_id)) } fn submit_promise_resume_data( &mut self, - _data_id: near_indexer_primitives::CryptoHash, - _data: Vec, + data_id: near_indexer_primitives::CryptoHash, + data: Vec, ) -> Result { - panic!("Prohibited in view. `submit_promise_resume_data`"); + if !self.is_tx_emulator { + return Err(near_vm_runner::logic::VMLogicError::HostError( + near_vm_runner::logic::HostError::ProhibitedInView { + method_name: String::from("submit_promise_resume_data"), + }, + )); + } + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::YieldResume { data_id, data }, + ); + for action in &self.tx_actions { + let near_vm_runner::logic::mocks::mock_external::MockAction::YieldCreate { + data_id: done, + receiver_id, + } = action + else { + continue; + }; + if data_id == *done && self.account_id == *receiver_id { + return Ok(true); + } + } + Ok(false) } fn append_action_create_account( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, ) -> Result<()> { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::CreateAccount { + receipt_index, + }, + ); Ok(()) } fn append_action_deploy_contract( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, - _code: Vec, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + code: Vec, ) -> Result<()> { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::DeployContract { + receipt_index, + code, + }, + ); Ok(()) } fn append_action_function_call_weight( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, - _method_name: Vec, - _args: Vec, - _attached_deposit: near_primitives::types::Balance, - _prepaid_gas: near_primitives::types::Gas, - _gas_weight: near_primitives::types::GasWeight, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + method_name: Vec, + args: Vec, + attached_deposit: near_primitives::types::Balance, + prepaid_gas: near_primitives::types::Gas, + gas_weight: near_primitives::types::GasWeight, ) -> Result<()> { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::FunctionCallWeight { + receipt_index, + method_name, + args, + attached_deposit, + prepaid_gas, + gas_weight, + }, + ); Ok(()) } fn append_action_transfer( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, - _deposit: near_primitives::types::Balance, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + deposit: near_primitives::types::Balance, ) -> Result<()> { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::Transfer { + receipt_index, + deposit, + }, + ); Ok(()) } fn append_action_stake( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, - _stake: near_primitives::types::Balance, - _public_key: near_crypto::PublicKey, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + stake: near_primitives::types::Balance, + public_key: near_crypto::PublicKey, ) { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::Stake { + receipt_index, + stake, + public_key, + }, + ); } fn append_action_add_key_with_full_access( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, - _public_key: near_crypto::PublicKey, - _nonce: near_primitives::types::Nonce, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + public_key: near_crypto::PublicKey, + nonce: near_primitives::types::Nonce, ) { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::AddKeyWithFullAccess { + receipt_index, + public_key, + nonce, + }, + ); } fn append_action_add_key_with_function_call( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, - _public_key: near_crypto::PublicKey, - _nonce: near_primitives::types::Nonce, - _allowance: Option, - _receiver_id: near_primitives::types::AccountId, - _method_names: Vec>, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + public_key: near_crypto::PublicKey, + nonce: near_primitives::types::Nonce, + allowance: Option, + receiver_id: near_primitives::types::AccountId, + method_names: Vec>, ) -> Result<()> { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::AddKeyWithFunctionCall { + receipt_index, + public_key, + nonce, + allowance, + receiver_id, + method_names, + }, + ); Ok(()) } fn append_action_delete_key( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, - _public_key: near_crypto::PublicKey, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + public_key: near_crypto::PublicKey, ) { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::DeleteKey { + receipt_index, + public_key, + }, + ); } fn append_action_delete_account( &mut self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, - _beneficiary_id: near_primitives::types::AccountId, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + beneficiary_id: near_primitives::types::AccountId, ) -> Result<()> { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::DeleteAccount { + receipt_index, + beneficiary_id, + }, + ); Ok(()) } fn get_receipt_receiver( &self, - _receipt_index: near_vm_runner::logic::types::ReceiptIndex, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, ) -> &near_primitives::types::AccountId { - panic!("Prohibited in view. `get_receipt_receiver`"); + if !self.is_tx_emulator { + panic!("Prohibited in view. `get_receipt_receiver`"); + } + match &self.tx_actions[receipt_index as usize] { + near_vm_runner::logic::mocks::mock_external::MockAction::CreateReceipt { + receiver_id, + .. + } => receiver_id, + _ => panic!("not a valid receipt index!"), + } + } + + fn append_action_deploy_global_contract( + &mut self, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + code: Vec, + mode: near_vm_runner::logic::types::GlobalContractDeployMode, + ) -> Result<()> { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::DeployGlobalContract { + receipt_index, + code, + mode, + }, + ); + Ok(()) + } + + fn append_action_use_global_contract( + &mut self, + receipt_index: near_vm_runner::logic::types::ReceiptIndex, + contract_id: near_vm_runner::logic::types::GlobalContractIdentifier, + ) -> Result<()> { + self.push_action( + near_vm_runner::logic::mocks::mock_external::MockAction::UseGlobalContract { + receipt_index, + contract_id, + }, + ); + Ok(()) } } diff --git a/rpc-server/src/modules/queries/contract_runner/mod.rs b/rpc-server/src/modules/queries/contract_runner/mod.rs index a1c6fce8..8ab0f17c 100644 --- a/rpc-server/src/modules/queries/contract_runner/mod.rs +++ b/rpc-server/src/modules/queries/contract_runner/mod.rs @@ -6,6 +6,15 @@ use near_vm_runner::ContractRuntimeCache; mod code_storage; +#[derive(Debug)] +pub struct RunContractContext { + pub block: near_primitives::views::BlockView, + pub account_id: near_primitives::types::AccountId, + pub method_name: String, + pub args: near_primitives::types::FunctionArgs, + pub is_optimistic: bool, +} + pub struct Contract { pub contract_code: Option>, pub hash: near_primitives::hash::CryptoHash, @@ -37,64 +46,78 @@ impl near_vm_runner::Contract for Contract { } pub struct RunContractResponse { - pub result: Vec, - pub logs: Vec, + pub result: near_vm_runner::logic::VMOutcome, + pub block_height: near_primitives::types::BlockHeight, + pub block_hash: near_primitives::hash::CryptoHash, } #[allow(clippy::too_many_arguments)] #[cfg_attr( feature = "tracing-instrumentation", - tracing::instrument(skip(db_manager, compiled_contract_code_cache, contract_code_cache)) + tracing::instrument(skip( + db_manager, + compiled_contract_code_cache, + contract_code_cache, + tx_actions_collector + )) )] pub async fn run_contract( - account_id: &near_primitives::types::AccountId, - method_name: &str, - args: &near_primitives::types::FunctionArgs, + run_contract_context: crate::modules::queries::contract_runner::RunContractContext, db_manager: &std::sync::Arc>, compiled_contract_code_cache: &std::sync::Arc, contract_code_cache: &std::sync::Arc< crate::cache::RwLockLruMemoryCache>, >, blocks_info_by_finality: &std::sync::Arc, - block: &near_primitives::views::BlockView, max_gas_burnt: near_primitives::types::Gas, optimistic_data: HashMap< readnode_primitives::StateKey, Option, >, prefetch_state_size_limit: u64, -) -> Result { + tx_actions_collector: Option>, + is_tx_emulation: bool, +) -> Result +{ let contract = db_manager - .get_account(account_id, block.header.height, "query_call_function") + .get_account( + &run_contract_context.account_id, + run_contract_context.block.header.height, + "query_call_function", + ) .await .map_err( |_| near_jsonrpc::primitives::types::query::RpcQueryError::UnknownAccount { - requested_account_id: account_id.clone(), - block_height: block.header.height, - block_hash: block.header.hash, + requested_account_id: run_contract_context.account_id.clone(), + block_height: run_contract_context.block.header.height, + block_hash: run_contract_context.block.header.hash, }, )?; - let (epoch_height, validators) = - epoch_height_and_validators_with_balances(db_manager, blocks_info_by_finality, block) - .await?; + let (epoch_height, validators) = epoch_height_and_validators_with_balances( + db_manager, + blocks_info_by_finality, + &run_contract_context.block, + ) + .await?; // Prepare context for the VM run contract let public_key = near_crypto::PublicKey::empty(near_crypto::KeyType::ED25519); let random_seed = near_primitives::utils::create_random_seed( - block.header.latest_protocol_version, + // It is not needed to generate unique action hashes for our contract calls, + // so we can use block hash + run_contract_context.block.header.hash, near_primitives::hash::CryptoHash::default(), - block.header.prev_state_root, ); let context = near_vm_runner::logic::VMContext { - current_account_id: account_id.clone(), - signer_account_id: account_id.clone(), + current_account_id: run_contract_context.account_id.clone(), + signer_account_id: run_contract_context.account_id.clone(), signer_account_pk: borsh::to_vec(&public_key).expect("Failed to serialize"), - predecessor_account_id: account_id.clone(), - input: args.to_vec(), + predecessor_account_id: run_contract_context.account_id.clone(), + input: run_contract_context.args.to_vec(), promise_results: Vec::new().into(), - block_height: block.header.height, - block_timestamp: block.header.timestamp, + block_height: run_contract_context.block.header.height, + block_timestamp: run_contract_context.block.header.timestamp, epoch_height, account_balance: contract.data.amount(), account_locked_balance: contract.data.locked(), @@ -109,7 +132,7 @@ pub async fn run_contract( // Init runtime config for each protocol version let store = near_parameters::RuntimeConfigStore::free(); let config = store - .get_config(block.header.latest_protocol_version) + .get_config(run_contract_context.block.header.latest_protocol_version) .wasm_config .clone(); let vm_config = near_parameters::vm::Config { @@ -130,13 +153,17 @@ pub async fn run_contract( Some(code) => Contract::new(Some(code), code_hash), None => { let code = db_manager - .get_contract_code(account_id, block.header.height, "query_call_function") + .get_contract_code( + &run_contract_context.account_id, + run_contract_context.block.header.height, + "query_call_function", + ) .await .map_err(|_| { near_jsonrpc::primitives::types::query::RpcQueryError::InvalidAccount { - requested_account_id: account_id.clone(), - block_height: block.header.height, - block_hash: block.header.hash, + requested_account_id: run_contract_context.account_id.clone(), + block_height: run_contract_context.block.header.height, + block_hash: run_contract_context.block.header.hash, } })?; contract_code_cache.put(code_hash, code.data.clone()).await; @@ -154,7 +181,11 @@ pub async fn run_contract( code.len() } else { db_manager - .get_contract_code(account_id, block.header.height, "query_call_function") + .get_contract_code( + &run_contract_context.account_id, + run_contract_context.block.header.height, + "query_call_function", + ) .await .map(|code| code.data.len()) .unwrap_or_default() @@ -166,18 +197,20 @@ pub async fn run_contract( // Init an external database interface for the Runtime logic let code_storage = CodeStorage::init( db_manager.clone(), - account_id.clone(), - block.header.height, + run_contract_context.account_id.clone(), + run_contract_context.block.header.height, validators, optimistic_data, state_size <= prefetch_state_size_limit, + tx_actions_collector, + is_tx_emulation, ) .await; // Execute the contract in the near VM - let result = run_code_in_vm_runner( + run_code_in_vm_runner( contract_code, - method_name.to_string(), + run_contract_context.method_name.to_string(), context, code_storage, vm_config, @@ -188,26 +221,7 @@ pub async fn run_contract( |e| near_jsonrpc::primitives::types::query::RpcQueryError::InternalError { error_message: e.to_string(), }, - )?; - - if let Some(err) = result.aborted { - let message = format!("wasm execution failed with error: {:?}", err); - Err( - near_jsonrpc::primitives::types::query::RpcQueryError::ContractExecutionError { - vm_error: message, - block_height: block.header.height, - block_hash: block.header.hash, - }, - ) - } else { - let logs = result.logs; - let result = match result.return_data { - near_vm_runner::logic::ReturnData::Value(buf) => buf, - near_vm_runner::logic::ReturnData::ReceiptIndex(_) - | near_vm_runner::logic::ReturnData::None => vec![], - }; - Ok(RunContractResponse { result, logs }) - } + ) } async fn epoch_height_and_validators_with_balances( @@ -250,7 +264,6 @@ async fn epoch_height_and_validators_with_balances( )) } -#[allow(clippy::too_many_arguments)] #[cfg_attr( feature = "tracing-instrumentation", tracing::instrument(skip(context, code_storage, contract, compiled_contract_code_cache)) diff --git a/rpc-server/src/modules/queries/methods.rs b/rpc-server/src/modules/queries/methods.rs index b48b362f..9793a94c 100644 --- a/rpc-server/src/modules/queries/methods.rs +++ b/rpc-server/src/modules/queries/methods.rs @@ -29,6 +29,12 @@ pub async fn query( near_primitives::views::QueryRequest::ViewAccessKey { .. } => "query_view_access_key", near_primitives::views::QueryRequest::ViewState { .. } => "query_view_state", near_primitives::views::QueryRequest::CallFunction { .. } => "query_call_function", + near_primitives::views::QueryRequest::ViewGlobalContractCode { .. } => { + "query_view_global_contract_code" + } + near_primitives::views::QueryRequest::ViewGlobalContractCodeByAccountId { .. } => { + "query_view_global_contract_code_by_account_id" + } near_primitives::views::QueryRequest::ViewAccessKeyList { .. } => { "query_view_access_key_list" } @@ -145,10 +151,33 @@ async fn query_call( account_id, method_name, args, - } => function_call(data, &block, account_id, method_name, args, is_optimistic).await, + } => { + let run_contract_context = + crate::modules::queries::contract_runner::RunContractContext { + block: block.clone(), + account_id: account_id.clone(), + method_name: method_name.clone(), + args: args.clone(), + is_optimistic, + }; + function_call(data, run_contract_context).await + } near_primitives::views::QueryRequest::ViewAccessKeyList { account_id } => { view_access_keys_list(data, &block, account_id).await } + near_primitives::views::QueryRequest::ViewGlobalContractCode { .. } => Err( + near_jsonrpc::primitives::types::query::RpcQueryError::InternalError { + error_message: "ViewGlobalContractCode is not implemented in read-rpc yet." + .to_string(), + }, + ), + near_primitives::views::QueryRequest::ViewGlobalContractCodeByAccountId { .. } => Err( + near_jsonrpc::primitives::types::query::RpcQueryError::InternalError { + error_message: + "ViewGlobalContractCodeByAccountId is not implemented in read-rpc yet." + .to_string(), + }, + ), }; #[cfg(feature = "shadow-data-consistency")] @@ -354,62 +383,83 @@ async fn database_view_code( .data) } -#[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip(data)))] -async fn function_call( +pub async fn process_function_call( data: &Data, - block: &near_primitives::views::BlockView, - account_id: &near_primitives::types::AccountId, - method_name: &str, - args: &near_primitives::types::FunctionArgs, - is_optimistic: bool, + run_contract_context: crate::modules::queries::contract_runner::RunContractContext, + tx_actions_collector: Option>, + is_tx_emulation: bool, ) -> Result< - near_jsonrpc::primitives::types::query::RpcQueryResponse, + contract_runner::RunContractResponse, near_jsonrpc::primitives::types::query::RpcQueryError, > { - tracing::debug!( - "`function_call` call. AccountID {}, block {}, method_name {}, args {:?}, optimistic {}", - account_id, - block.header.height, - method_name, - args, - is_optimistic, - ); + tracing::debug!("`function_call` call. Context: {:?}", run_contract_context); // Depending on the optimistic flag we need to run the contract with the optimistic // state changes or not. - let maybe_optimistic_data = if is_optimistic { + let maybe_optimistic_data = if run_contract_context.is_optimistic { data.blocks_info_by_finality - .optimistic_state_changes_in_block(account_id, &[]) + .optimistic_state_changes_in_block(&run_contract_context.account_id, &[]) .await } else { Default::default() }; + let block_clone = run_contract_context.block.clone(); + let call_results = contract_runner::run_contract( - account_id, - method_name, - args, + run_contract_context, &data.db_manager, &data.compiled_contract_code_cache, &data.contract_code_cache, &data.blocks_info_by_finality, - block, data.max_gas_burnt, maybe_optimistic_data, data.prefetch_state_size_limit, + tx_actions_collector, + is_tx_emulation, ) .await?; + Ok(contract_runner::RunContractResponse { + result: call_results, + block_height: block_clone.header.height, + block_hash: block_clone.header.hash, + }) +} - Ok(near_jsonrpc::primitives::types::query::RpcQueryResponse { - kind: near_jsonrpc::primitives::types::query::QueryResponseKind::CallResult( - near_primitives::views::CallResult { - result: call_results.result, - logs: call_results.logs, +#[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip(data)))] +async fn function_call( + data: &Data, + run_contract_context: crate::modules::queries::contract_runner::RunContractContext, +) -> Result< + near_jsonrpc::primitives::types::query::RpcQueryResponse, + near_jsonrpc::primitives::types::query::RpcQueryError, +> { + let call_results = process_function_call(data, run_contract_context, None, false).await?; + + if let Some(err) = call_results.result.aborted { + let message = format!("wasm execution failed with error: {:?}", err); + Err( + near_jsonrpc::primitives::types::query::RpcQueryError::ContractExecutionError { + vm_error: message, + block_height: call_results.block_height, + block_hash: call_results.block_hash, }, - ), - block_height: block.header.height, - block_hash: block.header.hash, - }) + ) + } else { + let logs = call_results.result.logs; + let result = match call_results.result.return_data { + near_vm_runner::logic::ReturnData::Value(buf) => buf, + near_vm_runner::logic::ReturnData::ReceiptIndex(_) + | near_vm_runner::logic::ReturnData::None => vec![], + }; + Ok(near_jsonrpc::primitives::types::query::RpcQueryResponse { + kind: near_jsonrpc::primitives::types::query::QueryResponseKind::CallResult( + near_primitives::views::CallResult { result, logs }, + ), + block_height: call_results.block_height, + block_hash: call_results.block_hash, + }) + } } #[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip(data)))] @@ -535,7 +585,7 @@ async fn optimistic_view_state( } #[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip(data)))] -async fn database_view_state( +pub async fn database_view_state( data: &Data, block: &near_primitives::views::BlockView, account_id: &near_primitives::types::AccountId, diff --git a/rpc-server/src/modules/queries/mod.rs b/rpc-server/src/modules/queries/mod.rs index e363fa87..4682bcee 100644 --- a/rpc-server/src/modules/queries/mod.rs +++ b/rpc-server/src/modules/queries/mod.rs @@ -1,3 +1,3 @@ -mod contract_runner; +pub(crate) mod contract_runner; pub mod methods; pub mod utils; diff --git a/rpc-server/src/modules/receipts/methods.rs b/rpc-server/src/modules/receipts/methods.rs index 9070e962..86c732bb 100644 --- a/rpc-server/src/modules/receipts/methods.rs +++ b/rpc-server/src/modules/receipts/methods.rs @@ -59,15 +59,16 @@ async fn fetch_receipt( let receipt_record = fetch_receipt_record(data, request, "EXPERIMENTAL_receipt").await?; - let transaction_details = - try_get_transaction_details_by_hash(data, &receipt_record.parent_transaction_hash) - .await - .map_err(|err| { - tracing::warn!("Error in `receipt` call: {:?}", err); - near_jsonrpc::primitives::types::receipts::RpcReceiptError::UnknownReceipt { - receipt_id, - } - })?; + let transaction_details = try_get_transaction_details_by_hash( + data, + &receipt_record.parent_transaction_hash, + &receipt_record.shard_id, + ) + .await + .map_err(|err| { + tracing::warn!("Error in `receipt` call: {:?}", err); + near_jsonrpc::primitives::types::receipts::RpcReceiptError::UnknownReceipt { receipt_id } + })?; let receipt_view = transaction_details .receipts diff --git a/rpc-server/src/modules/state/methods.rs b/rpc-server/src/modules/state/methods.rs index a764ee90..ae815dae 100644 --- a/rpc-server/src/modules/state/methods.rs +++ b/rpc-server/src/modules/state/methods.rs @@ -18,9 +18,9 @@ pub async fn view_state_paginated( fetch_block_from_cache_or_get(&data, &block_reference, "view_state_paginated").await?; let state_values = get_state_from_db_paginated( - &data.db_manager, + &data, &request_data.account_id, - block.header.height, + &block, request_data.next_page_token, ) .await?; diff --git a/rpc-server/src/modules/state/utils.rs b/rpc-server/src/modules/state/utils.rs index 98317c45..03dfa0f5 100644 --- a/rpc-server/src/modules/state/utils.rs +++ b/rpc-server/src/modules/state/utils.rs @@ -1,37 +1,76 @@ -#[cfg_attr( - feature = "tracing-instrumentation", - tracing::instrument(skip(db_manager)) -)] +use crate::{config::ServerContext, modules::queries::methods::database_view_state}; +use actix_web::web::Data; + +#[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip(data)))] pub async fn get_state_from_db_paginated( - db_manager: &std::sync::Arc>, + data: &Data, account_id: &near_primitives::types::AccountId, - block_height: near_primitives::types::BlockHeight, + block: &near_primitives::views::BlockView, page_token: database::PageToken, ) -> Result { tracing::debug!( "`get_state_from_db_paginated` call. AccountId {}, block {}, page_token {:?}", account_id, - block_height, + block.header.height, page_token, ); - let (values, next_page_token) = db_manager - .get_state_by_page(account_id, block_height, page_token, "view_state_paginated") + let account = data + .db_manager + .get_account(account_id, block.header.height, "view_state_paginated") + .await + .map_err( + |_err| near_jsonrpc::primitives::types::query::RpcQueryError::UnknownAccount { + requested_account_id: account_id.clone(), + block_height: block.header.height, + block_hash: block.header.hash, + }, + )?; + + // Calculate the state size excluding the contract code size to check if it's too large to fetch. + // The state size is the storage usage minus the code size. + // more details: nearcore/runtime/runtime/src/state_viewer/mod.rs:150 + let code_len = data + .db_manager + .get_contract_code(account_id, block.header.height, "view_state_paginated") .await - .map_err(|err| { - near_jsonrpc::primitives::errors::RpcError::new_internal_error( - Some(serde_json::Value::String(err.to_string())), - "Failed to get page state from DB. Please try again!".to_string(), + .map(|code| code.data.len() as u64) + .unwrap_or_default(); + + let state_size = account.data.storage_usage().saturating_sub(code_len); + let (values, next_page_token) = if state_size <= 1_000_000 { + let values = database_view_state(data, block, account_id, &[]).await?; + (values, None) + } else { + // If the state size is too large, we try to fetch the state in pages. + // This is a fallback mechanism to avoid fetching too much data at once. + let (raw_values, next_page_token) = data + .db_manager + .get_state_by_page( + account_id, + block.header.height, + page_token, + "view_state_paginated", ) - })?; - Ok(crate::modules::state::PageStateValues { - values: values + .await + .map_err(|err| { + near_jsonrpc::primitives::errors::RpcError::new_internal_error( + Some(serde_json::Value::String(err.to_string())), + "Failed to get page state from DB. Please try again!".to_string(), + ) + })?; + let values = raw_values .into_iter() .map(|(k, v)| near_primitives::views::StateItem { key: k.into(), value: v.into(), }) - .collect(), + .collect(); + (values, next_page_token) + }; + + Ok(crate::modules::state::PageStateValues { + values, next_page_token, }) } diff --git a/rpc-server/src/modules/transactions/methods.rs b/rpc-server/src/modules/transactions/methods.rs index ddfa0747..8cf63a32 100644 --- a/rpc-server/src/modules/transactions/methods.rs +++ b/rpc-server/src/modules/transactions/methods.rs @@ -159,17 +159,22 @@ async fn tx_status_common( near_jsonrpc::primitives::types::transactions::RpcTransactionError, > { tracing::debug!("`tx_status_common` call."); - let tx_hash = match &transaction_info { - near_jsonrpc::primitives::types::transactions::TransactionInfo::Transaction( - near_jsonrpc::primitives::types::transactions::SignedTransaction::SignedTransaction(tx), - ) => tx.get_hash(), + let (tx_hash, sender_id) = match &transaction_info { + near_jsonrpc::primitives::types::transactions::TransactionInfo::Transaction { + signed_tx, + } => ( + signed_tx.get_hash(), + signed_tx.transaction.signer_id().clone(), + ), near_jsonrpc::primitives::types::transactions::TransactionInfo::TransactionId { tx_hash, - .. - } => *tx_hash, + sender_account_id, + } => (*tx_hash, sender_account_id.clone()), }; - let transaction_details = super::try_get_transaction_details_by_hash(data, &tx_hash) + let shard_id = data.db_manager.get_shard_id_by_account_id(&sender_id); + + let transaction_details = super::try_get_transaction_details_by_hash(data, &tx_hash, &shard_id) .await .map_err(|err| { // logging the error at debug level since it's expected to see some "not found" @@ -208,3 +213,144 @@ async fn tx_status_common( ) } } + +/// Emulates the execution of a transaction by processing its actions and collecting the results. +/// +/// This function takes a signed transaction request, iterates over its actions, and processes +/// each supported action (currently only `FunctionCall` actions are supported). It collects +/// the results of these actions into a vector of `EmulateTransactionResponse`. Additionally, +/// it processes any cross-contract actions collected during the emulation and appends their +/// results as well. +/// +/// # Arguments +/// +/// * `data` - Shared server context containing dependencies and state. +/// * `request_data` - The transaction request containing the signed transaction to emulate. +/// +/// # Returns +/// +/// Returns a `Result` containing a vector of `EmulateTransactionResponse` on success, +/// or an `RpcError` if an error occurs during emulation. +pub async fn emulate_tx( + data: Data, + request_data: near_jsonrpc::primitives::types::transactions::RpcSendTransactionRequest, +) -> Result< + crate::modules::transactions::EmulateTransactionResponse, + near_jsonrpc::primitives::errors::RpcError, +> { + // Extracts the signer account ID from the signed transaction, prepares a results vector, + // and initializes a transaction actions collector. Iterates over each action in the transaction, + // processing only `FunctionCall` actions by invoking the function call processor and collecting + // the results. Unsupported actions are logged for debugging purposes. + let account_id = request_data.signed_transaction.transaction.signer_id(); + let receiver_id = request_data.signed_transaction.transaction.receiver_id(); + let block = data.blocks_info_by_finality.final_block_view().await; + let store = near_parameters::RuntimeConfigStore::for_chain_id( + &data.genesis_info.genesis_config.chain_id, + ); + let protocol_version = data + .blocks_info_by_finality + .current_protocol_version() + .await; + let runtime_config = store.get_config(protocol_version); + let results = actions_call( + &data, + account_id, + receiver_id, + &request_data + .signed_transaction + .transaction + .actions() + .to_vec(), + runtime_config, + ) + .await?; + let total_fee = results.iter().map(|r| r.fee()).sum(); + Ok(crate::modules::transactions::EmulateTransactionResponse { + results, + block_height: block.header.height, + gas_price: block.header.gas_price, + total_fee, + }) +} + +/// Processes a list of transaction actions, emulating their execution and collecting results. +/// +/// For each action in `tx_actions`, if it is a `FunctionCall`, this function processes the call, +/// collects the outcome and fee, and recursively processes any cross-contract actions collected +/// during the emulation. For other action types, it computes the fee and collects the result. +/// +/// # Arguments +/// * `data` - Shared server context. +/// * `account_id` - The signer account ID. +/// * `receiver_id` - The receiver account ID. +/// * `tx_actions` - The list of actions to emulate. +/// * `runtime_config` - The runtime configuration for fee calculation. +/// +/// # Returns +/// A `Result` containing a vector of `EmulateTransactionActionResult` on success, +/// or an `RpcError` if an error occurs. +async fn actions_call( + data: &Data, + account_id: &near_primitives::types::AccountId, + receiver_id: &near_primitives::types::AccountId, + tx_actions: &Vec, + runtime_config: &near_parameters::RuntimeConfig, +) -> Result< + Vec, + near_jsonrpc::primitives::errors::RpcError, +> { + let tx_actions_collector = + std::sync::Arc::new(crate::modules::transactions::TxActionsCollector::new()); + let mut results = vec![]; + for tx_action in tx_actions { + match tx_action { + near_primitives::transaction::Action::FunctionCall(action) => { + // let method_name = action.method_name.clone(); + // let args = action.args.clone(); + // let block = data.blocks_info_by_finality.final_block_view().await; + let run_contract_context = + crate::modules::queries::contract_runner::RunContractContext { + block: data.blocks_info_by_finality.final_block_view().await, + account_id: account_id.clone(), + method_name: action.method_name.clone(), + args: action.args.clone().into(), + is_optimistic: false, + }; + let call_results = crate::modules::queries::methods::process_function_call( + data, + run_contract_context, + Some(tx_actions_collector.clone()), + true, + ) + .await?; + + let fee = node_runtime::config::exec_fee(runtime_config, tx_action, receiver_id); + results.push( + crate::modules::transactions::EmulateTransactionActionResult::FunctionCall { + outcome: Box::new(call_results.into()), + fee, + }, + ); + let cross_results = Box::pin(actions_call( + data, + account_id, + receiver_id, + &tx_actions_collector.get_actions().await, + runtime_config, + )) + .await?; + results.extend(cross_results); + } + _ => { + let fee = node_runtime::config::exec_fee(runtime_config, tx_action, receiver_id); + results.push( + crate::modules::transactions::EmulateTransactionActionResult::from_tx_action( + tx_action, fee, + ), + ); + } + } + } + Ok(results) +} diff --git a/rpc-server/src/modules/transactions/mod.rs b/rpc-server/src/modules/transactions/mod.rs index 7169cc24..a0805781 100644 --- a/rpc-server/src/modules/transactions/mod.rs +++ b/rpc-server/src/modules/transactions/mod.rs @@ -1,16 +1,16 @@ -use actix_web::web::Data; - use crate::config::ServerContext; +use actix_web::web::Data; pub mod methods; pub(crate) async fn try_get_transaction_details_by_hash( data: &Data, tx_hash: &near_indexer_primitives::CryptoHash, + shard_id: &near_primitives::types::ShardId, ) -> anyhow::Result { if let Ok(transaction_details_bytes) = &data .tx_details_storage - .retrieve_tx(&tx_hash.to_string()) + .retrieve_tx(&tx_hash.to_string(), shard_id) .await { readnode_primitives::TransactionDetails::tx_deserialize(transaction_details_bytes) @@ -20,3 +20,292 @@ pub(crate) async fn try_get_transaction_details_by_hash( anyhow::bail!("Transaction not found") } } + +#[derive(serde::Serialize, serde::Deserialize, Debug, Default)] +pub struct FunctionCallOutcome { + pub balance: near_primitives::types::Balance, + pub storage_usage: near_primitives::types::StorageUsage, + pub return_data: Option>, + pub burnt_gas: near_primitives::types::Gas, + pub used_gas: near_primitives::types::Gas, + pub compute_usage: near_primitives::types::Compute, + pub logs: Vec, + /// Data collected from making a contract call + pub profile: ProfileData, + pub aborted: Option, +} + +#[derive(serde::Serialize, serde::Deserialize, Debug, Default)] +pub struct ProfileData { + /// Gas spent on sending or executing actions. + pub actions_profile: std::collections::HashMap, + /// Non-action gas spent outside the WASM VM while executing a contract. + pub wasm_ext_profile: std::collections::HashMap, + /// Gas spent on execution inside the WASM VM. + pub wasm_gas: near_primitives::types::Gas, +} + +impl From for ProfileData { + fn from(profile: near_vm_runner::ProfileDataV3) -> Self { + ProfileData { + actions_profile: profile + .actions_profile + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect(), + wasm_ext_profile: profile + .wasm_ext_profile + .into_iter() + .map(|(k, v)| (k.to_string(), v)) + .collect(), + wasm_gas: profile.wasm_gas, + } + } +} + +impl From for FunctionCallOutcome { + fn from( + contract_response: crate::modules::queries::contract_runner::RunContractResponse, + ) -> Self { + FunctionCallOutcome { + balance: contract_response.result.balance, + storage_usage: contract_response.result.storage_usage, + return_data: contract_response.result.return_data.as_value(), + burnt_gas: contract_response.result.burnt_gas, + used_gas: contract_response.result.used_gas, + compute_usage: contract_response.result.compute_usage, + logs: contract_response.result.logs, + profile: contract_response.result.profile.into(), + aborted: contract_response.result.aborted.map(|err| { + let message = format!("wasm execution failed with error: {:?}", err); + near_jsonrpc::primitives::types::query::RpcQueryError::ContractExecutionError { + vm_error: message, + block_height: contract_response.block_height, + block_hash: contract_response.block_hash, + } + }), + } + } +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +pub enum EmulateTransactionActionResult { + CreateAccount { + fee: near_primitives::types::Gas, + }, + DeployContract { + fee: near_primitives::types::Gas, + }, + FunctionCall { + outcome: Box, + fee: near_primitives::types::Gas, + }, + Transfer { + fee: near_primitives::types::Gas, + }, + Stake { + fee: near_primitives::types::Gas, + }, + AddKey { + fee: near_primitives::types::Gas, + }, + DeleteKey { + fee: near_primitives::types::Gas, + }, + DeleteAccount { + fee: near_primitives::types::Gas, + }, + Delegate { + fee: near_primitives::types::Gas, + }, + DeployGlobalContract { + fee: near_primitives::types::Gas, + }, + UseGlobalContract { + fee: near_primitives::types::Gas, + }, +} + +impl EmulateTransactionActionResult { + pub fn from_tx_action( + tx_action: &near_primitives::transaction::Action, + fee: near_primitives::types::Gas, + ) -> Self { + match tx_action { + near_primitives::transaction::Action::CreateAccount(_) => Self::CreateAccount { fee }, + near_primitives::transaction::Action::DeployContract(_) => Self::DeployContract { fee }, + near_primitives::transaction::Action::FunctionCall(_) => Self::FunctionCall { + outcome: Box::new(FunctionCallOutcome::default()), + fee, + }, + near_primitives::transaction::Action::Transfer(_) => Self::Transfer { fee }, + near_primitives::transaction::Action::Stake(_) => Self::Stake { fee }, + near_primitives::transaction::Action::AddKey(_) => Self::AddKey { fee }, + near_primitives::transaction::Action::DeleteKey(_) => Self::DeleteKey { fee }, + near_primitives::transaction::Action::DeleteAccount(_) => Self::DeleteAccount { fee }, + near_primitives::transaction::Action::Delegate(_) => Self::Delegate { fee }, + near_primitives::transaction::Action::DeployGlobalContract(_) => { + Self::DeployGlobalContract { fee } + } + near_primitives::transaction::Action::UseGlobalContract(_) => { + Self::UseGlobalContract { fee } + } + } + } + + pub fn fee(&self) -> near_primitives::types::Gas { + match self { + EmulateTransactionActionResult::CreateAccount { fee } + | EmulateTransactionActionResult::DeployContract { fee } + | EmulateTransactionActionResult::Transfer { fee } + | EmulateTransactionActionResult::Stake { fee } + | EmulateTransactionActionResult::AddKey { fee } + | EmulateTransactionActionResult::DeleteKey { fee } + | EmulateTransactionActionResult::DeleteAccount { fee } + | EmulateTransactionActionResult::Delegate { fee } + | EmulateTransactionActionResult::DeployGlobalContract { fee } + | EmulateTransactionActionResult::UseGlobalContract { fee } + | EmulateTransactionActionResult::FunctionCall { fee, .. } => *fee, + } + } +} + +#[derive(serde::Serialize, serde::Deserialize, Debug)] +pub struct EmulateTransactionResponse { + pub results: Vec, + pub block_height: near_primitives::types::BlockHeight, + pub gas_price: near_primitives::types::Balance, + pub total_fee: near_primitives::types::Gas, +} + +impl near_jsonrpc_client::methods::RpcHandlerResponse for EmulateTransactionResponse {} + +/// Collector for transaction actions, providing thread-safe storage and retrieval. +/// +/// Stores a vector of `Action` instances using an async RwLock. +#[derive(Default)] +pub struct TxActionsCollector { + inner: futures_locks::RwLock>, +} + +impl TxActionsCollector { + /// Creates a new, empty `TxActionsCollector`. + pub fn new() -> Self { + Self { + inner: futures_locks::RwLock::new(Vec::new()), + } + } + + /// Pushes a new `Action` into the collector. + /// + /// This method blocks on acquiring a write lock. + pub fn push_mock_action( + &self, + mock_action: near_vm_runner::logic::mocks::mock_external::MockAction, + ) { + let tx_action = match mock_action { + near_vm_runner::logic::mocks::mock_external::MockAction::CreateAccount { .. } => { + Some(near_primitives::transaction::Action::CreateAccount( + near_primitives::transaction::CreateAccountAction {}, + )) + } + near_vm_runner::logic::mocks::mock_external::MockAction::DeployContract { + code, + .. + } => Some(near_primitives::transaction::Action::DeployContract( + near_primitives::transaction::DeployContractAction { code }, + )), + near_vm_runner::logic::mocks::mock_external::MockAction::FunctionCallWeight { + method_name, + args, + gas_weight, + .. + } => Some(near_primitives::transaction::Action::FunctionCall( + Box::new(near_primitives::transaction::FunctionCallAction { + method_name: String::from_utf8(method_name) + .expect("Method name should be valid UTF-8"), + args, + gas: gas_weight.0, + deposit: 0, + }), + )), + near_vm_runner::logic::mocks::mock_external::MockAction::Transfer { + deposit, .. + } => Some(near_primitives::transaction::Action::Transfer( + near_primitives::transaction::TransferAction { deposit }, + )), + near_vm_runner::logic::mocks::mock_external::MockAction::Stake { + stake, + public_key, + .. + } => Some(near_primitives::transaction::Action::Stake(Box::new( + near_primitives::transaction::StakeAction { stake, public_key }, + ))), + near_vm_runner::logic::mocks::mock_external::MockAction::AddKeyWithFullAccess { + public_key, + nonce, + .. + } => Some(near_primitives::transaction::Action::AddKey(Box::new( + near_primitives::transaction::AddKeyAction { + public_key, + access_key: near_primitives::account::AccessKey { + nonce, + permission: near_primitives::account::AccessKeyPermission::FullAccess, + }, + }, + ))), + near_vm_runner::logic::mocks::mock_external::MockAction::AddKeyWithFunctionCall { + public_key, + nonce, + allowance, + receiver_id, + method_names, + .. + } => Some(near_primitives::transaction::Action::AddKey(Box::new( + near_primitives::transaction::AddKeyAction { + public_key, + access_key: near_primitives::account::AccessKey { + nonce, + permission: near_primitives::account::AccessKeyPermission::FunctionCall( + near_primitives::account::FunctionCallPermission { + allowance, + receiver_id: receiver_id.into(), + method_names: method_names + .into_iter() + .map(|method_name| { + String::from_utf8(method_name) + .expect("Method name should be valid UTF-8") + }) + .collect(), + }, + ), + }, + }, + ))), + near_vm_runner::logic::mocks::mock_external::MockAction::DeleteKey { + public_key, + .. + } => Some(near_primitives::transaction::Action::DeleteKey(Box::new( + near_primitives::transaction::DeleteKeyAction { public_key }, + ))), + near_vm_runner::logic::mocks::mock_external::MockAction::DeleteAccount { + beneficiary_id, + .. + } => Some(near_primitives::transaction::Action::DeleteAccount( + near_primitives::transaction::DeleteAccountAction { beneficiary_id }, + )), + _ => { + // For unsupported actions, we can log or handle them as needed. + None + } + }; + if let Some(action) = tx_action { + futures::executor::block_on(async { self.inner.write().await.push(action) }); + } + } + + /// Asynchronously retrieves a clone of all collected actions. + pub async fn get_actions(&self) -> Vec { + self.inner.read().await.clone() + } +} diff --git a/rpc-server/src/utils.rs b/rpc-server/src/utils.rs index 170c8686..3dbb7ece 100644 --- a/rpc-server/src/utils.rs +++ b/rpc-server/src/utils.rs @@ -129,8 +129,8 @@ pub async fn get_current_protocol_version( near_rpc_client: &JsonRpcClient, ) -> anyhow::Result { let params = near_jsonrpc_client::methods::status::RpcStatusRequest; - let protocol_version = near_rpc_client.call(params, None).await?.protocol_version; - Ok(protocol_version) + let protocol_version = near_rpc_client.call(params, None).await?; + Ok(protocol_version.protocol_version) } async fn handle_streamer_message( diff --git a/rust-toolchain b/rust-toolchain index f288d111..b7844a6f 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.85.0 +1.86.0 diff --git a/scripts/apply_all_migrations.sh b/scripts/apply_all_migrations.sh new file mode 100644 index 00000000..ebeeb843 --- /dev/null +++ b/scripts/apply_all_migrations.sh @@ -0,0 +1,144 @@ +#!/bin/bash +# Apply all database migrations for NEAR Read RPC project +# +# This script applies migrations to all database types: +# - Meta database +# - Shard databases +# - Transaction details databases +# +# Prerequisites: +# - SQLx CLI installed: cargo install sqlx-cli --no-default-features --features native-tls,postgres +# - Environment variables set for database URLs +# +# Usage: ./scripts/apply_all_migrations.sh + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check if SQLx CLI is installed +if ! command -v sqlx &> /dev/null; then + print_error "SQLx CLI is not installed. Please install it with:" + echo "cargo install sqlx-cli --no-default-features --features native-tls,postgres" + exit 1 +fi + +# Get the project root directory +PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +MIGRATIONS_DIR="$PROJECT_ROOT/database/src/postgres/migrations" + +# Check if migrations directory exists +if [ ! -d "$MIGRATIONS_DIR" ]; then + print_error "Migrations directory not found: $MIGRATIONS_DIR" + exit 1 +fi + +print_status "Starting database migrations for NEAR Read RPC..." +print_status "Project root: $PROJECT_ROOT" + +# Function to run migrations for a specific database and path +run_migrations() { + local db_url="$1" + local migration_path="$2" + local db_name="$3" + + if [ -z "$db_url" ]; then + print_warning "Skipping $db_name - database URL not set" + return 0 + fi + + print_status "Applying migrations to $db_name..." + print_status "Database URL: $db_url" + print_status "Migration path: $migration_path" + + export DATABASE_URL="$db_url" + + if [ ! -d "$migration_path" ]; then + print_warning "Migration directory not found: $migration_path" + return 0 + fi + + # Check if there are any migration files + if [ -z "$(find "$migration_path" -name "*.sql" -type f)" ]; then + print_warning "No migration files found in $migration_path" + return 0 + fi + + # Change to migration directory and run migrations + cd "$migration_path" + + # Test database connection first + if ! sqlx database create 2>/dev/null; then + print_status "Database already exists or connection successful" + fi + + # Run migrations + if sqlx migrate run; then + print_status "✓ Successfully applied migrations to $db_name" + else + print_error "✗ Failed to apply migrations to $db_name" + return 1 + fi + + echo "" +} + +# 1. Apply Meta Database migrations +print_status "=== Meta Database Migrations ===" +run_migrations "$META_DATABASE_URL" "$MIGRATIONS_DIR/meta_db" "Meta Database" + +# Apply receipts and outcomes migrations to Meta Database +if [ ! -z "$META_DATABASE_URL" ]; then + run_migrations "$META_DATABASE_URL" "$MIGRATIONS_DIR/tx_details/receipts_and_outcomes" "Meta Database - Receipts and Outcomes" +fi + +# 2. Apply Shard Database migrations +print_status "=== Shard Database Migrations ===" + +# List of shard database environment variables +SHARD_DBS=( + "SHARD_0_DATABASE_URL" + "SHARD_1_DATABASE_URL" + "SHARD_2_DATABASE_URL" + "SHARD_3_DATABASE_URL" + "SHARD_4_DATABASE_URL" + "SHARD_5_DATABASE_URL" +) + +for shard_var in "${SHARD_DBS[@]}"; do + shard_url="${!shard_var}" + if [ ! -z "$shard_url" ]; then + run_migrations "$shard_url" "$MIGRATIONS_DIR/shard_db" "Shard Database ($shard_var)" + # Apply transactions migrations to each shard database + run_migrations "$shard_url" "$MIGRATIONS_DIR/tx_details/transactions" "Shard Database ($shard_var) - Transactions" + fi +done + +# 3. Summary +print_status "=== Migration Summary ===" +print_status "All database migrations completed successfully!" +print_status "" +print_status "Next steps:" +print_status "1. Verify migrations with: sqlx migrate info" +print_status "2. Start your application services" +print_status "3. Check application logs for any issues" + +# Return to original directory +cd "$PROJECT_ROOT" diff --git a/state-indexer/Dockerfile b/state-indexer/Dockerfile index c0099d0d..b5c00b97 100644 --- a/state-indexer/Dockerfile +++ b/state-indexer/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.85 AS builder +FROM rust:1.86 AS builder ARG features="default" ARG profile="release" WORKDIR /tmp/ diff --git a/tx-details-storage/Cargo.toml b/tx-details-storage/Cargo.toml index 91e246fa..ebdece09 100644 --- a/tx-details-storage/Cargo.toml +++ b/tx-details-storage/Cargo.toml @@ -10,10 +10,14 @@ license.workspace = true # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +async-trait = "0.1.88" anyhow = "1.0.70" +bigdecimal = "0.4" num-bigint = "0.3.3" num-traits = "0.2.19" futures = "0.3.31" scylla = { version = "0.15.1", features = ["ssl", "full-serialization"] } +database.workspace = true +near-primitives.workspace = true readnode-primitives.workspace = true diff --git a/tx-details-storage/README.md b/tx-details-storage/README.md index 86699cea..0148bd85 100644 --- a/tx-details-storage/README.md +++ b/tx-details-storage/README.md @@ -1,6 +1,12 @@ # tx-details-storage -This is a small library that provides the interface to store and retrieve `TransactionDetails` to/from bucket. The functionality is extracted into this separate library to provide a common interface for all the components that need to store and retrieve `TransactionDetails` (e.g. `tx-indexer` and `rpc-server`). +This is a small library that provides the interface to store and retrieve `TransactionDetails` to/from different storage engines: +* ScyllaDB - recommeded for archival nodes +* PostgreSQL - recommended for regular nodes + +The choice of the storage engine is made in configuration `tx_details_storage_provider` parameter in `config.toml` file in the project root. The default value is `postgres`, but it can be changed to `scylla` if needed. + +The functionality is extracted into this separate library to provide a common interface for all the components that need to store and retrieve `TransactionDetails` (e.g. `tx-indexer` and `rpc-server`). `TransactionDetails` is a data class defined in the `readnode-primitives` module, it contains all the details of the transactions: - `SignedTransactionView` itself diff --git a/tx-details-storage/src/drivers/mod.rs b/tx-details-storage/src/drivers/mod.rs new file mode 100644 index 00000000..63337f60 --- /dev/null +++ b/tx-details-storage/src/drivers/mod.rs @@ -0,0 +1,2 @@ +pub mod postgres; +pub mod scylladb; diff --git a/tx-details-storage/src/drivers/postgres.rs b/tx-details-storage/src/drivers/postgres.rs new file mode 100644 index 00000000..6fbf0ef4 --- /dev/null +++ b/tx-details-storage/src/drivers/postgres.rs @@ -0,0 +1,84 @@ +use crate::traits::Storage; +use anyhow::Result; +use async_trait::async_trait; +use database::TxIndexerDbManager; +use std::sync::Arc; + +pub struct PostgresTxDetailsStorage { + db_manager: Arc, +} + +impl PostgresTxDetailsStorage { + /// Creates a new instance of `PostgresTxDetailsStorage`. + pub async fn new(db_manager: Arc) -> Result { + db_manager.create_tx_tables().await?; + Ok(Self { db_manager }) + } +} + +#[async_trait] +impl Storage for PostgresTxDetailsStorage { + async fn save_tx( + &self, + sender_id: &near_primitives::types::AccountId, + key: &str, + data: Vec, + block_height: u64, + ) -> Result<()> { + self.db_manager + .save_transaction(sender_id, key, data, block_height) + .await + } + + async fn retrieve_tx( + &self, + key: &str, + shard_id: &near_primitives::types::ShardId, + ) -> Result> { + self.db_manager.retrieve_transaction(key, shard_id).await + } + + async fn save_receipts(&self, receipts: Vec) -> Result<()> { + self.db_manager.save_receipts(receipts).await + } + + async fn get_receipt_by_id( + &self, + receipt_id: &str, + ) -> Result { + self.db_manager.get_receipt_by_id(receipt_id).await + } + + async fn save_outcomes(&self, outcomes: Vec) -> Result<()> { + self.db_manager.save_outcomes(outcomes).await + } + + async fn get_outcome_by_id( + &self, + outcome_id: &str, + ) -> Result { + self.db_manager.get_outcome_by_id(outcome_id).await + } + + async fn update_meta(&self, indexer_id: &str, last_processed_block_height: u64) -> Result<()> { + self.db_manager + .update_meta(indexer_id, last_processed_block_height) + .await + } + + async fn get_last_processed_block_height(&self, indexer_id: &str) -> Result { + self.db_manager + .get_last_processed_block_height(indexer_id) + .await + } + + async fn save_outcomes_and_receipts( + &self, + receipts: Vec, + outcomes: Vec, + ) -> Result<()> { + self.db_manager + .save_outcomes_and_receipts(receipts, outcomes) + .await + } +} diff --git a/tx-details-storage/src/drivers/scylladb.rs b/tx-details-storage/src/drivers/scylladb.rs new file mode 100644 index 00000000..85741d9d --- /dev/null +++ b/tx-details-storage/src/drivers/scylladb.rs @@ -0,0 +1,86 @@ +use anyhow::Result; +use async_trait::async_trait; +use database::TxIndexerDbManager; +use std::sync::Arc; + +use crate::traits::Storage; + +pub struct ScyllaDbTxDetailsStorage { + db_manager: Arc, +} + +impl ScyllaDbTxDetailsStorage { + pub async fn new( + db_manager: Arc, + ) -> anyhow::Result { + db_manager.create_tx_tables().await?; + Ok(Self { db_manager }) + } +} + +#[async_trait] +impl Storage for ScyllaDbTxDetailsStorage { + async fn save_tx( + &self, + sender_id: &near_primitives::types::AccountId, + key: &str, + data: Vec, + block_height: u64, + ) -> Result<()> { + self.db_manager + .save_transaction(sender_id, key, data, block_height) + .await + } + + async fn retrieve_tx( + &self, + key: &str, + shard_id: &near_primitives::types::ShardId, + ) -> Result> { + self.db_manager.retrieve_transaction(key, shard_id).await + } + + async fn save_receipts(&self, receipts: Vec) -> Result<()> { + self.db_manager.save_receipts(receipts).await + } + + async fn get_receipt_by_id( + &self, + receipt_id: &str, + ) -> Result { + self.db_manager.get_receipt_by_id(receipt_id).await + } + + async fn save_outcomes(&self, outcomes: Vec) -> Result<()> { + self.db_manager.save_outcomes(outcomes).await + } + + async fn get_outcome_by_id( + &self, + outcome_id: &str, + ) -> Result { + self.db_manager.get_outcome_by_id(outcome_id).await + } + + async fn update_meta(&self, indexer_id: &str, last_processed_block_height: u64) -> Result<()> { + self.db_manager + .update_meta(indexer_id, last_processed_block_height) + .await + } + + async fn get_last_processed_block_height(&self, indexer_id: &str) -> Result { + self.db_manager + .get_last_processed_block_height(indexer_id) + .await + } + + async fn save_outcomes_and_receipts( + &self, + receipts: Vec, + outcomes: Vec, + ) -> anyhow::Result<()> { + self.db_manager + .save_outcomes_and_receipts(receipts, outcomes) + .await + } +} diff --git a/tx-details-storage/src/lib.rs b/tx-details-storage/src/lib.rs index 9b63d865..4242e6ba 100644 --- a/tx-details-storage/src/lib.rs +++ b/tx-details-storage/src/lib.rs @@ -1,300 +1,6 @@ -use futures::FutureExt; -use num_traits::cast::ToPrimitive; +pub use crate::drivers::postgres::PostgresTxDetailsStorage; +pub use crate::drivers::scylladb::ScyllaDbTxDetailsStorage; +pub use crate::traits::Storage; -pub struct TxDetailsStorage { - add_transaction: scylla::prepared_statement::PreparedStatement, - get_transaction: scylla::prepared_statement::PreparedStatement, - - add_receipt: scylla::prepared_statement::PreparedStatement, - get_receipt: scylla::prepared_statement::PreparedStatement, - - add_outcome: scylla::prepared_statement::PreparedStatement, - get_outcome: scylla::prepared_statement::PreparedStatement, - - update_meta: scylla::prepared_statement::PreparedStatement, - last_processed_block_height: scylla::prepared_statement::PreparedStatement, - - scylla_session: scylla::Session, -} - -impl TxDetailsStorage { - pub async fn new(scylla_session: scylla::Session) -> anyhow::Result { - Self::create_keyspace(&scylla_session).await?; - Self::create_table(&scylla_session).await?; - Ok(Self { - add_transaction: Self::prepare_query( - &scylla_session, - "INSERT INTO tx_details.transactions - (transaction_hash, transaction_details) - VALUES(?, ?)", - scylla::frame::types::Consistency::LocalQuorum, - ).await?, - get_transaction: Self::prepare_query( - &scylla_session, - "SELECT transaction_details FROM tx_details.transactions WHERE transaction_hash = ? LIMIT 1", - scylla::frame::types::Consistency::LocalOne, - ).await?, - add_receipt: Self::prepare_query( - &scylla_session, - "INSERT INTO tx_details.receipts_map - (receipt_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id) - VALUES(?, ?, ?, ?, ?, ?)", - scylla::frame::types::Consistency::LocalQuorum, - ).await?, - get_receipt: Self::prepare_query( - &scylla_session, - "SELECT receipt_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id FROM tx_details.receipts_map WHERE receipt_id = ? LIMIT 1", - scylla::frame::types::Consistency::LocalOne, - ).await?, - add_outcome: Self::prepare_query( - &scylla_session, - "INSERT INTO tx_details.outcomes_map - (outcome_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id) - VALUES(?, ?, ?, ?, ?, ?)", - scylla::frame::types::Consistency::LocalQuorum, - ).await?, - get_outcome: Self::prepare_query( - &scylla_session, - "SELECT outcome_id, parent_transaction_hash, receiver_id, block_height, block_hash, shard_id FROM tx_details.outcomes_map WHERE outcome_id = ? LIMIT 1", - scylla::frame::types::Consistency::LocalOne, - ).await?, - update_meta: Self::prepare_query( - &scylla_session, - "INSERT INTO tx_details.meta - (indexer_id, last_processed_block_height) - VALUES (?, ?)", - scylla::frame::types::Consistency::LocalQuorum, - ).await?, - last_processed_block_height: Self::prepare_query( - &scylla_session, - "SELECT last_processed_block_height FROM tx_details.meta WHERE indexer_id = ? LIMIT 1", - scylla::frame::types::Consistency::LocalOne, - ).await?, - scylla_session, - }) - } - - async fn prepare_query( - scylla_db_session: &scylla::Session, - query_text: &str, - consistency: scylla::frame::types::Consistency, - ) -> anyhow::Result { - let mut query = scylla::statement::query::Query::new(query_text); - query.set_consistency(consistency); - Ok(scylla_db_session.prepare(query).await?) - } - - pub async fn create_keyspace(scylla_session: &scylla::Session) -> anyhow::Result<()> { - scylla_session - .query_unpaged( - "CREATE KEYSPACE IF NOT EXISTS tx_details - WITH REPLICATION = { - 'class': 'NetworkTopologyStrategy', - 'replication_factor': 3 - }", - &[], - ) - .await?; - Ok(()) - } - - pub async fn create_table(scylla_session: &scylla::Session) -> anyhow::Result<()> { - scylla_session - .query_unpaged( - "CREATE TABLE IF NOT EXISTS tx_details.transactions ( - transaction_hash varchar PRIMARY KEY, - transaction_details BLOB - )", - &[], - ) - .await?; - scylla_session - .query_unpaged( - "CREATE TABLE IF NOT EXISTS tx_details.receipts_map ( - receipt_id varchar PRIMARY KEY, - parent_transaction_hash varchar, - receiver_id varchar, - block_height varint, - block_hash varchar, - shard_id varint - )", - &[], - ) - .await?; - scylla_session - .query_unpaged( - "CREATE TABLE IF NOT EXISTS tx_details.outcomes_map ( - outcome_id varchar PRIMARY KEY, - parent_transaction_hash varchar, - receiver_id varchar, - block_height varint, - block_hash varchar, - shard_id varint - )", - &[], - ) - .await?; - scylla_session - .query_unpaged( - " - CREATE TABLE IF NOT EXISTS tx_details.meta ( - indexer_id varchar PRIMARY KEY, - last_processed_block_height varint - ) - ", - &[], - ) - .await?; - Ok(()) - } - - pub async fn save_tx(&self, key: &str, data: Vec) -> anyhow::Result<()> { - self.scylla_session - .execute_unpaged(&self.add_transaction, (key, data)) - .await?; - Ok(()) - } - - pub async fn retrieve_tx(&self, key: &str) -> anyhow::Result> { - let (data,) = self - .scylla_session - .execute_unpaged(&self.get_transaction, (key.to_string(),)) - .await? - .into_rows_result()? - .single_row::<(Vec,)>()?; - Ok(data) - } - - pub async fn save_receipts( - &self, - receipts: Vec, - ) -> anyhow::Result<()> { - if receipts.is_empty() { - return Ok(()); - } - let mut batch: scylla::batch::Batch = Default::default(); - let mut batch_values = Vec::new(); - for receipt in receipts { - batch.append_statement(self.add_receipt.clone()); - let shard_id: u64 = receipt.shard_id.into(); - batch_values.push(( - receipt.receipt_id.to_string(), - receipt.parent_transaction_hash.to_string(), - receipt.receiver_id.to_string(), - num_bigint::BigInt::from(receipt.block_height), - receipt.block_hash.to_string(), - num_bigint::BigInt::from(shard_id), - )); - } - self.scylla_session.batch(&batch, batch_values).await?; - Ok(()) - } - - pub async fn get_receipt_by_id( - &self, - receipt_id: &str, - ) -> anyhow::Result { - readnode_primitives::ReceiptRecord::try_from( - self.scylla_session - .execute_unpaged(&self.get_receipt, (receipt_id.to_string(),)) - .await? - .into_rows_result()? - .single_row::<( - String, - String, - String, - num_bigint::BigInt, - String, - num_bigint::BigInt, - )>()?, - ) - } - - pub async fn save_outcomes( - &self, - outcomes: Vec, - ) -> anyhow::Result<()> { - if outcomes.is_empty() { - return Ok(()); - } - let mut batch: scylla::batch::Batch = Default::default(); - let mut batch_values = Vec::new(); - for outcome in outcomes { - batch.append_statement(self.add_outcome.clone()); - let shard_id: u64 = outcome.shard_id.into(); - batch_values.push(( - outcome.outcome_id.to_string(), - outcome.parent_transaction_hash.to_string(), - outcome.receiver_id.to_string(), - num_bigint::BigInt::from(outcome.block_height), - outcome.block_hash.to_string(), - num_bigint::BigInt::from(shard_id), - )); - } - self.scylla_session.batch(&batch, batch_values).await?; - Ok(()) - } - - pub async fn get_outcome_by_id( - &self, - outcome_id: &str, - ) -> anyhow::Result { - readnode_primitives::OutcomeRecord::try_from( - self.scylla_session - .execute_unpaged(&self.get_outcome, (outcome_id.to_string(),)) - .await? - .into_rows_result()? - .single_row::<( - String, - String, - String, - num_bigint::BigInt, - String, - num_bigint::BigInt, - )>()?, - ) - } - - pub async fn save_outcomes_and_receipts( - &self, - receipts: Vec, - outcomes: Vec, - ) -> anyhow::Result<()> { - let save_outcome_future = self.save_outcomes(outcomes); - let save_receipt_future = self.save_receipts(receipts); - - futures::future::join_all([save_outcome_future.boxed(), save_receipt_future.boxed()]) - .await - .into_iter() - .collect::>() - } - - pub async fn update_meta( - &self, - indexer_id: &str, - last_processed_block_height: u64, - ) -> anyhow::Result<()> { - self.scylla_session - .execute_unpaged( - &self.update_meta, - ( - indexer_id.to_string(), - num_bigint::BigInt::from(last_processed_block_height), - ), - ) - .await?; - Ok(()) - } - - pub async fn get_last_processed_block_height(&self, indexer_id: &str) -> anyhow::Result { - let (last_processed_block_height,) = self - .scylla_session - .execute_unpaged(&self.last_processed_block_height, (indexer_id.to_string(),)) - .await? - .into_rows_result()? - .single_row::<(num_bigint::BigInt,)>()?; - last_processed_block_height.to_u64().ok_or(anyhow::anyhow!( - "Failed to convert last_processed_block_height to u64" - )) - } -} +pub mod drivers; +mod traits; diff --git a/tx-details-storage/src/traits.rs b/tx-details-storage/src/traits.rs new file mode 100644 index 00000000..627d69e0 --- /dev/null +++ b/tx-details-storage/src/traits.rs @@ -0,0 +1,35 @@ +use anyhow::Result; +use async_trait::async_trait; + +#[async_trait] +pub trait Storage { + async fn save_tx( + &self, + sender_id: &near_primitives::types::AccountId, + key: &str, + data: Vec, + block_height: u64, + ) -> Result<()>; + async fn retrieve_tx( + &self, + key: &str, + shard_id: &near_primitives::types::ShardId, + ) -> Result>; + async fn save_receipts(&self, receipts: Vec) -> Result<()>; + async fn get_receipt_by_id( + &self, + receipt_id: &str, + ) -> Result; + async fn save_outcomes(&self, outcomes: Vec) -> Result<()>; + async fn save_outcomes_and_receipts( + &self, + receipts: Vec, + outcomes: Vec, + ) -> Result<()>; + async fn get_outcome_by_id( + &self, + outcome_id: &str, + ) -> Result; + async fn update_meta(&self, indexer_id: &str, last_processed_block_height: u64) -> Result<()>; + async fn get_last_processed_block_height(&self, indexer_id: &str) -> Result; +} diff --git a/tx-indexer/Cargo.toml b/tx-indexer/Cargo.toml index 2680ce91..f7a33af1 100644 --- a/tx-indexer/Cargo.toml +++ b/tx-indexer/Cargo.toml @@ -31,6 +31,7 @@ tokio-retry = "0.3" tokio-stream = "0.1.12" tracing = "0.1.34" +database.workspace = true cache-storage.workspace = true configuration.workspace = true readnode-primitives.workspace = true diff --git a/tx-indexer/Dockerfile b/tx-indexer/Dockerfile index cabe842a..b04c1350 100644 --- a/tx-indexer/Dockerfile +++ b/tx-indexer/Dockerfile @@ -1,4 +1,4 @@ -FROM rust:1.85 AS builder +FROM rust:1.86 AS builder ARG features="default" ARG profile="release" WORKDIR /tmp/ diff --git a/tx-indexer/README.md b/tx-indexer/README.md index 8b52d85c..352cce96 100644 --- a/tx-indexer/README.md +++ b/tx-indexer/README.md @@ -36,6 +36,7 @@ In order to collect a `Transactions` with all related entities it does the follo An example `.env` file: ``` INDEXER_ID=tx-indexer +TX_DETAILS_STORAGE_PROVIDER=scylla DATABASE_URL=127.0.0.1:9042 DATABASE_USER=admin DATABASE_PASSWORD=password @@ -44,7 +45,8 @@ AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY AWS_DEFAULT_REGION=eu-central-1 ``` -### Features + +In case of `TX_DETAILS_STORAGE_PROVIDER=postgres`, the database credentials and connections from the `rpc-server` will be used. ### Command to run diff --git a/tx-indexer/src/collector.rs b/tx-indexer/src/collector.rs index 029997bd..0b66c68c 100644 --- a/tx-indexer/src/collector.rs +++ b/tx-indexer/src/collector.rs @@ -16,7 +16,7 @@ const SAVE_ATTEMPTS: usize = 20; pub(crate) async fn index_transactions( streamer_message: &near_indexer_primitives::StreamerMessage, tx_collecting_storage: &std::sync::Arc, - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, indexer_config: &configuration::TxIndexerConfig, ) -> anyhow::Result<()> { extract_transactions_to_collect(streamer_message, tx_collecting_storage, indexer_config) @@ -40,7 +40,7 @@ pub(crate) async fn index_transactions( async fn save_finished_transaction_details( tx_collecting_storage: &std::sync::Arc, - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, ) -> anyhow::Result<()> { let finished_transaction_details = tx_collecting_storage @@ -76,7 +76,7 @@ async fn save_finished_transaction_details( } async fn save_outcomes_and_receipts( - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, tx_collecting_storage: &std::sync::Arc, ) -> anyhow::Result<()> { let receipts_and_outcomes_to_save = tx_collecting_storage @@ -112,7 +112,7 @@ async fn save_outcomes_and_receipts( /// We use 1500 records because we should be sure that the batch size is less than 50MB #[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip_all))] async fn save_receipts_and_outcomes_details( - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, tx_collecting_storage: &std::sync::Arc, receipts: Vec, outcomes: Vec, @@ -153,7 +153,7 @@ async fn save_receipts_and_outcomes_details( #[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip_all))] async fn save_chunks_receipts_and_outcomes_details( - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, tx_collecting_storage: &std::sync::Arc, receipts: Vec, outcomes: Vec, @@ -185,7 +185,7 @@ async fn save_chunks_receipts_and_outcomes_details( } async fn save_outcome_and_receipt_to_scylla( - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, receipts: Vec, outcomes: Vec, ) -> anyhow::Result<()> { @@ -441,7 +441,7 @@ async fn process_receipt_execution_outcome( #[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip_all))] async fn save_transaction_details( tx_collecting_storage: &std::sync::Arc, - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, tx_details: readnode_primitives::CollectingTransactionDetails, ) { let tx_key = tx_details.transaction_key(); @@ -484,9 +484,10 @@ async fn save_transaction_details( // Save transaction detail into the storage #[cfg_attr(feature = "tracing-instrumentation", tracing::instrument(skip_all))] async fn save_transaction_details_to_storage( - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, tx_details: readnode_primitives::CollectingTransactionDetails, ) -> anyhow::Result<()> { + let sender_id = tx_details.transaction.signer_id.clone(); let transaction_details = tx_details.to_final_transaction_result()?; let transaction_hash = transaction_details.transaction.hash.to_string(); let tx_bytes = transaction_details.tx_serialize()?; @@ -495,7 +496,12 @@ async fn save_transaction_details_to_storage( let operation = || async { tx_details_storage - .save_tx(&transaction_hash, tx_bytes.clone()) + .save_tx( + &sender_id, + &transaction_hash, + tx_bytes.clone(), + tx_details.block_height, + ) .await .map_err(|e| { crate::metrics::TX_STORE_ERRORS_TOTAL.inc(); diff --git a/tx-indexer/src/config.rs b/tx-indexer/src/config.rs index b2f1c391..0797c515 100644 --- a/tx-indexer/src/config.rs +++ b/tx-indexer/src/config.rs @@ -1,5 +1,4 @@ pub use clap::{Parser, Subcommand}; -use tx_details_storage::TxDetailsStorage; /// NEAR Indexer for Explorer /// Watches for stream of blocks from the chain @@ -25,7 +24,7 @@ pub enum StartOptions { pub(crate) async fn get_start_block_height( fastnear_client: &near_lake_framework::FastNearClient, - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, start_options: &StartOptions, indexer_id: &str, ) -> anyhow::Result { diff --git a/tx-indexer/src/main.rs b/tx-indexer/src/main.rs index a6e38c07..bed9751d 100644 --- a/tx-indexer/src/main.rs +++ b/tx-indexer/src/main.rs @@ -1,6 +1,5 @@ use clap::Parser; use futures::{FutureExt, StreamExt}; -use tx_details_storage::TxDetailsStorage; mod collector; mod config; @@ -31,10 +30,38 @@ async fn main() -> anyhow::Result<()> { .lake_client(indexer_config.general.chain_id.clone()) .await?; - tracing::info!(target: INDEXER, "Instantiating the tx_details storage client..."); - let tx_details_storage = std::sync::Arc::new( - TxDetailsStorage::new(indexer_config.tx_details_storage.scylla_client().await).await?, - ); + tracing::info!(target: INDEXER, "Instantiating the tx_details storage client with {:?} provider...", &indexer_config.tx_details_storage_provider); + let tx_details_storage: std::sync::Arc = + match indexer_config.tx_details_storage_provider { + configuration::StorageProvider::ScyllaDb => { + let scylla_session = indexer_config + .tx_details_storage + .scylla_client() + .await + .expect("Failed to create ScyllaDB client"); + let scylla_db_manager = + database::scylla::tx_indexer::ScyllaDBManager::new(scylla_session).await?; + // Use ScyllaDBManager directly for tx_details_storage, since it does not implement ReaderDbManager + std::sync::Arc::new( + tx_details_storage::ScyllaDbTxDetailsStorage::new(std::sync::Arc::new( + scylla_db_manager, + )) + .await?, + ) + } + configuration::StorageProvider::Postgres => { + let db_manager = database::prepare_db_manager::( + &indexer_config.database, + ) + .await?; + std::sync::Arc::new( + tx_details_storage::PostgresTxDetailsStorage::new(std::sync::Arc::new( + db_manager, + )) + .await?, + ) + } + }; let start_block_height = config::get_start_block_height( &fastnear_client, @@ -103,7 +130,7 @@ async fn main() -> anyhow::Result<()> { async fn handle_streamer_message( streamer_message: near_indexer_primitives::StreamerMessage, tx_collecting_storage: &std::sync::Arc, - tx_details_storage: &std::sync::Arc, + tx_details_storage: &std::sync::Arc, indexer_config: configuration::TxIndexerConfig, stats: std::sync::Arc>, ) -> anyhow::Result {