From 8cd91ad9cf0ed70e8a2b7f5122ce380c3a76c67b Mon Sep 17 00:00:00 2001 From: Vladimir Petrzhikovskii Date: Mon, 24 Jun 2024 14:17:11 +0200 Subject: [PATCH] wip: explorer models --- Cargo.lock | 947 +++++++++++++++++++++++++++-- Cargo.toml | 1 + explorer-models/Cargo.toml | 27 + explorer-models/src/accounts.rs | 149 +++++ explorer-models/src/block.rs | 299 +++++++++ explorer-models/src/contracts.rs | 16 + explorer-models/src/lib.rs | 66 ++ explorer-models/src/message.rs | 95 +++ explorer-models/src/schema.rs | 240 ++++++++ explorer-models/src/transaction.rs | 74 +++ explorer-models/src/types.rs | 40 ++ explorer-models/src/utils.rs | 314 ++++++++++ 12 files changed, 2231 insertions(+), 37 deletions(-) create mode 100644 explorer-models/Cargo.toml create mode 100644 explorer-models/src/accounts.rs create mode 100644 explorer-models/src/block.rs create mode 100644 explorer-models/src/contracts.rs create mode 100644 explorer-models/src/lib.rs create mode 100644 explorer-models/src/message.rs create mode 100644 explorer-models/src/schema.rs create mode 100644 explorer-models/src/transaction.rs create mode 100644 explorer-models/src/types.rs create mode 100644 explorer-models/src/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 60965708e..af219db7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.11" @@ -39,6 +50,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.14" @@ -103,6 +129,12 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + [[package]] name = "asn1-rs" version = "0.5.2" @@ -305,6 +337,17 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bigdecimal" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6773ddc0eafc0e509fb60e48dff7f450f8e674a0686ae8605e8d9901bd5eefa" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "bincode" version = "1.3.3" @@ -343,6 +386,18 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -352,12 +407,64 @@ dependencies = [ "generic-array", ] +[[package]] +name = "borsh" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6362ed55def622cddc70a4746a68554d7b687713770de539e59a739b249f8ed" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ef8005764f53cd4dca619f5bf64cafd4664dada50ece25e4d81de54c80cc0b" +dependencies = [ + "once_cell", + "proc-macro-crate 3.1.0", + "proc-macro2", + "quote", + "syn 2.0.66", + "syn_derive", +] + [[package]] name = "bumpalo" version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.6.0" @@ -421,6 +528,26 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.5", +] + [[package]] name = "clang-sys" version = "1.8.1" @@ -552,6 +679,19 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + [[package]] name = "crossbeam-channel" version = "0.5.13" @@ -580,6 +720,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -629,8 +778,18 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d706e75d87e35569db781a9b5e2416cff1236a47ed380831f959382ccd5f858" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.10.2", + "darling_macro 0.10.2", +] + +[[package]] +name = "darling" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +dependencies = [ + "darling_core 0.20.9", + "darling_macro 0.20.9", ] [[package]] @@ -647,17 +806,42 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "darling_core" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.66", +] + [[package]] name = "darling_macro" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ - "darling_core", + "darling_core 0.10.2", "quote", "syn 1.0.109", ] +[[package]] +name = "darling_macro" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +dependencies = [ + "darling_core 0.20.9", + "quote", + "syn 2.0.66", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -665,7 +849,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", @@ -716,7 +900,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" dependencies = [ - "darling", + "darling 0.10.2", "derive_builder_core", "proc-macro2", "quote", @@ -729,12 +913,75 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" dependencies = [ - "darling", + "darling 0.10.2", "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "diesel" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff236accb9a5069572099f0b350a92e9560e8e63a9b8d546162f4a5e03026bb2" +dependencies = [ + "byteorder", + "chrono", + "diesel_derives", + "serde_json", + "uuid", +] + +[[package]] +name = "diesel-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acada1517534c92d3f382217b485db8a8638f111b0e3f2a2a8e26165050f77be" +dependencies = [ + "async-trait", + "diesel", + "futures-channel", + "futures-util", + "mobc", + "mysql_async", + "mysql_common", + "scoped-futures", + "tokio", +] + +[[package]] +name = "diesel-derive-enum" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81c5131a2895ef64741dad1d483f358c2a229a3a2d1b256778cdc5e146db64d4" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "diesel_derives" +version = "2.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14701062d6bed917b5c7103bdffaee1e4609279e240488ad24e7bd979ca6866c" +dependencies = [ + "diesel_table_macro_syntax", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "diesel_table_macro_syntax" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" +dependencies = [ + "syn 2.0.66", +] + [[package]] name = "digest" version = "0.10.7" @@ -844,7 +1091,7 @@ name = "everscale-types" version = "0.1.0-rc.6" source = "git+https://github.com/broxus/everscale-types.git?branch=tycho#1a88545a9a627e3a4f50f39699c12615442d874d" dependencies = [ - "ahash", + "ahash 0.8.11", "base64 0.21.7", "bitflags", "crc32c", @@ -869,6 +1116,24 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "explorer-models" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "diesel", + "diesel-async", + "diesel-derive-enum", + "hex", + "log", + "once_cell", + "serde", + "serde_json", + "tokio", + "uuid", +] + [[package]] name = "exponential-backoff" version = "1.2.0" @@ -913,6 +1178,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", + "libz-sys", "miniz_oxide", ] @@ -946,12 +1212,70 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "frunk" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11a351b59e12f97b4176ee78497dff72e4276fb1ceb13e19056aca7fa0206287" +dependencies = [ + "frunk_core", + "frunk_derives", + "frunk_proc_macros", +] + +[[package]] +name = "frunk_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af2469fab0bd07e64ccf0ad57a1438f63160c69b2e57f04a439653d68eb558d6" + +[[package]] +name = "frunk_derives" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fa992f1656e1707946bbba340ad244f0814009ef8c0118eb7b658395f19a2e" +dependencies = [ + "frunk_proc_macro_helpers", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "frunk_proc_macro_helpers" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35b54add839292b743aeda6ebedbd8b11e93404f902c56223e51b9ec18a13d2c" +dependencies = [ + "frunk_core", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "frunk_proc_macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71b85a1d4a9a6b300b41c05e8e13ef2feca03e0334127f29eca9506a7fe13a93" +dependencies = [ + "frunk_core", + "frunk_proc_macro_helpers", + "quote", + "syn 2.0.66", +] + [[package]] name = "fs_extra" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.3.30" @@ -1023,6 +1347,12 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.30" @@ -1086,20 +1416,38 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.11", +] + [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ - "ahash", + "ahash 0.8.11", ] [[package]] @@ -1303,6 +1651,29 @@ dependencies = [ "tracing", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1330,6 +1701,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -1337,7 +1718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1397,6 +1778,79 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lexical" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" +dependencies = [ + "lexical-core", +] + +[[package]] +name = "lexical-core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" +dependencies = [ + "lexical-parse-integer", + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-parse-integer" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" +dependencies = [ + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-util" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" +dependencies = [ + "static_assertions", +] + +[[package]] +name = "lexical-write-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" +dependencies = [ + "lexical-util", + "lexical-write-integer", + "static_assertions", +] + +[[package]] +name = "lexical-write-integer" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" +dependencies = [ + "lexical-util", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.155" @@ -1463,6 +1917,15 @@ version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "lru" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718e8fae447df0c7e1ba7f5189829e63fd536945c8988d61444c19039f16b670" +dependencies = [ + "hashbrown 0.13.2", +] + [[package]] name = "lz4-sys" version = "1.9.4" @@ -1500,13 +1963,23 @@ version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +[[package]] +name = "metrics" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be3cbd384d4e955b231c895ce10685e3d8260c5ccffae898c96c723b0772835" +dependencies = [ + "ahash 0.8.11", + "portable-atomic", +] + [[package]] name = "metrics" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "884adb57038347dfbaf2d5065887b6cf4312330dc8e94bc30a1a839bd79d3261" dependencies = [ - "ahash", + "ahash 0.8.11", "portable-atomic", ] @@ -1521,9 +1994,9 @@ dependencies = [ "hyper 1.3.1", "hyper-tls", "hyper-util", - "indexmap", + "indexmap 2.2.6", "ipnet", - "metrics", + "metrics 0.23.0", "metrics-util", "quanta", "thiserror", @@ -1539,8 +2012,8 @@ checksum = "4259040465c955f9f2f1a4a8a16dc46726169bca0f88e8fb2dbeced487c3e828" dependencies = [ "crossbeam-epoch", "crossbeam-utils", - "hashbrown", - "metrics", + "hashbrown 0.14.5", + "metrics 0.23.0", "num_cpus", "quanta", "sketches-ddsketch", @@ -1574,6 +2047,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] @@ -1584,6 +2058,25 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" +[[package]] +name = "mobc" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8d3681f0b299413df040f53c6950de82e48a8e1a9f79d442ed1ad3694d660b9" +dependencies = [ + "async-trait", + "futures-channel", + "futures-core", + "futures-timer", + "futures-util", + "log", + "metrics 0.22.3", + "thiserror", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "moka" version = "0.12.7" @@ -1604,6 +2097,95 @@ dependencies = [ "uuid", ] +[[package]] +name = "mysql-common-derive" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56b0d8a0db9bf6d2213e11f2c701cb91387b0614361625ab7b9743b41aa4938f" +dependencies = [ + "darling 0.20.9", + "heck 0.4.1", + "num-bigint", + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", + "termcolor", + "thiserror", +] + +[[package]] +name = "mysql_async" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5272f59b5b1f93d65f7f826c1f025d6e410e89fb50a67e05aa20b35a55a8c0a" +dependencies = [ + "bytes", + "crossbeam", + "flate2", + "futures-core", + "futures-sink", + "futures-util", + "lazy_static", + "lru", + "mio", + "mysql_common", + "native-tls", + "once_cell", + "pem 2.0.1", + "percent-encoding", + "pin-project", + "priority-queue", + "serde", + "serde_json", + "socket2 0.5.7", + "thiserror", + "tokio", + "tokio-native-tls", + "tokio-util", + "twox-hash", + "url", +] + +[[package]] +name = "mysql_common" +version = "0.30.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57349d5a326b437989b6ee4dc8f2f34b0cc131202748414712a8e7d98952fc8c" +dependencies = [ + "base64 0.21.7", + "bigdecimal", + "bindgen", + "bitflags", + "bitvec", + "byteorder", + "bytes", + "cc", + "cmake", + "crc32fast", + "flate2", + "frunk", + "lazy_static", + "lexical", + "mysql-common-derive", + "num-bigint", + "num-traits", + "rand", + "regex", + "rust_decimal", + "saturating", + "serde", + "serde_json", + "sha1", + "sha2", + "smallvec", + "subprocess", + "thiserror", + "time", + "uuid", +] + [[package]] name = "native-tls" version = "0.2.12" @@ -1865,6 +2447,16 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pem" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b13fe415cdf3c8e44518e18a7c95a13431d9bdf6d15367d82b23c377fdd441a" +dependencies = [ + "base64 0.21.7", + "serde", +] + [[package]] name = "pem" version = "3.0.4" @@ -1933,7 +2525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 2.2.6", ] [[package]] @@ -2018,6 +2610,59 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "priority-queue" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0bda9164fe05bc9225752d54aae413343c36f684380005398a6a8fde95fe785" +dependencies = [ + "autocfg", + "indexmap 1.9.3", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" version = "1.0.85" @@ -2027,6 +2672,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "public-ip" version = "0.2.2" @@ -2069,9 +2734,9 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "347e1a588d1de074eeb3c00eadff93db4db65aeb62aee852b1efd0949fe65b6c" dependencies = [ - "ahash", + "ahash 0.8.11", "equivalent", - "hashbrown", + "hashbrown 0.14.5", "parking_lot", ] @@ -2131,6 +2796,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "radix_trie" version = "0.2.1" @@ -2215,7 +2886,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54077e1872c46788540de1ea3d7f4ccb1983d12f9aa909b234468676c1a36779" dependencies = [ - "pem", + "pem 3.0.4", "ring", "rustls-pki-types", "time", @@ -2275,6 +2946,15 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + [[package]] name = "ring" version = "0.17.8" @@ -2290,6 +2970,35 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.7.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rlimit" version = "0.10.1" @@ -2309,6 +3018,22 @@ dependencies = [ "librocksdb-sys", ] +[[package]] +name = "rust_decimal" +version = "1.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1790d1c4c0ca81211399e0e0af16333276f375209e71a37b67698a373db5b47a" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand", + "rkyv", + "serde", + "serde_json", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -2398,6 +3123,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +[[package]] +name = "saturating" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece8e78b2f38ec51c51f5d475df0a7187ba5111b2a28bdc761ee05b075d40a71" + [[package]] name = "scc" version = "2.1.1" @@ -2416,6 +3147,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "scoped-futures" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1473e24c637950c9bd38763220bea91ec3e095a89f672bbd7a10d03e77ba467" +dependencies = [ + "cfg-if", + "pin-utils", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -2428,6 +3169,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "security-framework" version = "2.11.0" @@ -2483,7 +3230,7 @@ version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ - "indexmap", + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -2511,6 +3258,17 @@ dependencies = [ "serde", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.8" @@ -2555,6 +3313,12 @@ dependencies = [ "rand_core", ] +[[package]] +name = "simdutf8" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" + [[package]] name = "sketches-ddsketch" version = "0.2.2" @@ -2618,6 +3382,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strsim" version = "0.9.3" @@ -2630,6 +3400,16 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subprocess" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2e86926081dda636c546d8c5e641661049d7562a68f5488be4a1f7f66f6086" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "subtle" version = "2.5.0" @@ -2658,6 +3438,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "sync_wrapper" version = "0.1.2" @@ -2703,6 +3495,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.10.1" @@ -2715,6 +3513,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" version = "0.3.0" @@ -2947,12 +3754,40 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml_datetime" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow", +] + [[package]] name = "ton_executor" version = "2.0.0" source = "git+https://github.com/broxus/ton-labs-executor.git?branch=new_cells#923a1061ef70448c487a4ffdd91aa859d3e29335" dependencies = [ - "ahash", + "ahash 0.8.11", "anyhow", "everscale-types", "thiserror", @@ -2965,7 +3800,7 @@ name = "ton_vm" version = "2.0.0" source = "git+https://github.com/broxus/ton-labs-vm.git?branch=new_cells#0ca8a499b4bfa7717fd9f7b8d0564fcbff987408" dependencies = [ - "ahash", + "ahash 0.8.11", "anyhow", "everscale-crypto", "everscale-types", @@ -3218,6 +4053,17 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "rand", + "static_assertions", +] + [[package]] name = "tycho-block-util" version = "0.0.1" @@ -3249,7 +4095,7 @@ dependencies = [ "futures-util", "hex", "libc", - "metrics", + "metrics 0.23.0", "metrics-exporter-prometheus", "parking_lot", "public-ip", @@ -3290,8 +4136,8 @@ dependencies = [ "everscale-types", "futures-util", "humantime", - "indexmap", - "metrics", + "indexmap 2.2.6", + "metrics 0.23.0", "parking_lot", "rand", "serde", @@ -3320,7 +4166,7 @@ dependencies = [ name = "tycho-consensus" version = "0.0.1" dependencies = [ - "ahash", + "ahash 0.8.11", "anyhow", "arc-swap", "async-trait", @@ -3333,7 +4179,7 @@ dependencies = [ "hex", "humantime", "itertools", - "metrics", + "metrics 0.23.0", "parking_lot", "rand", "rand_pcg", @@ -3368,7 +4214,7 @@ dependencies = [ "everscale-types", "futures-util", "itertools", - "metrics", + "metrics 0.23.0", "parking_lot", "rand", "serde", @@ -3389,7 +4235,7 @@ dependencies = [ name = "tycho-network" version = "0.0.1" dependencies = [ - "ahash", + "ahash 0.8.11", "anyhow", "arc-swap", "base64 0.22.1", @@ -3402,8 +4248,8 @@ dependencies = [ "exponential-backoff", "futures-util", "hex", - "indexmap", - "metrics", + "indexmap 2.2.6", + "metrics 0.23.0", "moka", "parking_lot", "pin-project-lite", @@ -3440,7 +4286,7 @@ dependencies = [ "bytes", "everscale-types", "futures-util", - "metrics", + "metrics 0.23.0", "parking_lot", "serde", "serde_json", @@ -3474,7 +4320,7 @@ dependencies = [ name = "tycho-storage" version = "0.0.1" dependencies = [ - "ahash", + "ahash 0.8.11", "anyhow", "arc-swap", "base64 0.22.1", @@ -3488,7 +4334,7 @@ dependencies = [ "hex", "humantime", "libc", - "metrics", + "metrics 0.23.0", "num-traits", "parking_lot", "parking_lot_core", @@ -3518,7 +4364,7 @@ dependencies = [ name = "tycho-util" version = "0.0.1" dependencies = [ - "ahash", + "ahash 0.8.11", "anyhow", "castaway", "dashmap", @@ -3527,7 +4373,7 @@ dependencies = [ "hex", "humantime", "libc", - "metrics", + "metrics 0.23.0", "rand", "rayon", "serde", @@ -3715,7 +4561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28ceae4f0ce90e6e953ef9a1d8cc3c95fc7f9b77bf86470b596fe29db53311e4" dependencies = [ "librocksdb-sys", - "metrics", + "metrics 0.23.0", "rocksdb", "thiserror", "tracing", @@ -3749,6 +4595,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -3913,6 +4768,24 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x509-parser" version = "0.15.1" diff --git a/Cargo.toml b/Cargo.toml index 61fe6156c..f11c172e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ "collator", "consensus", "core", + "explorer-models", "network", "rpc", "simulator", diff --git a/explorer-models/Cargo.toml b/explorer-models/Cargo.toml new file mode 100644 index 000000000..a4da22eec --- /dev/null +++ b/explorer-models/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "explorer-models" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "1.0.70" +log = "0.4.17" +once_cell = "1.17.1" +serde = { version = "1.0.159", features = ["derive"] } +serde_json = "1.0.95" + + +hex = "0.4.3" +diesel = { version = "2.1.0", features = ["mysql_backend", "serde_json", "uuid", "chrono"] } +chrono = "0.4.26" +diesel-derive-enum = { version = "2.1.0", features = ["mysql"] } +uuid = "1.4.0" + +[features] +default = [] +csv = [] +venom = [] + +[dev-dependencies] +tokio = { version = "1.12.0", features = ["full"] } +diesel-async = { version = "0.4.1", features = ["mysql", "mobc"] } diff --git a/explorer-models/src/accounts.rs b/explorer-models/src/accounts.rs new file mode 100644 index 000000000..654c6b95e --- /dev/null +++ b/explorer-models/src/accounts.rs @@ -0,0 +1,149 @@ +use diesel::mysql::Mysql; +use diesel::{Insertable, Queryable, Selectable}; +use serde::{Deserialize, Serialize}; + +use crate::schema::sql_types::State; +#[cfg(feature = "csv")] +use crate::utils::*; +use crate::{Hash, NumBinds}; + +#[derive(Debug, Serialize, Clone, Insertable, Queryable, Eq, PartialEq)] +#[diesel(table_name = crate::schema::accounts)] +pub struct Account { + pub workchain: i8, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub address: Hash, + pub state: State, + pub balance: u64, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub init_code_hash: Option, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub code_hash: Option, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub data_hash: Option, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub creator_address: Option, + pub creator_wc: i8, + pub created_at: u32, + pub updated_at: u32, + pub updated_lt: u64, +} + +impl NumBinds for Account { + const NUM_BINDS: usize = 12; +} + +#[derive(Debug, Selectable, Queryable)] +#[diesel(check_for_backend(Mysql))] +#[diesel(table_name = crate::schema::accounts)] +pub struct BriefAccountData { + pub address: Hash, + pub state: State, + pub creator_wc: i8, + pub creator_address: Option, + pub created_at: u32, + pub balance: u64, + pub init_code_hash: Option, + pub code_hash: Option, + pub data_hash: Option, +} + +impl Account { + pub fn delete(&mut self) { + // Leave account state as `Deleted` + // or set `NonExist` otherwise + if self.state != State::Deleted { + self.state = State::NonExist; + } + + // Reset other state variables + self.balance = 0; + self.init_code_hash = None; + self.code_hash = None; + self.data_hash = None; + } +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct AccountUpdate { + pub address: Hash, + pub wc: i8, + pub last_transaction_time: u32, + pub last_transaction_lt: u64, + pub creator: Option, + pub state: State, + pub deleted: bool, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +pub struct CreatorInfo { + pub created_at: u32, + pub creator_address: Hash, + pub creator_wc: i8, +} + +#[derive(Queryable, Selectable)] +#[diesel(check_for_backend(Mysql))] +#[diesel(table_name = crate::schema::accounts)] +pub struct AccountWithCreatorInfo { + pub address: Hash, + pub creator_address: Option, + pub creator_wc: i8, + pub created_at: u32, + pub state: State, +} + +#[cfg(test)] +mod test { + use diesel::{BoolExpressionMethods, ExpressionMethods, QueryDsl, SelectableHelper}; + use diesel_async::pooled_connection::mobc::Pool; + use diesel_async::pooled_connection::AsyncDieselConnectionManager; + use diesel_async::{AsyncMysqlConnection, RunQueryDsl}; + + #[tokio::test] + async fn aaa() { + use super::BriefAccountData; + use crate::schema::accounts::dsl::*; + + let db_client: AsyncDieselConnectionManager = + AsyncDieselConnectionManager::new(std::env::var("DATABASE_URL").unwrap()); + let db_client = Pool::builder().build(db_client); + + let workchains = std::iter::repeat(0).take(100_000).collect::>(); + let addrs = (0..100_000) + .map(|x| { + let mut addr = [0u8; 32]; + addr[0] = x as u8; + addr.to_vec() + }) + .collect::>(); + + let rand_addrs: Vec> = accounts + .limit(100_000) + .filter(workchain.eq(0)) + .select(address) + .load(&mut db_client.get().await.unwrap()) + .await + .unwrap(); + + for zipped in workchains.chunks(31000).zip(rand_addrs.chunks(31000)) { + let (workchains, addrs) = zipped; + let query = accounts + .filter(workchain.eq_any(workchains).and(address.eq_any(addrs))) + .select(BriefAccountData::as_select()) + .load(&mut db_client.get().await.unwrap()) + .await + .unwrap(); + println!("Returnd {} rows", query.len()); + } + + // let query = accounts + // .filter(workchain.eq_any(workchains).and(address.eq_any(addrs))) + // .select(BriefAccountData::as_select()) + // .load(&mut db_client.get().await.unwrap()) + // .await + // .unwrap(); + + // println!("{}", diesel::debug_query::(&query)); + } +} diff --git a/explorer-models/src/block.rs b/explorer-models/src/block.rs new file mode 100644 index 000000000..6e129b560 --- /dev/null +++ b/explorer-models/src/block.rs @@ -0,0 +1,299 @@ +use diesel::Insertable; +use serde::{Deserialize, Serialize}; + +use crate::utils::*; +use crate::{Hash, NumBinds}; + +#[cfg(not(feature = "csv"))] +#[derive(Debug, Serialize, Clone, Insertable)] +#[diesel(table_name = crate::schema::blocks)] +pub struct Block { + // indexed + pub workchain: i8, + pub shard: u64, + pub seqno: u32, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub root_hash: Hash, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub file_hash: Hash, + + // Brief meta + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bool"))] + pub is_key_block: bool, + pub transaction_count: u16, + pub gen_utime: u32, + pub gen_software_version: u32, + + // Prev block ref + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub prev1: Hash, + pub prev1_seqno: u32, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub prev2: Option, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_optional"))] + pub prev2_seqno: Option, + + pub prev_key_block: u32, + + // Detailed info + pub block_info: JsonValue, + pub value_flow: JsonValue, + pub account_blocks: JsonValue, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_optional"))] + pub shards_info: Option, + + #[cfg_attr(feature = "csv", serde(with = "serde_csv_optional"))] + pub additional_info: Option, +} + +#[cfg(feature = "csv")] +#[derive(Debug, Serialize, Clone)] +pub struct Block { + // indexed + pub workchain: i8, + pub shard: u64, + pub seqno: u32, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub root_hash: Hash, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub file_hash: Hash, + + // Brief meta + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bool"))] + pub is_key_block: bool, + pub transaction_count: u16, + pub gen_utime: u32, + pub gen_software_version: u32, + + // Prev block ref + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub prev1: Hash, + pub prev1_seqno: u32, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub prev2: Option, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_optional"))] + pub prev2_seqno: Option, + + pub prev_key_block: u32, + + // Detailed info + pub block_info: JsonValue, + pub value_flow: JsonValue, + pub account_blocks: JsonValue, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_optional"))] + pub shards_info: Option, + + #[cfg_attr(feature = "csv", serde(with = "serde_csv_optional"))] + pub additional_info: Option, +} + +impl NumBinds for Block { + const NUM_BINDS: usize = 19; +} + +#[derive(Debug, Serialize, Clone, Insertable)] +#[diesel(table_name = crate::schema::network_config)] +pub struct KeyBlockConfig { + pub end_lt: u64, + pub seq_no: u32, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub config_params_boc: Vec, +} + +impl NumBinds for KeyBlockConfig { + const NUM_BINDS: usize = 3; +} + +#[cfg(not(feature = "csv"))] +type JsonValue = serde_json::Value; +#[cfg(feature = "csv")] +type JsonValue = String; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct BlockInfo { + #[serde(default, skip_serializing_if = "is_default")] + pub version: u32, + #[serde(default, skip_serializing_if = "is_default")] + pub after_merge: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub before_split: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub after_split: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub want_split: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub want_merge: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub key_block: bool, + + #[serde(default, skip_serializing_if = "is_default")] + pub vert_seq_no: u32, + #[serde(default, skip_serializing_if = "is_default")] + pub vert_seq_no_incr: u32, + + pub flags: u8, + + #[serde(with = "serde_string")] + pub start_lt: u64, + #[serde(with = "serde_string")] + pub end_lt: u64, + pub gen_validator_list_hash_short: u32, + pub gen_catchain_seqno: u32, + pub min_ref_mc_seqno: u32, + pub prev_key_block_seqno: u32, + pub gen_software: Option, + + pub master_ref: Option, + pub prev_ref: BlkPrevInfo, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub prev_vert_ref: Option, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(tag = "kind")] +pub enum BlkPrevInfo { + Block { prev: ExtBlkRef }, + Blocks { prev1: ExtBlkRef, prev2: ExtBlkRef }, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ExtBlkRef { + #[serde(with = "serde_string")] + pub end_lt: u64, + pub seq_no: u32, + pub root_hash: HashInsert<32>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GlobalVersion { + pub version: u32, + #[serde(with = "serde_string")] + pub capabilities: u64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ValueFlow { + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub from_prev_blk: u64, + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub to_next_blk: u64, + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub imported: u64, + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub exported: u64, + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub fees_collected: u64, + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub fees_imported: u64, + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub recovered: u64, + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub created: u64, + #[serde(default, with = "serde_string", skip_serializing_if = "is_default")] + pub minted: u64, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct AccountBlockInfo { + wc: i32, + address: Hash, + old_hash: Hash, + new_hash: Hash, + transaction_count: u16, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShardDescrInfoItem { + pub shard_ident: ShardId, + pub info: ShardDescrInfo, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShardId { + pub wc: i32, + #[serde(with = "serde_string")] + pub shard_prefix: u64, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ShardDescrInfo { + pub seq_no: u32, + pub reg_mc_seqno: u32, + #[serde(with = "serde_string")] + pub start_lt: u64, + #[serde(with = "serde_string")] + pub end_lt: u64, + pub root_hash: Hash, + pub file_hash: Hash, + #[serde(default, skip_serializing_if = "is_default")] + pub before_split: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub before_merge: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub want_split: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub want_merge: bool, + #[serde(default, skip_serializing_if = "is_default")] + pub nx_cc_updated: bool, + pub flags: u8, + pub next_catchain_seqno: u32, + #[serde(with = "serde_string")] + pub next_validator_shard: u64, + pub min_ref_mc_seqno: u32, + pub gen_utime: u32, + pub split_merge_at: FutureSplitMerge, + #[serde(with = "serde_string")] + pub fees_collected: u64, + #[serde(with = "serde_string")] + pub funds_created: u64, + #[cfg(feature = "venom")] + pub collators_info: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(tag = "kind")] +pub enum FutureSplitMerge { + None, + #[serde(rename_all = "camelCase")] + Split { + split_utime: u32, + interval: u32, + }, + #[serde(rename_all = "camelCase")] + Merge { + merge_utime: u32, + interval: u32, + }, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ShardCollators { + pub prev: CollatorRange, + pub prev2: Option, + pub current: CollatorRange, + pub next: CollatorRange, + pub next2: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CollatorRange { + pub collator: u16, + pub collator_info: Option, + pub start: u32, + pub finish: u32, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct ValidatorDescr { + pub public_key: String, + pub weight: u64, + pub adnl_addr: Option, + pub mc_seq_no_since: u32, +} diff --git a/explorer-models/src/contracts.rs b/explorer-models/src/contracts.rs new file mode 100644 index 000000000..4c80af4e3 --- /dev/null +++ b/explorer-models/src/contracts.rs @@ -0,0 +1,16 @@ +use chrono::NaiveDateTime; +use diesel::mysql::Mysql; +use diesel::{Queryable, Selectable}; + +use crate::schema::contracts_info; +use crate::utils::HashInsert; + +#[derive(Queryable, Debug, Selectable)] +#[diesel(check_for_backend(Mysql))] +#[diesel(table_name = contracts_info)] +pub struct ContractData { + pub code_hash: HashInsert<32>, + pub abi: serde_json::Value, + pub contract_id: HashInsert<16>, + pub created_at: NaiveDateTime, +} diff --git a/explorer-models/src/lib.rs b/explorer-models/src/lib.rs new file mode 100644 index 000000000..e6a3fdf53 --- /dev/null +++ b/explorer-models/src/lib.rs @@ -0,0 +1,66 @@ +pub use contracts::*; + +pub use self::accounts::*; +pub use self::block::*; +pub use self::message::*; +pub use self::transaction::*; +pub use crate::utils::HashInsert; + +mod accounts; +mod block; +mod contracts; +mod message; +pub mod schema; +mod transaction; +mod types; +mod utils; + +pub type Hash = HashInsert<32>; + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum ProcessingType { + OnlyBlocks, + Full, +} + +#[derive(Default)] +pub struct ProcessingContext { + pub blocks: Vec, + pub configs: Vec, + pub transactions: Vec, + pub messages: Vec, + pub transaction_messages: Vec, + pub raw_transactions: Vec, + pub account_updates: Vec, +} + +impl ProcessingContext { + // accounts are in one block so in one shard + pub fn known_accounts(&self) -> Option<(i8, Vec>)> { + let wc = self.account_updates.first()?.wc; + let accounts = self.account_updates.iter().map(|x| x.address).collect(); + + Some((wc, accounts)) + } + + pub fn clear(&mut self) { + self.blocks.clear(); + self.configs.clear(); + self.transactions.clear(); + self.messages.clear(); + self.transaction_messages.clear(); + self.raw_transactions.clear(); + self.account_updates.clear(); + } +} + +pub struct TransactionForParsing<'tx> { + pub code_hash: HashInsert<32>, + pub serialized_tx: &'tx [u8], + pub workchain: i8, + pub account_id: &'tx [u8], +} + +pub trait NumBinds { + const NUM_BINDS: usize; +} diff --git a/explorer-models/src/message.rs b/explorer-models/src/message.rs new file mode 100644 index 000000000..c227f50f7 --- /dev/null +++ b/explorer-models/src/message.rs @@ -0,0 +1,95 @@ +use diesel::Insertable; +use serde::Serialize; + +use crate::schema::sql_types::MessageType; +#[cfg(feature = "csv")] +use crate::utils::*; +use crate::{Hash, NumBinds}; + +#[derive(Debug, Serialize, Clone, Insertable)] +#[diesel(table_name = crate::schema::messages)] +pub struct Message { + /// Primary key + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub message_hash: Hash, + + pub src_workchain: i8, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub src_address: Option, + + pub dst_workchain: i8, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub dst_address: Option, + + pub message_type: MessageType, + + pub message_value: u64, + pub ihr_fee: u64, + pub fwd_fee: u64, + pub import_fee: u64, + + pub created_lt: u64, + pub created_at: u32, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bool"))] + pub bounced: bool, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bool"))] + pub bounce: bool, +} + +impl NumBinds for Message { + const NUM_BINDS: usize = 14; +} + +#[derive(Debug, Serialize, Clone, Insertable)] +#[diesel(table_name = crate::schema::transaction_messages)] +pub struct TransactionMessage { + /// Primary key. Column 0 + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub transaction_hash: Hash, + /// Primary key. Column 1 + pub index_in_transaction: u16, + /// Primary key. Column 2 + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bool"))] + pub is_out: bool, + pub transaction_time: u32, + pub transaction_lt: u64, + pub transaction_account_workchain: i8, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub transaction_account_address: Hash, + + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub block_hash: Hash, + + pub dst_workchain: i8, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub dst_address: Option, + pub src_workchain: i8, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes_optional"))] + pub src_address: Option, + + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub message_hash: Hash, + pub message_type: MessageType, + pub message_value: u64, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bool"))] + pub bounced: bool, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bool"))] + pub bounce: bool, +} + +impl NumBinds for TransactionMessage { + const NUM_BINDS: usize = 17; +} + +#[derive(Debug, Default)] +pub struct MessageInfo { + pub value: u64, + pub ihr_fee: u64, + pub fwd_fee: u64, + pub import_fee: u64, + + pub bounce: bool, + pub bounced: bool, + pub created_lt: u64, + pub created_at: u32, +} diff --git a/explorer-models/src/schema.rs b/explorer-models/src/schema.rs new file mode 100644 index 000000000..69cee87b1 --- /dev/null +++ b/explorer-models/src/schema.rs @@ -0,0 +1,240 @@ +// @generated automatically by Diesel CLI. + +pub mod sql_types { + pub use crate::types::*; +} + +diesel::table! { + use diesel::sql_types::*; + use super::sql_types::StateMapping; + + accounts (address, workchain) { + workchain -> Tinyint, + #[max_length = 32] + address -> Varbinary, + #[max_length = 8] + state -> StateMapping, + balance -> Unsigned, + #[max_length = 32] + init_code_hash -> Nullable, + #[max_length = 32] + code_hash -> Nullable, + #[max_length = 32] + data_hash -> Nullable, + #[max_length = 32] + creator_address -> Nullable, + creator_wc -> Tinyint, + created_at -> Unsigned, + updated_at -> Unsigned, + updated_lt -> Unsigned, + } +} + +diesel::table! { + address_info (workchain_id, address) { + #[max_length = 32] + user_public_key -> Varbinary, + workchain_id -> Tinyint, + #[max_length = 32] + address -> Varbinary, + #[max_length = 32] + code_hash -> Nullable, + #[max_length = 100] + name -> Varchar, + #[max_length = 255] + descr -> Nullable, + socials -> Nullable, + #[max_length = 255] + url -> Nullable, + system_info -> Bool, + } +} + +diesel::table! { + blocks (workchain, shard, seqno) { + workchain -> Tinyint, + shard -> Unsigned, + seqno -> Unsigned, + #[max_length = 32] + root_hash -> Varbinary, + #[max_length = 32] + file_hash -> Varbinary, + is_key_block -> Bool, + transaction_count -> Unsigned, + gen_utime -> Unsigned, + gen_software_version -> Unsigned, + #[max_length = 32] + prev1 -> Varbinary, + prev1_seqno -> Unsigned, + #[max_length = 32] + prev2 -> Nullable, + prev2_seqno -> Nullable>, + prev_key_block -> Unsigned, + block_info -> Json, + value_flow -> Json, + account_blocks -> Json, + shards_info -> Nullable, + additional_info -> Nullable, + } +} + +diesel::table! { + use diesel::sql_types::*; + use super::sql_types::MessageTypeMapping; + + messages (message_hash) { + #[max_length = 32] + message_hash -> Varbinary, + src_workchain -> Tinyint, + #[max_length = 32] + src_address -> Nullable, + dst_workchain -> Tinyint, + #[max_length = 32] + dst_address -> Nullable, + #[max_length = 11] + message_type -> MessageTypeMapping, + message_value -> Unsigned, + ihr_fee -> Unsigned, + fwd_fee -> Unsigned, + import_fee -> Unsigned, + created_lt -> Unsigned, + created_at -> Unsigned, + bounced -> Bool, + bounce -> Bool, + } +} + +diesel::table! { + network_config (end_lt) { + end_lt -> Unsigned, + seq_no -> Unsigned, + config_params_boc -> Mediumblob, + } +} + +diesel::table! { + network_info (root_hash) { + #[max_length = 64] + root_hash -> Varchar, + } +} + +diesel::table! { + contracts_info (contract_id) { + #[max_length = 1024] + contract_name -> Varchar, + #[max_length = 1024] + project_link -> Nullable, + #[max_length = 32] + code_hash -> Varbinary, + #[max_length = 16] + contract_id -> Varbinary, + abi -> Json, + tvc -> Mediumblob, + sources -> Json, + history_processed -> Unsigned, + created_at -> Datetime, + #[max_length = 128] + compiler_version -> Varchar, + #[max_length = 128] + linker_version -> Varchar, + } +} + +diesel::table! { + use diesel::sql_types::*; + use super::sql_types::ParsedTypeMapping; + + parsed_messages_new (message_hash) { + #[max_length = 32] + message_hash -> Varbinary, + #[max_length = 128] + method_name -> Varchar, + #[max_length = 16] + contract_id -> Varbinary, + parsed_id -> Unsigned, + #[max_length = 15] + parsed_type -> ParsedTypeMapping, + } +} + +diesel::table! { + raw_transactions (wc, account_id, lt) { + wc -> Tinyint, + #[max_length = 32] + account_id -> Varbinary, + lt -> Unsigned, + data -> Mediumblob, + } +} + +diesel::table! { + use diesel::sql_types::*; + use super::sql_types::MessageTypeMapping; + + transaction_messages (transaction_time, transaction_lt, transaction_hash, is_out, index_in_transaction) { + #[max_length = 32] + transaction_hash -> Varbinary, + index_in_transaction -> Unsigned, + is_out -> Bool, + transaction_time -> Unsigned, + transaction_lt -> Unsigned, + transaction_account_workchain -> Tinyint, + #[max_length = 32] + transaction_account_address -> Varbinary, + #[max_length = 32] + block_hash -> Varbinary, + dst_workchain -> Tinyint, + #[max_length = 32] + dst_address -> Nullable, + src_workchain -> Tinyint, + #[max_length = 32] + src_address -> Nullable, + #[max_length = 32] + message_hash -> Varbinary, + #[max_length = 11] + message_type -> MessageTypeMapping, + message_value -> Unsigned, + bounced -> Bool, + bounce -> Bool, + } +} + +diesel::table! { + use diesel::sql_types::*; + use super::sql_types::TransactionTypeMapping; + + transactions (time, lt, hash) { + workchain -> Tinyint, + #[max_length = 32] + account_id -> Varbinary, + lt -> Unsigned, + time -> Unsigned, + #[max_length = 32] + hash -> Varbinary, + block_shard -> Unsigned, + block_seqno -> Unsigned, + #[max_length = 32] + block_hash -> Varbinary, + #[max_length = 12] + tx_type -> TransactionTypeMapping, + aborted -> Bool, + balance_change -> Bigint, + exit_code -> Nullable, + result_code -> Nullable, + } +} + +diesel::allow_tables_to_appear_in_same_query!( + accounts, + address_info, + blocks, + contracts_info, + messages, + network_config, + network_info, + parsed_messages_new, + raw_transactions, + transaction_messages, + transactions, +); diff --git a/explorer-models/src/transaction.rs b/explorer-models/src/transaction.rs new file mode 100644 index 000000000..2045e096e --- /dev/null +++ b/explorer-models/src/transaction.rs @@ -0,0 +1,74 @@ +use std::fmt::Debug; + +use diesel::Insertable; +use serde::Serialize; +use uuid::Uuid; + +use crate::schema::sql_types::{ParsedType, TransactionType}; +use crate::utils::HashInsert; +#[cfg(feature = "csv")] +use crate::utils::*; +use crate::{Hash, NumBinds}; + +#[derive(Debug, Serialize, Clone, Insertable)] +#[diesel(table_name = crate::schema::transactions)] +pub struct Transaction { + pub workchain: i8, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub account_id: Hash, + pub lt: u64, + pub time: u32, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub hash: Hash, + pub block_shard: u64, + pub block_seqno: u32, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub block_hash: Hash, + pub tx_type: TransactionType, + + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bool"))] + pub aborted: bool, + pub balance_change: i64, + /// Compute phase result + #[cfg_attr(feature = "csv", serde(with = "serde_csv_optional"))] + pub exit_code: Option, + /// Action phase result + #[cfg_attr(feature = "csv", serde(with = "serde_csv_optional"))] + pub result_code: Option, +} + +impl NumBinds for Transaction { + const NUM_BINDS: usize = 13; +} + +#[derive(Debug, Serialize, Clone, Insertable)] +#[diesel(table_name = crate::schema::raw_transactions)] +pub struct RawTransaction { + pub wc: i8, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub account_id: Hash, + pub lt: u64, + #[cfg_attr(feature = "csv", serde(with = "serde_csv_bytes"))] + pub data: Vec, +} + +impl NumBinds for RawTransaction { + const NUM_BINDS: usize = 4; +} + +#[derive(Debug, Clone, Insertable)] +#[diesel(check_for_backend(Mysql))] +#[diesel(table_name = crate::schema::parsed_messages_new)] +pub struct ParsedRecord { + #[diesel(serialize_as = HashInsert<32>)] + pub message_hash: [u8; 32], + pub method_name: String, + #[diesel(serialize_as = HashInsert<16>)] + pub contract_id: Uuid, + pub parsed_id: u32, + pub parsed_type: ParsedType, +} + +impl NumBinds for ParsedRecord { + const NUM_BINDS: usize = 5; +} diff --git a/explorer-models/src/types.rs b/explorer-models/src/types.rs new file mode 100644 index 000000000..1ff1e7934 --- /dev/null +++ b/explorer-models/src/types.rs @@ -0,0 +1,40 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, diesel_derive_enum::DbEnum)] +#[DbValueStyle = "PascalCase"] +pub enum State { + NonExist, + Uninit, + Active, + Frozen, + Deleted, +} + +#[derive(Debug, Serialize, Deserialize, Copy, Clone, diesel_derive_enum::DbEnum)] +#[DbValueStyle = "PascalCase"] +pub enum MessageType { + Internal, + ExternalIn, + ExternalOut, +} + +#[derive(Debug, Serialize, Deserialize, Clone, Copy, diesel_derive_enum::DbEnum)] +#[DbValueStyle = "PascalCase"] +pub enum TransactionType { + Ordinary, + Storage, + TickTock, + SplitPrepare, + SplitInstall, + MergePrepare, + MergeInstall, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, diesel_derive_enum::DbEnum)] +#[DbValueStyle = "PascalCase"] +pub enum ParsedType { + FunctionInput, + FunctionOutput, + BouncedFunction, + Event, +} diff --git a/explorer-models/src/utils.rs b/explorer-models/src/utils.rs new file mode 100644 index 000000000..059f8fa52 --- /dev/null +++ b/explorer-models/src/utils.rs @@ -0,0 +1,314 @@ +use std::fmt; +use std::fmt::Debug; + +use anyhow::anyhow; +use diesel::deserialize::FromSql; +use diesel::mysql::Mysql; +use diesel::serialize::{Output, ToSql}; +use diesel::sql_types::Binary; +use diesel::{serialize, AsExpression, Queryable}; +use serde::de::{Error, Unexpected, Visitor}; +use serde::ser::SerializeSeq; +use serde::{Deserialize, Serialize, Serializer}; +use uuid::Uuid; + +#[derive(AsExpression, Hash, Eq, PartialEq, Clone, Copy)] +#[diesel(sql_type = diesel::sql_types::Binary)] +pub struct HashInsert { + pub hash: [u8; N], +} + +impl Debug for HashInsert { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("HashInsert") + .field("hash", &hex::encode(self.hash)) + .finish() + } +} + +impl Serialize for HashInsert { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + if serializer.is_human_readable() { + serializer.serialize_str(&hex::encode(self.hash)) + } else { + let mut seq = serializer.serialize_seq(Some(N))?; + for byte in self.hash.iter() { + seq.serialize_element(byte)?; + } + seq.end() + } + } +} + +impl<'de, const N: usize> Deserialize<'de> for HashInsert { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct HexVisitor; + + impl<'de, const N: usize> Visitor<'de> for HexVisitor { + type Value = HashInsert; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("hex-encoded byte array") + } + + fn visit_str(self, value: &str) -> Result { + let bytes = hex::decode(value) + .map_err(|_| E::invalid_type(Unexpected::Str(value), &self))?; + let len = bytes.len(); + HashInsert::try_from(bytes).map_err(|_| E::invalid_length(len, &self)) + } + + fn visit_bytes(self, value: &[u8]) -> Result { + HashInsert::try_from(value.to_vec()) + .map_err(|_| E::invalid_length(value.len(), &self)) + } + } + + struct BytesVisitor; + + impl<'de, const N: usize> Visitor<'de> for BytesVisitor { + type Value = HashInsert; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("byte array") + } + + fn visit_bytes(self, value: &[u8]) -> Result { + HashInsert::try_from(value.to_vec()) + .map_err(|_| E::invalid_length(value.len(), &self)) + } + } + + if deserializer.is_human_readable() { + deserializer.deserialize_str(HexVisitor::) + } else { + deserializer.deserialize_bytes(BytesVisitor::) + } + } +} + +impl FromSql for HashInsert { + fn from_sql(bytes: diesel::mysql::MysqlValue<'_>) -> diesel::deserialize::Result { + let ty = bytes.value_type(); + let bytes = bytes.as_bytes(); + if bytes.len() != N { + return Err(format!( + "Invalid hash length FromSql: expected {}, got {}. Type: {:?}", + N, + bytes.len(), + &ty + ) + .into()); + } + let mut hash = [0u8; N]; + hash.copy_from_slice(bytes); + Ok(Self { hash }) + } +} + +impl ToSql for HashInsert { + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Mysql>) -> serialize::Result { + let data: &[u8] = self.hash.as_slice(); + <[u8] as ToSql>::to_sql(data, out) + } +} + +impl Queryable for HashInsert { + type Row = Vec; + + fn build(row: Self::Row) -> diesel::deserialize::Result { + if row.len() != N { + return Err(format!( + "Invalid hash length queryable Vec: expected {}, got {}", + N, + row.len() + ) + .into()); + } + + let mut hash = [0u8; N]; + hash.copy_from_slice(&row); + Ok(Self { hash }) + } +} + +impl From<[u8; N]> for HashInsert { + fn from(hash: [u8; N]) -> Self { + Self { hash } + } +} + +impl<'a, const N: usize> From<&'a [u8; N]> for HashInsert { + fn from(hash: &'a [u8; N]) -> Self { + Self { hash: *hash } + } +} + +impl From> for [u8; N] { + fn from(value: HashInsert) -> Self { + value.hash + } +} + +impl From for HashInsert<16> { + fn from(value: Uuid) -> Self { + Self { + hash: *value.as_bytes(), + } + } +} + +impl From> for Uuid { + fn from(value: HashInsert<16>) -> Self { + Uuid::from_bytes(value.hash) + } +} + +impl AsRef<[u8]> for HashInsert { + fn as_ref(&self) -> &[u8] { + &self.hash + } +} + +impl TryFrom<&[u8]> for HashInsert { + type Error = anyhow::Error; + + fn try_from(value: &[u8]) -> Result { + if value.len() != N { + return Err(anyhow!( + "Invalid hash length from slice: expected {}, got {}", + N, + value.len() + )); + } + + let mut hash = [0u8; N]; + hash.copy_from_slice(value); + Ok(Self { hash }) + } +} + +impl TryFrom> for HashInsert { + type Error = anyhow::Error; + + fn try_from(value: Vec) -> Result { + if value.len() != N { + return Err(anyhow!( + "Invalid hash length from vec: expected {}, got {}", + N, + value.len() + )); + } + + let mut hash = [0u8; N]; + hash.copy_from_slice(&value); + Ok(Self { hash }) + } +} + +#[cfg(feature = "csv")] +pub mod serde_csv_bytes { + pub fn serialize(data: &T, serializer: S) -> Result + where + S: serde::Serializer, + T: AsRef<[u8]>, + { + // see https://gist.github.com/siddontang/8875771 + + let mut result = Vec::with_capacity(data.as_ref().len() * 2); + for byte in data.as_ref() { + let escaped = match byte { + 0 => Some(b"\\0"), + 8 => Some(b"\\b"), + b'\n' => Some(b"\\n"), + b'\r' => Some(b"\\r"), + b'\t' => Some(b"\\t"), + b'\\' => Some(b"\\\\"), + 26 => Some(b"\\Z"), + _ => None, + }; + + match escaped { + Some(escaped) => result.extend_from_slice(escaped), + None => result.push(*byte), + }; + } + serializer.serialize_bytes(&result) + } +} + +#[cfg(feature = "csv")] +pub mod serde_csv_bytes_optional { + use super::*; + + pub fn serialize(data: &Option, serializer: S) -> Result + where + S: serde::Serializer, + T: AsRef<[u8]>, + { + match data { + Some(data) => serde_csv_bytes::serialize(data, serializer), + None => serializer.serialize_bytes(b"\\N"), + } + } +} + +#[cfg(feature = "csv")] +pub mod serde_csv_optional { + use serde::Serialize; + + pub fn serialize(data: &Option, serializer: S) -> Result + where + S: serde::Serializer, + T: Serialize, + { + match data { + Some(data) => serializer.serialize_some(data), + None => serializer.serialize_bytes(b"\\N"), + } + } +} + +#[cfg(feature = "csv")] +pub mod serde_csv_bool { + pub fn serialize(data: &bool, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_u8(*data as u8) + } +} + +pub fn is_default(value: &T) -> bool { + value == &T::default() +} + +pub mod serde_string { + use std::fmt; + use std::str::FromStr; + + use super::*; + + pub fn serialize(data: &dyn fmt::Display, serializer: S) -> Result + where + S: serde::Serializer, + { + data.to_string().serialize(serializer) + } + + pub fn deserialize<'de, D, T>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + T: FromStr, + T::Err: fmt::Display, + { + String::deserialize(deserializer) + .and_then(|data| T::from_str(&data).map_err(D::Error::custom)) + } +}