diff --git a/Cargo.lock b/Cargo.lock index c359a53..836c48d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,6 +27,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "aead" version = "0.5.2" @@ -461,18 +467,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -570,7 +576,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.7.4", "object", "rustc-demangle", ] @@ -625,7 +631,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -731,10 +737,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" dependencies = [ "once_cell", - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "syn_derive", ] @@ -818,9 +824,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd4c6dcc3b0aea2f5c0b4b82c2b15fe39ddbc76041a310848f4706edf76bb31" +checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2" dependencies = [ "bytemuck_derive", ] @@ -833,7 +839,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -881,9 +887,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.13" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72db2f7947ecee9b03b510377e8bb9077afa27176fdbff55c51027e976fdcc48" +checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" dependencies = [ "jobserver", "libc", @@ -1030,7 +1036,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1111,9 +1117,9 @@ dependencies = [ [[package]] name = "constant_time_eq" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" [[package]] name = "convert_case" @@ -1272,7 +1278,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1283,7 +1289,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1356,7 +1362,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1435,7 +1441,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1458,7 +1464,7 @@ checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1546,7 +1552,7 @@ checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1630,9 +1636,9 @@ dependencies = [ "anyhow", "chrono", "env_logger 0.11.5", + "igloo-interface", "log", "rand 0.8.5", - "rollups-interface", "solana-entry", "solana-ledger", "solana-sdk", @@ -1652,9 +1658,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "feature-probe" @@ -1664,9 +1670,9 @@ checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" [[package]] name = "filetime" -version = "0.2.24" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf401df4a4e3872c4fe8151134cf483738e74b67fc934d6532c882b3d24a4550" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if 1.0.0", "libc", @@ -1682,12 +1688,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1804,7 +1810,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -1952,7 +1958,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.4.0", + "indexmap 2.5.0", "slab", "tokio", "tokio-util 0.7.11", @@ -2275,6 +2281,95 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9007da9cacbd3e6343da136e98b0d2df013f553d35bdec8b518f07bea768e19c" +[[package]] +name = "igloo-executor" +version = "0.1.0" +dependencies = [ + "anyhow", + "crossbeam-channel", + "igloo-interface", + "igloo-storage", + "igloo-validator", + "log", + "solana-accounts-db", + "solana-core", + "solana-ledger", + "solana-runtime", + "solana-sdk", + "solana-svm", + "tempfile", + "thiserror", + "tokio", +] + +[[package]] +name = "igloo-interface" +version = "0.1.0" +dependencies = [ + "bincode", + "thiserror", + "tokio", +] + +[[package]] +name = "igloo-storage" +version = "0.1.0" +dependencies = [ + "anyhow", + "assert_matches", + "bincode", + "crossbeam-channel", + "igloo-interface", + "log", + "rand 0.8.5", + "solana-account-decoder", + "solana-accounts-db", + "solana-bpf-loader-program", + "solana-compute-budget", + "solana-core", + "solana-entry", + "solana-gossip", + "solana-ledger", + "solana-measure", + "solana-metrics", + "solana-program-runtime", + "solana-rpc", + "solana-runtime", + "solana-sdk", + "solana-stake-program", + "solana-streamer", + "solana-svm", + "solana-system-program", + "solana-transaction-status", + "spl-token", + "spl-token-2022", + "svm-executor", + "tempfile", + "thiserror", + "tokio", +] + +[[package]] +name = "igloo-validator" +version = "0.1.0" +dependencies = [ + "anyhow", + "crossbeam-channel", + "igloo-interface", + "igloo-storage", + "log", + "solana-accounts-db", + "solana-core", + "solana-entry", + "solana-ledger", + "solana-runtime", + "solana-sdk", + "solana-svm", + "tempfile", + "thiserror", + "tokio", +] + [[package]] name = "im" version = "15.1.0" @@ -2328,9 +2423,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -2683,9 +2778,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.19" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc53a7799a7496ebc9fd29f31f7df80e83c9bda5299768af5f9e59eeea74647" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "pkg-config", @@ -2840,6 +2935,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "1.0.2" @@ -3022,7 +3126,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3091,10 +3195,10 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3105,9 +3209,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -3156,7 +3260,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3167,9 +3271,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.3.1+3.3.1" +version = "300.3.2+3.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7259953d42a81bf137fbbd73bd30a8e1914d6dce43c2b90ed575783a22608b91" +checksum = "a211a18d945ef7e648cc6e0058f4c548ee46aab922ea203e0d30e966ea23647b" dependencies = [ "cc", ] @@ -3326,7 +3430,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3347,7 +3451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.4.0", + "indexmap 2.5.0", ] [[package]] @@ -3367,7 +3471,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3484,9 +3588,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ "toml_edit", ] @@ -3604,7 +3708,7 @@ checksum = "9e2e25ee72f5b24d773cae88422baddefff7714f97aab68d96fe2b6fc4a28fb2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -3657,9 +3761,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -3784,9 +3888,9 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.15", "libredox", @@ -3948,53 +4052,6 @@ dependencies = [ "chrono", ] -[[package]] -name = "rollups-interface" -version = "0.1.0" -dependencies = [ - "bincode", - "thiserror", - "tokio", -] - -[[package]] -name = "rollups-storage" -version = "0.1.0" -dependencies = [ - "anyhow", - "assert_matches", - "bincode", - "crossbeam-channel", - "log", - "rand 0.8.5", - "rollups-interface", - "solana-account-decoder", - "solana-accounts-db", - "solana-bpf-loader-program", - "solana-compute-budget", - "solana-core", - "solana-entry", - "solana-gossip", - "solana-ledger", - "solana-measure", - "solana-metrics", - "solana-program-runtime", - "solana-rpc", - "solana-runtime", - "solana-sdk", - "solana-stake-program", - "solana-streamer", - "solana-svm", - "solana-system-program", - "solana-transaction-status", - "spl-token", - "spl-token-2022", - "svm-executor", - "tempfile", - "thiserror", - "tokio", -] - [[package]] name = "rpassword" version = "7.3.1" @@ -4030,9 +4087,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -4048,9 +4105,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "a85d50532239da68e9addb745ba38ff4612a242c1c7ceea689c4bc7c2f43c36f" dependencies = [ "bitflags 2.6.0", "errno", @@ -4155,7 +4212,7 @@ checksum = "1db149f81d46d2deba7cd3c50772474707729550221e69588478ebf9ada425ae" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -4208,9 +4265,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] @@ -4226,20 +4283,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.125" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c8e735a073ccf5be70aa8066aa984eaf2fa000db6c8d0100ae605b366d31ed" +checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" dependencies = [ "itoa", "memchr", @@ -4278,7 +4335,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -4287,7 +4344,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.5.0", "itoa", "ryu", "serde", @@ -4509,7 +4566,7 @@ dependencies = [ "crossbeam-channel", "dashmap", "index_list", - "indexmap 2.4.0", + "indexmap 2.5.0", "itertools 0.12.1", "lazy_static", "log", @@ -4659,7 +4716,7 @@ dependencies = [ "dashmap", "futures 0.3.30", "futures-util", - "indexmap 2.4.0", + "indexmap 2.5.0", "indicatif", "log", "quinn", @@ -4725,7 +4782,7 @@ dependencies = [ "bincode", "crossbeam-channel", "futures-util", - "indexmap 2.4.0", + "indexmap 2.5.0", "log", "rand 0.8.5", "rayon", @@ -4935,7 +4992,7 @@ dependencies = [ "clap 2.34.0", "crossbeam-channel", "flate2", - "indexmap 2.4.0", + "indexmap 2.5.0", "itertools 0.12.1", "log", "lru", @@ -5615,7 +5672,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -5720,7 +5777,7 @@ dependencies = [ "dashmap", "futures-util", "histogram", - "indexmap 2.4.0", + "indexmap 2.5.0", "itertools 0.12.1", "libc", "log", @@ -5807,7 +5864,7 @@ dependencies = [ "async-trait", "bincode", "futures-util", - "indexmap 2.4.0", + "indexmap 2.5.0", "indicatif", "log", "rayon", @@ -6187,7 +6244,7 @@ checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" dependencies = [ "quote", "spl-discriminator-syn", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -6199,7 +6256,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.8", - "syn 2.0.75", + "syn 2.0.77", "thiserror", ] @@ -6248,7 +6305,7 @@ dependencies = [ "proc-macro2", "quote", "sha2 0.10.8", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -6431,8 +6488,8 @@ dependencies = [ "clap 4.5.16", "env_logger 0.11.5", "hex", + "igloo-interface", "log", - "rollups-interface", "solana-sdk", "solana-svm", "svm-executor", @@ -6443,7 +6500,8 @@ name = "svm-executor" version = "0.1.0" dependencies = [ "bincode", - "rollups-interface", + "igloo-interface", + "igloo-storage", "solana-accounts-db", "solana-bpf-loader-program", "solana-compute-budget", @@ -6475,9 +6533,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.75" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6af063034fc1935ede7be0122941bafa9bacb949334d090b77ca98b5817c7d9" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -6493,7 +6551,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -6638,7 +6696,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -6708,9 +6766,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.39.3" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -6742,7 +6800,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -6836,11 +6894,11 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.4.0", + "indexmap 2.5.0", "toml_datetime", "winnow", ] @@ -6941,7 +6999,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -7036,9 +7094,9 @@ checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a" [[package]] name = "universal-hash" @@ -7204,7 +7262,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-shared", ] @@ -7238,7 +7296,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7488,9 +7546,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.40" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -7552,7 +7610,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] @@ -7572,7 +7630,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.75", + "syn 2.0.77", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 84ab1dd..778cc76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,15 @@ debug = true split-debuginfo = "packed" [workspace] -members = ["example", "interface", "storage", "svm/cli", "svm/executor"] +members = [ + "example", + "executor", + "interface", + "storage", + "svm/cli", + "svm/executor", + "validator", +] resolver = "2" [workspace.package] @@ -54,7 +62,9 @@ solana-metrics = { version = "2.0.7" } spl-token = "=6.0.0" spl-token-2022 = "=4.0.0" -rollups-interface = { path = "interface" } +igloo-interface = { path = "interface" } +igloo-storage = { path = "storage" } +igloo-validator = { path = "validator" } svm-executor = { path = "svm/executor" } [patch.crates-io] @@ -64,3 +74,31 @@ solana-curve25519 = { git = "https://github.com/anza-xyz/agave.git", rev = "11b8 solana-program = { git = "https://github.com/anza-xyz/agave.git", rev = "11b87c1ba32c1895898f2a17502417fccdf1a4c8" } solana-zk-sdk = { git = "https://github.com/anza-xyz/agave.git", rev = "11b87c1ba32c1895898f2a17502417fccdf1a4c8" } solana-zk-token-sdk = { git = "https://github.com/anza-xyz/agave.git", rev = "11b87c1ba32c1895898f2a17502417fccdf1a4c8" } + +## patches to use local versions, uncomment if needed +# solana-program = { path = "../agave/sdk/program" } +# solana-zk-sdk = { path = "../agave/zk-sdk" } +# solana-zk-token-sdk = { path = "../agave/zk-token-sdk" } + +## patches to use local versions, uncomment if needed +# solana-bpf-loader-program = { path = "../agave/programs/bpf_loader" } +# solana-compute-budget = { path = "../agave/compute-budget" } +# solana-program-runtime = { path = "../agave/program-runtime" } +# solana-sdk = { path = "../agave/sdk" } +# solana-svm = { path = "../agave/svm" } +# solana-system-program = { path = "../agave/programs/system" } +# solana-logger = { path = "../agave/logger" } +# solana-test-validator = { path = "../agave/test-validator" } +# solana-ledger = { path = "../agave/ledger" } +# solana-runtime = { path = "../agave/runtime" } +# solana-entry = { path = "../agave/entry" } +# solana-accounts-db = { path = "../agave/accounts-db" } +# solana-core = { path = "../agave/core" } +# solana-stake-program = { path = "../agave/programs/stake" } +# solana-measure = { path = "../agave/measure" } +# solana-gossip = { path = "../agave/gossip" } +# solana-streamer = { path = "../agave/streamer" } +# solana-rpc = { path = "../agave/rpc" } +# solana-transaction-status = { path = "../agave/transaction-status" } +# solana-account-decoder = { path = "../agave/account-decoder" } +# solana-metrics = { path = "../agave/metrics" } diff --git a/example/Cargo.toml b/example/Cargo.toml index 706a6d3..10f4895 100644 --- a/example/Cargo.toml +++ b/example/Cargo.toml @@ -8,7 +8,7 @@ license.workspace = true edition.workspace = true [dependencies] -rollups-interface = { workspace = true } +igloo-interface = { workspace = true } svm-executor = { workspace = true } solana-sdk = { workspace = true } diff --git a/example/src/derive/da.rs b/example/src/derive/da.rs index 7522253..475dbf8 100644 --- a/example/src/derive/da.rs +++ b/example/src/derive/da.rs @@ -1,5 +1,5 @@ use crate::l1::attribute::PayloadAttributeImpl; -use rollups_interface::derive::DaDerive; +use igloo_interface::derive::DaDerive; use std::sync::Arc; use tokio::sync::{mpsc::Receiver, RwLock}; diff --git a/example/src/derive/instant.rs b/example/src/derive/instant.rs index 3413282..11eadb2 100644 --- a/example/src/derive/instant.rs +++ b/example/src/derive/instant.rs @@ -1,4 +1,4 @@ -use rollups_interface::derive::InstantDerive; +use igloo_interface::derive::InstantDerive; use tokio::sync::mpsc::{error::TryRecvError, Receiver}; use crate::l1::{attribute::PayloadAttributeImpl, block::L1BlockInfoImpl}; diff --git a/example/src/l1/attribute.rs b/example/src/l1/attribute.rs index 713a53b..0d2051b 100644 --- a/example/src/l1/attribute.rs +++ b/example/src/l1/attribute.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use super::{head::L1HeadImpl, L1Hash, L1Height, L1Timestamp}; use crate::l2::tx::L2Transaction; -use rollups_interface::l1::{Epoch, PayloadAttribute}; +use igloo_interface::l1::{Epoch, PayloadAttribute}; #[derive(Clone)] pub struct EpochInfo { diff --git a/example/src/l1/batch.rs b/example/src/l1/batch.rs index abf2a6b..1da531a 100644 --- a/example/src/l1/batch.rs +++ b/example/src/l1/batch.rs @@ -1,4 +1,4 @@ -use rollups_interface::l1::BatchInfo; +use igloo_interface::l1::BatchInfo; use super::L1Hash; diff --git a/example/src/l1/block.rs b/example/src/l1/block.rs index 2ca1112..13aaaa1 100644 --- a/example/src/l1/block.rs +++ b/example/src/l1/block.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use rollups_interface::l1::L1BlockInfo; +use igloo_interface::l1::L1BlockInfo; use crate::l2::tx::L2Transaction; diff --git a/example/src/l1/head.rs b/example/src/l1/head.rs index fc2b88c..5aac919 100644 --- a/example/src/l1/head.rs +++ b/example/src/l1/head.rs @@ -1,4 +1,4 @@ -use rollups_interface::l1::L1Head; +use igloo_interface::l1::L1Head; use super::{L1Hash, L1Height, L1Timestamp}; diff --git a/example/src/l1/tx.rs b/example/src/l1/tx.rs index d6af0f0..7575fa8 100644 --- a/example/src/l1/tx.rs +++ b/example/src/l1/tx.rs @@ -1,4 +1,4 @@ -use rollups_interface::l1::DepositTransaction; +use igloo_interface::l1::DepositTransaction; use solana_sdk::pubkey::Pubkey; pub struct DepositTx { diff --git a/example/src/l2/block.rs b/example/src/l2/block.rs index dbf192c..1202141 100644 --- a/example/src/l2/block.rs +++ b/example/src/l2/block.rs @@ -1,4 +1,4 @@ -use rollups_interface::l2::{Block, BlockPayload, Entry}; +use igloo_interface::l2::{Block, BlockPayload, Entry}; use solana_sdk::transaction::VersionedTransaction; use super::head::L2HeadImpl; diff --git a/example/src/l2/engine.rs b/example/src/l2/engine.rs index 0e28a00..3a9fa30 100644 --- a/example/src/l2/engine.rs +++ b/example/src/l2/engine.rs @@ -3,9 +3,7 @@ use solana_sdk::signature::Keypair; use std::{path::Path, sync::Arc}; use tokio::sync::{mpsc::Sender, RwLock}; -use rollups_interface::l2::{ - stream::TransactionStream, Block, Engine, EngineApi, L2Head, Producer, -}; +use igloo_interface::l2::{stream::TransactionStream, Block, Engine, EngineApi, L2Head, Producer}; use crate::l1::attribute::PayloadAttributeImpl; diff --git a/example/src/l2/head.rs b/example/src/l2/head.rs index a54cd60..a3967ee 100644 --- a/example/src/l2/head.rs +++ b/example/src/l2/head.rs @@ -1,4 +1,4 @@ -use rollups_interface::l2::L2Head; +use igloo_interface::l2::L2Head; use super::{L2Hash, L2Height, L2Timestamp}; diff --git a/example/src/l2/ledger.rs b/example/src/l2/ledger.rs index 1e7cf4e..a6fb46a 100644 --- a/example/src/l2/ledger.rs +++ b/example/src/l2/ledger.rs @@ -3,7 +3,7 @@ use std::{ sync::Arc, }; -use rollups_interface::l2::{Block, L2Head}; +use igloo_interface::l2::{Block, L2Head}; use tokio::sync::RwLock; use super::{block::BlockImpl, head::L2HeadImpl, L2Hash, L2Height}; diff --git a/example/src/l2/producer.rs b/example/src/l2/producer.rs index d179093..0745127 100644 --- a/example/src/l2/producer.rs +++ b/example/src/l2/producer.rs @@ -1,5 +1,5 @@ use anyhow::{Ok, Result}; -use rollups_interface::{ +use igloo_interface::{ l1::PayloadAttribute, l2::{executor::Init, Entry, Producer}, }; diff --git a/example/src/l2/stream.rs b/example/src/l2/stream.rs index d2d007a..bfe71e1 100644 --- a/example/src/l2/stream.rs +++ b/example/src/l2/stream.rs @@ -1,4 +1,4 @@ -use rollups_interface::l2::stream::{BatchSettings, TransactionStream}; +use igloo_interface::l2::stream::{BatchSettings, TransactionStream}; use std::sync::Arc; use tokio::sync::RwLock; diff --git a/example/src/l2/tx.rs b/example/src/l2/tx.rs index f569ff6..2c55ac1 100644 --- a/example/src/l2/tx.rs +++ b/example/src/l2/tx.rs @@ -1,4 +1,4 @@ -use rollups_interface::l2::Transaction; +use igloo_interface::l2::Transaction; use solana_sdk::pubkey::Pubkey; use crate::l1::tx::DepositTx; diff --git a/example/src/main.rs b/example/src/main.rs index 8dbde5a..5eb4979 100644 --- a/example/src/main.rs +++ b/example/src/main.rs @@ -1,8 +1,8 @@ use anyhow::Result; use derive::{da::DaDeriveImpl, instant::InstantDeriveImpl}; +use igloo_interface::{l2::Engine, runner::Runner}; use l2::batcher::Batcher; use mock::{chain::MockLayer1, stream::TxServer}; -use rollups_interface::{l2::Engine, runner::Runner}; use runner::SimpleRunner; use std::path::Path; use tokio::sync::mpsc::channel; @@ -27,7 +27,7 @@ async fn main() -> Result<()> { let da_driver = DaDeriveImpl::default(); let (attribute_sender, attribute_receiver) = channel(1024); - let mut runner = SimpleRunner::new(Path::new("/tmp/rollups-example"), attribute_sender)?; + let mut runner = SimpleRunner::new(Path::new("/tmp/igloo-example"), attribute_sender)?; runner.register_instant(instanct_driver); runner.register_da(da_driver.clone()); diff --git a/example/src/mock/stream.rs b/example/src/mock/stream.rs index b8ed8c9..b129af6 100644 --- a/example/src/mock/stream.rs +++ b/example/src/mock/stream.rs @@ -1,5 +1,5 @@ use crate::l2::{stream::SharedStream, tx::L2Transaction}; -use rollups_interface::l2::stream::TransactionStream; +use igloo_interface::l2::stream::TransactionStream; use solana_sdk::{signature::Keypair, signer::Signer}; pub struct TxServer { diff --git a/example/src/runner.rs b/example/src/runner.rs index e8e2919..a1f39d6 100644 --- a/example/src/runner.rs +++ b/example/src/runner.rs @@ -1,7 +1,7 @@ use std::path::Path; use anyhow::Result; -use rollups_interface::{ +use igloo_interface::{ derive::{DaDerive, InstantDerive}, l1::{Epoch, L1BlockInfo, L1Head}, l2::{EngineApi, L2Head}, diff --git a/executor/Cargo.toml b/executor/Cargo.toml new file mode 100644 index 0000000..224c71d --- /dev/null +++ b/executor/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "igloo-executor" +version.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true +license.workspace = true +edition.workspace = true + +[dependencies] +igloo-interface = { workspace = true } +igloo-storage = { workspace = true } +igloo-validator = { workspace = true } +tempfile = { workspace = true } + +thiserror = { workspace = true } +tokio = { workspace = true } +log = { workspace = true } +crossbeam-channel = { workspace = true } + +solana-ledger = { workspace = true } +solana-accounts-db = { workspace = true } +solana-sdk = { workspace = true } +solana-svm = { workspace = true } +solana-runtime = { workspace = true } +solana-core = { workspace = true } + +[dev-dependencies] +anyhow = { workspace = true } diff --git a/executor/src/defs.rs b/executor/src/defs.rs new file mode 100644 index 0000000..80a5a71 --- /dev/null +++ b/executor/src/defs.rs @@ -0,0 +1,5 @@ +use solana_sdk::transaction::SanitizedTransaction; + +pub struct BlockPayload { + pub transactions: Vec, +} diff --git a/executor/src/engine/mod.rs b/executor/src/engine/mod.rs new file mode 100644 index 0000000..550fde4 --- /dev/null +++ b/executor/src/engine/mod.rs @@ -0,0 +1,113 @@ +use crate::{ + defs::BlockPayload, + processor::{bank::BankProcessor, Processor}, + Result, +}; +use igloo_interface::l2::{bank::BankOperations, storage::StorageOperations}; +use igloo_storage::{ + blockstore::txs::CommitBatch, config::GlobalConfig, ledger::SlotInfo, RollupStorage, +}; +use igloo_validator::{ + settings::{Settings, Switchs}, + BankValidator, TransactionChecks, +}; +use solana_sdk::clock::Slot; +use std::{borrow::Cow, path::Path}; + +pub mod storage; + +pub struct Engine { + storage: RollupStorage, + finalized: Slot, + validator_settings: Settings, +} + +impl Engine { + pub fn new(ledger_path: &Path) -> Result { + let mut config = GlobalConfig::new(ledger_path)?; + config.keypairs.set_default_path(ledger_path); + Self::new_with_config(config) + } + + pub fn new_for_test(ledger_path: &Path) -> Result { + let config = GlobalConfig::new_temp(&ledger_path)?; + Self::new_with_config(config) + } + + pub fn new_with_config(config: GlobalConfig) -> Result { + let settings = Settings { + max_age: 150, // set default max_age from solana + switchs: Switchs { + tx_sanity_check: true, + txs_conflict_check: true, + }, + }; + Self::new_with_validator_settings(config, settings) + } + + pub fn new_with_validator_settings( + config: GlobalConfig, + validator_settings: Settings, + ) -> Result { + let mut storage = RollupStorage::new(config)?; + storage.init()?; + + let finalized = storage.get_root(); + Ok(Self { + storage, + finalized, + validator_settings, + }) + } + + pub async fn close(self) -> Result<()> { + self.storage.close().await?; + Ok(()) + } + + /// Check the block before processing + pub fn check_block(&self, block: &BlockPayload, settins: Option) -> Result<()> { + let switchs = settins.unwrap_or(self.validator_settings.switchs.clone()); + let validator = BankValidator::new(self.storage.current_bank(), Default::default()); + if switchs.tx_sanity_check { + validator.transactions_sanity_check(&block.transactions)?; + } + if switchs.txs_conflict_check { + validator.transactions_conflict_check(&block.transactions)?; + } + Ok(()) + } + + pub async fn new_block(&mut self, block: BlockPayload) -> Result { + self.storage.bump()?; + + let processor = + BankProcessor::new(self.storage.current_bank(), self.validator_settings.clone()); + let results = processor.process(Cow::Borrowed(&block.transactions))?; + self.storage + .commit( + results.into(), + CommitBatch::new(Cow::Borrowed(&block.transactions)), + ) + .await?; + + let info = self.storage.get_slot_info(self.storage.current_height())?; + info!("New block: {:?}", info); + Ok(info) + } + + pub fn confirm(&mut self, block: Slot) -> Result<()> { + self.storage.confirm(block)?; + Ok(()) + } + + pub fn reorg(&mut self, reset_to: Slot) -> Result<()> { + self.storage.reorg(reset_to, Some(self.finalized))?; + Ok(()) + } + + pub fn finalize(&mut self, block: Slot) -> Result<()> { + self.storage.set_root(block, None)?; + Ok(()) + } +} diff --git a/executor/src/engine/storage.rs b/executor/src/engine/storage.rs new file mode 100644 index 0000000..54a974c --- /dev/null +++ b/executor/src/engine/storage.rs @@ -0,0 +1,9 @@ +use igloo_storage::RollupStorage; + +use super::Engine; + +impl Engine { + pub fn store(&self) -> &RollupStorage { + &self.storage + } +} diff --git a/executor/src/error.rs b/executor/src/error.rs new file mode 100644 index 0000000..db24837 --- /dev/null +++ b/executor/src/error.rs @@ -0,0 +1,12 @@ +use thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Debug, Error)] +pub enum Error { + #[error(transparent)] + StorageError(#[from] igloo_storage::Error), + + #[error(transparent)] + ValidatorError(#[from] igloo_validator::Error), +} diff --git a/executor/src/lib.rs b/executor/src/lib.rs new file mode 100644 index 0000000..7d0a24f --- /dev/null +++ b/executor/src/lib.rs @@ -0,0 +1,14 @@ +pub mod defs; +pub mod engine; +pub mod error; +pub mod processor; +#[cfg(test)] +mod tests; + +pub use { + engine::Engine, + error::{Error, Result}, +}; + +#[macro_use] +extern crate log; diff --git a/executor/src/processor/bank.rs b/executor/src/processor/bank.rs new file mode 100644 index 0000000..df39323 --- /dev/null +++ b/executor/src/processor/bank.rs @@ -0,0 +1,69 @@ +use super::Processor; +use crate::Result; +use igloo_validator::{settings::Settings, BankValidator, SvmValidator}; +use solana_runtime::bank::Bank; +use solana_sdk::transaction::SanitizedTransaction; +use solana_svm::transaction_processor::{ + LoadAndExecuteSanitizedTransactionsOutput, TransactionProcessingConfig, + TransactionProcessingEnvironment, +}; +use std::{borrow::Cow, sync::Arc}; + +pub struct BankProcessor { + bank: Arc, + settings: Settings, +} + +impl Processor for BankProcessor { + fn process<'a>( + &self, + transactions: Cow<'a, [SanitizedTransaction]>, + ) -> Result { + let validator = BankValidator::new(self.bank.clone(), self.settings.clone()); + let result = validator.get_batch_results(transactions.clone()); + + // use the bank's transaction processor to process the transactions + let transaction_processor = self.bank.get_transaction_processor(); + let output = transaction_processor.load_and_execute_sanitized_transactions( + self.bank.as_ref(), + &transactions, + result, + &self.environment(), + &self.processing_config(), + ); + + Ok(output) + } +} + +impl BankProcessor { + pub fn new(bank: Arc, settings: Settings) -> Self { + Self { bank, settings } + } + + fn environment(&self) -> TransactionProcessingEnvironment { + let (blockhash, lamports_per_signature) = + self.bank.last_blockhash_and_lamports_per_signature(); + let processing_environment = TransactionProcessingEnvironment { + blockhash, + epoch_total_stake: self.bank.epoch_total_stake(self.bank.epoch()), + epoch_vote_accounts: self.bank.epoch_vote_accounts(self.bank.epoch()), + feature_set: Arc::clone(&self.bank.feature_set), + fee_structure: Some(self.bank.fee_structure()), + lamports_per_signature, + rent_collector: Some(self.bank.rent_collector()), + }; + processing_environment + } + + fn processing_config(&self) -> TransactionProcessingConfig { + TransactionProcessingConfig { + account_overrides: None, + check_program_modification_slot: self.bank.check_program_modification_slot(), + compute_budget: self.bank.compute_budget(), + limit_to_load_programs: false, + transaction_account_lock_limit: Some(self.bank.get_transaction_account_lock_limit()), + ..Default::default() + } + } +} diff --git a/executor/src/processor/mod.rs b/executor/src/processor/mod.rs new file mode 100644 index 0000000..b3da0a5 --- /dev/null +++ b/executor/src/processor/mod.rs @@ -0,0 +1,13 @@ +use crate::Result; +use solana_sdk::transaction::SanitizedTransaction; +use solana_svm::transaction_processor::LoadAndExecuteSanitizedTransactionsOutput; +use std::borrow::Cow; + +pub mod bank; + +pub trait Processor { + fn process<'a>( + &self, + transactions: Cow<'a, [SanitizedTransaction]>, + ) -> Result; +} diff --git a/executor/src/tests/basic.rs b/executor/src/tests/basic.rs new file mode 100644 index 0000000..b8d0646 --- /dev/null +++ b/executor/src/tests/basic.rs @@ -0,0 +1,100 @@ +use anyhow::Result; +use igloo_storage::{ + config::GlobalConfig, + init::default::{DEFAULT_MINT_LAMPORTS, DEFAULT_VALIDATOR_LAMPORTS}, +}; +use solana_sdk::{ + signature::Keypair, signer::Signer, system_transaction, transaction::SanitizedTransaction, +}; + +use crate::{defs::BlockPayload, Engine}; + +#[tokio::test] +async fn engine_basic_process_works() -> Result<()> { + let ledger_path = tempfile::tempdir()?.into_path(); + let mut engine = Engine::new_for_test(&ledger_path)?; + let keypairs = engine.store().keypairs().clone(); + + let alice = keypairs.mint_keypair.as_ref().unwrap().clone(); + let bob = keypairs.validator_keypair.as_ref().unwrap().clone(); + let charlie = Keypair::new().pubkey(); + let dave = Keypair::new().pubkey(); + + const ALICE_INIT_BALANCE: u64 = DEFAULT_MINT_LAMPORTS; + const BOB_INIT_BALANCE: u64 = DEFAULT_VALIDATOR_LAMPORTS; + assert_eq!(engine.store().balance(&alice.pubkey()), ALICE_INIT_BALANCE); + assert_eq!(engine.store().balance(&bob.pubkey()), BOB_INIT_BALANCE); + assert_eq!(engine.store().balance(&charlie), 0); + assert_eq!(engine.store().balance(&dave), 0); + + const TO_CHARLIE: u64 = 2000000; + const TO_DAVE: u64 = 1000000; + + let raw_txs = vec![ + system_transaction::transfer( + &alice, + &charlie, + TO_CHARLIE, + engine.store().current_bank().last_blockhash(), + ), + system_transaction::transfer( + &bob, + &dave, + TO_DAVE, + engine.store().current_bank().last_blockhash(), + ), + ]; + let block_payload = BlockPayload { + transactions: raw_txs + .clone() + .into_iter() + .map(|tx| SanitizedTransaction::from_transaction_for_tests(tx)) + .collect::>(), + }; + + // we can check block before processing + assert!(engine.check_block(&block_payload, None).is_ok()); + + let info = engine.new_block(block_payload).await?; + assert_eq!(info.head.slot, 1); + assert_eq!(info.store_height, Some(1)); + assert_eq!(info.parent.slot, 0); + + // after commit new block balance changed + assert_eq!( + engine.store().balance(&alice.pubkey()), + ALICE_INIT_BALANCE - TO_CHARLIE + ); + assert_eq!( + engine.store().balance(&bob.pubkey()), + BOB_INIT_BALANCE - TO_DAVE + ); + assert_eq!(engine.store().balance(&charlie), TO_CHARLIE); + assert_eq!(engine.store().balance(&dave), TO_DAVE); + + // save and close + engine.confirm(info.head.slot)?; + engine.close().await?; + + // open again + let mut config = GlobalConfig::new(&ledger_path)?; + config.keypairs = keypairs; + let engine = Engine::new_with_config(config)?; + + let (bank_height, store_height) = engine.store().get_mixed_heights()?; + assert_eq!(bank_height, 1); + assert_eq!(store_height, Some(1)); + assert_eq!( + engine.store().balance(&alice.pubkey()), + ALICE_INIT_BALANCE - TO_CHARLIE + ); + assert_eq!( + engine.store().balance(&bob.pubkey()), + BOB_INIT_BALANCE - TO_DAVE + ); + assert_eq!(engine.store().balance(&charlie), TO_CHARLIE); + assert_eq!(engine.store().balance(&dave), TO_DAVE); + engine.close().await?; + + Ok(()) +} diff --git a/executor/src/tests/mod.rs b/executor/src/tests/mod.rs new file mode 100644 index 0000000..1bca5f8 --- /dev/null +++ b/executor/src/tests/mod.rs @@ -0,0 +1 @@ +mod basic; diff --git a/interface/Cargo.toml b/interface/Cargo.toml index c17d802..fdc7c66 100644 --- a/interface/Cargo.toml +++ b/interface/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rollups-interface" +name = "igloo-interface" version = "0.1.0" edition = "2021" diff --git a/storage/Cargo.toml b/storage/Cargo.toml index 1ec72b1..a2d4bf8 100644 --- a/storage/Cargo.toml +++ b/storage/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "rollups-storage" +name = "igloo-storage" version.workspace = true authors.workspace = true repository.workspace = true @@ -34,7 +34,7 @@ solana-metrics = { workspace = true } spl-token = { workspace = true } spl-token-2022 = { workspace = true } -rollups-interface = { workspace = true } +igloo-interface = { workspace = true } [dev-dependencies] anyhow = { workspace = true } diff --git a/storage/src/accounts/mod.rs b/storage/src/accounts/mod.rs index 0fc790b..e808a01 100644 --- a/storage/src/accounts/mod.rs +++ b/storage/src/accounts/mod.rs @@ -1,4 +1,4 @@ -use rollups_interface::l2::{bank::BankInfo, storage::TransactionSet}; +use igloo_interface::l2::{bank::BankInfo, storage::TransactionSet}; use solana_entry::entry::Entry; use solana_runtime::{ bank::{Bank, ExecutedTransactionCounts, NewBankOptions, TotalAccountsStats}, diff --git a/storage/src/accounts/tests.rs b/storage/src/accounts/tests.rs index 659808e..208258e 100644 --- a/storage/src/accounts/tests.rs +++ b/storage/src/accounts/tests.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use rollups_interface::l2::{bank::BankOperations, storage::StorageOperations}; +use igloo_interface::l2::{bank::BankOperations, storage::StorageOperations}; use solana_accounts_db::{ accounts_db::{self, ACCOUNTS_DB_CONFIG_FOR_TESTING}, accounts_index::AccountSecondaryIndexes, diff --git a/storage/src/blockstore/txs.rs b/storage/src/blockstore/txs.rs index 786b8ca..94a4852 100644 --- a/storage/src/blockstore/txs.rs +++ b/storage/src/blockstore/txs.rs @@ -1,4 +1,4 @@ -use rollups_interface::l2::storage::TransactionSet; +use igloo_interface::l2::storage::TransactionSet; use solana_account_decoder::{ parse_account_data::SplTokenAdditionalData, parse_token::{is_known_spl_token_id, token_amount_to_ui_amount_v2, UiTokenAmount}, diff --git a/storage/src/config.rs b/storage/src/config.rs index fc6c2a3..f5c963e 100644 --- a/storage/src/config.rs +++ b/storage/src/config.rs @@ -5,7 +5,7 @@ use std::{ time::Duration, }; -use rollups_interface::l2::executor::Config; +use igloo_interface::l2::executor::Config; use solana_accounts_db::{ accounts_db::{AccountShrinkThreshold, AccountsDbConfig}, accounts_index::AccountSecondaryIndexes, @@ -22,7 +22,7 @@ use solana_sdk::{ }; use solana_svm::runtime_config::RuntimeConfig; -use crate::{init::init_config, Result}; +use crate::{init::init_config, Result, RollupStorage}; pub const MAX_GENESIS_ARCHIVE_UNPACKED_SIZE: u64 = 10 * 1024 * 1024; // 10 MiB @@ -46,6 +46,12 @@ pub struct KeypairsConfig { pub voting_keypair: Option>, } +impl RollupStorage { + pub fn keypairs(&self) -> &KeypairsConfig { + &self.config.keypairs + } +} + impl Config for GlobalConfig {} impl GlobalConfig { @@ -156,6 +162,15 @@ impl Default for HistoryConfig { } impl KeypairsConfig { + pub fn set_default_path(&mut self, base: &Path) { + self.validator_key_path + .get_or_insert(base.join("../genesis/validator-identity.json")); + self.mint_key_path + .get_or_insert(base.join("../genesis/validator-stake-account.json")); + self.voting_key_path + .get_or_insert(base.join("../genesis/validator-vote-account.json")); + } + pub fn init(&mut self) -> crate::Result<()> { Self::try_init( &mut self.validator_keypair, diff --git a/storage/src/error.rs b/storage/src/error.rs index 88b52ca..1fb8dfe 100644 --- a/storage/src/error.rs +++ b/storage/src/error.rs @@ -53,6 +53,9 @@ pub enum StorageError { #[error("Empty entries hashes")] EmptyEntriesHashes, + + #[error("Blockstore set root failed: {0}")] + SetRootFailed(String), } #[derive(Debug, Error)] @@ -60,7 +63,7 @@ pub enum BankError { #[error("Bank common error: {0}")] Common(String), - #[error("Set root failed: {0}")] + #[error("Bank set root failed: {0}")] SetRootFailed(String), #[error("Bank at slot {0} not found")] diff --git a/storage/src/execution/mod.rs b/storage/src/execution/mod.rs index 304b0e1..efdae12 100644 --- a/storage/src/execution/mod.rs +++ b/storage/src/execution/mod.rs @@ -1,5 +1,5 @@ use crate::{blockstore::txs::CommitBatch, Result, RollupStorage}; -use rollups_interface::l2::storage::{TransactionSet, TransactionsResult}; +use igloo_interface::l2::storage::{TransactionSet, TransactionsResult}; use solana_sdk::transaction::{SanitizedTransaction, VersionedTransaction}; use solana_svm::{ transaction_processor::LoadAndExecuteSanitizedTransactionsOutput, @@ -47,3 +47,9 @@ impl TransactionsResult for TransactionsResultWrapper { .collect() } } + +impl From for TransactionsResultWrapper { + fn from(output: LoadAndExecuteSanitizedTransactionsOutput) -> Self { + Self { output } + } +} diff --git a/storage/src/execution/tests.rs b/storage/src/execution/tests.rs index 6d79f14..3d4a78f 100644 --- a/storage/src/execution/tests.rs +++ b/storage/src/execution/tests.rs @@ -12,7 +12,7 @@ use crate::{ RollupStorage, }; use anyhow::Result; -use rollups_interface::l2::{bank::BankOperations, storage::StorageOperations}; +use igloo_interface::l2::{bank::BankOperations, storage::StorageOperations}; use solana_sdk::{signature::Keypair, signer::Signer, system_transaction}; #[tokio::test] diff --git a/storage/src/history/mod.rs b/storage/src/history/mod.rs index ccd8b69..7dec48c 100644 --- a/storage/src/history/mod.rs +++ b/storage/src/history/mod.rs @@ -3,7 +3,7 @@ use crate::{ Result, RollupStorage, }; use crossbeam_channel::unbounded; -use rollups_interface::l2::storage::TransactionSet; +use igloo_interface::l2::storage::TransactionSet; use solana_core::cache_block_meta_service::CacheBlockMetaService; use solana_ledger::{ blockstore::Blockstore, diff --git a/storage/src/history/tests.rs b/storage/src/history/tests.rs index fd3cb9a..c5d3d1b 100644 --- a/storage/src/history/tests.rs +++ b/storage/src/history/tests.rs @@ -7,7 +7,7 @@ use crate::{ RollupStorage, }; use anyhow::Result; -use rollups_interface::l2::{bank::BankOperations, storage::StorageOperations}; +use igloo_interface::l2::{bank::BankOperations, storage::StorageOperations}; use solana_sdk::{ signature::Keypair, signer::Signer, system_transaction, transaction::SanitizedTransaction, }; diff --git a/storage/src/impls.rs b/storage/src/impls.rs index f500f63..576e466 100644 --- a/storage/src/impls.rs +++ b/storage/src/impls.rs @@ -1,4 +1,4 @@ -use rollups_interface::l2::{ +use igloo_interface::l2::{ bank::{BankInfo, BankOperations}, executor::Init, storage::StorageOperations, diff --git a/storage/src/init/default.rs b/storage/src/init/default.rs index 7f81754..c8b1867 100644 --- a/storage/src/init/default.rs +++ b/storage/src/init/default.rs @@ -13,9 +13,9 @@ use solana_sdk::{ }; use std::path::Path; -pub(crate) const DEFAULT_VALIDATOR_LAMPORTS: u64 = 10_000_000; -pub(crate) const DEFAULT_MINT_LAMPORTS: u64 = 1_000_000_000; -pub(crate) const DEFAULT_STAKE_LAMPORTS: u64 = 50_000_000; +pub const DEFAULT_VALIDATOR_LAMPORTS: u64 = 10_000_000; +pub const DEFAULT_MINT_LAMPORTS: u64 = 1_000_000_000; +pub const DEFAULT_STAKE_LAMPORTS: u64 = 50_000_000; pub(crate) fn default_genesis_config(ledger_path: &Path) -> Result<(GenesisConfigInfo, Keypair)> { let validator_key = Keypair::new(); diff --git a/storage/src/ledger/mod.rs b/storage/src/ledger/mod.rs index a79130d..c4f4bec 100644 --- a/storage/src/ledger/mod.rs +++ b/storage/src/ledger/mod.rs @@ -1,6 +1,9 @@ -use crate::{error::BankError, Result, RollupStorage}; +use crate::{ + error::{BankError, StorageError}, + Result, RollupStorage, +}; use solana_runtime::{bank_forks::BankForks, installed_scheduler_pool::BankWithScheduler}; -use solana_sdk::{account::ReadableAccount, pubkey::Pubkey}; +use solana_sdk::{account::ReadableAccount, hash::Hash, pubkey::Pubkey}; use std::{ collections::HashSet, sync::{Arc, RwLock}, @@ -9,7 +12,57 @@ use std::{ #[cfg(test)] mod tests; +#[derive(Debug, Clone, Default)] +pub struct SlotHead { + pub slot: u64, + pub hash: Option, + pub timestamp: Option, +} + +#[derive(Debug, Clone, Default)] +pub struct SlotInfo { + pub head: SlotHead, + pub parent: SlotHead, + pub store_height: Option, +} + impl RollupStorage { + pub fn get_slot_info(&self, slot: u64) -> Result { + let head = self.get_slot_head(slot)?; + let parent = self.get_slot_head(head.slot - 1)?; + let store_height = self.blockstore.highest_slot()?; + Ok(SlotInfo { + head, + parent, + store_height, + }) + } + + pub fn get_slot_head(&self, slot: u64) -> Result { + let hash = { self.bank_forks.read().unwrap().get(slot) }; + let timestamp = self.blockstore.get_rooted_block_time(slot).ok(); + hash.map_or_else( + || { + Ok(SlotHead { + slot, + timestamp, + ..Default::default() + }) + }, + |b| { + Ok(SlotHead { + slot, + hash: Some(b.hash()), + timestamp, + }) + }, + ) + } + + pub fn get_root(&self) -> u64 { + self.bank_forks.read().unwrap().root() + } + pub fn get_mixed_heights(&self) -> Result<(u64, Option)> { let bank_height = self.bank_forks.read().unwrap().highest_slot(); let store_height = self.blockstore.highest_slot()?; @@ -46,6 +99,14 @@ impl RollupStorage { Ok(removed) } + pub fn confirm(&mut self, slot: u64) -> Result<()> { + self.bank.freeze(); + self.blockstore + .set_roots(std::iter::once(&slot)) + .map_err(|e| StorageError::SetRootFailed(e.to_string()))?; + Ok(()) + } + pub fn set_root( &mut self, slot: u64, @@ -53,7 +114,7 @@ impl RollupStorage { ) -> Result> { self.blockstore .set_roots(std::iter::once(&slot)) - .map_err(|e| BankError::SetRootFailed(e.to_string()))?; + .map_err(|e| StorageError::SetRootFailed(e.to_string()))?; let removed_banks = self .bank_forks .write() diff --git a/storage/src/tests/basic.rs b/storage/src/tests/basic.rs index 1900215..785fdb1 100644 --- a/storage/src/tests/basic.rs +++ b/storage/src/tests/basic.rs @@ -2,14 +2,14 @@ use std::path::Path; use crate::{ blockstore::txs::CommitBatch, - config::{GlobalConfig, KeypairsConfig}, + config::GlobalConfig, execution::TransactionsResultWrapper, init::default::{DEFAULT_MINT_LAMPORTS, DEFAULT_STAKE_LAMPORTS, DEFAULT_VALIDATOR_LAMPORTS}, tests::mock::{assert_result_balance, processor::process_transfers_ex}, RollupStorage, }; use anyhow::Result; -use rollups_interface::l2::{bank::BankOperations, storage::StorageOperations}; +use igloo_interface::l2::{bank::BankOperations, storage::StorageOperations}; use solana_sdk::{ signature::Keypair, signer::Signer, @@ -75,13 +75,9 @@ async fn init_with_all_default_works() -> Result<()> { #[test] fn init_with_given_config_works() -> Result<()> { - let mut config = GlobalConfig::new(&Path::new("data/config/ledger"))?; - config.keypairs = KeypairsConfig { - validator_key_path: Some("data/config/genesis/validator-identity.json".into()), - mint_key_path: Some("data/config/genesis/validator-stake-account.json".into()), - voting_key_path: Some("data/config/genesis/validator-vote-account.json".into()), - ..Default::default() - }; + let ledger_path = Path::new("data/config/ledger"); + let mut config = GlobalConfig::new(&ledger_path)?; + config.keypairs.set_default_path(ledger_path); let mut store = RollupStorage::new(config)?; store.init()?; @@ -210,7 +206,7 @@ async fn storage_basic_process_works() -> Result<()> { assert_eq!(store.balance(&dave), TO_DAVE); // 3. save and close - store.force_save().await?; + store.confirm(store.current_height())?; store.close().await?; // 4. open again diff --git a/storage/src/tests/reorg.rs b/storage/src/tests/reorg.rs index acc7f62..bcf0d7a 100644 --- a/storage/src/tests/reorg.rs +++ b/storage/src/tests/reorg.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use anyhow::Result; -use rollups_interface::l2::{bank::BankOperations, storage::StorageOperations}; +use igloo_interface::l2::{bank::BankOperations, storage::StorageOperations}; use solana_runtime::bank::Bank; use solana_sdk::{ pubkey::Pubkey, signature::Keypair, signer::Signer, system_transaction, diff --git a/storage/src/tests/svm.rs b/storage/src/tests/svm.rs index 25a56cb..fd8a78d 100644 --- a/storage/src/tests/svm.rs +++ b/storage/src/tests/svm.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use rollups_interface::l2::executor::Init; +use igloo_interface::l2::executor::Init; use solana_sdk::{ account::ReadableAccount, clock::Clock, pubkey::Pubkey, sysvar::SysvarId, transaction::TransactionError, diff --git a/svm/cli/Cargo.toml b/svm/cli/Cargo.toml index 9a0a128..5cfe17c 100644 --- a/svm/cli/Cargo.toml +++ b/svm/cli/Cargo.toml @@ -11,7 +11,7 @@ edition.workspace = true [dependencies] svm-executor = { workspace = true } -rollups-interface = { workspace = true } +igloo-interface = { workspace = true } solana-sdk = { workspace = true } solana-svm = { workspace = true } diff --git a/svm/cli/src/main.rs b/svm/cli/src/main.rs index 6d98e43..efa1ffb 100644 --- a/svm/cli/src/main.rs +++ b/svm/cli/src/main.rs @@ -1,6 +1,6 @@ use anyhow::Result; use clap::Parser; -use rollups_interface::l2::{ +use igloo_interface::l2::{ bank::{BankInfo, BankOperations}, executor::{Config, Init}, }; diff --git a/svm/executor/Cargo.toml b/svm/executor/Cargo.toml index 1c15d60..c64c8c4 100644 --- a/svm/executor/Cargo.toml +++ b/svm/executor/Cargo.toml @@ -23,7 +23,8 @@ solana-runtime = { workspace = true, features = ["dev-context-only-utils"] } solana-ledger = { workspace = true } solana-accounts-db = { workspace = true } -rollups-interface = { workspace = true } +igloo-interface = { workspace = true } +igloo-storage = { workspace = true } [features] __test = [] diff --git a/svm/executor/src/bank/mod.rs b/svm/executor/src/bank/mod.rs index 0588cff..3ed3904 100644 --- a/svm/executor/src/bank/mod.rs +++ b/svm/executor/src/bank/mod.rs @@ -1,4 +1,4 @@ -use rollups_interface::l2::executor::Config; +use igloo_interface::l2::executor::Config; use solana_sdk::clock::Slot; mod wrapper; diff --git a/svm/executor/src/bank/wrapper.rs b/svm/executor/src/bank/wrapper.rs index eaab5fd..29db672 100644 --- a/svm/executor/src/bank/wrapper.rs +++ b/svm/executor/src/bank/wrapper.rs @@ -3,7 +3,7 @@ use std::{ sync::{Arc, RwLock}, }; -use rollups_interface::l2::{ +use igloo_interface::l2::{ bank::{BankInfo, BankOperations}, executor::Init, }; diff --git a/svm/executor/src/builder/db_tests.rs b/svm/executor/src/builder/db_tests.rs index 60d87cd..1ea9753 100644 --- a/svm/executor/src/builder/db_tests.rs +++ b/svm/executor/src/builder/db_tests.rs @@ -1,6 +1,6 @@ use std::env; -use rollups_interface::l2::executor::Init; +use igloo_interface::l2::executor::Init; use solana_sdk::{ account::ReadableAccount, clock::Clock, pubkey::Pubkey, sysvar::SysvarId, transaction::TransactionError, diff --git a/svm/executor/src/builder/simple.rs b/svm/executor/src/builder/simple.rs index 3d680d5..ffefd81 100644 --- a/svm/executor/src/builder/simple.rs +++ b/svm/executor/src/builder/simple.rs @@ -5,7 +5,7 @@ use std::{ sync::{Arc, RwLock}, }; -use rollups_interface::l2::{ +use igloo_interface::l2::{ bank::{BankInfo, BankOperations}, executor::{Config, Init}, }; diff --git a/svm/executor/src/builder/tests.rs b/svm/executor/src/builder/tests.rs index 233c8f9..67fb56f 100644 --- a/svm/executor/src/builder/tests.rs +++ b/svm/executor/src/builder/tests.rs @@ -1,6 +1,6 @@ use std::env; -use rollups_interface::l2::executor::Init; +use igloo_interface::l2::executor::Init; use solana_sdk::{ account::ReadableAccount, clock::Clock, pubkey::Pubkey, sysvar::SysvarId, transaction::TransactionError, diff --git a/svm/executor/src/mock/bank.rs b/svm/executor/src/mock/bank.rs index bb051d3..95fad14 100644 --- a/svm/executor/src/mock/bank.rs +++ b/svm/executor/src/mock/bank.rs @@ -3,7 +3,7 @@ use { env::{DEPLOYMENT_EPOCH, DEPLOYMENT_SLOT}, error::Error, }, - rollups_interface::l2::{ + igloo_interface::l2::{ bank::{BankInfo, BankOperations}, executor::{Config, Init}, }, diff --git a/validator/Cargo.toml b/validator/Cargo.toml new file mode 100644 index 0000000..ee3ca46 --- /dev/null +++ b/validator/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "igloo-validator" +version.workspace = true +authors.workspace = true +repository.workspace = true +homepage.workspace = true +license.workspace = true +edition.workspace = true + +[dependencies] +igloo-interface = { workspace = true } +igloo-storage = { workspace = true } +tempfile = { workspace = true } + +thiserror = { workspace = true } +tokio = { workspace = true } +log = { workspace = true } +crossbeam-channel = { workspace = true } + +solana-ledger = { workspace = true } +solana-accounts-db = { workspace = true } +solana-sdk = { workspace = true } +solana-svm = { workspace = true } +solana-runtime = { workspace = true } +solana-core = { workspace = true } +solana-entry = { workspace = true } + +[dev-dependencies] +anyhow = { workspace = true } diff --git a/validator/src/bank_validator.rs b/validator/src/bank_validator.rs new file mode 100644 index 0000000..8811ef4 --- /dev/null +++ b/validator/src/bank_validator.rs @@ -0,0 +1,185 @@ +use crate::{error::TicksError, settings::Settings, Result, SvmValidator, TransactionChecks}; +use solana_entry::entry::{Entry, EntrySlice}; +use solana_runtime::{bank::Bank, transaction_batch::TransactionBatch}; +use solana_sdk::transaction::{ + SanitizedTransaction, TransactionError, TransactionVerificationMode, +}; +use solana_svm::{ + account_loader::TransactionCheckResult, transaction_error_metrics::TransactionErrorMetrics, +}; +use std::{borrow::Cow, sync::Arc}; + +#[derive(Clone)] +pub struct BankValidator { + bank: Arc, + settings: Settings, +} + +impl SvmValidator for BankValidator { + type Transaction = SanitizedTransaction; + + type TransactionCheckResult = TransactionCheckResult; + + fn get_batch_results<'a>( + &self, + transactions: std::borrow::Cow<'a, [Self::Transaction]>, + ) -> Vec { + let transaction_results = if self.settings.switchs.tx_sanity_check { + self.get_transactions_sanity_results(&transactions) + } else { + transactions.iter().map(|_| Ok(())).collect() + }; + + let batch = self.batch_and_verify_conflicts(transactions, transaction_results.into_iter()); + let result = self.validate_batch(&batch); + result + } +} + +impl TransactionChecks for BankValidator { + type Transaction = SanitizedTransaction; + + type Error = crate::Error; + + fn transactions_sanity_check( + &self, + txs: &[Self::Transaction], + ) -> std::result::Result<(), Self::Error> { + txs.iter() + .map(|tx| { + self.bank + .fully_verify_transaction(tx.to_versioned_transaction()) + }) + .collect::, TransactionError>>()?; + Ok(()) + } + + fn transactions_conflict_check( + &self, + txs: &[Self::Transaction], + ) -> std::result::Result<(), Self::Error> { + let tx_account_lock_limit = self.bank.get_transaction_account_lock_limit(); + let results = self + .bank + .rc + .accounts + .lock_accounts(txs.iter(), tx_account_lock_limit); + results + .into_iter() + .collect::, TransactionError>>()?; + Ok(()) + } +} + +impl BankValidator { + pub fn new(bank: Arc, settings: Settings) -> Self { + Self { bank, settings } + } + + pub fn get_transactions_sanity_results( + &self, + txs: &[SanitizedTransaction], + ) -> Vec> { + txs.iter() + .map(|tx| { + let resanitized_tx = self + .bank + .fully_verify_transaction(tx.to_versioned_transaction())?; + if resanitized_tx != *tx { + // Sanitization before/after epoch give different transaction data - do not execute. + return Err(TransactionError::ResanitizationNeeded.into()); + } + Ok(()) + }) + .collect::>() + } + + pub fn entry_sanity_check( + &self, + entry: &Entry, + verification_mode: TransactionVerificationMode, + ) -> Result<()> { + entry + .transactions + .iter() + .map(|tx| self.bank.verify_transaction(tx.clone(), verification_mode)) + .collect::, TransactionError>>()?; + Ok(()) + } + + pub fn batch_and_verify_conflicts<'a, 'b>( + &'a self, + sanitized_txs: Cow<'b, [SanitizedTransaction]>, + transaction_results: impl Iterator>, + ) -> TransactionBatch<'a, 'b> { + let tx_account_lock_limit = self.bank.get_transaction_account_lock_limit(); + let lock_result = if self.settings.switchs.txs_conflict_check { + self.bank.rc.accounts.lock_accounts_with_results( + sanitized_txs.iter(), + transaction_results, + tx_account_lock_limit, + ) + } else { + transaction_results.map(|_| Ok(())).collect() + }; + TransactionBatch::new(lock_result, &self.bank, sanitized_txs) + } + + pub fn validate_batch(&self, batch: &TransactionBatch) -> Vec { + let mut error_counters = TransactionErrorMetrics::default(); + + let sanitized_txs = batch.sanitized_transactions(); + // check age and cache using the bank directly + let check_results = self.bank.check_transactions( + sanitized_txs, + batch.lock_results(), + self.settings.max_age, + &mut error_counters, + ); + check_results + } + + pub fn verify_ticks( + &self, + entries: &[Entry], + slot_full: bool, + tick_hash_count: &mut u64, + ) -> Result<()> { + let next_bank_tick_height = self.bank.tick_height() + entries.tick_count(); + let max_bank_tick_height = self.bank.max_tick_height(); + + if next_bank_tick_height > max_bank_tick_height { + warn!("Too many entry ticks found in slot: {}", self.bank.slot()); + return Err(TicksError::TooManyTicks.into()); + } + + if next_bank_tick_height < max_bank_tick_height && slot_full { + info!("Too few entry ticks found in slot: {}", self.bank.slot()); + return Err(TicksError::TooFewTicks.into()); + } + + if next_bank_tick_height == max_bank_tick_height { + let has_trailing_entry = entries.last().map(|e| !e.is_tick()).unwrap_or_default(); + if has_trailing_entry { + warn!("Slot: {} did not end with a tick entry", self.bank.slot()); + return Err(TicksError::TrailingEntry.into()); + } + + if !slot_full { + warn!("Slot: {} was not marked full", self.bank.slot()); + return Err(TicksError::InvalidLastTick.into()); + } + } + + let hashes_per_tick = self.bank.hashes_per_tick().unwrap_or(0); + if !entries.verify_tick_hash_count(tick_hash_count, hashes_per_tick) { + warn!( + "Tick with invalid number of hashes found in slot: {}", + self.bank.slot() + ); + return Err(TicksError::InvalidTickHashCount.into()); + } + + Ok(()) + } +} diff --git a/validator/src/error.rs b/validator/src/error.rs new file mode 100644 index 0000000..0684367 --- /dev/null +++ b/validator/src/error.rs @@ -0,0 +1,40 @@ +use solana_sdk::transaction::TransactionError; +use thiserror::Error; + +pub type Result = std::result::Result; + +#[derive(Error, Debug)] +pub enum Error { + #[error(transparent)] + TickError(#[from] TicksError), + + #[error(transparent)] + TransactionError(#[from] TransactionError), +} + +#[derive(Error, Debug)] +pub enum TicksError { + /// Blocks must end in a tick that has been marked as the last tick. + #[error("invalid last tick")] + InvalidLastTick, + + /// Blocks can not have missing ticks + /// Usually indicates that the node was interrupted with a more valuable block during + /// production and abandoned it for that more-favorable block. Leader sent data to indicate + /// the end of the block. + #[error("too few ticks")] + TooFewTicks, + + /// Blocks can not have extra ticks + #[error("too many ticks")] + TooManyTicks, + + /// All ticks must contain the same number of hashes within a block + #[error("invalid tick hash count")] + InvalidTickHashCount, + + /// Blocks must end in a tick entry, trailing transaction entries are not allowed to guarantee + /// that each block has the same number of hashes + #[error("trailing entry")] + TrailingEntry, +} diff --git a/validator/src/lib.rs b/validator/src/lib.rs new file mode 100644 index 0000000..7cd1e35 --- /dev/null +++ b/validator/src/lib.rs @@ -0,0 +1,36 @@ +pub mod bank_validator; +pub mod error; +pub mod settings; + +pub use { + bank_validator::BankValidator, + error::{Error, Result}, +}; + +#[macro_use] +extern crate log; + +pub trait SvmValidator { + type Transaction: Clone; + type TransactionCheckResult; + + fn get_batch_results<'a>( + &self, + transactions: std::borrow::Cow<'a, [Self::Transaction]>, + ) -> Vec; +} + +pub trait TransactionChecks { + type Transaction: Clone; + type Error; + + fn transactions_sanity_check( + &self, + txs: &[Self::Transaction], + ) -> std::result::Result<(), Self::Error>; + + fn transactions_conflict_check( + &self, + txs: &[Self::Transaction], + ) -> std::result::Result<(), Self::Error>; +} diff --git a/validator/src/settings.rs b/validator/src/settings.rs new file mode 100644 index 0000000..d3ac260 --- /dev/null +++ b/validator/src/settings.rs @@ -0,0 +1,20 @@ +#[derive(Debug, Clone)] +pub struct Settings { + pub max_age: usize, + pub switchs: Switchs, +} + +impl Default for Settings { + fn default() -> Self { + Self { + max_age: 150, // set default max_age from solana + switchs: Default::default(), + } + } +} + +#[derive(Debug, Clone, Default)] +pub struct Switchs { + pub tx_sanity_check: bool, + pub txs_conflict_check: bool, +}