diff --git a/Cargo.lock b/Cargo.lock index 1b9a9b25f..1ac755ecd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "alloy-eip7702" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6cee6a35793f3db8a5ffe60e86c695f321d081a567211245f503e8c498fce8" +checksum = "4c986539255fb839d1533c128e190e557e52ff652c9ef62939e233a81dd93f7e" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -131,7 +131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b6aa3961694b30ba53d41006131a2fca3bdab22e4c344e46db2c639e7c2dfdd" dependencies = [ "alloy-eip2930", - "alloy-eip7702 0.4.1", + "alloy-eip7702 0.4.2", "alloy-primitives", "alloy-rlp", "alloy-serde", @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fce5dbd6a4f118eecc4719eaa9c7ffc31c315e6c5ccde3642db927802312425" +checksum = "3aeeb5825c2fc8c2662167058347cd0cafc3cb15bcb5cdb1758a63c2dca0409e" dependencies = [ "alloy-rlp", "arbitrary", @@ -206,7 +206,7 @@ dependencies = [ "derive_arbitrary", "derive_more", "foldhash", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "hex-literal", "indexmap 2.6.0", "itoa", @@ -279,7 +279,7 @@ checksum = "2b09cae092c27b6f1bde952653a22708691802e57bfef4a2973b80bea21efd3f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -404,23 +404,23 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9343289b4a7461ed8bab8618504c995c049c082b70c7332efd7b32125633dc05" +checksum = "5c0279d09463a4695788a3622fd95443625f7be307422deba4b55dd491a9c7a1" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] name = "alloy-sol-macro-expander" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4222d70bec485ceccc5d8fd4f2909edd65b5d5e43d4aca0b5dcee65d519ae98f" +checksum = "4feea540fc8233df2ad1156efd744b2075372f43a8f942a68b3b19c8a00e2c12" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -429,31 +429,31 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e17f2677369571b976e51ea1430eb41c3690d344fef567b840bfc0b01b6f83a" +checksum = "2a0ad281f3d1b613af814b66977ee698e443d4644a1510962d0241f26e0e53ae" dependencies = [ "const-hex", "dunce", "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "syn-solidity", ] [[package]] name = "alloy-sol-types" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6520d427d4a8eb7aa803d852d7a52ceb0c519e784c292f64bb339e636918cf27" +checksum = "cff34e0682d6665da243a3e81da96f07a2dd50f7e64073e382b1a141f5a2a2f6" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -757,7 +757,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -768,7 +768,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -795,7 +795,7 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -854,7 +854,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -970,7 +970,7 @@ checksum = "523363cbe1df49b68215efdf500b103ac3b0fb4836aed6d15689a076eadb8fff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1134,7 +1134,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1160,9 +1160,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0121754e84117e65f9d90648ee6aa4882a6e63110307ab73967a4c5e7e69e586" +checksum = "487981fa1af147182687064d0a2c336586d337a606595ced9ffb0c685c250c73" dependencies = [ "cfg-if", "cpufeatures", @@ -1204,9 +1204,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -1321,7 +1321,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1332,7 +1332,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1397,7 +1397,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1417,7 +1417,7 @@ checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "unicode-xid", ] @@ -1450,7 +1450,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1521,7 +1521,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1710,7 +1710,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -1843,9 +1843,9 @@ checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", @@ -2145,7 +2145,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2186,13 +2186,13 @@ dependencies = [ [[package]] name = "impl-trait-for-tuples" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.89", ] [[package]] @@ -2214,7 +2214,7 @@ checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "arbitrary", "equivalent", - "hashbrown 0.15.1", + "hashbrown 0.15.2", "serde", ] @@ -2288,9 +2288,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -2562,7 +2562,7 @@ dependencies = [ "kona-std-fpvm", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2582,9 +2582,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36" [[package]] name = "libloading" @@ -2644,9 +2644,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -2670,7 +2670,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.15.1", + "hashbrown 0.15.2", ] [[package]] @@ -2738,7 +2738,7 @@ checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -2906,7 +2906,7 @@ checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3048,7 +3048,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3111,7 +3111,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3183,7 +3183,7 @@ checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3327,14 +3327,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -3367,7 +3367,7 @@ checksum = "6ff7ff745a347b87471d859a377a9a404361e7efc2a971d73424a6d183c0fc77" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3387,7 +3387,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3689,13 +3689,13 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395027076c569819ea6035ee62e664f5e03d74e281744f55261dd1afd939212b" +checksum = "b11a153aec4a6ab60795f8ebe2923c597b16b05bb1504377451e705ef1a45323" dependencies = [ "bytecheck", "bytes", - "hashbrown 0.14.5", + "hashbrown 0.15.2", "indexmap 2.6.0", "munge", "ptr_meta", @@ -3708,13 +3708,13 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cb82b74b4810f07e460852c32f522e979787691b0b7b7439fe473e49d49b2f" +checksum = "beb382a4d9f53bd5c0be86b10d8179c3f8a14c30bf774ff77096ed6581e35981" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -3825,9 +3825,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.18" +version = "0.23.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" +checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" dependencies = [ "once_cell", "rustls-pki-types", @@ -4018,7 +4018,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4042,7 +4042,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4084,7 +4084,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4257,7 +4257,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4281,9 +4281,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" -version = "12.12.1" +version = "12.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4d73159efebfb389d819fd479afb2dbd57dcb3e3f4b7fcfa0e675f5a46c1cb" +checksum = "e5ba5365997a4e375660bed52f5b42766475d5bc8ceb1bb13fea09c469ea0f49" dependencies = [ "debugid", "memmap2", @@ -4293,9 +4293,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.12.1" +version = "12.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a767859f6549c665011970874c3f541838b4835d5aaaa493d3ee383918be9f10" +checksum = "beff338b2788519120f38c59ff4bb15174f52a183e547bac3d6072c2c0aa48aa" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -4315,9 +4315,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" dependencies = [ "proc-macro2", "quote", @@ -4326,14 +4326,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f76fe0a3e1476bdaa0775b9aec5b869ed9520c2b2fedfe9c6df3618f8ea6290b" +checksum = "6bdaa7b9e815582ba343a20c66627437cf45f1c6fba7f69772cbfd1358c7e197" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4359,7 +4359,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4428,7 +4428,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4439,7 +4439,7 @@ checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4562,7 +4562,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -4667,20 +4667,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -4773,9 +4773,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -4880,7 +4880,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "wasm-bindgen-shared", ] @@ -4914,7 +4914,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5133,9 +5133,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -5145,13 +5145,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "synstructure", ] @@ -5173,27 +5173,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", "synstructure", ] @@ -5214,7 +5214,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] [[package]] @@ -5236,5 +5236,5 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.89", ] diff --git a/bin/host/src/blobs.rs b/bin/host/src/blobs.rs new file mode 100644 index 000000000..908cb12f5 --- /dev/null +++ b/bin/host/src/blobs.rs @@ -0,0 +1,237 @@ +//! Contains an online implementation of the `BlobProvider` trait. + +use alloy_eips::eip4844::{Blob, BlobTransactionSidecarItem, IndexedBlobHash}; +use alloy_rpc_types_beacon::sidecar::{BeaconBlobBundle, BlobData}; +use async_trait::async_trait; +use kona_derive::{errors::BlobProviderError, traits::BlobProvider}; +use op_alloy_protocol::BlockInfo; +use reqwest::Client; + +/// The config spec engine api method. +const SPEC_METHOD: &str = "eth/v1/config/spec"; + +/// The beacon genesis engine api method. +const GENESIS_METHOD: &str = "eth/v1/beacon/genesis"; + +/// The blob sidecars engine api method prefix. +const SIDECARS_METHOD_PREFIX: &str = "eth/v1/beacon/blob_sidecars"; + +/// A reduced genesis data. +#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct ReducedGenesisData { + /// The genesis time. + #[serde(rename = "genesis_time")] + #[serde(with = "alloy_serde::quantity")] + pub genesis_time: u64, +} + +/// An API genesis response. +#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct APIGenesisResponse { + /// The data. + pub data: ReducedGenesisData, +} + +/// A reduced config data. +#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct ReducedConfigData { + /// The seconds per slot. + #[serde(rename = "SECONDS_PER_SLOT")] + #[serde(with = "alloy_serde::quantity")] + pub seconds_per_slot: u64, +} + +/// An API config response. +#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct APIConfigResponse { + /// The data. + pub data: ReducedConfigData, +} + +impl APIConfigResponse { + /// Creates a new API config response. + pub const fn new(seconds_per_slot: u64) -> Self { + Self { data: ReducedConfigData { seconds_per_slot } } + } +} + +impl APIGenesisResponse { + /// Creates a new API genesis response. + pub const fn new(genesis_time: u64) -> Self { + Self { data: ReducedGenesisData { genesis_time } } + } +} + +/// An online implementation of the [BlobProvider] trait. +#[derive(Debug, Clone)] +pub struct OnlineBlobProvider { + /// The base url. + base: String, + /// The inner reqwest client. + inner: Client, + /// The genesis time. + genesis_time: u64, + /// The slot interval. + slot_interval: u64, +} + +impl OnlineBlobProvider { + /// Creates a new instance of the [OnlineBlobProvider]. + /// + /// The `genesis_time` and `slot_interval` arguments are _optional_ and the + /// [OnlineBlobProvider] will attempt to load them dynamically at runtime if they are not + /// provided. + pub async fn new_http(base: String) -> Result { + let inner = Client::new(); + let genesis = inner + .get(format!("{}/{}", base, GENESIS_METHOD)) + .send() + .await + .map_err(|_| BlobProviderError::Backend("Failed to fetch genesis".to_string()))?; + let genesis_time = genesis + .json::() + .await + .map_err(|e| BlobProviderError::Backend(e.to_string()))? + .data + .genesis_time; + let spec = inner + .get(format!("{}/{}", base, SPEC_METHOD)) + .send() + .await + .map_err(|_| BlobProviderError::Backend("Failed to fetch config".to_string()))?; + let slot_interval = spec + .json::() + .await + .map_err(|e| BlobProviderError::Backend(e.to_string()))? + .data + .seconds_per_slot; + Ok(Self { base, inner, genesis_time, slot_interval }) + } + + /// Fetches blob sidecars that were confirmed in the specified L1 block with the given indexed + /// hashes. Order of the returned sidecars is guaranteed to be that of the hashes. Blob data is + /// not checked for validity. + async fn beacon_blob_side_cars( + &self, + slot: u64, + hashes: &[IndexedBlobHash], + ) -> Result, reqwest::Error> { + let raw_response = self + .inner + .get(format!("{}/{}/{}", self.base, SIDECARS_METHOD_PREFIX, slot)) + .send() + .await?; + let raw_response = raw_response.json::().await?; + + // Filter the sidecars by the hashes, in-order. + let mut sidecars = Vec::with_capacity(hashes.len()); + hashes.iter().for_each(|hash| { + if let Some(sidecar) = + raw_response.data.iter().find(|sidecar| sidecar.index == hash.index) + { + sidecars.push(sidecar.clone()); + } + }); + + Ok(sidecars) + } + + /// Fetches blob sidecars for the given slot and blob hashes. + pub async fn fetch_sidecars( + &self, + slot: u64, + hashes: &[IndexedBlobHash], + ) -> Result, BlobProviderError> { + self.beacon_blob_side_cars(slot, hashes) + .await + .map_err(|e| BlobProviderError::Backend(e.to_string())) + } + + /// Computes the slot for the given timestamp. + pub const fn slot( + genesis: u64, + slot_time: u64, + timestamp: u64, + ) -> Result { + if timestamp < genesis { + return Err(BlobProviderError::SlotDerivation); + } + Ok((timestamp - genesis) / slot_time) + } + + /// Fetches blob sidecars for the given block reference and blob hashes. + pub async fn fetch_filtered_sidecars( + &self, + block_ref: &BlockInfo, + blob_hashes: &[IndexedBlobHash], + ) -> Result, BlobProviderError> { + if blob_hashes.is_empty() { + return Ok(Vec::new()); + } + + // Calculate the slot for the given timestamp. + let slot = Self::slot(self.genesis_time, self.slot_interval, block_ref.timestamp)?; + + // Fetch blob sidecars for the slot using the given blob hashes. + let sidecars = self.fetch_sidecars(slot, blob_hashes).await?; + + // Filter blob sidecars that match the indicies in the specified list. + let blob_hash_indicies = blob_hashes.iter().map(|b| b.index).collect::>(); + let filtered = sidecars + .into_iter() + .filter(|s| blob_hash_indicies.contains(&s.index)) + .collect::>(); + + // Validate the correct number of blob sidecars were retrieved. + if blob_hashes.len() != filtered.len() { + return Err(BlobProviderError::SidecarLengthMismatch(blob_hashes.len(), filtered.len())); + } + + Ok(filtered + .into_iter() + .map(|s| BlobTransactionSidecarItem { + index: s.index, + blob: s.blob, + kzg_commitment: s.kzg_commitment, + kzg_proof: s.kzg_proof, + }) + .collect::>()) + } +} + +#[async_trait] +impl BlobProvider for OnlineBlobProvider { + type Error = BlobProviderError; + + /// Fetches blob sidecars that were confirmed in the specified L1 block with the given indexed + /// hashes. The blobs are validated for their index and hashes using the specified + /// [IndexedBlobHash]. + async fn get_blobs( + &mut self, + block_ref: &BlockInfo, + blob_hashes: &[IndexedBlobHash], + ) -> Result>, Self::Error> { + // Fetch the blob sidecars for the given block reference and blob hashes. + let sidecars = self.fetch_filtered_sidecars(block_ref, blob_hashes).await?; + + // Validate the blob sidecars straight away with the num hashes. + let blobs = sidecars + .into_iter() + .enumerate() + .map(|(i, sidecar)| { + let hash = blob_hashes + .get(i) + .ok_or(BlobProviderError::Backend("Missing blob hash".to_string()))?; + match sidecar.verify_blob(&alloy_eips::eip4844::IndexedBlobHash { + hash: hash.hash, + index: hash.index, + }) { + Ok(_) => Ok(sidecar.blob), + Err(e) => Err(BlobProviderError::Backend(e.to_string())), + } + }) + .collect::>, BlobProviderError>>() + .map_err(|e| BlobProviderError::Backend(e.to_string()))?; + Ok(blobs) + } +} diff --git a/bin/host/src/cli/mod.rs b/bin/host/src/cli/mod.rs index 324bd8661..a4206960d 100644 --- a/bin/host/src/cli/mod.rs +++ b/bin/host/src/cli/mod.rs @@ -1,11 +1,11 @@ //! This module contains all CLI-specific code for the host binary. use crate::{ + blobs::OnlineBlobProvider, kv::{ DiskKeyValueStore, LocalKeyValueStore, MemoryKeyValueStore, SharedKeyValueStore, SplitKeyValueStore, }, - providers::{OnlineBeaconClient, OnlineBlobProvider}, util, }; use alloy_primitives::B256; @@ -136,15 +136,12 @@ impl HostCli { /// - A [ReqwestProvider] for the L2 node. pub async fn create_providers( &self, - ) -> Result<(ReqwestProvider, OnlineBlobProvider, ReqwestProvider)> { - let beacon_client = OnlineBeaconClient::new_http( + ) -> Result<(ReqwestProvider, OnlineBlobProvider, ReqwestProvider)> { + let blob_provider = OnlineBlobProvider::new_http( self.l1_beacon_address.clone().ok_or(anyhow!("Beacon API URL must be set"))?, - ); - let mut blob_provider = OnlineBlobProvider::new(beacon_client, None, None); - blob_provider - .load_configs() - .await - .map_err(|e| anyhow!("Failed to load blob provider configuration: {e}"))?; + ) + .await + .map_err(|e| anyhow!("Failed to load blob provider configuration: {e}"))?; let l1_provider = util::http_provider( self.l1_node_address.as_ref().ok_or(anyhow!("Provider must be set"))?, ); diff --git a/bin/host/src/fetcher/mod.rs b/bin/host/src/fetcher/mod.rs index 18f777222..644306b97 100644 --- a/bin/host/src/fetcher/mod.rs +++ b/bin/host/src/fetcher/mod.rs @@ -1,11 +1,7 @@ //! This module contains the [Fetcher] struct, which is responsible for fetching preimages from a //! remote source. -use crate::{ - kv::KeyValueStore, - providers::{OnlineBeaconClient, OnlineBlobProvider}, - util, -}; +use crate::{blobs::OnlineBlobProvider, kv::KeyValueStore, util}; use alloy_consensus::{Header, TxEnvelope, EMPTY_ROOT_HASH}; use alloy_eips::{ eip2718::Encodable2718, @@ -41,7 +37,7 @@ where /// L1 chain provider. l1_provider: ReqwestProvider, /// The blob provider - blob_provider: OnlineBlobProvider, + blob_provider: OnlineBlobProvider, /// L2 chain provider. l2_provider: ReqwestProvider, /// L2 head @@ -58,7 +54,7 @@ where pub const fn new( kv_store: Arc>, l1_provider: ReqwestProvider, - blob_provider: OnlineBlobProvider, + blob_provider: OnlineBlobProvider, l2_provider: ReqwestProvider, l2_head: B256, ) -> Self { diff --git a/bin/host/src/lib.rs b/bin/host/src/lib.rs index b523c350c..9f3029633 100644 --- a/bin/host/src/lib.rs +++ b/bin/host/src/lib.rs @@ -2,13 +2,13 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(not(test), warn(unused_crate_dependencies))] +pub mod blobs; pub mod cli; pub use cli::{init_tracing_subscriber, HostCli}; pub mod fetcher; pub mod kv; pub mod preimage; -pub mod providers; pub mod server; pub mod util; diff --git a/bin/host/src/providers/beacon.rs b/bin/host/src/providers/beacon.rs deleted file mode 100644 index 9f6b84748..000000000 --- a/bin/host/src/providers/beacon.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! Contains an online implementation of the `BeaconClient` trait. - -use alloy_eips::eip4844::IndexedBlobHash; -use alloy_rpc_types_beacon::sidecar::{BeaconBlobBundle, BlobData}; -use async_trait::async_trait; -use reqwest::Client; - -/// The config spec engine api method. -pub(crate) const SPEC_METHOD: &str = "eth/v1/config/spec"; - -/// The beacon genesis engine api method. -pub(crate) const GENESIS_METHOD: &str = "eth/v1/beacon/genesis"; - -/// The blob sidecars engine api method prefix. -pub(crate) const SIDECARS_METHOD_PREFIX: &str = "eth/v1/beacon/blob_sidecars"; - -/// A reduced genesis data. -#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub struct ReducedGenesisData { - /// The genesis time. - #[serde(rename = "genesis_time")] - #[serde(with = "alloy_serde::quantity")] - pub genesis_time: u64, -} - -/// An API genesis response. -#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub struct APIGenesisResponse { - /// The data. - pub data: ReducedGenesisData, -} - -/// A reduced config data. -#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub struct ReducedConfigData { - /// The seconds per slot. - #[serde(rename = "SECONDS_PER_SLOT")] - #[serde(with = "alloy_serde::quantity")] - pub seconds_per_slot: u64, -} - -/// An API config response. -#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] -pub struct APIConfigResponse { - /// The data. - pub data: ReducedConfigData, -} - -impl APIConfigResponse { - /// Creates a new API config response. - pub const fn new(seconds_per_slot: u64) -> Self { - Self { data: ReducedConfigData { seconds_per_slot } } - } -} - -impl APIGenesisResponse { - /// Creates a new API genesis response. - pub const fn new(genesis_time: u64) -> Self { - Self { data: ReducedGenesisData { genesis_time } } - } -} - -/// The [BeaconClient] is a thin wrapper around the Beacon API. -#[async_trait] -pub trait BeaconClient { - /// The error type for [BeaconClient] implementations. - type Error: std::fmt::Display + ToString; - - /// Returns the config spec. - async fn config_spec(&self) -> Result; - - /// Returns the beacon genesis. - async fn beacon_genesis(&self) -> Result; - - /// Fetches blob sidecars that were confirmed in the specified L1 block with the given indexed - /// hashes. Order of the returned sidecars is guaranteed to be that of the hashes. Blob data is - /// not checked for validity. - async fn beacon_blob_side_cars( - &self, - slot: u64, - hashes: &[IndexedBlobHash], - ) -> Result, Self::Error>; -} - -/// An online implementation of the [BeaconClient] trait. -#[derive(Debug, Clone)] -pub struct OnlineBeaconClient { - /// The base URL of the beacon API. - base: String, - /// The inner reqwest client. - inner: Client, -} - -impl OnlineBeaconClient { - /// Creates a new [OnlineBeaconClient] from the provided [reqwest::Url]. - pub fn new_http(base: String) -> Self { - Self { base, inner: Client::new() } - } -} - -#[async_trait] -impl BeaconClient for OnlineBeaconClient { - type Error = reqwest::Error; - - async fn config_spec(&self) -> Result { - let first = self.inner.get(format!("{}/{}", self.base, SPEC_METHOD)).send().await?; - first.json::().await - } - - async fn beacon_genesis(&self) -> Result { - let first = self.inner.get(format!("{}/{}", self.base, GENESIS_METHOD)).send().await?; - first.json::().await - } - - async fn beacon_blob_side_cars( - &self, - slot: u64, - hashes: &[IndexedBlobHash], - ) -> Result, Self::Error> { - let raw_response = self - .inner - .get(format!("{}/{}/{}", self.base, SIDECARS_METHOD_PREFIX, slot)) - .send() - .await?; - let raw_response = raw_response.json::().await?; - - // Filter the sidecars by the hashes, in-order. - let mut sidecars = Vec::with_capacity(hashes.len()); - hashes.iter().for_each(|hash| { - if let Some(sidecar) = - raw_response.data.iter().find(|sidecar| sidecar.index == hash.index) - { - sidecars.push(sidecar.clone()); - } - }); - - Ok(sidecars) - } -} diff --git a/bin/host/src/providers/blob.rs b/bin/host/src/providers/blob.rs deleted file mode 100644 index f719537b3..000000000 --- a/bin/host/src/providers/blob.rs +++ /dev/null @@ -1,416 +0,0 @@ -//! Contains an online implementation of the `BlobProvider` trait. - -use crate::providers::{BeaconClient, OnlineBeaconClient}; -use alloy_eips::eip4844::{Blob, BlobTransactionSidecarItem, IndexedBlobHash}; -use alloy_rpc_types_beacon::sidecar::BlobData; -use async_trait::async_trait; -use kona_derive::{errors::BlobProviderError, traits::BlobProvider}; -use op_alloy_protocol::BlockInfo; -use tracing::warn; - -/// An online implementation of the [BlobProvider] trait. -#[derive(Debug, Clone)] -pub struct OnlineBlobProvider { - /// The Beacon API client. - beacon_client: B, - /// Beacon Genesis time used for the time to slot conversion. - pub genesis_time: Option, - /// Slot interval used for the time to slot conversion. - pub slot_interval: Option, -} - -impl OnlineBlobProvider { - /// Creates a new instance of the [OnlineBlobProvider]. - /// - /// The `genesis_time` and `slot_interval` arguments are _optional_ and the - /// [OnlineBlobProvider] will attempt to load them dynamically at runtime if they are not - /// provided. - pub const fn new( - beacon_client: B, - genesis_time: Option, - slot_interval: Option, - ) -> Self { - Self { beacon_client, genesis_time, slot_interval } - } - - /// Loads the beacon genesis and config spec - pub async fn load_configs(&mut self) -> Result<(), BlobProviderError> { - if self.genesis_time.is_none() { - self.genesis_time = Some( - self.beacon_client - .beacon_genesis() - .await - .map_err(|e| BlobProviderError::Backend(e.to_string()))? - .data - .genesis_time, - ); - } - if self.slot_interval.is_none() { - self.slot_interval = Some( - self.beacon_client - .config_spec() - .await - .map_err(|e| BlobProviderError::Backend(e.to_string()))? - .data - .seconds_per_slot, - ); - } - Ok(()) - } - - /// Fetches blob sidecars for the given slot and blob hashes. - pub async fn fetch_sidecars( - &self, - slot: u64, - hashes: &[IndexedBlobHash], - ) -> Result, BlobProviderError> { - self.beacon_client - .beacon_blob_side_cars(slot, hashes) - .await - .map_err(|e| BlobProviderError::Backend(e.to_string())) - } - - /// Computes the slot for the given timestamp. - pub const fn slot( - genesis: u64, - slot_time: u64, - timestamp: u64, - ) -> Result { - if timestamp < genesis { - return Err(BlobProviderError::SlotDerivation); - } - Ok((timestamp - genesis) / slot_time) - } - - /// Fetches blob sidecars for the given block reference and blob hashes. - pub async fn fetch_filtered_sidecars( - &self, - block_ref: &BlockInfo, - blob_hashes: &[IndexedBlobHash], - ) -> Result, BlobProviderError> { - if blob_hashes.is_empty() { - return Ok(Vec::new()); - } - - // Extract the genesis timestamp and slot interval from the loaded configs. - let genesis = self.genesis_time.expect("Genesis Config Loaded"); - let interval = self.slot_interval.expect("Config Spec Loaded"); - - // Calculate the slot for the given timestamp. - let slot = Self::slot(genesis, interval, block_ref.timestamp)?; - - // Fetch blob sidecars for the slot using the given blob hashes. - let sidecars = self.fetch_sidecars(slot, blob_hashes).await?; - - // Filter blob sidecars that match the indicies in the specified list. - let blob_hash_indicies = blob_hashes.iter().map(|b| b.index).collect::>(); - let filtered = sidecars - .into_iter() - .filter(|s| blob_hash_indicies.contains(&s.index)) - .collect::>(); - - // Validate the correct number of blob sidecars were retrieved. - if blob_hashes.len() != filtered.len() { - return Err(BlobProviderError::SidecarLengthMismatch(blob_hashes.len(), filtered.len())); - } - - Ok(filtered - .into_iter() - .map(|s| BlobTransactionSidecarItem { - index: s.index, - blob: s.blob, - kzg_commitment: s.kzg_commitment, - kzg_proof: s.kzg_proof, - }) - .collect::>()) - } -} - -#[async_trait] -impl BlobProvider for OnlineBlobProvider -where - B: BeaconClient + Send + Sync, -{ - type Error = BlobProviderError; - - /// Fetches blob sidecars that were confirmed in the specified L1 block with the given indexed - /// hashes. The blobs are validated for their index and hashes using the specified - /// [IndexedBlobHash]. - async fn get_blobs( - &mut self, - block_ref: &BlockInfo, - blob_hashes: &[IndexedBlobHash], - ) -> Result>, Self::Error> { - // Fetches the genesis timestamp and slot interval from the - // [BeaconGenesis] and [ConfigSpec] if not previously loaded. - self.load_configs().await?; - - // Fetch the blob sidecars for the given block reference and blob hashes. - let sidecars = self.fetch_filtered_sidecars(block_ref, blob_hashes).await?; - - // Validate the blob sidecars straight away with the num hashes. - let blobs = sidecars - .into_iter() - .enumerate() - .map(|(i, sidecar)| { - let hash = blob_hashes - .get(i) - .ok_or(BlobProviderError::Backend("Missing blob hash".to_string()))?; - match sidecar.verify_blob(&IndexedBlobHash { hash: hash.hash, index: hash.index }) { - Ok(_) => Ok(sidecar.blob), - Err(e) => Err(BlobProviderError::Backend(e.to_string())), - } - }) - .collect::>, BlobProviderError>>() - .map_err(|e| BlobProviderError::Backend(e.to_string()))?; - Ok(blobs) - } -} - -/// The minimal interface required to fetch sidecars from a remote blob store. -#[async_trait] -pub trait BlobSidecarProvider { - /// Fetches blob sidecars that were confirmed in the specified L1 block with the given indexed - /// hashes. Order of the returned sidecars is guaranteed to be that of the hashes. Blob data is - /// not checked for validity. - /// - /// Consensus specs: - async fn beacon_blob_side_cars( - &self, - slot: u64, - hashes: &[IndexedBlobHash], - ) -> Result, BlobProviderError>; -} - -/// Blanket implementation of the [BlobSidecarProvider] trait for all types that -/// implemend [BeaconClient], which has a superset of the required functionality. -#[async_trait] -impl BlobSidecarProvider for B { - async fn beacon_blob_side_cars( - &self, - slot: u64, - hashes: &[IndexedBlobHash], - ) -> Result, BlobProviderError> { - self.beacon_blob_side_cars(slot, hashes) - .await - .map_err(|e| BlobProviderError::Backend(e.to_string())) - } -} - -/// An online blob provider that optionally falls back to a secondary provider if the -/// primary fails to fetch blob sidecars. -/// -/// This is useful for scenarios where blobs have been evicted from the primary provider's -/// blob store and need to be fetched from a remote archive API. The default eviction -/// policy on Ethereum is to keep blobs for 18 days. -/// -/// Blob storage APIs are expected to implement the [BlobSidecarProvider] trait. -/// One example can be found at -#[derive(Debug, Clone)] -pub struct OnlineBlobProviderWithFallback { - primary: OnlineBlobProvider, - fallback: Option, -} - -impl OnlineBlobProviderWithFallback { - /// Creates a new instance of the [OnlineBlobProviderWithFallback] with the - /// specified primary and fallback providers. - pub const fn new(primary: OnlineBlobProvider, fallback: Option) -> Self { - Self { primary, fallback } - } - - /// Attempts to fetch blob sidecars from the fallback provider, if configured. - /// Calling this method without a fallback provider will return an error. - async fn fallback_fetch_filtered_sidecars( - &self, - block_ref: &BlockInfo, - blob_hashes: &[IndexedBlobHash], - ) -> Result, BlobProviderError> { - let Some(fallback) = self.fallback.as_ref() else { - return Err(BlobProviderError::Backend( - "cannot fetch blobs: the primary blob provider failed, and no fallback is configured".to_string() - )); - }; - - if blob_hashes.is_empty() { - return Ok(Vec::new()); - } - - // Extract the genesis timestamp and slot interval from the primary provider. - let slot = OnlineBlobProvider::::slot( - self.primary.genesis_time.expect("Genesis Config Loaded"), - self.primary.slot_interval.expect("Config Spec Loaded"), - block_ref.timestamp, - )?; - - // Fetch blob sidecars for the given block reference and blob hashes. - let sidecars = fallback.beacon_blob_side_cars(slot, blob_hashes).await?; - - // Filter blob sidecars that match the indicies in the specified list. - let blob_hash_indicies = blob_hashes.iter().map(|b| b.index).collect::>(); - let filtered = sidecars - .into_iter() - .filter(|s| blob_hash_indicies.contains(&s.index)) - .collect::>(); - - // Validate the correct number of blob sidecars were retrieved. - if blob_hashes.len() != filtered.len() { - return Err(BlobProviderError::SidecarLengthMismatch(blob_hashes.len(), filtered.len())); - } - - Ok(filtered - .into_iter() - .map(|s| BlobTransactionSidecarItem { - index: s.index, - blob: s.blob, - kzg_commitment: s.kzg_commitment, - kzg_proof: s.kzg_proof, - }) - .collect::>()) - } -} - -#[async_trait] -impl BlobProvider for OnlineBlobProviderWithFallback -where - B: BeaconClient + Send + Sync, - F: BlobSidecarProvider + Send + Sync, -{ - type Error = BlobProviderError; - - /// Fetches blob sidecars that were confirmed in the specified L1 block with the given indexed - /// hashes. The blobs are validated for their index and hashes using the specified - /// [IndexedBlobHash]. - async fn get_blobs( - &mut self, - block_ref: &BlockInfo, - blob_hashes: &[IndexedBlobHash], - ) -> Result>, BlobProviderError> { - match self.primary.get_blobs(block_ref, blob_hashes).await { - Ok(blobs) => Ok(blobs), - Err(primary_err) => { - warn!(target: "blob_provider", "Primary provider failed: {:?}", primary_err); - - // Fetch the blob sidecars for the given block reference and blob hashes. - let sidecars = - match self.fallback_fetch_filtered_sidecars(block_ref, blob_hashes).await { - Ok(sidecars) => sidecars, - Err(e) => { - warn!(target: "blob_provider", "Fallback provider failed: {:?}", e); - return Err(e); - } - }; - - // Validate the blob sidecars straight away with the num hashes. - let blobs = sidecars - .into_iter() - .enumerate() - .map(|(i, sidecar)| { - let hash = blob_hashes.get(i).ok_or(BlobProviderError::Backend( - "fallback: failed to get blob hash".to_string(), - ))?; - match sidecar - .verify_blob(&IndexedBlobHash { hash: hash.hash, index: hash.index }) - { - Ok(_) => Ok(sidecar.blob), - Err(e) => Err(BlobProviderError::Backend(e.to_string())), - } - }) - .collect::>, BlobProviderError>>()?; - Ok(blobs) - } - } - } -} - -/// A builder for a [OnlineBlobProviderWithFallback] instance. -/// -/// This builder allows for the construction of a blob provider that -/// uses a primary beacon node and can fallback to a secondary [BlobSidecarProvider] -/// if the primary fails to fetch blob sidecars. -/// -/// The fallback provider is optional and can be set using the [Self::with_fallback] method. -/// -/// Two convenience methods are available for initializing the providers from beacon client URLs: -/// - [Self::with_primary] for the primary beacon client. -/// - [Self::with_fallback] for the fallback beacon client. -#[derive(Debug, Clone)] -pub struct OnlineBlobProviderBuilder { - beacon_client: Option, - fallback: Option, - genesis_time: Option, - slot_interval: Option, -} - -impl Default for OnlineBlobProviderBuilder { - fn default() -> Self { - Self { beacon_client: None, fallback: None, genesis_time: None, slot_interval: None } - } -} - -impl OnlineBlobProviderBuilder { - /// Creates a new [OnlineBlobProviderBuilder]. - pub fn new() -> Self { - Self::default() - } - - /// Adds a primary beacon client to the builder. This is required. - pub fn with_beacon_client(mut self, beacon_client: B) -> Self { - self.beacon_client = Some(beacon_client); - self - } - - /// Adds a genesis time to the builder. This is optional. - pub const fn with_genesis_time(mut self, genesis_time: u64) -> Self { - self.genesis_time = Some(genesis_time); - self - } - - /// Adds a slot interval to the builder. This is optional. - pub const fn with_slot_interval(mut self, slot_interval: u64) -> Self { - self.slot_interval = Some(slot_interval); - self - } - - /// Adds a fallback blob provider to the builder. This is optional. - pub fn with_fallback_provider(mut self, fallback: F) -> Self { - self.fallback = Some(fallback); - self - } - - /// Builds the [OnlineBlobProviderWithFallback] instance. - pub fn build(self) -> OnlineBlobProviderWithFallback { - self.into() - } -} - -impl OnlineBlobProviderBuilder { - /// Adds a primary [OnlineBeaconClient] to the builder using the specified HTTP URL. - pub fn with_primary(mut self, url: String) -> Self { - self.beacon_client = Some(OnlineBeaconClient::new_http(url)); - self - } -} - -impl OnlineBlobProviderBuilder { - /// Adds a fallback [OnlineBeaconClient] to the builder using the specified HTTP URL. - pub fn with_fallback(mut self, maybe_url: Option) -> Self { - self.fallback = maybe_url.map(OnlineBeaconClient::new_http); - self - } -} - -impl From> - for OnlineBlobProviderWithFallback -{ - fn from(builder: OnlineBlobProviderBuilder) -> Self { - Self::new( - OnlineBlobProvider::new( - builder.beacon_client.expect("Primary beacon client must be set"), - builder.genesis_time, - builder.slot_interval, - ), - builder.fallback, - ) - } -} diff --git a/bin/host/src/providers/mod.rs b/bin/host/src/providers/mod.rs deleted file mode 100644 index 3030533cd..000000000 --- a/bin/host/src/providers/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Contains provider implementations for kona's host. - -pub mod blob; -pub use blob::OnlineBlobProvider; - -pub mod beacon; -pub use beacon::{BeaconClient, OnlineBeaconClient};