From df6914e4c2decc5f0f706b4f28f2b9d6c4e995c5 Mon Sep 17 00:00:00 2001 From: Arda Nakisci Date: Fri, 26 Jun 2026 12:44:53 +0300 Subject: [PATCH] Add atomic transaction API --- Cargo.lock | 2107 +++-------------- Cargo.toml | 6 +- flake.lock | 127 +- flake.nix | 3 +- lib/rain.math.float | 2 +- packages/sqlite-web-core/src/coordination.rs | 235 +- packages/sqlite-web-core/src/database.rs | 607 +++++ packages/sqlite-web-core/src/messages.rs | 64 + packages/sqlite-web/src/db.rs | 289 ++- scripts/local-bundle.sh | 4 +- svelte-test/bun.lock | 4 +- svelte-test/package-lock.json | 8 +- svelte-test/package.json | 2 +- .../transaction-interleaving.test.ts | 154 ++ 14 files changed, 1732 insertions(+), 1880 deletions(-) create mode 100644 svelte-test/tests/integration/transaction-interleaving.test.ts diff --git a/Cargo.lock b/Cargo.lock index d003c62..12c99d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,17 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addchain" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" -dependencies = [ - "num-bigint 0.3.3", - "num-integer", - "num-traits", -] - [[package]] name = "addr2line" version = "0.24.2" @@ -52,93 +41,7 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48dff4dd98e17de00203f851800bbc8b76eb29a4d4e3e44074614338b7a3308d" dependencies = [ - "alloy-consensus", - "alloy-contract", "alloy-core", - "alloy-eips", - "alloy-genesis", - "alloy-json-rpc", - "alloy-network", - "alloy-provider", - "alloy-rpc-client", - "alloy-rpc-types", - "alloy-serde", - "alloy-signer", - "alloy-signer-local", - "alloy-transport", - "alloy-transport-http", -] - -[[package]] -name = "alloy-chains" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4195a29a4b87137b2bb02105e746102873bc03561805cf45c0e510c961f160e6" -dependencies = [ - "alloy-primitives", - "num_enum", - "strum", -] - -[[package]] -name = "alloy-consensus" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda689f7287f15bd3582daba6be8d1545bad3740fd1fb778f629a1fe866bb43b" -dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "alloy-trie", - "alloy-tx-macros", - "auto_impl", - "c-kzg", - "derive_more", - "either", - "k256", - "once_cell", - "rand 0.8.5", - "secp256k1", - "serde", - "serde_with", - "thiserror", -] - -[[package]] -name = "alloy-consensus-any" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5659581e41e8fe350ecc3593cb5c9dcffddfd550896390f2b78a07af67b0fa" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-contract" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "944085cf3ac8f32d96299aa26c03db7c8ca6cdaafdbc467910b889f0328e6b70" -dependencies = [ - "alloy-consensus", - "alloy-dyn-abi", - "alloy-json-abi", - "alloy-network", - "alloy-network-primitives", - "alloy-primitives", - "alloy-provider", - "alloy-rpc-types-eth", - "alloy-sol-types", - "alloy-transport", - "futures", - "futures-util", - "serde_json", - "thiserror", ] [[package]] @@ -147,29 +50,11 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d47400608fc869727ad81dba058d55f97b29ad8b5c5256d9598523df8f356ab6" dependencies = [ - "alloy-dyn-abi", "alloy-json-abi", "alloy-primitives", - "alloy-rlp", "alloy-sol-types", ] -[[package]] -name = "alloy-dyn-abi" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9e8a436f0aad7df8bb47f144095fba61202265d9f5f09a70b0e3227881a668e" -dependencies = [ - "alloy-json-abi", - "alloy-primitives", - "alloy-sol-type-parser", - "alloy-sol-types", - "itoa", - "serde", - "serde_json", - "winnow", -] - [[package]] name = "alloy-eip2124" version = "0.2.0" @@ -185,60 +70,65 @@ dependencies = [ [[package]] name = "alloy-eip2930" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" +checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" dependencies = [ "alloy-primitives", "alloy-rlp", + "borsh", "serde", ] [[package]] name = "alloy-eip7702" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" +checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" dependencies = [ "alloy-primitives", "alloy-rlp", + "borsh", "k256", "serde", "thiserror", ] +[[package]] +name = "alloy-eip7928" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b827a6d7784fe3eb3489d40699407a4cdcce74271421a01bdffe60cf573bb16" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "once_cell", + "serde", + "thiserror", +] + [[package]] name = "alloy-eips" -version = "1.0.24" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f35887da30b5fc50267109a3c61cd63e6ca1f45967983641053a40ee83468c1" +checksum = "e6ef28c9fdad22d4eec52d894f5f2673a0895f1e5ef196734568e68c0f6caca8" dependencies = [ "alloy-eip2124", "alloy-eip2930", "alloy-eip7702", + "alloy-eip7928", "alloy-primitives", "alloy-rlp", "alloy-serde", "auto_impl", + "borsh", "c-kzg", "derive_more", "either", "serde", - "sha2 0.10.9", -] - -[[package]] -name = "alloy-genesis" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d4009efea6f403b3a80531f9c6f70fc242399498ff71196a1688cc1c901f44" -dependencies = [ - "alloy-eips", - "alloy-primitives", - "alloy-serde", - "alloy-trie", - "serde", "serde_with", + "sha2", ] [[package]] @@ -253,65 +143,11 @@ dependencies = [ "serde_json", ] -[[package]] -name = "alloy-json-rpc" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "883dee3b4020fcb5667ee627b4f401e899dad82bf37b246620339dd980720ed9" -dependencies = [ - "alloy-primitives", - "alloy-sol-types", - "http", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "alloy-network" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6e5b8ac1654a05c224390008e43634a2bdc74e181e02cf8ed591d8b3d4ad08" -dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-json-rpc", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rpc-types-any", - "alloy-rpc-types-eth", - "alloy-serde", - "alloy-signer", - "alloy-sol-types", - "async-trait", - "auto_impl", - "derive_more", - "futures-utils-wasm", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "alloy-network-primitives" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7980333dd9391719756ac28bc2afa9baa705fc70ffd11dc86ab078dd64477" -dependencies = [ - "alloy-consensus", - "alloy-eips", - "alloy-primitives", - "alloy-serde", - "serde", -] - [[package]] name = "alloy-primitives" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfebde8c581a5d37b678d0a48a32decb51efd7a63a08ce2517ddec26db705c8" +checksum = "4885c1409b6936c4898e646ef58baf6ec54edaf6d8179f79df805a7b85b7cf3e" dependencies = [ "alloy-rlp", "bytes", @@ -319,7 +155,7 @@ dependencies = [ "const-hex", "derive_more", "foldhash", - "hashbrown 0.15.5", + "hashbrown 0.17.1", "indexmap 2.10.0", "itoa", "k256", @@ -327,50 +163,12 @@ dependencies = [ "paste", "proptest", "rand 0.9.2", + "rapidhash", "ruint", "rustc-hash", + "secp256k1", "serde", "sha3", - "tiny-keccak", -] - -[[package]] -name = "alloy-provider" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478a42fe167057b7b919cd8b0c2844f0247f667473340dad100eaf969de5754e" -dependencies = [ - "alloy-chains", - "alloy-consensus", - "alloy-eips", - "alloy-json-rpc", - "alloy-network", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rpc-client", - "alloy-rpc-types-eth", - "alloy-signer", - "alloy-sol-types", - "alloy-transport", - "alloy-transport-http", - "async-stream", - "async-trait", - "auto_impl", - "dashmap", - "either", - "futures", - "futures-utils-wasm", - "lru", - "parking_lot", - "pin-project", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "url", - "wasmtimer", ] [[package]] @@ -395,115 +193,17 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "alloy-rpc-client" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0c6d723fbdf4a87454e2e3a275e161be27edcfbf46e2e3255dd66c138634b6" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "alloy-transport", - "alloy-transport-http", - "futures", - "pin-project", - "reqwest", - "serde", - "serde_json", - "tokio", - "tokio-stream", - "tower", - "tracing", - "url", - "wasmtimer", -] - -[[package]] -name = "alloy-rpc-types" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41492dac39365b86a954de86c47ec23dcc7452cdb2fde591caadc194b3e34c6" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types-eth", - "alloy-serde", - "serde", -] - -[[package]] -name = "alloy-rpc-types-any" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f7eb22670a972ad6c222a6c6dac3eef905579acffe9d63ab42be24c7d158535" -dependencies = [ - "alloy-consensus-any", - "alloy-rpc-types-eth", - "alloy-serde", -] - -[[package]] -name = "alloy-rpc-types-eth" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b777b98526bbe5b7892ca22a7fd5f18ed624ff664a79f40d0f9f2bf94ba79a84" -dependencies = [ - "alloy-consensus", - "alloy-consensus-any", - "alloy-eips", - "alloy-network-primitives", - "alloy-primitives", - "alloy-rlp", - "alloy-serde", - "alloy-sol-types", - "itertools 0.14.0", - "serde", - "serde_json", - "serde_with", - "thiserror", -] - [[package]] name = "alloy-serde" -version = "1.0.24" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8d2c52adebf3e6494976c8542fbdf12f10123b26e11ad56f77274c16a2a039" +checksum = "11ece63b89294b8614ab3f483560c08d016930f842bf36da56bf0b764a15c11e" dependencies = [ "alloy-primitives", "serde", "serde_json", ] -[[package]] -name = "alloy-signer" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c0494d1e0f802716480aabbe25549c7f6bc2a25ff33b08fd332bbb4b7d06894" -dependencies = [ - "alloy-primitives", - "async-trait", - "auto_impl", - "either", - "elliptic-curve", - "k256", - "thiserror", -] - -[[package]] -name = "alloy-signer-local" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c2435eb8979a020763ced3fb478932071c56e5f75ea86db41f320915d325ba" -dependencies = [ - "alloy-consensus", - "alloy-network", - "alloy-primitives", - "alloy-signer", - "async-trait", - "k256", - "rand 0.8.5", - "thiserror", -] - [[package]] name = "alloy-sol-macro" version = "1.3.0" @@ -574,75 +274,6 @@ dependencies = [ "alloy-json-abi", "alloy-primitives", "alloy-sol-macro", - "serde", -] - -[[package]] -name = "alloy-transport" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0107675e10c7f248bf7273c1e7fdb02409a717269cc744012e6f3c39959bfb" -dependencies = [ - "alloy-json-rpc", - "alloy-primitives", - "auto_impl", - "base64 0.22.1", - "derive_more", - "futures", - "futures-utils-wasm", - "parking_lot", - "serde", - "serde_json", - "thiserror", - "tokio", - "tower", - "tracing", - "url", - "wasmtimer", -] - -[[package]] -name = "alloy-transport-http" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78e3736701b5433afd06eecff08f0688a71a10e0e1352e0bbf0bed72f0dd4e35" -dependencies = [ - "alloy-json-rpc", - "alloy-transport", - "reqwest", - "serde_json", - "tower", - "tracing", - "url", -] - -[[package]] -name = "alloy-trie" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bada1fc392a33665de0dc50d401a3701b62583c655e3522a323490a5da016962" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "arrayvec", - "derive_more", - "nybbles", - "serde", - "smallvec", - "tracing", -] - -[[package]] -name = "alloy-tx-macros" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6acb36318dfa50817154064fea7932adf2eec3f51c86680e2b37d7e8906c66bb" -dependencies = [ - "alloy-primitives", - "darling", - "proc-macro2", - "quote", - "syn 2.0.104", ] [[package]] @@ -699,7 +330,7 @@ dependencies = [ "fnv", "hashbrown 0.15.5", "itertools 0.13.0", - "num-bigint 0.4.6", + "num-bigint", "num-integer", "num-traits", "zeroize", @@ -716,7 +347,7 @@ dependencies = [ "ark-serialize 0.3.0", "ark-std 0.3.0", "derivative", - "num-bigint 0.4.6", + "num-bigint", "num-traits", "paste", "rustc_version 0.3.3", @@ -736,7 +367,7 @@ dependencies = [ "derivative", "digest 0.10.7", "itertools 0.10.5", - "num-bigint 0.4.6", + "num-bigint", "num-traits", "paste", "rustc_version 0.4.1", @@ -757,7 +388,7 @@ dependencies = [ "digest 0.10.7", "educe", "itertools 0.13.0", - "num-bigint 0.4.6", + "num-bigint", "num-traits", "paste", "zeroize", @@ -799,7 +430,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ - "num-bigint 0.4.6", + "num-bigint", "num-traits", "quote", "syn 1.0.109", @@ -811,7 +442,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ - "num-bigint 0.4.6", + "num-bigint", "num-traits", "proc-macro2", "quote", @@ -824,7 +455,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" dependencies = [ - "num-bigint 0.4.6", + "num-bigint", "num-traits", "proc-macro2", "quote", @@ -857,7 +488,7 @@ dependencies = [ "ark-relations", "ark-std 0.5.0", "educe", - "num-bigint 0.4.6", + "num-bigint", "num-integer", "num-traits", "tracing", @@ -893,7 +524,7 @@ checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ "ark-std 0.4.0", "digest 0.10.7", - "num-bigint 0.4.6", + "num-bigint", ] [[package]] @@ -906,7 +537,7 @@ dependencies = [ "ark-std 0.5.0", "arrayvec", "digest 0.10.7", - "num-bigint 0.4.6", + "num-bigint", ] [[package]] @@ -961,37 +592,12 @@ name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -dependencies = [ - "serde", -] - -[[package]] -name = "async-stream" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" -dependencies = [ - "async-stream-impl", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-stream-impl" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] [[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", @@ -1064,15 +670,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - [[package]] name = "bit-set" version = "0.8.0" @@ -1106,11 +703,11 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -1126,42 +723,29 @@ dependencies = [ "wyz", ] -[[package]] -name = "blake3" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", -] - [[package]] name = "block-buffer" -version = "0.9.0" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] name = "blst" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd49896f12ac9b6dcd7a5998466b9b58263a695a3dd1ecc1aaca2e12a90b080" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" dependencies = [ "cc", "glob", @@ -1169,6 +753,30 @@ dependencies = [ "zeroize", ] +[[package]] +name = "borsh" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3f6da4992df95bbcd9af42a6c7dcb994498fc9048230405f3b36ff7cd3f145" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae8fb4fb5740e4b2c4884ff95f5f32f5e8479db1e8fd8eb49ddbe09eb09bb7c" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.104", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -1198,9 +806,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "2.1.1" +version = "2.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7318cfa722931cb5fe0838b98d3ce5621e75f6a6408abc21721d80de9223f2e4" +checksum = "6648ed1e4ea8e8a1a4a2c78e1cda29a3fd500bc622899c340d8525ea9a76b24a" dependencies = [ "blst", "cc", @@ -1211,6 +819,12 @@ dependencies = [ "serde", ] +[[package]] +name = "cast" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" + [[package]] name = "cc" version = "1.2.32" @@ -1226,6 +840,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.41" @@ -1256,7 +876,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83e22e0ed40b96a48d3db274f72fd365bd78f67af39b6bbd47e8a15e1c6207ff" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "hex", "proptest", "serde", @@ -1289,32 +909,25 @@ dependencies = [ ] [[package]] -name = "constant_time_eq" -version = "0.3.1" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "core-foundation" -version = "0.9.4" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "core-foundation-sys", "libc", ] -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -1334,12 +947,6 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - [[package]] name = "crunchy" version = "0.2.4" @@ -1368,6 +975,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "crypto-common" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +dependencies = [ + "hybrid-array", +] + [[package]] name = "darling" version = "0.20.11" @@ -1403,20 +1019,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", -] - [[package]] name = "der" version = "0.7.10" @@ -1497,19 +1099,18 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", - "crypto-common", + "crypto-common 0.1.6", "subtle", ] [[package]] -name = "displaydoc" -version = "0.2.5" +name = "digest" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", + "block-buffer 0.12.1", + "crypto-common 0.2.2", ] [[package]] @@ -1534,7 +1135,6 @@ dependencies = [ "digest 0.10.7", "elliptic-curve", "rfc6979", - "serdect", "signature", "spki", ] @@ -1575,7 +1175,6 @@ dependencies = [ "pkcs8", "rand_core 0.6.4", "sec1", - "serdect", "subtle", "zeroize", ] @@ -1641,160 +1240,60 @@ checksum = "ce8dba4714ef14b8274c371879b175aa55b16b30f269663f19d576f380018dc4" dependencies = [ "arrayvec", "auto_impl", - "bytes", -] - -[[package]] -name = "ff" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" -dependencies = [ - "byteorder", - "ff_derive", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "ff_derive" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f10d12652036b0e99197587c6ba87a8fc3031986499973c030d8b44fcc151b60" -dependencies = [ - "addchain", - "num-bigint 0.3.3", - "num-integer", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand 0.8.5", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fragile" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + "bytes", +] [[package]] -name = "futures" -version = "0.3.31" +name = "ff" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", + "rand_core 0.6.4", + "subtle", ] [[package]] -name = "futures-channel" -version = "0.3.31" +name = "fixed-hash" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ - "futures-core", - "futures-sink", + "byteorder", + "rand 0.8.5", + "rustc-hex", + "static_assertions", ] [[package]] -name = "futures-core" -version = "0.3.31" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "futures-executor" -version = "0.3.31" +name = "foldhash" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] -name = "futures-io" -version = "0.3.31" +name = "fragile" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "28dd6caf6059519a65843af8fe2a3ae298b14b80179855aeb4adc2c1934ee619" [[package]] -name = "futures-macro" -version = "0.3.31" +name = "funty" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] -name = "futures-sink" +name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-task" @@ -1808,30 +1307,13 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ - "futures-channel", "futures-core", - "futures-io", - "futures-macro", - "futures-sink", "futures-task", - "memchr", "pin-project-lite", "pin-utils", "slab", ] -[[package]] -name = "futures-utils-wasm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" - -[[package]] -name = "gcd" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" - [[package]] name = "generic-array" version = "0.14.7" @@ -1899,20 +1381,22 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", +] [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ - "allocator-api2", - "equivalent", "foldhash", "serde", + "serde_core", ] [[package]] @@ -1955,102 +1439,12 @@ dependencies = [ ] [[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "hyper" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.16" +name = "hybrid-array" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" dependencies = [ - "base64 0.22.1", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", + "typenum", ] [[package]] @@ -2077,119 +1471,12 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" -dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locale_core" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_normalizer" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" - -[[package]] -name = "icu_properties" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "potential_utf", - "zerotrie", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" - -[[package]] -name = "icu_provider" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" -dependencies = [ - "displaydoc", - "icu_locale_core", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", -] - [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - [[package]] name = "impl-codec" version = "0.6.0" @@ -2243,22 +1530,6 @@ dependencies = [ "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 = "itertools" version = "0.10.5" @@ -2268,15 +1539,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -2286,15 +1548,6 @@ 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" @@ -2303,11 +1556,12 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] @@ -2321,43 +1575,29 @@ dependencies = [ "ecdsa", "elliptic-curve", "once_cell", - "serdect", - "sha2 0.10.9", + "sha2", ] [[package]] name = "keccak" -version = "0.1.5" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" dependencies = [ - "cpufeatures", + "cfg-if", + "cpufeatures 0.3.0", ] [[package]] name = "keccak-asm" -version = "0.1.4" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "505d1856a39b200489082f90d897c3f07c455563880bc5952e38eabf731c83b6" +checksum = "dd5dc2c0d691cbf7595cde551ced329cca99c2387c2cbc97754c5d0cd045d3ee" dependencies = [ "digest 0.10.7", "sha3-asm", ] -[[package]] -name = "kzg-rs" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9201effeea3fcc93b587904ae2df9ce97e433184b9d6d299e9ebc9830a546636" -dependencies = [ - "ff", - "hex", - "serde_arrays", - "sha2 0.10.9", - "sp1_bls12_381", - "spin", -] - [[package]] name = "lazy_static" version = "1.5.0" @@ -2376,64 +1616,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" -[[package]] -name = "libsecp256k1" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79019718125edc905a079a70cfa5f3820bc76139fc91d6f9abc27ea2a887139" -dependencies = [ - "arrayref", - "base64 0.22.1", - "digest 0.9.0", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand 0.8.5", - "serde", - "sha2 0.9.9", -] - -[[package]] -name = "libsecp256k1-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" -dependencies = [ - "libsecp256k1-core", -] - [[package]] name = "linux-raw-sys" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" -[[package]] -name = "litemap" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" - [[package]] name = "lock_api" version = "0.4.13" @@ -2446,18 +1634,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "lru" -version = "0.13.0" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" -dependencies = [ - "hashbrown 0.15.5", -] +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "macro-string" @@ -2478,9 +1657,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "minicov" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +checksum = "4869b6a491569605d66d3952bcdf03df789e5b536e5f0cf7758a7f08a55ae24d" dependencies = [ "cc", "walkdir", @@ -2507,20 +1686,12 @@ dependencies = [ ] [[package]] -name = "native-tls" -version = "0.2.14" +name = "nu-ansi-term" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", + "windows-sys", ] [[package]] @@ -2529,7 +1700,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint 0.4.6", + "num-bigint", "num-complex", "num-integer", "num-iter", @@ -2537,17 +1708,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-bigint" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.6" @@ -2599,7 +1759,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "num-bigint 0.4.6", + "num-bigint", "num-integer", "num-traits", ] @@ -2646,20 +1806,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "nybbles" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "675b3a54e5b12af997abc8b6638b0aee51a28caedab70d4967e0d5db3a3f1d06" -dependencies = [ - "alloy-rlp", - "cfg-if", - "proptest", - "ruint", - "serde", - "smallvec", -] - [[package]] name = "object" version = "0.36.7" @@ -2676,54 +1822,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[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", - "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.104", -] - -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "openssl-sys" -version = "0.9.109" +name = "oorandom" +version = "11.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] +checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "p256" @@ -2734,128 +1836,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2 0.10.9", -] - -[[package]] -name = "p3-baby-bear" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7521838ecab2ddf4f7bc4ceebad06ec02414729598485c1ada516c39900820e8" -dependencies = [ - "num-bigint 0.4.6", - "p3-field", - "p3-mds", - "p3-poseidon2", - "p3-symmetric", - "rand 0.8.5", - "serde", -] - -[[package]] -name = "p3-dft" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46414daedd796f1eefcdc1811c0484e4bced5729486b6eaba9521c572c76761a" -dependencies = [ - "p3-field", - "p3-matrix", - "p3-maybe-rayon", - "p3-util", - "tracing", -] - -[[package]] -name = "p3-field" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48948a0516b349e9d1cdb95e7236a6ee010c44e68c5cc78b4b92bf1c4022a0d9" -dependencies = [ - "itertools 0.12.1", - "num-bigint 0.4.6", - "num-traits", - "p3-util", - "rand 0.8.5", - "serde", -] - -[[package]] -name = "p3-matrix" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4de3f373589477cb735ea58e125898ed20935e03664b4614c7fac258b3c42f" -dependencies = [ - "itertools 0.12.1", - "p3-field", - "p3-maybe-rayon", - "p3-util", - "rand 0.8.5", - "serde", - "tracing", -] - -[[package]] -name = "p3-maybe-rayon" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3968ad1160310296eb04f91a5f4edfa38fe1d6b2b8cd6b5c64e6f9b7370979e" - -[[package]] -name = "p3-mds" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2356b1ed0add6d5dfbf7a338ce534a6fde827374394a52cec16a0840af6e97c9" -dependencies = [ - "itertools 0.12.1", - "p3-dft", - "p3-field", - "p3-matrix", - "p3-symmetric", - "p3-util", - "rand 0.8.5", -] - -[[package]] -name = "p3-poseidon2" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da1eec7e1b6900581bedd95e76e1ef4975608dd55be9872c9d257a8a9651c3a" -dependencies = [ - "gcd", - "p3-field", - "p3-mds", - "p3-symmetric", - "rand 0.8.5", - "serde", -] - -[[package]] -name = "p3-symmetric" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb439bea1d822623b41ff4b51e3309e80d13cadf8b86d16ffd5e6efb9fdc360" -dependencies = [ - "itertools 0.12.1", - "p3-field", - "serde", -] - -[[package]] -name = "p3-util" -version = "0.2.3-succinct" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c2c2010678b9332b563eaa38364915b585c1a94b5ca61e2c7541c087ddda5c" -dependencies = [ - "serde", -] - -[[package]] -name = "pairing" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fec4625e73cf41ef4bb6846cafa6d44736525f442ba45e407c4a000a13996f" -dependencies = [ - "group", + "sha2", ] [[package]] @@ -2915,12 +1896,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - [[package]] name = "pest" version = "2.8.1" @@ -2934,9 +1909,9 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ "phf_macros", "phf_shared", @@ -2945,19 +1920,19 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" dependencies = [ + "fastrand", "phf_shared", - "rand 0.8.5", ] [[package]] name = "phf_macros" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" dependencies = [ "phf_generator", "phf_shared", @@ -2968,33 +1943,13 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" dependencies = [ "siphasher", ] -[[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "pin-project-lite" version = "0.2.16" @@ -3017,21 +1972,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[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" @@ -3156,13 +2096,14 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rain-math-float" -version = "0.1.0" +version = "0.1.9" dependencies = [ "alloy", "getrandom 0.2.16", "revm", "serde", "thiserror", + "wasm-bindgen", "wasm-bindgen-utils", ] @@ -3175,7 +2116,6 @@ dependencies = [ "libc", "rand_chacha 0.3.1", "rand_core 0.6.4", - "serde", ] [[package]] @@ -3237,6 +2177,15 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rapidhash" +version = "4.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e48930979c155e2f33aa36ab3119b5ee81332beb6482199a8ecd6029b80b59" +dependencies = [ + "rustversion", +] + [[package]] name = "redox_syscall" version = "0.5.17" @@ -3272,47 +2221,11 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" -[[package]] -name = "reqwest" -version = "0.12.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-tls", - "hyper-util", - "js-sys", - "log", - "native-tls", - "percent-encoding", - "pin-project-lite", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-native-tls", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "revm" -version = "25.0.0" +version = "36.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08fd78df29217546ddfd587fe313aff2bf86e57cfe0f18d16cb326d9f50ba54d" +checksum = "b0abc15d09cd211e9e73410ada10134069c794d4bcdb787dfc16a1bf0939849c" dependencies = [ "revm-bytecode", "revm-context", @@ -3329,12 +2242,11 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "4.1.0" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942fe4724cf552fd28db6b0a2ca5b79e884d40dd8288a4027ed1e9090e0c6f49" +checksum = "e86e468df3cf5cf59fa7ef71a3e9ccabb76bb336401ea2c0674f563104cf3c5e" dependencies = [ "bitvec", - "once_cell", "phf", "revm-primitives", "serde", @@ -3342,10 +2254,11 @@ dependencies = [ [[package]] name = "revm-context" -version = "6.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190f211f04c8030f5393cfcfa1569b88d5649f0f266bf4291981ba879fa6c5d1" +checksum = "9eb1f0a76b14d684a444fc52f7bf6b7564bf882599d91ee62e76d602e7a187c7" dependencies = [ + "bitvec", "cfg-if", "derive-where", "revm-bytecode", @@ -3358,9 +2271,9 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "6.0.0" +version = "16.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b7e7ff1154e6460cec025fe20dfe45f3325bbb905718643b6d053ec49da6e8" +checksum = "fc256b27743e2912ca16899568e6652a372eb5d1d573e6edb16c7836b16cf487" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3374,9 +2287,9 @@ dependencies = [ [[package]] name = "revm-database" -version = "5.0.0" +version = "12.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9456d5cb165fef91c8b538d0115de50059d1cf352d160a1396894eac017a2a34" +checksum = "2c0a7d6da41061f2c50f99a2632571026b23684b5449ff319914151f4449b6c8" dependencies = [ "alloy-eips", "revm-bytecode", @@ -3388,23 +2301,26 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "5.0.0" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaeb608de31bfd0e64bf9b5b18ee70ac70094c8c045b28ae8ae8701608d17d34" +checksum = "bd497a38a79057b94a049552cb1f925ad15078bc1a479c132aeeebd1d2ccc768" dependencies = [ "auto_impl", + "either", "revm-primitives", "revm-state", "serde", + "thiserror", ] [[package]] name = "revm-handler" -version = "6.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfeaecd909e6be655c36d21032ca932b347e60ec5849ee29e670d63aa97b6adb" +checksum = "9f1eed729ca9b228ae98688f352235871e9b8be3d568d488e4070f64c56e9d3d" dependencies = [ "auto_impl", + "derive-where", "revm-bytecode", "revm-context", "revm-context-interface", @@ -3418,11 +2334,12 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "6.0.0" +version = "17.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4de1c6cddc7d62364dc9fa2f405c2c4637c933c5591addf09977ec8a156e4b23" +checksum = "cbf5102391706513689f91cb3cb3d97b5f13a02e8647e6e9cb7620877ef84847" dependencies = [ "auto_impl", + "either", "revm-context", "revm-database-interface", "revm-handler", @@ -3435,59 +2352,60 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "21.0.0" +version = "34.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c3ca670eee335d9268a9100932ec1e09638bdd9b31eac9e22dec4de00f2cba" +checksum = "cf22f80612bb8f58fd1f578750281f2afadb6c93835b14ae6a4d6b75ca26f445" dependencies = [ "revm-bytecode", "revm-context-interface", "revm-primitives", + "revm-state", "serde", ] [[package]] name = "revm-precompile" -version = "22.0.0" +version = "32.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4330c6982a2ef1d318cb10ce7e726a64e11e44fe1eac29d055de849a5e1e080e" +checksum = "e2ec11f45deec71e4945e1809736bb20d454285f9167ab53c5159dae1deb603f" dependencies = [ "ark-bls12-381", "ark-bn254", "ark-ec", "ark-ff 0.5.0", "ark-serialize 0.5.0", + "arrayref", "aurora-engine-modexp", "blst", "c-kzg", "cfg-if", "k256", - "kzg-rs", - "libsecp256k1", - "once_cell", "p256", "revm-primitives", "ripemd", "secp256k1", - "sha2 0.10.9", + "sha2", ] [[package]] name = "revm-primitives" -version = "19.2.0" +version = "22.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c1588093530ec4442461163be49c433c07a3235d1ca6f6799fef338dacc50d3" +checksum = "4bcfb5ce6cf18b118932bcdb7da05cd9c250f2cb9f64131396b55f3fe3537c35" dependencies = [ "alloy-primitives", "num_enum", + "once_cell", "serde", ] [[package]] name = "revm-state" -version = "5.0.0" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44320ccf53067136a83cdbc54f4b7529e8f61497666f31d6f5cfd9035a1cc08f" +checksum = "d29404707763da607e5d6e4771cb203998c28159279c2f64cc32de08d2814651" dependencies = [ + "alloy-eip7928", "bitflags", "revm-bytecode", "revm-primitives", @@ -3535,7 +2453,7 @@ dependencies = [ "bytes", "fastrlp 0.3.1", "fastrlp 0.4.0", - "num-bigint 0.4.6", + "num-bigint", "num-integer", "num-traits", "parity-scale-codec", @@ -3605,15 +2523,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "rustls-pki-types" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" -dependencies = [ - "zeroize", -] - [[package]] name = "rustversion" version = "1.0.22" @@ -3647,15 +2556,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys", -] - [[package]] name = "schemars" version = "0.9.0" @@ -3696,55 +2596,30 @@ dependencies = [ "der", "generic-array", "pkcs8", - "serdect", "subtle", "zeroize", ] [[package]] name = "secp256k1" -version = "0.30.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +checksum = "2c3c81b43dc2d8877c216a3fccf76677ee1ebccd429566d3e67447290d0c42b2" dependencies = [ "bitcoin_hashes", - "rand 0.8.5", + "rand 0.9.2", "secp256k1-sys", - "serde", ] [[package]] name = "secp256k1-sys" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +checksum = "dcb913707158fadaf0d8702c2db0e857de66eb003ccfdda5924b5f5ac98efb38" dependencies = [ "cc", ] -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -3771,10 +2646,11 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ + "serde_core", "serde_derive", ] @@ -3801,19 +2677,19 @@ dependencies = [ ] [[package]] -name = "serde_arrays" -version = "0.2.0" +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a16b99c5ea4fe3daccd14853ad260ec00ea043b2708d1fd1da3106dcd8d9df" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ - "serde", + "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -3844,18 +2720,6 @@ dependencies = [ "serde", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_with" version = "3.14.0" @@ -3888,29 +2752,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "serdect" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" -dependencies = [ - "base16ct", - "serde", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug", -] - [[package]] name = "sha2" version = "0.10.9" @@ -3918,25 +2759,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] [[package]] name = "sha3" -version = "0.10.8" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" dependencies = [ - "digest 0.10.7", + "digest 0.11.3", "keccak", ] [[package]] name = "sha3-asm" -version = "0.1.4" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28efc5e327c837aa837c59eae585fc250715ef939ac32881bcc11677cd02d46" +checksum = "a6287fd675f713484342a89cbf0a386abef5f15919cfad607e5e1f19e1e15331" dependencies = [ "cc", "cfg-if", @@ -3975,71 +2816,6 @@ name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" -dependencies = [ - "serde", -] - -[[package]] -name = "socket2" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "sp1-lib" -version = "5.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1fe81b6f87134f9170cb642f948ae41e0ee1cd3785e0cb665add5b67106d1a" -dependencies = [ - "bincode", - "serde", - "sp1-primitives", -] - -[[package]] -name = "sp1-primitives" -version = "5.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dddd8d022840c1c500e0d7f82e9b9cf080b7dabd469f06b394010e6a594f692b" -dependencies = [ - "bincode", - "blake3", - "cfg-if", - "hex", - "lazy_static", - "num-bigint 0.4.6", - "p3-baby-bear", - "p3-field", - "p3-poseidon2", - "p3-symmetric", - "serde", - "sha2 0.10.9", -] - -[[package]] -name = "sp1_bls12_381" -version = "0.8.0-sp1-5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac255e1704ebcdeec5e02f6a0ebc4d2e9e6b802161938330b6810c13a610c583" -dependencies = [ - "cfg-if", - "ff", - "group", - "pairing", - "rand_core 0.6.4", - "sp1-lib", - "subtle", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" @@ -4070,7 +2846,7 @@ dependencies = [ [[package]] name = "sqlite-web" -version = "0.0.1-alpha.20" +version = "0.0.2" dependencies = [ "base64 0.21.7", "js-sys", @@ -4086,7 +2862,7 @@ dependencies = [ [[package]] name = "sqlite-web-core" -version = "0.0.1-alpha.20" +version = "0.0.2" dependencies = [ "alloy", "base64 0.21.7", @@ -4104,12 +2880,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "static_assertions" version = "1.1.0" @@ -4122,27 +2892,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "subtle" version = "2.6.1" @@ -4183,26 +2932,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[package]] -name = "synstructure" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - [[package]] name = "tap" version = "1.0.1" @@ -4291,16 +3020,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "tinystr" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tokio" version = "1.47.1" @@ -4308,61 +3027,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", - "bytes", "io-uring", "libc", "mio", "pin-project-lite", "slab", - "socket2", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", - "tokio-util", -] - -[[package]] -name = "tokio-util" -version = "0.7.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", ] [[package]] @@ -4382,51 +3051,6 @@ dependencies = [ "winnow", ] -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "pin-project-lite", - "sync_wrapper", - "tokio", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-http" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" -dependencies = [ - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - [[package]] name = "tracing" version = "0.1.41" @@ -4468,12 +3092,6 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - [[package]] name = "tsify" version = "0.4.5" @@ -4500,9 +3118,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.18.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ucd-trie" @@ -4540,23 +3158,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" -[[package]] -name = "url" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "uuid" version = "1.17.0" @@ -4574,12 +3175,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.5" @@ -4605,15 +3200,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -4631,48 +3217,32 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.104", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4680,54 +3250,70 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.104", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.50" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" +checksum = "2a0d555ca874445df8d314f94f5c948a4e74e5418f332c89f660a3d8310a96f4" dependencies = [ + "async-trait", + "cast", "js-sys", + "libm", "minicov", + "nu-ansi-term", + "num-traits", + "oorandom", + "serde", + "serde_json", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", + "wasm-bindgen-test-shared", ] [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.50" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" +checksum = "94eb68555b95bcea5e8cf4abe280b529049479fa995bfc23734af96a6aedc120" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] +[[package]] +name = "wasm-bindgen-test-shared" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31d56021e873866c968588ed85ccdf56db5c426e44afdb4618c39895104b920" + [[package]] name = "wasm-bindgen-utils" -version = "0.0.10" -source = "git+https://github.com/rainlanguage/rain.wasm?rev=06990d85a0b7c55378a1c8cca4dd9e2bc34a596a#06990d85a0b7c55378a1c8cca4dd9e2bc34a596a" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83ead9e122abfd725c8a2ac0ec27540fdc9585dc0cc3eaaba98cb2d0ff3d8026" dependencies = [ "js-sys", "paste", @@ -4741,33 +3327,20 @@ dependencies = [ [[package]] name = "wasm-bindgen-utils-macros" -version = "0.0.5" -source = "git+https://github.com/rainlanguage/rain.wasm?rev=06990d85a0b7c55378a1c8cca4dd9e2bc34a596a#06990d85a0b7c55378a1c8cca4dd9e2bc34a596a" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ca0b2e5d68b4faad662b20de1f2ad95fb04a491b0200376aefd4dbc49647d4" dependencies = [ "proc-macro2", "quote", "syn 2.0.104", ] -[[package]] -name = "wasmtimer" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8d49b5d6c64e8558d9b1b065014426f35c18de636895d24893dbbd329743446" -dependencies = [ - "futures", - "js-sys", - "parking_lot", - "pin-utils", - "slab", - "wasm-bindgen", -] - [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -4932,12 +3505,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "writeable" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" - [[package]] name = "wyz" version = "0.5.1" @@ -4947,30 +3514,6 @@ dependencies = [ "tap", ] -[[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", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", - "synstructure", -] - [[package]] name = "zerocopy" version = "0.8.26" @@ -4991,27 +3534,6 @@ dependencies = [ "syn 2.0.104", ] -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", - "synstructure", -] - [[package]] name = "zeroize" version = "1.8.1" @@ -5031,36 +3553,3 @@ dependencies = [ "quote", "syn 2.0.104", ] - -[[package]] -name = "zerotrie" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - -[[package]] -name = "zerovec" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] diff --git a/Cargo.toml b/Cargo.toml index 26f8653..c955b5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,11 +45,11 @@ uuid = { version = "1.0", features = ["v4", "js"] } console_error_panic_hook = "0.1" base64 = "0.21" sqlite-wasm-rs = { version = "=0.3.0", default-features = false, features = ["precompiled"] } -alloy = { version = "1.0.9", features = ["sol-types", "json", "json-abi"] } +alloy = { version = "1.0.9", default-features = false, features = ["sol-types", "json", "json-abi"] } thiserror = "2.0.12" proptest = "1.7.0" -revm = { version = "25.0.0", default-features = false } -wasm-bindgen-utils = { git = "https://github.com/rainlanguage/rain.wasm", rev = "06990d85a0b7c55378a1c8cca4dd9e2bc34a596a" } +revm = { version = "36", default-features = false, features = ["portable", "std", "tracer"] } +wasm-bindgen-utils = "0.1.2" wasm-bindgen-test = "0.3" [profile.release] diff --git a/flake.lock b/flake.lock index 2c5fe29..f05ef6b 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,21 @@ { "nodes": { + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1767039857, + "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", + "owner": "NixOS", + "repo": "flake-compat", + "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems" @@ -75,11 +91,11 @@ "nixpkgs": "nixpkgs" }, "locked": { - "lastModified": 1741023058, - "narHash": "sha256-LSd/8CBlpDLjci5ANFJjP0w+dGdY/mqKsyUfhjGwnfs=", + "lastModified": 1778486972, + "narHash": "sha256-iuy/TbK9AbghEld2VSFuxyAF30LkOGUUdtrvixLfE7M=", "owner": "shazow", "repo": "foundry.nix", - "rev": "66becfe20b7e688b8f2e5774609c4436cf202ba0", + "rev": "db117ae95a77b9ead24137c3ccb28896ae4fa4ec", "type": "github" }, "original": { @@ -88,6 +104,48 @@ "type": "github" } }, + "git-hooks-nix": { + "inputs": { + "flake-compat": "flake-compat", + "gitignore": "gitignore", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1778507602, + "narHash": "sha256-kTwur1wV+01SdqskVMSo6JMEpg71ps3HpbFY2GsflKs=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "61ab0e80d9c7ab14c256b5b453d8b3fb0189ba0a", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "rainix", + "git-hooks-nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1666753130, @@ -104,11 +162,27 @@ }, "nixpkgs_2": { "locked": { - "lastModified": 1749104371, - "narHash": "sha256-m2NmOPd6XgBiskmUq/BS9Xxuf3z0ebnGVfSKNAO5NEM=", + "lastModified": 1770073757, + "narHash": "sha256-Vy+G+F+3E/Tl+GMNgiHl9Pah2DgShmIUBJXmbiQPHbI=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "47472570b1e607482890801aeaf29bfb749884f6", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1778656924, + "narHash": "sha256-lKVrom9wOmpC3i7m+uBoGaBdW0PfH3QbLRG1XmuC6YA=", "owner": "nixos", "repo": "nixpkgs", - "rev": "48975d7f9b9960ed33c4e8561bcce20cc0c2de5b", + "rev": "4ba039de0909446943c07e2b42bd2f0f4507072e", "type": "github" }, "original": { @@ -117,7 +191,7 @@ "type": "github" } }, - "nixpkgs_3": { + "nixpkgs_4": { "locked": { "lastModified": 1744536153, "narHash": "sha256-awS2zRgF4uTwrOKwwiJcByDzDOdo3Q1rPZbiHQg/N38=", @@ -133,13 +207,13 @@ "type": "github" } }, - "nixpkgs_4": { + "nixpkgs_5": { "locked": { - "lastModified": 1748662220, - "narHash": "sha256-7gGa49iB9nCnFk4h/g9zwjlQAyjtpgcFkODjcOQS0Es=", + "lastModified": 1777641297, + "narHash": "sha256-WNGcmeOZ8Tr9dq6ztCspYbzWFswr2mPebM9LpsfGxPk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "59138c7667b7970d205d6a05a8bfa2d78caa3643", + "rev": "c6d65881c5624c9cae5ea6cedef24699b0c0a4c0", "type": "github" }, "original": { @@ -153,16 +227,17 @@ "inputs": { "flake-utils": "flake-utils_2", "foundry": "foundry", - "nixpkgs": "nixpkgs_2", + "git-hooks-nix": "git-hooks-nix", + "nixpkgs": "nixpkgs_3", "rust-overlay": "rust-overlay", "solc": "solc" }, "locked": { - "lastModified": 1749284231, - "narHash": "sha256-2pxLmguxgvcIaoCrxrrJaod+Sen/HjULnibdjogNp14=", + "lastModified": 1781985867, + "narHash": "sha256-Ktb8hQGPdOxCbdpmcbhveYwndTsrqR/rd3hVNtRe7DE=", "owner": "rainprotocol", "repo": "rainix", - "rev": "f3ef7c9b21db154d6e57858aa2f59ce40e6677bb", + "rev": "6b43e604e1b6ce3c00ece4ae159bb5d1457548b5", "type": "github" }, "original": { @@ -179,14 +254,14 @@ }, "rust-overlay": { "inputs": { - "nixpkgs": "nixpkgs_3" + "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1749091064, - "narHash": "sha256-TGtYjzRX0sueFhwYsnNNFF5TTKnpnloznpIghLzxeXo=", + "lastModified": 1778642276, + "narHash": "sha256-bhk4lawR4ZnFhPtamB5WkCyvfgyZmsEUbWfT/3FRxFY=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "12419593ce78f2e8e1e89a373c6515885e218acb", + "rev": "77265d2dc1e61b2abfd3b1d6609dbb66fe75e0a5", "type": "github" }, "original": { @@ -198,15 +273,15 @@ "solc": { "inputs": { "flake-utils": "flake-utils_4", - "nixpkgs": "nixpkgs_4", + "nixpkgs": "nixpkgs_5", "solc-macos-amd64-list-json": "solc-macos-amd64-list-json" }, "locked": { - "lastModified": 1748780655, - "narHash": "sha256-mradCdMvjXwKd7kVFACB/d1CP2LLCyEgUu4vJCSzNLU=", + "lastModified": 1777817996, + "narHash": "sha256-iI71iUhD7THLibl3w1JcQEhHmTwZMxChi70RTe33BAo=", "owner": "hellwolf", "repo": "solc.nix", - "rev": "3b6f3223ace5a7bc400b01a434d86bb1cb2593fb", + "rev": "e3cf898cb804d5c0e5474b378a300fe8942e67d6", "type": "github" }, "original": { @@ -218,13 +293,13 @@ "solc-macos-amd64-list-json": { "flake": false, "locked": { - "narHash": "sha256-U5ckttxwKO13gIKggel6iybG5oTDbSidPR5nH3Gs+kY=", + "narHash": "sha256-zzwwHA2qPotv7yp8mK7+y9BZhm7ytuFeCJVvKBBdBn4=", "type": "file", - "url": "https://github.com/ethereum/solc-bin/raw/30a3695/macosx-amd64/list.json" + "url": "https://github.com/argotorg/solc-bin/raw/902dfaf/macosx-amd64/list.json" }, "original": { "type": "file", - "url": "https://github.com/ethereum/solc-bin/raw/30a3695/macosx-amd64/list.json" + "url": "https://github.com/argotorg/solc-bin/raw/902dfaf/macosx-amd64/list.json" } }, "systems": { diff --git a/flake.nix b/flake.nix index dbc3426..e6be566 100644 --- a/flake.nix +++ b/flake.nix @@ -60,8 +60,9 @@ name = "build-submodules"; body = '' set -euxo pipefail - rainix-sol-prelude cd lib/rain.math.float + forge soldeer install --config-location foundry + forge install forge build cd ../.. ''; diff --git a/lib/rain.math.float b/lib/rain.math.float index f17ae6d..1586a59 160000 --- a/lib/rain.math.float +++ b/lib/rain.math.float @@ -1 +1 @@ -Subproject commit f17ae6d21d63d50642cc0de00f6b22d38636e133 +Subproject commit 1586a5973882b6acb72c2677c29ad23c4c6f85ef diff --git a/packages/sqlite-web-core/src/coordination.rs b/packages/sqlite-web-core/src/coordination.rs index 31376df..0756ec4 100644 --- a/packages/sqlite-web-core/src/coordination.rs +++ b/packages/sqlite-web-core/src/coordination.rs @@ -16,7 +16,7 @@ use web_sys::{ use crate::database::SQLiteDatabase; use crate::messages::{ - ChannelMessage, MainThreadMessage, WorkerErrorPayload, WorkerMessage, + ChannelMessage, MainThreadMessage, SqlBatchStatement, WorkerErrorPayload, WorkerMessage, WORKER_ERROR_TYPE_INITIALIZATION_PENDING, }; use crate::util::{js_value_to_string, sanitize_identifier, set_js_property}; @@ -28,7 +28,6 @@ pub enum LeadershipRole { } const MAX_DB_WORKER_RESPAWNS: u32 = 3; - pub struct WorkerConfig { pub db_name: String, pub follower_timeout_ms: f64, @@ -89,26 +88,32 @@ enum DbRequestOrigin { struct DbJob { request_id: u32, - sql: String, - params: Option>, + payload: DbJobPayload, +} + +pub(crate) enum DbJobPayload { + Query { + sql: String, + params: Option>, + }, + Batch { + statements: Vec, + }, } type DbExecFuture = Pin> + 'static>>; -type DbExecFn = dyn Fn( - Rc>>, - String, - Option>, -) -> DbExecFuture; +type DbExecFn = dyn Fn(Rc>>, DbJobPayload) -> DbExecFuture; type DbDeliverFn = dyn Fn(&js_sys::Object); #[derive(Clone)] -pub struct DbWorkerHooks { +pub(crate) struct DbWorkerHooks { exec: Rc, deliver: Rc, } impl DbWorkerHooks { - pub fn new(exec: Rc, deliver: Rc) -> Self { + #[cfg_attr(not(all(test, target_family = "wasm")), allow(dead_code))] + pub(crate) fn new(exec: Rc, deliver: Rc) -> Self { Self { exec, deliver } } } @@ -116,7 +121,7 @@ impl DbWorkerHooks { impl Default for DbWorkerHooks { fn default() -> Self { Self { - exec: Rc::new(|db, sql, params| Box::pin(exec_on_db(db, sql, params))), + exec: Rc::new(|db, payload| Box::pin(exec_on_db(db, payload))), deliver: Rc::new(deliver_db_result), } } @@ -187,6 +192,20 @@ impl CoordinatorState { Ok(()) } + fn batch_timeout_ms(&self, statement_count: usize) -> f64 { + let count = statement_count.max(1) as f64; + if self.query_timeout_ms.is_finite() { + self.query_timeout_ms.max(0.0) * count + } else { + f64::INFINITY + } + } + + fn handle_follower_forward_failure(&self, query_id: &str, request_id: u32, err: &str) { + self.follower_pending.borrow_mut().remove(query_id); + let _ = send_query_result_to_main(request_id, Err(err.to_string())); + } + pub fn start_leader_probe(self: &Rc) { if matches!(*self.role.borrow(), LeadershipRole::Leader) { return; @@ -444,6 +463,7 @@ impl CoordinatorState { .insert(query_id.clone(), request_id); let pending = Rc::clone(&self.follower_pending); let timeout = self.query_timeout_ms; + let cleanup_query_id = query_id.clone(); let timeout_query_id = query_id.clone(); spawn_local(async move { sleep_ms(timeout.ceil() as i32).await; @@ -460,6 +480,56 @@ impl CoordinatorState { params, }; if let Err(err) = send_channel_message(&self.channel, &request) { + self.handle_follower_forward_failure(&cleanup_query_id, request_id, &err); + let _ = send_worker_error_message(&err); + } + } + }, + WorkerMessage::ExecuteBatch { + request_id, + statements, + } => match *self.role.borrow() { + LeadershipRole::Leader => { + if !*self.db_worker_ready.borrow() { + let _ = send_query_result_to_main( + request_id, + Err(WORKER_ERROR_TYPE_INITIALIZATION_PENDING.to_string()), + ); + return; + } + self.forward_batch_to_db(DbRequestOrigin::Local { request_id }, statements); + } + LeadershipRole::Follower => { + if !*self.leader_ready.borrow() { + let _ = send_query_result_to_main( + request_id, + Err(WORKER_ERROR_TYPE_INITIALIZATION_PENDING.to_string()), + ); + return; + } + let query_id = Uuid::new_v4().to_string(); + self.follower_pending + .borrow_mut() + .insert(query_id.clone(), request_id); + let pending = Rc::clone(&self.follower_pending); + let timeout = self.batch_timeout_ms(statements.len()); + let cleanup_query_id = query_id.clone(); + let timeout_query_id = query_id.clone(); + spawn_local(async move { + sleep_ms(timeout.ceil() as i32).await; + if let Some(original) = pending.borrow_mut().remove(&timeout_query_id) { + let _ = send_query_result_to_main( + original, + Err("Query timeout".to_string()), + ); + } + }); + let request = ChannelMessage::BatchRequest { + query_id, + statements, + }; + if let Err(err) = send_channel_message(&self.channel, &request) { + self.handle_follower_forward_failure(&cleanup_query_id, request_id, &err); let _ = send_worker_error_message(&err); } } @@ -521,6 +591,25 @@ impl CoordinatorState { self.forward_query_to_db(DbRequestOrigin::Forwarded { query_id }, sql, params); } } + ChannelMessage::BatchRequest { + query_id, + statements, + } => { + if matches!(*self.role.borrow(), LeadershipRole::Leader) { + if !*self.db_worker_ready.borrow() { + let _ = send_channel_message( + &self.channel, + &ChannelMessage::QueryResponse { + query_id, + result: None, + error: Some(WORKER_ERROR_TYPE_INITIALIZATION_PENDING.to_string()), + }, + ); + return; + } + self.forward_batch_to_db(DbRequestOrigin::Forwarded { query_id }, statements); + } + } ChannelMessage::QueryResponse { query_id, result, @@ -583,6 +672,56 @@ impl CoordinatorState { sql, params, }; + self.post_db_worker_message(worker, db_request_id, msg); + } + + fn forward_batch_to_db( + self: &Rc, + origin: DbRequestOrigin, + statements: Vec, + ) { + let worker = { + let borrow = self.db_worker.borrow(); + let Some(worker) = borrow.as_ref() else { + match origin { + DbRequestOrigin::Local { request_id } => { + let _ = send_query_result_to_main( + request_id, + Err(WORKER_ERROR_TYPE_INITIALIZATION_PENDING.to_string()), + ); + } + DbRequestOrigin::Forwarded { query_id } => { + let _ = send_channel_message( + &self.channel, + &ChannelMessage::QueryResponse { + query_id, + result: None, + error: Some(WORKER_ERROR_TYPE_INITIALIZATION_PENDING.to_string()), + }, + ); + } + } + return; + }; + worker.clone() + }; + + let db_request_id = { + let mut next = self.next_db_request_id.borrow_mut(); + let id = *next; + *next = next.wrapping_add(1).max(1); + id + }; + self.db_pending.borrow_mut().insert(db_request_id, origin); + + let msg = WorkerMessage::ExecuteBatch { + request_id: db_request_id, + statements, + }; + self.post_db_worker_message(worker, db_request_id, msg); + } + + fn post_db_worker_message(&self, worker: Worker, db_request_id: u32, msg: WorkerMessage) { match serde_wasm_bindgen::to_value(&msg) { Ok(val) => { if let Err(err) = worker.post_message(&val) { @@ -685,7 +824,7 @@ impl DbWorkerState { Self::new_with_hooks(config, DbWorkerHooks::default()) } - pub fn new_with_hooks(config: WorkerConfig, hooks: DbWorkerHooks) -> Rc { + pub(crate) fn new_with_hooks(config: WorkerConfig, hooks: DbWorkerHooks) -> Rc { Rc::new(DbWorkerState { db: Rc::new(RefCell::new(None)), db_name: config.db_name, @@ -717,21 +856,21 @@ impl DbWorkerState { sql, params, } => { - self.enqueue_query(request_id, sql, params); + self.enqueue_job(request_id, DbJobPayload::Query { sql, params }); + } + WorkerMessage::ExecuteBatch { + request_id, + statements, + } => { + self.enqueue_job(request_id, DbJobPayload::Batch { statements }); } } } - fn enqueue_query( - self: &Rc, - request_id: u32, - sql: String, - params: Option>, - ) { + fn enqueue_job(self: &Rc, request_id: u32, payload: DbJobPayload) { self.db_queue.borrow_mut().push_back(DbJob { request_id, - sql, - params, + payload, }); self.start_queue_processor(); } @@ -752,7 +891,7 @@ impl DbWorkerState { let db = Rc::clone(&state.db); let exec = Rc::clone(&hooks.exec); let deliver = Rc::clone(&hooks.deliver); - let result = exec.as_ref()(db, job.sql, job.params).await; + let result = exec.as_ref()(db, job.payload).await; match make_query_result_message(job.request_id, result) { Ok(resp) => deliver.as_ref()(&resp), Err(err) => { @@ -900,15 +1039,17 @@ fn deliver_db_result(obj: &js_sys::Object) { } async fn exec_on_db( db: Rc>>, - sql: String, - params: Option>, + payload: DbJobPayload, ) -> Result { let db_opt = db.borrow_mut().take(); let result = match db_opt { Some(mut database) => { - let result = match params { - Some(p) => database.exec_with_params(&sql, p).await, - None => database.exec(&sql).await, + let result = match payload { + DbJobPayload::Query { sql, params } => match params { + Some(p) => database.exec_with_params(&sql, p).await, + None => database.exec(&sql).await, + }, + DbJobPayload::Batch { statements } => database.exec_batch(statements).await, }; *db.borrow_mut() = Some(database); result @@ -1006,6 +1147,42 @@ mod tests { assert_eq!(cfg.query_timeout_ms, 30000.0); } + #[wasm_bindgen_test] + fn batch_timeout_scales_with_statement_count() { + let state = CoordinatorState::new(WorkerConfig { + db_name: "testdb-batch-timeout".to_string(), + follower_timeout_ms: 10.0, + query_timeout_ms: 50.0, + }) + .expect("state"); + + assert_eq!(state.batch_timeout_ms(0), 50.0); + assert_eq!(state.batch_timeout_ms(1), 50.0); + assert_eq!(state.batch_timeout_ms(3), 150.0); + } + + #[wasm_bindgen_test] + fn follower_forward_failure_removes_pending_request() { + let state = CoordinatorState::new(WorkerConfig { + db_name: "testdb-forward-failure".to_string(), + follower_timeout_ms: 10.0, + query_timeout_ms: 50.0, + }) + .expect("state"); + + state + .follower_pending + .borrow_mut() + .insert("query-1".to_string(), 42); + + state.handle_follower_forward_failure("query-1", 42, "post failed"); + + assert!( + !state.follower_pending.borrow().contains_key("query-1"), + "failed follower forwards should not wait for timeout cleanup" + ); + } + #[wasm_bindgen_test(async)] async fn coordinator_broadcasts_leader_and_ready() { set_global_str("__SQLITE_DB_NAME", "testdb-coordinator"); @@ -1244,7 +1421,7 @@ mod tests { let hooks = DbWorkerHooks::new( { let busy_flag = Rc::clone(&busy_flag); - Rc::new(move |_db, _sql, _params| { + Rc::new(move |_db, _payload| { let busy_flag = Rc::clone(&busy_flag); Box::pin(async move { if busy_flag.replace(true) { diff --git a/packages/sqlite-web-core/src/database.rs b/packages/sqlite-web-core/src/database.rs index 8f641ca..32a13c7 100644 --- a/packages/sqlite-web-core/src/database.rs +++ b/packages/sqlite-web-core/src/database.rs @@ -1,4 +1,5 @@ use crate::database_functions::register_custom_functions; +use crate::messages::SqlBatchStatement; use crate::util::sanitize_db_filename; use base64::Engine; use sqlite_wasm_rs::export::{install_opfs_sahpool, *}; @@ -579,6 +580,124 @@ impl SQLiteDatabase { self.exec_prepared_statement(stmt_guard.take()) } + async fn exec_single_statement_strict( + &self, + sql: &str, + ) -> Result<(Option>, i32), String> { + let sql_cstr = CString::new(sql).map_err(|e| format!("Invalid SQL string: {e}"))?; + let ptr = sql_cstr.as_ptr(); + let (stmt_opt, tail) = self.prepare_one(ptr)?; + let Some(stmt) = stmt_opt else { + if !Self::is_trivia_tail_only(tail) { + return Err("Batch statements must contain a single statement.".to_string()); + } + return Ok((None, 0)); + }; + let mut stmt_guard = StmtGuard::new(stmt); + if !Self::is_trivia_tail_only(tail) { + return Err("Batch statements must contain a single statement.".to_string()); + } + self.exec_prepared_statement(stmt_guard.take()) + } + + fn is_transaction_control_statement(sql: &str) -> bool { + let Some(keyword) = Self::first_sql_keyword(sql) else { + return false; + }; + let upper = keyword.to_ascii_uppercase(); + matches!( + upper.as_str(), + "BEGIN" | "COMMIT" | "END" | "ROLLBACK" | "SAVEPOINT" | "RELEASE" + ) + } + + fn first_sql_keyword(sql: &str) -> Option<&str> { + let bytes = sql.as_bytes(); + let mut i = 0; + + loop { + while i < bytes.len() && bytes[i].is_ascii_whitespace() { + i += 1; + } + + if bytes.get(i) == Some(&b'-') && bytes.get(i + 1) == Some(&b'-') { + i += 2; + while i < bytes.len() && bytes[i] != b'\n' { + i += 1; + } + continue; + } + + if bytes.get(i) == Some(&b'/') && bytes.get(i + 1) == Some(&b'*') { + i += 2; + let mut closed = false; + while i + 1 < bytes.len() { + if bytes[i] == b'*' && bytes[i + 1] == b'/' { + i += 2; + closed = true; + break; + } + i += 1; + } + if !closed { + return None; + } + continue; + } + + break; + } + + let start = i; + while i < bytes.len() && (bytes[i].is_ascii_alphabetic() || bytes[i] == b'_') { + i += 1; + } + + if i == start { + None + } else { + Some(&sql[start..i]) + } + } + + fn is_sql_trivia_only(sql: &str) -> bool { + let bytes = sql.as_bytes(); + let mut i = 0; + + loop { + while i < bytes.len() && bytes[i].is_ascii_whitespace() { + i += 1; + } + + if bytes.get(i) == Some(&b'-') && bytes.get(i + 1) == Some(&b'-') { + i += 2; + while i < bytes.len() && bytes[i] != b'\n' { + i += 1; + } + continue; + } + + if bytes.get(i) == Some(&b'/') && bytes.get(i + 1) == Some(&b'*') { + i += 2; + let mut closed = false; + while i + 1 < bytes.len() { + if bytes[i] == b'*' && bytes[i + 1] == b'/' { + i += 2; + closed = true; + break; + } + i += 1; + } + if !closed { + return true; + } + continue; + } + + return i == bytes.len(); + } + } + pub async fn initialize_opfs(db_name: &str) -> Result { // Install OPFS VFS and set as default install_opfs_sahpool(None, true) @@ -817,6 +936,97 @@ impl SQLiteDatabase { )) } } + + /// Execute a list of single statements atomically as one database-worker job. + pub async fn exec_batch( + &mut self, + statements: Vec, + ) -> Result { + if statements.is_empty() { + return Err("Batch must contain at least one statement.".to_string()); + } + self.refresh_transaction_state(); + if self.in_transaction { + return Err("Cannot execute a batch while a transaction is already open.".to_string()); + } + + self.exec_single_statement("BEGIN TRANSACTION").await?; + self.refresh_transaction_state(); + + let mut last_statement_rows: Option> = None; + let mut total_affected_rows = 0; + let mut executed_any = false; + + for (idx, statement) in statements.into_iter().enumerate() { + let sql = statement.sql.trim(); + if sql.is_empty() { + continue; + } + if Self::first_sql_keyword(sql).is_none() { + if Self::is_sql_trivia_only(sql) { + continue; + } + let _ = self.exec_single_statement("ROLLBACK").await; + self.refresh_transaction_state(); + return Err(format!( + "Batch statement {} must contain exactly one executable statement.", + idx + 1 + )); + } + if Self::is_transaction_control_statement(sql) { + let _ = self.exec_single_statement("ROLLBACK").await; + self.refresh_transaction_state(); + return Err(format!( + "Batch statement {} contains a transaction-control keyword; transaction() manages the transaction for you.", + idx + 1 + )); + } + + let statement_result = match statement.params { + Some(params) => self.exec_single_statement_with_params(sql, params).await, + None => self.exec_single_statement_strict(sql).await, + }; + + match statement_result { + Ok((rows_opt, affected)) => { + executed_any = true; + if rows_opt.is_some() { + last_statement_rows = rows_opt; + } else { + last_statement_rows = None; + total_affected_rows += affected; + } + } + Err(err) => { + let _ = self.exec_single_statement("ROLLBACK").await; + self.refresh_transaction_state(); + return Err(format!("Batch statement {} failed: {}", idx + 1, err)); + } + } + } + + if !executed_any { + let _ = self.exec_single_statement("ROLLBACK").await; + self.refresh_transaction_state(); + return Err("Batch must contain at least one executable statement.".to_string()); + } + + if let Err(err) = self.exec_single_statement("COMMIT").await { + let _ = self.exec_single_statement("ROLLBACK").await; + self.refresh_transaction_state(); + return Err(format!("Batch commit failed: {err}")); + } + self.refresh_transaction_state(); + + if let Some(results) = last_statement_rows { + serde_json::to_string_pretty(&results) + .map_err(|e| format!("JSON serialization error: {e}")) + } else { + Ok(format!( + "Batch executed successfully. Rows affected: {total_affected_rows}" + )) + } + } } impl Drop for SQLiteDatabase { @@ -1683,6 +1893,402 @@ mod tests { ); } + #[wasm_bindgen_test] + async fn split_transaction_calls_can_interleave_and_nested_begin_fails() { + let Some(mut db) = get_test_db().await else { + return; + }; + + db.exec("ROLLBACK").await.ok(); + db.exec("BEGIN TRANSACTION") + .await + .expect("first logical client starts a transaction"); + + let second_begin = db.exec("BEGIN TRANSACTION").await; + assert!( + second_begin + .expect_err("second logical client BEGIN should fail") + .contains("cannot start a transaction within a transaction"), + "SQLite reports the nested BEGIN failure" + ); + + db.exec("ROLLBACK").await.ok(); + } + + #[wasm_bindgen_test] + async fn exec_batch_wraps_statements_in_one_transaction() { + let Some(mut db) = get_test_db().await else { + return; + }; + + db.exec("DROP TABLE IF EXISTS batch_test").await.ok(); + let result = db + .exec_batch(vec![ + SqlBatchStatement { + sql: "CREATE TABLE batch_test (id INTEGER PRIMARY KEY, name TEXT)".to_string(), + params: None, + }, + SqlBatchStatement { + sql: "INSERT INTO batch_test (name) VALUES (?)".to_string(), + params: Some(vec![json!("Alice")]), + }, + SqlBatchStatement { + sql: "SELECT COUNT(*) as count FROM batch_test".to_string(), + params: None, + }, + ]) + .await + .expect("batch should execute"); + + let rows: serde_json::Value = serde_json::from_str(&result).expect("select result json"); + assert_eq!(rows[0]["count"].as_i64(), Some(1)); + assert!(!db.in_transaction, "batch should commit before returning"); + } + + #[wasm_bindgen_test] + async fn exec_batch_returns_last_row_result() { + let Some(mut db) = get_test_db().await else { + return; + }; + + let result = db + .exec_batch(vec![ + SqlBatchStatement { + sql: "SELECT 'first' as label".to_string(), + params: None, + }, + SqlBatchStatement { + sql: "CREATE TABLE IF NOT EXISTS batch_last_result_test (id INTEGER)" + .to_string(), + params: None, + }, + SqlBatchStatement { + sql: "SELECT 'last' as label".to_string(), + params: None, + }, + ]) + .await + .expect("batch should execute"); + + let rows: serde_json::Value = serde_json::from_str(&result).expect("select result json"); + assert_eq!(rows[0]["label"].as_str(), Some("last")); + } + + #[wasm_bindgen_test] + async fn exec_batch_returns_success_when_last_statement_has_no_rows() { + let Some(mut db) = get_test_db().await else { + return; + }; + + db.exec("DROP TABLE IF EXISTS batch_last_non_query_test") + .await + .ok(); + db.exec("CREATE TABLE batch_last_non_query_test (id INTEGER PRIMARY KEY, name TEXT)") + .await + .expect("create table"); + + let result = db + .exec_batch(vec![ + SqlBatchStatement { + sql: "SELECT 'stale' as label".to_string(), + params: None, + }, + SqlBatchStatement { + sql: "INSERT INTO batch_last_non_query_test (name) VALUES ('Alice')" + .to_string(), + params: None, + }, + ]) + .await + .expect("batch should execute"); + + assert!( + result.starts_with("Batch executed successfully."), + "final non-query statement should not return stale rows: {result}" + ); + assert!( + result.contains("Rows affected: 1"), + "row-returning statements should not contribute stale affected rows: {result}" + ); + + let count = db + .exec("SELECT COUNT(*) as count FROM batch_last_non_query_test") + .await + .expect("count query"); + let rows: serde_json::Value = serde_json::from_str(&count).expect("count json"); + assert_eq!(rows[0]["count"].as_i64(), Some(1)); + } + + #[wasm_bindgen_test] + async fn exec_batch_rejects_non_trivia_statement_without_keyword() { + let Some(mut db) = get_test_db().await else { + return; + }; + + db.exec("DROP TABLE IF EXISTS batch_no_keyword_test") + .await + .ok(); + db.exec("CREATE TABLE batch_no_keyword_test (id INTEGER PRIMARY KEY)") + .await + .expect("create table"); + + let result = db + .exec_batch(vec![SqlBatchStatement { + sql: "; INSERT INTO batch_no_keyword_test DEFAULT VALUES".to_string(), + params: None, + }]) + .await; + + assert_eq!( + result.expect_err("delimiter-prefixed SQL should be rejected"), + "Batch statement 1 must contain exactly one executable statement." + ); + assert!( + !db.in_transaction, + "invalid batch statement should roll back before returning" + ); + + let count = db + .exec("SELECT COUNT(*) as count FROM batch_no_keyword_test") + .await + .expect("count query"); + let rows: serde_json::Value = serde_json::from_str(&count).expect("count json"); + assert_eq!(rows[0]["count"].as_i64(), Some(0)); + } + + #[wasm_bindgen_test] + async fn exec_batch_rolls_back_on_failure() { + let Some(mut db) = get_test_db().await else { + return; + }; + + db.exec("DROP TABLE IF EXISTS batch_rollback_test") + .await + .ok(); + db.exec("CREATE TABLE batch_rollback_test (id INTEGER PRIMARY KEY, name TEXT)") + .await + .expect("create table"); + + let result = db + .exec_batch(vec![ + SqlBatchStatement { + sql: "INSERT INTO batch_rollback_test (id, name) VALUES (1, 'Alice')" + .to_string(), + params: None, + }, + SqlBatchStatement { + sql: "INSERT INTO missing_batch_table (id) VALUES (1)".to_string(), + params: None, + }, + ]) + .await; + assert!(result.is_err(), "batch should fail"); + assert!( + !db.in_transaction, + "failure should roll back before returning" + ); + + let count = db + .exec("SELECT COUNT(*) as count FROM batch_rollback_test") + .await + .expect("count query"); + let rows: serde_json::Value = serde_json::from_str(&count).expect("count json"); + assert_eq!(rows[0]["count"].as_i64(), Some(0)); + } + + #[wasm_bindgen_test] + async fn exec_batch_rejects_when_transaction_is_already_open() { + let Some(mut db) = get_test_db().await else { + return; + }; + + db.exec("ROLLBACK").await.ok(); + db.exec("BEGIN TRANSACTION") + .await + .expect("begin transaction"); + assert!(db.in_transaction, "BEGIN should mark transaction open"); + + let result = db + .exec_batch(vec![SqlBatchStatement { + sql: "SELECT 1".to_string(), + params: None, + }]) + .await; + + assert_eq!( + result.expect_err("batch should reject nested transaction"), + "Cannot execute a batch while a transaction is already open." + ); + assert!( + db.in_transaction, + "rejected batch should not close the caller's transaction" + ); + + db.exec("ROLLBACK").await.ok(); + assert!(!db.in_transaction, "cleanup should close transaction"); + } + + #[wasm_bindgen_test] + async fn exec_batch_rejects_all_empty_statements_and_rolls_back() { + let Some(mut db) = get_test_db().await else { + return; + }; + + let result = db + .exec_batch(vec![SqlBatchStatement { + sql: " \n\t ".to_string(), + params: None, + }]) + .await; + + assert_eq!( + result.expect_err("empty statement batch should be rejected"), + "Batch must contain at least one executable statement." + ); + assert!( + !db.in_transaction, + "empty batch rejection should leave no open transaction" + ); + + let result = db + .exec_batch(vec![SqlBatchStatement { + sql: "-- comment only\n/* and another comment */".to_string(), + params: None, + }]) + .await; + + assert_eq!( + result.expect_err("comment-only batch should be rejected"), + "Batch must contain at least one executable statement." + ); + assert!( + !db.in_transaction, + "comment-only batch rejection should leave no open transaction" + ); + } + + #[wasm_bindgen_test] + async fn exec_batch_ignores_comment_only_statements_around_executable_statements() { + let Some(mut db) = get_test_db().await else { + return; + }; + + let result = db + .exec_batch(vec![ + SqlBatchStatement { + sql: "-- comment only".to_string(), + params: None, + }, + SqlBatchStatement { + sql: "SELECT 'executed' as label".to_string(), + params: None, + }, + SqlBatchStatement { + sql: "/* trailing comment only */".to_string(), + params: None, + }, + ]) + .await + .expect("batch should execute non-comment statement"); + + let rows: serde_json::Value = serde_json::from_str(&result).expect("select result json"); + assert_eq!(rows[0]["label"].as_str(), Some("executed")); + assert!(!db.in_transaction, "batch should commit before returning"); + } + + #[wasm_bindgen_test] + async fn exec_batch_rejects_transaction_control_statements() { + let Some(mut db) = get_test_db().await else { + return; + }; + + for sql in [ + "BEGIN TRANSACTION", + "COMMIT", + "ROLLBACK", + "END TRANSACTION", + "SAVEPOINT sp1", + "RELEASE sp1", + ] { + let result = db + .exec_batch(vec![SqlBatchStatement { + sql: sql.to_string(), + params: None, + }]) + .await; + assert!(result + .expect_err("transaction control should be rejected") + .contains("transaction() manages the transaction for you")); + assert!( + !db.in_transaction, + "rejection should leave no open transaction" + ); + } + } + + #[wasm_bindgen_test] + async fn exec_batch_refreshes_stale_transaction_state_before_rejecting() { + let Some(mut db) = get_test_db().await else { + return; + }; + + db.exec("DROP TABLE IF EXISTS batch_stale_state_test") + .await + .ok(); + db.exec("CREATE TABLE batch_stale_state_test (id INTEGER PRIMARY KEY)") + .await + .expect("create table"); + db.exec("BEGIN TRANSACTION") + .await + .expect("begin transaction"); + assert!(db.in_transaction, "BEGIN should mark the cache as open"); + + let result = db + .exec("COMMIT; SELECT * FROM missing_batch_stale_state_table;") + .await; + assert!(result.is_err(), "second statement should fail after COMMIT"); + assert!( + db.in_transaction, + "the error path leaves the cached transaction state stale" + ); + + db.exec_batch(vec![SqlBatchStatement { + sql: "INSERT INTO batch_stale_state_test DEFAULT VALUES".to_string(), + params: None, + }]) + .await + .expect("batch should refresh stale state before checking for open transactions"); + assert!( + !db.in_transaction, + "successful batch should leave no open transaction" + ); + } + + #[wasm_bindgen_test] + fn transaction_control_detection_skips_leading_comments() { + assert!(SQLiteDatabase::is_transaction_control_statement( + "/* leading */ COMMIT;" + )); + assert!(SQLiteDatabase::is_transaction_control_statement( + "-- leading\nROLLBACK" + )); + assert!(SQLiteDatabase::is_transaction_control_statement( + "END TRANSACTION" + )); + assert!(SQLiteDatabase::is_transaction_control_statement( + "SAVEPOINT sp1" + )); + assert!(SQLiteDatabase::is_transaction_control_statement( + "RELEASE sp1" + )); + assert!(!SQLiteDatabase::is_transaction_control_statement( + "INSERT INTO t VALUES ('COMMIT')" + )); + assert!(!SQLiteDatabase::is_transaction_control_statement( + "START TRANSACTION" + )); + } + #[wasm_bindgen_test] async fn test_sql_splitting_utility() { // Ensure production logic handles multiple semicolons and empty statements gracefully @@ -1698,6 +2304,7 @@ mod tests { let parsed: serde_json::Value = serde_json::from_str(&res).expect("Invalid JSON"); let array = parsed.as_array().expect("Should be array"); assert_eq!(array.len(), 1, "Only first result set should be returned"); + assert_eq!(array[0]["1"].as_i64(), Some(1)); } #[wasm_bindgen_test] diff --git a/packages/sqlite-web-core/src/messages.rs b/packages/sqlite-web-core/src/messages.rs index cb2f249..6fba81b 100644 --- a/packages/sqlite-web-core/src/messages.rs +++ b/packages/sqlite-web-core/src/messages.rs @@ -13,6 +13,14 @@ pub struct WorkerErrorPayload { pub message: Option, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub struct SqlBatchStatement { + pub sql: String, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(default)] + pub params: Option>, +} + // Message types for BroadcastChannel communication #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[serde(tag = "type")] @@ -36,6 +44,12 @@ pub enum ChannelMessage { #[serde(default)] params: Option>, }, + #[serde(rename = "batch-request")] + BatchRequest { + #[serde(rename = "queryId")] + query_id: String, + statements: Vec, + }, #[serde(rename = "query-response")] QueryResponse { #[serde(rename = "queryId")] @@ -63,6 +77,12 @@ pub enum WorkerMessage { #[serde(default)] params: Option>, }, + #[serde(rename = "execute-batch")] + ExecuteBatch { + #[serde(rename = "requestId")] + request_id: u32, + statements: Vec, + }, } // Messages to main thread @@ -126,6 +146,19 @@ mod tests { assert!(json.contains("\"sql\":\"SELECT * FROM users\"")); }); + let batch_request = ChannelMessage::BatchRequest { + query_id: "batch-456".to_string(), + statements: vec![SqlBatchStatement { + sql: "INSERT INTO users (name) VALUES (?)".to_string(), + params: Some(vec![serde_json::json!("Alice")]), + }], + }; + assert_serialization_roundtrip(batch_request, "batch-request", |json| { + assert!(json.contains("\"queryId\":\"batch-456\"")); + assert!(json.contains("\"statements\"")); + assert!(json.contains("\"params\"")); + }); + let query_success = ChannelMessage::QueryResponse { query_id: "query-789".to_string(), result: Some("[{\"id\": 1, \"name\": \"test\"}]".to_string()), @@ -175,6 +208,37 @@ mod tests { assert_eq!(sql, "INSERT INTO table VALUES (1, 'test')"); assert_eq!(request_id, 42); } + other => panic!("expected ExecuteQuery, got {other:?}"), + } + } + + #[wasm_bindgen_test] + fn test_worker_message_execute_batch_serialization() { + // Guard the JS/Rust worker wire format against accidental message renames. + let msg = WorkerMessage::ExecuteBatch { + request_id: 43, + statements: vec![SqlBatchStatement { + sql: "INSERT INTO table VALUES (?)".to_string(), + params: Some(vec![serde_json::json!(1)]), + }], + }; + + let json = serde_json::to_string(&msg).expect("Should serialize"); + assert!(json.contains("\"type\":\"execute-batch\"")); + assert!(json.contains("\"requestId\":43")); + assert!(json.contains("\"statements\"")); + + let deserialized: WorkerMessage = serde_json::from_str(&json).expect("Should deserialize"); + match deserialized { + WorkerMessage::ExecuteBatch { + request_id, + statements, + } => { + assert_eq!(request_id, 43); + assert_eq!(statements.len(), 1); + assert_eq!(statements[0].sql, "INSERT INTO table VALUES (?)"); + } + other => panic!("expected ExecuteBatch, got {other:?}"), } } diff --git a/packages/sqlite-web/src/db.rs b/packages/sqlite-web/src/db.rs index 0c22f56..f3aa0ee 100644 --- a/packages/sqlite-web/src/db.rs +++ b/packages/sqlite-web/src/db.rs @@ -5,6 +5,7 @@ use std::rc::Rc; use js_sys::{Array, Reflect}; use serde::Serialize; use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; use wasm_bindgen_futures::JsFuture; use wasm_bindgen_utils::prelude::*; use web_sys::Worker; @@ -78,6 +79,63 @@ impl SQLiteWasmDatabase { normalize_params_js(¶ms_js) } + fn normalize_batch_statements(statements: Array) -> Result { + if statements.length() == 0 { + return Err(SQLiteWasmDatabaseError::JsError(JsValue::from_str( + "transaction requires at least one statement", + ))); + } + + (0..statements.length()).try_fold(Array::new(), |normalized, i| { + let input = statements.get(i); + if !input.is_object() || input.is_null() { + return Err(SQLiteWasmDatabaseError::JsError(JsValue::from_str( + &format!("Batch statement {} must be an object", i + 1), + ))); + } + let sql = Reflect::get(&input, &JsValue::from_str("sql")) + .map_err(SQLiteWasmDatabaseError::JsError)? + .as_string() + .ok_or_else(|| { + SQLiteWasmDatabaseError::JsError(JsValue::from_str(&format!( + "Batch statement {} must include a sql string", + i + 1 + ))) + })?; + if sql.trim().is_empty() { + return Err(SQLiteWasmDatabaseError::JsError(JsValue::from_str( + &format!( + "Batch statement {} must include a non-empty sql string", + i + 1 + ), + ))); + } + + let statement = js_sys::Object::new(); + Reflect::set( + &statement, + &JsValue::from_str("sql"), + &JsValue::from_str(&sql), + ) + .map_err(SQLiteWasmDatabaseError::JsError)?; + + let params_value = Reflect::get(&input, &JsValue::from_str("params")) + .map_err(SQLiteWasmDatabaseError::JsError)?; + if !params_value.is_undefined() && !params_value.is_null() { + let params = normalize_params_js(¶ms_value)?; + Reflect::set( + &statement, + &JsValue::from_str("params"), + &JsValue::from(params), + ) + .map_err(SQLiteWasmDatabaseError::JsError)?; + } + + normalized.push(&statement); + Ok(normalized) + }) + } + async fn wait_until_ready(&self) -> Result<(), SQLiteWasmDatabaseError> { match self.ready_signal.current_state() { InitializationState::Ready => return Ok(()), @@ -183,6 +241,81 @@ impl SQLiteWasmDatabase { Ok(result.as_string().unwrap_or_else(|| format!("{result:?}"))) } + /// Execute a list of single SQL statements atomically as one worker job. + /// + /// Each item must be `{ sql: string, params?: Array }`. Do not include + /// transaction-control statements; the worker owns the transaction. + #[wasm_export(js_name = "transaction", unchecked_return_type = "string")] + pub async fn transaction(&self, statements: Array) -> Result { + self.transaction_inner(statements).await + } + + async fn transaction_inner( + &self, + statements: Array, + ) -> Result { + let worker = Rc::clone(&self.worker); + let pending_queries = Rc::clone(&self.pending_queries); + let statements = Self::normalize_batch_statements(statements)?; + + if let InitializationState::Failed(reason) = self.ready_signal.current_state() { + return Err(SQLiteWasmDatabaseError::InitializationFailed(reason)); + } + + let message = js_sys::Object::new(); + Reflect::set( + &message, + &JsValue::from_str("type"), + &JsValue::from_str("execute-batch"), + ) + .map_err(SQLiteWasmDatabaseError::JsError)?; + + let request_id = { + let mut n = self.next_request_id.borrow_mut(); + let id = *n; + *n = n.wrapping_add(1).max(1); + id + }; + Reflect::set( + &message, + &JsValue::from_str("requestId"), + &JsValue::from_f64(request_id as f64), + ) + .map_err(SQLiteWasmDatabaseError::JsError)?; + Reflect::set( + &message, + &JsValue::from_str("statements"), + &JsValue::from(statements), + ) + .map_err(SQLiteWasmDatabaseError::JsError)?; + + let rid_for_insert = request_id; + let promise = js_sys::Promise::new(&mut |resolve, reject| match worker + .borrow() + .post_message(&message) + { + Ok(()) => { + pending_queries + .borrow_mut() + .insert(rid_for_insert, (resolve, reject)); + } + Err(err) => { + let _ = reject.call1(&JsValue::NULL, &err); + } + }); + + let result = match JsFuture::from(promise).await { + Ok(value) => value, + Err(err) if is_initialization_pending_error(&err) => { + return Err(SQLiteWasmDatabaseError::InitializationPending); + } + Err(err) => { + return Err(SQLiteWasmDatabaseError::JsError(err)); + } + }; + Ok(result.as_string().unwrap_or_else(|| format!("{result:?}"))) + } + #[wasm_export(js_name = "wipeAndRecreate", unchecked_return_type = "void")] pub async fn wipe_and_recreate(&self) -> Result<(), SQLiteWasmDatabaseError> { self.worker.borrow().terminate(); @@ -194,7 +327,7 @@ impl SQLiteWasmDatabase { self.ready_signal.reset(); - let deletion_result = delete_opfs_sahpool_directory().await; + let deletion_result = delete_opfs_sahpool_directory_with_retries().await; let worker_code = generate_self_contained_worker(&self.db_name); let new_worker = @@ -224,11 +357,46 @@ fn is_initialization_pending_error(err: &JsValue) -> bool { err.as_string().as_deref() == Some(WORKER_ERROR_TYPE_INITIALIZATION_PENDING) } +async fn delete_opfs_sahpool_directory_with_retries() -> Result<(), SQLiteWasmDatabaseError> { + let mut deletion_result = delete_opfs_sahpool_directory().await; + for _ in 0..4 { + if deletion_result.is_ok() { + return deletion_result; + } + sleep_ms(50).await; + deletion_result = delete_opfs_sahpool_directory().await; + } + deletion_result +} + +async fn sleep_ms(ms: i32) { + let promise = js_sys::Promise::new(&mut |resolve, _reject| { + let Some(window) = web_sys::window() else { + let _ = resolve.call0(&JsValue::UNDEFINED); + return; + }; + + let resolve_for_timeout = resolve.clone(); + let callback = wasm_bindgen::closure::Closure::once_into_js(move || { + let _ = resolve_for_timeout.call0(&JsValue::UNDEFINED); + }); + + if window + .set_timeout_with_callback_and_timeout_and_arguments_0(callback.unchecked_ref(), ms) + .is_err() + { + let _ = resolve.call0(&JsValue::UNDEFINED); + } + }); + + let _ = JsFuture::from(promise).await; +} + #[cfg(all(test, target_family = "wasm"))] mod tests { use super::*; use base64::Engine; - use js_sys::{Array, ArrayBuffer, BigInt, Object, Uint8Array}; + use js_sys::{Array, ArrayBuffer, BigInt, Function, Object, Uint8Array}; use wasm_bindgen_test::*; wasm_bindgen_test_configure!(run_in_browser); @@ -244,6 +412,123 @@ mod tests { assert_eq!(normalized.length(), 0); } + #[wasm_bindgen_test] + fn normalize_batch_statements_requires_non_empty_array() { + let empty = Array::new(); + let err = SQLiteWasmDatabase::normalize_batch_statements(empty) + .expect_err("empty batch should be rejected"); + match err { + SQLiteWasmDatabaseError::JsError(js) => assert_eq!( + js.as_string().as_deref(), + Some("transaction requires at least one statement") + ), + other => panic!("expected JsError, got {other:?}"), + } + } + + #[wasm_bindgen_test] + fn normalize_batch_statements_rejects_empty_sql() { + let statements = Array::new(); + let statement = Object::new(); + Reflect::set( + &statement, + &JsValue::from_str("sql"), + &JsValue::from_str(" \n\t "), + ) + .unwrap(); + statements.push(&statement); + + let err = SQLiteWasmDatabase::normalize_batch_statements(statements) + .expect_err("empty SQL should be rejected"); + match err { + SQLiteWasmDatabaseError::JsError(js) => assert_eq!( + js.as_string().as_deref(), + Some("Batch statement 1 must include a non-empty sql string") + ), + other => panic!("expected JsError, got {other:?}"), + } + } + + #[wasm_bindgen_test] + fn normalize_batch_statements_normalizes_params() { + let statements = Array::new(); + let statement = Object::new(); + Reflect::set( + &statement, + &JsValue::from_str("sql"), + &JsValue::from_str("SELECT ?"), + ) + .unwrap(); + let params = Array::new(); + let bi: JsValue = BigInt::from(77u32).into(); + params.push(&bi); + Reflect::set(&statement, &JsValue::from_str("params"), ¶ms).unwrap(); + statements.push(&statement); + + let normalized = SQLiteWasmDatabase::normalize_batch_statements(statements) + .expect("valid batch should normalize"); + let first = normalized.get(0); + assert_eq!( + Reflect::get(&first, &JsValue::from_str("sql")) + .unwrap() + .as_string() + .as_deref(), + Some("SELECT ?") + ); + let normalized_params = Reflect::get(&first, &JsValue::from_str("params")).unwrap(); + let normalized_params: Array = normalized_params.unchecked_into(); + let encoded_bigint = normalized_params.get(0); + assert_eq!( + Reflect::get(&encoded_bigint, &JsValue::from_str("__type")) + .unwrap() + .as_string() + .as_deref(), + Some("bigint") + ); + assert_eq!( + Reflect::get(&encoded_bigint, &JsValue::from_str("value")) + .unwrap() + .as_string() + .as_deref(), + Some("77") + ); + } + + #[wasm_bindgen_test] + fn normalize_batch_statements_propagates_params_getter_errors() { + let statements = Array::new(); + let statement = Object::new(); + Reflect::set( + &statement, + &JsValue::from_str("sql"), + &JsValue::from_str("SELECT ?"), + ) + .unwrap(); + + let descriptor = Object::new(); + Reflect::set( + &descriptor, + &JsValue::from_str("get"), + &Function::new_no_args("throw new Error('params getter failed')"), + ) + .unwrap(); + Object::define_property(&statement, &JsValue::from_str("params"), &descriptor); + statements.push(&statement); + + let err = SQLiteWasmDatabase::normalize_batch_statements(statements) + .expect_err("throwing params getter should be propagated"); + match err { + SQLiteWasmDatabaseError::JsError(js) => { + let message = describe_js_value(&js); + assert!( + message.contains("params getter failed"), + "unexpected JS error: {message}" + ); + } + other => panic!("expected JsError, got {other:?}"), + } + } + #[wasm_bindgen_test] fn normalize_params_normalizes_mixed_values() { let params = Array::new(); diff --git a/scripts/local-bundle.sh b/scripts/local-bundle.sh index 774468e..d1eadc1 100755 --- a/scripts/local-bundle.sh +++ b/scripts/local-bundle.sh @@ -67,7 +67,7 @@ JS_GLUE_PLACEHOLDER // Initialize the worker after everything is set up // For web target, wasm_bindgen is a function, not an object console.log('[Worker] Initializing core WASM...'); - wasm_bindgen('./sqlite_web_core_bg.wasm').then(function(wasm) { + self.wasm_bindgen('./sqlite_web_core_bg.wasm').then(function(wasm) { console.log('[Worker] Core WASM loaded, starting worker_main...'); if (typeof wasm.worker_main === 'function') { wasm.worker_main(); @@ -93,7 +93,7 @@ echo "🔄 Assembling final worker..." sed '/JS_GLUE_PLACEHOLDER/,$d' packages/sqlite-web/src/embedded_worker.js # Add the JS glue code (convert exports to regular variables for worker context) - sed 's/^export function /function /; s/^export class /class /; s/^export { initSync };/self.initSync = initSync;/; s/^export default __wbg_init;/self.wasm_bindgen = __wbg_init;/; s/import\.meta\.url/self.location.href/g' pkg/sqlite_web_core.js + sed 's/^export function /function /; s/^export class /class /; s/^export { initSync };/self.initSync = initSync;/; s/^export default __wbg_init;/self.wasm_bindgen = __wbg_init;/; s/^export { initSync, __wbg_init as default };/self.initSync = initSync; self.wasm_bindgen = __wbg_init;/; s/import\.meta\.url/self.location.href/g' pkg/sqlite_web_core.js # Add the rest of the template (everything after JS_GLUE_PLACEHOLDER) sed '1,/JS_GLUE_PLACEHOLDER/d' packages/sqlite-web/src/embedded_worker.js diff --git a/svelte-test/bun.lock b/svelte-test/bun.lock index 2762957..21707c5 100644 --- a/svelte-test/bun.lock +++ b/svelte-test/bun.lock @@ -4,7 +4,7 @@ "": { "name": "svelte-test", "dependencies": { - "@rainlanguage/sqlite-web": "file:../pkg/rainlanguage-sqlite-web-0.1.0.tgz", + "@rainlanguage/sqlite-web": "file:../pkg/rainlanguage-sqlite-web-0.0.2.tgz", }, "devDependencies": { "@eslint/js": "^9.33.0", @@ -490,7 +490,7 @@ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - "@rainlanguage/sqlite-web": ["@rainlanguage/sqlite-web@../pkg/rainlanguage-sqlite-web-0.1.0.tgz", {}], + "@rainlanguage/sqlite-web": ["@rainlanguage/sqlite-web@../pkg/rainlanguage-sqlite-web-0.0.2.tgz", {}], "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], diff --git a/svelte-test/package-lock.json b/svelte-test/package-lock.json index 50fdbf1..e47131d 100644 --- a/svelte-test/package-lock.json +++ b/svelte-test/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.1", "dependencies": { "@rainlanguage/float": "^0.0.0-alpha.22", - "@rainlanguage/sqlite-web": "file:../pkg/rainlanguage-sqlite-web-0.0.1-alpha.20.tgz" + "@rainlanguage/sqlite-web": "file:../pkg/rainlanguage-sqlite-web-0.0.2.tgz" }, "devDependencies": { "@sveltejs/adapter-auto": "^6.0.0", @@ -912,9 +912,9 @@ } }, "node_modules/@rainlanguage/sqlite-web": { - "version": "0.0.1-alpha.20", - "resolved": "file:../pkg/rainlanguage-sqlite-web-0.0.1-alpha.20.tgz", - "integrity": "sha512-FbZSTg/UyLPWZqyktF5q+Wj7jkR1vJXE65PPpRp2E8FXGFXfz9VkAdHYWnE9ogR6JcskuqwENgepjTAE8w8zyA==" + "version": "0.0.2", + "resolved": "file:../pkg/rainlanguage-sqlite-web-0.0.2.tgz", + "integrity": "sha512-6T2e8gpHUCZNNnveADR9aWBBbSuUxpVHs5T+M1EPnUPifFwvoSmGffloUDpLjg0bk8Pi0288kUdu1kFDqcPM7A==" }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.57.0", diff --git a/svelte-test/package.json b/svelte-test/package.json index 5a9ad8e..1955d31 100644 --- a/svelte-test/package.json +++ b/svelte-test/package.json @@ -41,6 +41,6 @@ "type": "module", "dependencies": { "@rainlanguage/float": "^0.0.0-alpha.22", - "@rainlanguage/sqlite-web": "file:../pkg/rainlanguage-sqlite-web-0.0.1-alpha.20.tgz" + "@rainlanguage/sqlite-web": "file:../pkg/rainlanguage-sqlite-web-0.0.2.tgz" } } diff --git a/svelte-test/tests/integration/transaction-interleaving.test.ts b/svelte-test/tests/integration/transaction-interleaving.test.ts new file mode 100644 index 0000000..85ac3cf --- /dev/null +++ b/svelte-test/tests/integration/transaction-interleaving.test.ts @@ -0,0 +1,154 @@ +import { describe, it, expect } from "vitest"; +import { createTestDatabase } from "../fixtures/test-helpers.js"; + +describe("Transaction interleaving", () => { + // Reuse one OPFS database name in this file because sqlite-web does not expose + // a close API; opening independent sahpool handles per test can conflict. + const dbName = `transaction-interleaving-${Date.now()}`; + + it("executes a transaction batch and returns the last row result", async () => { + const db = await createTestDatabase(dbName); + + await db.query("DROP TABLE IF EXISTS batch_api_test"); + const batchResult = await db.transaction([ + { + sql: "CREATE TABLE batch_api_test (id INTEGER PRIMARY KEY, name TEXT)", + }, + { + sql: "SELECT 'first' as label", + }, + { + sql: "INSERT INTO batch_api_test (name) VALUES (?)", + params: ["Alice"], + }, + { + sql: "SELECT COUNT(*) as count FROM batch_api_test", + }, + ]); + + expect(batchResult.error).toBeUndefined(); + const batchRows = JSON.parse(batchResult.value || "[]"); + expect(batchRows[0].count).toBe(1); + + await db.query("DROP TABLE IF EXISTS batch_api_test"); + }); + + it("rolls back all transaction statements after a mid-batch failure", async () => { + const db = await createTestDatabase(dbName); + + await db.query("DROP TABLE IF EXISTS batch_api_rollback_test"); + await db.query( + "CREATE TABLE batch_api_rollback_test (id INTEGER PRIMARY KEY, name TEXT)", + ); + + const rollbackResult = await db.transaction([ + { + sql: "INSERT INTO batch_api_rollback_test (id, name) VALUES (1, 'Alice')", + }, + { + sql: "INSERT INTO missing_batch_api_table (id) VALUES (1)", + }, + ]); + + expect( + rollbackResult.error?.readableMsg || rollbackResult.error?.msg || "", + ).toContain("Batch statement 2 failed"); + + const countResult = await db.query( + "SELECT COUNT(*) as count FROM batch_api_rollback_test", + ); + const rollbackRows = JSON.parse(countResult.value || "[]"); + expect(rollbackRows[0].count).toBe(0); + + await db.query("DROP TABLE IF EXISTS batch_api_rollback_test"); + }); + + it("does not expose partial transaction state to a competing client", async () => { + const db = await createTestDatabase(dbName); + const clientB = await createTestDatabase(dbName); + + await db.query("DROP TABLE IF EXISTS batch_api_visibility_test"); + await db.query( + "CREATE TABLE batch_api_visibility_test (id INTEGER PRIMARY KEY)", + ); + + const batchVisibility = db.transaction([ + { + sql: "INSERT INTO batch_api_visibility_test DEFAULT VALUES", + }, + { + sql: "INSERT INTO batch_api_visibility_test DEFAULT VALUES", + }, + ]); + const competingRead = clientB.query( + "SELECT COUNT(*) as count FROM batch_api_visibility_test", + ); + const [visibilityResult, competingReadResult] = await Promise.all([ + batchVisibility, + competingRead, + ]); + + expect(visibilityResult.error).toBeUndefined(); + expect(competingReadResult.error).toBeUndefined(); + + const competingRows = JSON.parse(competingReadResult.value || "[]"); + expect([0, 2]).toContain(competingRows[0].count); + + const finalVisibilityResult = await db.query( + "SELECT COUNT(*) as count FROM batch_api_visibility_test", + ); + const finalVisibilityRows = JSON.parse(finalVisibilityResult.value || "[]"); + expect(finalVisibilityRows[0].count).toBe(2); + + await db.query("DROP TABLE IF EXISTS batch_api_visibility_test"); + }); + + it("allows a follower client to originate a transaction batch", async () => { + const db = await createTestDatabase(dbName); + const clientB = await createTestDatabase(dbName); + + await db.query("DROP TABLE IF EXISTS batch_api_follower_test"); + await db.query( + "CREATE TABLE batch_api_follower_test (id INTEGER PRIMARY KEY, name TEXT)", + ); + + const followerTransaction = await clientB.transaction([ + { + sql: "INSERT INTO batch_api_follower_test (name) VALUES (?)", + params: ["Bob"], + }, + { + sql: "INSERT INTO batch_api_follower_test (name) VALUES (?)", + params: ["Carol"], + }, + ]); + + expect(followerTransaction.error).toBeUndefined(); + + const countResult = await db.query( + "SELECT COUNT(*) as count FROM batch_api_follower_test", + ); + const countRows = JSON.parse(countResult.value || "[]"); + expect(countRows[0].count).toBe(2); + + await db.query("DROP TABLE IF EXISTS batch_api_follower_test"); + }); + + it("reproduces split transaction interleaving with separate query calls", async () => { + const db = await createTestDatabase(dbName); + const clientB = await createTestDatabase(dbName); + + await db.query("DROP TABLE IF EXISTS interleave_test"); + await db.query("CREATE TABLE interleave_test (id INTEGER PRIMARY KEY)"); + + await db.query("BEGIN TRANSACTION"); + const clientBBegin = await clientB.query("BEGIN TRANSACTION"); + + const message = + clientBBegin.error?.readableMsg ?? clientBBegin.error?.msg ?? ""; + expect(message).toContain("cannot start a transaction within a transaction"); + + await db.query("ROLLBACK"); + await db.query("DROP TABLE IF EXISTS interleave_test"); + }); +});