From 6ca02e91b9dcf3739d8bc502d6688dce7fbbc704 Mon Sep 17 00:00:00 2001 From: ghe0 Date: Fri, 14 Mar 2025 16:16:17 +0200 Subject: [PATCH] added app code from noor --- Cargo.lock | 261 ++++++++++++++++------------ Cargo.toml | 3 + README.md | 3 + src/data.rs | 483 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/grpc.rs | 273 +++++++++++++++++++++++++++++ src/main.rs | 10 ++ 6 files changed, 926 insertions(+), 107 deletions(-) create mode 100644 README.md diff --git a/Cargo.lock b/Cargo.lock index 14d3b2f..17c0d8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,11 +82,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.6" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", + "once_cell", "windows-sys 0.59.0", ] @@ -120,9 +121,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" dependencies = [ "proc-macro2", "quote", @@ -217,9 +218,9 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "block-buffer" @@ -237,6 +238,7 @@ dependencies = [ "bs58", "chrono", "dashmap", + "detee-shared", "ed25519-dalek", "env_logger", "log", @@ -264,9 +266,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.16.0" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" [[package]] name = "byteorder" @@ -276,15 +278,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" [[package]] name = "cc" -version = "1.2.5" +version = "1.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e" +checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" dependencies = [ "shlex", ] @@ -415,6 +417,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "detee-shared" +version = "0.1.0" +source = "git+ssh://git@gitea.detee.cloud/noormohammedb/detee-shared?branch=stable_01#099f0a0488bce8e59c9c9e9a5e9b1f24998f1633" +dependencies = [ + "base64", + "prost", + "serde", + "serde_yaml", + "thiserror", + "tonic", + "tonic-build", +] + [[package]] name = "digest" version = "0.10.7" @@ -619,7 +635,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", ] [[package]] @@ -640,7 +668,7 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.7.0", + "indexmap 2.7.1", "slab", "tokio", "tokio-util", @@ -707,9 +735,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.5" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" [[package]] name = "httpdate" @@ -725,9 +753,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" dependencies = [ "bytes", "futures-channel", @@ -983,9 +1011,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -993,9 +1021,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is_terminal_polyfill" @@ -1020,9 +1048,9 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ "once_cell", "wasm-bindgen", @@ -1030,15 +1058,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" @@ -1058,9 +1086,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "matchit" @@ -1082,9 +1110,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] @@ -1096,7 +1124,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] @@ -1108,9 +1136,9 @@ checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" [[package]] name = "native-tls" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +checksum = "0dab59f8e050d5df8e4dd87d9206fb6f65a483e20ac9fda365ade4fab353196c" dependencies = [ "libc", "log", @@ -1134,24 +1162,24 @@ dependencies = [ [[package]] name = "object" -version = "0.36.5" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" [[package]] name = "openssl" -version = "0.10.68" +version = "0.10.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" dependencies = [ "bitflags", "cfg-if", @@ -1175,15 +1203,15 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.104" +version = "0.9.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" dependencies = [ "cc", "libc", @@ -1217,23 +1245,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset", - "indexmap 2.7.0", + "indexmap 2.7.1", ] [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67" dependencies = [ "proc-macro2", "quote", @@ -1242,9 +1270,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -1279,9 +1307,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.25" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" +checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", "syn", @@ -1289,9 +1317,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -1350,9 +1378,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -1384,7 +1412,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -1427,9 +1455,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.10" +version = "0.12.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3536321cfc54baa8cf3e273d5e1f63f889067829c4b410fcdbac8ca7b80994" +checksum = "43e734407157c3c2034e0258f5e4473ddb361b1e85f95a66690d67264d7cd1da" dependencies = [ "base64", "bytes", @@ -1477,7 +1505,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", - "getrandom", + "getrandom 0.2.15", "libc", "spin", "untrusted", @@ -1501,9 +1529,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", @@ -1514,9 +1542,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.20" +version = "0.23.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" +checksum = "9fb9263ab4eb695e42321db096e3b8fbd715a59b154d5c88d82db2175b681ba7" dependencies = [ "once_cell", "rustls-pki-types", @@ -1536,9 +1564,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" [[package]] name = "rustls-webpki" @@ -1553,15 +1581,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "schannel" @@ -1593,9 +1621,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -1629,9 +1657,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" dependencies = [ "itoa", "memchr", @@ -1657,7 +1685,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.7.0", + "indexmap 2.7.1", "itoa", "ryu", "serde", @@ -1745,9 +1773,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.90" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -1797,12 +1825,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" dependencies = [ "cfg-if", "fastrand", + "getrandom 0.3.1", "once_cell", "rustix", "windows-sys 0.59.0", @@ -1855,9 +1884,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -1871,9 +1900,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", @@ -2060,9 +2089,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "unsafe-libyaml" @@ -2107,11 +2136,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.11.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +checksum = "ced87ca4be083373936a67f8de945faa23b6b42384bd5b64434850802c6dccd0" dependencies = [ - "getrandom", + "getrandom 0.3.1", ] [[package]] @@ -2142,21 +2171,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "wasm-bindgen" -version = "0.2.99" +name = "wasi" +version = "0.13.3+wasi-0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", @@ -2168,9 +2207,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.49" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", @@ -2181,9 +2220,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2191,9 +2230,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", @@ -2204,15 +2243,18 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.99" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.76" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" dependencies = [ "js-sys", "wasm-bindgen", @@ -2339,6 +2381,15 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags", +] + [[package]] name = "write16" version = "1.0.0" diff --git a/Cargo.toml b/Cargo.toml index 3ae3262..d91d473 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,5 +21,8 @@ tokio-stream = "0.1.17" tonic = "0.12" uuid = { version = "1.11.0", features = ["v4"] } +detee-shared = { git = "ssh://git@gitea.detee.cloud/noormohammedb/detee-shared", branch = "stable_01" } +# detee-shared = { path = "../detee-shared" } + [build-dependencies] tonic-build = "0.12" diff --git a/README.md b/README.md new file mode 100644 index 0000000..a818250 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Brain mock + +eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519 \ No newline at end of file diff --git a/src/data.rs b/src/data.rs index 17add83..92a1ad4 100644 --- a/src/data.rs +++ b/src/data.rs @@ -13,6 +13,17 @@ use std::{ use tokio::sync::mpsc::Sender; use tokio::sync::oneshot::Sender as OneshotSender; +use detee_shared::sgx::pb::brain::brain_message_app; +use detee_shared::sgx::pb::brain::AppContract as AppContractPB; +use detee_shared::sgx::pb::brain::AppNodeFilters; +use detee_shared::sgx::pb::brain::AppNodeListResp; +use detee_shared::sgx::pb::brain::AppNodeResources; +use detee_shared::sgx::pb::brain::AppResource as AppResourcePB; +use detee_shared::sgx::pb::brain::BrainMessageApp; +use detee_shared::sgx::pb::brain::DelAppReq; +use detee_shared::sgx::pb::brain::MappedPort; +use detee_shared::sgx::pb::brain::NewAppReq; +use detee_shared::sgx::pb::brain::NewAppRes; const DATA_PATH: &str = "/etc/detee/brain-mock/saved_data.yaml"; #[derive(thiserror::Error, Debug)] @@ -29,9 +40,12 @@ pub enum Error { ImpossibleError, #[error("You don't have the required permissions for this operation.")] AccessDenied, + + #[error("Could not find contract {0}")] + AppContractNotFound(String), } -#[derive(Clone, Default, Serialize, Deserialize)] +#[derive(Clone, Default, Serialize, Deserialize, Debug)] pub struct AccountData { pub balance: u64, pub tmp_locked: u64, @@ -48,6 +62,7 @@ pub struct OperatorData { pub email: String, pub banned_users: HashSet, pub vm_nodes: HashSet, + pub app_nodes: HashSet, } impl From for grpc::AccountBalance { @@ -162,9 +177,115 @@ impl Into for VmContract { } } +#[derive(Clone, Debug, Default, Serialize, Deserialize)] +pub struct AppContract { + pub uuid: String, + pub package_url: String, + pub admin_pubkey: String, + pub node_pubkey: String, + pub mapped_ports: Vec<(u16, u16)>, + pub host_ipv4: String, + pub disk_size_mb: u32, + pub vcpus: u32, + pub memory_mb: u32, + pub created_at: chrono::DateTime, + pub updated_at: chrono::DateTime, + // price per unit per minute + // recommended value is 20000 + pub price_per_unit: u64, + pub locked_nano: u64, + pub collected_at: chrono::DateTime, + pub hratls_pubkey: String, + pub public_package_mr_enclave: Option>, + pub app_name: String, +} + +impl AppContract { + fn total_units(&self) -> f64 { + // TODO: Optimize this based on price of hardware. + (self.vcpus as f64 * 5f64) + + (self.memory_mb as f64 / 200f64) + + (self.disk_size_mb as f64 / 10000f64) + } + + /// Returns price per minute in nanoLP + fn price_per_minute(&self) -> u64 { + (self.total_units() * self.price_per_unit as f64) as u64 + } +} + +impl From for AppContractPB { + fn from(value: AppContract) -> Self { + let mapped_ports = value + .mapped_ports + .clone() + .into_iter() + .map(MappedPort::from) + .collect(); + + let nano_per_minute = value.price_per_minute(); + let resource = Some(AppResourcePB { + memory_mb: value.memory_mb, + disk_mb: value.disk_size_mb, + vcpu: value.vcpus, + ports: value.mapped_ports.iter().map(|p| p.1 as u32).collect(), + }); + Self { + uuid: value.uuid, + package_url: value.package_url, + admin_pubkey: value.admin_pubkey, + node_pubkey: value.node_pubkey, + mapped_ports, + public_ipv4: value.host_ipv4, + resource, + created_at: value.created_at.to_rfc3339(), + updated_at: value.updated_at.to_rfc3339(), + nano_per_minute, + locked_nano: value.locked_nano, + collected_at: value.collected_at.to_rfc3339(), + hratls_pubkey: value.hratls_pubkey, + public_package_mr_enclave: value.public_package_mr_enclave, + app_name: value.app_name, + } + } +} + +#[derive(Eq, Hash, PartialEq, Clone, Debug, Default, Serialize, Deserialize)] +pub struct AppNode { + pub node_pubkey: String, + pub operator_wallet: String, + pub country: String, + pub region: String, + pub city: String, + pub ip: String, + pub avail_mem_mb: u32, + pub avail_vcpus: u32, + pub avail_storage_mb: u32, + pub avail_no_of_port: u32, + pub max_ports_per_app: u32, + // nanotokens per unit per minute + pub price: u64, + + pub offline_minutes: u64, +} + +impl From for AppNodeListResp { + fn from(value: AppNode) -> Self { + Self { + operator: value.operator_wallet, + node_pubkey: value.node_pubkey, + country: value.country, + region: value.region, + city: value.city, + ip: value.ip, + price: value.price, + reports: Vec::new(), + } + } +} + #[derive(Default, Serialize, Deserialize)] pub struct BrainData { - // amount of nanoLP in each account accounts: DashMap, operators: DashMap, vm_nodes: RwLock>, @@ -175,6 +296,13 @@ pub struct BrainData { tmp_updatevm_reqs: DashMap)>, #[serde(skip_serializing, skip_deserializing)] daemon_tx: DashMap>, + + app_nodes: RwLock>, + #[serde(skip_serializing, skip_deserializing)] + app_daemon_tx: DashMap>, + #[serde(skip_serializing, skip_deserializing)] + tmp_new_container_reqs: DashMap)>, + app_contracts: RwLock>, } impl BrainData { @@ -204,6 +332,11 @@ impl BrainData { tmp_newvm_reqs: DashMap::new(), tmp_updatevm_reqs: DashMap::new(), daemon_tx: DashMap::new(), + + app_nodes: RwLock::new(Vec::new()), + app_daemon_tx: DashMap::new(), + tmp_new_container_reqs: DashMap::new(), + app_contracts: RwLock::new(Vec::new()), } } } @@ -850,6 +983,7 @@ impl BrainData { email: String::new(), banned_users: HashSet::new(), vm_nodes: HashSet::from([node_pubkey.to_string()]), + app_nodes: HashSet::new(), }); } @@ -1043,3 +1177,348 @@ impl BrainData { .collect() } } + +impl BrainData { + pub fn add_app_daemon_tx(&self, node_pubkey: &str, tx: Sender) { + self.app_daemon_tx.insert(node_pubkey.to_string(), tx); + } + + pub fn del_app_daemon_tx(&self, node_pubkey: &str) { + self.app_daemon_tx.remove(node_pubkey); + } + + pub fn register_app_node(&self, node: AppNode) { + info!("Registering app node {node:?}"); + self.add_app_node_to_operator(&node.operator_wallet, &node.node_pubkey); + let mut nodes = self.app_nodes.write().unwrap(); + for n in nodes.iter_mut() { + if n.node_pubkey == node.node_pubkey { + // TODO: figure what to do in this case. + warn!("Node {} already exists. Updating data.", n.node_pubkey); + *n = node; + return; + } + } + nodes.push(node); + } + + pub fn add_app_node_to_operator(&self, operator_wallet: &str, node_pubkey: &str) { + self.operators + .entry(operator_wallet.to_string()) + .and_modify(|op| { + op.app_nodes.insert(node_pubkey.to_string()); + }) + .or_insert(OperatorData { + escrow: 0, + email: String::new(), + banned_users: HashSet::new(), + vm_nodes: HashSet::new(), + app_nodes: HashSet::from([node_pubkey.to_string()]), + }); + } + + pub fn find_app_nodes_by_filters(&self, filters: &AppNodeFilters) -> Vec { + let nodes = self.app_nodes.read().unwrap(); + nodes + .iter() + .filter(|n| { + n.avail_vcpus >= filters.vcpus + && n.avail_mem_mb >= filters.memory_mb + && n.avail_storage_mb >= filters.storage_mb + && (filters.country.is_empty() || (n.country == filters.country)) + && (filters.city.is_empty() || (n.city == filters.city)) + && (filters.region.is_empty() || (n.region == filters.region)) + && (filters.ip.is_empty() || (n.ip == filters.ip)) + }) + .cloned() + .collect() + } + + // TODO: sort by rating + pub fn get_one_app_node_by_filters(&self, filters: &AppNodeFilters) -> Option { + let nodes = self.app_nodes.read().unwrap(); + nodes + .iter() + .find(|n| { + n.avail_vcpus >= filters.vcpus + && n.avail_mem_mb >= filters.memory_mb + && n.avail_storage_mb >= filters.storage_mb + && (filters.country.is_empty() || (n.country == filters.country)) + && (filters.city.is_empty() || (n.city == filters.city)) + && (filters.region.is_empty() || (n.region == filters.region)) + && (filters.ip.is_empty() || (n.ip == filters.ip)) + && (filters.node_pubkey.is_empty() || (n.node_pubkey == filters.node_pubkey)) + }) + .cloned() + } + + pub fn find_app_contract_by_uuid(&self, uuid: &str) -> Result { + let contracts = self.app_contracts.read().unwrap(); + contracts + .iter() + .find(|c| c.uuid == uuid) + .cloned() + .ok_or(Error::AppContractNotFound(uuid.to_string())) + } + + pub fn find_app_node_by_pubkey(&self, public_key: &str) -> Option { + let nodes = self.app_nodes.read().unwrap(); + nodes.iter().cloned().find(|n| n.node_pubkey == public_key) + } + + pub fn find_app_contracts_by_admin_pubkey(&self, admin_pubkey: &str) -> Vec { + debug!("Searching contracts for admin pubkey {admin_pubkey}"); + let contracts: Vec = self + .app_contracts + .read() + .unwrap() + .iter() + .filter(|c| c.admin_pubkey == admin_pubkey) + .cloned() + .collect(); + debug!("Found {} contracts or {admin_pubkey}.", contracts.len()); + contracts + } + + pub fn list_all_app_contracts(&self) -> Vec { + let contracts = self.app_contracts.read().unwrap(); + contracts.iter().cloned().collect() + } + + pub fn find_app_contracts_by_node(&self, node_pubkey: &str) -> Vec { + let app_contracts = self.app_contracts.read().unwrap(); + app_contracts + .iter() + .filter(|c| c.node_pubkey == node_pubkey) + .cloned() + .collect() + } + + pub async fn app_contracts_cron(&self) { + let mut deleted_app_contracts: Vec<(String, String)> = Vec::new(); + log::debug!("Running app contracts cron..."); + { + let mut app_contracts = self.app_contracts.write().unwrap(); + app_contracts.retain_mut(|c| { + let node = self.find_app_node_by_pubkey(&c.node_pubkey).unwrap(); + if node.offline_minutes == 0 { + let operator_wallet = node.operator_wallet.clone(); + let minutes_to_collect = (Utc::now() - c.collected_at).num_minutes() as u64; + c.collected_at = Utc::now(); + dbg!(&minutes_to_collect); + dbg!(&c.price_per_minute()); + let mut nanolp_to_collect = + c.price_per_minute().saturating_mul(minutes_to_collect); + if nanolp_to_collect > c.locked_nano { + nanolp_to_collect = c.locked_nano; + } + dbg!(&nanolp_to_collect); + log::debug!("Removing {nanolp_to_collect} nanoLP from {}", c.uuid); + c.locked_nano -= nanolp_to_collect; + let escrow_multiplier = match self.operators.get(&operator_wallet) { + Some(op) if op.escrow > 5000 => match self.operators.get(&c.admin_pubkey) { + Some(user_is_op) if user_is_op.escrow > 5000 => 1, + _ => 5, + }, + _ => 1, + }; + self.add_nano_to_wallet( + &operator_wallet, + nanolp_to_collect * escrow_multiplier, + ); + if c.locked_nano == 0 { + deleted_app_contracts.push((c.uuid.clone(), c.node_pubkey.clone())); + } + } + c.locked_nano > 0 + }); + } + // inform daemons of the deletion of the contracts + for (uuid, node_pubkey) in deleted_app_contracts.iter() { + if let Some(app_daemon_tx) = self.app_daemon_tx.get(&node_pubkey.clone()) { + let msg = BrainMessageApp { + msg: Some(brain_message_app::Msg::DeleteAppReq(DelAppReq { + uuid: uuid.to_string(), + admin_pubkey: String::new(), + })), + }; + let app_daemon_tx = app_daemon_tx.clone(); + let _ = app_daemon_tx.send(msg).await; + } + } + } + + pub fn submit_app_node_resources(&self, node_resource: AppNodeResources) { + debug!("{:#?}", &node_resource); + let mut nodes = self.app_nodes.write().unwrap(); + for n in nodes.iter_mut() { + if n.node_pubkey == node_resource.node_pubkey { + debug!( + "Found node {}. Updating resources to {:?}", + n.node_pubkey, node_resource + ); + n.avail_vcpus = node_resource.avail_vcpus; + n.avail_mem_mb = node_resource.avail_memory_mb; + n.avail_storage_mb = node_resource.avail_storage_mb; + n.max_ports_per_app = node_resource.max_ports_per_app; + n.avail_no_of_port = node_resource.avail_no_of_port; + return; + } + } + debug!( + "VM Node {} not found when trying to update resources.", + node_resource.node_pubkey + ); + debug!("VM Node list:\n{:?}", nodes); + } + + pub async fn send_new_container_req(&self, mut req: NewAppReq, tx: OneshotSender) { + if let Err(e) = self.lock_nanotockens(&req.admin_pubkey, req.locked_nano) { + let _ = tx.send(NewAppRes { + uuid: String::new(), + error: e.to_string(), + status: "failed".to_string(), + ..Default::default() + }); + return; + } + + req.uuid = uuid::Uuid::new_v4().to_string(); + + info!("Inserting new container request in memory: {req:?}"); + self.tmp_new_container_reqs + .insert(req.uuid.clone(), (req.clone(), tx)); + + if let Some(app_daemon_tx) = self.app_daemon_tx.get(&req.node_pubkey) { + debug!( + "Found daemon TX for {}. Sending newVMReq {}", + req.node_pubkey, req.uuid + ); + let msg = BrainMessageApp { + msg: Some( + detee_shared::sgx::pb::brain::brain_message_app::Msg::NewAppReq(req.clone()), + ), + }; + if let Err(e) = app_daemon_tx.send(msg).await { + warn!( + "Failed to send new container request to {} due to error: {e:?}", + req.node_pubkey + ); + info!("Deleting daemon TX for {}", req.node_pubkey); + self.del_app_daemon_tx(&req.node_pubkey); + self.send_new_container_resp(NewAppRes { + uuid: req.uuid, + status: "failed".to_string(), + error: "Daemon is offline.".to_string(), + ..Default::default() + }) + .await; + } + } else { + self.send_new_container_resp(NewAppRes { + status: "failed".to_string(), + error: "Daemon is offline.".to_string(), + uuid: req.uuid, + ..Default::default() + }) + .await; + } + } + + pub async fn send_del_container_req(&self, req: DelAppReq) -> Result<(), Error> { + log::debug!("Starting deletion of app {}", req.uuid); + let app_contract = self.find_app_contract_by_uuid(&req.uuid)?; + + if app_contract.admin_pubkey != req.admin_pubkey { + return Err(Error::AccessDenied); + } + + info!("Found app contract {}. Deleting...", &req.uuid); + if let Some(app_daemon_tx) = self.app_daemon_tx.get(&app_contract.node_pubkey) { + debug!( + "TX for daemon {} found. Informing daemon about deletion of {}.", + app_contract.node_pubkey, &req.uuid + ); + let msg = BrainMessageApp { + msg: Some(brain_message_app::Msg::DeleteAppReq(req.clone())), + }; + + if let Err(e) = app_daemon_tx.send(msg).await { + warn!( + "Failed to send deletion request to {} due to error: {e:?}", + app_contract.node_pubkey + ); + info!("Deleting daemon TX for {}", app_contract.node_pubkey); + self.del_app_daemon_tx(&app_contract.node_pubkey); + } + } + + self.add_nano_to_wallet(&app_contract.admin_pubkey, app_contract.locked_nano); + let mut app_contracts = self.app_contracts.write().unwrap(); + app_contracts.retain(|c| c.uuid != req.uuid); + + Ok(()) + } + + pub async fn send_new_container_resp(&self, new_container_resp: NewAppRes) { + let new_container_req = match self.tmp_new_container_reqs.remove(&new_container_resp.uuid) { + Some((_, r)) => r, + None => { + log::error!( + "Received confirmation for ghost new container req {}", + new_container_resp.uuid + ); + return; + } + }; + if let Err(err) = new_container_req.1.send(new_container_resp.clone()) { + log::error!( + "CLI RX for {} dropped before receiving confirmation {:?}.\n{:?}", + &new_container_req.0.admin_pubkey, + new_container_resp, + err + ); + } + + if new_container_resp.error != "" { + if let Some(mut admin_wallet) = self.accounts.get_mut(&new_container_req.0.admin_pubkey) + { + admin_wallet.balance += new_container_req.0.locked_nano; + admin_wallet.tmp_locked -= new_container_req.0.locked_nano; + } + return; + } + + if let Some(mut admin_wallet) = self.accounts.get_mut(&new_container_req.0.admin_pubkey) { + admin_wallet.tmp_locked -= new_container_req.0.locked_nano; + } + + let requested_resource = new_container_req.0.resource.clone().unwrap_or_default(); + + let app_contracts = AppContract { + uuid: new_container_req.0.uuid, + package_url: new_container_req.0.package_url, + admin_pubkey: new_container_req.0.admin_pubkey, + node_pubkey: new_container_req.0.node_pubkey.clone(), + mapped_ports: new_container_resp + .mapped_ports + .iter() + .map(|p| (p.host_port as u16, p.app_port as u16)) + .collect::>(), + host_ipv4: new_container_resp.ip_address, + disk_size_mb: requested_resource.disk_mb, + vcpus: requested_resource.vcpu, + memory_mb: requested_resource.memory_mb, + created_at: Utc::now(), + updated_at: Utc::now(), + price_per_unit: new_container_req.0.price_per_unit, + locked_nano: new_container_req.0.locked_nano, + collected_at: Utc::now(), + hratls_pubkey: new_container_req.0.hratls_pubkey, + public_package_mr_enclave: new_container_req.0.public_package_mr_enclave, + app_name: new_container_req.0.app_name, + }; + log::info!("Created new app contract: {app_contracts:?}"); + self.app_contracts.write().unwrap().push(app_contracts); + } +} diff --git a/src/grpc.rs b/src/grpc.rs index 370d075..c5a7102 100644 --- a/src/grpc.rs +++ b/src/grpc.rs @@ -14,6 +14,12 @@ use tokio::sync::mpsc; use tokio_stream::{wrappers::ReceiverStream, Stream, StreamExt}; use tonic::{Request, Response, Status, Streaming}; +use detee_shared::sgx::pb::brain::brain_app_cli_server::BrainAppCli; +use detee_shared::sgx::pb::brain::brain_app_daemon_server::BrainAppDaemon; +use detee_shared::sgx::pb::brain::{ + AppContract, AppNodeFilters, AppNodeListResp, BrainMessageApp, DaemonMessageApp, DelAppReq, + ListAppContractsReq, NewAppReq, NewAppRes, RegisterAppNodeReq, +}; const ADMIN_ACCOUNTS: &[&str] = &[ "x52w7jARC5erhWWK65VZmjdGXzBK6ZDgfv1A283d8XK", "FHuecMbeC1PfjkW2JKyoicJAuiU7khgQT16QUB3Q1XdL", @@ -40,6 +46,26 @@ impl BrainCliMock { } } +pub struct BrainAppCliMock { + data: Arc, +} + +impl BrainAppCliMock { + pub fn new(data: Arc) -> Self { + Self { data } + } +} + +pub struct BrainAppDaemonMock { + data: Arc, +} + +impl BrainAppDaemonMock { + pub fn new(data: Arc) -> Self { + Self { data } + } +} + #[tonic::async_trait] impl BrainVmDaemon for BrainDaemonMock { type RegisterVmNodeStream = Pin> + Send>>; @@ -428,6 +454,245 @@ trait PubkeyGetter { fn get_pubkey(&self) -> Option; } +#[tonic::async_trait] +impl BrainAppCli for BrainAppCliMock { + type ListAppContractsStream = Pin> + Send>>; + type ListAppNodesStream = Pin> + Send>>; + type ListAllAppContractsStream = + Pin> + Send>>; + + async fn deploy_app( + &self, + req: tonic::Request, + ) -> Result, Status> { + let req_data = check_sig_from_req(req)?; + log::info!("Creating new container: {req_data:?}"); + let admin_pubkey = req_data.admin_pubkey.clone(); + let (oneshot_tx, oneshot_rx) = tokio::sync::oneshot::channel(); + self.data.send_new_container_req(req_data, oneshot_tx).await; + + match oneshot_rx.await { + Ok(response) => { + info!("responding container confirmation to {admin_pubkey}: {response:?}"); + Ok(Response::new(response)) + } + Err(e) => { + log::error!("Something went wrong. Reached error {e:?}"); + Err(Status::unknown( + "Request failed due to unknown error. Please try again or contact the DeTEE devs team.", + )) + } + } + } + + async fn delete_app( + &self, + req: tonic::Request, + ) -> Result, Status> { + let req_data = check_sig_from_req(req)?; + log::info!("deleting container: {}", req_data.uuid.clone()); + if let Err(er) = self.data.send_del_container_req(req_data).await { + info!("Could not delete container: {er}"); + return Err(Status::not_found("Could not find container")); + }; + + Ok(Response::new(detee_shared::sgx::pb::brain::Empty {})) + } + + async fn list_app_contracts( + &self, + req: tonic::Request, + ) -> Result, Status> { + let req_data = check_sig_from_req(req)?; + let app_contracts = self + .data + .find_app_contracts_by_admin_pubkey(&req_data.admin_pubkey); + + let (tx, rx) = mpsc::channel(6); + tokio::spawn(async move { + for contract in app_contracts { + let _ = tx.send(contract.into()).await; + } + }); + let output_stream = ReceiverStream::new(rx).map(Ok); + Ok(Response::new( + Box::pin(output_stream) as Self::ListAppContractsStream + )) + } + + async fn list_app_nodes( + &self, + req: tonic::Request, + ) -> Result, Status> { + let req = check_sig_from_req(req)?; + info!("CLI requested ListAppNodes: {req:?}"); + let nodes = self.data.find_app_nodes_by_filters(&req); + let (tx, rx) = mpsc::channel(6); + tokio::spawn(async move { + for node in nodes { + let _ = tx.send(Ok(node.into())).await; + } + }); + let output_stream = ReceiverStream::new(rx); + Ok(Response::new(Box::pin(output_stream))) + } + + async fn get_one_app_node( + &self, + req: tonic::Request, + ) -> Result, Status> { + let req = check_sig_from_req(req)?; + info!("CLI requested GetOneAppNode: {req:?}"); + match self.data.get_one_app_node_by_filters(&req) { + Some(node) => Ok(Response::new(node.into())), + None => Err(Status::not_found( + "Could not find any node based on your search criteria", + )), + } + } + + async fn list_all_app_contracts( + &self, + req: tonic::Request, + ) -> Result, Status> { + check_admin_key(&req)?; + let _ = check_sig_from_req(req)?; + let contracts = self.data.list_all_app_contracts(); + let (tx, rx) = mpsc::channel(6); + tokio::spawn(async move { + for contract in contracts { + let _ = tx.send(Ok(contract.into())).await; + } + }); + let output_stream = ReceiverStream::new(rx); + Ok(Response::new(Box::pin(output_stream))) + } +} + +#[tonic::async_trait] +impl BrainAppDaemon for BrainAppDaemonMock { + type RegisterAppNodeStream = Pin> + Send>>; + type BrainMessagesStream = Pin> + Send>>; + + async fn register_app_node( + &self, + req: tonic::Request, + ) -> Result, Status> { + let req_data = check_sig_from_req(req)?; + log::info!( + "registering app node_key : {}, operator_key: {}", + &req_data.node_pubkey, + &req_data.operator_wallet + ); + + let app_node = crate::data::AppNode { + node_pubkey: req_data.node_pubkey.clone(), + operator_wallet: req_data.operator_wallet, + ip: req_data.main_ip, + city: req_data.city, + region: req_data.region, + country: req_data.country, + ..Default::default() + }; + self.data.register_app_node(app_node); + + log::info!("Sending existing contracts to {}", &req_data.node_pubkey); + let app_contracts = self.data.find_app_contracts_by_node(&req_data.node_pubkey); + let (tx, rx) = mpsc::channel(6); + tokio::spawn(async move { + for contract in app_contracts { + let _ = tx.send(contract.into()).await; + } + }); + let output_stream = ReceiverStream::new(rx).map(Ok); + Ok(Response::new(Box::pin(output_stream))) + } + + async fn brain_messages( + &self, + req: tonic::Request, + ) -> Result, Status> { + let req_data = req.into_inner(); + let pubkey = req_data.pubkey.clone(); + check_sig_from_parts( + &pubkey, + &req_data.timestamp, + &format!("{:?}", req_data.contracts), + &req_data.signature, + )?; + + info!( + "Daemon {} connected to receive brain messages", + req_data.pubkey + ); + let (tx, rx) = mpsc::channel(6); + self.data.add_app_daemon_tx(&req_data.pubkey, tx); + let output_stream = ReceiverStream::new(rx).map(Ok); + Ok(Response::new( + Box::pin(output_stream) as Self::BrainMessagesStream + )) + } + + async fn daemon_messages( + &self, + req: tonic::Request>, + ) -> Result, Status> { + let mut req_stream = req.into_inner(); + let mut pubkey; + + if let Some(Ok(msg)) = req_stream.next().await { + log::debug!( + "demon_messages received the following auth message: {:?}", + msg.msg + ); + if let Some(detee_shared::sgx::pb::brain::daemon_message_app::Msg::Auth(auth)) = msg.msg + { + pubkey = auth.pubkey.clone(); + check_sig_from_parts( + &pubkey, + &auth.timestamp, + &format!("{:?}", auth.contracts), + &auth.signature, + )?; + } else { + return Err(Status::unauthenticated( + "Could not authenticate the daemon: could not extract auth signature", + )); + } + } else { + return Err(Status::unauthenticated("Could not authenticate the daemon")); + } + + while let Some(daemon_message) = req_stream.next().await { + match daemon_message { + Ok(msg) => match msg.msg { + Some(detee_shared::sgx::pb::brain::daemon_message_app::Msg::Auth( + daemon_auth, + )) => pubkey = daemon_auth.pubkey, + Some(detee_shared::sgx::pb::brain::daemon_message_app::Msg::NewAppRes( + new_app_res, + )) => self.data.send_new_container_resp(new_app_res).await, + Some( + detee_shared::sgx::pb::brain::daemon_message_app::Msg::AppNodeResources( + node_resource, + ), + ) => self.data.submit_app_node_resources(node_resource), + _ => { + dbg!("None"); + } + }, + Err(e) => { + log::warn!("Daemon disconnected: {e:?}"); + self.data.del_app_daemon_tx(&pubkey); + } + } + // + } + + Ok(Response::new(detee_shared::sgx::pb::brain::Empty {})) + } +} + macro_rules! impl_pubkey_getter { ($t:ty, $field:ident) => { impl PubkeyGetter for $t { @@ -462,6 +727,14 @@ impl_pubkey_getter!(Empty); impl_pubkey_getter!(AirdropReq); impl_pubkey_getter!(SlashReq); +impl_pubkey_getter!(NewAppReq, admin_pubkey); +impl_pubkey_getter!(DelAppReq, admin_pubkey); +impl_pubkey_getter!(ListAppContractsReq, admin_pubkey); + +impl_pubkey_getter!(RegisterAppNodeReq); +impl_pubkey_getter!(detee_shared::sgx::pb::brain::Empty); +impl_pubkey_getter!(AppNodeFilters); + fn check_sig_from_req(req: Request) -> Result { let time = match req.metadata().get("timestamp") { Some(t) => t.clone(), diff --git a/src/main.rs b/src/main.rs index 64936a3..f9b1041 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,8 +2,12 @@ mod data; mod grpc; use data::BrainData; +use detee_shared::sgx::pb::brain::brain_app_cli_server::BrainAppCliServer; +use detee_shared::sgx::pb::brain::brain_app_daemon_server::BrainAppDaemonServer; use grpc::snp_proto::brain_cli_server::BrainCliServer; use grpc::snp_proto::brain_vm_daemon_server::BrainVmDaemonServer; +use grpc::BrainAppCliMock; +use grpc::BrainAppDaemonMock; use grpc::BrainCliMock; use grpc::BrainDaemonMock; use std::sync::Arc; @@ -21,6 +25,7 @@ async fn main() { tokio::time::sleep(tokio::time::Duration::from_secs(60)).await; data_clone.vm_nodes_cron().await; data_clone.vm_contracts_cron().await; + data_clone.app_contracts_cron().await; if let Err(e) = data_clone.save_to_disk() { log::error!("Could not save data to disk due to error: {e}") } @@ -31,9 +36,14 @@ async fn main() { let daemon_server = BrainVmDaemonServer::new(BrainDaemonMock::new(data.clone())); let cli_server = BrainCliServer::new(BrainCliMock::new(data.clone())); + let sgx_cli_server = BrainAppCliServer::new(BrainAppCliMock::new(data.clone())); + let sgx_daemon_server = BrainAppDaemonServer::new(BrainAppDaemonMock::new(data.clone())); + Server::builder() .add_service(daemon_server) .add_service(cli_server) + .add_service(sgx_cli_server) + .add_service(sgx_daemon_server) .serve(addr) .await .unwrap();